tdns.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
tdns.c (15204B)
---
     1 #include 
     2 #include 
     3 #include 
     4 #include 
     5 #include 
     6 #include 
     7 #include 
     8 #include 
     9 #include 
    10 #include "dns.h"
    11 
    12 enum
    13 {
    14         Maxrequest=                1024,
    15         Ncache=                        8,
    16         Maxpath=                128,
    17         Maxreply=                512,
    18         Maxrrr=                        16,
    19         Maxfdata=                8192,
    20 
    21         Qdir=                        0,
    22         Qdns=                        1
    23 };
    24 
    25 typedef struct Mfile        Mfile;
    26 typedef struct Job        Job;
    27 typedef struct Network        Network;
    28 
    29 int vers;                /* incremented each clone/attach */
    30 
    31 struct Mfile
    32 {
    33         Mfile                *next;                /* next free mfile */
    34         int                ref;
    35 
    36         char                *user;
    37         Qid                qid;
    38         int                fid;
    39 
    40         int                type;                /* reply type */
    41         char                reply[Maxreply];
    42         ushort                rr[Maxrrr];        /* offset of rr's */
    43         ushort                nrr;                /* number of rr's */
    44 };
    45 
    46 /*
    47  * active local requests
    48  */
    49 struct Job
    50 {
    51         Job        *next;
    52         int        flushed;
    53         Fcall        request;
    54         Fcall        reply;
    55 };
    56 Lock        joblock;
    57 Job        *joblist;
    58 
    59 struct {
    60         Lock        lk;
    61         Mfile        *inuse;                /* active mfile's */
    62 } mfalloc;
    63 
    64 int        mfd[2];
    65 int        debug;
    66 int traceactivity;
    67 int        cachedb;
    68 ulong        now;
    69 int        testing;
    70 char        *trace;
    71 int        needrefresh;
    72 int        resolver;
    73 uchar        ipaddr[IPaddrlen];        /* my ip address */
    74 int        maxage;
    75 char        *zonerefreshprogram;
    76 int        sendnotifies;
    77 
    78 void        rversion(Job*);
    79 void        rauth(Job*);
    80 void        rflush(Job*);
    81 void        rattach(Job*, Mfile*);
    82 char*        rwalk(Job*, Mfile*);
    83 void        ropen(Job*, Mfile*);
    84 void        rcreate(Job*, Mfile*);
    85 void        rread(Job*, Mfile*);
    86 void        rwrite(Job*, Mfile*, Request*);
    87 void        rclunk(Job*, Mfile*);
    88 void        rremove(Job*, Mfile*);
    89 void        rstat(Job*, Mfile*);
    90 void        rwstat(Job*, Mfile*);
    91 void        sendmsg(Job*, char*);
    92 void        mountinit(char*);
    93 void        io(void);
    94 int        fillreply(Mfile*, int);
    95 Job*        newjob(void);
    96 void        freejob(Job*);
    97 void        setext(char*, int, char*);
    98 
    99 char *tcpaddr = "tcp!*!domain";
   100 char *udpaddr = "udp!*!domain";
   101 char        *logfile = "dns";
   102 char        *dbfile;
   103 char        mntpt[Maxpath];
   104 char        *LOG;
   105 
   106 void
   107 usage(void)
   108 {
   109         fprint(2, "usage: dns [-dnrst] [-a maxage] [-f ndb-file] [-T tcpaddr] [-U udpaddr] [-x service] [-z zoneprog]\n");
   110         threadexitsall("usage");
   111 }
   112 
   113 void
   114 checkaddress(void)
   115 {
   116         char *u, *t;
   117 
   118         u = strchr(udpaddr, '!');
   119         t = strchr(tcpaddr, '!');
   120         if(u && t && strcmp(u, t) != 0)
   121                 fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr);
   122 }
   123 
   124 int
   125 threadmaybackground(void)
   126 {
   127         return 1;
   128 }
   129 
   130 void
   131 threadmain(int argc, char *argv[])
   132 {
   133         int serveudp, servetcp;
   134         char *service;
   135 
   136         serveudp = 0;
   137         servetcp = 0;
   138         service = "dns";
   139         ARGBEGIN{
   140         case 'd':
   141                 debug = 1;
   142                 traceactivity = 1;
   143                 break;
   144         case 'f':
   145                 dbfile = EARGF(usage());
   146                 break;
   147         case 'x':
   148                 service = EARGF(usage());
   149                 break;
   150         case 'r':
   151                 resolver = 1;
   152                 break;
   153         case 's':
   154                 serveudp = 1;
   155                 cachedb = 1;
   156                 break;
   157         case 't':
   158                 servetcp = 1;
   159                 cachedb = 1;
   160                 break;
   161         case 'a':
   162                 maxage = atoi(EARGF(usage()));
   163                 break;
   164         case 'z':
   165                 zonerefreshprogram = EARGF(usage());
   166                 break;
   167         case 'n':
   168                 sendnotifies = 1;
   169                 break;
   170         case 'U':
   171                 udpaddr = estrdup(netmkaddr(EARGF(usage()), "udp", "domain"));
   172                 break;
   173         case 'T':
   174                 tcpaddr = estrdup(netmkaddr(EARGF(usage()), "tcp", "domain"));
   175                 break;
   176         default:
   177                 usage();
   178         }ARGEND
   179 
   180         if(argc)
   181                 usage();
   182         if(serveudp && servetcp)
   183                 checkaddress();
   184 
   185         rfork(RFNOTEG);
   186 
   187         /* start syslog before we fork */
   188         fmtinstall('F', fcallfmt);
   189         dninit();
   190         if(myipaddr(ipaddr, mntpt) < 0)
   191                 sysfatal("can't read my ip address");
   192 
   193         syslog(0, logfile, "starting dns on %I", ipaddr);
   194 
   195         opendatabase();
   196 
   197         mountinit(service);
   198 
   199         now = time(0);
   200         srand(now*getpid());
   201         db2cache(1);
   202 
   203         if(serveudp)
   204                 proccreate(dnudpserver, nil, STACK);
   205         if(servetcp)
   206                 proccreate(dntcpserver, nil, STACK);
   207         if(sendnotifies)
   208                 proccreate(notifyproc, nil, STACK);
   209 
   210         io();
   211 }
   212 
   213 /*
   214  *  if a mount point is specified, set the cs extention to be the mount point
   215  *  with '_'s replacing '/'s
   216  */
   217 void
   218 setext(char *ext, int n, char *p)
   219 {
   220         int i, c;
   221 
   222         n--;
   223         for(i = 0; i < n; i++){
   224                 c = p[i];
   225                 if(c == 0)
   226                         break;
   227                 if(c == '/')
   228                         c = '_';
   229                 ext[i] = c;
   230         }
   231         ext[i] = 0;
   232 }
   233 
   234 void
   235 mountinit(char *service)
   236 {
   237         int p[2];
   238 
   239         if(pipe(p) < 0)
   240                 abort(); /* "pipe failed" */;
   241         if(post9pservice(p[1], service, nil) < 0)
   242                 fprint(2, "post9pservice dns: %r\n");
   243         close(p[1]);
   244         mfd[0] = mfd[1] = p[0];
   245 }
   246 
   247 Mfile*
   248 newfid(int fid, int needunused)
   249 {
   250         Mfile *mf;
   251 
   252         lock(&mfalloc.lk);
   253         for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
   254                 if(mf->fid == fid){
   255                         unlock(&mfalloc.lk);
   256                         if(needunused)
   257                                 return nil;
   258                         return mf;
   259                 }
   260         }
   261         if(!needunused){
   262                 unlock(&mfalloc.lk);
   263                 return nil;
   264         }
   265         mf = emalloc(sizeof(*mf));
   266         if(mf == nil)
   267                 sysfatal("out of memory");
   268         mf->fid = fid;
   269         mf->next = mfalloc.inuse;
   270         mfalloc.inuse = mf;
   271         unlock(&mfalloc.lk);
   272         return mf;
   273 }
   274 
   275 void
   276 freefid(Mfile *mf)
   277 {
   278         Mfile **l;
   279 
   280         lock(&mfalloc.lk);
   281         for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
   282                 if(*l == mf){
   283                         *l = mf->next;
   284                         if(mf->user)
   285                                 free(mf->user);
   286                         free(mf);
   287                         unlock(&mfalloc.lk);
   288                         return;
   289                 }
   290         }
   291         sysfatal("freeing unused fid");
   292 }
   293 
   294 Mfile*
   295 copyfid(Mfile *mf, int fid)
   296 {
   297         Mfile *nmf;
   298 
   299         nmf = newfid(fid, 1);
   300         if(nmf == nil)
   301                 return nil;
   302         nmf->fid = fid;
   303         nmf->user = estrdup(mf->user);
   304         nmf->qid.type = mf->qid.type;
   305         nmf->qid.path = mf->qid.path;
   306         nmf->qid.vers = vers++;
   307         return nmf;
   308 }
   309 
   310 Job*
   311 newjob(void)
   312 {
   313         Job *job;
   314 
   315         job = emalloc(sizeof(*job));
   316         lock(&joblock);
   317         job->next = joblist;
   318         joblist = job;
   319         job->request.tag = -1;
   320         unlock(&joblock);
   321         return job;
   322 }
   323 
   324 void
   325 freejob(Job *job)
   326 {
   327         Job **l;
   328 
   329         lock(&joblock);
   330         for(l = &joblist; *l; l = &(*l)->next){
   331                 if((*l) == job){
   332                         *l = job->next;
   333                         free(job);
   334                         break;
   335                 }
   336         }
   337         unlock(&joblock);
   338 }
   339 
   340 void
   341 flushjob(int tag)
   342 {
   343         Job *job;
   344 
   345         lock(&joblock);
   346         for(job = joblist; job; job = job->next){
   347                 if(job->request.tag == tag && job->request.type != Tflush){
   348                         job->flushed = 1;
   349                         break;
   350                 }
   351         }
   352         unlock(&joblock);
   353 }
   354 
   355 void
   356 ioproc0(void *v)
   357 {
   358         long n;
   359         Mfile *mf;
   360         uchar mdata[IOHDRSZ + Maxfdata];
   361         Request req;
   362         Job *job;
   363 
   364         USED(v);
   365 
   366         for(;;){
   367                 n = read9pmsg(mfd[0], mdata, sizeof mdata);
   368                 if(n <= 0){
   369                         syslog(0, logfile, "error reading mntpt: %r");
   370                         break;
   371                 }
   372                 job = newjob();
   373                 if(convM2S(mdata, n, &job->request) != n){
   374                         freejob(job);
   375                         continue;
   376                 }
   377                 if(debug)
   378                         syslog(0, logfile, "%F", &job->request);
   379 
   380                 getactivity(&req);
   381                 req.aborttime = now + 60;        /* don't spend more than 60 seconds */
   382 
   383                 mf = nil;
   384                 switch(job->request.type){
   385                 case Tversion:
   386                 case Tauth:
   387                 case Tflush:
   388                         break;
   389                 case Tattach:
   390                         mf = newfid(job->request.fid, 1);
   391                         if(mf == nil){
   392                                 sendmsg(job, "fid in use");
   393                                 goto skip;
   394                         }
   395                         break;
   396                 default:
   397                         mf = newfid(job->request.fid, 0);
   398                         if(mf == nil){
   399                                 sendmsg(job, "unknown fid");
   400                                 goto skip;
   401                         }
   402                         break;
   403                 }
   404 
   405                 switch(job->request.type){
   406                 default:
   407                         syslog(1, logfile, "unknown request type %d", job->request.type);
   408                         break;
   409                 case Tversion:
   410                         rversion(job);
   411                         break;
   412                 case Tauth:
   413                         rauth(job);
   414                         break;
   415                 case Tflush:
   416                         rflush(job);
   417                         break;
   418                 case Tattach:
   419                         rattach(job, mf);
   420                         break;
   421                 case Twalk:
   422                         rwalk(job, mf);
   423                         break;
   424                 case Topen:
   425                         ropen(job, mf);
   426                         break;
   427                 case Tcreate:
   428                         rcreate(job, mf);
   429                         break;
   430                 case Tread:
   431                         rread(job, mf);
   432                         break;
   433                 case Twrite:
   434                         rwrite(job, mf, &req);
   435                         break;
   436                 case Tclunk:
   437                         rclunk(job, mf);
   438                         break;
   439                 case Tremove:
   440                         rremove(job, mf);
   441                         break;
   442                 case Tstat:
   443                         rstat(job, mf);
   444                         break;
   445                 case Twstat:
   446                         rwstat(job, mf);
   447                         break;
   448                 }
   449 skip:
   450                 freejob(job);
   451                 putactivity();
   452         }
   453 }
   454 
   455 void
   456 io(void)
   457 {
   458         int i;
   459 
   460         for(i=0; irequest.msize > IOHDRSZ + Maxfdata)
   468                 job->reply.msize = IOHDRSZ + Maxfdata;
   469         else
   470                 job->reply.msize = job->request.msize;
   471         if(strncmp(job->request.version, "9P2000", 6) != 0)
   472                 sendmsg(job, "unknown 9P version");
   473         else{
   474                 job->reply.version = "9P2000";
   475                 sendmsg(job, 0);
   476         }
   477 }
   478 
   479 void
   480 rauth(Job *job)
   481 {
   482         sendmsg(job, "dns: authentication not required");
   483 }
   484 
   485 /*
   486  *  don't flush till all the slaves are done
   487  */
   488 void
   489 rflush(Job *job)
   490 {
   491         flushjob(job->request.oldtag);
   492         sendmsg(job, 0);
   493 }
   494 
   495 void
   496 rattach(Job *job, Mfile *mf)
   497 {
   498         if(mf->user != nil)
   499                 free(mf->user);
   500         mf->user = estrdup(job->request.uname);
   501         mf->qid.vers = vers++;
   502         mf->qid.type = QTDIR;
   503         mf->qid.path = 0LL;
   504         job->reply.qid = mf->qid;
   505         sendmsg(job, 0);
   506 }
   507 
   508 char*
   509 rwalk(Job *job, Mfile *mf)
   510 {
   511         char *err;
   512         char **elems;
   513         int nelems;
   514         int i;
   515         Mfile *nmf;
   516         Qid qid;
   517 
   518         err = 0;
   519         nmf = nil;
   520         elems = job->request.wname;
   521         nelems = job->request.nwname;
   522         job->reply.nwqid = 0;
   523 
   524         if(job->request.newfid != job->request.fid){
   525                 /* clone fid */
   526                 nmf = copyfid(mf, job->request.newfid);
   527                 if(nmf == nil){
   528                         err = "clone bad newfid";
   529                         goto send;
   530                 }
   531                 mf = nmf;
   532         }
   533         /* else nmf will be nil */
   534 
   535         qid = mf->qid;
   536         if(nelems > 0){
   537                 /* walk fid */
   538                 for(i=0; ireply.wqid[i] = qid;
   548                                 job->reply.nwqid++;
   549                                 continue;
   550                         }
   551                         if(strcmp(elems[i], "dns") == 0){
   552                                 qid.type = QTFILE;
   553                                 qid.path = Qdns;
   554                                 goto Found;
   555                         }
   556                         err = "file does not exist";
   557                         break;
   558                 }
   559         }
   560 
   561     send:
   562         if(nmf != nil && (err!=nil || job->reply.nwqidqid = qid;
   566         sendmsg(job, err);
   567         return err;
   568 }
   569 
   570 void
   571 ropen(Job *job, Mfile *mf)
   572 {
   573         int mode;
   574         char *err;
   575 
   576         err = 0;
   577         mode = job->request.mode;
   578         if(mf->qid.type & QTDIR){
   579                 if(mode)
   580                         err = "permission denied";
   581         }
   582         job->reply.qid = mf->qid;
   583         job->reply.iounit = 0;
   584         sendmsg(job, err);
   585 }
   586 
   587 void
   588 rcreate(Job *job, Mfile *mf)
   589 {
   590         USED(mf);
   591         sendmsg(job, "creation permission denied");
   592 }
   593 
   594 void
   595 rread(Job *job, Mfile *mf)
   596 {
   597         int i, n, cnt;
   598         long off;
   599         Dir dir;
   600         uchar buf[Maxfdata];
   601         char *err;
   602         long clock;
   603 
   604         n = 0;
   605         err = 0;
   606         off = job->request.offset;
   607         cnt = job->request.count;
   608         if(mf->qid.type & QTDIR){
   609                 clock = time(0);
   610                 if(off == 0){
   611                         dir.name = "dns";
   612                         dir.qid.type = QTFILE;
   613                         dir.qid.vers = vers;
   614                         dir.qid.path = Qdns;
   615                         dir.mode = 0666;
   616                         dir.length = 0;
   617                         dir.uid = mf->user;
   618                         dir.gid = mf->user;
   619                         dir.muid = mf->user;
   620                         dir.atime = clock;        /* wrong */
   621                         dir.mtime = clock;        /* wrong */
   622                         n = convD2M(&dir, buf, sizeof buf);
   623                 }
   624                 job->reply.data = (char*)buf;
   625         } else {
   626                 for(i = 1; i <= mf->nrr; i++)
   627                         if(mf->rr[i] > off)
   628                                 break;
   629                 if(i > mf->nrr)
   630                         goto send;
   631                 if(off + cnt > mf->rr[i])
   632                         n = mf->rr[i] - off;
   633                 else
   634                         n = cnt;
   635                 job->reply.data = mf->reply + off;
   636         }
   637 send:
   638         job->reply.count = n;
   639         sendmsg(job, err);
   640 }
   641 
   642 void
   643 rwrite(Job *job, Mfile *mf, Request *req)
   644 {
   645         int cnt, rooted, status;
   646         long n;
   647         char *err, *p, *atype;
   648         RR *rp, *tp, *neg;
   649         int wantsav;
   650         static char *dumpfile;
   651 
   652         err = 0;
   653         cnt = job->request.count;
   654         if(mf->qid.type & QTDIR){
   655                 err = "can't write directory";
   656                 goto send;
   657         }
   658         if(cnt >= Maxrequest){
   659                 err = "request too long";
   660                 goto send;
   661         }
   662         job->request.data[cnt] = 0;
   663         if(cnt > 0 && job->request.data[cnt-1] == '\n')
   664                 job->request.data[cnt-1] = 0;
   665 
   666         /*
   667          *  special commands
   668          */
   669         p = job->request.data;
   670         if(strcmp(p, "debug")==0){
   671                 debug ^= 1;
   672                 goto send;
   673         } else if(strcmp(p, "dump")==0){
   674                 if(dumpfile == nil)
   675                         dumpfile = unsharp("#9/ndb/dnsdump");
   676                 dndump(dumpfile);
   677                 goto send;
   678         } else if(strncmp(p, "dump ", 5) == 0){
   679                 if(*(p+5))
   680                         dndump(p+5);
   681                 else
   682                         err = "bad filename";
   683                 goto send;
   684         } else if(strcmp(p, "refresh")==0){
   685                 needrefresh = 1;
   686                 goto send;
   687         }
   688 
   689         /*
   690          *  kill previous reply
   691          */
   692         mf->nrr = 0;
   693         mf->rr[0] = 0;
   694 
   695         /*
   696          *  break up request (into a name and a type)
   697          */
   698         atype = strchr(job->request.data, ' ');
   699         if(atype == 0){
   700                 err = "illegal request";
   701                 goto send;
   702         } else
   703                 *atype++ = 0;
   704 
   705         /*
   706          *  tracing request
   707          */
   708         if(strcmp(atype, "trace") == 0){
   709                 if(trace)
   710                         free(trace);
   711                 if(*job->request.data)
   712                         trace = estrdup(job->request.data);
   713                 else
   714                         trace = 0;
   715                 goto send;
   716         }
   717 
   718         mf->type = rrtype(atype);
   719         if(mf->type < 0){
   720                 err = "unknown type";
   721                 goto send;
   722         }
   723 
   724         p = atype - 2;
   725         if(p >= job->request.data && *p == '.'){
   726                 rooted = 1;
   727                 *p = 0;
   728         } else
   729                 rooted = 0;
   730 
   731         p = job->request.data;
   732         if(*p == '!'){
   733                 wantsav = 1;
   734                 p++;
   735         } else
   736                 wantsav = 0;
   737         dncheck(0, 1);
   738         rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
   739         dncheck(0, 1);
   740         neg = rrremneg(&rp);
   741         if(neg){
   742                 status = neg->negrcode;
   743                 rrfreelist(neg);
   744         }
   745         if(rp == 0){
   746                 switch(status){
   747                 case Rname:
   748                         err = "name does not exist";
   749                         break;
   750                 case Rserver:
   751                         err = "dns failure";
   752                         break;
   753                 default:
   754                         err = "resource does not exist";
   755                         break;
   756                 }
   757         } else {
   758                 lock(&joblock);
   759                 if(!job->flushed){
   760                         /* format data to be read later */
   761                         n = 0;
   762                         mf->nrr = 0;
   763                         for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
   764                                         tsame(mf->type, tp->type); tp = tp->next){
   765                                 mf->rr[mf->nrr++] = n;
   766                                 if(wantsav)
   767                                         n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
   768                                 else
   769                                         n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
   770                         }
   771                         mf->rr[mf->nrr] = n;
   772                 }
   773                 unlock(&joblock);
   774                 rrfreelist(rp);
   775         }
   776 
   777     send:
   778         dncheck(0, 1);
   779         job->reply.count = cnt;
   780         sendmsg(job, err);
   781 }
   782 
   783 void
   784 rclunk(Job *job, Mfile *mf)
   785 {
   786         freefid(mf);
   787         sendmsg(job, 0);
   788 }
   789 
   790 void
   791 rremove(Job *job, Mfile *mf)
   792 {
   793         USED(mf);
   794         sendmsg(job, "remove permission denied");
   795 }
   796 
   797 void
   798 rstat(Job *job, Mfile *mf)
   799 {
   800         Dir dir;
   801         uchar buf[IOHDRSZ+Maxfdata];
   802 
   803         if(mf->qid.type & QTDIR){
   804                 dir.name = ".";
   805                 dir.mode = DMDIR|0555;
   806         } else {
   807                 dir.name = "dns";
   808                 dir.mode = 0666;
   809         }
   810         dir.qid = mf->qid;
   811         dir.length = 0;
   812         dir.uid = mf->user;
   813         dir.gid = mf->user;
   814         dir.muid = mf->user;
   815         dir.atime = dir.mtime = time(0);
   816         job->reply.nstat = convD2M(&dir, buf, sizeof buf);
   817         job->reply.stat = buf;
   818         sendmsg(job, 0);
   819 }
   820 
   821 void
   822 rwstat(Job *job, Mfile *mf)
   823 {
   824         USED(mf);
   825         sendmsg(job, "wstat permission denied");
   826 }
   827 
   828 void
   829 sendmsg(Job *job, char *err)
   830 {
   831         int n;
   832         uchar mdata[IOHDRSZ + Maxfdata];
   833         char ename[ERRMAX];
   834 
   835         if(err){
   836                 job->reply.type = Rerror;
   837                 snprint(ename, sizeof(ename), "dns: %s", err);
   838                 job->reply.ename = ename;
   839         }else{
   840                 job->reply.type = job->request.type+1;
   841         }
   842         job->reply.tag = job->request.tag;
   843         n = convS2M(&job->reply, mdata, sizeof mdata);
   844         if(n == 0){
   845                 syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
   846                 abort();
   847         }
   848         lock(&joblock);
   849         if(job->flushed == 0)
   850                 if(write(mfd[1], mdata, n)!=n)
   851                         sysfatal("mount write");
   852         unlock(&joblock);
   853         if(debug)
   854                 syslog(0, logfile, "%F %d", &job->reply, n);
   855 }
   856 
   857 /*
   858  *  the following varies between dnsdebug and dns
   859  */
   860 void
   861 logreply(int id, uchar *addr, DNSmsg *mp)
   862 {
   863         RR *rp;
   864 
   865         syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
   866                 mp->flags & Fauth ? " auth" : "",
   867                 mp->flags & Ftrunc ? " trunc" : "",
   868                 mp->flags & Frecurse ? " rd" : "",
   869                 mp->flags & Fcanrec ? " ra" : "",
   870                 mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
   871                 " nx" : "");
   872         for(rp = mp->qd; rp != nil; rp = rp->next)
   873                 syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
   874         for(rp = mp->an; rp != nil; rp = rp->next)
   875                 syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
   876         for(rp = mp->ns; rp != nil; rp = rp->next)
   877                 syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
   878         for(rp = mp->ar; rp != nil; rp = rp->next)
   879                 syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
   880 }
   881 
   882 void
   883 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
   884 {
   885         char buf[12];
   886 
   887         syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
   888                 id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
   889 }
   890 
   891 RR*
   892 getdnsservers(int class)
   893 {
   894         return dnsservers(class);
   895 }