add dns
This commit is contained in:
parent
cff43a06f2
commit
3e0d8fb3ea
15 changed files with 7047 additions and 0 deletions
178
src/cmd/ndb/dnserver.c
Executable file
178
src/cmd/ndb/dnserver.c
Executable file
|
|
@ -0,0 +1,178 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ip.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
#include "dns.h"
|
||||
|
||||
static RR* doextquery(DNSmsg*, Request*, int);
|
||||
static void hint(RR**, RR*);
|
||||
|
||||
extern char *logfile;
|
||||
|
||||
/*
|
||||
* answer a dns request
|
||||
*/
|
||||
void
|
||||
dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
|
||||
{
|
||||
RR *tp, *neg;
|
||||
char *cp;
|
||||
DN *nsdp, *dp;
|
||||
Area *myarea;
|
||||
char tname[32];
|
||||
|
||||
dncheck(nil, 1);
|
||||
|
||||
memset(repp, 0, sizeof(*repp));
|
||||
repp->id = reqp->id;
|
||||
repp->flags = Fresp | Fcanrec | Oquery;
|
||||
|
||||
/* move one question from reqp to repp */
|
||||
tp = reqp->qd;
|
||||
reqp->qd = tp->next;
|
||||
tp->next = 0;
|
||||
repp->qd = tp;
|
||||
|
||||
if(!rrsupported(repp->qd->type)){
|
||||
syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
|
||||
repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
|
||||
return;
|
||||
}
|
||||
|
||||
if(repp->qd->owner->class != Cin){
|
||||
syslog(0, logfile, "server: class %d", repp->qd->owner->class);
|
||||
repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
|
||||
return;
|
||||
}
|
||||
|
||||
myarea = inmyarea(repp->qd->owner->name);
|
||||
if(myarea != nil && (repp->qd->type == Tixfr || repp->qd->type == Taxfr)){
|
||||
syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
|
||||
repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the answer if we can
|
||||
*/
|
||||
if(reqp->flags & Frecurse)
|
||||
neg = doextquery(repp, req, Recurse);
|
||||
else
|
||||
neg = doextquery(repp, req, Dontrecurse);
|
||||
|
||||
/* authority is transitive */
|
||||
if(myarea != nil || (repp->an && repp->an->auth))
|
||||
repp->flags |= Fauth;
|
||||
|
||||
/* pass on error codes */
|
||||
if(repp->an == 0){
|
||||
dp = dnlookup(repp->qd->owner->name, repp->qd->owner->class, 0);
|
||||
if(dp->rr == 0)
|
||||
if(reqp->flags & Frecurse)
|
||||
repp->flags |= dp->nonexistent|Fauth;
|
||||
}
|
||||
|
||||
if(myarea == nil){
|
||||
/*
|
||||
* add name server if we know
|
||||
*/
|
||||
for(cp = repp->qd->owner->name; cp; cp = walkup(cp)){
|
||||
nsdp = dnlookup(cp, repp->qd->owner->class, 0);
|
||||
if(nsdp == 0)
|
||||
continue;
|
||||
|
||||
repp->ns = rrlookup(nsdp, Tns, OKneg);
|
||||
if(repp->ns){
|
||||
/* don't pass on anything we know is wrong */
|
||||
if(repp->ns->negative){
|
||||
rrfreelist(repp->ns);
|
||||
repp->ns = nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
repp->ns = dblookup(cp, repp->qd->owner->class, Tns, 0, 0);
|
||||
if(repp->ns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add ip addresses as hints
|
||||
*/
|
||||
if(repp->qd->type != Taxfr && repp->qd->type != Tixfr){
|
||||
for(tp = repp->ns; tp; tp = tp->next)
|
||||
hint(&repp->ar, tp);
|
||||
for(tp = repp->an; tp; tp = tp->next)
|
||||
hint(&repp->ar, tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* add an soa to the authority section to help client with negative caching
|
||||
*/
|
||||
if(repp->an == nil){
|
||||
if(myarea != nil){
|
||||
rrcopy(myarea->soarr, &tp);
|
||||
rrcat(&repp->ns, tp);
|
||||
} else if(neg != nil) {
|
||||
if(neg->negsoaowner != nil)
|
||||
rrcat(&repp->ns, rrlookup(neg->negsoaowner, Tsoa, NOneg));
|
||||
repp->flags |= neg->negrcode;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get rid of duplicates
|
||||
*/
|
||||
unique(repp->an);
|
||||
unique(repp->ns);
|
||||
unique(repp->ar);
|
||||
|
||||
rrfreelist(neg);
|
||||
|
||||
dncheck(nil, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* satisfy a recursive request. dnlookup will handle cnames.
|
||||
*/
|
||||
static RR*
|
||||
doextquery(DNSmsg *mp, Request *req, int recurse)
|
||||
{
|
||||
int type;
|
||||
char *name;
|
||||
RR *rp, *neg;
|
||||
|
||||
name = mp->qd->owner->name;
|
||||
type = mp->qd->type;
|
||||
rp = dnresolve(name, Cin, type, req, &mp->an, 0, recurse, 1, 0);
|
||||
|
||||
/* don't return soa hints as answers, it's wrong */
|
||||
if(rp && rp->db && !rp->auth && rp->type == Tsoa)
|
||||
rrfreelist(rp);
|
||||
|
||||
/* don't let negative cached entries escape */
|
||||
neg = rrremneg(&rp);
|
||||
rrcat(&mp->an, rp);
|
||||
return neg;
|
||||
}
|
||||
|
||||
static void
|
||||
hint(RR **last, RR *rp)
|
||||
{
|
||||
RR *hp;
|
||||
|
||||
switch(rp->type){
|
||||
case Tns:
|
||||
case Tmx:
|
||||
case Tmb:
|
||||
case Tmf:
|
||||
case Tmd:
|
||||
hp = rrlookup(rp->host, Ta, NOneg);
|
||||
if(hp == nil)
|
||||
hp = dblookup(rp->host->name, Cin, Ta, 0, 0);
|
||||
rrcat(last, hp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue