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