URI:
       tconvDNS2M.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tconvDNS2M.c (6895B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <ip.h>
            4 #include <bio.h>
            5 #include <ndb.h>
            6 #include "dns.h"
            7 
            8 /*
            9  *  a dictionary of domain names for packing messages
           10  */
           11 enum
           12 {
           13         Ndict=        64
           14 };
           15 typedef struct Dict        Dict;
           16 struct Dict
           17 {
           18         struct {
           19                 ushort        offset;                /* pointer to packed name in message */
           20                 char        *name;                /* pointer to unpacked name in buf */
           21         } x[Ndict];
           22         int n;                        /* size of dictionary */
           23         uchar *start;                /* start of packed message */
           24         char buf[4*1024];        /* buffer for unpacked names */
           25         char *ep;                /* first free char in buf */
           26 };
           27 
           28 #define NAME(x)                p = pname(p, ep, x, dp)
           29 #define SYMBOL(x)        p = psym(p, ep, x)
           30 #define STRING(x)        p = pstr(p, ep, x)
           31 #define BYTES(x, n)        p = pbytes(p, ep, x, n)
           32 #define USHORT(x)        p = pushort(p, ep, x)
           33 #define UCHAR(x)        p = puchar(p, ep, x)
           34 #define ULONG(x)        p = pulong(p, ep, x)
           35 #define V4ADDR(x)        p = pv4addr(p, ep, x)
           36 #define V6ADDR(x)        p = pv6addr(p, ep, x)
           37 
           38 static uchar*
           39 psym(uchar *p, uchar *ep, char *np)
           40 {
           41         int n;
           42 
           43         n = strlen(np);
           44         if(n >= Strlen)                        /* DNS maximum length string */
           45                 n = Strlen - 1;
           46         if(ep - p < n+1)                /* see if it fits in the buffer */
           47                 return ep+1;
           48         *p++ = n;
           49         memcpy(p, np, n);
           50         return p + n;
           51 }
           52 
           53 static uchar*
           54 pstr(uchar *p, uchar *ep, char *np)
           55 {
           56         int n;
           57 
           58         n = strlen(np);
           59         if(n >= Strlen)                        /* DNS maximum length string */
           60                 n = Strlen - 1;
           61         if(ep - p < n+1)                /* see if it fits in the buffer */
           62                 return ep+1;
           63         *p++ = n;
           64         memcpy(p, np, n);
           65         return p + n;
           66 }
           67 
           68 static uchar*
           69 pbytes(uchar *p, uchar *ep, uchar *np, int n)
           70 {
           71         if(ep - p < n)
           72                 return ep+1;
           73         memcpy(p, np, n);
           74         return p + n;
           75 }
           76 
           77 static uchar*
           78 puchar(uchar *p, uchar *ep, int val)
           79 {
           80         if(ep - p < 1)
           81                 return ep+1;
           82         *p++ = val;
           83         return p;
           84 }
           85 
           86 static uchar*
           87 pushort(uchar *p, uchar *ep, int val)
           88 {
           89         if(ep - p < 2)
           90                 return ep+1;
           91         *p++ = val>>8;
           92         *p++ = val;
           93         return p;
           94 }
           95 
           96 static uchar*
           97 pulong(uchar *p, uchar *ep, int val)
           98 {
           99         if(ep - p < 4)
          100                 return ep+1;
          101         *p++ = val>>24;
          102         *p++ = val>>16;
          103         *p++ = val>>8;
          104         *p++ = val;
          105         return p;
          106 }
          107 
          108 static uchar*
          109 pv4addr(uchar *p, uchar *ep, char *name)
          110 {
          111         uchar ip[IPaddrlen];
          112 
          113         if(ep - p < 4)
          114                 return ep+1;
          115         parseip(ip, name);
          116         v6tov4(p, ip);
          117         return p + 4;
          118 
          119 }
          120 
          121 static uchar*
          122 pv6addr(uchar *p, uchar *ep, char *name)
          123 {
          124         if(ep - p < IPaddrlen)
          125                 return ep+1;
          126         parseip(p, name);
          127         return p + IPaddrlen;
          128 
          129 }
          130 
          131 static uchar*
          132 pname(uchar *p, uchar *ep, char *np, Dict *dp)
          133 {
          134         char *cp;
          135         int i;
          136         char *last;                /* last component packed */
          137 
          138         if(strlen(np) >= Domlen)        /* make sure we don't exceed DNS limits */
          139                 return ep+1;
          140 
          141         last = 0;
          142         while(*np){
          143                 /* look through every component in the dictionary for a match */
          144                 for(i = 0; i < dp->n; i++){
          145                         if(strcmp(np, dp->x[i].name) == 0){
          146                                 if(ep - p < 2)
          147                                         return ep+1;
          148                                 *p++ = (dp->x[i].offset>>8) | 0xc0;
          149                                 *p++ = dp->x[i].offset;
          150                                 return p;
          151                         }
          152                 }
          153 
          154                 /* if there's room, enter this name in dictionary */
          155                 if(dp->n < Ndict){
          156                         if(last){
          157                                 /* the whole name is already in dp->buf */
          158                                 last = strchr(last, '.') + 1;
          159                                 dp->x[dp->n].name = last;
          160                                 dp->x[dp->n].offset = p - dp->start;
          161                                 dp->n++;
          162                         } else {
          163                                 /* add to dp->buf */
          164                                 i = strlen(np);
          165                                 if(dp->ep + i + 1 < &dp->buf[sizeof(dp->buf)]){
          166                                         strcpy(dp->ep, np);
          167                                         dp->x[dp->n].name = dp->ep;
          168                                         last = dp->ep;
          169                                         dp->x[dp->n].offset = p - dp->start;
          170                                         dp->ep += i + 1;
          171                                         dp->n++;
          172                                 }
          173                         }
          174                 }
          175 
          176                 /* put next component into message */
          177                 cp = strchr(np, '.');
          178                 if(cp == 0){
          179                         i = strlen(np);
          180                         cp = np + i;        /* point to null terminator */
          181                 } else {
          182                         i = cp - np;
          183                         cp++;                /* point past '.' */
          184                 }
          185                 if(ep-p < i+1)
          186                         return ep+1;
          187                 *p++ = i;                /* count of chars in label */
          188                 memcpy(p, np, i);
          189                 np = cp;
          190                 p += i;
          191         }
          192 
          193         if(p >= ep)
          194                 return ep+1;
          195         *p++ = 0;        /* add top level domain */
          196 
          197         return p;
          198 }
          199 
          200 static uchar*
          201 convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
          202 {
          203         uchar *lp, *data;
          204         int len, ttl;
          205         Txt *t;
          206 
          207         NAME(rp->owner->name);
          208         USHORT(rp->type);
          209         USHORT(rp->owner->class);
          210 
          211         /* egregious overuse of ttl (it's absolute time in the cache) */
          212         if(rp->db)
          213                 ttl = rp->ttl;
          214         else
          215                 ttl = rp->ttl - now;
          216         if(ttl < 0)
          217                 ttl = 0;
          218         ULONG(ttl);
          219 
          220         lp = p;                        /* leave room for the rdata length */
          221         p += 2;
          222         data = p;
          223 
          224         if(data >= ep)
          225                 return p+1;
          226 
          227         switch(rp->type){
          228         case Thinfo:
          229                 SYMBOL(rp->cpu->name);
          230                 SYMBOL(rp->os->name);
          231                 break;
          232         case Tcname:
          233         case Tmb:
          234         case Tmd:
          235         case Tmf:
          236         case Tns:
          237                 NAME(rp->host->name);
          238                 break;
          239         case Tmg:
          240         case Tmr:
          241                 NAME(rp->mb->name);
          242                 break;
          243         case Tminfo:
          244                 NAME(rp->rmb->name);
          245                 NAME(rp->mb->name);
          246                 break;
          247         case Tmx:
          248                 USHORT(rp->pref);
          249                 NAME(rp->host->name);
          250                 break;
          251         case Ta:
          252                 V4ADDR(rp->ip->name);
          253                 break;
          254         case Taaaa:
          255                 V6ADDR(rp->ip->name);
          256                 break;
          257         case Tptr:
          258                 NAME(rp->ptr->name);
          259                 break;
          260         case Tsoa:
          261                 NAME(rp->host->name);
          262                 NAME(rp->rmb->name);
          263                 ULONG(rp->soa->serial);
          264                 ULONG(rp->soa->refresh);
          265                 ULONG(rp->soa->retry);
          266                 ULONG(rp->soa->expire);
          267                 ULONG(rp->soa->minttl);
          268                 break;
          269         case Ttxt:
          270                 for(t = rp->txt; t != nil; t = t->next)
          271                         STRING(t->p);
          272                 break;
          273         case Tnull:
          274                 BYTES(rp->null->data, rp->null->dlen);
          275                 break;
          276         case Trp:
          277                 NAME(rp->rmb->name);
          278                 NAME(rp->rp->name);
          279                 break;
          280         case Tkey:
          281                 USHORT(rp->key->flags);
          282                 UCHAR(rp->key->proto);
          283                 UCHAR(rp->key->alg);
          284                 BYTES(rp->key->data, rp->key->dlen);
          285                 break;
          286         case Tsig:
          287                 USHORT(rp->sig->type);
          288                 UCHAR(rp->sig->alg);
          289                 UCHAR(rp->sig->labels);
          290                 ULONG(rp->sig->ttl);
          291                 ULONG(rp->sig->exp);
          292                 ULONG(rp->sig->incep);
          293                 USHORT(rp->sig->tag);
          294                 NAME(rp->sig->signer->name);
          295                 BYTES(rp->sig->data, rp->sig->dlen);
          296                 break;
          297         case Tcert:
          298                 USHORT(rp->cert->type);
          299                 USHORT(rp->cert->tag);
          300                 UCHAR(rp->cert->alg);
          301                 BYTES(rp->cert->data, rp->cert->dlen);
          302                 break;
          303         }
          304 
          305         /* stuff in the rdata section length */
          306         len = p - data;
          307         *lp++ = len >> 8;
          308         *lp = len;
          309 
          310         return p;
          311 }
          312 
          313 static uchar*
          314 convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
          315 {
          316         NAME(rp->owner->name);
          317         USHORT(rp->type);
          318         USHORT(rp->owner->class);
          319         return p;
          320 }
          321 
          322 static uchar*
          323 rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
          324 {
          325         uchar *np;
          326 
          327         *countp = 0;
          328         for(; rp && p < ep; rp = rp->next){
          329                 if(quest)
          330                         np = convQ2M(rp, p, ep, dp);
          331                 else
          332                         np = convRR2M(rp, p, ep, dp);
          333                 if(np > ep)
          334                         break;
          335                 p = np;
          336                 (*countp)++;
          337         }
          338         return p;
          339 }
          340 
          341 /*
          342  *  convert into a message
          343  */
          344 int
          345 convDNS2M(DNSmsg *m, uchar *buf, int len)
          346 {
          347         uchar *p, *ep, *np;
          348         Dict d;
          349 
          350         d.n = 0;
          351         d.start = buf;
          352         d.ep = d.buf;
          353         memset(buf, 0, len);
          354         m->qdcount = m->ancount = m->nscount = m->arcount = 0;
          355 
          356         /* first pack in the RR's so we can get real counts */
          357         p = buf + 12;
          358         ep = buf + len;
          359         p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
          360         p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
          361         p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
          362         p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
          363         if(p > ep)
          364                 return -1;
          365 
          366         /* now pack the rest */
          367         np = p;
          368         p = buf;
          369         ep = buf + len;
          370         USHORT(m->id);
          371         USHORT(m->flags);
          372         USHORT(m->qdcount);
          373         USHORT(m->ancount);
          374         USHORT(m->nscount);
          375         USHORT(m->arcount);
          376         if(p > ep)
          377                 return -1;
          378 
          379         return np - buf;
          380 }