void sr_handleARPpacket(struct sr_instance *sr, uint8_t* packet, unsigned int len, struct sr_if * iface) { assert(packet); sr_ethernet_hdr_t* ethHeader = (sr_ethernet_hdr_t*) packet; sr_arp_hdr_t * arpHeader = (sr_arp_hdr_t *) (packet+14); enum sr_arp_opcode request = arp_op_request; enum sr_arp_opcode reply = arp_op_reply; struct sr_if *interface = sr_get_interface_from_ip(sr, htonl(arpHeader->ar_tip)); /* handle an arp request.*/ if (ntohs(arpHeader->ar_op) == request) { /* found an ip->mac mapping. send a reply to the requester's MAC addr */ if (interface){ arpHeader->ar_op = ntohs(reply); uint32_t temp = arpHeader->ar_sip; arpHeader->ar_sip = arpHeader->ar_tip; arpHeader->ar_tip = temp; memcpy(arpHeader->ar_tha, arpHeader->ar_sha,6); memcpy(arpHeader->ar_sha, iface->addr,6); /*swapping outgoing and incoming addr*/ set_addr(ethHeader, iface->addr, ethHeader->ether_shost); sr_send_packet(sr,(uint8_t*)ethHeader,len,iface->name); } } /* handle an arp reply */ else { struct sr_packet *req_packet = NULL; struct sr_arpreq *req = NULL; pthread_mutex_lock(&(sr->cache.lock)); for (req = sr->cache.requests; req != NULL; req = req->next){ if(req->ip == arpHeader->ar_sip){ /* find the interface the packets should be sent out of */ struct sr_rt * rt = (struct sr_rt *)sr_find_routing_entry_int(sr, req->ip); if (rt) { iface = sr_get_interface(sr, rt->interface); /* send all packets waiting on the request that was replied to */ for (req_packet = req->packets; req_packet != NULL; req_packet = req_packet->next) { sr_ethernet_hdr_t * outEther = (sr_ethernet_hdr_t *)req_packet->buf; memcpy(outEther->ether_shost, iface->addr,6); memcpy(outEther->ether_dhost, ethHeader->ether_shost,6); sr_ip_hdr_t * outIP = (sr_ip_hdr_t *)(req_packet->buf+14); outIP->ip_ttl = outIP->ip_ttl-1; outIP->ip_sum = 0; outIP->ip_sum = cksum((uint8_t *)outIP,20); sr_send_packet(sr,req_packet->buf,req_packet->len,iface->name); } sr_arpreq_destroy(&(sr->cache), req); } break; } } pthread_mutex_unlock(&(sr->cache.lock)); sr_arpcache_insert(&(sr->cache),arpHeader->ar_sha,arpHeader->ar_sip); } }
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) { time_t now = time(NULL); if(difftime(now, req->sent) > 1.0) { /* request timeout */ if(req->times_sent > 5) { struct sr_packet *packets = req->packets; /* iterate through all packets on queue */ while(packets) { uint8_t *reply_packet = 0; sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packets->buf+sizeof(sr_ethernet_hdr_t)); reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packets->buf, ip_hdr, sr_get_interface(sr, packets->iface), 3, 1); /* create ICMP type 3, code 1 (host unreachable) */ /* if ICMP packet fails to generate */ if(reply_packet == 0) { fprintf(stderr, "Error: failed to generate ICMP packet\n"); } /* send ICMP packet to ip of packet in queue */ if(sr_send_packet(sr, reply_packet, sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t), (const char*)(packets->iface)) == -1) { fprintf(stderr, "Error: sending packet failed (handle_arpreq)"); } packets = packets->next; free(reply_packet); } sr_arpreq_destroy(&(sr->cache), req); } else { /* generate ARP packet */ struct sr_if *iface = 0; /* if interface is not found */ if((iface = sr_get_interface(sr, req->packets->iface)) == 0) { fprintf(stderr, "Error: interface does not exist (handle_arpreq)"); return; } uint8_t *arp_pkt = sr_new_arpreq_packet(NULL, iface->addr, req->ip, iface->ip); /* create ARP request packet to re-send */ /* send ARP request packet */ if (sr_send_packet(sr, arp_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), (const char*)(iface->name))==-1) { fprintf(stderr, "Error: sending packet failed."); } /* update arpreq fields */ req->times_sent++; req->sent = now; free(arp_pkt); } } }
/* * When we want to send an ip packet, we need to firstly check arp acache. */ void sr_check_and_send_arp(struct sr_instance* sr, uint8_t* packet, uint32_t next_hop_ip, struct sr_if* out_iface, unsigned int len) { Debug("\ncheck_and_send_arp called\n"); struct sr_arpentry* entry = sr_arpcache_lookup(&(sr->cache), next_hop_ip); if(entry) { Debug("\narp_cache hit!\n"); next_hop_ip = entry->ip; int i; for (i = 0; i < ETHER_ADDR_LEN; i++) { packet[i] = entry->mac[i]; } sr_send_packet(sr, packet, len, out_iface->name); free(packet); free(entry); } else { Debug("\narp_cache miss; call handle_arppreq\n"); struct sr_arpreq* req = sr_arpcache_queuereq(&(sr->cache), next_hop_ip, packet, len, out_iface->name); free(packet); sr_handle_arpreq(sr, req); } }
void arp_respond(struct sr_instance* sr, uint8_t * req_packet, struct sr_if * sr_interface) { struct sr_arphdr *req_arp_hdr = (struct sr_arphdr *)(req_packet + sizeof(struct sr_ethernet_hdr)); /* Setup ethernet frame */ unsigned int resp_len = sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arphdr); uint8_t *resp_packet = (uint8_t *)construct_ethernet_frame( sr_interface->addr, req_arp_hdr->ar_sha, ETHERTYPE_ARP, sizeof(struct sr_arphdr)); if(resp_packet == NULL) { fprintf(stderr, "Failed to construct ethernet frame.\n"); return; } /* Setup arp packet */ struct sr_arphdr *resp_arp_hdr = (struct sr_arphdr *)(resp_packet+sizeof(struct sr_ethernet_hdr)); resp_arp_hdr->ar_hrd = htons(ARPHDR_ETHER); resp_arp_hdr->ar_pro = htons(ETHERTYPE_IP); resp_arp_hdr->ar_hln = ETHER_ADDR_LEN; resp_arp_hdr->ar_pln = IP_ADDR_LEN; resp_arp_hdr->ar_op = htons(ARP_REPLY); memcpy(resp_arp_hdr->ar_sha, sr_interface->addr, ETHER_ADDR_LEN); resp_arp_hdr->ar_sip = sr_interface->ip; memcpy(resp_arp_hdr->ar_tha, req_arp_hdr->ar_sha, ETHER_ADDR_LEN); resp_arp_hdr->ar_tip = req_arp_hdr->ar_sip; /* Send packet */ //printf("*** -> Sending ARP reply packet of length %d.\n", resp_len); if(sr_send_packet(sr, resp_packet, resp_len, sr_interface->name)) { fprintf(stderr, "Failed to send ARP response packet.\n"); } else { //print_etherinfo(resp_packet); dump(resp_packet, resp_len); } free(resp_packet); }
void cache_add_packet(struct sr_instance * sr, uint8_t * packet, unsigned int length, char * interface, struct in_addr ip) { struct in_addr dest_ip = next_hop_ip(sr, ip); struct sr_arp_record *record = cache_lookup(sr, dest_ip); if(record == NULL) { // Check to see if there is an outstanding ARP request struct sr_arp_request *request = cache_lookup_outstanding(sr, dest_ip); if(request == NULL) { // Create a new ARP request if(arp_request(sr, dest_ip, interface) == 0) { request = cache_add_request(sr, dest_ip); // Add the recieved message to the outstanding arp request cache_add_message(request, packet, length, interface, ip); } /* endif: arp request sent succesfully */ else { printf("ARP request failed for address %s - dropping packet.\n", inet_ntoa(ip)); } /* endelse: arp request not sent succesfully */ } /* endif: no outstanding ARP request */ else { cache_add_message(request, packet, length, interface, ip); } /* endelse: ARP request already outstanding for this ip */ } /* endif: No record */ else { // Send packet struct sr_ethernet_hdr *eth_hdr = (struct sr_ethernet_hdr *)packet; memcpy(eth_hdr->ether_dhost, record->address, ETHER_ADDR_LEN); sr_send_packet(sr, packet, length, interface); } /* endelse: ARP record already exists */ }
/*forwards normal IP packet, returns 1 on success*/ int ip_forward(struct sr_instance* sr, uint8_t* packet, int len, struct sr_ethernet_hdr* ethernet_hdr, uint8_t dest_mac[], uint32_t dest_ip, uint16_t cksum, char* interface){ //reuse some of old contents, change some //uint8_t a[ETHER_ADDR_LEN]; int j; for(j=0;j<ETHER_ADDR_LEN;j++){ (ethernet_hdr->ether_dhost)[j] = dest_mac[j]; } struct sr_if* ifRecord = (struct sr_if*)getIfRecord(sr, dest_ip); //unsigned char addr[ETHER_ADDR_LEN] uint8_t addr[ETHER_ADDR_LEN]; convertMAC(addr, ifRecord->addr); //int j; for (j=0;j<ETHER_ADDR_LEN;j++){ (ethernet_hdr->ether_shost)[j] = addr[j]; } sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)(packet + (uint8_t)eth_size); ip_header->ip_sum = htonl(modCksum); //Send packet int ret = sr_send_packet(sr, packet, len, interface); if (ret != 0){ fprintf(stderr, "Didn't send packet properly\n"); } return ret; }
void sr_send_arp_request(struct sr_instance *sr, struct sr_if *oiface, uint32_t tip) { assert(sr); assert(oiface); unsigned int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t); uint8_t *buf = (uint8_t *)malloc(len); assert(buf); sr_ethernet_hdr_t *eth_hdr = (sr_ethernet_hdr_t *)buf; sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(buf + sizeof(sr_ethernet_hdr_t)); /* ethernet header */ memset(eth_hdr->ether_dhost, 255, ETHER_ADDR_LEN); memcpy(eth_hdr->ether_shost, oiface->addr, ETHER_ADDR_LEN); eth_hdr->ether_type = htons(ethertype_arp); /* arp header */ arp_hdr->ar_hrd = htons(arp_hrd_ethernet); arp_hdr->ar_pro = htons(ethertype_ip); arp_hdr->ar_hln = ETHER_ADDR_LEN; arp_hdr->ar_pln = sizeof(uint32_t); arp_hdr->ar_op = htons(arp_op_request); memcpy(arp_hdr->ar_sha, oiface->addr, ETHER_ADDR_LEN); arp_hdr->ar_sip = oiface->ip; memset(arp_hdr->ar_tha, 0, ETHER_ADDR_LEN); arp_hdr->ar_tip = tip; /* print_hdrs(buf, len); */ sr_send_packet(sr, buf, len, oiface->name); free(buf); } /* -- sr_send_arp_request -- */
/* * Send ARP request. */ void send_arp_request(struct sr_instance *sr, uint32_t dst_ip, char *interface) { uint8_t *packet = (uint8_t *)malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); unsigned int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t); struct sr_if *rt_if = (struct sr_if *)sr_get_interface(sr, interface); uint8_t brdcst_addr[ETHER_ADDR_LEN]; int i = 0; for(i; i < ETHER_ADDR_LEN; i++){ brdcst_addr[i] = 255; } /* Prepare ethernet header. */ sr_ethernet_hdr_t *ether_hdr = (sr_ethernet_hdr_t *)(packet); ether_hdr->ether_type = htons(ethertype_arp); memcpy(ether_hdr->ether_shost, rt_if->addr, ETHER_ADDR_LEN); memcpy(ether_hdr->ether_dhost, brdcst_addr, ETHER_ADDR_LEN); /* Prepare ARP header. */ sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t)); arp_hdr->ar_hrd = htons(arp_hrd_ethernet); arp_hdr->ar_pro = htons(ethertype_ip); arp_hdr->ar_hln = ETHER_ADDR_LEN; arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(arp_op_request); memcpy(arp_hdr->ar_sha, rt_if->addr, ETHER_ADDR_LEN); arp_hdr->ar_sip = rt_if->ip; memcpy(arp_hdr->ar_tha, brdcst_addr, ETHER_ADDR_LEN); arp_hdr->ar_tip = dst_ip; /* Send the packet. */ sr_send_packet(sr, packet, len, interface); }
void sr_send_arpreq(struct sr_instance *sr, uint32_t ip, struct sr_if* iface) { assert(iface); const int pktlen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t); uint8_t* pktbuf = calloc(1, pktlen); sr_fill_eth(pktbuf, NULL, iface->addr, ethertype_arp); /* Fill ARP Request */ sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(pktbuf + sizeof(sr_ethernet_hdr_t)); arp_hdr->ar_hrd = htons(1); /* Hardware type : Ethernet(1) */ arp_hdr->ar_pro = htons(0x0800); /* Protocol type : ARP (0x0800) */ arp_hdr->ar_hln = ETHER_ADDR_LEN; arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(arp_op_request); /* sender hardware address */ memcpy(arp_hdr->ar_sha, iface->addr, ETHER_ADDR_LEN); arp_hdr->ar_sip = iface->ip; /* sender ip address */ /* target hardware address */ memset(arp_hdr->ar_tha, 0, ETHER_ADDR_LEN); arp_hdr->ar_tip = ip; /* target ip address */ /* Send ARP Request */ sr_send_packet(sr, pktbuf, pktlen, iface->name); free(pktbuf); }
/*--------------------------------------------------------------------- * Method: handle_arp_request * Scope: local * * Handles an ARP request sent to an interface. * *---------------------------------------------------------------------*/ static void handle_arp_request(struct sr_instance *sr, struct sr_ethernet_hdr *ethernet_header, struct sr_arphdr *arp_header, char *interface) { printf("\tIt's an ARP request!\n"); // Get the interface address struct sr_if* iface = sr_get_interface(sr, interface); if ( iface == 0 ) { fprintf( stderr, "** Error, interface %s, does not exist\n", interface); } // Create ARP reply :) struct sr_arphdr arp_reply; memcpy(&arp_reply, arp_header, sizeof(struct sr_arphdr)); arp_reply.ar_op = htons(ARP_REPLY); memcpy(&arp_reply.ar_sha, iface->addr, ETHER_ADDR_LEN); memcpy(&arp_reply.ar_tha, arp_header->ar_sha, ETHER_ADDR_LEN); memcpy(&arp_reply.ar_sip, &(arp_header->ar_tip), sizeof(uint32_t)); memcpy(&arp_reply.ar_tip, &(arp_header->ar_sip), sizeof(uint32_t)); // Send the reply uint8_t *buffer = pack_ethernet_packet(ethernet_header->ether_shost, iface->addr, ETHERTYPE_ARP, (uint8_t *) &arp_reply, sizeof(struct sr_arphdr)); sr_send_packet(sr, buffer, sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arphdr), interface); }
void ARP_request_send(struct sr_instance* sr,uint32_t gateway_IP,struct sr_if* interface) { /* Build both ethernet and ARP header for the request packet */ uint8_t* packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); /* Build ethernet header */ sr_ethernet_hdr_t* new_eth = (sr_ethernet_hdr_t*)packet; memcpy(new_eth->ether_shost,interface->addr,sizeof(uint8_t)*6); memset(new_eth->ether_dhost,255,sizeof(uint8_t)*6); new_eth->ether_type = htons(ARP_PROTOCOL); /* Build ARP header */ sr_arp_hdr_t* arp_reply_structure = (sr_arp_hdr_t*)(packet+sizeof(sr_ethernet_hdr_t)); arp_reply_structure->ar_op = htons(0x0001); memcpy(arp_reply_structure->ar_sha,interface->addr,sizeof(uint8_t)*6); bzero(arp_reply_structure->ar_tha,sizeof(uint8_t)*6); arp_reply_structure->ar_sip = interface->ip; arp_reply_structure->ar_tip = gateway_IP; arp_reply_structure->ar_pro = htons(0x0800); arp_reply_structure->ar_pln = 0x04; arp_reply_structure->ar_hrd = htons(0x0001); arp_reply_structure->ar_hln = 0x06; /* Now everything is complete */ /* Now send the packet */ sr_send_packet(sr,packet,sizeof(sr_ethernet_hdr_t)+sizeof(sr_arp_hdr_t),interface->name); }
void sr_send_arpreply(struct sr_instance* sr, sr_arp_hdr_t *arp_req, struct sr_if* iface) { const int pktlen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t); uint8_t pktbuf[pktlen]; sr_fill_eth(pktbuf, arp_req->ar_sha, iface->addr, ethertype_arp); /* Fill ARP Reply */ sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(pktbuf + sizeof(sr_ethernet_hdr_t)); arp_hdr->ar_hrd = htons(1); /* Hardware type : Ethernet(1) */ arp_hdr->ar_pro = htons(0x0800); /* Protocol type : ARP (0x0800) */ arp_hdr->ar_hln = ETHER_ADDR_LEN; arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(arp_op_reply); /* sender hardware address */ memcpy(arp_hdr->ar_sha, iface->addr, ETHER_ADDR_LEN); arp_hdr->ar_sip = iface->ip; /* sender ip address */ /* target hardware address */ memcpy(arp_hdr->ar_tha, arp_req->ar_sha, ETHER_ADDR_LEN); arp_hdr->ar_tip = arp_req->ar_sip; /* target ip address */ /* Send ARP Reply */ sr_send_packet(sr, pktbuf, pktlen, iface->name); }
/* Tries to find ip address in arp cache. If found, sends ethernet frame. If not found, adds packet to arp queue */ void sr_attempt_send(struct sr_instance *sr, uint32_t ip_dest, uint8_t *frame, unsigned int frame_len, char *iface){ struct sr_arpentry *entry = sr_arpcache_lookup(&(sr->cache), ip_dest); if (entry){ unsigned char *mac_address = entry->mac; memcpy( ((sr_ethernet_hdr_t *)frame)->ether_dhost, mac_address, ETHER_ADDR_LEN); //free packet?? sr_send_packet(sr, frame, frame_len, iface); free(entry); }else{ fprintf(stderr, "Couldn't find entry for: "); print_addr_ip_int(ntohl(ip_dest)); struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), ip_dest, frame, frame_len, iface); sr_handle_arpreq(sr, req); } }
void sr_icmp_echo_reply(struct sr_instance *sr, uint8_t * packet, unsigned int len, char* interface, struct sr_ethernet_hdr *e_hdr, struct ip *ip_hdr, struct sr_icmphdr *icmp_hdr) { /* Ethernet header */ uint8_t addr_tmp[6]; memcpy(addr_tmp, e_hdr->ether_dhost, 6); memcpy(e_hdr->ether_dhost, e_hdr->ether_shost, 6); memcpy(e_hdr->ether_shost, addr_tmp, 6); /* IP header */ struct in_addr ip_addr_tmp = ip_hdr->ip_src; ip_hdr->ip_src = ip_hdr->ip_dst; ip_hdr->ip_dst = ip_addr_tmp; ip_hdr->ip_sum = 0; ip_hdr->ip_sum = checksum(ip_hdr, sizeof(struct ip)); /* ICMP header */ icmp_hdr->icmp_type = 0x0; icmp_hdr->icmp_chksum = 0x0; icmp_hdr->icmp_chksum = checksum((uint16_t *)icmp_hdr, ntohs(ip_hdr->ip_len) - 20); int success = sr_send_packet(sr, packet, len, interface); if (success != 0) { fprintf(stderr, "%s: Sending packet failed!\n", __func__); } }
void arpq_packets_icmpsend(struct sr_instance *sr, struct packetq *arpq_packets){ struct queued_packet *current_packet = arpq_packets->first; struct frame_t *ICMP_err; while(current_packet){ //first, make sure current packet isn't an ICMP error message itself if (current_packet->outgoing->ip_header->ip_p == IPPROTO_ICMP){ current_packet->outgoing->icmp_header = ((void *) current_packet->outgoing->ip_header + current_packet->outgoing->ip_hl); uint8_t code = current_packet->outgoing->icmp_header->icmp_type; if (code == DEST_UNREACH || code == TIME_EXCEEDED || code == 12 || code == 31) //12 and 31 indicate bad IP header and datagram conversion error, respectively continue; } //get back old info so we can send it back the way it came current_packet->outgoing->iface = current_packet->from_iface; memcpy(current_packet->outgoing->from_MAC, current_packet->from_MAC, ETHER_ADDR_LEN); ICMP_err = generate_icmp_error(current_packet->outgoing, DEST_UNREACH, HOST_UNREACH); printf("sending Host Unreachable packets\n"); sr_send_packet(sr, (uint8_t *)current_packet->outgoing->frame, current_packet->outgoing->len, current_packet->from_iface->name); destroy_frame_t(ICMP_err); current_packet = current_packet->next; } }
/* 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 sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) { time_t curtime = time(NULL); if (difftime(curtime, req->sent) < 1.0) return; if (req->times_sent <= 4) { /* Find out which interface it's on */ char *interface = req->packets->iface; struct sr_if* iface = sr_get_interface(sr, interface); /* Allocate a new packet */ size_t out_len = ARP_REPLY_SIZE; uint8_t *packet_out = malloc(out_len); /* ====== Headers ====== */ /* Allow easy access to the headers */ sr_ethernet_hdr_t *eth_header_out = (sr_ethernet_hdr_t*) packet_out; sr_arp_hdr_t *arp_header_out = (sr_arp_hdr_t*) (packet_out + ARP_HEAD_OFF); /* Create the ethernet header */ char bcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; memcpy(eth_header_out->ether_dhost, bcast_addr, ETHER_ADDR_LEN); memcpy(eth_header_out->ether_shost, iface->addr, ETHER_ADDR_LEN); eth_header_out->ether_type = htons(ethertype_arp); /* ====== Body ====== */ /* Create the ARP packet */ arp_header_out->ar_hrd = htons(0x1); arp_header_out->ar_pro = htons(ethertype_ip); arp_header_out->ar_hln = ETHER_ADDR_LEN; arp_header_out->ar_pln = IP_ADDR_LEN; arp_header_out->ar_op = htons(arp_op_request); memcpy(arp_header_out->ar_sha, iface->addr, ETHER_ADDR_LEN); arp_header_out->ar_sip = iface->ip; char zeroes[] = {0,0,0,0,0,0}; memcpy(arp_header_out->ar_tha, zeroes, ETHER_ADDR_LEN); arp_header_out->ar_tip = req->ip; /* Send the packet */ sr_send_packet(sr, packet_out, out_len, interface); free(packet_out); return; } else { struct sr_packet *packet = req->packets; while (packet) { struct sr_packet *next = packet->next; send_icmp_error(sr, packet->buf, packet->len, packet->iface, 3, 1); packet = next; } sr_arpreq_destroy(&(sr->cache), req); } return; }
/*sends packet, checks any errors and frees buffer */ void sendPacket(struct sr_instance* sr, uint8_t* buf, char* iface, int len){ //send out icmp packet now //Send packet int ret = sr_send_packet(sr, buf, len, iface); if (ret != 0){ fprintf(stderr, "Didn't send packet properly\n"); } free(buf); }
int sr_integ_low_level_output(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { #ifdef _CPUMODE_ return sr_cpu_output(sr, buf /*lent*/, len, iface); #else return sr_send_packet(sr, buf /*lent*/, len, iface); #endif /* _CPUMODE_ */ } /* -- sr_vns_integ_output -- */
int sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *request){ time_t now = get_now(&now); struct sr_packet * packetptr = request->packets; int i; if(difftime(now, request->sent) > 1.0){ if(request->times_sent >= 5){ while(packetptr != NULL){ icmp_send_reply(sr, (uint8_t *)packetptr, packetptr->len, packetptr->iface, 3, 1); /* send unreachable */ packetptr = packetptr->next; } sr_arpreq_destroy(&(sr->cache), request); return -1; }else{ struct sr_rt* entry; struct sr_rt* routing = sr->routing_table; for(entry = routing; entry != NULL; entry = routing->next){ struct sr_if * interface2 = sr_get_interface(sr, entry->interface); /*create arp packet*/ enum sr_arp_opcode opcode = arp_op_request; struct sr_packet *raw = malloc(sizeof(struct sr_arp_hdr) + ETHER_HDR_LEN); /* may need to memset here*/ struct sr_ethernet_hdr *eth = (struct sr_ethernet_hdr *)raw; struct sr_arp_hdr *req = (struct sr_arp_hdr *)(raw + ETHER_HDR_LEN); req->ar_hrd = 0; req->ar_pro = 0; req->ar_hln = 0; req->ar_pln = 0; req->ar_op = opcode; req->ar_sip = sr->sr_addr.sin_addr.s_addr; req->ar_tip = request->ip; for (i = 0; i < ETHER_ADDR_LEN; i++){ req->ar_tha[i] = 0xff; req->ar_sha[i] = interface2->addr[i]; eth->ether_dhost[i] = 0xff; eth->ether_shost[i] = interface2->addr[i]; } /*send packet to the interface on routing_table*/ sr_send_packet(sr, (uint8_t *)raw, sizeof(struct sr_arp_hdr) + ETHER_HDR_LEN, request->packets->iface); free(raw); } request->sent = now; request->times_sent++; } } return 0; }
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) { time_t now = time(NULL); if (difftime(now, req->sent) >= 0.9) { if (req->times_sent >= 5) { struct sr_packet *pkt_pending = req->packets; struct sr_if *interface = sr_get_interface(sr, pkt_pending->iface); while (pkt_pending) { icmp_handler(sr, pkt_pending->buf, 0, interface->ip, HOST_UNREACHABLE); pkt_pending = pkt_pending->next; } sr_arpreq_destroy(&(sr->cache), req); } else { int packet_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t); uint8_t *pkt = malloc(packet_len); struct sr_ethernet_hdr *eth_hdr = (struct sr_ethernet_hdr *)pkt; struct sr_if *interface = sr_get_interface(sr, req->packets->iface); uint8_t hrd_addr[ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; enum sr_ethertype eth_arp = ethertype_arp; enum sr_ethertype eth_ip = ethertype_ip; memcpy(eth_hdr->ether_dhost, hrd_addr, ETHER_ADDR_LEN); memcpy(eth_hdr->ether_shost, interface->addr, ETHER_ADDR_LEN); eth_hdr->ether_type = htons(eth_arp); struct sr_arp_hdr *arp_hdr = (struct sr_arp_hdr *)(sizeof(sr_ethernet_hdr_t) + pkt); enum sr_arp_hrd_fmt hrd_eth = arp_hrd_ethernet; enum sr_arp_opcode arp_op_req = arp_op_request; arp_hdr->ar_hrd = htons(hrd_eth); arp_hdr->ar_pro = htons(eth_ip); arp_hdr->ar_hln = ETHER_ADDR_LEN; arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(arp_op_req); arp_hdr->ar_sip = interface->ip; arp_hdr->ar_tip = req->ip; memcpy(arp_hdr->ar_sha, interface->addr, ETHER_ADDR_LEN); memcpy(arp_hdr->ar_tha, hrd_addr, ETHER_ADDR_LEN); printf("Sending Packets.. [3].\n"); sr_send_packet(sr, pkt, packet_len, interface->name); free(pkt); req->sent = now; req->times_sent++; } } }
void handle_arp_reply(struct sr_instance *sr, uint8_t* ethernet_data_addr, struct sr_if* in_f){ printf("in handle arp reply\n"); /* The ARP reply processing code should move entries from the ARP request queue to the ARP cache: # When servicing an arp reply that gives us an IP->MAC mapping req = arpcache_insert(ip, mac) if req: send all packets on the req->packets linked list arpreq_destroy(req) */ /*Loop through sr_cache requests and look for an IP match to the ARP header source IP*/ sr_arp_hdr_t *arp_header = (sr_arp_hdr_t *) ethernet_data_addr; struct sr_arpreq *req_ptr = sr_arpcache_insert(&(sr->cache), arp_header->ar_sha, arp_header->ar_sip); /*If the IP in the reply matched something in our request queue*/ if (req_ptr) { struct sr_packet *req_pkts = req_ptr->packets; struct sr_packet *req_pkt_ptr = req_pkts; for (; req_pkt_ptr; req_pkt_ptr = req_pkt_ptr->next) { sr_ethernet_hdr_t *packet_eth_hdr = (sr_ethernet_hdr_t *) req_pkts->buf; sr_ip_hdr_t *packet_ip_hdr = (sr_ip_hdr_t *) (req_pkts->buf + sizeof(sr_ethernet_hdr_t)); /*ret_if will be populated if this was originally an echo request, else 0*/ struct sr_if* ret_if = sr_get_interface_from_ip(sr, packet_ip_hdr->ip_dst); if (ret_if) { /*Doesn't have a code so just passing 0 as code*/ send_icmp_echo_reply(sr, (uint8_t *) packet_eth_hdr, req_pkt_ptr->len, in_f, arp_header->ar_sha, echo_reply_type, 0); } else { memcpy(packet_eth_hdr->ether_dhost, arp_header->ar_sha, ETHER_ADDR_LEN); sr_send_packet(sr, (uint8_t *) packet_eth_hdr, req_pkt_ptr->len, in_f->name); } } sr_arpreq_destroy(&(sr->cache), req_ptr); } /*Otherwise do nothing, the reply wasn't about anything in our queue*/ }
/*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; }
/* prepare arp into ethernet frame and send it */ int boardcast_arpreq(struct sr_instance *sr, struct sr_arpreq *arp_req){ struct sr_if *o_interface; /*first package the arp package header first...*/ o_interface = sr_get_interface(sr, arp_req->packets->iface); struct sr_arp_hdr arp_hdr; uint8_t *arp_package; uint8_t *e_pack; arp_hdr.ar_hrd = sr_arp_hrd_fmt hfmt = arp_hrd_ethernet; /* format of hardware address */ arp_hdr.ar_pro = 0X800; /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/ arp_hdr.ar_hln = ETHER_ADDR_LEN = 8; /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/ arp_hdr.ar_pln = 8; /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/ sr_arp_opcode code = arp_op_request; arp_hdr.ar_op = code; /* ARP opcode (command) */ memcpy(arp_hdr.ar_sha, o_interface->addr, ETHER_ADDR_LEN); /* sender hardware address */ arp_hdr.ar_sip = o_interface.ip; /* sender IP address */ arp_hdr.ar_tip = arp_req.ip; /* target IP address */ /*copy everything into the arp_header*/ arp_package = malloc(sizeof(sr_arp_hdr_t)); print_hdr_arp(arp_package); memcpy(arp_package, &apr_hdr, sizeof(sr_arp_hdr_t)); /*then package the ethernet header along with the arp header...*/ e_pack = eth_hdr_package(uint8_t ether_dhost, sr, o_interface->addr, arp_package, sizeof(struct sr_arp_hdr)); print_hdr_eth(e_pack); /*send it out*/ sr_send_packet(sr, e_pack, sizeof(struct sr_arp_hdr) + sizeof(struct sr_ethernet_hdr), o_interface); /* build the ethernet frame to be broadcast */ int eth_hdr_package(uint8_t ether_dhost, uint8_t ether_shost, uint16_t ether_type, uint8_t *content, int len){ uint8_t *output; int total_length; struct sr_ethernet_hdr e_hdr; /*first step is to create a ethernet header...*/ memcpy(e_hdr.ether_dhost,ether_dhost,ETHER_ADDR_LEN); /* destination ethernet address */ memcpy(e_hdr.ether_shost,ether_shost,ETHER_ADDR_LEN); /* source ethernet address */ e_hdr.ether_type = ether_type; /*calculate the length of the entire thing...*/ total_length = sizeof(sr_ethernet_hdr_t) + len; /*put everything together*/ output = malloc(total_length); /*put the ethernet header in the front*/ memcpy(output, &e_hdr, sizeof(sr_ethernet_hdr_t)); memcpy(output + sizeof(sr_ethernet_hdr_t), content,len); return output; }
void handle_arpreq(struct sr_instance* sr, struct sr_arpreq *cache_req_ptr) { char *iface_name = cache_req_ptr->packets->iface; struct sr_if *interface = sr_get_interface(sr, iface_name); /*Only broadcast if this hasn't been sent out before: *Otherwise, our packet has been added to the end of the * request's linkedlist in the cache: do nothing*/ if (difftime(time(0), cache_req_ptr->sent) > 1.0) { if (cache_req_ptr->times_sent >= 5) { struct sr_packet *req_pkt_ptr = cache_req_ptr->packets; for (; req_pkt_ptr; req_pkt_ptr = req_pkt_ptr->next) { send_icmp(sr, req_pkt_ptr->buf, req_pkt_ptr->len, interface, dest_host_unreach_type, dest_host_unreach_code); } sr_arpreq_destroy(&(sr->cache), cache_req_ptr); } else { /*Create space for the request*/ uint8_t* eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); uint8_t* arp_pkt_buf; /*Pointers to where different header structs start in the packet*/ sr_ethernet_hdr_t* req_eth_header = (sr_ethernet_hdr_t*) eth_pkt_buf; /* Allocate mem for reply packet buffer */ /* Copy addresses and type into the ethernet header */ uint8_t broadcast_addr[ETHER_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; memcpy(req_eth_header->ether_dhost, broadcast_addr, ETHER_ADDR_LEN); memcpy(req_eth_header->ether_shost, interface->addr, ETHER_ADDR_LEN); req_eth_header->ether_type = ethertype_arp; /* Convert to network byte ordering */ hton_eth_hdr(&req_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_req_packet(arp_pkt_buf, cache_req_ptr, interface); /* Send the ARP request packet */ sr_send_packet(sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), interface->name); cache_req_ptr->sent = time(0); cache_req_ptr->times_sent++; free(eth_pkt_buf); } } }
void sr_icmp_ttl_exceeded(struct sr_instance *sr, uint8_t * packet, unsigned int len, char* interface, struct sr_ethernet_hdr *e_hdr, struct ip *ip_hdr) { struct sr_if *iface = sr_get_interface(sr, interface); /* Send ICMP time exceeded message. This is need for traceroute to work. */ uint8_t *new_pkt = (uint8_t *) calloc(1, 70); struct sr_ethernet_hdr *new_e_hdr = (struct sr_ethernet_hdr *) new_pkt; struct ip *new_ip_hdr = (struct ip *) (new_pkt + 14); struct sr_icmphdr *new_icmp_hdr = (struct sr_icmphdr *) (new_pkt + 34); /* ethernet header */ memcpy(new_e_hdr->ether_dhost, e_hdr->ether_shost, 6); memcpy(new_e_hdr->ether_shost, e_hdr->ether_dhost, 6); new_e_hdr->ether_type = htons(0x0800); /* IP header */ new_ip_hdr->ip_hl = 5; new_ip_hdr->ip_v = 4; new_ip_hdr->ip_tos = 0; new_ip_hdr->ip_len = htons(56); new_ip_hdr->ip_id = ip_hdr->ip_id; new_ip_hdr->ip_off = ip_hdr->ip_off; new_ip_hdr->ip_ttl = 64; new_ip_hdr->ip_p = 1; new_ip_hdr->ip_src.s_addr = iface->ip; new_ip_hdr->ip_dst = ip_hdr->ip_src; new_ip_hdr->ip_sum = 0; new_ip_hdr->ip_sum = checksum(new_ip_hdr, 20); /* ICMP ttl exceeded: type: 11, code: 0 */ new_icmp_hdr->icmp_type = 11; new_icmp_hdr->icmp_code = 0; new_icmp_hdr->id = 0; new_icmp_hdr->seqno = 0; memcpy(new_pkt+42, ip_hdr, 28); new_icmp_hdr->icmp_chksum = 0; new_icmp_hdr->icmp_chksum = checksum((uint16_t *)new_icmp_hdr, 36); int success = sr_send_packet(sr, new_pkt, 70, interface); if (success != 0) { fprintf(stderr, "%s: Sending packet failed!\n", __func__); } }
/* * Send an ICMP Error. */ void send_icmp_error(uint8_t type, uint8_t code, struct sr_instance *sr, char *interface, unsigned int len, uint8_t *pkt) { int new_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t); uint8_t *packet = (uint8_t *) malloc(new_len); struct sr_if *rt_if = (struct sr_if *)malloc(sizeof(struct sr_if)); rt_if = (struct sr_if *)sr_get_interface(sr, interface); /* Prepare ethernet header. */ sr_ethernet_hdr_t *ether_hdr = (sr_ethernet_hdr_t *) pkt; sr_ethernet_hdr_t *ether_newhdr = (sr_ethernet_hdr_t *) packet; ether_newhdr->ether_type = htons(ethertype_ip); memcpy(ether_newhdr->ether_shost, rt_if->addr, ETHER_ADDR_LEN); memcpy(ether_newhdr->ether_dhost, ether_hdr->ether_shost, ETHER_ADDR_LEN); /* Prepare IP header. */ sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(pkt + sizeof(sr_ethernet_hdr_t)); sr_ip_hdr_t *ip_newhdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t)); memcpy(ip_newhdr, ip_hdr, sizeof(sr_ip_hdr_t)); ip_newhdr->ip_src = rt_if->ip; ip_newhdr->ip_dst = ip_hdr->ip_src; ip_newhdr->ip_len = htons(56); ip_newhdr->ip_id = 0; ip_newhdr->ip_hl = 5; ip_newhdr->ip_off = 0; ip_newhdr->ip_ttl = 64; ip_newhdr->ip_p = ip_protocol_icmp; ip_newhdr->ip_sum = 0; ip_newhdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t)); /* Prepare the ICMP t3 header. */ sr_icmp_t3_hdr_t *icmp_t3_hdr = (sr_icmp_t3_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t)); icmp_t3_hdr->icmp_type = type; icmp_t3_hdr->icmp_code = code; icmp_t3_hdr->icmp_sum = 0; memcpy(icmp_t3_hdr->data, ip_hdr, 20); memcpy(icmp_t3_hdr->data + 20, pkt + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), 8); icmp_t3_hdr->icmp_sum = cksum(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), sizeof(sr_icmp_t3_hdr_t)); /* Send the ICMP error packet. */ sr_send_packet(sr, packet, new_len, interface); }
void sr_icmp_port_unreach(struct sr_instance *sr, uint8_t * packet, unsigned int len, char* interface, struct sr_ethernet_hdr *e_hdr, struct ip *ip_hdr) { /* 70: minimum length for ICMP port unreachable reply. */ uint8_t *new_pkt = (uint8_t *) calloc(1, 70); // hardcoded constant! anyway... struct sr_ethernet_hdr *new_e_hdr = (struct sr_ethernet_hdr *) new_pkt; struct ip *new_ip_hdr = (struct ip *) (new_pkt + 14); struct sr_icmphdr *new_icmp_hdr = (struct sr_icmphdr *) (new_pkt + 34); /* ethernet header */ memcpy(new_e_hdr->ether_dhost, e_hdr->ether_shost, 6); memcpy(new_e_hdr->ether_shost, e_hdr->ether_dhost, 6); new_e_hdr->ether_type = htons(0x0800); /* IP header */ new_ip_hdr->ip_hl = 5; new_ip_hdr->ip_v = 4; new_ip_hdr->ip_tos = 0; new_ip_hdr->ip_len = htons(56); // hardcoded constant! anyway... new_ip_hdr->ip_id = ip_hdr->ip_id; new_ip_hdr->ip_off = ip_hdr->ip_off; new_ip_hdr->ip_ttl = 64; new_ip_hdr->ip_p = 1; new_ip_hdr->ip_src = ip_hdr->ip_dst; new_ip_hdr->ip_dst = ip_hdr->ip_src; new_ip_hdr->ip_sum = 0; new_ip_hdr->ip_sum = checksum(new_ip_hdr, 20); /* ICMP port unreachable */ new_icmp_hdr->icmp_type = 3; new_icmp_hdr->icmp_code = 3; new_icmp_hdr->id = 0; new_icmp_hdr->seqno = 0; memcpy(new_pkt+42, ip_hdr, 28); new_icmp_hdr->icmp_chksum = 0; new_icmp_hdr->icmp_chksum = checksum((uint16_t *)new_icmp_hdr, 36); int success = sr_send_packet(sr, new_pkt, 70, interface); if (success != 0) { fprintf(stderr, "%s: Sending packet failed!\n", __func__); } }
/* Send a host unreachable ICMP to the given source address */ void send_echo_reply(uint8_t source_addr, uint8_t *packet, struct sr_instance *sr){ /*Allocate a buffer to hold the packet*/ uint8_t *buf = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t)); /*Create and send the host unreachable ICMP TO source, telling them that dest was unreachable*/ /*First have to create the ICMP packet*/ sr_icmp_t3_hdr_t *icmp_packet = (sr_icmp_hdr_t *)(buf + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t)); icmp_packet->icmp_type = 1; icmp_packet->icmp_code = 1; icmp_packet->icmp_sum = 0; icmp_packet->icmp_sum = cksum((const void *)(icmp_packet.icmp_type + icmp_packet.icmp_code), 2); print_hdr_icmp(icmp_packet); /*Have to craft data. Data will be the original packet header plus the first 8 bytes of the packet content.*/ memcpy(icmp_packet->data, packet, ICMP_DATA_SIZE); /*Now have to form the ip packet to encase the icmp content*/ sr_ip_hdr_t *ip_packet = (sr_ip_hdr_t *)(buf + sizeof(sr_ethernet_hdr_t)); ip_packet->ip_p = 1; ip_packet->ip_tos; /* type of service */ ip_packet->ip_len; /* total length */ ip_packet->ip_id; /* identification */ ip_packet->ip_off; /* fragment offset field */ ip_packet->ip_ttl; /* time to live */ ip_packet->ip_p = 1; /* protocol */ ip_packet->ip_sum; /* checksum */ ip_packet->ip_src = sr->if_list[0]->ip; /*Assign the packet source to one of the router's interfaces*/ ip_packet->ip_dst = get_ip_addr(packet); /*set the packet destination to the original source IP*/ print_hdr_ip(ip_packet); memcpy((void *)arp_packet->ar_sha, (void *)sender_eth, ETHER_ADDR_LEN); /*Now make an ethernet frame to wrap the IP packet with the ICMP packet*/ sr_ethernet_hdr_t *ether_packet = (sr_ethernet_hdr_t *)(buf); ether_packet->ether_dhost = source_addr; /*Set ethernet destination*/ ether_packet->ether_shost = sr->if_list[0]->addr; /*Set ethernet source*/ ether_packet->ether_type = sr_ethertype.ethertype_ip; print_hdr_eth(ether_packet); print_hdr_icmp(uint8_t *buf); /*Now send off the packet*/ int size = 32+20+8+28; /*Size of the packet. Ether header = 32, ip header = 20, ICMP header = 8, ICMP data = 28.*/ sr_send_packet(sr, buf, size, sr->if_list); }
int send_arp_response(struct sr_instance * sr, struct sr_if * assoc_iface, uint8_t * packet, unsigned int len) { int res; /* we have a MAC address */ uint8_t newpacket[len]; memcpy(newpacket, packet, len); struct sr_arp_hdr * new_arp_hdr = (sr_arp_hdr_t *)(newpacket + sizeof(sr_ethernet_hdr_t)); struct sr_ethernet_hdr* ether_hdr = (struct sr_ethernet_hdr *) newpacket; /* send it back to whoever sent it (ethernet) */ memcpy(ether_hdr->ether_dhost, ether_hdr->ether_shost, ETHER_ADDR_LEN); /* make sure the ethernet packet header is updated with the new mac */ memcpy(ether_hdr->ether_shost, assoc_iface->addr, ETHER_ADDR_LEN); /* take the old sender address and make it the target */ memcpy(new_arp_hdr->ar_tha, new_arp_hdr->ar_sha, ETHER_ADDR_LEN); /* load in the discovered MAC address as the sender address */ memcpy(new_arp_hdr->ar_sha, assoc_iface->addr, ETHER_ADDR_LEN); uint32_t temp = new_arp_hdr->ar_tip; /* send it back to the IP we got it from */ new_arp_hdr->ar_tip = new_arp_hdr->ar_sip; /* replace IP with what it was sent to */ new_arp_hdr->ar_sip = temp; /* set arp op to reply */ new_arp_hdr->ar_op = htons(arp_op_reply); res = sr_send_packet(sr, newpacket, len, assoc_iface->name); if (res != 0) { return -1; } return 0; }