X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=net%2Farp.c;h=21ed31bf742dd3582add21aed5bf1333591d3c0e;hb=8104f546296a8e1fc1dd6129041e22f508b314f9;hp=5b16de7cededd64ad464a1fff0fc4ea045fa27eb;hpb=738853bb6d290dc4b52d8c2989c0998d7aa26913;p=karo-tx-uboot.git diff --git a/net/arp.c b/net/arp.c index 5b16de7ced..21ed31bf74 100644 --- a/net/arp.c +++ b/net/arp.c @@ -6,6 +6,7 @@ * Copyright 2000 Roland Borde * Copyright 2000 Paolo Scaffardi * Copyright 2000-2002 Wolfgang Denk, wd@denx.de + * SPDX-License-Identifier: GPL-2.0 */ #include @@ -27,52 +28,59 @@ #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; - pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP); + eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_ARP); + pkt += eth_hdr_size; arp = (struct arp_hdr *) pkt; arp->ar_hrd = htons(ARP_ETHER); arp->ar_pro = htons(PROT_IP); - arp->ar_hln = 6; - arp->ar_pln = 4; + arp->ar_hln = ARP_HLEN; + arp->ar_pln = ARP_PLEN; arp->ar_op = htons(ARPOP_REQUEST); - /* source ET addr */ - memcpy(&arp->ar_data[0], NetOurEther, 6); - /* source IP addr */ - NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP); - /* dest ET addr = 0 */ - memset(&arp->ar_data[10], '\0', 6); + 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) { @@ -85,8 +93,7 @@ void ArpRequest(void) NetArpWaitReplyIP = NetArpWaitPacketIP; } - NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP); - (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); + arp_raw_request(NetOurIP, NetEtherNullAddr, NetArpWaitReplyIP); } void ArpTimeoutCheck(void) @@ -116,8 +123,9 @@ void ArpTimeoutCheck(void) void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) { struct arp_hdr *arp; - IPaddr_t tmp; + IPaddr_t reply_ip_addr; uchar *pkt; + int eth_hdr_size; /* * We have to deal with two types of ARP packets: @@ -128,7 +136,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) { @@ -139,64 +147,80 @@ void ArpReceive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len) return; if (ntohs(arp->ar_pro) != PROT_IP) return; - if (arp->ar_hln != 6) + if (arp->ar_hln != ARP_HLEN) return; - if (arp->ar_pln != 4) + if (arp->ar_pln != ARP_PLEN) return; if (NetOurIP == 0) return; - if (NetReadIP(&arp->ar_data[16]) != NetOurIP) + if (NetReadIP(&arp->ar_tpa) != NetOurIP) return; 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; - pkt += 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_data[10], &arp->ar_data[0], 6); - NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); - memcpy(&arp->ar_data[0], NetOurEther, 6); - NetCopyIP(&arp->ar_data[6], &NetOurIP); - (void) eth_send((uchar *)et, - (pkt - (uchar *)et) + ARP_HDR_SIZE); + 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_data); + sprintf(buf, "%pM", &arp->ar_sha); setenv("serveraddr", buf); } #endif - tmp = NetReadIP(&arp->ar_data[6]); + reply_ip_addr = NetReadIP(&arp->ar_spa); /* matched waiting packet's address */ - if (tmp == NetArpWaitReplyIP) { - debug("Got ARP REPLY, set eth addr (%pM)\n", + 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 */ - memcpy(NetArpWaitPacketMAC, - &arp->ar_data[0], 6); - -#ifdef CONFIG_NETCONSOLE - NetGetHandler()(0, 0, 0, 0, 0); -#endif - /* modify header, and transmit it */ - memcpy(((struct ethernet_hdr *)NetArpWaitTxPacket)-> - et_dest, NetArpWaitPacketMAC, 6); - (void) eth_send(NetArpWaitTxPacket, - NetArpWaitTxPacketSize); + 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;