/** * @function: arp_decode * @param: uint16_t, Length of the packet received. * @param: uint8_t *, Pointer to the first byte of the packet. * @return: uint16_t, Size of the new reply packet to be transmitted. * @brief: Decodes a received packet into a ARP-packet and * runs nessesary actions. Which eventually will create * an appropriate reply. */ uint16_t arp_decode(uint16_t length, uint8_t* packet) { // Packet is valid ARP packet if(length < sizeof(struct arp_header_t)) { return 0; } // Assign ARP header pointer struct arp_header_t* arp_header = ((struct arp_header_t*) &packet[0]); // Select ARP operation switch(htons(arp_header->opcode)) { case ARP_OPCODE_REQUEST: // If it asked for our address, we send out a reply. if(!ip_addr_compare(arp_header->ip_dest_addr, ip_get_host_addr())) { break; } // First, we register the one who made the request in our ARP // table, since it is likely that we will do more communication // with this host in the future. arp_update(arp_header->ip_src_addr, arp_header->mac_src_addr); // Set new destination and source mac address memcpy(arp_header->mac_dest_addr, arp_header->mac_src_addr, 6); memcpy(arp_header->mac.dest_addr, arp_header->mac_src_addr, 6); memcpy(arp_header->mac_src_addr, mac_get_host_addr(), 6); memcpy(arp_header->mac.src_addr, mac_get_host_addr(), 6); // Set new destination and source ip address memcpy(arp_header->ip_dest_addr, arp_header->ip_src_addr, 4); memcpy(arp_header->ip_src_addr, ip_get_host_addr(), 4); // Set the opcode to reply arp_header->opcode = htons((uint16_t)ARP_OPCODE_REPLY); // return packet size return sizeof(struct arp_header_t); break; case ARP_OPCODE_REPLY: // We insert or update the ARP table if it was meant for us. if(ip_addr_compare(arp_header->ip_dest_addr, ip_get_host_addr())) { arp_update(arp_header->ip_src_addr, arp_header->mac_src_addr); } // XXX: Unqueue packets for received destination. // See the queue_get_table and unqueue_packet funcions break; } return 0; }
void arp_process(void) { int i; #if debug_arp arp_display(); #endif //debug_arp if (differ_subnet(ARPr->senproaddr)==0) // only update addresses from local network devices arp_update(); // (the rest will use the Gateway's address) if (! memcmp(ARPr->tarproaddr, MyIP, 4)) { // is this ARP message for us? if (ARPr->opcode == HTONS(ARP_Request)) { // is this an ARP Request? ARPt->hwtype = HTONS(0x0001); ARPt->protype = HTONS(0x0800); ARPt->hwaddrlen = 6; ARPt->proaddrlen = 4; ARPt->opcode= HTONS(ARP_Reply); // Opcode for ARP Reply memcpy(ARPt->tarhwaddr, ARPr->senhwaddr, 6); // use the sender MAC address memcpy(ARPt->tarproaddr, ARPr->senproaddr, 4); // use the sender IP address memcpy(ARPt->senhwaddr, MyMAC, 6); // use our MAC address memcpy(ARPt->senproaddr, MyIP, 4); // use our IP address for(i=0;i<18;i++) tx_buf[42+i] = 0x20; ethernet_send(ARP_PROTOCOL, sizeof(struct arp_hdr)+18); // Send frame (Padding) } } }
void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr) { in_addr_t ipaddr = net_ip4addr_conv32(pipaddr); /* Update the ARP table */ (void)arp_update(ipaddr, ethaddr); }
static inline void dhcpd_arpupdate(uint16_t *pipaddr, uint8_t *phwaddr) { uip_lock_t flags; /* Disable interrupts and update the ARP table -- very non-portable hack. * REVISIT -- switch to the SIOCSARP ioctl call if/when it is implemented. */ flags = uip_lock(); arp_update(pipaddr, phwaddr); uip_unlock(flags); }
static int netdev_arp_ioctl(FAR struct socket *psock, int cmd, FAR struct arpreq *req) { int ret; /* Execute the command */ switch (cmd) { case SIOCSARP: /* Set an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET && req->arp_ha.sa_family == ARPHRD_ETHER) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Update any existing ARP table entry for this protocol * address -OR- add a new ARP table entry if there is not. */ ret = arp_update(addr->sin_addr.s_addr, (FAR uint8_t *)req->arp_ha.sa_data); } else { ret = -EINVAL; } } break; case SIOCDARP: /* Delete an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Find the existing ARP table entry for this protocol address. */ FAR struct arp_entry_s *entry = arp_lookup(addr->sin_addr.s_addr); if (entry != NULL) { /* The ARP table is fixed size; an entry is deleted * by nullifying its protocol address. */ entry->at_ipaddr = 0; ret = OK; } else { ret = -ENOENT; } } else { ret = -EINVAL; } } break; case SIOCGARP: /* Get an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Get the hardware address from an existing ARP table entry * matching this protocol address. */ ret = arp_find(addr->sin_addr.s_addr, (FAR struct ether_addr *)req->arp_ha.sa_data); if (ret >= 0) { /* Return the mapped hardware address. */ req->arp_ha.sa_family = ARPHRD_ETHER; ret = OK; } } else { ret = -EINVAL; } } break; default: ret = -ENOTTY; break; } return ret; }
void arp_arpin(FAR struct net_driver_s *dev) { FAR struct arp_hdr_s *parp = ARPBUF; in_addr_t ipaddr; if (dev->d_len < (sizeof(struct arp_hdr_s) + NET_LL_HDRLEN)) { nlldbg("Too small\n"); dev->d_len = 0; return; } dev->d_len = 0; ipaddr = net_ip4addr_conv32(parp->ah_dipaddr); switch(parp->ah_opcode) { case HTONS(ARP_REQUEST): nllvdbg("ARP request for IP %04lx\n", (long)ipaddr); /* ARP request. If it asked for our address, we send out a reply. */ if (net_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { struct eth_hdr_s *peth = ETHBUF; /* First, we register the one who made the request in our ARP * table, since it is likely that we will do more communication * with this host in the future. */ arp_update(parp->ah_sipaddr, parp->ah_shwaddr); parp->ah_opcode = HTONS(ARP_REPLY); memcpy(parp->ah_dhwaddr, parp->ah_shwaddr, ETHER_ADDR_LEN); memcpy(parp->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); memcpy(peth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); memcpy(peth->dest, parp->ah_dhwaddr, ETHER_ADDR_LEN); parp->ah_dipaddr[0] = parp->ah_sipaddr[0]; parp->ah_dipaddr[1] = parp->ah_sipaddr[1]; net_ipaddr_hdrcopy(parp->ah_sipaddr, &dev->d_ipaddr); arp_dump(parp); peth->type = HTONS(ETHTYPE_ARP); dev->d_len = sizeof(struct arp_hdr_s) + NET_LL_HDRLEN; } break; case HTONS(ARP_REPLY): nllvdbg("ARP reply for IP %04lx\n", (long)ipaddr); /* ARP reply. We insert or update the ARP table if it was meant * for us. */ if (net_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { /* Yes... Insert the address mapping in the ARP table */ arp_update(parp->ah_sipaddr, parp->ah_shwaddr); /* Then notify any logic waiting for the ARP result */ arp_notify(net_ip4addr_conv32(parp->ah_sipaddr)); } break; } }