|
|
1.1 root 1: /*
2: * Copyright (c) 1986, 1989, 1990 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1986, 1989, 1990 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)ns_main.c 4.50 (Berkeley) 6/29/90";
28: #endif /* not lint */
29:
30: /*
31: * Internet Name server (see rfc883 & others).
32: */
33:
34: #include <sys/param.h>
35: #if defined(SYSV)
36: #include <fcntl.h>
37: #endif SYSV
38: #include <sys/file.h>
39: #include <sys/time.h>
40: #if !defined(SYSV)
41: #include <sys/wait.h>
42: #endif !SYSV
43: #include <sys/resource.h>
44: #include <sys/ioctl.h>
45: #include <sys/socket.h>
46: #include <netinet/in.h>
47: #include <net/if.h>
48: #include <stdio.h>
49: #include <syslog.h>
50: #include <errno.h>
51: #include <signal.h>
52: #include <netdb.h>
53: #include <arpa/nameser.h>
54: #include <arpa/inet.h>
55: #include <resolv.h>
56: #undef nsaddr /* XXX */
57: #include "ns.h"
58: #include "db.h"
59: #include "pathnames.h"
60:
61: #ifdef BOOTFILE /* default boot file */
62: char *bootfile = BOOTFILE;
63: #else
64: char *bootfile = _PATH_BOOT;
65: #endif
66:
67: #ifdef DEBUGFILE /* default debug output file */
68: char *debugfile = DEBUGFILE;
69: #else
70: char *debugfile = _PATH_DEBUG;
71: #endif
72:
73: #ifdef PIDFILE /* file to store current named PID */
74: char *PidFile = PIDFILE;
75: #else
76: char *PidFile = _PATH_PIDFILE;
77: #endif
78:
79: #ifndef FD_SET
80: #define NFDBITS 32
81: #define FD_SETSIZE 32
82: #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
83: #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
84: #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
85: #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
86: #endif
87:
88: FILE *fp; /* file descriptor for pid file */
89:
90: #ifdef DEBUG
91: FILE *ddt;
92: #endif
93:
94: int debug = 0; /* debugging flag */
95: int ds; /* datagram socket */
96: int needreload = 0; /* received SIGHUP, need to reload db */
97: int needmaint = 0; /* need to call ns_maint()*/
98: int needzoneload = 0; /* need to reload secondary zone(s) */
99: int needToDoadump = 0; /* need to dump database */
100: int needToChkpt = 0; /* need to checkpoint cache */
101: int needStatsDump = 0; /* need to dump statistics */
102: #ifdef ALLOW_UPDATES
103: int needToExit = 0; /* need to exit (may need to doadump
104: * first, if database has changed since
105: * it was last dumped/booted). Gets
106: * set by shutdown signal handler
107: * (onintr)
108: */
109: #endif ALLOW_UPDATES
110:
111: int priming = 0; /* is cache being primed */
112:
113: #ifdef SO_RCVBUF
114: int rbufsize = 8 * 1024; /* UDP recive buffer size */
115: #endif
116:
117: struct qstream *streamq = QSTREAM_NULL; /* list of open streams */
118: struct qdatagram *datagramq = QDATAGRAM_NULL; /* list of datagram interfaces */
119: struct sockaddr_in nsaddr;
120: struct timeval tt;
121: /*
122: * We keep a list of favored networks headed by nettab.
123: * There are three (possibly empty) parts to this list, in this order:
124: * 1. directly attached (sub)nets.
125: * 2. logical networks for directly attached subnetted networks.
126: * 3. networks from the sort list.
127: * The value (*elocal) points at the first entry in the second part of the list,
128: * if any, while (*enettab) points at the first entry in the sort list.
129: */
130: struct netinfo *nettab = NULL;
131: struct netinfo **elocal = &nettab;
132: struct netinfo **enettab = &nettab;
133: struct netinfo netloop;
134: struct netinfo *findnetinfo();
135: u_long net_mask();
136: u_short ns_port;
137: struct sockaddr_in from_addr; /* Source addr of last packet */
138: int from_len; /* Source addr size of last packet */
139: time_t boottime, resettime; /* Used by ns_stats */
140: static fd_set mask; /* select mask of open descriptors */
141: static int vs; /* listening TCP socket */
142:
143: char **Argv = NULL; /* pointer to argument vector */
144: char *LastArg = NULL; /* end of argv */
145:
146: extern int errno;
147:
148: #if defined(SYSV)
149: getdtablesize()
150: {
151: return(FD_SETSIZE);
152: }
153: #endif SYSV
154:
155: main(argc, argv, envp)
156: int argc;
157: char *argv[], *envp[];
158: {
159: register int n, udpcnt;
160: register char *arg;
161: register struct qstream *sp;
162: register struct qdatagram *dqp;
163: struct qstream *nextsp;
164: int nfds;
165: int on = 1;
166: int rfd, size;
167: u_long lasttime, maxctime;
168: char buf[BUFSIZ];
169: #ifndef SYSV
170: struct sigvec vec;
171: #endif
172:
173: fd_set tmpmask;
174:
175: struct timeval t, *tp;
176: struct qstream *candidate = QSTREAM_NULL;
177: extern VOID onintr(), maint_alarm(), endxfer();
178: extern VOID setdumpflg(), onhup();
179: extern VOID setIncrDbgFlg(), setNoDbgFlg(), sigprof();
180: extern VOID setchkptflg(), setstatsflg();
181: extern int loadxfer();
182: extern struct qstream *sqadd();
183: extern struct qinfo *qhead;
184: extern char Version[];
185:
186: ns_port = htons(NAMESERVER_PORT);
187:
188: /*
189: ** Save start and extent of argv for setproctitle.
190: */
191:
192: Argv = argv;
193: if (envp == 0 || *envp == 0)
194: envp = argv;
195: while (*envp)
196: envp++;
197: LastArg = envp[-1] + strlen(envp[-1]);
198:
199: (void) umask(022);
200: while (--argc > 0) {
201: arg = *++argv;
202: if (*arg == '-') {
203: while (*++arg)
204: switch (*arg) {
205: case 'b':
206: if (--argc <= 0)
207: usage();
208: bootfile = *++argv;
209: break;
210:
211: case 'd':
212: ++argv;
213:
214: if (*argv != 0) {
215: if (**argv == '-') {
216: argv--;
217: break;
218: }
219: debug = atoi(*argv);
220: --argc;
221: }
222: if (debug <= 0)
223: debug = 1;
224: setdebug(1);
225: break;
226:
227: case 'p':
228: if (--argc <= 0)
229: usage();
230: ns_port = htons((u_short)atoi(*++argv));
231: break;
232:
233: default:
234: usage();
235: }
236: } else
237: bootfile = *argv;
238: }
239:
240: if (!debug)
241: for (n = getdtablesize() - 1; n > 2; n--)
242: (void) close(n);
243: #ifdef DEBUG
244: else {
245: fprintf(ddt,"Debug turned ON, Level %d\n",debug);
246: fprintf(ddt,"Version = %s\t",Version);
247: fprintf(ddt,"bootfile = %s\n",bootfile);
248: }
249: #endif
250:
251: #ifdef LOG_DAEMON
252: openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY, LOG_DAEMON);
253: #else
254: openlog("named", LOG_PID);
255: #endif
256:
257: /* tuck my process id away */
258: fp = fopen(PidFile, "w");
259: if (fp != NULL) {
260: fprintf(fp, "%d\n", getpid());
261: (void) fclose(fp);
262: }
263: syslog(LOG_NOTICE, "restarted\n");
264:
265: _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
266:
267: nsaddr.sin_family = AF_INET;
268: nsaddr.sin_addr.s_addr = INADDR_ANY;
269: nsaddr.sin_port = ns_port;
270:
271: /*
272: ** Open stream port.
273: */
274: if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
275: syslog(LOG_ERR, "socket(SOCK_STREAM): %m");
276: exit(1);
277: }
278: (void)setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
279: if (bind(vs, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
280: syslog(LOG_ERR, "bind(vs, %s[%d]): %m",
281: inet_ntoa(nsaddr.sin_addr), ntohs(nsaddr.sin_port));
282: exit(1);
283: }
284: (void) listen(vs, 5);
285:
286: /*
287: * Get list of local addresses and set up datagram sockets.
288: */
289: getnetconf();
290:
291: /*
292: ** Initialize and load database.
293: */
294: gettime(&tt);
295: buildservicelist();
296: buildprotolist();
297: ns_init(bootfile);
298: #ifdef DEBUG
299: if (debug) {
300: fprintf(ddt, "Network and sort list:\n");
301: printnetinfo(nettab);
302: }
303: #endif DEBUG
304:
305: time(&boottime);
306: resettime = boottime;
307:
308: (void) signal(SIGHUP, onhup);
309: #if defined(SYSV)
310: (void) signal(SIGCLD, endxfer);
311: (void) signal(SIGALRM, maint_alarm);
312: #else
313: bzero((char *)&vec, sizeof(vec));
314: vec.sv_handler = maint_alarm;
315: vec.sv_mask = sigmask(SIGCHLD);
316: (void) sigvec(SIGALRM, &vec, (struct sigvec *)NULL);
317:
318: vec.sv_handler = endxfer;
319: vec.sv_mask = sigmask(SIGALRM);
320: (void) sigvec(SIGCHLD, &vec, (struct sigvec *)NULL);
321: #endif SYSV
322: (void) signal(SIGPIPE, SIG_IGN);
323: (void) signal(SIGSYS, sigprof);
324: (void) signal(SIGINT, setdumpflg);
325: (void) signal(SIGQUIT, setchkptflg);
326: (void) signal(SIGIOT, setstatsflg);
327:
328: #ifdef ALLOW_UPDATES
329: /* Catch SIGTERM so we can dump the database upon shutdown if it
330: has changed since it was last dumped/booted */
331: (void) signal(SIGTERM, onintr);
332: #endif ALLOW_UPDATES
333:
334: #if defined(SIGUSR1) && defined(SIGUSR2)
335: (void) signal(SIGUSR1, setIncrDbgFlg);
336: (void) signal(SIGUSR2, setNoDbgFlg);
337: #else SIGUSR1&&SIGUSR2
338: (void) signal(SIGEMT, setIncrDbgFlg);
339: (void) signal(SIGFPE, setNoDbgFlg);
340: #endif SIGUSR1&&SIGUSR2
341:
342: #ifdef DEBUG
343: if (debug) {
344: fprintf(ddt,"database initialized\n");
345: }
346: #endif
347:
348: t.tv_usec = 0;
349:
350: /*
351: * Fork and go into background now that
352: * we've done any slow initialization
353: * and are ready to answer queries.
354: */
355: if (!debug) {
356: #if defined(BSD) && BSD >= 199006
357: daemon(1, 0);
358: #else
359: if (fork() > 0)
360: exit(0);
361: n = open(_PATH_DEVNULL, O_RDONLY);
362: (void) dup2(n, 0);
363: (void) dup2(n, 1);
364: (void) dup2(n, 2);
365: if (n > 2)
366: (void) close(n);
367: #ifdef SYSV
368: setpgrp();
369: #else
370: {
371: struct itimerval ival;
372:
373: /*
374: * The open below may hang on pseudo ttys if the person
375: * who starts named logs out before this point.
376: *
377: * needmaint may get set inapropriately if the open
378: * hangs, but all that will happen is we will see that
379: * no maintenance is required.
380: */
381: bzero((char *)&ival, sizeof(ival));
382: ival.it_value.tv_sec = 120;
383: (void) setitimer(ITIMER_REAL, &ival,
384: (struct itimerval *)NULL);
385: n = open(_PATH_TTY, O_RDWR);
386: ival.it_value.tv_sec = 0;
387: (void) setitimer(ITIMER_REAL, &ival,
388: (struct itimerval *)NULL);
389: if (n > 0) {
390: (void) ioctl(n, TIOCNOTTY, (char *)NULL);
391: (void) close(n);
392: }
393: }
394: #endif /* SYSV */
395: #endif /* BSD > 199006 */
396: }
397: /* tuck my process id away again */
398: fp = fopen(PidFile, "w");
399: if (fp != NULL) {
400: fprintf(fp, "%d\n", getpid());
401: (void) fclose(fp);
402: }
403:
404: #ifdef DEBUG
405: if (debug)
406: fprintf(ddt,"Ready to answer queries.\n");
407: #endif
408: prime_cache();
409: nfds = getdtablesize(); /* get the number of file descriptors */
410: if (nfds > FD_SETSIZE) {
411: nfds = FD_SETSIZE; /* Bulletproofing */
412: syslog(LOG_ERR, "Return from getdtablesize() > FD_SETSIZE");
413: #ifdef DEBUG
414: if (debug)
415: fprintf(ddt,"Return from getdtablesize() > FD_SETSIZE\n");
416: #endif
417: }
418: FD_ZERO(&mask);
419: FD_SET(vs, &mask);
420: for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next)
421: FD_SET(dqp->dq_dfd, &mask);
422: for (;;) {
423: #ifdef DEBUG
424: if (ddt && debug == 0) {
425: fprintf(ddt,"Debug turned OFF\n");
426: (void) fclose(ddt);
427: ddt = 0;
428: }
429: #endif
430: #ifdef ALLOW_UPDATES
431: if (needToExit) {
432: struct zoneinfo *zp;
433: sigblock(~0); /*
434: * Block all blockable signals
435: * to ensure a consistant
436: * state during final dump
437: */
438: #ifdef DEBUG
439: if (debug)
440: fprintf(ddt, "Received shutdown signal\n");
441: #endif DEBUG
442: for (zp = zones; zp < &zones[nzones]; zp++) {
443: if (zp->hasChanged)
444: zonedump(zp);
445: }
446: exit(0);
447: }
448: #endif ALLOW_UPDATES
449: if (needreload) {
450: needreload = 0;
451: db_reload();
452: }
453: #ifdef STATS
454: if (needStatsDump) {
455: needStatsDump = 0;
456: ns_stats();
457: }
458: #endif STATS
459: if (needzoneload) {
460: needzoneload = 0;
461: loadxfer();
462: }
463: if (needmaint) {
464: needmaint = 0;
465: ns_maint();
466: }
467: if(needToChkpt) {
468: needToChkpt = 0;
469: doachkpt();
470: }
471: if(needToDoadump) {
472: needToDoadump = 0;
473: doadump();
474: }
475: /*
476: ** Wait until a query arrives
477: */
478: if (retryqp != NULL) {
479: gettime(&tt);
480: t.tv_sec = (long) retryqp->q_time - tt.tv_sec;
481: if (t.tv_sec <= 0) {
482: retry(retryqp);
483: continue;
484: }
485: tp = &t;
486: } else
487: tp = NULL;
488: tmpmask = mask;
489: n = select(nfds, &tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp);
490: if (n < 0) {
491: if (errno == EINTR)
492: continue;
493: syslog(LOG_ERR, "select: %m");
494: #ifdef DEBUG
495: if (debug)
496: fprintf(ddt,"select error\n");
497: #endif
498: ;
499: }
500: if (n == 0)
501: continue;
502:
503: for (dqp = datagramq; dqp != QDATAGRAM_NULL;
504: dqp = dqp->dq_next) {
505: if (FD_ISSET(dqp->dq_dfd, &tmpmask))
506: for(udpcnt = 0; udpcnt < 25; udpcnt++) {
507: from_len = sizeof(from_addr);
508: if ((n = recvfrom(dqp->dq_dfd, buf, sizeof(buf), 0,
509: (struct sockaddr *)&from_addr, &from_len)) < 0)
510: {
511: if ((n == -1) && (errno == EWOULDBLOCK))
512: break;
513: syslog(LOG_WARNING, "recvfrom: %m");
514: break;
515: }
516: #ifdef STATS
517: stats[S_INPKTS].cnt++;
518: #endif
519: #ifdef DEBUG
520: if (debug)
521: fprintf(ddt,
522: "\ndatagram from %s port %d, fd %d, len %d\n",
523: inet_ntoa(from_addr.sin_addr),
524: ntohs(from_addr.sin_port), dqp->dq_dfd, n);
525: if (debug >= 10)
526: fp_query(buf, ddt);
527: #endif
528: /*
529: * Consult database to get the answer.
530: */
531: gettime(&tt);
532: ns_req(buf, n, PACKETSZ, QSTREAM_NULL, &from_addr,
533: dqp->dq_dfd);
534: }
535: }
536: /*
537: ** Process stream connection
538: */
539: if (FD_ISSET(vs, &tmpmask)) {
540: from_len = sizeof(from_addr);
541: rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
542: gettime(&tt);
543: if (rfd < 0 && errno == EMFILE && streamq != NULL) {
544: maxctime = 0;
545: candidate = QSTREAM_NULL;
546: for (sp = streamq; sp != QSTREAM_NULL;
547: sp = nextsp) {
548: nextsp = sp->s_next;
549: if (sp->s_refcnt != 0)
550: continue;
551: lasttime = tt.tv_sec - sp->s_time;
552: if (lasttime >= 900)
553: sqrm(sp);
554: else if (lasttime > maxctime) {
555: candidate = sp;
556: maxctime = lasttime;
557: }
558: }
559: rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
560: if ((rfd < 0) && (errno == EMFILE) &&
561: candidate != QSTREAM_NULL) {
562: sqrm(candidate);
563: rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
564: }
565: }
566: if (rfd < 0) {
567: syslog(LOG_WARNING, "accept: %m");
568: continue;
569: }
570: (void) fcntl(rfd, F_SETFL, FNDELAY);
571: (void) setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE,
572: (char *)&on, sizeof(on));
573: if ((sp = sqadd()) == QSTREAM_NULL) {
574: (void) close(rfd);
575: continue;
576: }
577: sp->s_rfd = rfd; /* stream file descriptor */
578: sp->s_size = -1; /* amount of data to receive */
579: gettime(&tt);
580: sp->s_time = tt.tv_sec; /* last transaction time */
581: sp->s_from = from_addr; /* address to respond to */
582: sp->s_bufp = (char *)&sp->s_tempsize;
583: FD_SET(rfd, &mask);
584: FD_SET(rfd, &tmpmask);
585: #ifdef DEBUG
586: if (debug) {
587: fprintf(ddt,
588: "\nTCP connection from %s port %d (fd %d)\n",
589: inet_ntoa(sp->s_from.sin_addr),
590: ntohs(sp->s_from.sin_port), rfd);
591: }
592: #endif
593: }
594: #ifdef DEBUG
595: if (debug > 2 && streamq)
596: fprintf(ddt,"streamq = x%x\n",streamq);
597: #endif
598: if (streamq != NULL) {
599: for (sp = streamq; sp != QSTREAM_NULL; sp = nextsp) {
600: nextsp = sp->s_next;
601: if (FD_ISSET(sp->s_rfd, &tmpmask)) {
602: #ifdef DEBUG
603: if (debug > 5) {
604: fprintf(ddt,
605: "sp x%x rfd %d size %d time %d ",
606: sp, sp->s_rfd, sp->s_size,
607: sp->s_time );
608: fprintf(ddt," next x%x \n", sp->s_next );
609: fprintf(ddt,"\tbufsize %d",sp->s_bufsize);
610: fprintf(ddt," buf x%x ",sp->s_buf);
611: fprintf(ddt," bufp x%x\n",sp->s_bufp);
612: }
613: #endif DEBUG
614: if (sp->s_size < 0) {
615: size = sizeof(u_short) -
616: (sp->s_bufp - (char *)&sp->s_tempsize);
617: while (size > 0 &&
618: (n = read(sp->s_rfd, sp->s_bufp, size)) > 0){
619: sp->s_bufp += n;
620: size -= n;
621: }
622: if ((n == -1) && (errno == EWOULDBLOCK))
623: continue;
624: if (n <= 0) {
625: sqrm(sp);
626: continue;
627: }
628: if ((sp->s_bufp - (char *)&sp->s_tempsize) ==
629: sizeof(u_short)) {
630: sp->s_size = htons(sp->s_tempsize);
631: if (sp->s_bufsize == 0) {
632: if ( (sp->s_buf = malloc(BUFSIZ))
633: == NULL) {
634: sp->s_buf = buf;
635: sp->s_size = sizeof(buf);
636: } else {
637: sp->s_bufsize = BUFSIZ;
638: }
639: }
640: if (sp->s_size > sp->s_bufsize &&
641: sp->s_bufsize != 0) {
642: if ((sp->s_buf = realloc(
643: (char *)sp->s_buf,
644: (unsigned)sp->s_size)) == NULL){
645: sp->s_buf = buf;
646: sp->s_bufsize = 0;
647: sp->s_size = sizeof(buf);
648: } else {
649: sp->s_bufsize = sp->s_size;
650: }
651: }
652: sp->s_bufp = sp->s_buf;
653: }
654: }
655: gettime(&tt);
656: sp->s_time = tt.tv_sec;
657: while (sp->s_size > 0 &&
658: (n = read(sp->s_rfd, sp->s_bufp, sp->s_size)) > 0)
659: {
660: sp->s_bufp += n;
661: sp->s_size -= n;
662: }
663: /*
664: * we don't have enough memory for the query.
665: * if we have a query id, then we will send an
666: * error back to the user.
667: */
668: if (sp->s_bufsize == 0 &&
669: (sp->s_bufp - sp->s_buf > sizeof(u_short))) {
670: HEADER *hp;
671:
672: hp = (HEADER *)sp->s_buf;
673: hp->qr = 1;
674: hp->ra = 1;
675: hp->ancount = 0;
676: hp->qdcount = 0;
677: hp->nscount = 0;
678: hp->arcount = 0;
679: hp->rcode = SERVFAIL;
680: (void) writemsg(sp->s_rfd, sp->s_buf,
681: sizeof(HEADER));
682: continue;
683: }
684: if ((n == -1) && (errno == EWOULDBLOCK))
685: continue;
686: if (n <= 0) {
687: sqrm(sp);
688: continue;
689: }
690: /*
691: * Consult database to get the answer.
692: */
693: if (sp->s_size == 0) {
694: sq_query(sp);
695: ns_req(sp->s_buf,
696: sp->s_bufp - sp->s_buf,
697: sp->s_bufsize, sp,
698: &sp->s_from, -1);
699: sp->s_bufp = (char *)&sp->s_tempsize;
700: sp->s_size = -1;
701: continue;
702: }
703: }
704: }
705: }
706: }
707: /* NOTREACHED */
708: }
709:
710: usage()
711: {
712: fprintf(stderr, "Usage: named [-d #] [-p port] [{-b} bootfile]\n");
713: exit(1);
714: }
715:
716: getnetconf()
717: {
718: register struct netinfo *ntp;
719: struct netinfo *ontp;
720: struct ifconf ifc;
721: struct ifreq ifreq, *ifr;
722: struct qdatagram *dqp;
723: static int first = 1;
724: char buf[BUFSIZ], *cp, *cplim;
725: u_long nm;
726:
727: ifc.ifc_len = sizeof(buf);
728: ifc.ifc_buf = buf;
729: if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
730: syslog(LOG_ERR, "get interface configuration: %m");
731: exit(1);
732: }
733: ntp = NULL;
734: #ifdef AF_LINK
735: #define max(a, b) (a > b ? a : b)
736: #define size(p) max((p).sa_len, sizeof(p))
737: #else
738: #define size(p) (sizeof (p))
739: #endif
740: cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
741: for (cp = buf; cp < cplim;
742: cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
743: #undef size
744: ifr = (struct ifreq *)cp;
745: if (ifr->ifr_addr.sa_family != AF_INET)
746: continue;
747: ifreq = *ifr;
748: /*
749: * Don't test IFF_UP, packets may still be received at this
750: * address if any other interface is up.
751: */
752: if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
753: syslog(LOG_ERR, "get interface addr: %m");
754: continue;
755: }
756: /* build datagram queue */
757: /*
758: * look for an already existing source interface address.
759: * This happens mostly when reinitializing. Also, if
760: * the machine has multiple point to point interfaces, then
761: * the local address may appear more than once.
762: */
763: for (dqp=datagramq; dqp != NULL; dqp = dqp->dq_next)
764: if (((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr
765: == dqp->dq_addr.s_addr) {
766: #ifdef DEBUG
767: if (debug)
768: fprintf(ddt, "dup interface address %s on %s\n",
769: inet_ntoa(dqp->dq_addr), ifreq.ifr_name);
770: #endif
771: break;
772: }
773: if (dqp != NULL)
774: continue;
775:
776: if ((dqp = (struct qdatagram *)calloc(1,
777: sizeof(struct qdatagram))) == NULL) {
778: #ifdef DEBUG
779: if (debug >= 5)
780: fprintf(ddt,"getnetconf: malloc error\n");
781: #endif
782: syslog(LOG_ERR, "getnetconf: Out Of Memory");
783: exit(12);
784: }
785: dqp->dq_next = datagramq;
786: datagramq = dqp;
787: dqp->dq_addr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
788: opensocket(dqp);
789:
790: /*
791: * Add interface to list of directly-attached (sub)nets
792: * for use in sorting addresses.
793: */
794: if (ntp == NULL)
795: ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
796: ntp->my_addr =
797: ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
798: #ifdef SIOCGIFNETMASK
799: if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
800: syslog(LOG_ERR, "get netmask: %m");
801: ntp->mask = net_mask(ntp->my_addr);
802: } else
803: ntp->mask = ((struct sockaddr_in *)
804: &ifreq.ifr_addr)->sin_addr.s_addr;
805: #else
806: /* 4.2 does not support subnets */
807: ntp->mask = net_mask(ntp->my_addr);
808: #endif
809: if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
810: syslog(LOG_ERR, "get interface flags: %m");
811: continue;
812: }
813: #ifdef IFF_LOOPBACK
814: if (ifreq.ifr_flags & IFF_LOOPBACK)
815: #else
816: /* test against 127.0.0.1 (yuck!!) */
817: if (ntp->my_addr.s_addr == htonl(0x7F000001))
818: #endif
819: {
820: if (netloop.my_addr.s_addr == 0) {
821: netloop.my_addr = ntp->my_addr;
822: netloop.mask = 0xffffffff;
823: netloop.net = ntp->my_addr.s_addr;
824: #ifdef DEBUG
825: if (debug)
826: fprintf(ddt,"loopback address: x%lx\n",
827: netloop.my_addr.s_addr);
828: #endif DEBUG
829: }
830: continue;
831: } else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {
832: if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
833: syslog(LOG_ERR, "get dst addr: %m");
834: continue;
835: }
836: ntp->mask = 0xffffffff;
837: ntp->net = ((struct sockaddr_in *)
838: &ifreq.ifr_addr)->sin_addr.s_addr;
839: } else {
840: ntp->net = ntp->mask & ntp->my_addr.s_addr;
841: }
842: /*
843: * Place on end of list of locally-attached (sub)nets,
844: * but before logical nets for subnetted nets.
845: */
846: ntp->next = *elocal;
847: *elocal = ntp;
848: if (elocal == enettab)
849: enettab = &ntp->next;
850: elocal = &ntp->next;
851: ntp = NULL;
852: }
853: if (ntp)
854: (void) free((char *)ntp);
855:
856: /*
857: * Create separate qdatagram structure for socket
858: * wildcard address.
859: */
860: if (first) {
861: if ((dqp = (struct qdatagram *)calloc(1, sizeof(*dqp))) == NULL) {
862: #ifdef DEBUG
863: if (debug >= 5)
864: fprintf(ddt,"getnetconf: malloc error\n");
865: #endif
866: syslog(LOG_ERR, "getnetconf: Out Of Memory");
867: exit(12);
868: }
869: dqp->dq_next = datagramq;
870: datagramq = dqp;
871: dqp->dq_addr.s_addr = INADDR_ANY;
872: opensocket(dqp);
873: ds = dqp->dq_dfd; /* used externally */
874: }
875:
876: /*
877: * Compute logical networks to which we're connected
878: * based on attached subnets;
879: * used for sorting based on network configuration.
880: */
881: for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
882: nm = net_mask(ntp->my_addr);
883: if (nm != ntp->mask) {
884: if (findnetinfo(ntp->my_addr))
885: continue;
886: ontp = (struct netinfo *)malloc(sizeof(struct netinfo));
887: if (ontp == NULL) {
888: #ifdef DEBUG
889: if (debug >= 5)
890: fprintf(ddt,"getnetconf: malloc error\n");
891: #endif
892: syslog(LOG_ERR, "getnetconf: Out Of Memory");
893: exit(12);
894: }
895: ontp->my_addr = ntp->my_addr;
896: ontp->mask = nm;
897: ontp->net = ontp->my_addr.s_addr & nm;
898: ontp->next = *enettab;
899: *enettab = ontp;
900: enettab = &ontp->next;
901: }
902: }
903: first = 0;
904: }
905:
906: /*
907: * Find netinfo structure for logical network implied by address "addr",
908: * if it's on list of local/favored networks.
909: */
910: struct netinfo *
911: findnetinfo(addr)
912: struct in_addr addr;
913: {
914: register struct netinfo *ntp;
915: u_long net, mask;
916:
917: mask = net_mask(addr);
918: net = addr.s_addr & mask;
919: for (ntp = nettab; ntp != NULL; ntp = ntp->next)
920: if (ntp->net == net && ntp->mask == mask)
921: return (ntp);
922: return ((struct netinfo *) NULL);
923: }
924:
925: #ifdef DEBUG
926: printnetinfo(ntp)
927: register struct netinfo *ntp;
928: {
929: for ( ; ntp != NULL; ntp = ntp->next) {
930: fprintf(ddt,"net x%lx mask x%lx", ntp->net, ntp->mask);
931: fprintf(ddt," my_addr x%lx", ntp->my_addr.s_addr);
932: fprintf(ddt," %s\n", inet_ntoa(ntp->my_addr));
933: }
934: }
935: #endif
936:
937: opensocket(dqp)
938: register struct qdatagram *dqp;
939: {
940: int on = 1;
941:
942: /*
943: * Open datagram sockets bound to interface address.
944: */
945: if ((dqp->dq_dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
946: syslog(LOG_ERR, "socket(SOCK_DGRAM): %m");
947: exit(1);
948: }
949: #ifdef DEBUG
950: if (debug)
951: fprintf(ddt,"dqp->dq_addr %s d_dfd %d\n",
952: inet_ntoa(dqp->dq_addr), dqp->dq_dfd);
953: #endif DEBUG
954: (void)setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
955: (char *)&on, sizeof(on));
956: #ifdef SO_RCVBUF
957: (void)setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF,
958: (char *)&rbufsize, sizeof(rbufsize));
959: #endif SO_RCVBUF
960: (void) fcntl(dqp->dq_dfd, F_SETFL, FNDELAY);
961: /*
962: * NOTE: Some versions of SunOS have problems with the following
963: * call to bind. Bind still seems to function on these systems
964: * if you comment out the exit inside the if. This may cause
965: * Suns with multiple interfaces to reply strangely.
966: */
967: nsaddr.sin_addr = dqp->dq_addr;
968: if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
969: syslog(LOG_ERR, "bind(dfd %d, %s[%d]): %m",
970: dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr),
971: ntohs(nsaddr.sin_port));
972: #if !defined(sun)
973: exit(1);
974: #endif
975: }
976: }
977:
978: /*
979: ** Set flag saying to reload database upon receiving SIGHUP.
980: ** Must make sure that someone isn't walking through a data
981: ** structure at the time.
982: */
983:
984: VOID
985: onhup()
986: {
987: #if defined(SYSV)
988: (void)signal(SIGHUP, onhup);
989: #endif SYSV
990: needreload = 1;
991: }
992:
993: /*
994: ** Set flag saying to call ns_maint()
995: ** Must make sure that someone isn't walking through a data
996: ** structure at the time.
997: */
998:
999: VOID
1000: maint_alarm()
1001: {
1002: #if defined(SYSV)
1003: (void)signal(SIGALRM, maint_alarm);
1004: #endif SYSV
1005: needmaint = 1;
1006: }
1007:
1008:
1009: #ifdef ALLOW_UPDATES
1010: /*
1011: * Signal handler to schedule shutdown. Just set flag, to ensure a consistent
1012: * state during dump.
1013: */
1014: VOID
1015: onintr()
1016: {
1017: needToExit = 1;
1018: }
1019: #endif ALLOW_UPDATES
1020:
1021: /*
1022: * Signal handler to schedule a data base dump. Do this instead of dumping the
1023: * data base immediately, to avoid seeing it in a possibly inconsistent state
1024: * (due to updates), and to avoid long disk I/O delays at signal-handler
1025: * level
1026: */
1027: VOID
1028: setdumpflg()
1029: {
1030: #if defined(SYSV)
1031: (void)signal(SIGINT, setdumpflg);
1032: #endif SYSV
1033: needToDoadump = 1;
1034: }
1035:
1036: /*
1037: ** Turn on or off debuging by open or closeing the debug file
1038: */
1039:
1040: setdebug(code)
1041: int code;
1042: {
1043: #if defined(lint) && !defined(DEBUG)
1044: code = code;
1045: #endif
1046: #ifdef DEBUG
1047:
1048: if (code) {
1049: ddt = freopen(debugfile, "w+", stderr);
1050: if ( ddt == NULL) {
1051: syslog(LOG_WARNING, "can't open debug file %s: %m",
1052: debugfile);
1053: debug = 0;
1054: } else {
1055: #if defined(SYSV)
1056: setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
1057: #else
1058: setlinebuf(ddt);
1059: #endif
1060: (void) fcntl(fileno(ddt), F_SETFL, FAPPEND);
1061: }
1062: } else
1063: debug = 0;
1064: /* delay closing ddt, we might interrupt someone */
1065: #endif
1066: }
1067:
1068: /*
1069: ** Catch a special signal and set debug level.
1070: **
1071: ** If debuging is off then turn on debuging else increment the level.
1072: **
1073: ** Handy for looking in on long running name servers.
1074: */
1075:
1076: VOID
1077: setIncrDbgFlg()
1078: {
1079: #if defined(SYSV)
1080: (void)signal(SIGUSR1, setIncrDbgFlg);
1081: #endif SYSV
1082: #ifdef DEBUG
1083: if (debug == 0) {
1084: debug++;
1085: setdebug(1);
1086: }
1087: else {
1088: debug++;
1089: }
1090: fprintf(ddt,"Debug turned ON, Level %d\n",debug);
1091: #endif
1092: }
1093:
1094: /*
1095: ** Catch a special signal to turn off debugging
1096: */
1097:
1098: VOID
1099: setNoDbgFlg()
1100: {
1101: #if defined(SYSV)
1102: (void)signal(SIGUSR2, setNoDbgFlg);
1103: #endif SYSV
1104: setdebug(0);
1105: }
1106:
1107: /*
1108: ** Set flag for statistics dump
1109: */
1110: VOID
1111: setstatsflg()
1112: {
1113: #if defined(SYSV)
1114: (void)signal(SIGIOT, setstatsflg);
1115: #endif SYSV
1116: needStatsDump = 1;
1117: }
1118:
1119: VOID
1120: setchkptflg()
1121: {
1122: #if defined(SYSV)
1123: (void)signal(SIGQUIT, setchkptflg);
1124: #endif SYSV
1125: needToChkpt = 1;
1126: }
1127:
1128: /*
1129: ** Catch a special signal SIGSYS
1130: **
1131: ** this is setup to fork and exit to drop to /usr/tmp/gmon.out
1132: ** and keep the server running
1133: */
1134:
1135: VOID
1136: sigprof()
1137: {
1138: #if defined(SYSV)
1139: (void)signal(SIGSYS, sigprof);
1140: #endif SYSV
1141: #ifdef DEBUG
1142: if (debug)
1143: fprintf(ddt,"sigprof()\n");
1144: #endif
1145: if ( fork() == 0)
1146: {
1147: (void) chdir(_PATH_TMPDIR);
1148: exit(1);
1149: }
1150: }
1151:
1152: /*
1153: ** Routines for managing stream queue
1154: */
1155:
1156: struct qstream *
1157: sqadd()
1158: {
1159: register struct qstream *sqp;
1160:
1161: if ((sqp = (struct qstream *)calloc(1, sizeof(struct qstream)))
1162: == NULL ) {
1163: #ifdef DEBUG
1164: if (debug >= 5)
1165: fprintf(ddt,"sqadd: malloc error\n");
1166: #endif
1167: syslog(LOG_ERR, "sqadd: Out Of Memory");
1168: return(QSTREAM_NULL);
1169: }
1170: #ifdef DEBUG
1171: if (debug > 3)
1172: fprintf(ddt,"sqadd(x%x)\n", sqp);
1173: #endif
1174:
1175: sqp->s_next = streamq;
1176: streamq = sqp;
1177: return(sqp);
1178: }
1179:
1180: /*
1181: * Remove stream queue structure.
1182: * No current queries may refer to this stream when it is removed.
1183: */
1184: sqrm(qp)
1185: register struct qstream *qp;
1186: {
1187: register struct qstream *qsp;
1188:
1189: #ifdef DEBUG
1190: if (debug > 1) {
1191: fprintf(ddt,"sqrm(%#x, %d ) rfcnt=%d\n",
1192: qp, qp->s_rfd, qp->s_refcnt);
1193: }
1194: #endif
1195:
1196: if (qp->s_bufsize != 0)
1197: (void) free(qp->s_buf);
1198: FD_CLR(qp->s_rfd, &mask);
1199: (void) close(qp->s_rfd);
1200: if (qp == streamq) {
1201: streamq = qp->s_next;
1202: } else {
1203: for (qsp = streamq; qsp->s_next != qp; qsp = qsp->s_next)
1204: ;
1205: qsp->s_next = qp->s_next;
1206: }
1207: (void)free((char *)qp);
1208: }
1209:
1210: sqflush()
1211: {
1212: register struct qstream *sp, *spnext;
1213:
1214: for (sp = streamq; sp != QSTREAM_NULL; sp = spnext) {
1215: spnext = sp->s_next;
1216: sqrm(sp);
1217: }
1218: }
1219:
1220: /*
1221: * Initiate query on stream;
1222: * mark as referenced and stop selecting for input.
1223: */
1224: sq_query(sp)
1225: register struct qstream *sp;
1226: {
1227: sp->s_refcnt++;
1228: FD_CLR(sp->s_rfd, &mask);
1229: }
1230:
1231: /*
1232: * Note that the current request on a stream has completed,
1233: * and that we should continue looking for requests on the stream.
1234: */
1235: sq_done(sp)
1236: register struct qstream *sp;
1237: {
1238:
1239: sp->s_refcnt = 0;
1240: sp->s_time = tt.tv_sec;
1241: FD_SET(sp->s_rfd, &mask);
1242: }
1243:
1244: setproctitle(a, s)
1245: char *a;
1246: int s;
1247: {
1248: int size;
1249: register char *cp;
1250: struct sockaddr_in sin;
1251: char buf[80];
1252:
1253: cp = Argv[0];
1254: size = sizeof(sin);
1255: if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1256: (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
1257: else {
1258: syslog(LOG_DEBUG, "getpeername: %m");
1259: (void) sprintf(buf, "-%s", a);
1260: }
1261: (void) strncpy(cp, buf, LastArg - cp);
1262: cp += strlen(cp);
1263: while (cp < LastArg)
1264: *cp++ = ' ';
1265: }
1266:
1267: u_long
1268: net_mask(in)
1269: struct in_addr in;
1270: {
1271: register u_long i = ntohl(in.s_addr);
1272:
1273: if (IN_CLASSA(i))
1274: return (htonl(IN_CLASSA_NET));
1275: else if (IN_CLASSB(i))
1276: return (htonl(IN_CLASSB_NET));
1277: else
1278: return (htonl(IN_CLASSC_NET));
1279: }
1280:
1281: gettime(ttp)
1282: struct timeval *ttp;
1283: {
1284: if (gettimeofday(ttp, (struct timezone *)0) < 0)
1285: syslog(LOG_ERR, "gettimeofday failed: %m");
1286: return;
1287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.