/* bootp.c */ /* * includes */ #include #include #include "vtcpip.h" #include "dfault.h" #include "evtdef.h" #include "hstdef.h" #include "prodef.h" #include "prodat.h" #include "tcpdat.h" #include "btpdat.h" #include "bytprc.h" #include "cticks.h" /* * Bootp routines : from the Clarkson 2.2 version of NCSA Telnet. * Thanks to Brad Clements for implementing this! * * bootp routines - These routines are based on the stanford/clarkson * bootp code. Originally developed at Stanford University. * * Bootp is a UDP based protocol that determines the clients IP address and * gateway information etc. */ static struct bootp bpacket; static long bp_xid; static union { char junk_buff[1476]; /* TCPPKT - endrvr.mac */ struct bootp bpacket; } udp_data; /* * sendbp * * sends a bootp broadcast packet * this routine does not do the * initial setup of the bootp packet */ static int sendbp() { return(ntusend(broadip,IP_BPS,IP_BPC, &bpacket, sizeof(struct bootp))); } /* * bp_init * * initialize the bootp packet */ static void bp_init() { char *bpkt; int i; /* * get a unique transaction ID */ bp_xid = (int) cticks(NULL); bpkt = &bpacket; for(i=0; ibp_siaddr.addr; printf("BootP: Server IP [%d.%d.%d.%d] %s\n", c[0] & 0xFF, c[1] & 0xFF, c[2] & 0xFF, c[3] & 0xFF, bp->bp_sname); c = bp->bp_yiaddr.addr; printf("BootP: My IP [%d.%d.%d.%d]\n", c[0] & 0xFF, c[1] & 0xFF, c[2] & 0xFF, c[3] & 0xFF); c = bp->bp_giaddr.addr; printf("Bootp: Gateway IP [%d.%d.%d.%d]\n", c[0] & 0xFF, c[1] & 0xFF, c[2] & 0xFF, c[3] & 0xFF); /* * set my ip address */ ntstip(bp->bp_yiaddr.addr); movebytes(Scon.myipnum,bp->bp_yiaddr.addr,4); if(comparen(bp->bp_vend,VM_RFC1048,4)) { printf("\nBootP: RFC1048 Style BootP Packet Received\n"); c = bp->bp_vend+4; while((*c!=255)&&((c-bp->bp_vend)<64)) { switch(*c) { case 0: /* nop pad */ c++; break; case 1: /* subnet mask */ len = *(c+1); c += 2; movebytes(Scon.netmask,c, 4); ntstmask(Scon.netmask); printf("BootP: Subnet is [%d.%d.%d.%d]\n", *(c+0) & 0xFF, *(c+1) & 0xFF, *(c+2) & 0xFF, *(c+3) & 0xFF); c += len; Scon.havemask = 1; break; case 2: /* time offset */ c += *(c+1)+2; break; case 3: /* gateways */ len = *(c+1); items = len/4; c += 2; for(x=0; xhname); sp->gateway = gateway; movebytes(sp->hostip,c,4); sp->mstat = HFILE; c += 4; } break; case 4: /* time servers */ case 5: /* IEN=116 name server */ c += *(c+1)+2; Scon.nstype = 2; break; case 6: /* domain name server */ len = *(c+1); items = len/4; c += 2; for(x=0; xhname); sp->nameserv = nameserver; movebytes(sp->hostip,c,4); sp->mstat = HFILE; if(!Sns) Sns = sp; c += 4; } Scon.nstype = 1; break; case 7: /* log server */ case 8: /* cookie server */ case 9: /* lpr server */ case 10: /* impress server */ case 11: /* rlp server */ c += *(c+1)+2; break; case 12: /* client host name */ len = *(c+1); strncpy(Scon.me,c+2,len); Scon.me[len] = '\0'; if(strchr(Scon.me,'.')==NULL && Scon.defdom!=NULL) { Scon.me[len] = '.'; strcpy(&Scon.me[len+1],Scon.defdom); } printf("BootP: My name is %s\n", Scon.me); c += len+2; break; case 255: break; default: c += *(c+1)+2; break; } } } /* * if none were in the rfc1048 vend packet, * add the default gateway as an entry */ if(!gateway) { c = bp->bp_giaddr.addr; sprintf(message,"%d.%d.%d.%d", *(c+0) & 0xFF, *(c+1) & 0xFF, *(c+2) & 0xFF, *(c+3) & 0xFF); if(!(sp = Smadd(-1,message))) { printf("Out of Memory Adding Gateway-Smadd()\n"); return(-1); } gateway++; printf("BootP: Adding Gateway number %d IP %s\n", gateway,sp->hname); sp->gateway = gateway; movebytes(sp->hostip,c,4); sp->mstat = HFILE; } return(0); } /* * bootp * * main processing of bootp lookup request calls * sendbootp to send a bootp request, * sets up the udp listen socket etc, handles retries */ static char myip[]={0,0,0,0}; int bootp() { int x,y,delay; long start_time; register char *ea; register struct bootp *bp; ntstip(myip); bp_init(); bp = &udp_data.bpacket; ea = (char *) nnmyaddr; printf("Ethernet Physical Address: "); printf("%02x-%02x-%02x-%02x-%02x-%02x\n", *ea & 0xFF, *(ea+1) & 0xFF, *(ea+2) & 0xFF, *(ea+3) & 0xFF, *(ea+4) & 0xFF, *(ea+5) & 0xFF); printf("Sending BOOTPs\n"); /* * should only go around once */ while(nturead(udp_data.junk_buff)!=-1); for(x=0; xbp_xid == bp_xid && bp->bp_op == BPREPLY && comparen(bp->bp_chaddr,nnmyaddr,sizeof(nnmyaddr))) /* * got a valid reply */ break; } if(x==BTP_RETRIES) { /* * do some error processing */ printf("\nBOOTP Timeout. No Response from BOOTP server\n"); return(-1); } if(parse_bp(bp)) return(-1); return(0); }