/* Expects entire ethernet frame and ARP header still in network order. */ void handle_arp_reply(struct sr_instance *sr, uint8_t *pkt) { struct sr_if *requested_inf = find_interface_with_ip(sr, ntohl(get_arp_hdr(pkt)->ar_tip)); if (!requested_inf) { /*Only cache entry if the target IP is one of the router's addresses*/ return; } struct sr_arpreq *arpreq = sr_arpcache_insert(&(sr->cache), get_arp_hdr(pkt)->ar_sha, get_arp_hdr(pkt)->ar_sip); if (arpreq) { struct sr_packet *outgoing_pkt = arpreq->packets; while (outgoing_pkt) { sr_ethernet_hdr_t *eth_hdr = get_ethernet_hdr(outgoing_pkt->buf); sr_arp_hdr_t *incoming_arp_hdr = get_arp_hdr(pkt); memcpy(eth_hdr->ether_dhost, incoming_arp_hdr->ar_sha, ETHER_ADDR_LEN); sr_send_packet(sr, outgoing_pkt->buf, outgoing_pkt->len, outgoing_pkt->iface); outgoing_pkt = outgoing_pkt->next; } free(pkt); sr_arpreq_destroy(&(sr->cache), arpreq); } }
void process_arp_request( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface) { assert(sr); assert(packet); assert(interface); arp_hdr* arp = get_arp_hdr(packet, len); router_state *rs = get_router_state(sr); /* get interface list read lock */ lock_if_list_rd(rs); /* scan the interface list * match the requested ip */ node* n = get_router_state(sr)->if_list; while (n) { /* see if we have an interface matching the requested ip */ if (((iface_entry*)n->data)->ip == arp->arp_tip.s_addr) { send_arp_reply(sr, packet, len, (iface_entry*)(n->data)); break; } n = n->next; } /* release the interface list lock */ unlock_if_list(rs); }
/* * Send an arp reply out of the given interface, as a reply to the given packet */ void send_arp_reply(struct sr_instance *sr, const uint8_t *packet, unsigned int len, iface_entry* iface) { eth_hdr* eth = (eth_hdr*)packet; arp_hdr* arp_req = get_arp_hdr(packet, len); uint8_t* new_packet = (uint8_t*)malloc(sizeof(eth_hdr) + sizeof(arp_hdr)); /* Setup the ETHERNET header */ eth_hdr* new_eth = (eth_hdr*)new_packet; populate_eth_hdr(new_eth, eth->eth_shost, iface->addr, ETH_TYPE_ARP); /* Setup the ARP header */ arp_hdr* new_arp = get_arp_hdr(new_packet, sizeof(eth_hdr) + sizeof(arp_hdr)); populate_arp_hdr(new_arp, arp_req->arp_sha, arp_req->arp_sip.s_addr, iface->addr, iface->ip, ARP_OP_REPLY); /* Send the reply */ if (send_packet(sr, new_packet, sizeof(eth_hdr) + sizeof(arp_hdr), iface->name) != 0) { printf("Error sending ARP reply\n"); } free(new_packet); }
/* Expects entire ethernet frame and ARP header still in network order. */ void handle_arp_request(struct sr_instance *sr, uint8_t *pkt, char *interface) { struct sr_if *requested_inf = find_interface_with_ip(sr, ntohl(get_arp_hdr(pkt)->ar_tip)); if (!requested_inf) { /*Only send an arp reply if the target IP is one of the router's IP addresses*/ free(pkt); return; } uint8_t *outgoing_pkt = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); sr_ethernet_hdr_t *outgoing_eth_hdr = get_ethernet_hdr(outgoing_pkt); sr_arp_hdr_t *outgoing_arp_hdr = get_arp_hdr(outgoing_pkt); /*Ethernet*/ /*src MAC is the outgoing interface's MAC, dest MAC is the src MAC of the arp request*/ memcpy(outgoing_eth_hdr->ether_dhost, get_ethernet_hdr(pkt)->ether_shost, ETHER_ADDR_LEN); memcpy(outgoing_eth_hdr->ether_shost, requested_inf->addr, ETHER_ADDR_LEN); outgoing_eth_hdr->ether_type = htons(ethertype_arp); /*ARP*/ outgoing_arp_hdr->ar_hrd = htons(arp_hrd_ethernet); outgoing_arp_hdr->ar_pro = htons(ethertype_ip); outgoing_arp_hdr->ar_hln = ETHER_ADDR_LEN; outgoing_arp_hdr->ar_pln = NUM_BYTES_IN_IP_ADDR; outgoing_arp_hdr->ar_op = htons(arp_op_reply); memcpy(outgoing_arp_hdr->ar_sha, requested_inf->addr, ETHER_ADDR_LEN); outgoing_arp_hdr->ar_sip = requested_inf->ip; memcpy(outgoing_arp_hdr->ar_tha, get_arp_hdr(pkt)->ar_sha, ETHER_ADDR_LEN); outgoing_arp_hdr->ar_tip = get_arp_hdr(pkt)->ar_sip; sr_send_packet(sr, (uint8_t *)outgoing_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), interface); /*No reliability guarantee, so don't keep around for a restransmit*/ free(outgoing_pkt); free(pkt); }
void process_arp_packet( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface) { assert(sr); assert(packet); assert(interface); arp_hdr *arp_packet = get_arp_hdr(packet, len); switch(ntohs(arp_packet->arp_op)) { case ARP_OP_REQUEST: process_arp_request(sr, packet, len, interface); break; case ARP_OP_REPLY: process_arp_reply(sr, packet, len, interface); break; default: return; } }
void process_arp_reply( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface) { assert(sr); assert(packet); assert(interface); router_state *rs = get_router_state(sr); /* update the arp cache */ arp_hdr *arp = get_arp_hdr(packet, len); lock_arp_cache_wr(rs); update_arp_cache(sr, &(arp->arp_sip), arp->arp_sha, 0); unlock_arp_cache(rs); lock_arp_cache_rd(rs); lock_arp_queue_wr(rs); send_queued_packets(sr, &(arp->arp_sip), arp->arp_sha); unlock_arp_queue(rs); unlock_arp_cache(rs); }
/* 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 print_arp_hdr(const uint8_t *packet, unsigned int len) { assert(packet); arp_hdr *arp = get_arp_hdr(packet, len); indent(1); printf("ARP Packet (%d bytes)\n", sizeof(arp_hdr)); indent(2); printf("Hardware Type: "); switch(ntohs(arp->arp_hrd)) { case 1: { printf("Ethernet\n"); break; } default: { printf("%X\n", ntohs(arp->arp_hrd)); break; } } indent(2); printf("Protocol Type = %X (IP)\n", ntohs(arp->arp_pro)); indent(2); printf("Hardware Address Length = %d\n", arp->arp_hln); indent(2); printf("Protocol Address Length = %d\n", arp->arp_pln); indent(2); printf("Opcode = "); switch(ntohs(arp->arp_op)) { case 1: { printf("Request\n"); break; } case 2: { printf("Reply\n"); break; } default: { printf("%X\n", arp->arp_op); break; } } indent(2); print_mac_address("Src Hardware Address", arp->arp_sha); indent(2); print_ip_address("Src Protocol Address", arp->arp_sip); indent(2); print_mac_address("Dst Hardware Address", arp->arp_tha); indent(2); print_ip_address("Dst Protocol Address", arp->arp_tip); }
/* handle/generate ARP packet */ void sr_handle_arppacket(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */) { assert(sr); assert(packet); assert(interface); /* Get ethernet header */ sr_ethernet_hdr_t *eth_hdr = (sr_ethernet_hdr_t *)get_eth_hdr(packet); if (eth_hdr == NULL) { printf("ethernet header NULL!!!\n"); return; } /* Get arp header */ sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)get_arp_hdr(packet); if (arp_hdr == NULL) { printf("arp header NULL!!!\n"); return; } /* Check the arp packet minimum length */ if (!check_min_length(len, ARP_PACKET_LEN)) { fprintf(stderr, "arp packet length is not enough:(\n"); return; } /* check the opcode to see if it is request or reply */ unsigned short ar_op = ntohs(arp_hdr->ar_op); /* Get the connected interface in the router */ struct sr_if *sr_con_if = sr_get_interface(sr, interface); /* Get the detination interface in the router */ /* If the connected interface exists, because arp has to be the connected interface */ if (sr_con_if) { /* ********** ARP request ********** */ /* Construct an arp reply and send it back */ if (ar_op == arp_op_request) { /*fprintf(stderr, "********** ARP REQUEST **********\n"); ar_op = 1 */ /* Set the back-packet length */ int packet_len = ARP_PACKET_LEN; uint8_t *arp_reply_hdr = (uint8_t *)malloc(packet_len); /* Create ethernet header */ create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)arp_reply_hdr, sr_con_if); /* Create arp header */ create_back_arp_hdr(arp_hdr, (sr_arp_hdr_t *)((unsigned char *)arp_reply_hdr+ETHER_PACKET_LEN), sr_con_if); /* Send APR reply */ sr_send_packet(sr, /*(sr_ethernet_hdr_t *)*/arp_reply_hdr, packet_len, sr_con_if->name); free(arp_reply_hdr); return; } /* ********** ARP reply ********** */ /* Cache it, go thru my request queue and send outstanding packets */ else if (ar_op == arp_op_reply) { /*fprintf(stderr, "********** ARP REPLY **********\n"); ar_op = 2 */ /* cache first, and send all the packets in the queue with ip->mac mapping!!! */ handle_arpreply(arp_hdr, sr); return; } /* ********** Otherwise, error! ********** */ else { fprintf(stderr, "Invalid arp type!!!\n"); return; } } else { fprintf(stderr, "Router doesnt have this interface, drop it!\n"); return; } return; }