HOST.C
上传用户:better800
上传日期:2022-06-13
资源大小:1853k
文件大小:15k
源码类别:

TCP/IP协议栈

开发平台:

DOS

  1. #include <copyright.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <tcp.h>
  5. /* domain name server protocol
  6.  *
  7.  * This portion of the code needs some major work.  I ported it (read STOLE IT)
  8.  * from NCSA and lost about half the code somewhere in the process.
  9.  *
  10.  * Note, this is a user level process.  We include <tcp.h> not <wattcp.h>
  11.  *
  12.  *  0.2 : Apr 24, 1991 - use substring portions of domain
  13.  *  0.1 : Mar 18, 1991 - improved the trailing domain list
  14.  *  0.0 : Feb 19, 1991 - pirated by Erick Engelke
  15.  * -1.0 :              - NCSA code
  16.  */
  17. /* These next 'constants' are loaded from WATTCP.CFG file */
  18. extern char *def_domain;
  19. extern char *loc_domain;       /* current subname to be used by the domain system */
  20. extern longword def_nameservers[ MAX_NAMESERVERS ];
  21. extern int _last_nameserver;
  22. extern word _domaintimeout = 0;
  23. static longword timeoutwhen;
  24. /*
  25. longword def_nameserver;
  26. longword def2_nameserver;
  27. */
  28. static udp_Socket *dom_sock;
  29. #define DOMSIZE 512 /* maximum domain message size to mess with */
  30. /*
  31.  *  Header for the DOMAIN queries
  32.  *  ALL OF THESE ARE BYTE SWAPPED QUANTITIES!
  33.  *  We are the poor slobs who are incompatible with the world's byte order
  34.  */
  35. struct dhead {
  36.     word ident, /* unique identifier */
  37. flags,
  38. qdcount, /* question section, # of entries */
  39. ancount, /* answers, how many */
  40. nscount, /* count of name server RRs */
  41. arcount; /* number of "additional" records */
  42. };
  43. /*
  44.  *  flag masks for the flags field of the DOMAIN header
  45.  */
  46. #define DQR 0x8000 /* query = 0, response = 1 */
  47. #define DOPCODE 0x7100 /* opcode, see below */
  48. #define DAA 0x0400 /* Authoritative answer */
  49. #define DTC 0x0200 /* Truncation, response was cut off at 512 */
  50. #define DRD 0x0100 /* Recursion desired */
  51. #define DRA 0x0080 /* Recursion available */
  52. #define DRCODE 0x000F /* response code, see below */
  53. /* opcode possible values: */
  54. #define DOPQUERY 0 /* a standard query */
  55. #define DOPIQ           1       /* an inverse query */
  56. #define DOPCQM 2 /* a completion query, multiple reply */
  57. #define DOPCQU 3      /* a completion query, single reply */
  58. /* the rest reserved for future */
  59. /* legal response codes: */
  60. #define DROK 0 /* okay response */
  61. #define DRFORM 1 /* format error */
  62. #define DRFAIL 2 /* their problem, server failed */
  63. #define DRNAME 3 /* name error, we know name doesn't exist */
  64. #define DRNOPE 4 /* no can do request */
  65. #define DRNOWAY 5 /* name server refusing to do request */
  66. #define DTYPEA 1 /* host address resource record (RR) */
  67. #define DTYPEPTR 12 /* a domain name ptr */
  68. #define DIN 1 /* ARPA internet class */
  69. #define DWILD 255 /* wildcard for several of the classifications */
  70. /*
  71.  *  a resource record is made up of a compressed domain name followed by
  72.  *  this structure.  All of these ints need to be byteswapped before use.
  73.  */
  74. struct rrpart {
  75.     word    rtype, /* resource record type = DTYPEA */
  76. rclass; /* RR class = DIN */
  77.     longword ttl; /* time-to-live, changed to 32 bits */
  78.     word rdlength; /* length of next field */
  79.     byte  rdata[DOMSIZE]; /* data field */
  80. };
  81. /*
  82.  *  data for domain name lookup
  83.  */
  84. static struct useek {
  85.     struct dhead h;
  86.     byte         x[DOMSIZE];
  87. } *question;
  88. /*********************************************************************/
  89. /*  packdom
  90. *   pack a regular text string into a packed domain name, suitable
  91. *   for the name server.
  92. *
  93. *   returns length
  94. */
  95. static packdom(dst,src)
  96. char *src,*dst;
  97. {
  98.     char *p,*q,*savedst;
  99.     int i,dotflag,defflag;
  100.     p = src;
  101.     dotflag = defflag = 0;
  102.     savedst = dst;
  103.     do { /* copy whole string */
  104. *dst = 0;
  105. q = dst + 1;
  106. while (*p && (*p != '.'))
  107.     *q++ = *p++;
  108. i = p - src;
  109. if (i > 0x3f)
  110.     return(-1);
  111. *dst = i;
  112. *q = 0;
  113. if (*p) { /* update pointers */
  114.     dotflag = 1;
  115.     src = ++p;
  116.     dst = q;
  117. }
  118. else if (!dotflag && !defflag && loc_domain) {
  119.     p = loc_domain; /* continue packing with default */
  120.     defflag = 1;
  121.     src = p;
  122.     dst = q;
  123. }
  124.     }
  125.     while (*p);
  126.     q++;
  127.     return(q-savedst); /* length of packed string */
  128. }
  129. /*********************************************************************/
  130. /*  unpackdom
  131. *  Unpack a compressed domain name that we have received from another
  132. *  host.  Handles pointers to continuation domain names -- buf is used
  133. *  as the base for the offset of any pointer which is present.
  134. *  returns the number of bytes at src which should be skipped over.
  135. *  Includes the NULL terminator in its length count.
  136. */
  137. static unpackdom(dst,src,buf)
  138. char *src,*dst,buf[];
  139. {
  140.     int i,j,retval;
  141.     char *savesrc;
  142.     savesrc = src;
  143.     retval = 0;
  144.     while (*src) {
  145. j = *src;
  146. while ((j & 0xC0) == 0xC0) {
  147.     if (!retval)
  148. retval = src-savesrc+2;
  149.     src++;
  150.     src = &buf[(j & 0x3f)*256+*src]; /* pointer dereference */
  151.     j = *src;
  152. }
  153. src++;
  154. for (i=0; i < (j & 0x3f) ; i++)
  155.     *dst++ = *src++;
  156. *dst++ = '.';
  157.     }
  158.     *(--dst) = 0; /* add terminator */
  159.     src++; /* account for terminator on src */
  160.     if (!retval)
  161. retval = src-savesrc;
  162.     return(retval);
  163. }
  164. /*********************************************************************/
  165. /*  sendom
  166. *   put together a domain lookup packet and send it
  167. *   uses port 53
  168. * num is used as identifier
  169. */
  170. static sendom(s,towho,num)
  171. char *s;
  172. longword towho;
  173. word num;
  174. {
  175.     word i,ulen;
  176.     byte *psave,*p;
  177.     psave = (byte*)&(question->x);
  178.     i = packdom(&(question->x),s);
  179.     p = &(question->x[i]);
  180.     *p++ = 0; /* high byte of qtype */
  181.     *p++ = DTYPEA; /* number is < 256, so we know high byte=0 */
  182.     *p++ = 0; /* high byte of qclass */
  183.     *p++ = DIN; /* qtype is < 256 */
  184.     question->h.ident = intel16(num);
  185.     ulen = sizeof(struct dhead)+(p-psave);
  186.     udp_open( dom_sock, 997, towho, 53, NULL );    /* divide err */
  187.     sock_write( dom_sock, question, ulen );
  188.     return( ulen);
  189. }
  190. /*********************************************************************/
  191. /*  senrdom
  192. *   put together a reverse domain lookup packet and send it
  193. *   uses port 53
  194. * num is used as identifier
  195. */
  196. static sendrdom(char *s, longword towhom, word num )
  197. {
  198.     word i,ulen;
  199.     byte *psave,*p;
  200.     psave = (byte*)&(question->x);
  201.     i = packdom(&(question->x),s);
  202.     p = &(question->x[i]);
  203.     *p++ = 0; /* high byte of qtype */
  204.     *p++ = DTYPEA;                      /* want host address */
  205.     *p++ = 0; /* high byte of qclass */
  206.     *p++ = DIN; /* qtype is < 256 */
  207.     question->h.ident = intel16(num);
  208.     ulen = sizeof(struct dhead)+(p-psave);
  209.     udp_open( dom_sock, 997, towho, 53, NULL );    /* divide err */
  210.     sock_write( dom_sock, question, ulen );
  211.     return( ulen);
  212. }
  213. static int countpaths(pathstring)
  214. char *pathstring;
  215. {
  216.     int     count = 0;
  217.     char    *p;
  218.     for(p=pathstring; (*p != 0) || (*(p+1) != 0); p++) {
  219. if(*p == 0)
  220.     count++;
  221.     }
  222.     return(++count);
  223. }
  224. static char *getpath(pathstring,whichone)
  225. char *pathstring;            /* the path list to search      */
  226. int   whichone;               /* which path to get, starts at 1 */
  227. {
  228.     char    *retval;
  229.     if(whichone > countpaths(pathstring))
  230. return(NULL);
  231.     whichone--;
  232.     for(retval = pathstring;whichone ; retval++ ) {
  233. if(*retval == 0)
  234.     whichone--;
  235.     }
  236.     return(retval);
  237. }
  238. /*********************************************************************/
  239. /*  ddextract
  240. *   extract the ip number from a response message.
  241. *   returns the appropriate status code and if the ip number is available,
  242. *   copies it into mip
  243. */
  244. static longword ddextract(qp,mip)
  245. struct useek *qp;
  246. unsigned char *mip;
  247. {
  248.     word i,j,nans,rcode;
  249.     struct rrpart *rrp;
  250.     byte *p,space[260];
  251.     nans = intel16(qp->h.ancount); /* number of answers */
  252.     rcode = DRCODE & intel16(qp->h.flags); /* return code for this message*/
  253.     if (rcode > 0)
  254. return(rcode);
  255.     if (nans > 0 && /* at least one answer */
  256.     (intel16(qp->h.flags) & DQR)) { /* response flag is set */
  257.     p = (byte *)&qp->x;                 /* where question starts */
  258. i = unpackdom(space,p,qp); /* unpack question name */
  259. /*  spec defines name then  QTYPE + QCLASS = 4 bytes */
  260. p += i+4;
  261. printf(" NAME : ? %sn", space );
  262.         
  263. /*
  264.  *  at this point, there may be several answers.  We will take the first
  265.  *  one which has an IP number.  There may be other types of answers that
  266.  *  we want to support later.
  267.  */
  268. while (nans-- > 0) { /* look at each answer */
  269.     i = unpackdom(space,p,qp); /* answer name to unpack */
  270.     /* n_puts(space);*/
  271.     p += i; /* account for string */
  272.     rrp = (struct rrpart *)p; /* resource record here */
  273.  /*
  274.   *  check things which might not align on 68000 chip one byte at a time
  275.   */
  276.     if (!*p && *(p+1) == DTYPEA &&  /* correct type and class */
  277.     !*(p+2) && *(p+3) == DIN) {
  278. movmem(rrp->rdata,mip,4); /* save IP #  */
  279. return(0); /* successful return */
  280.     }
  281.     movmem(&rrp->rdlength,&j,2); /* 68000 alignment */
  282.     p += 10+intel16(j); /* length of rest of RR */
  283. }
  284.     }
  285.     return(-1); /* generic failed to parse */
  286. }
  287. /*********************************************************************/
  288. /*  getdomain
  289. *   Look at the results to see if our DOMAIN request is ready.
  290. *   It may be a timeout, which requires another query.
  291. */
  292. static longword udpdom()
  293. {
  294.     int i,uret;
  295.     longword desired;
  296.     uret = sock_fastread(dom_sock, question, sizeof(struct useek ));
  297.     /* this does not happen */
  298.     if (uret < 0) {
  299. /* netputevent(USERCLASS,DOMFAIL,-1);  */
  300. return(-1);
  301.     }
  302.  /* num = intel16(question->h.ident); */     /* get machine number */
  303. /*
  304.  *  check to see if the necessary information was in the UDP response
  305.  */
  306.     i = ddextract(question, &desired);
  307.     switch (i) {
  308.         case 3: return(0); /* name does not exist */
  309.         case 0: return(intel(desired)); /* we found the IP number */
  310.         case -1:return( 0 ); /* strange return code from ddextract */
  311.         default:return( 0 );            /* dunno */
  312.     }
  313. }
  314. /**************************************************************************/
  315. /*  Sdomain
  316. *   DOMAIN based name lookup
  317. *   query a domain name server to get an IP number
  318. * Returns the machine number of the machine record for future reference.
  319. *   Events generated will have this number tagged with them.
  320. *   Returns various negative numbers on error conditions.
  321. *
  322. *   if adddom is nonzero, add default domain
  323. */
  324. static longword Sdomain(mname, adddom, nameserver, timedout )
  325. char *mname;
  326. int adddom;
  327. longword nameserver;
  328. int *timedout; /* set to 1 on timeout */
  329. {
  330.     char namebuff[512];
  331.     int isaname;
  332.     int domainsremaining;
  333.     int status, i;
  334.     longword response;
  335.     isaname = !isaddr( mname );
  336.     response = 0;
  337.     *timedout = 1;
  338.     if (!nameserver) { /* no nameserver, give up now */
  339. outs("No nameserver defined!nr");
  340. return(0);
  341.     }
  342.     while (*mname && *mname < 33) mname ++;   /* kill leading spaces */
  343.     if (!(*mname))
  344. return(0L);
  345.     question->h.flags = intel16(DRD);   /* use recursion */
  346.     question->h.qdcount = 0;
  347.     question->h.ancount = 0;
  348.     question->h.nscount = 0;
  349.     question->h.arcount = 0;
  350.     qinit(); /* initialize some flag fields */
  351.     strcpy( namebuff, mname );
  352.     if ( isaname ) {
  353.         /* forward lookup */
  354.         /* only add these things if we are doing a real name */
  355.         question->h.qdcount = intel16(1);
  356.         if ( adddom ) {
  357.             if(namebuff[strlen(namebuff)-1] != '.') {       /* if no trailing dot */
  358.                 if(loc_domain) {             /* there is a search list */
  359.                     domainsremaining = countpaths( loc_domain );
  360.                     strcat(namebuff,".");
  361.                     strcat(namebuff,getpath(loc_domain,1));
  362.                 }
  363.             } else
  364.                 namebuff[ strlen(namebuff)-1] = 0;  /* kill trailing dot */
  365.         }
  366.     } else {
  367.         /* reverse lookup */
  368.         question->h.ancount = intel16(1);
  369.     }
  370.     /*
  371.      * This is not terribly good, but it attempts to use a binary
  372.      * exponentially increasing delays.
  373.      */
  374.      for ( i = 2; i < 17; i *= 2) {
  375.         if ( isaname ) sendom(namebuff,nameserver, 0xf001);    /* try UDP */
  376.         else sendrdom( namebuff, nameserver, 0xf001 );
  377.         ip_timer_init( dom_sock, i );
  378.         do {
  379.             kbhit();
  380.             tcp_tick( dom_sock );
  381.             if (ip_timer_expired( dom_sock )) break;
  382.             if ( watcbroke ) {
  383.                 break;
  384.             }
  385.             if (chk_timeout( timeoutwhen ))
  386.                 break;
  387.             if ( sock_dataready( dom_sock )) *timedout = 0;
  388.         } while ( *timedout );
  389. if ( !*timedout ) break; /* got an answer */
  390.     }
  391.     if ( !*timedout )
  392. response = udpdom(); /* process the received data */
  393.     sock_close( dom_sock );
  394.     return( response );
  395. }
  396. /*
  397.  * nextdomain - given domain and count = 0,1,2,..., return next larger
  398.  * domain or NULL when no more are available
  399.  */
  400. static char *nextdomain( char *domain, int count )
  401. {
  402.     char *p;
  403.     int i;
  404.     p = domain;
  405.     for (i = 0; i < count; ++i) {
  406. p = strchr( p, '.' );
  407. if (!p) return( NULL );
  408. ++p;
  409.     }
  410.     return( p );
  411. }
  412. /*
  413.  * newresolve()
  414.  *  convert domain name -> address resolution.
  415.  *  returns 0 if name is unresolvable right now
  416.  */
  417. longword newresolve(name)
  418. char *name;
  419. {
  420.     longword ip_address, temp;
  421.     int count, i;
  422.     byte timeout[ MAX_NAMESERVERS ];
  423.     struct useek qp;        /* temp buffer */
  424.     udp_Socket ds;          /* temp buffer */
  425.     word oldhndlcbrk;
  426.     question = &qp;
  427.     dom_sock = &ds;
  428.     if (!name) return( 0 );
  429.     rip( name );
  430.     if (!_domaintimeout) _domaintimeout = sock_delay << 2;
  431.     timeoutwhen = set_timeout( _domaintimeout );
  432.     count = 0;
  433.     memset( &timeout, 0, sizeof( timeout ));
  434.     oldhndlcbrk = wathndlcbrk;
  435.     wathndlcbrk = 1;        /* enable special interrupt mode */
  436.     watcbroke = 0;
  437.     do {
  438. if (!(loc_domain = nextdomain( def_domain, count )))
  439. count = -1; /* use default name */
  440. for ( i = 0; i < _last_nameserver ; ++i ) {
  441.     if (!timeout[i])
  442. if (ip_address = Sdomain( name , count != -1 ,
  443. def_nameservers[i], &timeout[i] ))
  444.     break; /* got name, bail out of loop */
  445. }
  446. if (count == -1) break;
  447. count++;
  448.     } while (!ip_address);
  449.     watcbroke = 0;          /* always clean up */
  450.     wathndlcbrk = oldhndlcbrk;
  451.     return( ip_address );
  452. }
  453. main(int argc, char **argv )
  454. {
  455.     char *name;
  456.     longword host;
  457.     int status,i;
  458.     char buffer[ 20];
  459.     if (argc < 2) {
  460.         puts("HOST  hostname");
  461.         exit(3);
  462.     }
  463.     sock_init();
  464.     for ( i = 1 ; i < argc ; ++i ) {
  465.         if ((*argv[i] == '/') || (*argv[i] == '-' )) {
  466.         }
  467.         else {
  468.             name = strdup( argv[i] );
  469.             printf("resolving "%s"...", name );
  470.             host = newresolve( name );
  471.             printf("r");
  472.             clreol();
  473.         }
  474.     }
  475.     if ( host ) {
  476.         printf("r");
  477.         clreol();
  478.         printf("%s : %sn", name, inet_ntoa( buffer , host ));
  479.     }
  480.     exit( host ? 0 : 1 );
  481. }
  482. /* udpdom &&  ddextract(question, &desired); */