📄 ns_main.c
字号:
syslog(LOG_NOTICE, "Ready to answer queries.\n"); prime_cache(); nfds = getdtablesize(); /* get the number of file descriptors */ if (nfds > FD_SETSIZE) { nfds = FD_SETSIZE; /* Bulletproofing */ syslog(LOG_ERR, "Return from getdtablesize() > FD_SETSIZE");#ifdef DEBUG if (debug) fprintf(ddt,"Return from getdtablesize() > FD_SETSIZE\n");#endif } FD_ZERO(&mask); FD_SET(vs, &mask); for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next) FD_SET(dqp->dq_dfd, &mask); for (;;) {#ifdef DEBUG if (ddt && debug == 0) { fprintf(ddt,"Debug turned OFF\n"); (void) my_fclose(ddt); ddt = 0; }#endif#ifdef ALLOW_UPDATES if (needToExit) { struct zoneinfo *zp; sigblock(~0); /* * Block all blockable signals * to ensure a consistant * state during final dump */#ifdef DEBUG if (debug) fprintf(ddt, "Received shutdown signal\n"); #endif for (zp = zones; zp < &zones[nzones]; zp++) { if (zp->z_state & Z_CHANGED) zonedump(zp); } exit(0); }#endif /* ALLOW_UPDATES */ if (needreload) { needreload = 0; db_reload(); } if (needStatsDump) { needStatsDump = 0; ns_stats(); } if (needzoneload) { needzoneload = 0; loadxfer(); } if (needmaint) { needmaint = 0; ns_maint(); } if(needToChkpt) { needToChkpt = 0; doachkpt(); } if(needToDoadump) { needToDoadump = 0; doadump(); } /* ** Wait until a query arrives */ if (retryqp != NULL) { gettime(&tt); /* ** The tv_sec field might be unsigned ** and thus cannot be negative. */ if ((int32_t) retryqp->q_time <= tt.tv_sec) { retry(retryqp); continue; } t.tv_sec = (int32_t) retryqp->q_time - tt.tv_sec; tp = &t; } else tp = NULL; tmpmask = mask; n = select(nfds, &tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp); if (n < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "select: %m");#ifdef DEBUG if (debug) fprintf(ddt,"select error\n");#endif ; } if (n == 0) continue; for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next) { if (FD_ISSET(dqp->dq_dfd, &tmpmask)) for(udpcnt = 0; udpcnt < 25; udpcnt++) { from_len = sizeof(from_addr); if ((n = recvfrom(dqp->dq_dfd, buf, sizeof(buf), 0, (struct sockaddr *)&from_addr, &from_len)) < 0) { if ((n < 0) && (errno == PORT_WOULDBLK)) break; syslog(LOG_WARNING, "recvfrom: %m"); break; } if (n == 0) break; stats[S_INPKTS].cnt++; gettime(&tt); dprintf(1, (ddt, "\ndatagram from [%s].%d, fd %d, len %d; now %s", inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port), dqp->dq_dfd, n, ctime(&tt.tv_sec)));#ifdef DEBUG if (debug >= 10) fp_query((char *)buf, ddt);#endif /* * Consult database to get the answer. */ gettime(&tt); ns_req(buf, n, PACKETSZ, QSTREAM_NULL, &from_addr, dqp->dq_dfd); } } /* ** Process stream connection */ if (FD_ISSET(vs, &tmpmask)) { from_len = sizeof(from_addr); rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len); gettime(&tt); if (rfd < 0 && errno == EMFILE && streamq != NULL) { maxctime = 0; candidate = QSTREAM_NULL; for (sp = streamq; sp != QSTREAM_NULL; sp = nextsp) { nextsp = sp->s_next; if (sp->s_refcnt != 0) continue; lasttime = tt.tv_sec - sp->s_time; if (lasttime >= 900) sqrm(sp); else if (lasttime > maxctime) { candidate = sp; maxctime = lasttime; } } rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len); if ((rfd < 0) && (errno == EMFILE) && candidate != QSTREAM_NULL) { sqrm(candidate); rfd = accept(vs, (struct sockaddr *) &from_addr, &from_len); } } if (rfd < 0) { syslog(LOG_WARNING, "accept: %m"); continue; } if ((n = fcntl(rfd, F_GETFL, 0)) < 0) { syslog(LOG_ERR, "fcntl(rfd, F_GETFL): %m"); (void) my_close(rfd); continue; } if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) != 0) { syslog(LOG_ERR, "fcntl(rfd, non-blocking): %m"); (void) my_close(rfd); continue; } if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) != 0) { syslog(LOG_ERR, "setsockopt(rfd, keepalive): %m"); (void) my_close(rfd); continue; } if ((sp = sqadd()) == QSTREAM_NULL) { (void) my_close(rfd); continue; } sp->s_rfd = rfd; /* stream file descriptor */ sp->s_size = -1; /* amount of data to receive */ gettime(&tt); sp->s_time = tt.tv_sec; /* last transaction time */ sp->s_from = from_addr; /* address to respond to */ sp->s_bufp = (u_char *)&sp->s_tempsize; FD_SET(rfd, &mask); FD_SET(rfd, &tmpmask); dprintf(1, (ddt, "\nTCP connection from [%s].%d (fd %d)\n", inet_ntoa(sp->s_from.sin_addr), ntohs(sp->s_from.sin_port), rfd)); } if (streamq) { dprintf(3, (ddt, "streamq = x%x\n",streamq)); } for (sp = streamq; sp != QSTREAM_NULL; sp = nextsp) { nextsp = sp->s_next; if (!FD_ISSET(sp->s_rfd, &tmpmask)) continue; dprintf(5, (ddt, "sp x%x rfd %d size %d time %d next x%x\n", sp, sp->s_rfd, sp->s_size, sp->s_time, sp->s_next)); dprintf(5, (ddt, "\tbufsize %d buf x%x bufp x%x\n", sp->s_bufsize, sp->s_buf, sp->s_bufp)); if (sp->s_size < 0) { size = sizeof(u_int16_t) - (sp->s_bufp - (u_char *)&sp->s_tempsize); while (size > 0 && (n = read(sp->s_rfd, sp->s_bufp, size)) > 0 ) { sp->s_bufp += n; size -= n; } if ((n < 0) && (errno == PORT_WOULDBLK)) continue; if (n <= 0) { sqrm(sp); continue; } if ((sp->s_bufp - (u_char *)&sp->s_tempsize) == sizeof(u_int16_t)) { sp->s_size = htons(sp->s_tempsize); if (sp->s_bufsize == 0) { if ( (sp->s_buf = (u_char *) malloc(BUFSIZ)) == NULL) { sp->s_buf = buf; sp->s_size = sizeof(buf); } else { sp->s_bufsize = BUFSIZ; } } if (sp->s_size > sp->s_bufsize && sp->s_bufsize != 0 ) { sp->s_buf = (u_char *) realloc((char *)sp->s_buf, (unsigned)sp->s_size); if (sp->s_buf == NULL) { sp->s_buf = buf; sp->s_bufsize = 0; sp->s_size = sizeof(buf); } else { sp->s_bufsize = sp->s_size; } } sp->s_bufp = sp->s_buf; } } gettime(&tt); sp->s_time = tt.tv_sec; while (sp->s_size > 0 && (n = read(sp->s_rfd, sp->s_bufp, sp->s_size) ) > 0 ) { sp->s_bufp += n; sp->s_size -= n; } /* * we don't have enough memory for the query. * if we have a query id, then we will send an * error back to the user. */ if (sp->s_bufsize == 0 && (sp->s_bufp - sp->s_buf > sizeof(u_int16_t))) { HEADER *hp; hp = (HEADER *)sp->s_buf; hp->qr = 1; hp->ra = 1; hp->ancount = 0; hp->qdcount = 0; hp->nscount = 0; hp->arcount = 0; hp->rcode = SERVFAIL; (void) writemsg(sp->s_rfd, sp->s_buf, sizeof(HEADER)); continue; } if ((n == -1) && (errno == PORT_WOULDBLK)) continue; if (n <= 0) { sqrm(sp); continue; } /* * Consult database to get the answer. */ if (sp->s_size == 0) { sq_query(sp); ns_req(sp->s_buf, sp->s_bufp - sp->s_buf, sp->s_bufsize, sp, &sp->s_from, -1); /* ns_req() can call sqrm() - check for it */ if (sq_here(sp)) { sp->s_bufp = (u_char *)&sp->s_tempsize; sp->s_size = -1; } continue; } } } /* NOTREACHED */}voidgetnetconf(){ register struct netinfo *ntp; struct netinfo *ontp; struct ifconf ifc; struct ifreq ifreq, *ifr; struct qdatagram *dqp, *pqp, *nqp; static int first = 1; char buf[BUFSIZ], *cp, *cplim; u_int32_t nm; time_t my_generation = time(NULL); ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "get interface configuration: %m - exiting"); exit(1); } ntp = NULL;#if defined(AF_LINK) && !defined(RISCOS_BSD)#define my_max(a, b) (a > b ? a : b)#define my_size(p) my_max((p).sa_len, sizeof(p))#else#define my_size(p) (sizeof (p))#endif cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + my_size(ifr->ifr_addr)) {#undef my_size ifr = (struct ifreq *)cp; if (ifr->ifr_addr.sa_family != AF_INET || ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr == 0) { continue; } ifreq = *ifr; /* * Don't test IFF_UP, packets may still be received at this * address if any other interface is up. */#if !defined(BSD) || (BSD < 199103) if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get interface addr: %m"); continue; }#endif dprintf(1, (ddt, "considering [%s]\n", inet_ntoa(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr))); /* build datagram queue */ /* * look for an already existing source interface address. * This happens mostly when reinitializing. Also, if * the machine has multiple point to point interfaces, then * the local address may appear more than once. */ if (dqp = aIsUs(((struct sockaddr_in *)&ifreq.ifr_addr) ->sin_addr)) { dprintf(1, (ddt, "dup interface address %s on %s\n", inet_ntoa(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr), ifreq.ifr_name)); dqp->dq_gen = my_generation; continue; } /* * Skip over address 0.0.0.0 since this will conflict * with binding to wildcard address later. Interfaces * which are not completely configured can have this addr. */ if (((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr == 0x00000000) { /* XXX */ dprintf(1, (ddt, "skipping address 0.0.0.0 on %s\n", ifreq.ifr_name)); continue; } if ((dqp = (struct qdatagram *) calloc(1, sizeof(struct qdatagram)) ) == NULL) { dprintf(5, (ddt, "getnetconf: malloc error\n")); syslog(LOG_ERR, "getnetconf: Out Of Memory"); exit(12); } dqp->dq_next = datagramq; datagramq = dqp; dqp->dq_addr = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr; dqp->dq_gen = my_generation; opensocket(dqp); dprintf(1, (ddt, "listening [%s]\n", inet_ntoa(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr))); /* * Add interface to list of directly-attached (sub)nets * for use in sorting addresses. */ if (ntp == NULL) { ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); } ntp->my_addr = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr;#ifdef SIOCGIFNETMASK if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get netmask: %m"); ntp->mask = net_mask(ntp->my_addr); } else ntp->mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;#else /* 4.2 does not support subnets */ ntp->mask = net_mask(ntp->my_addr);#endif if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get interface flags: %m"); continue; }#ifdef IFF_LOOPBACK if (ifreq.ifr_flags & IFF_LOOPBACK)#else /* test against 127.0.0.1 (yuck!!) */ if (ntp->my_addr.s_addr == inet_addr("127.0.0.1")) /* XXX */#endif { if (netloop.my_addr.s_addr == 0) { netloop.my_addr = ntp->my_addr; netloop.mask = 0xffffffff; netloop.net = ntp->my_addr.s_addr; dprintf(1, (ddt, "loopback address: x%lx\n", netloop.my_addr.s_addr)); } continue; } else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) { if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get dst addr: %m"); continue; } ntp->mask = 0xffffffff; ntp->net = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; } else { ntp->net = ntp->mask & ntp->my_addr.s_addr; } /* * Place on end of list of locally-attached (sub)nets, * but before logical nets for subnetted nets. */ ntp->next = *elocal; *elocal = ntp; if (elocal == enettab) enettab = &ntp->next; elocal = &ntp->next; ntp = NULL; } if (ntp) (void) free((char *)ntp); /* * now go through the datagramq and delete anything that * does not have the current generation number. this is * how we catch interfaces that go away or change their * addresses. note that 0.0.0.0 is the wildcard element * and should never be deleted by this code. * * XXX - need to update enettab/elocal as well. */ for (pqp = NULL, dqp = datagramq; dqp != NULL; pqp = dqp, dqp = nqp) { nqp = dqp->dq_next; if ((dqp->dq_addr.s_addr != INADDR_ANY) && (dqp->dq_gen != my_generation) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -