123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209 |
-
- #include "etherboot.h"
- #include "console.h"
- #include "url.h"
- #include "proto.h"
- #include "resolv.h"
- #include "dev.h"
- #include "nic.h"
- #include "background.h"
- #include "elf.h"
-
- struct arprequest {
- uint16_t hwtype;
- uint16_t protocol;
- uint8_t hwlen;
- uint8_t protolen;
- uint16_t opcode;
- uint8_t shwaddr[6];
- uint8_t sipaddr[4];
- uint8_t thwaddr[6];
- uint8_t tipaddr[4];
- } PACKED;
-
- struct arptable_t arptable[MAX_ARP];
-
- struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
- static unsigned long netmask;
-
- char *hostname = "";
- int hostnamelen = 0;
- static uint32_t xid;
- unsigned char *end_of_rfc1533 = NULL;
- unsigned char *addparam;
- int addparamlen;
-
- #ifdef IMAGE_FREEBSD
- int freebsd_howto = 0;
- char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE];
- #endif
-
- static int vendorext_isvalid;
- static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68};
- static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
- static const in_addr zeroIP = { 0L };
-
- struct bootpd_t bootp_data;
-
- #ifdef NO_DHCP_SUPPORT
- static unsigned char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
- #else
- static int dhcp_reply;
- static in_addr dhcp_server = { 0L };
- static in_addr dhcp_addr = { 0L };
- static unsigned char rfc1533_cookie[] = { RFC1533_COOKIE };
- #define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)
- static unsigned char dhcp_machine_info[] = {
-
- RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,
-
- RFC1533_VENDOR_NIC_DEV_ID, 5, 0, 0, 0, 0, 0,
-
- RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,
- #ifdef EM_CURRENT_64
-
- RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,
- #undef DHCP_MACHINE_INFO_SIZE
- #define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))
- #endif
- };
- static const unsigned char dhcpdiscover[] = {
- RFC2132_MSG_TYPE,1,DHCPDISCOVER,
- RFC2132_MAX_SIZE,2,
- ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
- #ifdef PXE_DHCP_STRICT
- RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
- RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
- RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
- RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
- #else
- RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
- '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
- #endif
- #ifdef DHCP_CLIENT_ID
-
- RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
- DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
- #endif
- #ifdef DHCP_USER_CLASS
-
- RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
- #endif
- RFC2132_PARAM_LIST,
- #define DHCPDISCOVER_PARAMS_BASE 4
- #ifdef PXE_DHCP_STRICT
- #define DHCPDISCOVER_PARAMS_PXE ( 1 + 8 )
- #else
- #define DHCPDISCOVER_PARAMS_PXE 0
- #endif
- #define DHCPDISCOVER_PARAMS_DNS 1
- ( DHCPDISCOVER_PARAMS_BASE +
- DHCPDISCOVER_PARAMS_PXE+
- DHCPDISCOVER_PARAMS_DNS ),
- RFC1533_NETMASK,
- RFC1533_GATEWAY,
- RFC1533_HOSTNAME,
- RFC1533_VENDOR,
- #ifdef PXE_DHCP_STRICT
- ,RFC2132_VENDOR_CLASS_ID,
- RFC1533_VENDOR_PXE_OPT128,
- RFC1533_VENDOR_PXE_OPT129,
- RFC1533_VENDOR_PXE_OPT130,
- RFC1533_VENDOR_PXE_OPT131,
- RFC1533_VENDOR_PXE_OPT132,
- RFC1533_VENDOR_PXE_OPT133,
- RFC1533_VENDOR_PXE_OPT134,
- RFC1533_VENDOR_PXE_OPT135,
- #endif
- RFC1533_DNS
- };
- static const unsigned char dhcprequest [] = {
- RFC2132_MSG_TYPE,1,DHCPREQUEST,
- RFC2132_SRV_ID,4,0,0,0,0,
- RFC2132_REQ_ADDR,4,0,0,0,0,
- RFC2132_MAX_SIZE,2,
- ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
- #ifdef PXE_DHCP_STRICT
- RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
- RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
- RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
- RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
- #else
- RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',
- '-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',
- #endif
- #ifdef DHCP_CLIENT_ID
-
- RFC2132_CLIENT_ID, ( DHCP_CLIENT_ID_LEN + 1 ),
- DHCP_CLIENT_ID_TYPE, DHCP_CLIENT_ID,
- #endif
- #ifdef DHCP_USER_CLASS
-
- RFC3004_USER_CLASS, DHCP_USER_CLASS_LEN, DHCP_USER_CLASS,
- #endif
-
- RFC2132_PARAM_LIST,
- #define DHCPREQUEST_PARAMS_BASE 5
- #ifdef PXE_DHCP_STRICT
- #define DHCPREQUEST_PARAMS_PXE 1
- #define DHCPREQUEST_PARAMS_VENDOR_PXE 8
- #define DHCPREQUEST_PARAMS_VENDOR_EB 0
- #else
- #define DHCPREQUEST_PARAMS_PXE 0
- #define DHCPREQUEST_PARAMS_VENDOR_PXE 0
- #define DHCPREQUEST_PARAMS_VENDOR_EB 4
- #endif
- #ifdef IMAGE_FREEBSD
- #define DHCPREQUEST_PARAMS_FREEBSD 2
- #else
- #define DHCPREQUEST_PARAMS_FREEBSD 0
- #endif
- #define DHCPREQUEST_PARAMS_DNS 1
- ( DHCPREQUEST_PARAMS_BASE +
- DHCPREQUEST_PARAMS_PXE +
- DHCPREQUEST_PARAMS_VENDOR_PXE +
- DHCPREQUEST_PARAMS_VENDOR_EB +
- DHCPREQUEST_PARAMS_DNS +
- DHCPREQUEST_PARAMS_FREEBSD ),
-
- RFC1533_NETMASK,
- RFC1533_GATEWAY,
- RFC1533_HOSTNAME,
- RFC1533_VENDOR,
- RFC1533_ROOTPATH,
- #ifndef PXE_DHCP_STRICT
-
- RFC1533_VENDOR_MAGIC,
- RFC1533_VENDOR_ADDPARM,
- RFC1533_VENDOR_ETHDEV,
- RFC1533_VENDOR_ETHERBOOT_ENCAP,
- #endif
- #ifdef IMAGE_FREEBSD
-
- RFC1533_VENDOR_HOWTO,
- RFC1533_VENDOR_KERNEL_ENV,
- #endif
-
- RFC1533_DNS,
- #ifdef PXE_DHCP_STRICT
- RFC2132_VENDOR_CLASS_ID,
- RFC1533_VENDOR_PXE_OPT128,
- RFC1533_VENDOR_PXE_OPT129,
- RFC1533_VENDOR_PXE_OPT130,
- RFC1533_VENDOR_PXE_OPT131,
- RFC1533_VENDOR_PXE_OPT132,
- RFC1533_VENDOR_PXE_OPT133,
- RFC1533_VENDOR_PXE_OPT134,
- RFC1533_VENDOR_PXE_OPT135,
- #endif
- };
- #ifdef PXE_EXPORT
- static const unsigned char proxydhcprequest [] = {
- RFC2132_MSG_TYPE,1,DHCPREQUEST,
- RFC2132_MAX_SIZE,2,
- ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
- #ifdef PXE_DHCP_STRICT
- RFC3679_PXE_CLIENT_UUID,RFC3679_PXE_CLIENT_UUID_LENGTH,RFC3679_PXE_CLIENT_UUID_DEFAULT,
- RFC3679_PXE_CLIENT_ARCH,RFC3679_PXE_CLIENT_ARCH_LENGTH,RFC3679_PXE_CLIENT_ARCH_IAX86PC,
- RFC3679_PXE_CLIENT_NDI, RFC3679_PXE_CLIENT_NDI_LENGTH, RFC3679_PXE_CLIENT_NDI_21,
- RFC2132_VENDOR_CLASS_ID,RFC2132_VENDOR_CLASS_ID_PXE_LENGTH,RFC2132_VENDOR_CLASS_ID_PXE,
- #endif
- };
- #endif
-
- #ifdef REQUIRE_VCI_ETHERBOOT
- int vci_etherboot;
- #endif
- #endif
-
- #ifdef RARP_NOT_BOOTP
- static int rarp(void);
- #else
- static int bootp(void);
- #endif
-
-
-
- static int nic_configure ( struct type_dev *type_dev ) {
- struct nic *nic = ( struct nic * ) type_dev;
- int server_found;
-
- if ( ! nic->nic_op->connect ( nic ) ) {
- printf ( "No connection to network\n" );
- return 0;
- }
-
-
- #ifdef RARP_NOT_BOOTP
- printf("Searching for server (RARP)...");
- #else
- #ifndef NO_DHCP_SUPPORT
- printf("Searching for server (DHCP)...");
- #else
- printf("Searching for server (BOOTP)...");
- #endif
- #endif
-
- #ifdef RARP_NOT_BOOTP
- server_found = rarp();
- #else
- server_found = bootp();
- #endif
- if (!server_found) {
- printf("No Server found\n");
- return 0;
- }
-
- printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
- #ifndef NO_DHCP_SUPPORT
- printf(", DHCP: %@", dhcp_server );
- #ifdef PXE_EXPORT
- if (arptable[ARP_PROXYDHCP].ipaddr.s_addr)
- printf(" (& %@)",
- arptable[ARP_PROXYDHCP].ipaddr.s_addr);
- #endif
- #endif
- printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr);
- if (bootp_data.bootp_reply.bp_giaddr.s_addr)
- printf(", Relay: %@", bootp_data.bootp_reply.bp_giaddr.s_addr);
- if (arptable[ARP_GATEWAY].ipaddr.s_addr)
- printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);
- if (arptable[ARP_NAMESERVER].ipaddr.s_addr)
- printf(", Nameserver %@", arptable[ARP_NAMESERVER].ipaddr.s_addr);
- putchar('\n');
-
- #ifdef MDEBUG
- printf("\n=>>"); getchar();
- #endif
-
- return 1;
- }
-
-
-
- int download_url ( char *url, struct buffer *buffer ) {
- struct protocol *proto;
- struct sockaddr_in server;
- char *filename;
-
- printf ( "Loading %s\n", url );
-
-
- if ( ! parse_url ( url, &proto, &server, &filename ) ) {
- DBG ( "Unusable URL %s\n", url );
- return 0;
- }
-
-
- return proto->load ( url, &server, filename, buffer );
- }
-
-
-
-
-
- static int nic_load ( struct type_dev *type_dev, struct buffer *buffer ) {
- char *kernel;
-
-
- kernel = KERNEL_BUF[0] == '\0' ?
- #ifdef DEFAULT_BOOTFILE
- DEFAULT_BOOTFILE
- #else
- NULL
- #endif
- : KERNEL_BUF;
- #ifdef ZPXE_SUFFIX_STRIP
- {
- int i = 0;
- while (kernel[i++]);
- if(i > 5) {
- if(kernel[i - 6] == '.' &&
- kernel[i - 5] == 'z' &&
- kernel[i - 4] == 'p' &&
- kernel[i - 3] == 'x' &&
- kernel[i - 2] == 'e') {
- printf("Trimming .zpxe extension\n");
- kernel[i - 6] = 0;
- }
- }
- }
- #endif
- if ( kernel ) {
- return download_url ( kernel, buffer );
- } else {
- printf("No filename\n");
- }
- return 0;
- }
-
- void nic_disable ( struct nic *nic __unused ) {
- #ifdef MULTICAST_LEVEL2
- int i;
- for(i = 0; i < MAX_IGMP; i++) {
- leave_group(i);
- }
- #endif
- }
-
- static char * nic_describe_device ( struct type_dev *type_dev ) {
- struct nic *nic = ( struct nic * ) type_dev;
- static char nic_description[] = "MAC 00:00:00:00:00:00";
-
- sprintf ( nic_description + 4, "%!", nic->node_addr );
- return nic_description;
- }
-
-
- struct type_driver nic_driver = {
- .name = "NIC",
- .type_dev = ( struct type_dev * ) &nic,
- .describe_device = nic_describe_device,
- .configure = nic_configure,
- .load = nic_load,
- };
-
-
- static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
-
- struct nic nic = {
- .node_addr = arptable[ARP_CLIENT].node,
- .packet = packet + ETH_DATA_ALIGN,
- };
-
-
-
- int dummy_connect ( struct nic *nic __unused ) {
- return 1;
- }
-
- void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
- return;
- }
-
-
- static inline unsigned long default_netmask(void)
- {
- int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
- if (net <= 127)
- return(htonl(0xff000000));
- else if (net < 192)
- return(htonl(0xffff0000));
- else
- return(htonl(0xffffff00));
- }
-
-
- static int await_arp(int ival, void *ptr,
- unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused,
- struct tcphdr *tcp __unused)
- {
- struct arprequest *arpreply;
- if (ptype != ETH_P_ARP)
- return 0;
- if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
- return 0;
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
-
- if (arpreply->opcode != htons(ARPOP_REPLY))
- return 0;
- if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)
- return 0;
- memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);
- return 1;
- }
-
- int ip_transmit(int len, const void *buf)
- {
- unsigned long destip;
- struct iphdr *ip;
- struct arprequest arpreq;
- int arpentry, i;
- int retry;
-
- ip = (struct iphdr *)buf;
- destip = ip->dest.s_addr;
- if (destip == IP_BROADCAST) {
- eth_transmit(broadcast, ETH_P_IP, len, buf);
- } else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
- unsigned char multicast[6];
- unsigned long hdestip;
- hdestip = ntohl(destip);
- multicast[0] = 0x01;
- multicast[1] = 0x00;
- multicast[2] = 0x5e;
- multicast[3] = (hdestip >> 16) & 0x7;
- multicast[4] = (hdestip >> 8) & 0xff;
- multicast[5] = hdestip & 0xff;
- eth_transmit(multicast, ETH_P_IP, len, buf);
- } else {
- if (((destip & netmask) !=
- (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
- arptable[ARP_GATEWAY].ipaddr.s_addr)
- destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
- for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
- if (arptable[arpentry].ipaddr.s_addr == destip) break;
- if (arpentry == MAX_ARP) {
- printf("%@ is not in my arp table!\n", destip);
- return(0);
- }
- for (i = 0; i < ETH_ALEN; i++)
- if (arptable[arpentry].node[i])
- break;
- if (i == ETH_ALEN) {
- arpreq.hwtype = htons(1);
- arpreq.protocol = htons(ETH_P_IP);
- arpreq.hwlen = ETH_ALEN;
- arpreq.protolen = 4;
- arpreq.opcode = htons(ARPOP_REQUEST);
- memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
- memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
- memset(arpreq.thwaddr, 0, ETH_ALEN);
- memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
- for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
- long timeout;
- eth_transmit(broadcast, ETH_P_ARP, sizeof(arpreq),
- &arpreq);
- timeout = rfc2131_sleep_interval(TIMEOUT, retry);
- if (await_reply(await_arp, arpentry,
- arpreq.tipaddr, timeout)) goto xmit;
- }
- return(0);
- }
- xmit:
- eth_transmit(arptable[arpentry].node, ETH_P_IP, len, buf);
- }
- return 1;
- }
-
- void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,
- int len, const void *buf)
- {
- struct iphdr *ip;
- ip = (struct iphdr *)buf;
- ip->verhdrlen = 0x45;
- ip->verhdrlen += (option_len/4);
- ip->service = 0;
- ip->len = htons(len);
- ip->ident = 0;
- ip->frags = 0;
- ip->ttl = ttl;
- ip->protocol = protocol;
- ip->chksum = 0;
- ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
- ip->dest.s_addr = destip;
- ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);
- }
-
- void build_udp_hdr(unsigned long destip,
- unsigned int srcsock, unsigned int destsock, int ttl,
- int len, const void *buf)
- {
- struct iphdr *ip;
- struct udphdr *udp;
- ip = (struct iphdr *)buf;
- build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);
- udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));
- udp->src = htons(srcsock);
- udp->dest = htons(destsock);
- udp->len = htons(len - sizeof(struct iphdr));
- udp->chksum = 0;
- if ((udp->chksum = tcpudpchksum(ip)) == 0)
- udp->chksum = 0xffff;
- }
-
-
- int udp_transmit(unsigned long destip, unsigned int srcsock,
- unsigned int destsock, int len, const void *buf)
- {
- build_udp_hdr(destip, srcsock, destsock, 60, len, buf);
- return ip_transmit(len, buf);
- }
-
-
-
- static int await_qdrain(int ival __unused, void *ptr __unused,
- unsigned short ptype __unused,
- struct iphdr *ip __unused, struct udphdr *udp __unused,
- struct tcphdr *tcp __unused)
- {
- return 0;
- }
-
- void rx_qdrain(void)
- {
-
-
- await_reply(await_qdrain, 0, NULL, 0);
- }
-
- #ifdef RARP_NOT_BOOTP
-
- static int await_rarp(int ival, void *ptr,
- unsigned short ptype, struct iphdr *ip, struct udphdr *udp,
- struct tcphdr *tcp __unused)
- {
- struct arprequest *arpreply;
- if (ptype != ETH_P_RARP)
- return 0;
- if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
- return 0;
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
- if (arpreply->opcode != htons(RARP_REPLY))
- return 0;
- if ((arpreply->opcode == htons(RARP_REPLY)) &&
- (memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {
- memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);
- memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
- memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
- return 1;
- }
- return 0;
- }
-
- static int rarp(void)
- {
- int retry;
-
-
- struct arprequest rarpreq;
-
- memset(&rarpreq, 0, sizeof(rarpreq));
-
- rarpreq.hwtype = htons(1);
- rarpreq.protocol = htons(IP);
- rarpreq.hwlen = ETH_ALEN;
- rarpreq.protolen = 4;
- rarpreq.opcode = htons(RARP_REQUEST);
- memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
-
- memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
-
-
- for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {
- long timeout;
- eth_transmit(broadcast, ETH_P_RARP, sizeof(rarpreq), &rarpreq);
-
- timeout = rfc2131_sleep_interval(TIMEOUT, retry);
- if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))
- break;
- }
-
- if (retry < MAX_ARP_RETRIES) {
- (void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);
-
- return (1);
- }
- return (0);
- }
-
- #else
-
-
- static int await_bootp(int ival __unused, void *ptr __unused,
- unsigned short ptype __unused, struct iphdr *ip __unused,
- struct udphdr *udp, struct tcphdr *tcp __unused)
- {
- struct bootp_t *bootpreply;
- if (!udp) {
- return 0;
- }
- bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
- sizeof(struct iphdr) + sizeof(struct udphdr)];
- if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
- sizeof(struct udphdr) +
- #ifdef NO_DHCP_SUPPORT
- sizeof(struct bootp_t)
- #else
- sizeof(struct bootp_t) - DHCP_OPT_LEN
- #endif
- ) {
- return 0;
- }
- if (udp->dest != htons(BOOTP_CLIENT))
- return 0;
- if (bootpreply->bp_op != BOOTP_REPLY)
- return 0;
- if (bootpreply->bp_xid != xid)
- return 0;
- if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)
- return 0;
- if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&
- (memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {
- return 0;
- }
- if ( bootpreply->bp_siaddr.s_addr ) {
- arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
- memset(arptable[ARP_SERVER].node, 0, ETH_ALEN);
- }
- if ( bootpreply->bp_giaddr.s_addr ) {
- arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
- memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN);
- }
- if (bootpreply->bp_yiaddr.s_addr) {
-
- arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
- #ifndef NO_DHCP_SUPPORT
- dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
- #endif
- netmask = default_netmask();
-
- memcpy((char *)&bootp_data, (char *)bootpreply, sizeof(struct bootpd_t));
- decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0,
- #ifdef NO_DHCP_SUPPORT
- BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN,
- #else
- DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
- #endif
- 1);
- #ifdef PXE_EXPORT
- } else {
-
- arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
- memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN);
-
- memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
- #endif
- }
- #ifdef REQUIRE_VCI_ETHERBOOT
- if (!vci_etherboot)
- return (0);
- #endif
- return(1);
- }
-
- static int bootp(void)
- {
- int retry;
- #ifndef NO_DHCP_SUPPORT
- int reqretry;
- #endif
- struct bootpip_t ip;
- unsigned long starttime;
- unsigned char *bp_vend;
-
- #ifndef NO_DHCP_SUPPORT
- * ( ( struct dhcp_dev_id * ) &dhcp_machine_info[4] ) = nic.dhcp_dev_id;
- #endif
- memset(&ip, 0, sizeof(struct bootpip_t));
- ip.bp.bp_op = BOOTP_REQUEST;
- ip.bp.bp_htype = 1;
- ip.bp.bp_hlen = ETH_ALEN;
- starttime = currticks();
-
-
- memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
- ip.bp.bp_xid = xid += htonl(starttime);
- memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
- #ifdef NO_DHCP_SUPPORT
- memcpy(ip.bp.bp_vend, rfc1533_cookie, 5);
- #else
- memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
- memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
-
- bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;
- memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
- bp_vend += DHCP_MACHINE_INFO_SIZE;
- *bp_vend++ = RFC1533_END;
- #endif
-
- for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
- uint8_t my_hwaddr[ETH_ALEN];
- unsigned long stop_time;
- long remaining_time;
-
- rx_qdrain();
-
-
- memcpy ( my_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN );
- memset ( arptable, 0, sizeof(arptable) );
- memcpy ( arptable[ARP_CLIENT].node, my_hwaddr, ETH_ALEN );
-
- udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
- sizeof(struct bootpip_t), &ip);
- remaining_time = rfc2131_sleep_interval(BOOTP_TIMEOUT, retry++);
- stop_time = currticks() + remaining_time;
- #ifdef NO_DHCP_SUPPORT
- if (await_reply(await_bootp, 0, NULL, remaining_time))
- return(1);
- #else
- while ( remaining_time > 0 ) {
- if (await_reply(await_bootp, 0, NULL, remaining_time)){
- if (arptable[ARP_CLIENT].ipaddr.s_addr)
- break;
- }
- remaining_time = stop_time - currticks();
- }
- if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
- printf("No IP address\n");
- continue;
- }
-
-
- if (dhcp_reply != DHCPOFFER)
- return(1);
- dhcp_reply = 0;
-
- memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
- memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
-
-
- memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));
- memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));
- bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;
-
- memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);
- bp_vend += DHCP_MACHINE_INFO_SIZE;
- *bp_vend++ = RFC1533_END;
- for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
- unsigned long timeout;
-
- udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
- sizeof(struct bootpip_t), &ip);
- dhcp_reply=0;
- timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
- if (!await_reply(await_bootp, 0, NULL, timeout))
- continue;
- if (dhcp_reply != DHCPACK)
- continue;
- dhcp_reply = 0;
- #ifdef PXE_EXPORT
- if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
-
- memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
- memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, proxydhcprequest, sizeof proxydhcprequest);
- for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {
- printf ( "\nSending ProxyDHCP request to %@...", arptable[ARP_PROXYDHCP].ipaddr.s_addr);
- udp_transmit(arptable[ARP_PROXYDHCP].ipaddr.s_addr, BOOTP_CLIENT, PROXYDHCP_SERVER,
- sizeof(struct bootpip_t), &ip);
- timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);
- if (await_reply(await_bootp, 0, NULL, timeout)) {
- break;
- }
- }
- }
- #endif
- return(1);
- }
- #endif
- ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);
- }
- return(0);
- }
- #endif
-
- uint16_t tcpudpchksum(struct iphdr *ip)
- {
- struct udp_pseudo_hdr pseudo;
- uint16_t checksum;
-
-
- pseudo.src.s_addr = ip->src.s_addr;
- pseudo.dest.s_addr = ip->dest.s_addr;
- pseudo.unused = 0;
- pseudo.protocol = ip->protocol;
- pseudo.len = htons(ntohs(ip->len) - sizeof(struct iphdr));
-
-
- checksum = ipchksum(&pseudo, 12);
-
-
- checksum = add_ipchksums(12, checksum, ipchksum(ip + 1,
- ntohs(ip->len) - sizeof(struct iphdr)));
- return checksum;
- }
-
-
- #include "proto_eth_slow.c"
-
-
-
- int await_reply(reply_t reply, int ival, void *ptr, long timeout)
- {
- unsigned long time, now;
- struct iphdr *ip;
- unsigned iplen = 0;
- struct udphdr *udp;
- struct tcphdr *tcp;
- unsigned short ptype;
- int result;
-
- time = timeout + currticks();
-
-
- for (;;) {
- now = currticks();
- background_send(now);
- send_eth_slow_reports(now);
- result = eth_poll(1);
- if (result == 0) {
-
-
-
-
- poll_interruptions();
-
- if ((timeout == 0) || (currticks() > time)) {
- break;
- }
- continue;
- }
-
-
-
-
- if (nic.packetlen >= ETH_HLEN) {
- ptype = ((unsigned short) nic.packet[12]) << 8
- | ((unsigned short) nic.packet[13]);
- } else continue;
-
- ip = 0;
- if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
- unsigned ipoptlen;
- ip = (struct iphdr *)&nic.packet[ETH_HLEN];
- if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
- continue;
- iplen = (ip->verhdrlen & 0xf) * 4;
- if (ipchksum(ip, iplen) != 0)
- continue;
- if (ip->frags & htons(0x3FFF)) {
- static int warned_fragmentation = 0;
- if (!warned_fragmentation) {
- printf("ALERT: got a fragmented packet - reconfigure your server\n");
- warned_fragmentation = 1;
- }
- continue;
- }
- if (ntohs(ip->len) > ETH_MAX_MTU)
- continue;
-
- ipoptlen = iplen - sizeof(struct iphdr);
- if (ipoptlen) {
-
-
- memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
- &nic.packet[ETH_HLEN + iplen],
- nic.packetlen - ipoptlen);
- nic.packetlen -= ipoptlen;
- }
- }
- udp = 0;
- if (ip && (ip->protocol == IP_UDP) &&
- (nic.packetlen >=
- ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
- udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
-
-
- if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
- continue;
-
- if (udp->chksum && tcpudpchksum(ip)) {
- printf("UDP checksum error\n");
- continue;
- }
- }
- tcp = 0;
- if (ip && (ip->protocol == IP_TCP) &&
- (nic.packetlen >=
- ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
- tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
- sizeof(struct iphdr)];
-
- if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
- ntohs(ip->len) - (int)iplen)
- continue;
- if (tcpudpchksum(ip)) {
- printf("TCP checksum error\n");
- continue;
- }
-
- }
- result = reply(ival, ptr, ptype, ip, udp, tcp);
- if (result > 0) {
- return result;
- }
-
-
-
- if ((ptype == ETH_P_ARP) &&
- (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
- struct arprequest *arpreply;
- unsigned long tmp;
-
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
- memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
- if ((arpreply->opcode == htons(ARPOP_REQUEST)) &&
- (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
- arpreply->opcode = htons(ARPOP_REPLY);
- memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
- memcpy(arpreply->thwaddr, arpreply->shwaddr, ETH_ALEN);
- memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
- memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
- eth_transmit(arpreply->thwaddr, ETH_P_ARP,
- sizeof(struct arprequest),
- arpreply);
- #ifdef MDEBUG
- memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
- printf("Sent ARP reply to: %@\n",tmp);
- #endif
- }
- }
- background_process(now, ptype, ip);
- process_eth_slow(ptype, now);
- }
- return(0);
- }
-
- #ifdef REQUIRE_VCI_ETHERBOOT
-
- static int find_vci_etherboot(unsigned char *p)
- {
- unsigned char *end = p + 1 + *p;
-
- for (p++; p < end; ) {
- if (*p == RFC2132_VENDOR_CLASS_ID) {
- if (strncmp("Etherboot", p + 2, sizeof("Etherboot") - 1) == 0)
- return (1);
- } else if (*p == RFC1533_END)
- return (0);
- p += TAG_LEN(p) + 2;
- }
- return (0);
- }
- #endif
-
-
- int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int eof)
- {
- static unsigned char *extdata = NULL, *extend = NULL;
- unsigned char *extpath = NULL;
- unsigned char *endp;
- static unsigned char in_encapsulated_options = 0;
-
- if (eof == -1) {
-
- endp = p + len;
- }
- else if (block == 0) {
- #ifdef REQUIRE_VCI_ETHERBOOT
- vci_etherboot = 0;
- #endif
- end_of_rfc1533 = NULL;
- #ifdef IMAGE_FREEBSD
-
-
- vendorext_isvalid = 1;
- #ifdef FREEBSD_KERNEL_ENV
- memcpy(freebsd_kernel_env, FREEBSD_KERNEL_ENV,
- sizeof(FREEBSD_KERNEL_ENV));
-
- #else
- freebsd_kernel_env[0]='\0';
- #endif
- #else
- vendorext_isvalid = 0;
- #endif
- addparam = NULL;
- addparamlen = 0;
- if (memcmp(p, rfc1533_cookie, 4))
- return(0);
- p += 4;
- endp = p + len;
- } else {
- if (block == 1) {
- if (memcmp(p, rfc1533_cookie, 4))
- return(0);
- p += 4;
- len -= 4; }
- if (extend + len <= (unsigned char *)&(bootp_data.bootp_extension[MAX_BOOTP_EXTLEN])) {
- memcpy(extend, p, len);
- extend += len;
- } else {
- printf("Overflow in vendor data buffer! Aborting...\n");
- *extdata = RFC1533_END;
- return(0);
- }
- p = extdata; endp = extend;
- }
- if (!eof)
- return 1;
- while (p < endp) {
- unsigned char c = *p;
- if (c == RFC1533_PAD) {
- p++;
- continue;
- }
- else if (c == RFC1533_END) {
- end_of_rfc1533 = endp = p;
- continue;
- }
- else if (NON_ENCAP_OPT c == RFC1533_NETMASK)
- memcpy(&netmask, p+2, sizeof(in_addr));
- else if (NON_ENCAP_OPT c == RFC1533_GATEWAY) {
-
-
- if (TAG_LEN(p) >= sizeof(in_addr))
- memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
- }
- else if (c == RFC1533_EXTENSIONPATH)
- extpath = p;
- #ifndef NO_DHCP_SUPPORT
- #ifdef REQUIRE_VCI_ETHERBOOT
- else if (NON_ENCAP_OPT c == RFC1533_VENDOR) {
- vci_etherboot = find_vci_etherboot(p+1);
- #ifdef MDEBUG
- printf("vci_etherboot %d\n", vci_etherboot);
- #endif
- }
- #endif
- else if (NON_ENCAP_OPT c == RFC2132_MSG_TYPE)
- dhcp_reply=*(p+2);
- else if (NON_ENCAP_OPT c == RFC2132_SRV_ID)
- memcpy(&dhcp_server, p+2, sizeof(in_addr));
- #endif
- else if (NON_ENCAP_OPT c == RFC1533_HOSTNAME) {
- hostname = p + 2;
- hostnamelen = *(p + 1);
- }
- else if (ENCAP_OPT c == RFC1533_VENDOR_MAGIC
- && TAG_LEN(p) >= 6 &&
- !memcmp(p+2,vendorext_magic,4) &&
- p[6] == RFC1533_VENDOR_MAJOR
- )
- vendorext_isvalid++;
- else if (c == RFC1533_VENDOR_ADDPARM) {
-
-
- addparam = p + 2;
- addparamlen = *(p + 1);
- }
- else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) {
- in_encapsulated_options = 1;
- decode_rfc1533(p+2, 0, TAG_LEN(p), -1);
- in_encapsulated_options = 0;
- }
- #ifdef IMAGE_FREEBSD
- else if (NON_ENCAP_OPT c == RFC1533_VENDOR_HOWTO)
- freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
- else if (NON_ENCAP_OPT c == RFC1533_VENDOR_KERNEL_ENV){
- if(*(p + 1) < sizeof(freebsd_kernel_env)){
- memcpy(freebsd_kernel_env,p+2,*(p+1));
- }else{
- printf("Only support %ld bytes in Kernel Env\n",
- sizeof(freebsd_kernel_env));
- }
- }
- #endif
- else if (NON_ENCAP_OPT c == RFC1533_DNS) {
-
- if (TAG_LEN(p) >= sizeof(in_addr))
- memcpy(&arptable[ARP_NAMESERVER].ipaddr, p+2, sizeof(in_addr));
- }
- else {
- #if 0
- unsigned char *q;
- printf("Unknown RFC1533-tag ");
- for(q=p;q<p+2+TAG_LEN(p);q++)
- printf("%hhX ",*q);
- putchar('\n');
- #endif
- }
- p += TAG_LEN(p) + 2;
- }
- extdata = extend = endp;
- if (block <= 0 && extpath != NULL) {
- char fname[64];
- memcpy(fname, extpath+2, TAG_LEN(extpath));
- fname[(int)TAG_LEN(extpath)] = '\0';
- printf("Loading BOOTP-extension file: %s\n",fname);
- #warning "BOOTP extension files are broken"
-
- }
- return 1;
- }
-
-
-
- #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
-
- long rfc2131_sleep_interval(long base, int exp)
- {
- unsigned long tmo;
- if (exp > BACKOFF_LIMIT)
- exp = BACKOFF_LIMIT;
- tmo = (base << exp) + (TICKS_PER_SEC - (random()/TWO_SECOND_DIVISOR));
- return tmo;
- }
-
|