/* * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet */ static void BootpCopyNetParams(Bootp_t *bp){ IPaddr_t tmp_ip; NetCopyIP(&NetOurIP, &bp->bp_yiaddr); NetCopyIP(&tmp_ip, &bp->bp_siaddr); if(tmp_ip != 0){ NetCopyIP(&NetServerIP, &bp->bp_siaddr); } memcpy(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6); if(strlen(bp->bp_file) > 0){ copy_filename(BootFile, bp->bp_file, sizeof(BootFile)); } #ifdef DEBUG printf("Bootfile: %s\n", BootFile); #endif /* * Propagate to environment: * don't delete exising entry when BOOTP / DHCP reply does * not contain a new value */ if(*BootFile){ setenv("bootfile", BootFile); } }
void ping_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) { struct icmp_hdr *icmph = (struct icmp_hdr *)&ip->udp_src; IPaddr_t src_ip; int eth_hdr_size; switch (icmph->type) { case ICMP_ECHO_REPLY: src_ip = NetReadIP((void *)&ip->ip_src); if (src_ip == NetPingIP) net_set_state(NETLOOP_SUCCESS); return; case ICMP_ECHO_REQUEST: eth_hdr_size = net_update_ether(et, et->et_src, PROT_IP); debug_cond(DEBUG_DEV_PKT, "Got ICMP ECHO REQUEST, return " "%d bytes\n", eth_hdr_size + len); ip->ip_sum = 0; ip->ip_off = 0; NetCopyIP((void *)&ip->ip_dst, &ip->ip_src); NetCopyIP((void *)&ip->ip_src, &NetOurIP); ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1); icmph->type = ICMP_ECHO_REPLY; icmph->checksum = 0; icmph->checksum = ~NetCksum((uchar *)icmph, (len - IP_HDR_SIZE) >> 1); NetSendPacket((uchar *)et, eth_hdr_size + len); return; /* default: return;*/ } }
/*------------------------------------------------------------------------ * This sends an TCP segment to the ip layer. The segment is * is normally either a web page or a graphic. * See "TCP/IP Illustrated, Volume 1" Sect 17.3 *------------------------------------------------------------------------ */ void http_send(uchar *outbuf, uint len, uchar nr) { TCP_t *tcp; IP_t *ip; uint sum; ushort result; uint dest_ip; /* Fill in TCP segment header */ tcp = (TCP_t *)(outbuf + 34); ip = (IP_t *)(outbuf + 14); tcp->source_port = htons(HTTP_PORT); tcp->dest_port = htons(conxn[nr].port); tcp->sequence = htonl(conxn[nr].my_sequence); tcp->ack_number = htonl(conxn[nr].his_sequence); /* Header is always 20 bytes long */ tcp->flags = htons(0x5000 | FLG_ACK | FLG_PSH); tcp->window = htons(WINDOW_SIZE); tcp->checksum = 0; tcp->urgent_ptr = 0; /* * Compute checksum including 12 bytes of pseudoheader * Must pre-fill 2 items in ip header to do this */ dest_ip = htonl(conxn[nr].ipaddr); NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* in network byte order */ NetCopyIP((void*)&ip->ip_dst, &dest_ip); /* Sum source_ipaddr, dest_ipaddr, and entire TCP message */ sum = (uint)cksum(outbuf + 26, 8 + len); /* * Add in the rest of pseudoheader which is * protocol id and TCP segment length */ sum += (uint)htons(0x0006); sum += (uint)htons(len); /* In case there was a carry, add it back around */ result = (uint)(sum + (sum >> 16)); tcp->checksum = ~result; memcpy(outbuf, conxn[nr].mac, 6); if (http_debug == DEBUG) printf("%s : Sending msg to IP layer\n", __func__); NetSendIPPacket(outbuf, dest_ip, TCP_TYPE, len); /* (Re)start TCP retransmit timer */ conxn[nr].timer = TCP_TIMEOUT; }
/* * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet */ static void BootpCopyNetParams(Bootp_t *bp) { IPaddr_t tmp_ip; NetCopyIP(&NetOurIP, &bp->bp_yiaddr); #if !defined(CONFIG_BOOTP_SERVERIP) NetCopyIP(&tmp_ip, &bp->bp_siaddr); if (tmp_ip != 0) NetCopyIP(&NetServerIP, &bp->bp_siaddr); memcpy (NetServerEther, ((Ethernet_t *)NetRxPacket)->et_src, 6); #endif }
static void keymile_hdlc_enet_doarp(volatile void *packet, int len) { ARP_t *arp; IPaddr_t src_ip; /* U-Boot's IP */ IPaddr_t dest_ip; /* the mgcoge's IP */ unsigned char *packet_copy = malloc(len); /* * Handling an ARP request means that a new transfer has started. * Update our cached parameters now. */ initCachedNumbers(0); /* may reinit port numbers */ /* special handling required for ARP */ arp = (ARP_t *)(packet + ETHER_HDR_SIZE); /* * XXXX * This is pretty dirty! NetReceive only uses * a few fields when handling an ARP reply, so * we only modify those here. This could * result in catastrophic failure at a later * time if the handler is modified! */ arp->ar_op = htons(ARPOP_REPLY); /* save his/our IP */ src_ip = NetReadIP(&arp->ar_data[6]); dest_ip = NetReadIP(&arp->ar_data[16]); /* copy target IP to source IP */ NetCopyIP(&arp->ar_data[6], &dest_ip); /* copy our IP to the right place */ NetCopyIP(&arp->ar_data[16], &src_ip); /* always use 0x7f as the MAC for the coge */ arp->ar_data[0] = HDLC_UACUA; /* * copy the packet * if NetReceive wants to write to stdout, it may overwrite packet * especially if stdout is set to nc! * * However, if the malloc() above fails then we can still try the * original packet, rather than causing the transfer to fail. */ if (packet_copy != NULL) { memcpy(packet_copy, (char *)packet, len); NetReceive(packet_copy, len); free(packet_copy); } else NetReceive(packet, len); }
/* * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet */ static void BootpCopyNetParams(Bootp_t *bp) { IPaddr_t tmp_ip; NetCopyIP(&NetOurIP, &bp->bp_yiaddr); #if !defined(CONFIG_BOOTP_SERVERIP) NetCopyIP(&tmp_ip, &bp->bp_siaddr); if (tmp_ip != 0) NetCopyIP(&NetServerIP, &bp->bp_siaddr); memcpy (NetServerEther, ((Ethernet_t *)NetRxPacket)->et_src, 6); #endif #ifdef PRODUCTION_CODE /* * Server overrides any target value to ensure the correct file is downloaded */ if (strlen(bp->bp_file) > 0) copy_filename (BootFile, bp->bp_file, sizeof(BootFile)); debug("Bootfile: %s\n", BootFile); /* Propagate to environment: * don't delete exising entry when BOOTP / DHCP reply does * not contain a new value */ if (*BootFile) { setenv ("bootfile", BootFile); } #else /* * During development it is useful to be able to force the bootfile value from the * target, rather than allowing the server to override it. */ if (strlen(bp->bp_file) > 0 && !getenv("bootfile")) { /* Propagate to environment: * Only set when BOOTP / DHCP reply contains a new value * and bootfile doesn't exist. */ copy_filename (BootFile, bp->bp_file, sizeof(BootFile)); setenv ("bootfile", BootFile); } debug ("Bootfile: %s\n", BootFile); #endif }
/* * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet */ static void BootpCopyNetParams(struct Bootp_t *bp) { #if !defined(CONFIG_BOOTP_SERVERIP) IPaddr_t tmp_ip; NetCopyIP(&tmp_ip, &bp->bp_siaddr); if (tmp_ip != 0) NetCopyIP(&NetServerIP, &bp->bp_siaddr); memcpy(NetServerEther, ((struct ethernet_hdr *)NetRxPacket)->et_src, 6); if (strlen(bp->bp_file) > 0) copy_filename(BootFile, bp->bp_file, sizeof(BootFile)); debug("Bootfile: %s\n", BootFile); /* Propagate to environment: * don't delete exising entry when BOOTP / DHCP reply does * not contain a new value */ if (*BootFile) setenv("bootfile", BootFile); #endif NetCopyIP(&NetOurIP, &bp->bp_yiaddr); }
static void BootpVendorFieldProcess(u8 * ext){ int size = *(ext + 1); NetBootFileSize = 0; switch(*ext){ /* Fixed length fields */ case 1: /* Subnet mask */ if (NetOurSubnetMask == 0){ NetCopyIP(&NetOurSubnetMask, (IPaddr_t *)(ext + 2)); } break; case 2: /* Time offset - Not yet supported */ break; /* Variable length fields */ case 3: /* Gateways list */ if(NetOurGatewayIP == 0){ NetCopyIP(&NetOurGatewayIP, (IPaddr_t *)(ext + 2)); } break; case 4: /* Time server - Not yet supported */ break; case 5: /* IEN-116 name server - Not yet supported */ break; case 6: if(NetOurDNSIP == 0){ NetCopyIP(&NetOurDNSIP, (IPaddr_t *)(ext + 2)); } #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2) if((NetOurDNS2IP == 0) && (size > 4)){ NetCopyIP(&NetOurDNS2IP, (IPaddr_t *)(ext + 2 + 4)); } #endif 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){ size = truncate_sz("Host Name", sizeof(NetOurHostName), size); memcpy(&NetOurHostName, ext + 2, size); NetOurHostName[size] = 0; } break; case 13: /* Boot file size */ if(size == 2){ NetBootFileSize = ntohs(*(ushort *)(ext + 2)); } else if(size == 4){ NetBootFileSize = ntohl(*(ulong *)(ext + 2)); } 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){ size = truncate_sz("Root Path", sizeof(NetOurRootPath), size); memcpy(&NetOurRootPath, ext + 2, size); NetOurRootPath[size] = 0; } break; case 18: /* Extension path - Not yet supported */ /* * This can be used to send the information 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){ size = truncate_sz("NIS Domain Name", sizeof(NetOurNISDomain), size); memcpy(&NetOurNISDomain, ext + 2, size); NetOurNISDomain[size] = 0; } break; /* Application layer fields */ case 43: /* Vendor specific info - Not yet supported */ /* * Binary information to exchange specific * product information. */ break; /* Reserved (custom) fields (128..254) */ } }
static void link_local_timeout(void) { switch (state) { case PROBE: /* timeouts in the PROBE state mean no conflicting ARP packets have been received, so we can progress through the states */ if (nprobes < PROBE_NUM) { nprobes++; debug_cond(DEBUG_LL_STATE, "probe/%u %s@%pI4\n", nprobes, eth_get_name(), &ip); arp_raw_request(0, NetEtherNullAddr, ip); timeout_ms = PROBE_MIN * 1000; timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); } else { /* Switch to announce state */ state = ANNOUNCE; nclaims = 0; debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n", nclaims, eth_get_name(), &ip); arp_raw_request(ip, NetOurEther, ip); timeout_ms = ANNOUNCE_INTERVAL * 1000; } break; case RATE_LIMIT_PROBE: /* timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets have been received, so we can move immediately to the announce state */ state = ANNOUNCE; nclaims = 0; debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n", nclaims, eth_get_name(), &ip); arp_raw_request(ip, NetOurEther, ip); timeout_ms = ANNOUNCE_INTERVAL * 1000; break; case ANNOUNCE: /* timeouts in the ANNOUNCE state mean no conflicting ARP packets have been received, so we can progress through the states */ if (nclaims < ANNOUNCE_NUM) { nclaims++; debug_cond(DEBUG_LL_STATE, "announce/%u %s@%pI4\n", nclaims, eth_get_name(), &ip); arp_raw_request(ip, NetOurEther, ip); timeout_ms = ANNOUNCE_INTERVAL * 1000; } else { /* Switch to monitor state */ state = MONITOR; printf("Successfully assigned %pI4\n", &ip); NetCopyIP(&NetOurIP, &ip); ready = 1; conflicts = 0; timeout_ms = -1; /* Never timeout in the monitor state */ NetSetTimeout(0, NULL); /* NOTE: all other exit paths should deconfig ... */ net_set_state(NETLOOP_SUCCESS); return; } break; case DEFEND: /* We won! No ARP replies, so just go back to monitor */ state = MONITOR; timeout_ms = -1; conflicts = 0; break; default: /* Invalid, should never happen. Restart the whole protocol */ state = PROBE; ip = pick(); timeout_ms = 0; nprobes = 0; nclaims = 0; break; } configure_wait(); }
static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) { ushort proto; int i; static int ledcount=0,ledstate=1; if (dest != TftpOurPort) { return; } /* don't care the packets that donot send to TFTP port */ if (TftpState != STATE_RRQ && src != TftpServerPort) { return; } if (len < 2) { return; } #if 0 if (0==ledcount%64)/*the led flicker when packet received*/ { ledstate+=1; ledstate%=2; } if(0==ledstate%2) LEDON(11); else LEDOFF(11); ++ledcount; if (0xffffff==i) i=0; #endif len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ proto = *((ushort *)pkt)++; switch (ntohs(proto)) { case TFTP_RRQ: printf("\n Get read request from:("); print_IPaddr(TempServerIP); printf(")\n"); NetCopyIP(&NetServerIP,&TempServerIP); TftpServerPort = src; TftpBlock = 1; TftpBlockWrapOffset = 0; TftpState = STATE_RRQ; for (i=0; i<13; i++) { if (*((uint8_t *)pkt)++ != asuslink[i]) break; } if (i==13) { /* it's the firmware transmitting situation */ /* here get the IP address from the first packet. */ NetOurIP = (*((uint8_t *)pkt)++) & 0x000000ff; NetOurIP<<=8; NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff; NetOurIP<<=8; NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff; NetOurIP<<=8; NetOurIP|= (*((uint8_t *)pkt)++) & 0x000000ff; } else { for (i=0; i<13; i++) { if (*((uint8_t *)pkt)++ != maclink[i]) break; } if(i==13) { /* here get the IP address from the first packet. */ NetOurIP = (*((uint8_t *)pkt)++)& 0x000000ff; NetOurIP<<=8; NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff; NetOurIP<<=8; NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff; NetOurIP<<=8; NetOurIP|=(*((uint8_t *)pkt)++)& 0x000000ff; } } TftpdSend();//send a vacant Data packet as a ACK break; case TFTP_WRQ: TftpServerPort = src; TftpBlock = 0; TftpState = STATE_WRQ; TftpdSend(); break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = ntohs(*(ushort *)pkt); /* * RFC1350 specifies that the first data packet will * have sequence number 1. If we receive a sequence * number of 0 this means that there was a wrap * around of the (16 bit) counter. */ if (TftpBlock == 0) { printf("\n\t %lu MB reveived\n\t ", TftpBlockWrapOffset>>20); } else { if (((TftpBlock - 1) % 10) == 0)
static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) { ushort proto; int i; if (dest != TftpOurPort) { return; } /* don't care the packets that donot send to TFTP port */ if (TftpState != STATE_RRQ && src != TftpServerPort) { return; } if (len < 2) { return; } len -= 2; /* warning: don't use increment (++) in ntohs() macros!! */ proto = *((ushort *)pkt)++; switch (ntohs(proto)) { case TFTP_RRQ: printf("\n Get read request from:("); print_IPaddr(TempServerIP); printf(")\n"); NetCopyIP(&NetServerIP,&TempServerIP); TftpServerPort = src; TftpBlock = 1; TftpBlockWrapOffset = 0; TftpState = STATE_RRQ; TftpdSend();//send a vacant Data packet as a ACK break; case TFTP_WRQ: TftpServerPort = src; TftpBlock = 0; TftpState = STATE_WRQ; TftpdSend(); break; case TFTP_DATA: if (len < 2) return; len -= 2; TftpBlock = ntohs(*(ushort *)pkt); /* * RFC1350 specifies that the first data packet will * have sequence number 1. If we receive a sequence * number of 0 this means that there was a wrap * around of the (16 bit) counter. */ if (TftpBlock == 0) { printf("\n\t %lu MB reveived\n\t ", TftpBlockWrapOffset>>20); } else { if (((TftpBlock - 1) % 10) == 0)
//extern int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); void recoveryHandle(void) { char cmd[256]; char img[10]; char * argv[3]; char *env; MV_32 imagAddr, imagSize = 0, netflag = 1; char ip[16]= {"dhcp"}; char* usbload[5]; unsigned int netwait = 3000; int upgrade = -1; /* get the loadaddr env var */ if (!getenv("loadaddr")) { printf("Missing loadaddr environment variable assuming default (%s)!\n", RCVR_LOAD_ADDR); setenv("loadaddr",RCVR_LOAD_ADDR); saveenv(); } #ifdef CONFIG_USB_STORAGE /* First try to perform recovery from USB DOK*/ /* try to recognize storage devices immediately */ if (usb_init() >= 0) { if (usb_stor_scan(1) >= 0) { netflag = 0; usbload[0] = "usbload"; usbload[1] = "usb"; usbload[2] = "0:1"; usbload[3] = getenv("loadaddr"); usbload[4] = "/multiware.img"; printf("Trying to load image from USB flash drive using FAT FS\n"); if (do_fat_fsload(0, 0, 5, usbload) == 1) { printf("Trying to load image from USB flash drive using ext2 FS partition 0\n"); usbload[2] = "0:0"; if(do_ext2load(0, 0, 5, usbload) == 1) { printf("Trying to load image from USB flash drive using ext2 FS partition 1\n"); usbload[2] = "0:1"; if(do_ext2load(0, 0, 5, usbload) == 1) { printf("Couldn't load recovery image from USB flash drive, Trying network interface\n"); netflag = 1; } else { env = getenv("filesize"); usbload[3] = getenv("loadaddr"); imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */ /* Trying to check if we forced to upgrade by placing upgrade.me */ usbload[4] = "/upgrade.me"; usbload[3] = "0x000000000"; env=getenv("loadaddr"); imagAddr=simple_strtoul(env, NULL, 16); sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1); printf("dummyaddr:%s\n", usbload[3]); upgrade=do_ext2load(0, 0, 5, usbload); } } else { env = getenv("filesize"); imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */ /* Trying to check if we forced to upgrade by placing upgrade.me */ usbload[4] = "/upgrade.me"; usbload[3] = "0x000000000"; env=getenv("loadaddr"); imagAddr=simple_strtoul(env, NULL, 16); sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1); printf("dummyaddr:%s\n", usbload[3]); upgrade=do_ext2load(0, 0, 5, usbload); } } else { env = getenv("filesize"); imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */ /* Trying to check if we forced to upgrade by placing upgrade.me */ usbload[4] = "/upgrade.me"; usbload[3] = "0x000000000"; env=getenv("loadaddr"); imagAddr=simple_strtoul(env, NULL, 16); sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1); printf("dummyaddr:%s\n", usbload[3]); upgrade=do_fat_fsload(0, 0, 5, usbload); } // Decide on upgrade/init mode if (upgrade == 0) sprintf(ip, "usb_upgrade"); else sprintf(ip, "usb"); printf("USB mode:%s\n", ip); } } #endif if(netflag == 1) { /* if recovery ip set same as our ip then skip dhcp */ while ( strcmp(getenv("rcvrip"), getenv("ipaddr")) && (netwait > 0) ) { /* Perform the DHCP */ printf("Aquiring an IP address using DHCP after delay...\n"); mvOsDelay(netwait); netwait-=1000; if (NetLoop(DHCP) != -1) { /* We'vev got DHCP progressing with recovery */ printf("DHCP should be ready for Recovery.\n"); break; } } /* No DHCP after timeout or forced */ if ( !strcmp(getenv("rcvrip"), getenv("ipaddr")) || (netwait <= 0) ) { ulong tmpip; printf("No DHCP after timeout or manual IP address configured, switching to static IP address (%s)!\n", getenv("rcvrip")); tmpip = getenv_IPaddr ("rcvrip"); NetCopyIP(&NetOurIP, &tmpip); sprintf(ip, "static"); } /* Perform the recovery */ printf("Starting retrieval of recovery image over network...\n"); if ((imagSize = NetLoop(RCVR)) == -1) { printf("Failed\n"); return; } } switch (mvBoardIdGet()) { case RD_88F6510_SFU_ID: case RD_88F6560_GW_ID: case DB_88F6535_BP_ID: setenv("bootcmd","setenv bootargs ${console} ubi.mtd=2 root=ubi0:rootfsU rootfstype=ubifs ${mvNetConfig} ${mvPhoneConfig}; nand read.e ${loadaddr} 0x200000 0x400000; bootm ${loadaddr};"); setenv("console","console=ttyS0,115200"); saveenv(); break; } printf("\nPermanent bootcmd: %s\n", getenv("bootcmd")); printf("\nPermanent console: %s\n", getenv("console")); /* This assignment to cmd should execute prior to the RD setenv and saveenv below*/ sprintf(cmd,"setenv bootargs ${console} root=/dev/ram0 ${mvNetConfig} recovery=%s rcvrip=%s:%s%s ethact=${ethact} ethaddr=%s eth1addr=%s; bootm ${loadaddr};", ip, getenv("rcvrip"), getenv("serverip"), getenv("bootargs_end"), getenv("ethaddr"), getenv("eth1addr")); setenv("bootcmd", cmd); printf("\nRecovery bootcmd: %s\n", cmd); printf("Booting recovery image at: [%s]...\n", getenv("loadaddr")); sprintf(cmd, "boot"); sprintf(img, "%s", getenv("loadaddr")); argv[0] = cmd; argv[1] = img; do_bootd(NULL, 0, 2, argv); }
void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) { struct arp_hdr *arp; IPaddr_t reply_ip_addr; uchar *pkt; int eth_hdr_size; /* * We have to deal with two types of ARP packets: * - REQUEST packets will be answered by sending our * IP address - if we know it. * - REPLY packates are expected only after we asked * for the TFTP server's or the gateway's ethernet * address; so if we receive such a packet, we set * the server ethernet address */ debug_cond(DEBUG_NET_PKT, "Got ARP\n"); arp = (struct arp_hdr *)ip; if (len < ARP_HDR_SIZE) { printf("bad length %d < %d\n", len, ARP_HDR_SIZE); return; } if (ntohs(arp->ar_hrd) != ARP_ETHER) return; if (ntohs(arp->ar_pro) != PROT_IP) return; if (arp->ar_hln != ARP_HLEN) return; if (arp->ar_pln != ARP_PLEN) return; if (NetOurIP == 0) return; if (NetReadIP(&arp->ar_tpa) != NetOurIP) return; switch (ntohs(arp->ar_op)) { case ARPOP_REQUEST: /* reply with our IP address */ debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); pkt = (uchar *)et; eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP); pkt += eth_hdr_size; arp->ar_op = htons(ARPOP_REPLY); memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN); NetCopyIP(&arp->ar_tpa, &arp->ar_spa); memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); NetCopyIP(&arp->ar_spa, &NetOurIP); #ifdef CONFIG_CMD_LINK_LOCAL /* * Work-around for brain-damaged Cisco equipment with * arp-proxy enabled. * * If the requesting IP is not on our subnet, wait 5ms to * reply to ARP request so that our reply will overwrite * the arp-proxy's instead of the other way around. */ if ((NetReadIP(&arp->ar_tpa) & NetOurSubnetMask) != (NetReadIP(&arp->ar_spa) & NetOurSubnetMask)) udelay(5000); #endif NetSendPacket((uchar *)et, eth_hdr_size + ARP_HDR_SIZE); return; case ARPOP_REPLY: /* arp reply */ /* are we waiting for a reply */ if (!NetArpWaitPacketIP) break; #ifdef CONFIG_KEEP_SERVERADDR if (NetServerIP == NetArpWaitPacketIP) { char buf[20]; sprintf(buf, "%pM", &arp->ar_sha); setenv("serveraddr", buf); } #endif reply_ip_addr = NetReadIP(&arp->ar_spa); /* matched waiting packet's address */ if (reply_ip_addr == NetArpWaitReplyIP) { debug_cond(DEBUG_DEV_PKT, "Got ARP REPLY, set eth addr (%pM)\n", arp->ar_data); /* save address for later use */ if (NetArpWaitPacketMAC != NULL) memcpy(NetArpWaitPacketMAC, &arp->ar_sha, ARP_HLEN); net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr, 0, len); /* set the mac address in the waiting packet's header and transmit it */ memcpy(((struct ethernet_hdr *)NetTxPacket)->et_dest, &arp->ar_sha, ARP_HLEN); NetSendPacket(NetTxPacket, NetArpWaitTxPacketSize); /* no arp request pending now */ NetArpWaitPacketIP = 0; NetArpWaitTxPacketSize = 0; NetArpWaitPacketMAC = NULL; } return; default: debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op)); return; } }