📄 dn.c
字号:
*/RR*rrlookup(DN *dp, int type, int flag){ RR *rp, *first, **last; assert(dp->magic == DNmagic); first = 0; last = &first; lock(&dnlock); /* try for an authoritative db entry */ for(rp = dp->rr; rp; rp = rp->next){ assert(rp->magic == RRmagic && rp->cached); if(rp->db) if(rp->auth) if(tsame(type, rp->type)) last = rrcopy(rp, last); } if(first) goto out; /* try for an living authoritative network entry */ for(rp = dp->rr; rp; rp = rp->next){ if(!rp->db) if(rp->auth) if(rp->ttl + 60 > now) if(tsame(type, rp->type)){ if(flag == NOneg && rp->negative) goto out; last = rrcopy(rp, last); } } if(first) goto out; /* try for an living unauthoritative network entry */ for(rp = dp->rr; rp; rp = rp->next){ if(!rp->db) if(rp->ttl + 60 > now) if(tsame(type, rp->type)){ if(flag == NOneg && rp->negative) goto out; last = rrcopy(rp, last); } } if(first) goto out; /* try for an unauthoritative db entry */ for(rp = dp->rr; rp; rp = rp->next){ if(rp->db) if(tsame(type, rp->type)) last = rrcopy(rp, last); } if(first) goto out; /* otherwise, settle for anything we got (except for negative caches) */ for(rp = dp->rr; rp; rp = rp->next){ if(tsame(type, rp->type)){ if(rp->negative) goto out; last = rrcopy(rp, last); } }out: unlock(&dnlock); unique(first); return first;}/* * convert an ascii RR type name to its integer representation */intrrtype(char *atype){ int i; for(i = 0; i <= Tall; i++) if(rrtname[i] && strcmp(rrtname[i], atype) == 0) return i; // make any a synonym for all if(strcmp(atype, "any") == 0) return Tall; return atoi(atype);}/* * convert an integer RR type to it's ascii name */char*rrname(int type, char *buf, int len){ char *t; t = 0; if(type <= Tall) t = rrtname[type]; if(t==0){ snprint(buf, len, "%d", type); t = buf; } return t;}/* * return 0 if not a supported rr type */intrrsupported(int type){ if(type < 0 || type >Tall) return 0; return rrtname[type] != 0;}/* * compare 2 types */inttsame(int t1, int t2){ return t1 == t2 || t1 == Tall;}/* * Add resource records to a list, duplicate them if they are cached * RR's since these are shared. */RR*rrcat(RR **start, RR *rp){ RR **last; last = start; while(*last != 0) last = &(*last)->next; *last = rp; return *start;}/* * remove negative cache rr's from an rr list */RR*rrremneg(RR **l){ RR **nl, *rp; RR *first; first = nil; nl = &first; while(*l != nil){ rp = *l; if(rp->negative){ *l = rp->next; *nl = rp; nl = &rp->next; *nl = nil; } else l = &rp->next; } return first;}/* * remove rr's of a particular type from an rr list */RR*rrremtype(RR **l, int type){ RR **nl, *rp; RR *first; first = nil; nl = &first; while(*l != nil){ rp = *l; if(rp->type == type){ *l = rp->next; *nl = rp; nl = &rp->next; *nl = nil; } else l = &(*l)->next; } return first;}/* * print conversion for rr records */intrrfmt(Fmt *f){ RR *rp; char *strp; Fmt fstr; int rv; char buf[Domlen]; Server *s; Txt *t; fmtstrinit(&fstr); rp = va_arg(f->args, RR*); if(rp == 0){ fmtprint(&fstr, "<null>"); goto out; } fmtprint(&fstr, "%s %s", rp->owner->name, rrname(rp->type, buf, sizeof buf)); if(rp->negative){ fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode); goto out; } switch(rp->type){ case Thinfo: fmtprint(&fstr, "\t%s %s", rp->cpu->name, rp->os->name); break; case Tcname: case Tmb: case Tmd: case Tmf: case Tns: fmtprint(&fstr, "\t%s", rp->host->name); break; case Tmg: case Tmr: fmtprint(&fstr, "\t%s", rp->mb->name); break; case Tminfo: fmtprint(&fstr, "\t%s %s", rp->mb->name, rp->rmb->name); break; case Tmx: fmtprint(&fstr, "\t%lud %s", rp->pref, rp->host->name); break; case Ta: case Taaaa: fmtprint(&fstr, "\t%s", rp->ip->name); break; case Tptr:// fmtprint(&fstr, "\t%s(%lud)", rp->ptr->name, rp->ptr->ordinal); fmtprint(&fstr, "\t%s", rp->ptr->name); break; case Tsoa: fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name, rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry, rp->soa->expire, rp->soa->minttl); for(s = rp->soa->slaves; s != nil; s = s->next) fmtprint(&fstr, " %s", s->name); break; case Tnull: fmtprint(&fstr, "\t%.*H", rp->null->dlen, rp->null->data); break; case Ttxt: fmtprint(&fstr, "\t"); for(t = rp->txt; t != nil; t = t->next) fmtprint(&fstr, "%s", t->p); break; case Trp: fmtprint(&fstr, "\t%s %s", rp->rmb->name, rp->rp->name); break; case Tkey: fmtprint(&fstr, "\t%d %d %d", rp->key->flags, rp->key->proto, rp->key->alg); break; case Tsig: fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s", rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl, rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name); break; case Tcert: fmtprint(&fstr, "\t%d %d %d", rp->sig->type, rp->sig->tag, rp->sig->alg); break; default: break; }out: strp = fmtstrflush(&fstr); rv = fmtstrcpy(f, strp); free(strp); return rv;}/* * print conversion for rr records in attribute value form */intrravfmt(Fmt *f){ RR *rp; char *strp; Fmt fstr; int rv; Server *s; Txt *t; int quote; fmtstrinit(&fstr); rp = va_arg(f->args, RR*); if(rp == 0){ fmtprint(&fstr, "<null>"); goto out; } if(rp->type == Tptr) fmtprint(&fstr, "ptr=%s", rp->owner->name); else fmtprint(&fstr, "dom=%s", rp->owner->name); switch(rp->type){ case Thinfo: fmtprint(&fstr, " cpu=%s os=%s", rp->cpu->name, rp->os->name); break; case Tcname: fmtprint(&fstr, " cname=%s", rp->host->name); break; case Tmb: case Tmd: case Tmf: fmtprint(&fstr, " mbox=%s", rp->host->name); break; case Tns: fmtprint(&fstr, " ns=%s", rp->host->name); break; case Tmg: case Tmr: fmtprint(&fstr, " mbox=%s", rp->mb->name); break; case Tminfo: fmtprint(&fstr, " mbox=%s mbox=%s", rp->mb->name, rp->rmb->name); break; case Tmx: fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, rp->host->name); break; case Ta: case Taaaa: fmtprint(&fstr, " ip=%s", rp->ip->name); break; case Tptr: fmtprint(&fstr, " dom=%s", rp->ptr->name); break; case Tsoa: fmtprint(&fstr, " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud", rp->host->name, rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry, rp->soa->expire, rp->soa->minttl); for(s = rp->soa->slaves; s != nil; s = s->next) fmtprint(&fstr, " dnsslave=%s", s->name); break; case Tnull: fmtprint(&fstr, " null=%.*H", rp->null->dlen, rp->null->data); break; case Ttxt: fmtprint(&fstr, " txt="); quote = 0; for(t = rp->txt; t != nil; t = t->next) if(strchr(t->p, ' ')) quote = 1; if(quote) fmtprint(&fstr, "\""); for(t = rp->txt; t != nil; t = t->next) fmtprint(&fstr, "%s", t->p); if(quote) fmtprint(&fstr, "\""); break; case Trp: fmtprint(&fstr, " rp=%s txt=%s", rp->rmb->name, rp->rp->name); break; case Tkey: fmtprint(&fstr, " flags=%d proto=%d alg=%d", rp->key->flags, rp->key->proto, rp->key->alg); break; case Tsig: fmtprint(&fstr, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s", rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl, rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name); break; case Tcert: fmtprint(&fstr, " type=%d tag=%d alg=%d", rp->sig->type, rp->sig->tag, rp->sig->alg); break; default: break; }out: strp = fmtstrflush(&fstr); rv = fmtstrcpy(f, strp); free(strp); return rv;}voidwarning(char *fmt, ...){ char dnserr[128]; va_list arg; va_start(arg, fmt); vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); va_end(arg); syslog(1, "dns", dnserr);}/* * create a slave process to handle a request to avoid one request blocking * another */voidslave(Request *req){ static int slaveid; int ppid; if(req->isslave) return; /* we're already a slave process */ /* * These calls to putactivity cannot block. * After getactivity(), the current process is counted * twice in dnvars.active (one will pass to the child). * If putactivity tries to wait for dnvars.active == 0, * it will never happen. */ /* limit parallelism */ if(getactivity(req, 1) > Maxactive){ if(traceactivity) syslog(0, "dns", "[%d] too much activity", getpid()); putactivity(1); return; } ppid = getpid(); switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ case -1: putactivity(1); break; case 0: if(traceactivity) syslog(0, "dns", "[%d] take activity from %d", ppid, getpid()); req->isslave = 1; break; default: longjmp(req->mret, 1); }}/* * chasing down double free's */voiddncheck(void *p, int dolock){ int i; DN *dp; RR *rp; extern Pool *mainmem; if(p != nil){ dp = p; assert(dp->magic == DNmagic); } if(!testing) return; if(dolock) lock(&dnlock); poolcheck(mainmem); for(i = 0; i < HTLEN; i++) for(dp = ht[i]; dp; dp = dp->next){ assert(dp != p); assert(dp->magic == DNmagic); for(rp = dp->rr; rp; rp = rp->next){ assert(rp->magic == RRmagic); assert(rp->cached); assert(rp->owner == dp); } } if(dolock) unlock(&dnlock);}static intrrequiv(RR *r1, RR *r2){ return r1->owner == r2->owner && r1->type == r2->type && r1->arg0 == r2->arg0 && r1->arg1 == r2->arg1;}voidunique(RR *rp){ RR **l, *nrp; for(; rp; rp = rp->next){ l = &rp->next; for(nrp = *l; nrp; nrp = *l){ if(rrequiv(rp, nrp)){ *l = nrp->next; rrfree(nrp); } else l = &nrp->next; } }}/* * true if second domain is subsumed by the first */intsubsume(char *higher, char *lower){ int hn, ln; ln = strlen(lower); hn = strlen(higher); if(ln < hn) return 0; if(cistrcmp(lower + ln - hn, higher) != 0) return 0; if(ln > hn && hn != 0 && lower[ln - hn - 1] != '.') return 0; return 1;}/* * randomize the order we return items to provide some * load balancing for servers. * * only randomize the first class of entries */RR*randomize(RR *rp){ RR *first, *last, *x, *base; ulong n; if(rp == nil || rp->next == nil) return rp; /* just randomize addresses and mx's */ for(x = rp; x; x = x->next) if(x->type != Ta && x->type != Tmx && x->type != Tns) return rp; base = rp; n = rand(); last = first = nil; while(rp != nil){ /* stop randomizing if we've moved past our class */ if(base->auth != rp->auth || base->db != rp->db){ last->next = rp; break; } /* unchain */ x = rp; rp = x->next; x->next = nil; if(n&1){ /* add to tail */ if(last == nil) first = x; else last->next = x; last = x; } else { /* add to head */ if(last == nil) last = x; x->next = first; first = x; } /* reroll the dice */ n >>= 1; } return first;}static intsencodefmt(Fmt *f){ char *out; char *buf; int i, len; int ilen; int rv; uchar *b; char obuf[64]; // rsc optimization if(!(f->flags&FmtPrec) || f->prec < 1) goto error; b = va_arg(f->args, uchar*); if(b == nil) goto error; /* if it's a printable, go for it */ len = f->prec; for(i = 0; i < len; i++) if(!isprint(b[i])) break; if(i == len){ if(len >= sizeof obuf) len = sizeof(obuf)-1; memmove(obuf, b, len); obuf[len] = 0; fmtstrcpy(f, obuf); return 0; } ilen = f->prec; f->prec = 0; f->flags &= ~FmtPrec; switch(f->r){ case '<': len = (8*ilen+4)/5 + 3; break; case '[': len = (8*ilen+5)/6 + 4; break; case 'H': len = 2*ilen + 1; break; default: goto error; } if(len > sizeof(obuf)){ buf = malloc(len); if(buf == nil) goto error; } else buf = obuf; // convert out = buf; switch(f->r){ case '<': rv = enc32(out, len, b, ilen); break; case '[': rv = enc64(out, len, b, ilen); break; case 'H': rv = enc16(out, len, b, ilen); break; default: rv = -1; break; } if(rv < 0) goto error; fmtstrcpy(f, buf); if(buf != obuf) free(buf); return 0;error: return fmtstrcpy(f, "<encodefmt>");}void*emalloc(int size){ char *x; x = mallocz(size, 1); if(x == nil) abort(); setmalloctag(x, getcallerpc(&size)); return x;}char*estrdup(char *s){ int size; char *p; size = strlen(s)+1; p = mallocz(size, 0); if(p == nil) abort(); memmove(p, s, size); setmalloctag(p, getcallerpc(&s)); return p;}/* * create a pointer record */static RR*mkptr(DN *dp, char *ptr, ulong ttl){ DN *ipdp; RR *rp; ipdp = dnlookup(ptr, Cin, 1); rp = rralloc(Tptr); rp->ptr = dp; rp->owner = ipdp; rp->db = 1; if(ttl) rp->ttl = ttl; return rp;}/* * look for all ip addresses in this network and make * pointer records for them. */voiddnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl){ int i, j; DN *dp; RR *rp, *nrp, *first, **l; uchar ip[IPaddrlen]; uchar nnet[IPaddrlen]; char ptr[Domlen]; char *p, *e; l = &first; first = nil; for(i = 0; i < HTLEN; i++){ for(dp = ht[i]; dp; dp = dp->next){ for(rp = dp->rr; rp; rp = rp->next){ if(rp->type != Ta || rp->negative) continue; parseip(ip, rp->ip->name); maskip(ip, mask, nnet); if(ipcmp(net, nnet) != 0) continue; p = ptr; e = ptr+sizeof(ptr); for(j = IPaddrlen-1; j >= IPaddrlen-bytes; j--) p = seprint(p, e, "%d.", ip[j]); seprint(p, e, "%s", dom); nrp = mkptr(dp, ptr, ttl); *l = nrp; l = &nrp->next; } } } for(rp = first; rp != nil; rp = nrp){ nrp = rp->next; rp->next = nil; rrattach(rp, 1); }}voidfreeserverlist(Server *s){ Server *next; for(; s != nil; s = next){ next = s->next; free(s); }}voidaddserver(Server **l, char *name){ Server *s; while(*l) l = &(*l)->next; s = malloc(sizeof(Server)+strlen(name)+1); if(s == nil) return; s->name = (char*)(s+1); strcpy(s->name, name); s->next = nil; *l = s;}Server*copyserverlist(Server *s){ Server *ns; for(ns = nil; s != nil; s = s->next) addserver(&ns, s->name); return ns;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -