4 ACCEPT = 0, /* verbs in control file */
12 Subchar = '#', /* character substituted for '/' in file names */
15 static Keyword actions[] = {
26 static void acctinsert(Node*, char*);
27 static char* getline(Biobuf*);
28 static void ipinsert(Node*, char*);
29 static void ipsort(void);
32 * Input the configuration file
33 * 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 if(cidrparse(&ip, cp) == -1)
81 np = newnode(dir, cp, Trustedperm, 0111, trustedqid++);
84 np->d.name = atom(cp);
89 lastconftime = time(0);
93 * Reload the control file, if necessary
104 fprint(debugfd,"loading %s\n", ctlfile);
106 bp = Bopen(ctlfile, OREAD);
111 for(dir = root->children; dir; dir = dir->sibs){
112 if (dir->d.type != Addrdir)
114 for(np = dir->children; np; np = np->sibs)
126 if(*cp == 0) /* space before keyword */
129 action = findkey(cp, actions);
132 if (action == ACCEPT)
133 dir = dirwalk("allow", root);
136 dir = dirwalk("delay", root);
138 dir = dirwalk(cp, root);
142 for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
151 dummy.d.mtime = dummy.d.atime = lastctltime = time(0);
155 * get a canonicalized line: a string of null-terminated lower-case
156 * tokens with a two null bytes at the end.
168 cp = Brdline(bp, '\n');
173 if(buf == 0 || bufsize < n+1){
177 buf = realloc(buf, bufsize);
182 for (p = cp; *p; p++){
184 if(c == '\\' && p[1]) /* we don't allow \<newline> */
190 if(c == ' ' || c == '\t' || c == ',')
191 if(q == buf || q[-1] == 0)
211 findkey(char *val, Keyword *p)
215 if(strcmp(val, p->name) == 0)
221 * parse a cidr specification in either IP/mask or IP#mask format
224 cidrparse(Cidraddr *cidr, char *cp)
227 char buf[64], *p, *slash;
231 * find '/' or '#' character in the cidr specification
234 for(p = buf; p < buf+sizeof(buf)-1 && *cp; p++) {
251 if(parseipandmask(ip, cidr->mask, buf, slash) == -1)
253 maskip(ip, cidr->mask, cidr->ipaddr);
259 * Substitute Subchar ('#') for '/'
273 * Insert an account pseudo-file in a directory
276 acctinsert(Node *np, char *cp)
282 static char *dangerous[] = { "*", "!", "*!", "!*", "*!*", 0 };
284 if(cp == 0 || *cp == 0)
287 /* rule out dangerous patterns */
288 for (i = 0; dangerous[i]; i++)
289 if(strcmp(cp, dangerous[i])== 0)
292 np = dirwalk("account", np);
297 if(i >= np->allocated){
298 np->allocated = np->count;
299 np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
301 fatal("out of memory");
304 ap = &np->addrs[i]; /* new entry on end */
307 fatal("out of memory");
309 ap->name = atom(tmp);
314 * Insert an IP address pseudo-file in a directory
317 ipinsert(Node *np, char *cp)
324 if(cp == 0 || *cp == 0 || cidrparse(&ip, cp) == -1)
327 np = dirwalk("ip", np);
332 if(i >= np->allocated){
333 np->allocated = np->count;
334 np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
336 fatal("out of memory");
339 ap = &np->addrs[i]; /* new entry on end */
343 fatal("out of memory");
345 ap->name = atom(tmp);
350 ipaddrcomp(void *a, void *b)
352 return ipcmp(((Address*)a)->ip.ipaddr, ((Address*)b)->ip.ipaddr);
356 * Sort a directory of IP addresses
365 for(dir = root->children; dir; dir = dir->sibs){
366 if (dir->d.type != Addrdir)
368 for(np = dir->children; np; np = np->sibs){
369 if(np->d.type == IPaddr && np->count && np->addrs)
370 qsort(np->addrs, np->count, sizeof(Address), ipaddrcomp);