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); }
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;*/ } }
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; } }