This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.sbin / named / db_load.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
36#endif /* not lint */
37
38/*
39 * Load data base from ascii backupfile. Format similar to RFC 883.
40 */
41
42#include <sys/param.h>
43#include <sys/time.h>
44#include <sys/stat.h>
45#include <netinet/in.h>
46#include <stdio.h>
47#include <syslog.h>
48#include <ctype.h>
49#include <netdb.h>
50#include <arpa/nameser.h>
51#include "ns.h"
52#include "db.h"
53
54extern char *index();
55extern int max_cache_ttl;
56
57/*
58 * Map class and type names to number
59 */
60struct map {
61 char token[8];
62 int val;
63};
64
65struct map m_class[] = {
66 "in", C_IN,
67#ifdef notdef
68 "any", C_ANY, /* any is a QCLASS, not CLASS */
69#endif
70 "chaos", C_CHAOS,
71 "hs", C_HS,
72};
73#define NCLASS (sizeof(m_class)/sizeof(struct map))
74
75struct map m_type[] = {
76 "a", T_A,
77 "ns", T_NS,
78 "cname", T_CNAME,
79 "soa", T_SOA,
80 "mb", T_MB,
81 "mg", T_MG,
82 "mr", T_MR,
83 "null", T_NULL,
84 "wks", T_WKS,
85 "ptr", T_PTR,
86 "hinfo", T_HINFO,
87 "minfo", T_MINFO,
88 "mx", T_MX,
89 "uinfo", T_UINFO,
90 "txt", T_TXT,
91 "uid", T_UID,
92 "gid", T_GID,
93#ifdef notdef
94 "any", T_ANY, /* any is a QTYPE, not TYPE */
95#endif
96#ifdef ALLOW_T_UNSPEC
97 "unspec", T_UNSPEC,
98#endif ALLOW_T_UNSPEC
99};
100#define NTYPE (sizeof(m_type)/sizeof(struct map))
101
102/*
103 * Parser token values
104 */
105#define CURRENT 1
106#define DOT 2
107#define AT 3
108#define DNAME 4
109#define INCLUDE 5
110#define ORIGIN 6
111#define ERROR 7
112
113int lineno; /* current line number */
114
115/*
116 * Load the database from 'filename'. Origin is appended to all domain
117 * names in the file.
118 */
119db_load(filename, in_origin, zp, doinginclude)
120 char *filename, *in_origin;
121 struct zoneinfo *zp;
122{
123 register u_char *cp;
124 register struct map *mp;
125 char domain[MAXDNAME];
126 char origin[MAXDNAME];
127 char tmporigin[MAXDNAME];
128 u_char buf[MAXDATA];
129 u_char data[MAXDATA];
130 u_char *cp1;
131 char *op;
132 int c;
133 int class, type, ttl, dbflags, dataflags;
134 int read_soa = 0; /* number of soa's read */
135 struct databuf *dp;
136 FILE *fp;
137 int slineno, i, errs = 0, didinclude = 0;
138 register u_long n;
139 struct stat sb;
140
141#ifdef DEBUG
142 if (debug)
143 fprintf(ddt,"db_load(%s, %s, %d, %d)\n",
144 filename, in_origin, zp - zones, doinginclude);
145#endif
146
147 (void) strcpy(origin, in_origin);
148 if ((fp = fopen(filename, "r")) == NULL) {
149 syslog(LOG_ERR, "%s: %m", filename);
150#ifdef DEBUG
151 if (debug)
152 fprintf(ddt,"db_load: error opening file %s\n", filename);
153#endif
154 return (-1);
155 }
156 if (zp->z_type == Z_CACHE) {
157 dbflags = DB_NODATA | DB_NOHINTS;
158 dataflags = DB_F_HINT;
159 } else {
160 dbflags = DB_NODATA;
161 dataflags = 0;
162 }
163 gettime(&tt);
164 if (fstat(fileno(fp), &sb) < 0) {
165 syslog(LOG_ERR, "%s: %m", filename);
166 sb.st_mtime = (int)tt.tv_sec;
167 }
168 slineno = lineno;
169 lineno = 1;
170 domain[0] = '\0';
171 class = C_IN;
172 zp->z_state &= ~(Z_INCLUDE|Z_DB_BAD);
173 while ((c = gettoken(fp)) != EOF) {
174 switch (c) {
175 case INCLUDE:
176 if (!getword(buf, sizeof(buf), fp)) /* file name */
177 break;
178 if (!getword(tmporigin, sizeof(tmporigin), fp))
179 strcpy(tmporigin, origin);
180 else {
181 makename(tmporigin, origin);
182 endline(fp);
183 }
184 didinclude = 1;
185 errs += db_load(buf, tmporigin, zp, 1);
186 continue;
187
188 case ORIGIN:
189 (void) strcpy((char *)buf, origin);
190 if (!getword(origin, sizeof(origin), fp))
191 break;
192#ifdef DEBUG
193 if (debug > 3)
194 fprintf(ddt,"db_load: origin %s, buf %s\n",
195 origin, buf);
196#endif
197 makename(origin, buf);
198#ifdef DEBUG
199 if (debug > 3)
200 fprintf(ddt,"db_load: origin now %s\n", origin);
201#endif
202 continue;
203
204 case DNAME:
205 if (!getword(domain, sizeof(domain), fp))
206 break;
207 n = strlen(domain) - 1;
208 if (domain[n] == '.')
209 domain[n] = '\0';
210 else if (*origin) {
211 (void) strcat(domain, ".");
212 (void) strcat(domain, origin);
213 }
214 goto gotdomain;
215
216 case AT:
217 (void) strcpy(domain, origin);
218 goto gotdomain;
219
220 case DOT:
221 domain[0] = '\0';
222 /* fall thru ... */
223 case CURRENT:
224 gotdomain:
225 if (!getword(buf, sizeof(buf), fp)) {
226 if (c == CURRENT)
227 continue;
228 break;
229 }
230 cp = buf;
231 ttl = 0;
232 if (isdigit(*cp)) {
233 n = 0;
234 do
235 n = n * 10 + (*cp++ - '0');
236 while (isdigit(*cp));
237 if (zp->z_type == Z_CACHE) {
238 /* this allows the cache entry to age */
239 /* while sitting on disk (powered off) */
240 if (n > max_cache_ttl)
241 n = max_cache_ttl;
242 n += sb.st_mtime;
243 }
244 ttl = n;
245 if (!getword(buf, sizeof(buf), fp))
246 break;
247 }
248 for (mp = m_class; mp < m_class+NCLASS; mp++)
249 if (!strcasecmp((char *)buf, mp->token)) {
250 class = mp->val;
251 (void) getword(buf, sizeof(buf), fp);
252 break;
253 }
254 for (mp = m_type; mp < m_type+NTYPE; mp++)
255 if (!strcasecmp((char *)buf, mp->token)) {
256 type = mp->val;
257 goto fndtype;
258 }
259#ifdef DEBUG
260 if (debug)
261 fprintf(ddt,"Line %d: Unknown type: %s.\n",
262 lineno, buf);
263#endif
264 errs++;
265 syslog(LOG_ERR, "Line %d: Unknown type: %s.\n",
266 lineno, buf);
267 break;
268 fndtype:
269#ifdef ALLOW_T_UNSPEC
270 /* Don't do anything here for T_UNSPEC...
271 * read input separately later
272 */
273 if (type != T_UNSPEC) {
274#endif ALLOW_T_UNSPEC
275 if (!getword(buf, sizeof(buf), fp))
276 break;
277#ifdef DEBUG
278 if (debug >= 3)
279 fprintf(ddt,
280 "d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",
281 domain, class, type, ttl, buf);
282#endif
283#ifdef ALLOW_T_UNSPEC
284 }
285#endif ALLOW_T_UNSPEC
286 /*
287 * Convert the ascii data 'buf' to the proper format
288 * based on the type and pack into 'data'.
289 */
290 switch (type) {
291 case T_A:
292 n = ntohl((u_long)inet_addr((char *)buf));
293 cp = data;
294 PUTLONG(n, cp);
295 n = sizeof(u_long);
296 break;
297
298 case T_HINFO:
299 n = strlen((char *)buf);
300 if (n > 255) {
301 syslog(LOG_WARNING,
302 "%s: line %d: CPU type too long",
303 filename, lineno);
304 n = 255;
305 }
306 data[0] = n;
307 bcopy(buf, (char *)data + 1, (int)n);
308 n++;
309 if (!getword(buf, sizeof(buf), fp))
310 break;
311 i = strlen((char *)buf);
312 if (i > 255) {
313 syslog(LOG_WARNING,
314 "%s: line %d: OS type too long",
315 filename, lineno);
316 i = 255;
317 }
318 data[n] = i;
319 bcopy(buf, data + n + 1, i);
320 n += i + 1;
321 endline(fp);
322 break;
323
324 case T_SOA:
325 case T_MINFO:
326 (void) strcpy((char *)data, (char *)buf);
327 makename(data, origin);
328 cp = data + strlen((char *)data) + 1;
329 if (!getword(cp,
330 sizeof(data) - (cp - data),fp)) {
331 n = cp - data;
332 break;
333 }
334 makename(cp, origin);
335 cp += strlen((char *)cp) + 1;
336 if (type == T_MINFO) {
337 n = cp - data;
338 break;
339 }
340 if (getnonblank(fp) != '(')
341 goto err;
342 zp->z_serial = getnum(fp);
343 n = (u_long) zp->z_serial;
344 PUTLONG(n, cp);
345 zp->z_refresh = getnum(fp);
346 n = (u_long) zp->z_refresh;
347 PUTLONG(n, cp);
348 if (zp->z_type == Z_SECONDARY)
349 zp->z_time = sb.st_mtime + zp->z_refresh;
350 zp->z_retry = getnum(fp);
351 n = (u_long) zp->z_retry;
352 PUTLONG(n, cp);
353 zp->z_expire = getnum(fp);
354 n = (u_long) zp->z_expire;
355 PUTLONG (n, cp);
356 zp->z_minimum = getnum(fp);
357 n = (u_long) zp->z_minimum;
358 PUTLONG (n, cp);
359 n = cp - data;
360 if (getnonblank(fp) != ')')
361 goto err;
362 read_soa++;
363 endline(fp);
364 break;
365
366 case T_UID:
367 case T_GID:
368 n = 0;
369 cp = buf;
370 while (isdigit(*cp))
371 n = n * 10 + (*cp++ - '0');
372 if (cp == buf)
373 goto err;
374 cp = data;
375 PUTLONG(n, cp);
376 n = sizeof(long);
377 break;
378
379 case T_WKS:
380 /* Address */
381 n = ntohl((u_long)inet_addr((char *)buf));
382 cp = data;
383 PUTLONG(n, cp);
384 *cp = getprotocol(fp, filename);
385 /* Protocol */
386 n = sizeof(u_long) + sizeof(char);
387 /* Services */
388 n = getservices((int)n, data, fp, filename);
389 break;
390
391 case T_NS:
392 case T_CNAME:
393 case T_MB:
394 case T_MG:
395 case T_MR:
396 case T_PTR:
397 (void) strcpy((char *)data, (char *)buf);
398 makename(data, origin);
399 n = strlen((char *)data) + 1;
400 break;
401
402 case T_UINFO:
403 cp = (u_char *)index((char *)buf, '&');
404 bzero(data, sizeof(data));
405 if ( cp != NULL) {
406 (void) strncpy((char *)data,
407 (char *)buf, cp - buf);
408 op = index(domain, '.');
409 if ( op != NULL)
410 (void) strncat((char *)data,
411 domain,op-domain);
412 else
413 (void) strcat((char *)data,
414 domain);
415 (void) strcat((char *)data,
416 (char *)++cp);
417 } else
418 (void) strcpy((char *)data,
419 (char *)buf);
420 n = strlen((char *)data) + 1;
421 break;
422 case T_MX:
423 n = 0;
424 cp = buf;
425 while (isdigit(*cp))
426 n = n * 10 + (*cp++ - '0');
427 /* catch bad values */
428 if ((cp == buf) || (n > 65535))
429 goto err;
430
431 cp = data;
432 PUTSHORT((u_short)n, cp);
433
434 if (!getword(buf, sizeof(buf), fp))
435 break;
436 (void) strcpy((char *)cp, (char *)buf);
437 makename(cp, origin);
438 /* get pointer to place in data */
439 cp += strlen((char *)cp) +1;
440
441 /* now save length */
442 n = (cp - data);
443 break;
444
445 case T_TXT:
446 i = strlen((char *)buf);
447 cp = data;
448 cp1 = buf;
449 /*
450 * there is expansion here so make sure we
451 * don't overflow data
452 */
453 if (i > sizeof(data) * 255 / 256) {
454 syslog(LOG_WARNING,
455 "%s: line %d: TXT record truncated",
456 filename, lineno);
457 i = sizeof(data) * 255 / 256;
458 }
459 while (i > 255) {
460 *cp++ = 255;
461 bcopy(cp1, cp, 255);
462 cp += 255;
463 cp1 += 255;
464 i -= 255;
465 }
466 *cp++ = i;
467 bcopy(cp1, cp, i);
468 cp += i;
469 n = cp - data;
470 endline(fp);
471 break;
472#ifdef ALLOW_T_UNSPEC
473 case T_UNSPEC:
474 {
475 int rcode;
476 fgets(buf, sizeof(buf), fp);
477#ifdef DEBUG
478 if (debug)
479 fprintf(ddt, "loading T_UNSPEC\n");
480#endif DEBUG
481 if (rcode = atob(buf,
482 strlen((char *)buf), data,
483 sizeof(data), &n)) {
484 if (rcode == CONV_OVERFLOW) {
485#ifdef DEBUG
486 if (debug)
487 fprintf(ddt,
488 "Load T_UNSPEC: input buffer overflow\n");
489#endif DEBUG
490 errs++;
491 syslog(LOG_ERR,
492 "Load T_UNSPEC: input buffer overflow");
493 } else {
494#ifdef DEBUG
495 if (debug)
496 fprintf(ddt,
497 "Load T_UNSPEC: Data in bad atob format\n");
498#endif DEBUG
499 errs++;
500 syslog(LOG_ERR,
501 "Load T_UNSPEC: Data in bad atob format");
502 }
503 }
504 }
505 break;
506#endif ALLOW_T_UNSPEC
507
508 default:
509 goto err;
510 }
511 dp = savedata(class, type, (u_long)ttl, data, (int)n);
512 dp->d_zone = zp - zones;
513 dp->d_flags = dataflags;
514 if ((c = db_update(domain, dp, dp, dbflags,
515 (zp->z_type == Z_CACHE)? fcachetab : hashtab)) < 0) {
516#ifdef DEBUG
517 if (debug && (c != DATAEXISTS))
518 fprintf(ddt,"update failed\n");
519#endif
520 }
521 continue;
522
523 case ERROR:
524 break;
525 }
526 err:
527 errs++;
528 syslog(LOG_ERR, "%s: line %d: database format error (%s)",
529 filename, lineno, buf);
530#ifdef DEBUG
531 if (debug)
532 fprintf(ddt,"%s: line %d: database format error ('%s', %d)\n",
533 filename, lineno, buf, n);
534#endif
535 while ((c = getc(fp)) != EOF && c != '\n')
536 ;
537 if (c == '\n')
538 lineno++;
539 }
540 (void) fclose(fp);
541 lineno = slineno;
542 if (doinginclude == 0) {
543 if (didinclude) {
544 zp->z_state |= Z_INCLUDE;
545 zp->z_ftime = 0;
546 } else
547 zp->z_ftime = sb.st_mtime;
548 zp->z_lastupdate = sb.st_mtime;
549 if (zp->z_type != Z_CACHE && read_soa != 1) {
550 errs++;
551 if (read_soa == 0)
552 syslog(LOG_ERR, "%s: no SOA record", filename);
553 else
554 syslog(LOG_ERR, "%s: multiple SOA records",
555 filename);
556 }
557 }
558 if (errs)
559 zp->z_state |= Z_DB_BAD;
560 return (errs);
561}
562
563int gettoken(fp)
564 register FILE *fp;
565{
566 register int c;
567 char op[32];
568
569 for (;;) {
570 c = getc(fp);
571 top:
572 switch (c) {
573 case EOF:
574 return (EOF);
575
576 case '$':
577 if (getword(op, sizeof(op), fp)) {
578 if (!strcasecmp("include", op))
579 return (INCLUDE);
580 if (!strcasecmp("origin", op))
581 return (ORIGIN);
582 }
583#ifdef DEBUG
584 if (debug)
585 fprintf(ddt,"Line %d: Unknown $ option: $%s\n",
586 lineno, op);
587#endif
588 syslog(LOG_ERR,"Line %d: Unknown $ option: $%s\n",
589 lineno, op);
590 return (ERROR);
591
592 case ';':
593 while ((c = getc(fp)) != EOF && c != '\n')
594 ;
595 goto top;
596
597 case ' ':
598 case '\t':
599 return (CURRENT);
600
601 case '.':
602 return (DOT);
603
604 case '@':
605 return (AT);
606
607 case '\n':
608 lineno++;
609 continue;
610
611 default:
612 (void) ungetc(c, fp);
613 return (DNAME);
614 }
615 }
616}
617
618/*
619 * Get next word, skipping blanks & comments.
620 */
621getword(buf, size, fp)
622 char *buf;
623 int size;
624 FILE *fp;
625{
626 register char *cp;
627 register int c;
628
629 for (cp = buf; (c = getc(fp)) != EOF; ) {
630 if (c == ';') {
631 while ((c = getc(fp)) != EOF && c != '\n')
632 ;
633 c = '\n';
634 }
635 if (c == '\n') {
636 if (cp != buf)
637 ungetc(c, fp);
638 else
639 lineno++;
640 break;
641 }
642 if (isspace(c)) {
643 while (isspace(c = getc(fp)) && c != '\n')
644 ;
645 ungetc(c, fp);
646 if (cp != buf) /* Trailing whitespace */
647 break;
648 continue; /* Leading whitespace */
649 }
650 if (c == '"') {
651 while ((c = getc(fp)) != EOF && c != '"' && c != '\n') {
652 if (c == '\\') {
653 if ((c = getc(fp)) == EOF)
654 c = '\\';
655 if (c == '\n')
656 lineno++;
657 }
658 if (cp >= buf+size-1)
659 break;
660 *cp++ = c;
661 }
662 if (c == '\n') {
663 lineno++;
664 break;
665 }
666 continue;
667 }
668 if (c == '\\') {
669 if ((c = getc(fp)) == EOF)
670 c = '\\';
671 if (c == '\n')
672 lineno++;
673 }
674 if (cp >= buf+size-1)
675 break;
676 *cp++ = c;
677 }
678 *cp = '\0';
679 return (cp != buf);
680}
681
682getnum(fp)
683 FILE *fp;
684{
685 register int c, n;
686 int seendigit = 0;
687 int seendecimal = 0;
688
689 for (n = 0; (c = getc(fp)) != EOF; ) {
690 if (isspace(c)) {
691 if (c == '\n')
692 lineno++;
693 if (seendigit)
694 break;
695 continue;
696 }
697 if (c == ';') {
698 while ((c = getc(fp)) != EOF && c != '\n')
699 ;
700 if (c == '\n')
701 lineno++;
702 if (seendigit)
703 break;
704 continue;
705 }
706 if (!isdigit(c)) {
707 if (c == ')' && seendigit) {
708 (void) ungetc(c, fp);
709 break;
710 }
711 if (seendecimal || c != '.') {
712 syslog(LOG_ERR, "line %d: expected a number",
713 lineno);
714#ifdef DEBUG
715 if (debug)
716 fprintf(ddt,"line %d: expected a number",
717 lineno);
718#endif
719 exit(1); /* XXX why exit */
720 } else {
721 if (!seendigit)
722 n = 1;
723 n = n * 1000 ;
724 seendigit = 1;
725 seendecimal = 1;
726 }
727 continue;
728 }
729 n = n * 10 + (c - '0');
730 seendigit = 1;
731 }
732 return (n);
733}
734
735getnonblank(fp)
736 FILE *fp;
737{
738 register int c;
739
740 while ( (c = getc(fp)) != EOF ) {
741 if (isspace(c)) {
742 if (c == '\n')
743 lineno++;
744 continue;
745 }
746 if (c == ';') {
747 while ((c = getc(fp)) != EOF && c != '\n')
748 ;
749 if (c == '\n')
750 lineno++;
751 continue;
752 }
753 return(c);
754 }
755 syslog(LOG_ERR, "line %d: unexpected EOF", lineno);
756#ifdef DEBUG
757 if (debug)
758 fprintf(ddt, "line %d: unexpected EOF", lineno);
759#endif
760 return (EOF);
761}
762
763/*
764 * Take name and fix it according to following rules:
765 * "." means root.
766 * "@" means current origin.
767 * "name." means no changes.
768 * "name" means append origin.
769 */
770makename(name, origin)
771 char *name, *origin;
772{
773 int n;
774
775 if (origin[0] == '.')
776 origin++;
777 n = strlen(name);
778 if (n == 1) {
779 if (name[0] == '.') {
780 name[0] = '\0';
781 return;
782 }
783 if (name[0] == '@') {
784 (void) strcpy(name, origin);
785 return;
786 }
787 }
788 if (n > 0) {
789 if (name[n - 1] == '.')
790 name[n - 1] = '\0';
791 else if (origin[0] != '\0') {
792 name[n] = '.';
793 (void) strcpy(name + n + 1, origin);
794 }
795 }
796}
797
798endline(fp)
799 register FILE *fp;
800{
801 register int c;
802 while (c = getc(fp))
803 if (c == '\n') {
804 (void) ungetc(c,fp);
805 break;
806 } else if (c == EOF)
807 break;
808}
809
810#define MAXPORT 256
811#define MAXLEN 24
812
813getprotocol(fp, src)
814 FILE *fp;
815 char *src;
816{
817 int k;
818 char b[MAXLEN];
819
820 (void) getword(b, sizeof(b), fp);
821
822 k = protocolnumber(b);
823 if(k == -1)
824 syslog(LOG_ERR, "%s: line %d: unknown protocol: %s.",
825 src, lineno, b);
826 return(k);
827}
828
829int
830getservices(n, data, fp, src)
831 int n;
832 char *data, *src;
833 FILE *fp;
834{
835 int j, ch;
836 int k;
837 int maxl;
838 int bracket;
839 char b[MAXLEN];
840 char bm[MAXPORT/8];
841
842 for (j = 0; j < MAXPORT/8; j++)
843 bm[j] = 0;
844 maxl = 0;
845 bracket = 0;
846 while (getword(b, sizeof(b), fp) || bracket) {
847 if (feof(fp) || ferror(fp))
848 break;
849 if (strlen(b) == 0)
850 continue;
851 if ( b[0] == '(') {
852 bracket++;
853 continue;
854 }
855 if ( b[0] == ')') {
856 bracket = 0;
857 while ((ch = getc(fp)) != EOF && ch != '\n')
858 ;
859 if (ch == '\n')
860 lineno++;
861 break;
862 }
863 k = servicenumber(b);
864 if (k == -1) {
865 syslog(LOG_WARNING, "%s: line %d: Unknown service '%s'",
866 src, lineno, b);
867 continue;
868 }
869 if ((k < MAXPORT) && (k)) {
870 bm[k/8] |= (0x80>>(k%8));
871 if (k > maxl)
872 maxl=k;
873 }
874 else {
875 syslog(LOG_WARNING,
876 "%s: line %d: port no. (%d) too big\n",
877 src, lineno, k);
878#ifdef DEBUG
879 if (debug)
880 fprintf(ddt,
881 "%s: line %d: port no. (%d) too big\n",
882 src, lineno, k);
883#endif
884 }
885 }
886 if (bracket)
887 syslog(LOG_WARNING, "%s: line %d: missing close paren\n",
888 src, lineno);
889 maxl = maxl/8+1;
890 bcopy(bm, data+n, maxl);
891 return(maxl+n);
892}
893
894get_sort_list(fp)
895 FILE *fp;
896{
897 extern struct netinfo **enettab;
898 register struct netinfo *ntp, **end = enettab;
899 extern struct netinfo *findnetinfo();
900 struct in_addr addr;
901 char buf[BUFSIZ];
902
903#ifdef DEBUG
904 if (debug)
905 fprintf(ddt,"sortlist ");
906#endif
907 while (getword(buf, sizeof(buf), fp)) {
908 if (strlen(buf) == 0)
909 break;
910#ifdef DEBUG
911 if (debug)
912 fprintf(ddt," %s",buf);
913#endif
914 addr.s_addr = inet_addr(buf);
915 if (addr.s_addr == (unsigned)-1) {
916 /* resolve name to address - XXX */
917 continue;
918 }
919 /* Check for duplicates, then add to linked list */
920 if (findnetinfo(addr))
921 continue;
922 ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
923 ntp->my_addr = addr;
924 ntp->next = NULL;
925 ntp->mask = net_mask(ntp->my_addr);
926 ntp->net = ntp->my_addr.s_addr & ntp->mask;
927 if (ntp->net != addr.s_addr) {
928 struct in_addr tmpaddr;
929
930 tmpaddr.s_addr = ntp->net;
931 syslog(LOG_WARNING, "sortlist: addr %s != %s", buf,
932 inet_ntoa(tmpaddr));
933#ifdef DEBUG
934 if (debug)
935 fprintf(ddt, "\nsortlist: addr %s != %s\n", buf,
936 inet_ntoa(tmpaddr));
937#endif
938 }
939
940 *end = ntp;
941 end = &ntp->next;
942 }
943
944#ifdef DEBUG
945 if (debug)
946 fprintf(ddt,"\n");
947 if (debug > 2)
948 printnetinfo(*enettab);
949 if (debug > 4) {
950 extern struct netinfo *nettab;
951
952 fprintf(ddt, "\nFull sort list:\n");
953 printnetinfo(nettab);
954 }
955#endif
956}
957
958free_sort_list()
959{
960 extern struct netinfo **enettab;
961 register struct netinfo *ntp, *next;
962
963 for (ntp = *enettab; ntp != NULL; ntp = next) {
964 next = ntp->next;
965 free((char *)ntp);
966 }
967 *enettab = NULL;
968}