5 ACCEPT = 0, /* verbs in control file */
13 Subchar = '#', /* character substituted for '/' in file names */
16 static Keyword actions[] = {
27 static void acctinsert(Node*, char*);
28 static char* getline(Biobuf*);
29 static void ipinsert(Node*, char*);
30 static void ipsort(void);
33 * Input the configuration file
34 * Currently we only process the "ournets"
45 fprint(debugfd, "loading %s\n", conffile);
47 bp = Bopen(conffile, OREAD);
51 dir = finddir(Trusted);
56 * if this isn't the first time, purge permanent entries
58 trustedqid = Qtrustedfile;
61 for(np = dir->children; np; np = *l){
62 if(np->d.type == Trustedperm){
66 np->d.qid.path = trustedqid++;
77 if (strcmp(cp, "ournets") == 0){
78 for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
79 np = newnode(dir, cp, Trustedperm, 0111, trustedqid++);
80 cidrparse(&np->ip, cp);
82 np->d.name = atom(cp);
87 lastconftime = time(0);
91 * Reload the control file, if necessary
102 fprint(debugfd,"loading %s\n", ctlfile);
104 bp = Bopen(ctlfile, OREAD);
109 for(dir = root->children; dir; dir = dir->sibs){
110 if (dir->d.type != Addrdir)
112 for(np = dir->children; np; np = np->sibs)
124 if(*cp == 0) /* space before keyword */
127 action = findkey(cp, actions);
130 if (action == ACCEPT)
131 dir = dirwalk("allow", root);
134 dir = dirwalk("delay", root);
136 dir = dirwalk(cp, root);
140 for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
149 dummy.d.mtime = dummy.d.atime = lastctltime = time(0);
153 * get a canonicalized line: a string of null-terminated lower-case
154 * tokens with a two null bytes at the end.
166 cp = Brdline(bp, '\n');
171 if(buf == 0 || bufsize < n+1){
175 buf = realloc(buf, bufsize);
180 for (p = cp; *p; p++){
182 if(c == '\\' && p[1]) /* we don't allow \<newline> */
188 if(c == ' ' || c == '\t' || c == ',')
189 if(q == buf || q[-1] == 0)
209 findkey(char *val, Keyword *p)
213 if(strcmp(val, p->name) == 0)
219 * parse a cidr specification in either IP/mask or IP#mask format
222 cidrparse(Cidraddr *cidr, char *cp)
228 uchar addr[IPv4addrlen];
229 uchar mask[IPv4addrlen];
233 * find '/' or '#' character in the cidr specification
236 for(p = buf; p < buf+sizeof(buf)-1 && *cp; p++) {
253 v4parsecidr(addr, mask, buf);
257 * if a mask isn't specified, we build a minimal mask
258 * instead of using the default mask for that net. in this
259 * case we never allow a class A mask (0xff000000).
264 for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.'))
265 m = (m>>8)|0xff000000;
267 /* force at least a class B */
275 * Substitute Subchar ('#') for '/'
289 * Insert an account pseudo-file in a directory
292 acctinsert(Node *np, char *cp)
298 static char *dangerous[] = { "*", "!", "*!", "!*", "*!*", 0 };
300 if(cp == 0 || *cp == 0)
303 /* rule out dangerous patterns */
304 for (i = 0; dangerous[i]; i++)
305 if(strcmp(cp, dangerous[i])== 0)
308 np = dirwalk("account", np);
313 if(i >= np->allocated){
314 np->allocated = np->count;
315 np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
317 fatal("out of memory");
320 ap = &np->addrs[i]; /* new entry on end */
323 fatal("out of memory");
325 ap->name = atom(tmp);
330 * Insert an IP address pseudo-file in a directory
333 ipinsert(Node *np, char *cp)
338 if(cp == 0 || *cp == 0)
341 np = dirwalk("ip", np);
346 if(i >= np->allocated){
347 np->allocated = np->count;
348 np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
350 fatal("out of memory");
353 ap = &np->addrs[i]; /* new entry on end */
356 fatal("out of memory");
358 ap->name = atom(tmp);
360 cidrparse(&ap->ip, cp);
364 ipcomp(void *a, void *b)
368 aip = ((Address*)a)->ip.ipaddr;
369 bip = ((Address*)b)->ip.ipaddr;
378 * Sort a directory of IP addresses
387 for(dir = root->children; dir; dir = dir->sibs){
388 if (dir->d.type != Addrdir)
390 for(np = dir->children; np; np = np->sibs){
391 if(np->d.type == IPaddr && np->count && np->addrs)
392 qsort(np->addrs, np->count, sizeof(Address), ipcomp);