/***************************************************************** ** ** @(#) scope.c -- SCOPE SECTION and prefix matching functions ** ** Copyright (c) Oct 2015, Holger Zuleger HZNET. All rights reserved. ** ** This software is open source. ** *****************************************************************/ # include # include # include # include /* for link(), unlink() */ # include # include # include # include # include # include # include # include #ifdef HAVE_CONFIG_H # include #endif # include "misc.h" # include "ip6.h" # include "hostid.h" #define extern # include "scope.h" #undef extern # include "gen6dns.h" /* List of prefixes from the command line */ static prfx_t prfxlist[MAXPREFIXES]; static int nprfx; /* no of entries in prfx[] */ /* List of scopes out of SCOPE SECTION */ static scope_t scopelist[MAXSCOPES]; static int nscope; /* no of entries in scopelist[] */ static int scopeset[MAXSCOPES]; static int namefromstr (char *to, int tolen, const char *from); /***************************************************************** ** prfxput () ** puts a prefix into the prefix list *****************************************************************/ int prfxput (const ip6_t *prfx, int to_del) { ip6_t *new; int i; if ( nprfx >= MAXPREFIXES ) fatal ("maximum number of prefixes (%d) reached\n", MAXPREFIXES); new = NULL; if ( prfx ) { for ( i = 0; i = 0 && n < nprfx ) { prfxlist[n].prfx = prfxlist[nprfx].prfx; prfxlist[n].del = prfxlist[nprfx].del; prfxlist[n].scope = prfxlist[nprfx].scope; } return --nprfx; } /***************************************************************** ** prfxget () ** returns a prefix from the prefix list *****************************************************************/ prfx_t *prfxget (int n) { if ( n >= 0 && n < nprfx ) return &prfxlist[n]; return NULL; } /* Next functions loop through the prefix lsit */ static int prfxcnt; /***************************************************************** ** prfxstart () *****************************************************************/ prfx_t *prfxstart () { return prfxget (prfxcnt = 0); } /***************************************************************** ** prfxnext () *****************************************************************/ prfx_t *prfxnext () { return prfxget (++prfxcnt); } /***************************************************************** ** Scope functions starting here *****************************************************************/ #define isequal(a, b) ((a == NULL && b == NULL) || (a && b && strcmp (a, b) == 0) ) /***************************************************************** ** scopeput () *****************************************************************/ int scopeput (const char *name, const char *view, const char *domain, ip6_t *prfx) { prfx_t *prf; ip6_t *new; int i; const char *p; assert ( name != NULL ); assert ( view != NULL ); assert ( domain != NULL ); if ( nscope >= MAXSCOPES ) fatal ("maximum number of scopes (%d) reached\n", MAXSCOPES); snprintf (scopelist[nscope].name, sizeof (scopelist[0].name), "%s", name); /* Is viewname set ? */ if ( *view && *view != '*' && strcmp (view, "none") != 0 && (p = strdup (view)) != NULL ) scopelist[nscope].view = p; else scopelist[nscope].view = NULL; /* Is domain name set ? */ if ( *domain && (p = strdup (domain)) != NULL ) scopelist[nscope].domain = p; else scopelist[nscope].domain = NULL; if ( (new = ip6copy (NULL, prfx)) == NULL ) fatal ("%s:%d scopeput(): out of memory\n", __FILE__, __LINE__); scopelist[nscope].matchprfx = new; scopelist[nscope].unique_scopeid = nscope; /* mark this scope as duplicate if there is another one with the same view and domain */ for ( i = 0; i < nscope; i++ ) { if ( isequal (scopelist[i].view, scopelist[nscope].view) && isequal (scopelist[i].domain, scopelist[nscope].domain) ) { scopelist[nscope].unique_scopeid = scopelist[i].unique_scopeid; break; } } /* lookup a prefix in prefixlist matching this scope */ prf = prfxstart(); while ( prf ) { if ( prf->scope == NULL && /* entry do not have a scope */ ip6match (prf->prfx, scopelist[nscope].matchprfx) > 0 ) prf->scope = &scopelist[nscope]; prf = prfxnext(); } return ++nscope; } /***************************************************************** ** scopeget () *****************************************************************/ scope_t *scopeget (const char *scope) { int i; for ( i = 0; i < nscope; i++ ) { // fprintf (stderr, "\"%s\" == \"%s\"? => %p\n", scope, snet[i].name, &snet[i].sid); if ( strcmp (scope, scopelist[i].name) == 0 ) return &scopelist[i]; } return NULL; } /***************************************************************** ** parsescopeline () *****************************************************************/ int parsescopeline (const char * line, int delim) { const char *p; int len; char name[15+1]; char view[254+1]; char domain[254+1]; ip6_t prfx; assert ( line != NULL ); p = skipdelim (line, delim); p += namefromstr (name, sizeof name, p); if ( !isdelim (*p, delim) ) { error ("parsescopeline(): illegal scopename found near \"%.10s ...\"\n", p); return 0; } p = skipdelim (p, delim); p += namefromstr (view, sizeof view, p); if ( !isdelim (*p, delim) ) { error ("parsescopeline(): illegal viewname found near \"%.10s ...\"\n", p); return 0; } p = skipdelim (p, delim); p += namefromstr (domain, sizeof(domain), p); if ( !isdelim (*p, delim) ) { error ("parsescopeline(): illegal domain found near \"%.10s ...\"\n", p); return 0; } p = skipdelim (p, delim); p += ip6fromstr (&prfx, p); if ( !(ip6isset (&prfx) && ip6getsbit (&prfx) == 0 && ip6getebit (&prfx) <= 64) ) { error ("parsescopeline(): no matching prefix found near \"%.10s ...\"\n", p); return 0; } len = strlen (domain); if ( len > 0 && domain[len-1] != '.' ) #if defined(ADD_DEF_ORIGIN) && ADD_DEF_ORIGIN == 1 snprintf (&domain[len], sizeof (domain) - (len), ".%s", parm.origin); #else error ("Missing dot at the end of domain \"%s\" (in scope definition \"%s\")!\n", domain, name); #endif scopeput (name, view, domain, &prfx); return 1; } void scopeset_clear (void) { int i; for ( i = 0; i < MAXSCOPES; i++ ) scopeset[i] = 0; } int scopeset_set (int n) { int prevval; prevval = 0; if ( n >= 0 && n < MAXSCOPES ) { prevval = scopeset[n]; scopeset[n] = 1; } return prevval; } int scopeset_get (int n) { if ( n >= 0 && n < MAXSCOPES ) return scopeset[n]; return -1; } /***************************************************************** ** dumpscope () *****************************************************************/ void dumpscope (FILE *out) { int i; char str[63+1]; assert ( out != NULL ); fprintf (out, "\n%%%%SCOPE SECTION (%d elements)\n", nscope); for ( i = 0; i < nscope; i++ ) { fprintf (out, "%s\t", scopelist[i].name); fprintf (out, "%s\t", scopelist[i].view && scopelist[i].view[0] ? scopelist[i].view: "none"); fprintf (out, "%s\t", scopelist[i].domain ? scopelist[i].domain: ""); ip6tostr (str, sizeof str, scopelist[i].matchprfx); fprintf (out, "%s\t", str); fprintf (out, "; unique_scopeid %d", scopelist[i].unique_scopeid); fprintf (out, "\n"); } fprintf (out, "%%%%END\n\n"); } /***************************************************************** ** dumpprefixlist () *****************************************************************/ void dumpprefixlist (FILE *out) { int i; char str[63+1]; assert ( out != NULL ); fprintf (out, "\n%%%%The current (command line) prefix list \n"); for ( i = 0; i < nprfx; i++ ) { if ( prfxlist[i].prfx ) ip6tostr (str, sizeof str, prfxlist[i].prfx); else if ( prfxlist[i].del ) strcpy (str, "ALL"); else /* should never happen */ fatal ("NULL prefix with add action in prefixlist; Use of -p w/o argument!"); fprintf (out, "%s\t", str); fprintf (out, "%s\t", prfxlist[i].del ? "to_del": "to_add"); fprintf (out, "[%s]\t", prfxlist[i].scope->name); fprintf (out, "\n"); } fprintf (out, "%%%%END\n\n"); } # define isnamechar(c) (isalpha (c) || isdigit (c) || (c) == '-' || (c) == '_' || (c) == '.') static int namefromstr (char *to, int tolen, const char *from) { int i; const char *p; assert ( to != NULL ); if ( from == NULL ) return 0; i = 0; p = from; if ( isalpha (*p) || *p == '_' ) { while ( *p && i < tolen && isnamechar (*p) ) to[i++] = *p++; } else if ( *p == '*' ) /* "wildcard" for an empty field */ p++; to[i] = '\0'; return p - from; }