xref: /386bsd/usr/src/usr.sbin/named/db_load.c (revision a2142627)
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
35 static 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 
54 extern char *index();
55 extern int max_cache_ttl;
56 
57 /*
58  * Map class and type names to number
59  */
60 struct map {
61 	char	token[8];
62 	int	val;
63 };
64 
65 struct 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 
75 struct 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 
113 int	lineno;		/* current line number */
114 
115 /*
116  * Load the database from 'filename'. Origin is appended to all domain
117  * names in the file.
118  */
db_load(filename,in_origin,zp,doinginclude)119 db_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 
gettoken(fp)563 int 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  */
getword(buf,size,fp)621 getword(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 
getnum(fp)682 getnum(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 
getnonblank(fp)735 getnonblank(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  */
makename(name,origin)770 makename(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 
endline(fp)798 endline(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 
getprotocol(fp,src)813 getprotocol(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 
829 int
getservices(n,data,fp,src)830 getservices(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 
get_sort_list(fp)894 get_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 
free_sort_list()958 free_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 }
969