home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / domhdr.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  7KB  |  294 lines

  1. /* Domain header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "domain.h"
  7.  
  8. static int dn_expand __ARGS((char *msg,char *eom,char *compressed,char *full,
  9.     int fullen));
  10. static char *getq __ARGS((struct rr **rrpp,char *msg,char *cp));
  11. static char *ntohrr __ARGS((struct rr **rrpp,char *msg,char *cp));
  12.  
  13. int
  14. ntohdomain(dhdr,bpp)
  15. register struct dhdr *dhdr;
  16. struct mbuf **bpp;
  17. {
  18.     int16 tmp,len;
  19.     register int16 i;
  20.     char *msg,*cp;
  21.     struct rr **rrpp;
  22.  
  23.     len = len_p(*bpp);
  24.     msg = mallocw(len);
  25.     pullup(bpp,msg,len);
  26.     memset((char *)dhdr,0,sizeof(*dhdr));
  27.  
  28.         dhdr->id = get16(&msg[0]);
  29.     tmp = get16(&msg[2]);
  30.     if(tmp & 0x8000)
  31.         dhdr->qr = 1;
  32.     dhdr->opcode = (tmp >> 11) & 0xf;
  33.     if(tmp & 0x0400)
  34.         dhdr->aa = 1;
  35.     if(tmp & 0x0200)
  36.         dhdr->tc = 1;
  37.     if(tmp & 0x0100)
  38.         dhdr->rd = 1;
  39.     if(tmp & 0x0080)
  40.         dhdr->ra = 1;
  41.     dhdr->rcode = tmp & 0xf;
  42.     dhdr->qdcount = get16(&msg[4]);
  43.     dhdr->ancount = get16(&msg[6]);
  44.     dhdr->nscount = get16(&msg[8]);
  45.     dhdr->arcount = get16(&msg[10]);
  46.  
  47.     /* Now parse the variable length sections */
  48.     cp = &msg[12];
  49.  
  50.     /* Question section */
  51.     rrpp = &dhdr->questions;
  52.     for(i=0;i<dhdr->qdcount;i++){
  53.         if((cp = getq(rrpp,msg,cp)) == NULLCHAR){
  54.             free(msg);
  55.             return -1;
  56.         }
  57.         (*rrpp)->source = RR_QUESTION;
  58.         rrpp = &(*rrpp)->next;
  59.     }
  60.     *rrpp = NULLRR;
  61.  
  62.     /* Answer section */
  63.     rrpp = &dhdr->answers;
  64.     for(i=0;i<dhdr->ancount;i++){
  65.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  66.             free(msg);
  67.             return -1;
  68.         }
  69.         (*rrpp)->source = RR_ANSWER;
  70.         rrpp = &(*rrpp)->next;
  71.     }
  72.     *rrpp = NULLRR;
  73.  
  74.     /* Name server (authority) section */
  75.     rrpp = &dhdr->authority;
  76.     for(i=0;i<dhdr->nscount;i++){
  77.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  78.             free(msg);
  79.             return -1;
  80.         }
  81.         (*rrpp)->source = RR_AUTHORITY;
  82.         rrpp = &(*rrpp)->next;
  83.     }
  84.     *rrpp = NULLRR;
  85.  
  86.     /* Additional section */
  87.     rrpp = &dhdr->additional;
  88.     for(i=0;i<dhdr->arcount;i++){
  89.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  90.             free(msg);
  91.             return -1;
  92.         }
  93.         (*rrpp)->source = RR_ADDITIONAL;
  94.         rrpp = &(*rrpp)->next;
  95.     }
  96.     *rrpp = NULLRR;
  97.     free(msg);
  98.     return 0;
  99. }
  100. static char *
  101. getq(rrpp,msg,cp)
  102. struct rr **rrpp;
  103. char *msg;
  104. char *cp;
  105. {
  106.     register struct rr *rrp;
  107.     int len;
  108.     char *name;
  109.  
  110.     *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  111.     name = mallocw(512);
  112.     len = dn_expand(msg,NULLCHAR,cp,name,512);
  113.     if(len == -1){
  114.         free(name);
  115.         return NULLCHAR;
  116.     }
  117.     cp += len;
  118.     rrp->name = strdup(name);
  119.     rrp->type = get16(cp);
  120.     cp += 2;
  121.     rrp->class = get16(cp);
  122.     cp += 2;
  123.     rrp->ttl = 0;
  124.     rrp->rdlength = 0;
  125.     free(name);
  126.     return cp;
  127. }
  128. /* Read a resource record from a domain message into a host structure */
  129. static char *
  130. ntohrr(rrpp,msg,cp)
  131. struct rr **rrpp; /* Where to allocate resource record structure */
  132. char *msg;    /* Pointer to beginning of domain message */
  133. char *cp;    /* Pointer to start of encoded RR record */
  134. {
  135.     register struct rr *rrp;
  136.     int len;
  137.     char *name;
  138.  
  139.     *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  140.     name = mallocw(512);
  141.     if((len = dn_expand(msg,NULLCHAR,cp,name,512)) == -1){
  142.         free(name);
  143.         return NULLCHAR;
  144.     }
  145.     cp += len;
  146.     rrp->name = strdup(name);
  147.     rrp->type = get16(cp);
  148.     cp += 2;
  149.     rrp->class = get16(cp);
  150.     cp+= 2;
  151.     rrp->ttl = get32(cp);
  152.     cp += 4;
  153.     rrp->rdlength = get16(cp);
  154.     cp += 2;
  155.     switch(rrp->type){
  156.     case TYPE_A:
  157.         /* Just read the address directly into the structure */
  158.         rrp->rdata.addr = get32(cp);
  159.         cp += 4;
  160.         break;
  161.     case TYPE_CNAME:
  162.     case TYPE_MB:
  163.     case TYPE_MG:
  164.     case TYPE_MR:
  165.     case TYPE_NS:
  166.     case TYPE_PTR:
  167.         /* These types all consist of a single domain name;
  168.          * convert it to ascii format
  169.          */
  170.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  171.         if(len == -1){
  172.             free(name);
  173.             return NULLCHAR;
  174.         }
  175.         rrp->rdata.name = strdup(name);
  176.         rrp->rdlength = strlen(name);
  177.         cp += len;
  178.         break;
  179.     case TYPE_HINFO:
  180.         rrp->rdata.hinfo.cpu = strdup(cp);
  181.         cp += strlen(cp) + 1;
  182.  
  183.         rrp->rdata.hinfo.os = strdup(cp);
  184.         cp += strlen(cp) + 1;
  185.         break;
  186.     case TYPE_MX:
  187.         rrp->rdata.mx.pref = get16(cp);
  188.         cp += 2;
  189.         /* Get domain name of exchanger */
  190.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  191.         if(len == -1){
  192.             free(name);
  193.             return NULLCHAR;
  194.         }
  195.         rrp->rdata.mx.exch = strdup(name);
  196.         cp += len;
  197.         break;
  198.     case TYPE_SOA:
  199.         /* Get domain name of name server */
  200.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  201.         if(len == -1){
  202.             free(name);
  203.             return NULLCHAR;
  204.         }
  205.         rrp->rdata.soa.mname = strdup(name);
  206.         cp += len;
  207.  
  208.         /* Get domain name of responsible person */
  209.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  210.         if(len == -1){
  211.             free(name);
  212.             return NULLCHAR;
  213.         }
  214.         rrp->rdata.soa.rname = strdup(name);
  215.         cp += len;
  216.  
  217.         rrp->rdata.soa.serial = get32(cp);
  218.         cp += 4;
  219.         rrp->rdata.soa.refresh = get32(cp);
  220.         cp += 4;
  221.         rrp->rdata.soa.retry = get32(cp);
  222.         cp += 4;
  223.         rrp->rdata.soa.expire = get32(cp);
  224.         cp += 4;
  225.         rrp->rdata.soa.minimum = get32(cp);
  226.         cp += 4;
  227.         break;
  228.     case TYPE_TXT:
  229.         /* Just stash */
  230.         rrp->rdata.data = mallocw(rrp->rdlength);
  231.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  232.         cp += rrp->rdlength;
  233.         break;
  234.     default:
  235.         /* Ignore */
  236.         cp += rrp->rdlength;
  237.         break;
  238.     }
  239.     free(name);
  240.     return cp;
  241. }
  242.  
  243. /* Convert a compressed domain name to the human-readable form */
  244. static int
  245. dn_expand(msg,eom,compressed,full,fullen)
  246. char *msg;        /* Complete domain message */
  247. char *eom;
  248. char *compressed;    /* Pointer to compressed name */
  249. char *full;        /* Pointer to result buffer */
  250. int fullen;        /* Length of same */
  251. {
  252.     unsigned int slen;    /* Length of current segment */
  253.     register char *cp;
  254.     int clen = 0;    /* Total length of compressed name */
  255.     int indirect = 0;    /* Set if indirection encountered */
  256.     int nseg = 0;        /* Total number of segments in name */
  257.  
  258.     cp = compressed;
  259.     for(;;){
  260.         slen = uchar(*cp++);    /* Length of this segment */
  261.         if(!indirect)
  262.             clen++;
  263.         if((slen & 0xc0) == 0xc0){
  264.             if(!indirect)
  265.                 clen++;
  266.             indirect = 1;
  267.             /* Follow indirection */
  268.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  269.             slen = uchar(*cp++);
  270.         }
  271.         if(slen == 0)    /* zero length == all done */
  272.             break;
  273.         fullen -= slen + 1;
  274.         if(fullen < 0)
  275.             return -1;
  276.         if(!indirect)
  277.             clen += slen;
  278.         while(slen-- != 0)
  279.             *full++ = *cp++;
  280.         *full++ = '.';
  281.         nseg++;
  282.     }
  283.     if(nseg == 0){
  284.         /* Root name; represent as single dot */
  285.         *full++ = '.';
  286.         fullen--;
  287.     }
  288.     *full++ = '\0';
  289.     fullen--;
  290.     return clen;    /* Length of compressed message */
  291. }
  292.  
  293.  
  294.