void bnep_dump(int level, struct frame *frm) { uint8_t type = p_get_u8(frm); uint16_t proto = 0x0000; int extension = type & 0x80; p_indent(level, frm); switch (type & 0x7f) { case BNEP_CONTROL: printf("BNEP: Control(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0"); bnep_control(level, frm, -1); break; case BNEP_COMPRESSED_ETHERNET: printf("BNEP: Compressed(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0"); p_indent(++level, frm); proto = p_get_u16(frm); printf("[proto 0x%04x]\n", proto); break; case BNEP_GENERAL_ETHERNET: printf("BNEP: General ethernet(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0"); p_indent(++level, frm); printf("dst %s ", get_macaddr(frm)); printf("src %s ", get_macaddr(frm)); proto = p_get_u16(frm); printf("[proto 0x%04x]\n", proto); break; case BNEP_COMPRESSED_ETHERNET_DEST_ONLY: printf("BNEP: Compressed DestOnly(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0"); p_indent(++level, frm); printf("dst %s ", get_macaddr(frm)); proto = p_get_u16(frm); printf("[proto 0x%04x]\n", proto); break; case BNEP_COMPRESSED_ETHERNET_SOURCE_ONLY: printf("BNEP: Compressed SrcOnly(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0"); p_indent(++level, frm); printf("src %s ", get_macaddr(frm)); proto = p_get_u16(frm); printf("[proto 0x%04x]\n", proto); break; default: printf("(Unknown packet type)\n"); return; } /* Extension info */ if (extension) bnep_eval_extension(++level, frm); /* Control packet => No payload info */ if ((type & 0x7f) == BNEP_CONTROL) return; /* 802.1p header */ if (proto == 0x8100) { p_indent(level, frm); printf("802.1p Header: 0x%04x ", p_get_u16(frm)); proto = p_get_u16(frm); printf("[proto 0x%04x]\n", proto); } if (!(parser.flags & DUMP_VERBOSE)) { raw_dump(level, frm); return; } switch (proto) { case ETHERTYPE_ARP: p_indent(++level, frm); printf("ARP: "); arp_dump(level, frm); break; case ETHERTYPE_REVARP: p_indent(++level, frm); printf("RARP: "); arp_dump(level, frm); break; case ETHERTYPE_IP: p_indent(++level, frm); printf("IP: "); ip_dump(level, frm); break; case ETHERTYPE_IPV6: p_indent(++level, frm); printf("IPV6: "); ip_dump(level, frm); break; default: raw_dump(level, frm); break; } }
void arp_out(FAR struct net_driver_s *dev) { struct ether_addr ethaddr; FAR struct eth_hdr_s *peth = ETHBUF; FAR struct arp_iphdr_s *pip = IPBUF; in_addr_t ipaddr; in_addr_t destipaddr; int ret; #if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_ARP_SEND) /* Skip sending ARP requests when the frame to be transmitted was * written into a packet socket. */ if (IFF_IS_NOARP(dev->d_flags)) { /* Clear the indication and let the packet continue on its way. */ IFF_CLR_NOARP(dev->d_flags); return; } #endif /* Find the destination IP address in the ARP table and construct * the Ethernet header. If the destination IP address isn't on the * local network, we use the default router's IP address instead. * * If not ARP table entry is found, we overwrite the original IP * packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if (net_ipv4addr_hdrcmp(pip->eh_destipaddr, g_broadcast_ipaddr)) { memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); goto finish_header; } #ifdef CONFIG_NET_IGMP /* Check if the destination address is a multicast address * * - IPv4: multicast addresses lie in the class D group -- The address range * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) * * - IPv6 multicast addresses are have the high-order octet of the * addresses=0xff (ff00::/8.) */ if (NTOHS(pip->eh_destipaddr[0]) >= 0xe000 && NTOHS(pip->eh_destipaddr[0]) <= 0xefff) { /* Build the well-known IPv4 IGMP Ethernet address. The first * three bytes are fixed; the final three variable come from the * last three bytes of the IPv4 address (network order). * * Address range : 01:00:5e:00:00:00 to 01:00:5e:7f:ff:ff */ FAR const uint8_t *ip = (FAR uint8_t *)pip->eh_destipaddr; peth->dest[0] = g_multicast_ethaddr[0]; peth->dest[1] = g_multicast_ethaddr[1]; peth->dest[2] = g_multicast_ethaddr[2]; peth->dest[3] = ip[1] & 0x7f; peth->dest[4] = ip[2]; peth->dest[5] = ip[3]; goto finish_header; } #endif /* Check if the destination address is on the local network. */ destipaddr = net_ip4addr_conv32(pip->eh_destipaddr); if (!net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)) { /* Destination address is not on the local network */ #ifdef CONFIG_NET_ROUTE /* We have a routing table.. find the correct router to use in * this case (or, as a fall-back, use the device's default router * address). We will use the router IP address instead of the * destination address when determining the MAC address. */ netdev_ipv4_router(dev, destipaddr, &ipaddr); #else /* Use the device's default router IP address instead of the * destination address when determining the MAC address. */ net_ipv4addr_copy(ipaddr, dev->d_draddr); #endif } /* The destination address is on the local network. Check if it is * the sub-net broadcast address. */ else if (net_ipv4addr_broadcast(destipaddr, dev->d_netmask)) { /* Yes.. then we won't need to know the destination MAC address */ memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); goto finish_header; } else { /* Else, we use the destination IP address. */ net_ipv4addr_copy(ipaddr, destipaddr); } /* Check if we already have this destination address in the ARP table */ ret = arp_find(ipaddr, ðaddr); if (ret < 0) { ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr); /* The destination address was not in our ARP table, so we overwrite * the IP packet with an ARP request. */ arp_format(dev, ipaddr); arp_dump(ARPBUF); return; } /* Build an Ethernet header. */ memcpy(peth->dest, ethaddr.ether_addr_octet, ETHER_ADDR_LEN); /* Finish populating the Ethernet header */ finish_header: memcpy(peth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN); peth->type = HTONS(ETHTYPE_IP); dev->d_len += ETH_HDRLEN; }
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; } }