📄 bootp.c
字号:
/*
* Based on LiMon - BOOTP.
*
* Copyright 1994, 1995, 2000 Neil Russell.
* (See License)
* Copyright 2000 Roland Borde
* Copyright 2000 Paolo Scaffardi
*/
/* #define DEBUG_BOOTP_EXT 1 / * Debug received vendor fields */
#include <ppcboot.h>
#include <command.h>
#include "net.h"
#include "bootp.h"
#include "tftp.h"
#define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#define TIMEOUT 5 /* Seconds before trying BOOTP again */
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
ulong BootpID;
char BootFile[128];
int BootpTry;
static ulong lAddr;
static int BootpExtended (u8 *e);
static void BootpVendorFieldProcess(u8 *ext)
{
int size = *(ext+1) ;
#ifdef DEBUG_BOOTP_EXT
printf("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
#endif
switch (*ext) {
/* Fixed length fields */
case 1: /* Subnet mask */
if (NetOurSubnetMask == 0)
memcpy(&NetOurSubnetMask, ext+2, 4);
break;
case 2: /* Time offset - Not yet supported */
break;
/* Variable length fields */
case 3: /* Gateways list */
if (NetOurGatewayIP == 0) {
memcpy(&NetOurGatewayIP, ext+2, 4);
}
break;
case 4: /* Time server - Not yet supported */
break;
case 5: /* IEN-116 name server - Not yet supported */
break;
case 6: /* Domain name server - Not yet supported */
break;
case 7: /* Log server - Not yet supported */
break;
case 8: /* Cookie/Quote server - Not yet supported */
break;
case 9: /* LPR server - Not yet supported */
break;
case 10: /* Impress server - Not yet supported */
break;
case 11: /* RPL server - Not yet supported */
break;
case 12: /* Host name */
if (NetOurHostName[0] == 0) {
memcpy(&NetOurHostName, ext+2, size);
NetOurHostName[size] = 0 ;
}
break;
case 13: /* Boot file size */
if (NetBootFileSize == 0)
memcpy(&NetBootFileSize, ext+2, size);
break;
case 14: /* Merit dump file - Not yet supported */
break;
case 15: /* Domain name - Not yet supported */
break;
case 16: /* Swap server - Not yet supported */
break;
case 17: /* Root path */
if (NetOurRootPath[0] == 0) {
memcpy(&NetOurRootPath, ext+2, size);
NetOurRootPath[size] = 0 ;
}
break;
case 18: /* Extension path - Not yet supported */
/*
* This can be used to send the informations of the
* vendor area in another file that the client can
* access via TFTP.
*/
break;
/* IP host layer fields */
case 40: /* NIS Domain name */
if (NetOurNISDomain[0] == 0) {
memcpy(&NetOurNISDomain, ext+2, size);
NetOurNISDomain[size] = 0 ;
}
break;
/* Application layer fields */
case 43: /* Vendor specific info - Not yet supported */
/*
* Binary informations to exchange specific
* product information.
*/
break;
/* Reserved (custom) fields (128..254) */
}
}
static void BootpVendorProcess(u8 *ext, int size)
{
u8 *end = ext + size ;
#ifdef DEBUG_BOOTP_EXT
printf("[BOOTP] Checking extension (%d bytes)...\n", size);
#endif
while ((ext < end) && (*ext != 0xff)) {
if (*ext == 0) {
ext ++ ;
} else {
u8 *opt = ext ;
ext += ext[1] + 2 ;
if (ext <= end)
BootpVendorFieldProcess (opt) ;
}
}
#ifdef DEBUG_BOOTP_EXT
printf("[BOOTP] Received fields: \n");
if (NetOurSubnetMask) {
puts ("NetOurSubnetMask : ");
NetPrintIPaddr (NetOurSubnetMask);
putc('\n');
}
if (NetOurGatewaysIP[0]) {
puts ("NetOurGatewaysIP : ");
NetPrintIPaddr (NetOurGatewaysIP[0]);
putc('\n');
}
if (NetBootFileSize) {
printf("NetBootFileSize : %d\n", NetBootFileSize);
}
if (NetOurHostName[0]) {
printf("NetOurHostName : %s\n", NetOurHostName);
}
if (NetOurRootPath[0]) {
printf("NetOurRootPath : %s\n", NetOurRootPath);
}
if (NetOurNISDomain[0]) {
printf("NetOurNISDomain : %s\n", NetOurNISDomain);
}
#endif
}
/*
* Handle a BOOTP received packet.
*/
static void
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
Bootp_t * bp;
#ifdef DEBUG
printf("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
src, dest, len, sizeof (Bootp_t));
#endif /* DEBUG */
bp = (Bootp_t *)pkt;
if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
return;
if (len < sizeof (Bootp_t))
return;
if (bp->bp_op != OP_BOOTREPLY)
return;
if (bp->bp_htype != HWT_ETHER)
return;
if (bp->bp_hlen != HWL_ETHER)
return;
if (bp->bp_id != BootpID)
return;
/*
* Got a good BOOTP reply. Copy the data into our variables.
*/
NetOurIP = bp->bp_yiaddr;
NetServerIP = bp->bp_siaddr;
NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
memcpy(BootFile, bp->bp_file, sizeof bp->bp_file);
/* Retrieve extended informations (we must parse the vendor area) */
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
BootpVendorProcess(&bp->bp_vend[4], len);
NetSetTimeout(0, (thand_f *)0);
#ifdef DEBUG
printf("Got good BOOTP\n");
#endif /* DEBUG */
TftpStart(lAddr);
}
/*
* Timeout on BOOTP request. Try again, forever.
*/
static void
BootpTimeout(void)
{
BootpRequest(BootFile, lAddr);
}
/*
* Initialize BOOTP extension fields in the request.
*
* Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
*/
static int BootpExtended (u8 *e)
{
u8 *start = e ;
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
*e++ = 83;
*e++ = 99;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
*e++ = 1; /* Subnet mask request */
*e++ = 4;
e += 4;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
*e++ = 3; /* Default gateway request */
*e++ = 4;
e += 4;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
*e++ = 12; /* Host name request */
*e++ = 32;
e += 32;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
*e++ = 40; /* NIS Domain name request */
*e++ = 32;
e += 32;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
*e++ = 17; /* Boot path */
*e++ = 32;
e += 32;
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
*e++ = 13; /* Boot file size */
*e++ = 4;
e += 4;
#endif
*e = 255; /* End of the list */
return e - start ;
}
void
BootpRequest(char *fileName, ulong loadAdr)
{
volatile uchar *pkt;
Bootp_t *bp;
int ext_len;
lAddr = loadAdr;
printf("BOOTP broadcast %d\n", ++BootpTry);
pkt = NetTxPacket;
NetSetEther(pkt, NetBcastAddr, PROT_IP);
pkt += ETHER_HDR_SIZE;
NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t));
pkt += IP_HDR_SIZE;
bp = (Bootp_t *)pkt;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
bp->bp_ciaddr = 0;
bp->bp_yiaddr = 0;
bp->bp_siaddr = 0;
bp->bp_giaddr = 0;
NetCopyEther(bp->bp_chaddr, NetOurEther);
strcpy(bp->bp_file, fileName);
/* Request additional information from the BOOTP server */
ext_len = BootpExtended (bp->bp_vend) - sizeof(bp->bp_vend);
if (ext_len < 0) {
ext_len = 0;
}
/* store boot file name for repetitions in case of bootp timeout */
strcpy(BootFile, fileName);
/*
* Bootp ID is the lower 4 bytes of our ethernet address
* plus the current time in HZ.
*/
BootpID = ((ulong)NetOurEther[2] << 24)
| ((ulong)NetOurEther[3] << 16)
| ((ulong)NetOurEther[4] << 8)
| (ulong)NetOurEther[5];
BootpID += get_timer(0);
bp->bp_id = BootpID;
NetSendPacket(NetTxPacket, BOOTP_SIZE + ext_len);
NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
NetSetHandler(BootpHandler);
}
#endif /* CFG_CMD_NET */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -