X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=net%2Farp.c;h=20c6b2d42ac0f6d90804de2d2e59fd0271da663b;hb=c7964f86c28da4e4cf5a7cc4430461ea17218d80;hp=997c2abdb35a901b4fca87022bc055b3b28266ec;hpb=adf5d93e441eb3eacd8c0430d6064b35d47ad2a5;p=oweals%2Fu-boot.git diff --git a/net/arp.c b/net/arp.c index 997c2abdb3..20c6b2d42a 100644 --- a/net/arp.c +++ b/net/arp.c @@ -27,36 +27,37 @@ #endif IPaddr_t NetArpWaitPacketIP; -IPaddr_t NetArpWaitReplyIP; +static IPaddr_t NetArpWaitReplyIP; /* MAC address of waiting packet's destination */ uchar *NetArpWaitPacketMAC; -/* THE transmit packet */ -uchar *NetArpWaitTxPacket; int NetArpWaitTxPacketSize; -uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; ulong NetArpWaitTimerStart; int NetArpWaitTry; +static uchar *NetArpTxPacket; /* THE ARP transmit packet */ +static uchar NetArpPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; + void ArpInit(void) { /* XXX problem with bss workaround */ NetArpWaitPacketMAC = NULL; NetArpWaitPacketIP = 0; NetArpWaitReplyIP = 0; - NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); - NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; NetArpWaitTxPacketSize = 0; + NetArpTxPacket = &NetArpPacketBuf[0] + (PKTALIGN - 1); + NetArpTxPacket -= (ulong)NetArpTxPacket % PKTALIGN; } -void ArpRequest(void) +void arp_raw_request(IPaddr_t sourceIP, const uchar *targetEther, + IPaddr_t targetIP) { uchar *pkt; struct arp_hdr *arp; int eth_hdr_size; - debug("ARP broadcast %d\n", NetArpWaitTry); + debug_cond(DEBUG_DEV_PKT, "ARP broadcast %d\n", NetArpWaitTry); - pkt = NetTxPacket; + pkt = NetArpTxPacket; eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_ARP); pkt += eth_hdr_size; @@ -69,12 +70,16 @@ void ArpRequest(void) arp->ar_pln = ARP_PLEN; arp->ar_op = htons(ARPOP_REQUEST); - /* source ET addr */ - memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); - /* source IP addr */ - NetWriteIP(&arp->ar_spa, NetOurIP); - /* dest ET addr = 0 */ - memset(&arp->ar_tha, 0, ARP_HLEN); + memcpy(&arp->ar_sha, NetOurEther, ARP_HLEN); /* source ET addr */ + NetWriteIP(&arp->ar_spa, sourceIP); /* source IP addr */ + memcpy(&arp->ar_tha, targetEther, ARP_HLEN); /* target ET addr */ + NetWriteIP(&arp->ar_tpa, targetIP); /* target IP addr */ + + NetSendPacket(NetArpTxPacket, eth_hdr_size + ARP_HDR_SIZE); +} + +void ArpRequest(void) +{ if ((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) { if (NetOurGatewayIP == 0) { @@ -87,8 +92,7 @@ void ArpRequest(void) NetArpWaitReplyIP = NetArpWaitPacketIP; } - NetWriteIP(&arp->ar_tpa, NetArpWaitReplyIP); - NetSendPacket(NetTxPacket, eth_hdr_size + ARP_HDR_SIZE); + arp_raw_request(NetOurIP, NetEtherNullAddr, NetArpWaitReplyIP); } void ArpTimeoutCheck(void) @@ -131,7 +135,7 @@ void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) * address; so if we receive such a packet, we set * the server ethernet address */ - debug("Got ARP\n"); + debug_cond(DEBUG_NET_PKT, "Got ARP\n"); arp = (struct arp_hdr *)ip; if (len < ARP_HDR_SIZE) { @@ -156,27 +160,41 @@ void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) switch (ntohs(arp->ar_op)) { case ARPOP_REQUEST: /* reply with our IP address */ - debug("Got ARP REQUEST, return our IP\n"); + debug_cond(DEBUG_DEV_PKT, "Got ARP REQUEST, return our IP\n"); pkt = (uchar *)et; - eth_hdr_size = NetSetEther(pkt, et->et_src, PROT_ARP); + 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 || !NetArpWaitPacketMAC) + if (!NetArpWaitPacketIP) break; #ifdef CONFIG_KEEP_SERVERADDR if (NetServerIP == NetArpWaitPacketIP) { char buf[20]; - sprintf(buf, "%pM", arp->ar_sha); + sprintf(buf, "%pM", &arp->ar_sha); setenv("serveraddr", buf); } #endif @@ -185,21 +203,23 @@ void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) /* matched waiting packet's address */ if (reply_ip_addr == NetArpWaitReplyIP) { - debug("Got ARP REPLY, set eth addr (%pM)\n", + debug_cond(DEBUG_DEV_PKT, + "Got ARP REPLY, set eth addr (%pM)\n", arp->ar_data); /* save address for later use */ - memcpy(NetArpWaitPacketMAC, - &arp->ar_sha, ARP_HLEN); + if (NetArpWaitPacketMAC != NULL) + memcpy(NetArpWaitPacketMAC, + &arp->ar_sha, ARP_HLEN); -#ifdef CONFIG_NETCONSOLE - NetGetHandler()(0, 0, 0, 0, 0); -#endif - /* modify header, and transmit it */ - memcpy(((struct ethernet_hdr *)NetArpWaitTxPacket)-> - et_dest, NetArpWaitPacketMAC, ARP_HLEN); - NetSendPacket(NetArpWaitTxPacket, - NetArpWaitTxPacketSize); + 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;