static status_t arp_receive(void *cookie, net_device *device, net_buffer *buffer) { TRACE(("ARP receive\n")); NetBufferHeaderReader<arp_header> bufferHeader(buffer); if (bufferHeader.Status() < B_OK) return bufferHeader.Status(); arp_header &header = bufferHeader.Data(); uint16 opcode = ntohs(header.opcode); #ifdef TRACE_ARP dprintf(" hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n", header.hardware_sender[0], header.hardware_sender[1], header.hardware_sender[2], header.hardware_sender[3], header.hardware_sender[4], header.hardware_sender[5]); dprintf(" proto sender: %ld.%ld.%ld.%ld\n", header.protocol_sender >> 24, (header.protocol_sender >> 16) & 0xff, (header.protocol_sender >> 8) & 0xff, header.protocol_sender & 0xff); dprintf(" hw target: %02x:%02x:%02x:%02x:%02x:%02x\n", header.hardware_target[0], header.hardware_target[1], header.hardware_target[2], header.hardware_target[3], header.hardware_target[4], header.hardware_target[5]); dprintf(" proto target: %ld.%ld.%ld.%ld\n", header.protocol_target >> 24, (header.protocol_target >> 16) & 0xff, (header.protocol_target >> 8) & 0xff, header.protocol_target & 0xff); #endif if (ntohs(header.protocol_type) != ETHER_TYPE_IP || ntohs(header.hardware_type) != ARP_HARDWARE_TYPE_ETHER) return B_BAD_TYPE; // check if the packet is okay if (header.hardware_length != ETHER_ADDRESS_LENGTH || header.protocol_length != sizeof(in_addr_t)) return B_BAD_DATA; // handle packet switch (opcode) { case ARP_OPCODE_REQUEST: TRACE((" got ARP request\n")); if (handle_arp_request(buffer, header) == B_OK) { // the function will take care of the buffer if everything // went well return B_OK; } break; case ARP_OPCODE_REPLY: TRACE((" got ARP reply\n")); handle_arp_reply(buffer, header); break; default: dprintf("unknown ARP opcode %d\n", opcode); return B_ERROR; } gBufferModule->free(buffer); return B_OK; }
static void transfer_boot(libusb_device_handle *handle, uint8_t endpoint, const char *name, const char *tip) { struct ethhdr eth_hdr; udp_t udp; memset(ð_hdr, 0, sizeof(struct ethhdr)); memset(&udp, 0, sizeof(udp_t)); printf(" %s\n\n", tip); handle_bootp_request(handle, endpoint, name); handle_arp_request(handle, endpoint); handle_tftp_request(handle, ð_hdr, &udp); if (udp.udpDst == 0 || udp.udpSrc == 0) { printf("Receive UDP packet failed.\n"); exit(EXIT_FAILURE); } tftp_send_file(handle, endpoint, eth_hdr.h_source, udp.udpDst, udp.udpSrc, name); }
/* Expects entire ethernet frame, still in network order. */ void handle_arp(struct sr_instance *sr, uint8_t *pkt, char* interface, unsigned int len) { sr_arp_hdr_t *arp_hdr = get_arp_hdr(pkt); unsigned short ar_op = ntohs(arp_hdr->ar_op); /*Should at least be this long*/ if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)) { free(pkt); free(interface); return; } if (ar_op == arp_op_request) { handle_arp_request(sr, pkt, interface); } else if (ar_op == arp_op_reply) { handle_arp_reply(sr, pkt); } else { free(pkt); fprintf(stderr, "invalid arp opcode\n"); } free(interface); }
void sr_handlepacket(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */) { /* REQUIRES */ assert(sr); assert(packet); assert(interface); printf("*** -> Received packet of length %d on interface \"%s\"\n", len, interface); // Deconstruct the packet's ethernet header struct sr_ethernet_hdr *header = malloc(sizeof(struct sr_ethernet_hdr)); memcpy(header, packet, sizeof(struct sr_ethernet_hdr)); header->ether_type = htons(header->ether_type); // Determine proper routing behavior based on ether_type switch(header->ether_type) { case ETHERTYPE_ARP: { // Unpack the ARP header struct sr_arphdr *arp_header = malloc(sizeof(struct sr_arphdr)); memcpy(arp_header, packet + 14, sizeof(struct sr_arphdr)); arp_header->ar_op = ntohs(arp_header->ar_op); // Check the ARP opcode switch(arp_header->ar_op) { case ARP_REQUEST: handle_arp_request(sr, header, arp_header, interface); break; case ARP_REPLY: printf("\tIt's an ARP reply!\n"); add_arp_cache_entry(cache, arp_header->ar_sip, arp_header->ar_sha); struct in_addr addr = {arp_header->ar_sip}; printf("\tMapping %s to ", inet_ntoa(addr)); print_ethernet_addr(arp_header->ar_sha, stdout); printf("\n"); // Scan for packets we can retransmit struct ip_cache_entry *cache_entry = next_packet_with_dest(ip_cache, addr); struct sr_if *iface = sr_get_interface(sr, interface); while(cache_entry) { // Wrap the IP packet in an ethernet header uint8_t *wrapped_packet = pack_ethernet_packet(arp_header->ar_sha, iface->addr, ETHERTYPE_IP, cache_entry->packet, cache_entry->len); // Send the newly wrapped packet sr_send_packet(sr, wrapped_packet, sizeof(struct sr_ethernet_hdr) + cache_entry->len, iface->name); // TODO: We're dumb are forgot this cache_entry = next_packet_with_dest(ip_cache, addr); } break; } break; } case ETHERTYPE_IP: { // TODO printf("\tIt's an IP packet!\n"); route_ip_packet(sr, packet, len, interface); break; } default: { printf("\tIt's an unknown packet type (ether_type = 0x%X)\n", header->ether_type); break; } } } /* end sr_ForwardPacket */