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