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; }
/*Returns 0 on success and error code on fail*/ int sr_handlearp(struct sr_instance** sr, uint8_t** ethernet_data_addr, struct sr_if* in_f, unsigned int len){ uint8_t *eth_pkt_buf; uint8_t *arp_pkt_buf; /* ARP packet buffer */ struct sr_if* ret_if; /* return interface */ printf("sr_handlearp"); sr_arp_hdr_t* arp_header_buffer = (sr_arp_hdr_t*)*ethernet_data_addr; ntoh_arp_hdr(&arp_header_buffer); /* converts header members into host byte order where appropriate */ /* Recieved ARP request! Reply to request. */ if(arp_header_buffer->ar_op == arp_op_request) { if ((ret_if = sr_get_interface_from_ip(*sr, arp_header_buffer->ar_tip))) { /* Target IP is IP of a Router Interface*/ /* Send an ARP reply (uint8_t*) */ /* Create reply frame */ eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); /* Allocate mem for reply packet buffer */ sr_ethernet_hdr_t *req_reply_eth_header = (sr_ethernet_hdr_t *) eth_pkt_buf; /* Build Ethernet Header */ memcpy(req_reply_eth_header->ether_dhost, arp_header_buffer->ar_sha, ETHER_ADDR_LEN); memcpy(req_reply_eth_header->ether_shost, in_f->addr, ETHER_ADDR_LEN); req_reply_eth_header->ether_type = ethertype_arp; /* Convert to network byte ordering */ hton_eth_hdr(&req_reply_eth_header); /* Get the Arp Buffer and Build the Arp packet*/ arp_pkt_buf = eth_pkt_buf + sizeof(sr_ethernet_hdr_t); sr_create_arp_packet(&arp_pkt_buf, arp_header_buffer, ret_if); /* Create arp packet to be sent as ARP reply, fill arp_pkt_buf with ARP reply header data */ /* Send the ARP reply packet */ sr_send_packet(*sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), in_f->name); free(eth_pkt_buf); } else { /* Target IP is *NOT* IP of a Router Interface */ /* I'm not sure what to do here yet MAYBE NOTHING?!*/ } } else if (arp_header_buffer->ar_op == arp_op_reply) { handle_arp_reply(*sr, *ethernet_data_addr, in_f); } return 0; }
int handle_arp_packet(struct sr_instance * sr, uint8_t * packet, unsigned int len ){ int res; struct sr_arp_hdr *arp_hdr = (struct sr_arp_hdr *)(packet + sizeof(sr_ethernet_hdr_t)); int arp_op = ntohs(arp_hdr->ar_op); /* check to see if the target IP belongs to one of our routers */ struct sr_if* assoc_iface = validate_ip(sr->if_list, arp_hdr->ar_tip); if (!assoc_iface){ /* if its not one of ours, ignore it */ return -1; } if (arp_op == arp_op_request){ /* this is an incoming request */ res = send_arp_response(sr, assoc_iface, packet, len); if (res != 0){ fprintf(stderr, "bad send_arp_response\n"); return -1; } } else if (arp_op == arp_op_reply) { /* this is an incoming reply */ res = handle_arp_reply(sr, packet, len); if (res != 0){ return -1; } } else { /* bad arp_op type */ return -1; } return 0; }
/* 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); }