home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / domhdr.c < prev    next >
C/C++ Source or Header  |  1991-03-07  |  7KB  |  300 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.         len = *cp++;
  181.         rrp->rdata.hinfo.cpu = mallocw(len+1);
  182.         memcpy( rrp->rdata.hinfo.cpu, cp, len );
  183.         rrp->rdata.hinfo.cpu[len] = '\0';
  184.         cp += len;
  185.  
  186.         len = *cp++;
  187.         rrp->rdata.hinfo.os = mallocw(len+1);
  188.         memcpy( rrp->rdata.hinfo.os, cp, len );
  189.         rrp->rdata.hinfo.os[len] = '\0';
  190.         cp += len;
  191.         break;
  192.     case TYPE_MX:
  193.         rrp->rdata.mx.pref = get16(cp);
  194.         cp += 2;
  195.         /* Get domain name of exchanger */
  196.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  197.         if(len == -1){
  198.             free(name);
  199.             return NULLCHAR;
  200.         }
  201.         rrp->rdata.mx.exch = strdup(name);
  202.         cp += len;
  203.         break;
  204.     case TYPE_SOA:
  205.         /* Get domain name of name server */
  206.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  207.         if(len == -1){
  208.             free(name);
  209.             return NULLCHAR;
  210.         }
  211.         rrp->rdata.soa.mname = strdup(name);
  212.         cp += len;
  213.  
  214.         /* Get domain name of responsible person */
  215.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  216.         if(len == -1){
  217.             free(name);
  218.             return NULLCHAR;
  219.         }
  220.         rrp->rdata.soa.rname = strdup(name);
  221.         cp += len;
  222.  
  223.         rrp->rdata.soa.serial = get32(cp);
  224.         cp += 4;
  225.         rrp->rdata.soa.refresh = get32(cp);
  226.         cp += 4;
  227.         rrp->rdata.soa.retry = get32(cp);
  228.         cp += 4;
  229.         rrp->rdata.soa.expire = get32(cp);
  230.         cp += 4;
  231.         rrp->rdata.soa.minimum = get32(cp);
  232.         cp += 4;
  233.         break;
  234.     case TYPE_TXT:
  235.         /* Just stash */
  236.         rrp->rdata.data = mallocw(rrp->rdlength);
  237.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  238.         cp += rrp->rdlength;
  239.         break;
  240.     default:
  241.         /* Ignore */
  242.         cp += rrp->rdlength;
  243.         break;
  244.     }
  245.     free(name);
  246.     return cp;
  247. }
  248.  
  249. /* Convert a compressed domain name to the human-readable form */
  250. static int
  251. dn_expand(msg,eom,compressed,full,fullen)
  252. char *msg;        /* Complete domain message */
  253. char *eom;
  254. char *compressed;    /* Pointer to compressed name */
  255. char *full;        /* Pointer to result buffer */
  256. int fullen;        /* Length of same */
  257. {
  258.     unsigned int slen;    /* Length of current segment */
  259.     register char *cp;
  260.     int clen = 0;    /* Total length of compressed name */
  261.     int indirect = 0;    /* Set if indirection encountered */
  262.     int nseg = 0;        /* Total number of segments in name */
  263.  
  264.     cp = compressed;
  265.     for(;;){
  266.         slen = uchar(*cp++);    /* Length of this segment */
  267.         if(!indirect)
  268.             clen++;
  269.         if((slen & 0xc0) == 0xc0){
  270.             if(!indirect)
  271.                 clen++;
  272.             indirect = 1;
  273.             /* Follow indirection */
  274.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  275.             slen = uchar(*cp++);
  276.         }
  277.         if(slen == 0)    /* zero length == all done */
  278.             break;
  279.         fullen -= slen + 1;
  280.         if(fullen < 0)
  281.             return -1;
  282.         if(!indirect)
  283.             clen += slen;
  284.         while(slen-- != 0)
  285.             *full++ = *cp++;
  286.         *full++ = '.';
  287.         nseg++;
  288.     }
  289.     if(nseg == 0){
  290.         /* Root name; represent as single dot */
  291.         *full++ = '.';
  292.         fullen--;
  293.     }
  294.     *full++ = '\0';
  295.     fullen--;
  296.     return clen;    /* Length of compressed message */
  297. }
  298.  
  299.  
  300.