1 /*****************************************************************
2 **
3 ** @(#) scope.c -- SCOPE SECTION and prefix matching functions
4 **
5 ** Copyright (c) Oct 2015, Holger Zuleger HZNET. All rights reserved.
6 **
7 ** This software is open source.
8 **
9 *****************************************************************/
10 # include <stdio.h>
11 # include <string.h>
12 # include <stdlib.h>
13 # include <unistd.h> /* for link(), unlink() */
14 # include <ctype.h>
15 # include <sys/types.h>
16 # include <sys/stat.h>
17 # include <time.h>
18 # include <utime.h>
19 # include <assert.h>
20 # include <errno.h>
21 # include <fcntl.h>
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 # include "misc.h"
26 # include "ip6.h"
27 # include "hostid.h"
28 #define extern
29 # include "scope.h"
30 #undef extern
31 # include "gen6dns.h"
32
33 /* List of prefixes from the command line */
34 static prfx_t prfxlist[MAXPREFIXES];
35 static int nprfx; /* no of entries in prfx[] */
36
37 /* List of scopes out of SCOPE SECTION */
38 static scope_t scopelist[MAXSCOPES];
39 static int nscope; /* no of entries in scopelist[] */
40
41 static int scopeset[MAXSCOPES];
42
43 static int namefromstr (char *to, int tolen, const char *from);
44
45 /*****************************************************************
46 ** prfxput ()
47 ** puts a prefix into the prefix list
48 *****************************************************************/
prfxput(const ip6_t * prfx,int to_del)49 int prfxput (const ip6_t *prfx, int to_del)
50 {
51 ip6_t *new;
52 int i;
53
54 if ( nprfx >= MAXPREFIXES )
55 fatal ("maximum number of prefixes (%d) reached\n", MAXPREFIXES);
56
57 new = NULL;
58 if ( prfx )
59 {
60 for ( i = 0; i <nprfx; i++ )
61 {
62 if ( ip6cmp (prfx, prfxlist[i].prfx) == 0 )
63 {
64 error ("duplicate ipv6 prefix (%s), skipped\n");
65 return nprfx;
66 }
67 }
68 if ( (new = ip6copy (NULL, prfx)) == NULL )
69 fatal ("%s:%d prfxput(): out of memory\n", __FILE__, __LINE__);
70 }
71 prfxlist[nprfx].prfx = new;
72 prfxlist[nprfx].del = to_del;
73 prfxlist[nprfx].scope = NULL;
74
75 return ++nprfx;
76 }
77
78 /*****************************************************************
79 ** prfxdel ()
80 ** removes a prefix from the prefix list
81 *****************************************************************/
prfxdel(int n)82 int prfxdel (int n)
83 {
84 if ( nprfx <= 0 )
85 return 0;
86 if ( n >= 0 && n < nprfx )
87 {
88 prfxlist[n].prfx = prfxlist[nprfx].prfx;
89 prfxlist[n].del = prfxlist[nprfx].del;
90 prfxlist[n].scope = prfxlist[nprfx].scope;
91 }
92 return --nprfx;
93 }
94
95 /*****************************************************************
96 ** prfxget ()
97 ** returns a prefix from the prefix list
98 *****************************************************************/
prfxget(int n)99 prfx_t *prfxget (int n)
100 {
101 if ( n >= 0 && n < nprfx )
102 return &prfxlist[n];
103
104 return NULL;
105 }
106
107 /* Next functions loop through the prefix lsit */
108 static int prfxcnt;
109 /*****************************************************************
110 ** prfxstart ()
111 *****************************************************************/
prfxstart()112 prfx_t *prfxstart ()
113 {
114
115 return prfxget (prfxcnt = 0);
116 }
117
118 /*****************************************************************
119 ** prfxnext ()
120 *****************************************************************/
prfxnext()121 prfx_t *prfxnext ()
122 {
123 return prfxget (++prfxcnt);
124 }
125
126
127 /*****************************************************************
128 ** Scope functions starting here
129 *****************************************************************/
130
131 #define isequal(a, b) ((a == NULL && b == NULL) || (a && b && strcmp (a, b) == 0) )
132 /*****************************************************************
133 ** scopeput ()
134 *****************************************************************/
scopeput(const char * name,const char * view,const char * domain,ip6_t * prfx)135 int scopeput (const char *name, const char *view, const char *domain, ip6_t *prfx)
136 {
137 prfx_t *prf;
138 ip6_t *new;
139 int i;
140 const char *p;
141
142 assert ( name != NULL );
143 assert ( view != NULL );
144 assert ( domain != NULL );
145
146 if ( nscope >= MAXSCOPES )
147 fatal ("maximum number of scopes (%d) reached\n", MAXSCOPES);
148
149 snprintf (scopelist[nscope].name, sizeof (scopelist[0].name), "%s", name);
150
151 /* Is viewname set ? */
152 if ( *view && *view != '*' && strcmp (view, "none") != 0 && (p = strdup (view)) != NULL )
153 scopelist[nscope].view = p;
154 else
155 scopelist[nscope].view = NULL;
156
157 /* Is domain name set ? */
158 if ( *domain && (p = strdup (domain)) != NULL )
159 scopelist[nscope].domain = p;
160 else
161 scopelist[nscope].domain = NULL;
162
163 if ( (new = ip6copy (NULL, prfx)) == NULL )
164 fatal ("%s:%d scopeput(): out of memory\n", __FILE__, __LINE__);
165 scopelist[nscope].matchprfx = new;
166
167 scopelist[nscope].unique_scopeid = nscope;
168
169 /* mark this scope as duplicate if there is another one with the same view and domain */
170 for ( i = 0; i < nscope; i++ )
171 {
172 if ( isequal (scopelist[i].view, scopelist[nscope].view) &&
173 isequal (scopelist[i].domain, scopelist[nscope].domain) )
174 {
175 scopelist[nscope].unique_scopeid = scopelist[i].unique_scopeid;
176 break;
177 }
178 }
179
180 /* lookup a prefix in prefixlist matching this scope */
181 prf = prfxstart();
182 while ( prf )
183 {
184 if ( prf->scope == NULL && /* entry do not have a scope */
185 ip6match (prf->prfx, scopelist[nscope].matchprfx) > 0 )
186 prf->scope = &scopelist[nscope];
187 prf = prfxnext();
188 }
189
190 return ++nscope;
191 }
192
193 /*****************************************************************
194 ** scopeget ()
195 *****************************************************************/
scopeget(const char * scope)196 scope_t *scopeget (const char *scope)
197 {
198 int i;
199
200 for ( i = 0; i < nscope; i++ )
201 {
202 // fprintf (stderr, "\"%s\" == \"%s\"? => %p\n", scope, snet[i].name, &snet[i].sid);
203 if ( strcmp (scope, scopelist[i].name) == 0 )
204 return &scopelist[i];
205 }
206
207 return NULL;
208 }
209
210 /*****************************************************************
211 ** parsescopeline ()
212 *****************************************************************/
parsescopeline(const char * line,int delim)213 int parsescopeline (const char * line, int delim)
214 {
215 const char *p;
216 int len;
217 char name[15+1];
218 char view[254+1];
219 char domain[254+1];
220 ip6_t prfx;
221
222 assert ( line != NULL );
223
224 p = skipdelim (line, delim);
225 p += namefromstr (name, sizeof name, p);
226 if ( !isdelim (*p, delim) )
227 {
228 error ("parsescopeline(): illegal scopename found near \"%.10s ...\"\n", p);
229 return 0;
230 }
231
232 p = skipdelim (p, delim);
233 p += namefromstr (view, sizeof view, p);
234 if ( !isdelim (*p, delim) )
235 {
236 error ("parsescopeline(): illegal viewname found near \"%.10s ...\"\n", p);
237 return 0;
238 }
239
240 p = skipdelim (p, delim);
241 p += namefromstr (domain, sizeof(domain), p);
242 if ( !isdelim (*p, delim) )
243 {
244 error ("parsescopeline(): illegal domain found near \"%.10s ...\"\n", p);
245 return 0;
246 }
247
248 p = skipdelim (p, delim);
249 p += ip6fromstr (&prfx, p);
250 if ( !(ip6isset (&prfx) && ip6getsbit (&prfx) == 0 && ip6getebit (&prfx) <= 64) )
251 {
252 error ("parsescopeline(): no matching prefix found near \"%.10s ...\"\n", p);
253 return 0;
254 }
255
256 len = strlen (domain);
257 if ( len > 0 && domain[len-1] != '.' )
258 #if defined(ADD_DEF_ORIGIN) && ADD_DEF_ORIGIN == 1
259 snprintf (&domain[len], sizeof (domain) - (len), ".%s", parm.origin);
260 #else
261 error ("Missing dot at the end of domain \"%s\" (in scope definition \"%s\")!\n", domain, name);
262 #endif
263
264 scopeput (name, view, domain, &prfx);
265
266 return 1;
267 }
268
scopeset_clear(void)269 void scopeset_clear (void)
270 {
271 int i;
272
273 for ( i = 0; i < MAXSCOPES; i++ )
274 scopeset[i] = 0;
275 }
276
scopeset_set(int n)277 int scopeset_set (int n)
278 {
279 int prevval;
280
281 prevval = 0;
282 if ( n >= 0 && n < MAXSCOPES )
283 {
284 prevval = scopeset[n];
285 scopeset[n] = 1;
286 }
287 return prevval;
288 }
289
scopeset_get(int n)290 int scopeset_get (int n)
291 {
292 if ( n >= 0 && n < MAXSCOPES )
293 return scopeset[n];
294 return -1;
295 }
296
297 /*****************************************************************
298 ** dumpscope ()
299 *****************************************************************/
dumpscope(FILE * out)300 void dumpscope (FILE *out)
301 {
302 int i;
303 char str[63+1];
304
305 assert ( out != NULL );
306
307 fprintf (out, "\n%%%%SCOPE SECTION (%d elements)\n", nscope);
308
309 for ( i = 0; i < nscope; i++ )
310 {
311 fprintf (out, "%s\t", scopelist[i].name);
312 fprintf (out, "%s\t", scopelist[i].view && scopelist[i].view[0] ? scopelist[i].view: "none");
313 fprintf (out, "%s\t", scopelist[i].domain ? scopelist[i].domain: "");
314 ip6tostr (str, sizeof str, scopelist[i].matchprfx);
315 fprintf (out, "%s\t", str);
316 fprintf (out, "; unique_scopeid %d", scopelist[i].unique_scopeid);
317 fprintf (out, "\n");
318 }
319 fprintf (out, "%%%%END\n\n");
320 }
321
322 /*****************************************************************
323 ** dumpprefixlist ()
324 *****************************************************************/
dumpprefixlist(FILE * out)325 void dumpprefixlist (FILE *out)
326 {
327 int i;
328 char str[63+1];
329
330 assert ( out != NULL );
331
332 fprintf (out, "\n%%%%The current (command line) prefix list \n");
333
334 for ( i = 0; i < nprfx; i++ )
335 {
336 if ( prfxlist[i].prfx )
337 ip6tostr (str, sizeof str, prfxlist[i].prfx);
338 else if ( prfxlist[i].del )
339 strcpy (str, "ALL");
340 else /* should never happen */
341 fatal ("NULL prefix with add action in prefixlist; Use of -p w/o argument!");
342 fprintf (out, "%s\t", str);
343 fprintf (out, "%s\t", prfxlist[i].del ? "to_del": "to_add");
344 fprintf (out, "[%s]\t", prfxlist[i].scope->name);
345 fprintf (out, "\n");
346 }
347 fprintf (out, "%%%%END\n\n");
348 }
349
350 # define isnamechar(c) (isalpha (c) || isdigit (c) || (c) == '-' || (c) == '_' || (c) == '.')
namefromstr(char * to,int tolen,const char * from)351 static int namefromstr (char *to, int tolen, const char *from)
352 {
353 int i;
354 const char *p;
355
356 assert ( to != NULL );
357
358 if ( from == NULL )
359 return 0;
360
361 i = 0;
362 p = from;
363 if ( isalpha (*p) || *p == '_' )
364 {
365 while ( *p && i < tolen && isnamechar (*p) )
366 to[i++] = *p++;
367 }
368 else if ( *p == '*' ) /* "wildcard" for an empty field */
369 p++;
370 to[i] = '\0';
371
372 return p - from;
373 }
374