home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / ENGINE / DOMAIN.C < prev    next >
C/C++ Source or Header  |  1992-02-22  |  10KB  |  358 lines

  1. /*
  2. *    DOMAIN.C
  3. *
  4. *    Domain processing
  5. *
  6. *****************************************************************************
  7. *                                                                            *
  8. *     part of:                                                                *
  9. *     TCP/IP kernel for NCSA Telnet                                            *
  10. *     by Tim Krauskopf                                                        *
  11. *                                                                            *
  12. *     National Center for Supercomputing Applications                        *
  13. *     152 Computing Applications Building                                    *
  14. *     605 E. Springfield Ave.                                                *
  15. *     Champaign, IL  61820                                                    *
  16. *                                                                            *
  17. *****************************************************************************
  18. *
  19. *    Revision history:
  20. *
  21. *    10/87  Initial source release, Tim Krauskopf
  22. *    5/89    clean up for 2.3 release, JKM    
  23. *
  24. */
  25.  
  26. #define DOMAINMASTER
  27.  
  28. /*
  29.  *    Includes
  30.  */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <ctype.h>
  34. #include <string.h>
  35. #include "whatami.h"
  36. #include "hostform.h"
  37. #include "domain.h"
  38. #include "externs.h"
  39.  
  40. extern struct config Scon;        /* hardware configuration */
  41. extern struct machinfo *Sns;
  42. static int domwait=0;            /* is domain waiting for nameserver? */
  43.  
  44. /*
  45. *  data for domain name lookup
  46. */
  47. static struct useek {
  48.     struct dhead h;
  49.     uint8 x[DOMSIZE];
  50. } question;
  51.  
  52.  
  53. /* STATIC function declarations */
  54. static int packdom(char *dst,char *src);
  55. static int unpackdom(char *dst,char *src,char buf[]);
  56. static int ddextract(struct useek *,unsigned char *);
  57. static void sendom(char *,char *,int16 );
  58. static void qinit(void );
  59.  
  60. static void qinit(void )
  61. {
  62.     question.h.flags=intswap(DRD);
  63.     question.h.qdcount=intswap(1);
  64.     question.h.ancount=0;
  65.     question.h.nscount=0;
  66.     question.h.arcount=0;
  67. }
  68.  
  69. /*********************************************************************/
  70. /*  packdom
  71. *   pack a regular text string into a packed domain name, suitable
  72. *   for the name server.
  73. */
  74. static int packdom(char *dst,char *src)
  75. {
  76.     char *p,*q,*savedst;
  77.     int i,dotflag,defflag;
  78.  
  79.     p=src;
  80.     dotflag=defflag=0;
  81.     savedst=dst;
  82.     do {                            /* copy whole string */
  83.         *dst=0;
  84.         q=dst+1;
  85. /*
  86. *  copy the next label along, char by char until it meets a period or
  87. *  end of string.
  88. */
  89.         while(*p && (*p!='.')) 
  90.             *q++=*p++;
  91.         i=p-src;
  92.         if(i>0x3f)
  93.             return(-1);
  94.         *dst=(char)i;
  95.         *q=0;
  96.         if(*p) {                    /* update pointers */
  97.             dotflag=1;
  98.             src=++p;
  99.             dst=q;
  100.           }
  101.         else
  102.             if(!dotflag && !defflag && Scon.defdom) {
  103.                 p=Scon.defdom;        /* continue packing with default */
  104.                 defflag=1;
  105.                 src=p;
  106.                 dst=q;
  107.                 netposterr(801);        /* using default domain */
  108.               }
  109.       } while(*p);
  110.     q++;
  111.     return((int)(q-savedst));            /* length of packed string */
  112. }
  113.  
  114. /*********************************************************************/
  115. /*  unpackdom
  116. *  Unpack a compressed domain name that we have received from another
  117. *  host.  Handles pointers to continuation domain names -- buf is used
  118. *  as the base for the offset of any pointer which is present.
  119. *  returns the number of bytes at src which should be skipped over.
  120. *  Includes the NULL terminator in its length count.
  121. */
  122. static int unpackdom(char *dst,char *src,char buf[])
  123. {
  124.     int i,j,retval=0;
  125.     char *savesrc;
  126.  
  127.     savesrc=src;
  128.     while(*src) {
  129.         j=*src;
  130.         while((j & 0xC0)==0xC0) {
  131.             if(!retval)
  132.                 retval=src-savesrc+2;
  133.             src++;
  134.             src=&buf[(j & 0x3f)*256+*src];        /* pointer dereference */
  135.             j=*src;
  136.           }
  137.         src++;
  138.         for(i=0; i<(j & 0x3f) ; i++)
  139.             *dst++=*src++;
  140.         *dst++='.';
  141.       }
  142.     *(--dst)=0;                /* add terminator */
  143.     src++;                    /* account for terminator on src */
  144.     if(!retval)
  145.         retval=src-savesrc;
  146.     return(retval);
  147. }
  148.  
  149. /*********************************************************************/
  150. /*  sendom
  151. *   put together a domain lookup packet and send it
  152. *   uses port 53
  153. */
  154. static void sendom(char *s,char *towho,int16 num)
  155. {
  156.     uint16 i,ulen;
  157.     uint8 *psave,*p;
  158.  
  159.     psave=(uint8 *)question.x;
  160.     i=packdom(question.x,s);
  161. /*
  162. *  load the fields of the question structure a character at a time so
  163. *  that 68000 machines won't choke.
  164. */
  165.     p=&question.x[i];
  166.     *p++=0;                    /* high byte of qtype */
  167.     *p++=DTYPEA;            /* number is<256, so we know high byte=0 */
  168.     *p++=0;                    /* high byte of qclass */
  169.     *p++=DIN;                /* qtype is<256 */
  170.     question.h.ident=intswap(num);
  171.     ulen=sizeof(struct dhead)+(p-psave);
  172.     netusend(towho,53,997,(char *)&question,ulen);
  173. }
  174.  
  175. /**************************************************************************/
  176. /*  Sdomain
  177. *   DOMAIN based name lookup
  178. *   query a domain name server to get an IP number
  179. *    Returns the machine number of the machine record for future reference.
  180. *   Events generated will have this number tagged with them.
  181. *   Returns various negative numbers on error conditions.
  182. *     Checks for different port and save the port number
  183. */
  184. int Sdomain(char *mname)
  185. {
  186.     struct machinfo *m;
  187.     int new,i,port,pflag=0;
  188.  
  189.     if(!Sns)                             /* no nameserver, give up now */
  190.         return(-1);
  191.     while(*mname && *mname<33)            /* kill leading spaces */
  192.         mname++;
  193.     if(!(*mname))
  194.         return(-1);
  195.  
  196. /*
  197. *    Find out what port to open to
  198. */
  199.     for(i=0; (mname[i]!=' ') && (mname[i]!='#') && (mname[i]!='\0'); i++);
  200.  
  201.     if((mname[i]=='#') || (mname[i]==' ')) {
  202.         mname[i++]='\0';
  203.         new=i;
  204.         pflag=1;
  205.         for( ; (mname[i]!='\0') && isdigit(mname[i]) ; i++);
  206.  
  207.         if(mname[i]!='\0') 
  208.             pflag=0;
  209.         if(pflag) 
  210.             port=(unsigned int)atoi(&mname[new]);
  211.       }
  212.  
  213.     if(!(m=Smadd(mname)))
  214.         return(-1);                        /* adds the number to the machlist */
  215.     if(domwait<Scon.domto)
  216.         domwait=Scon.domto;                /* set the minimum timeout */
  217.     qinit();                            /* initialize some flag fields */
  218.     netulisten(997);                    /* pick a return port */
  219.     if(!m->hname)
  220.         m->hname=m->sname;                /* copy pointer to sname */
  221.     if(pflag)
  222.         m->port=port;        /* Put save port number */
  223.     sendom(m->hname,Sns->hostip,m->mno);    /* try UDP */
  224.     Stimerset(SCLASS,UDPTO,m->mno,domwait);    /* time out quickly first time */
  225.     m->mstat=UDPDOM;
  226.     return(m->mno);
  227. }
  228.  
  229. /*********************************************************************/
  230. /*  getdomain
  231. *   Look at the results to see if our DOMAIN request is ready.
  232. *   It may be a timeout, which requires another query.
  233. */
  234. int udpdom(void )
  235. {
  236.     struct machinfo *m;
  237.     int i,uret,num;
  238.     char *p;
  239.  
  240.     uret=neturead((char *)&question);
  241.     if(uret<0) {
  242. /*        netputevent(USERCLASS,DOMFAIL,-1);  */
  243.         return(-1);
  244.       }
  245.     num=intswap(question.h.ident);        /* get machine number */
  246. /*
  247. *  check to see if the necessary information was in the UDP response
  248. */
  249.     m=Slooknum(num);                /* get machine info record */
  250.     if(!m) {
  251.         netputevent(USERCLASS,DOMFAIL,num);
  252.         return(-1);
  253.       }
  254. /*
  255. *  got a response, so reset timeout value to recommended minimum
  256. */
  257.     domwait=Scon.domto;
  258.     i=ddextract(&question,m->hostip);
  259.     switch (i) {
  260.         case 3:                        /* name does not exist */
  261.             netposterr(802);
  262.             p=neterrstring(-1);
  263.             strncpy(p,m->hname,78);        /* what name */
  264.             netposterr(-1);
  265.             netputevent(USERCLASS,DOMFAIL,num);
  266.             Stimerunset(SCLASS,UDPTO,num);
  267.             return(-1);
  268.  
  269.         case 0:                        /* we found the IP number */
  270.             Stimerunset(SCLASS,UDPTO,num);
  271.             m->mstat=DOM;            /* mark that we have it from DOMAIN */
  272.             netputevent(USERCLASS,DOMOK,num);
  273.             return(0);
  274.  
  275.         case -1:                    /* strange return code from ddextract */
  276.             netposterr(803);
  277.             break;
  278.  
  279.         default:
  280.             netposterr(804);
  281.             break;
  282.       }
  283.     return(0);
  284. }
  285.  
  286. /**************************************************************************/
  287. /*  domto
  288. *   Handle time out for DOMAIN name lookup
  289. *   Retry as many times as recommended by config file
  290. */
  291. int domto(int num)
  292. {
  293.     struct machinfo *m;
  294.  
  295.     m=Slooknum(num);
  296.     if(!m)
  297.         return(-1);
  298.     if(m->mstat>UDPDOM+Scon.ndom) {    /* permanent timeout */
  299.         netputevent(USERCLASS,DOMFAIL,num);
  300.         return(-1);
  301.       }
  302.     else
  303.         m->mstat++;            /* one more timeout */
  304.     if(domwait<20)        /* exponential backoff */
  305.         domwait <<= 1;
  306.     Snewns();                /* rotate to next nameserver */
  307.     qinit();
  308.     netulisten(997);                    /* pick a return port */
  309.     sendom(m->hname,Sns->hostip,num);        /* try UDP */
  310.     Stimerset(SCLASS,UDPTO,num,domwait);    /* time out more slowly */
  311.     return(num);
  312. }
  313.  
  314. /*********************************************************************/
  315. /*  ddextract
  316. *   extract the ip number from a response message.
  317. *   returns the appropriate status code and if the ip number is available,
  318. *   copies it into mip
  319. */
  320. static int ddextract(struct useek *qp,uint8 *mip)
  321. {
  322.     uint16 i,j,nans,rcode;
  323.     struct rrpart *rrp;
  324.     uint8 *p,space[260];
  325.  
  326.     nans=intswap(qp->h.ancount);                /* number of answers */
  327.     rcode=DRCODE & intswap(qp->h.flags);        /* return code for this message*/
  328.     if(rcode>0)
  329.         return((int)rcode);
  330.     if(nans>0 && (intswap(qp->h.flags) & DQR)) {            /* response flag is set  and at least one answer */
  331.         p=(uint8 *)qp->x;                    /* where question starts */
  332.         i=unpackdom(space,p,(char *)qp);            /* unpack question name */
  333. /*  spec defines name then  QTYPE+QCLASS=4 bytes */
  334.         p+=i+4;
  335. /*
  336. *  at this point, there may be several answers.  We will take the first
  337. *  one which has an IP number.  There may be other types of answers that
  338. *  we want to support later.
  339. */
  340.         while(nans-->0) {                    /* look at each answer */
  341.             i=unpackdom(space,p,(char *)qp);            /* answer name to unpack */
  342. /*            n_puts(space);*/
  343.             p+=i;                        /* account for string */
  344.             rrp=(struct rrpart *)p;            /* resource record here */
  345. /*
  346. *  check things which might not align on 68000 chip one byte at a time
  347. */
  348.             if(!*p && *(p+1)==DTYPEA && !*(p+2) && *(p+3)==DIN) {        /* correct type and class */
  349.                 movebytes(mip,rrp->rdata,4);    /* save IP #         */
  350.                 return(0);                        /* successful return */
  351.               }
  352.             movebytes(&j,&rrp->rdlength,2);        /* 68000 alignment */
  353.             p+=10+intswap(j);                    /* length of rest of RR */
  354.           }
  355.       }
  356.     return(-1);                        /* generic failed to parse */
  357. }
  358.