/* 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); }
/* Create type3 icmp header */ void create_icmp_t3_hdr(sr_ip_hdr_t *ip_hdr, sr_icmp_t3_hdr_t *icmp_t3_hdr, uint8_t icmp_type, uint8_t icmp_code) { assert(icmp_t3_hdr); /* type here should be 3 actually */ icmp_t3_hdr->icmp_type = icmp_type; /* get the icmp code from the input */ icmp_t3_hdr->icmp_code = icmp_code; icmp_t3_hdr->unused = 0; icmp_t3_hdr->next_mtu = 0; memcpy(icmp_t3_hdr->data, ip_hdr, ICMP_DATA_SIZE); icmp_t3_hdr->icmp_sum = 0; uint16_t checksum = cksum(icmp_t3_hdr, sizeof(sr_icmp_t3_hdr_t)); icmp_t3_hdr->icmp_sum = checksum; print_hdr_icmp((uint8_t*)icmp_t3_hdr); return; }
/* Create icmp header */ void create_icmp_hdr(sr_icmp_hdr_t *icmp_hdr, sr_icmp_hdr_t *new_icmp_hdr, unsigned int len) { assert(icmp_hdr); assert(new_icmp_hdr); memcpy(new_icmp_hdr, icmp_hdr, sizeof(sr_icmp_hdr_t)); /* here we construct a echo reply icmp */ unsigned int icmp_whole_size = len - IP_PACKET_LEN; new_icmp_hdr->icmp_type = 0; /* code and checksum should be the same */ new_icmp_hdr->icmp_code = 0; /* do we need to check the checksum??? */ new_icmp_hdr->icmp_sum = 0; memcpy(new_icmp_hdr+sizeof(sr_icmp_hdr_t), icmp_hdr+sizeof(sr_icmp_hdr_t), icmp_whole_size-sizeof(sr_icmp_hdr_t)); new_icmp_hdr->icmp_sum = cksum(new_icmp_hdr, icmp_whole_size); print_hdr_icmp((uint8_t*)new_icmp_hdr); return; }