home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msr313src.zip / msnbtp.c < prev    next >
C/C++ Source or Header  |  1993-07-12  |  9KB  |  249 lines

  1. /* File MSNBTP.C
  2.  * Bootp requestor
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1985, 1993, 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 May 1993 v3.13
  18.  *
  19.  *   BOOTP - Boot Protocol, RFCs 951, 1048, and 1395
  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. /*
  30.  * structure for send and receives
  31.  */
  32. typedef struct bootp {
  33.     byte     bp_op;        /* packet op code / message type. */
  34.     byte     bp_htype;    /* hardware address type, 1 = 10 mb ethernet */
  35.     byte     bp_hlen;    /* hardware address len, eg '6' for 10mb eth */
  36.     byte     bp_hops;    /* client sets to zero, optionally used by
  37.                    gateways in cross-gateway booting. */
  38.     longword bp_xid;    /* transaction ID, a random number */
  39.     word     bp_secs;    /* filled in by client, seconds elapsed since
  40.                    client started trying to boot. */
  41.     word     bp_spare;
  42.     longword bp_ciaddr;    /* client IP address filled in by client */
  43.                 /*  if known*/
  44.     longword bp_yiaddr;    /* 'your' (client) IP address
  45.                    filled by server if client doesn't know */
  46.     longword bp_siaddr;    /* server IP address returned in bootreply */
  47.     longword bp_giaddr;    /* gateway IP address,
  48.                    used in optional cross-gateway booting. */
  49.     byte     bp_chaddr[16];    /* client hardware address, filled by client */
  50.     byte     bp_sname[64];    /* optional server host name, null terminated*/
  51.  
  52.     byte     bp_file[128];    /* boot file name, null terminated string
  53.                    'generic' name or null in bootrequest,
  54.                    fully qualified directory-path
  55.                    name in bootreply. */
  56.     byte     bp_vend[ 64];    /* optional vendor-specific area */
  57. };
  58.  
  59. /* bootp.bp_op */
  60. #define BOOTREQUEST     1
  61. #define BOOTREPLY    2
  62.  
  63. /* UDP port numbers, server and client */
  64. #define    IPPORT_BOOTPS    67
  65. #define    IPPORT_BOOTPC    68
  66.  
  67.  
  68. /******** the following is stolen from NCSA which came from CUTCP *********/
  69. /* I have not implemented these, but someone may wish to in the future so */
  70. /* I kept them around.                                                    */
  71. /**************************************************************************/
  72.  
  73. /*
  74.  * "vendor" data permitted for Stanford boot clients.
  75.  */
  76. struct vend {
  77.     byte      v_magic[4];    /* magic number */
  78.     longword v_flags;    /* flags/opcodes, etc. */
  79.     byte      v_unused[56];    /* currently unused */
  80. };
  81.  
  82. #define    VM_STANFORD    "STAN"    /* v_magic for Stanford */
  83. #define VM_RFC1048      "\x63\x82\x53\x63" /* magic cookie for BOOTP */
  84.                     /* high byte listed first */
  85. /* v_flags values */
  86. #define    VF_PCBOOT    1    /* an IBMPC or Mac wants environment info */
  87. #define    VF_HELP        2        /* help me, I'm not registered */
  88. #define TAG_BOOTFILE_SIZE       13     /* tag used by vend fields rfc 1048 */
  89.  
  90. /* global variables */
  91. longword bootphost = 0xffffffffL;    /* broadcast IP */
  92. word bootptimeout = 30;
  93. extern longword set_timeout();
  94. extern word arp_hardware, MAC_len;    /* media details from msnpdi.asm */
  95. extern byte kdomain[];            /* our domain */
  96. extern byte kbtpserver[];        /* IP of responding Bootp server */
  97.  
  98. /*
  99.  * dobootpc - Checks global variables bootptimeout, bootphost
  100.  *             if no host specified, the broadcast address
  101.  *             returns 0 on success and sets ip address
  102.  */
  103.  
  104. int 
  105. dobootp(void)
  106. {
  107.     udp_Socket bsock;
  108.     longword sendtimeout, bootptmo;
  109.     word magictimeout, len;
  110.     struct bootp sendbootp;                /* outgoing data */
  111.     struct bootp bootp;                /* incoming data */
  112.     struct bootp register * sbp, * rbp;
  113.     longword xid;
  114.     byte *p;
  115.     extern byte * hostname;
  116.  
  117.     /* If we are running SLIP or ODI's SLIP_PPP which do not use
  118.     MAC level addresses use zeros for arp_hardware and MAC_len,
  119.     non-standard but perhaps useful to some cisco terminal servers */
  120.  
  121.     sbp = &sendbootp;            /* registered addresses */
  122.     rbp = &bootp;
  123.     memset((byte *)sbp, 0, sizeof(struct bootp));
  124.     memset((byte *)rbp, 0, sizeof(struct bootp));
  125.  
  126.     outs("\r\n Requesting a Bootp server ");
  127.     xid = my_ip_addr;   /* a unique value coming from the ethernet card */
  128.     my_ip_addr = 0;    /* init our IP address to unknown */
  129.  
  130.     if (udp_open(&bsock, IPPORT_BOOTPC, bootphost, IPPORT_BOOTPS) == 0)
  131.         {
  132.             outs("\n\r Unable to find a bootp server");
  133.             return (-1);
  134.         }
  135.  
  136.     bootptmo = set_timeout(bootptimeout);
  137.     magictimeout = (word)((xid & 7) + 7);     /* between 7 and 14 seconds */
  138.  
  139.     sbp->bp_op = BOOTREQUEST;
  140.     sbp->bp_htype = (byte)(arp_hardware & 0xff);
  141.             /* Copy into position the Magic Number used by Bootp */
  142.     bcopy(VM_RFC1048, sbp->bp_vend, 4);        /* high byte first */
  143.  
  144.     sbp->bp_hlen = MAC_len;            /* length of MAC address */
  145.     sbp->bp_xid = xid;
  146.     sbp->bp_secs = htons(1);
  147.     bcopy(eth_addr, sbp->bp_chaddr, MAC_len);
  148.     kbtpserver[0] = 0;
  149.  
  150.     while (1 == 1) {
  151.     sock_fastwrite(&bsock, (byte *)sbp, sizeof(struct bootp));
  152.         sbp->bp_secs += magictimeout;            /* for next time */
  153.         sendtimeout = set_timeout(magictimeout += (xid > 5) & 7);
  154.     outs(".");                /* progress tics */
  155.         while (chk_timeout(sendtimeout) == 0)
  156.         {
  157.         if (chk_timeout(bootptmo))
  158.                 {
  159.             outs(" Timed out, sorry");
  160.              sock_close(&bsock);
  161.                 return (-1);        /* fail */
  162.             }
  163.  
  164.             if (tcp_tick(&bsock) == 0) /* major network error if UDP fails */
  165.             {
  166.             outs(" Network troubles, quitting");
  167.             sock_close(&bsock);    /* quit now, with error */
  168.             return (-1);
  169.             }
  170.  
  171.         if (sock_dataready(&bsock) == 0)
  172.                 continue;            /* no data */
  173.  
  174.                         /* got a response, lets consider it */
  175.         if ((sizeof(struct bootp) > sock_fastread(&bsock, (byte *)rbp,
  176.             sizeof(struct bootp))) || (rbp->bp_xid != sbp->bp_xid))
  177.             {
  178.             bcopy((byte *)rbp, 0, sizeof(struct bootp)); /*clear*/
  179.                     continue;    /* too small for bootp pkt, not for us */
  180.             }
  181.  
  182.         if (*(long *)rbp->bp_vend != *(long *)sbp->bp_vend)
  183.                 continue;  /* magic cookies do not match */
  184.  
  185.         my_ip_addr = ntohl(rbp->bp_yiaddr);
  186.                     /* RFC1048 compliant BOOTP vendor field */
  187.         p = &rbp->bp_vend[4]; /* Point just after vendor field */
  188.  
  189.         while (*p != 255)
  190.             switch(*p)
  191.               {
  192.                           case 0: /* Nop Pad character */
  193.                                  p++;
  194.                                  break;
  195.                           case 1: /* Subnet Mask */
  196.                  sin_mask = ntohl(*(longword *)(&p[2]));
  197.                  p += *(p+1) + 2;
  198.                  break;
  199.               case 3: /* gateways */
  200.                 for (len = 0; len < *(p+1); len += 4)
  201.                   arp_add_gateway(NULL,
  202.                      ntohl(*(longword*)(&p[2 + len])));
  203.                 p += *(p+1) + 2;
  204.                                 break;
  205.               case 6: /* Domain Name Servers (BIND) */
  206.                 for (len = 0; len < *(p+1); len += 4)
  207.                     add_server(&last_nameserver,
  208.                     MAX_NAMESERVERS, def_nameservers,
  209.                         ntohl(*(longword*)(&p[2 + len])));
  210.                 p += *(p+1) + 2;
  211.                 break;
  212. #ifndef KERMIT
  213.               case 8: /* cookie server */
  214.                 for (len = 0; len < *(p+1); len += 4)
  215.                     add_server(&last_cookie, MAX_COOKIES,
  216.                     cookie,ntohl(*(longword*)(&p[2+len])));
  217.                 p += *(p+1) + 2;
  218.                 break;
  219. #endif /* KERMIT */
  220.               case 12: /* our hostname, hopefully complete */
  221.                 bcopyff(p+2, hostname, (int)(p[1] & 0xff));
  222.                 hostname[(int)(p[1] & 0xff)] = '\0';
  223.                 p += *(p+1) + 2;
  224.                 break;
  225.               case 15: /* RFC-1395, Domain Name tag */
  226.                   bcopyff(p+2, kdomain, (int)(p[1] & 0xff));
  227.                 p += *(p+1) + 2;
  228.                 break;
  229.                           case 255:
  230.                 break;
  231.               case 2: /* Time offset */
  232.               case 4: /* time servers */
  233.                           case 5: /* IEN=116 name server */
  234.               case 7: /* log server */
  235.                           case 9: /* lpr server */
  236.                           case 10: /* impress server */
  237.                           case 11: /* rlp server */
  238.                           default:
  239.                   p += *(p+1) + 2;
  240.                 break;
  241.                           }         /* end of switch */
  242.         ntoa(kbtpserver, ntohl(bsock.hisaddr));
  243.                     /* server IP to dotted decimal */
  244.         sock_close(&bsock);
  245.             return (my_ip_addr != 0? 0: -1);
  246.             }            /* while (chk_timeout...*/
  247.               }                /* while (1 == 1)    */
  248. }
  249.