📄 nserve.c
字号:
/* * if response was authoritative, break and return it. */ if (hp->h_flags & AUTHORITY) { ret = hp->h_rcode; nsrclose(npd); break; } /* * Otherwise check for indirection. */ if (hp->h_rcode == R_NOERR && hp->h_nscnt != 0 && hp->h_arcnt != 0) chg += mkalist(addrlist,nreq,NULL); freerp(nreq); free(nblock); hp = NULL; nsrclose(npd); } /* * Done. if hp is NULL, no response was found, otherwise * return nblock to sender. */ if (hp == NULL) { LOG2(L_ALL,"(%5d) remsend: return R_NSFAIL\n",Logstamp); /* if chg was set, we got an indirection, but no answer */ /* if oreq is set, we are going to the primary only, so */ /* no indirection is expected. */ if (sndback(pd,(chg || oreq)?R_SEND:R_RCV) == RFS_FAILURE) nsrclose(pd); ret = R_NSFAIL; /* this sets up backout if necessary */ } else { if (nswrite(pd,nblock,nsize) == -1) { LOG2(L_ALL,"(%5d) remsend: nswrite of resp failed\n", Logstamp); nsrclose(pd); } if (oreq && oreq->rq_head && oreq->rq_head->h_opcode == NS_INIT) { exit(setmaster(nreq)); /* NS_INIT does not signal parent */ } } kill(getppid(),SIGUSR2); /* notify parent */ exit(ret);}/* * This function is a sanity timer for the child process. * if the child takes longer than CHILDTIME to complete, it will be * interrupted, and the operation will fail. CHILDTIME should * be set to several minutes to guarantee that it only goes * off when things are clearly hung (i.e., > 200). In particular, * it should be at least double R_TIMEOUT, which is the recovery * timeout. */static intsane_cld(){ LOG3(L_OVER,"(%5d) sane_cld: Child %d timed out\n",Logstamp,getpid()); kill(getppid(),SIGUSR2); exit(R_NSFAIL);}intsndback(pd,rcode)int pd;int rcode;{ struct request rq; struct header hd; char *block=NULL; int size; LOG4(L_TRANS,"(%5d) sndback: pd=%d, rcode=%d\n",Logstamp,pd,rcode); rq.rq_head = &hd; hd.h_version = NSVERSION; hd.h_flags = RESPONSE | NOT_AUTHORITY; hd.h_opcode = NS_SNDBACK; hd.h_rcode = rcode; hd.h_dname = Dname; hd.h_qdcnt = hd.h_ancnt = hd.h_nscnt = hd.h_arcnt = 0; if ((block = reqtob(&rq,block,&size)) == NULL) { LOG1(L_TRANS,"(%5d) sndback: block is NULL\n"); return(RFS_FAILURE); } if (nswrite(pd,block,size) == -1) { LOG2(L_TRANS,"(%5d) sndback: nswrite failed\n",Logstamp); free(block); return(RFS_FAILURE); } free(block); return(RFS_SUCCESS);}/* * This function makes a temporary netmaster file * from an address, and reads it in using readfile. */static intputprime(addr)struct address *addr;{ char *tmpnam(); char *tmpfile = tmpnam(NULL); char *p_name = PRIMENAME; char addbuf[BUFSIZ]; FILE *fopen(); FILE *fd; int ret; LOG3(L_TRANS,"(%5d) putprime: addr=%x\n",Logstamp,addr); if (!addr || aatos(addbuf,addr,HEX) == NULL) { LOG2(L_TRANS,"(%5d) putprime: Can't translate address\n",Logstamp); return(RFS_FAILURE); } LOG3(L_TRANS | L_OVER,"(%5d) putprime: set primary address to %s\n", Logstamp,addbuf); if (eqaddr(addr,getmyaddr())) p_name = Dname; if ((fd = fopen(tmpfile,"w")) == NULL) { perror("RFS name server: putprime temporary file"); return(RFS_FAILURE); } fprintf(fd,"%s p %s\n%s a %s\n", dompart(Dname),p_name,p_name,addbuf); fclose(fd); ret = readdb(tmpfile); unlink(tmpfile); if (ret <= 0) PLOG1("RFS name server: RFS_FAILURE reading primary address\n"); return((ret <= 0)?RFS_FAILURE:RFS_SUCCESS);}intfreerp(req)struct request *req;{ long i; struct header *hp; hp = req->rq_head; /* remove resource records */ for (i=0; i < hp->h_ancnt; i++) freerec(req->rq_an[i]); for (i=0; i < hp->h_nscnt; i++) freerec(req->rq_ns[i]); for (i=0; i < hp->h_arcnt; i++) freerec(req->rq_ar[i]); if (hp->h_ancnt) free(req->rq_an); if (hp->h_nscnt) free(req->rq_ns); if (hp->h_arcnt) free(req->rq_ar); /* now do the query section */ for (i=0; i < hp->h_qdcnt; i++) { free(req->rq_qd[i]->q_name); free(req->rq_qd[i]); } if (hp->h_qdcnt) free(req->rq_qd); if (hp->h_dname) free(hp->h_dname); free(hp); free(req); return;}static intsigterm(){ LOG2(L_ALL,"(%5d): sigterm called\n",Logstamp); clrnslock(); Done = TRUE;}/* wait for child */static intwaitcld(){ register int i; int stat_loc; int child; struct request *req; int alrm_tim; static int alrm_fn(); sigset(SIGUSR2, SIG_IGN); alrm_tim = alarm(0); sigset(SIGALRM,alrm_fn); alarm(CHILDWAIT); LOG2(L_COMM,"(%5d) waitcld: entering\n", Logstamp); while ((child = wait(&stat_loc)) != -1) { alarm(0); LOG4(L_COMM,"(%5d) waitcld: child %d exits with code 0x%x\n", Logstamp,child,stat_loc); /* see if child is in table */ for (i=0; i < MAXCHILDREN; i++) if (Children[i].c_pid == child) { Children[i].c_pid = 0; req = Children[i].c_req; Children[i].c_req = NULL; if ((stat_loc & 0xFF) == 0 && stat_loc) ns_undo(req); else { if (req->rq_head->h_opcode == NS_INIT) { if (re_read() == RFS_FAILURE) Done = TRUE; else if (!Primary && r_init() == RFS_FAILURE) { PLOG1("RFS Name Server: r_init after merge FATAL\n"); Done = TRUE; } } freerp(req); } break; } sigset(SIGALRM,alrm_fn); alarm(CHILDWAIT); } alarm(0); sigset(SIGALRM,Alarmsig); if (Alarmsig != SIG_IGN) alarm((alrm_tim)?alrm_tim:Polltime); sigset(SIGUSR2,waitcld); return;}static intalrm_fn(){ sigset(SIGALRM,alrm_fn); LOG2(L_OVER,"(%5d) waitcld: wait sanity alarm\n",Logstamp);}static intre_read(){ int errflg; if ((errflg = readfile(Netmaster,TRUE,FALSE)) <= 0) { if (errflg == 0) PLOG2("RFS name server: %s is empty after INIT\n",Netmaster); else PLOG3("RFS name server: can't open %s, error %s after INIT\n", Netmaster, (errno > sys_nerr)?"unknown error":sys_errlist[errno]); return(RFS_FAILURE); } merge(DOMMASTER,FALSE); return(RFS_SUCCESS);}static intsavecld(child,req)int child;struct request *req;{ int i; for (i=0; i < MAXCHILDREN; i++) if (Children[i].c_pid == NULL) { Children[i].c_pid = child; Children[i].c_req = req; return(RFS_SUCCESS); } /* ran out of room, warn but continue */ PLOG1("RFS name server: WARNING exceeded maximum outstanding children\n"); freerp(req); return(RFS_FAILURE);}static intmkalist(addrlist,req,addr)struct address **addrlist;struct request *req;struct address **addr;{ int i,j; int istart; /* initial length of addrlist */ struct header *hp; struct address *ap; LOG5(L_TRANS,"(%5d) mkalist(addrlist=%x,req=%x,addr[0]=%s\n", Logstamp,addrlist,req,(addr && addr[0])? aatos(Logbuf,addr[0],KEEP | HEX):"NULL"); /* find end of addrlist */ for (i=0; addrlist[i] != NULL && i < MAX_RETRY; i++) ; if (i == MAX_RETRY) return(0); istart = i; if (addr) for (j=0; j < MAXNS; j++) if (addr[j] && notinlist(addrlist,addr[j])) { addrlist[i++] = addr[j]; if (i < MAX_RETRY) { LOG3(L_TRANS,"(%5d) mkalist: add Paddress %s\n", Logstamp,aatos(Logbuf,addr[j],KEEP|HEX)); addrlist[i] = NULL; } } if (req) { hp = req->rq_head; for (j=0; j < hp->h_arcnt && i < MAX_RETRY; j++) { if (ap = astoa(req->rq_ar[j]->rr_a,NULL)) { if (notinlist(addrlist,ap)) { addrlist[i++] = ap; if (i < MAX_RETRY) { LOG3(L_TRANS, "(%5d) mkalist: add address %s\n", Logstamp,aatos(Logbuf,ap,KEEP|HEX)); addrlist[i] = NULL; } } else free(ap); } } } return(i - istart);}static intnotinlist(addrlist,ap)register struct address **addrlist;register struct address *ap;{ register int i; for (i=0; i < MAX_RETRY && *addrlist != NULL; i++, addrlist++) if (eqaddr(*addrlist,ap)) return(FALSE); return(TRUE);}static inteqaddr(a,b)register struct address *a;register struct address *b;{ if (!a || !b) return(FALSE); if (a->addbuf.len != b->addbuf.len) return(FALSE); if (a->protocol && b->protocol && strcmp(a->protocol,b->protocol) != NULL) return(FALSE); if (memcmp(a->addbuf.buf,b->addbuf.buf,a->addbuf.len)) return(FALSE); return(TRUE);}static intns_undo(req)struct request *req;{ struct header *hp; struct request *nreq; LOG2(L_COMM,"ns_undo: req=0X%x\n",req); hp = req->rq_head; /* for now, only undo advertisements */ if (hp->h_opcode == NS_ADV) { hp->h_opcode = NS_UNADV; if ((nreq = nsfunc(req,-1)) == NULL) LOG1(L_ALL,"ns_undo: can't backout request\n"); else freerp(nreq); } freerp(req); return;}/* * setnslock sets a lock file to make sure that two name servers * are not allowed to run at once. It also writes this name server's * pid into the lock file so that rfstop can use it. */static int Lockfd = -1; /* current lock fd */static intsetnslock(){ char buf[BUFSIZ]; if ((Lockfd = open(NSPID, O_RDWR|O_CREAT, 0600)) == -1) { perror(NSPID); return(-1); } if (lockf(Lockfd,F_TLOCK,0L) == -1) { perror(NSPID); return(-1); } sprintf(buf,"%-7d",getpid()); write(Lockfd,buf,strlen(buf)+1); return(0);}static intclrnslock(){ if (Lockfd == -1) return(-1); close(Lockfd); unlink(NSPID); Lockfd = -1; return(0);}/* 4.1 BSD signalling functions used by the name server emulated * with 4.2 BSD calls. */intsighold(sig) int sig;{ if (sig == SIGKILL) { errno = EINVAL; return (-1); /* sigblock quietly disallows SIGKILL */ } (void) sigblock(sigmask(sig)); return (0); /* SVID specifies 0 return on success */}intsigrelse(sig) int sig;{ if (sig == SIGKILL) { errno = EINVAL; return (-1); /* sigsetmask quietly disallows SIGKILL */ } (void) sigsetmask(sigblock(0) & ~sigmask(sig)); return (0); /* SVID specifies 0 return on success */}intsigignore(sig) int sig;{ struct sigvec vec; if (sig == SIGKILL) { errno = EINVAL; return (-1); /* sigsetmask quietly disallows SIGKILL */ } if (sigvec(sig, (struct sigvec *)0, &vec) < 0) return (-1); vec.sv_handler = SIG_IGN; if (sigvec(sig, &vec, (struct sigvec *)0) < 0) return (-1); (void) sigsetmask(sigblock(0) & ~sigmask(sig)); return (0); /* SVID specifies 0 return on success */}void (*sigset(sig, func))() int sig; void (*func)();{ struct sigvec newvec; int newmask; struct sigvec oldvec; int oldmask; if (sigvec(sig, (struct sigvec *)0, &oldvec) < 0) return (SIG_ERR); oldmask = sigblock(0); newvec = oldvec; newvec.sv_flags |= SV_INTERRUPT; newvec.sv_flags &= ~SV_RESETHAND; newvec.sv_mask = 0; newmask = oldmask; if (func == SIG_HOLD) { /* * Signal will be held. Set the bit for that * signal in the signal mask. Leave the action * alone. */ newmask |= sigmask(sig); } else { /* * Signal will not be held. Clear the bit * for it in the signal mask. Set the action * for it. */ newmask &= ~sigmask(sig); newvec.sv_handler = func; } if (sigvec(sig, &newvec, (struct sigvec *)0) < 0) return (SIG_ERR); if (sigsetmask(newmask) < 0) return (SIG_ERR); if (oldmask & sigmask(sig)) return (SIG_HOLD); /* signal was held */ else return (oldvec.sv_handler);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -