home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msr313src.tar.gz
/
msr313src.tar
/
msnbtp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-12
|
8KB
|
249 lines
/* File MSNBTP.C
* Bootp requestor
*
* Copyright (C) 1991, University of Waterloo.
* Copyright (C) 1985, 1993, Trustees of Columbia University in the
* City of New York. Permission is granted to any individual or institution
* to use this software as long as it is not sold for profit. This copyright
* notice must be retained. This software may not be included in commercial
* products without written permission of Columbia University.
*
* Original version created by Erick Engelke of the University of
* Waterloo, Waterloo, Ontario, Canada.
* Adapted and modified for MS-DOS Kermit by Joe R. Doupnik,
* Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
*
* Last edit
* 22 May 1993 v3.13
*
* BOOTP - Boot Protocol, RFCs 951, 1048, and 1395
*
* These extensions get called if bootphost is set to an IP address or
* to 0xffffffff.
*
*/
#include "msntcp.h"
#include "msnlib.h"
/*
* structure for send and receives
*/
typedef struct bootp {
byte bp_op; /* packet op code / message type. */
byte bp_htype; /* hardware address type, 1 = 10 mb ethernet */
byte bp_hlen; /* hardware address len, eg '6' for 10mb eth */
byte bp_hops; /* client sets to zero, optionally used by
gateways in cross-gateway booting. */
longword bp_xid; /* transaction ID, a random number */
word bp_secs; /* filled in by client, seconds elapsed since
client started trying to boot. */
word bp_spare;
longword bp_ciaddr; /* client IP address filled in by client */
/* if known*/
longword bp_yiaddr; /* 'your' (client) IP address
filled by server if client doesn't know */
longword bp_siaddr; /* server IP address returned in bootreply */
longword bp_giaddr; /* gateway IP address,
used in optional cross-gateway booting. */
byte bp_chaddr[16]; /* client hardware address, filled by client */
byte bp_sname[64]; /* optional server host name, null terminated*/
byte bp_file[128]; /* boot file name, null terminated string
'generic' name or null in bootrequest,
fully qualified directory-path
name in bootreply. */
byte bp_vend[ 64]; /* optional vendor-specific area */
};
/* bootp.bp_op */
#define BOOTREQUEST 1
#define BOOTREPLY 2
/* UDP port numbers, server and client */
#define IPPORT_BOOTPS 67
#define IPPORT_BOOTPC 68
/******** the following is stolen from NCSA which came from CUTCP *********/
/* I have not implemented these, but someone may wish to in the future so */
/* I kept them around. */
/**************************************************************************/
/*
* "vendor" data permitted for Stanford boot clients.
*/
struct vend {
byte v_magic[4]; /* magic number */
longword v_flags; /* flags/opcodes, etc. */
byte v_unused[56]; /* currently unused */
};
#define VM_STANFORD "STAN" /* v_magic for Stanford */
#define VM_RFC1048 "\x63\x82\x53\x63" /* magic cookie for BOOTP */
/* high byte listed first */
/* v_flags values */
#define VF_PCBOOT 1 /* an IBMPC or Mac wants environment info */
#define VF_HELP 2 /* help me, I'm not registered */
#define TAG_BOOTFILE_SIZE 13 /* tag used by vend fields rfc 1048 */
/* global variables */
longword bootphost = 0xffffffffL; /* broadcast IP */
word bootptimeout = 30;
extern longword set_timeout();
extern word arp_hardware, MAC_len; /* media details from msnpdi.asm */
extern byte kdomain[]; /* our domain */
extern byte kbtpserver[]; /* IP of responding Bootp server */
/*
* dobootpc - Checks global variables bootptimeout, bootphost
* if no host specified, the broadcast address
* returns 0 on success and sets ip address
*/
int
dobootp(void)
{
udp_Socket bsock;
longword sendtimeout, bootptmo;
word magictimeout, len;
struct bootp sendbootp; /* outgoing data */
struct bootp bootp; /* incoming data */
struct bootp register * sbp, * rbp;
longword xid;
byte *p;
extern byte * hostname;
/* If we are running SLIP or ODI's SLIP_PPP which do not use
MAC level addresses use zeros for arp_hardware and MAC_len,
non-standard but perhaps useful to some cisco terminal servers */
sbp = &sendbootp; /* registered addresses */
rbp = &bootp;
memset((byte *)sbp, 0, sizeof(struct bootp));
memset((byte *)rbp, 0, sizeof(struct bootp));
outs("\r\n Requesting a Bootp server ");
xid = my_ip_addr; /* a unique value coming from the ethernet card */
my_ip_addr = 0; /* init our IP address to unknown */
if (udp_open(&bsock, IPPORT_BOOTPC, bootphost, IPPORT_BOOTPS) == 0)
{
outs("\n\r Unable to find a bootp server");
return (-1);
}
bootptmo = set_timeout(bootptimeout);
magictimeout = (word)((xid & 7) + 7); /* between 7 and 14 seconds */
sbp->bp_op = BOOTREQUEST;
sbp->bp_htype = (byte)(arp_hardware & 0xff);
/* Copy into position the Magic Number used by Bootp */
bcopy(VM_RFC1048, sbp->bp_vend, 4); /* high byte first */
sbp->bp_hlen = MAC_len; /* length of MAC address */
sbp->bp_xid = xid;
sbp->bp_secs = htons(1);
bcopy(eth_addr, sbp->bp_chaddr, MAC_len);
kbtpserver[0] = 0;
while (1 == 1) {
sock_fastwrite(&bsock, (byte *)sbp, sizeof(struct bootp));
sbp->bp_secs += magictimeout; /* for next time */
sendtimeout = set_timeout(magictimeout += (xid > 5) & 7);
outs("."); /* progress tics */
while (chk_timeout(sendtimeout) == 0)
{
if (chk_timeout(bootptmo))
{
outs(" Timed out, sorry");
sock_close(&bsock);
return (-1); /* fail */
}
if (tcp_tick(&bsock) == 0) /* major network error if UDP fails */
{
outs(" Network troubles, quitting");
sock_close(&bsock); /* quit now, with error */
return (-1);
}
if (sock_dataready(&bsock) == 0)
continue; /* no data */
/* got a response, lets consider it */
if ((sizeof(struct bootp) > sock_fastread(&bsock, (byte *)rbp,
sizeof(struct bootp))) || (rbp->bp_xid != sbp->bp_xid))
{
bcopy((byte *)rbp, 0, sizeof(struct bootp)); /*clear*/
continue; /* too small for bootp pkt, not for us */
}
if (*(long *)rbp->bp_vend != *(long *)sbp->bp_vend)
continue; /* magic cookies do not match */
my_ip_addr = ntohl(rbp->bp_yiaddr);
/* RFC1048 compliant BOOTP vendor field */
p = &rbp->bp_vend[4]; /* Point just after vendor field */
while (*p != 255)
switch(*p)
{
case 0: /* Nop Pad character */
p++;
break;
case 1: /* Subnet Mask */
sin_mask = ntohl(*(longword *)(&p[2]));
p += *(p+1) + 2;
break;
case 3: /* gateways */
for (len = 0; len < *(p+1); len += 4)
arp_add_gateway(NULL,
ntohl(*(longword*)(&p[2 + len])));
p += *(p+1) + 2;
break;
case 6: /* Domain Name Servers (BIND) */
for (len = 0; len < *(p+1); len += 4)
add_server(&last_nameserver,
MAX_NAMESERVERS, def_nameservers,
ntohl(*(longword*)(&p[2 + len])));
p += *(p+1) + 2;
break;
#ifndef KERMIT
case 8: /* cookie server */
for (len = 0; len < *(p+1); len += 4)
add_server(&last_cookie, MAX_COOKIES,
cookie,ntohl(*(longword*)(&p[2+len])));
p += *(p+1) + 2;
break;
#endif /* KERMIT */
case 12: /* our hostname, hopefully complete */
bcopyff(p+2, hostname, (int)(p[1] & 0xff));
hostname[(int)(p[1] & 0xff)] = '\0';
p += *(p+1) + 2;
break;
case 15: /* RFC-1395, Domain Name tag */
bcopyff(p+2, kdomain, (int)(p[1] & 0xff));
p += *(p+1) + 2;
break;
case 255:
break;
case 2: /* Time offset */
case 4: /* time servers */
case 5: /* IEN=116 name server */
case 7: /* log server */
case 9: /* lpr server */
case 10: /* impress server */
case 11: /* rlp server */
default:
p += *(p+1) + 2;
break;
} /* end of switch */
ntoa(kbtpserver, ntohl(bsock.hisaddr));
/* server IP to dotted decimal */
sock_close(&bsock);
return (my_ip_addr != 0? 0: -1);
} /* while (chk_timeout...*/
} /* while (1 == 1) */
}