home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msvp98b1.lzh / MSNBTP.C < prev    next >
Text File  |  1993-05-14  |  9KB  |  264 lines

  1. /* File MSNBTP.C
  2.  * Bootp requestor
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1985, 1992, Trustees of Columbia University in the 
  6.  * City of New York.  Permission is granted to any individual or institution
  7.  * to use this software as long as it is not sold for profit.  This copyright
  8.  * notice must be retained.  This software may not be included in commercial
  9.  * products without written permission of Columbia University.
  10.  *
  11.  * Original version created by Erick Engelke of the University of
  12.  *  Waterloo, Waterloo, Ontario, Canada.
  13.  * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik, 
  14.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  15.  *
  16.  * Last edit
  17.  * 22 Feb 1992
  18.  *
  19.  *   BOOTP - Boot Protocol, RFCs 951 and 1048
  20.  *
  21.  *   These extensions get called if bootphost is set to an IP address or
  22.  *   to 0xffffffff.
  23.  *
  24.  */
  25.  
  26. #include "msntcp.h"
  27. #include "msnlib.h"
  28.  
  29. #define BOOTREQUEST     1    /* bootp.bp_op */
  30. #define BOOTREPLY    2
  31.  
  32. /*
  33.  * structure for send and receives
  34.  */
  35. typedef struct bootp {
  36.     byte     bp_op;        /* packet op code / message type. */
  37.     byte     bp_htype;    /* hardware address type, 1 = 10 mb ethernet */
  38.     byte     bp_hlen;    /* hardware address len, eg '6' for 10mb eth */
  39.     byte     bp_hops;    /* client sets to zero, optionally used by
  40.                    gateways in cross-gateway booting. */
  41.     longword bp_xid;    /* transaction ID, a random number */
  42.     word     bp_secs;    /* filled in by client, seconds elapsed since
  43.                    client started trying to boot. */
  44.     word     bp_spare;
  45.     longword bp_ciaddr;    /* client IP address filled in by client */
  46.                 /*  if known*/
  47.     longword bp_yiaddr;    /* 'your' (client) IP address
  48.                    filled by server if client doesn't know */
  49.     longword bp_siaddr;    /* server IP address returned in bootreply */
  50.     longword bp_giaddr;    /* gateway IP address,
  51.                    used in optional cross-gateway booting. */
  52.     byte     bp_chaddr[16];    /* client hardware address, filled by client */
  53.     byte     bp_sname[64];    /* optional server host name, null terminated*/
  54.  
  55.     byte     bp_file[128];    /* boot file name, null terminated string
  56.                    'generic' name or null in bootrequest,
  57.                    fully qualified directory-path
  58.                    name in bootreply. */
  59.     byte     bp_vend[ 64];    /* optional vendor-specific area */
  60. };
  61.  
  62.  
  63. extern struct bootp _bootp;
  64.  
  65. /*
  66.  * UDP port numbers, server and client.
  67.  */
  68. #define    IPPORT_BOOTPS    67
  69. #define    IPPORT_BOOTPC    68
  70.  
  71.  
  72. /******** the following is stolen from NCSA which came from CUTCP *********/
  73. /* I have not implemented these, but someone may wish to in the future so */
  74. /* I kept them around.                                                    */
  75. /**************************************************************************/
  76.  
  77. /*
  78.  * "vendor" data permitted for Stanford boot clients.
  79.  */
  80. struct vend {
  81.     byte      v_magic[4];    /* magic number */
  82.     longword v_flags;    /* flags/opcodes, etc. */
  83.     byte      v_unused[56];    /* currently unused */
  84. };
  85.  
  86. #define    VM_STANFORD    "STAN"    /* v_magic for Stanford */
  87. #define VM_RFC1048      "\x63\x82\x53\x63" /* magic cookie for BOOTP */
  88.                     /* high byte listed first */
  89.  
  90. /* v_flags values */
  91. #define    VF_PCBOOT    1    /* an IBMPC or Mac wants environment info */
  92. #define    VF_HELP        2        /* help me, I'm not registered */
  93. #define TAG_BOOTFILE_SIZE       13     /* tag used by vend fields rfc 1048 */
  94.  
  95. /* global variables */
  96. longword bootphost = 0xffffffffL;    /* broadcast */
  97. word bootptimeout = 30;
  98. word bootpon = 0;
  99.  
  100. extern longword set_timeout();
  101.  
  102.  
  103. /*
  104.  * dobootpc - Checks global variables bootptimeout, bootphost
  105.  *             if no host specified, the broadcast address
  106.  *             returns 0 on success and sets ip address
  107.  */
  108. int dobootp()
  109. {
  110.     udp_Socket bsock;
  111.     longword sendtimeout, bootptmo;
  112.     word magictimeout;
  113.     word len, templen;
  114.     struct bootp sendbootp;            /* outgoing data */
  115.     struct bootp bootp;                /* incoming data */
  116.     struct bootp register * sbp, * rbp;
  117.     int status;
  118.     longword xid;
  119.     byte *p, *t;
  120.     int dummy;
  121.  
  122.     if (pktdevclass == PD_SLIP) return (-1);
  123.  
  124.     sbp = &sendbootp;            /* registered addresses */
  125.     rbp = &bootp;
  126.     memset((byte *)sbp, 0, sizeof(struct bootp));
  127.     memset((byte *)rbp, 0, sizeof(struct bootp));
  128.  
  129.     outs("\r\n Requesting a Bootp server ");
  130.     /* We must get Waterloo TCP to use IP address 0 for sending */
  131.     xid = my_ip_addr;   /* a unique value coming from the ethernet card */
  132.     my_ip_addr = 0;
  133.  
  134.     if (udp_open(&bsock, IPPORT_BOOTPC, bootphost, IPPORT_BOOTPS, NULL) == 0)
  135.     {
  136.         outs("\n\r Unable to find a bootp server");
  137.         return (-1);
  138.     }
  139.  
  140.     bootptmo = set_timeout(bootptimeout);
  141.     magictimeout = (xid & 7) + 7;          /* between 7 and 14 seconds */
  142.  
  143.     sbp->bp_op = BOOTREQUEST;
  144.     sbp->bp_htype = pktdevclass;
  145.             /* Copy into position the Magic Number used by Bootp */
  146.     bcopy(VM_RFC1048, sbp->bp_vend, 4);        /* high byte first */
  147.  
  148.     if (pktdevclass == PD_ETHER) sbp->bp_hlen = 6;
  149.  
  150.     sbp->bp_xid = xid;
  151.     sbp->bp_secs = htons(1);
  152.  
  153.     bcopy(eth_addr, sbp->bp_chaddr, sizeof(eth_address));
  154.  
  155.     while (1) {
  156.     sock_fastwrite(&bsock, (byte *)sbp, sizeof(struct bootp));
  157.         sbp->bp_secs += magictimeout;            /* for next time */
  158.         sendtimeout = set_timeout(magictimeout += (xid > 5) & 7);
  159.     outs(".");                /* progress tics */
  160.         while (chk_timeout(sendtimeout) == 0) {
  161.             if (chk_timeout(bootptmo))
  162.                 {
  163.             outs(" Timed out, sorry");
  164.                     goto give_up;
  165.             }
  166.             sock_tick(&bsock, &status);
  167.             if (len = sock_dataready(&bsock)) {
  168.  
  169.                 /* got a response, lets consider it */
  170.                 templen = sock_fastread(&bsock, (byte *)rbp, 
  171.             sizeof(struct bootp));
  172.                 if (templen < sizeof(struct bootp)) {
  173.                     /* too small, not a bootp packet */
  174.             bcopy((byte *)rbp, 0, sizeof(struct bootp));
  175.                     continue;
  176.                 }
  177.  
  178.                 /* we must see if this is for us */
  179.         if (rbp->bp_xid != sbp->bp_xid) {
  180.             bcopy((byte *)rbp, 0, sizeof(struct bootp));
  181.                     continue;
  182.                 }
  183.  
  184.                 /* we must have found it */
  185.         my_ip_addr = ntohl(rbp->bp_yiaddr);
  186.  
  187.         if (*(long *)rbp->bp_vend == *(long *)sbp->bp_vend)
  188.             {            /* if magic cookies match */
  189.             /*RFC1048 compliant BOOTP vendor field */
  190.             /* Based heavily on NCSA Telnet BOOTP */
  191.             p = &rbp->bp_vend[4]; /* Point just after vendor field */
  192.  
  193.             while (*p != 255) {
  194.             switch(*p) {
  195.                           case 0: /* Nop Pad character */
  196.                                  p++;
  197.                                  break;
  198.                           case 1: /* Subnet Mask */
  199.                  sin_mask = ntohl(*(longword *)(&p[2]));
  200.                  /* and fall through */
  201.               case 2: /* Time offset */
  202.                  p += *(p+1) + 2;
  203.                  break;
  204.               case 3: /* gateways */
  205.                 for (len = 0; len < *(p+1); len += 4)
  206.                   arp_add_gateway(NULL,
  207.                      ntohl(*(longword*)(&p[2 + len])));
  208.                           /* and fall through */
  209.               case 4: /*time servers */
  210.                           /* fall through */
  211.                           case 5: /* IEN=116 name server */
  212.                                  p +=*(p+1)+2;
  213.                                  break;
  214.               case 6: /* Domain Name Servers (BIND) */
  215.                 for (len = 0; len < *(p+1); len += 4)
  216.                     add_server(&last_nameserver,
  217.                     MAX_NAMESERVERS, def_nameservers,
  218.                         ntohl(*(longword*)(&p[2 + len])));
  219.                         /* and fall through */
  220.               case 7: /* log server */
  221.                  p += *(p+1)+2;
  222.                  break;
  223.               case 8: /* cookie server */
  224.                  for (len = 0; len < *(p+1); len += 4)
  225. #ifdef KERMIT
  226.     ;    /* omit cookie server with Kermit */
  227. #else
  228.                      add_server(&last_cookie, MAX_COOKIES,
  229.                     cookie, ntohl(*(longword*)(&p[2+len])));
  230. #endif /* KERMIT */
  231.                  /* and fall through */
  232.                           case 9: /* lpr server */
  233.                           case 10: /* impress server */
  234.                           case 11: /* rlp server */
  235.                    p +=*(p+1)+2;
  236.                                    break;
  237.               case 12: /* Client Hostname */
  238.                   bcopy(&p[2], hostname, MAX_STRING);
  239.                   hostname[MAX_STRING - 1] = 0;
  240.                   p += *(p+1)+2;
  241.                                   break;
  242.                           case 255:
  243.                                    break;
  244.                           default:
  245.                                    p +=*(p+1)+2;
  246.                                    break;
  247.                         } /* end of switch */
  248.                      } /* end of while */
  249.                 }/* end of RFC_1048 if */
  250.                 goto give_up;
  251.             }
  252.         }
  253.     }
  254. give_up:
  255.     sock_close(&bsock);
  256.     if (my_ip_addr != 0) outs(" succeeded.\r\n");
  257.     return (my_ip_addr == 0);  /* return 0 on success */
  258.  
  259. sock_err:
  260.     /* major network error if UDP fails */
  261.     sock_close(&bsock);
  262.     return (-1);
  263. }
  264.