void send_icmp(void) { switch(opt_icmptype) { case ICMP_ECHO: /* type 8 */ case ICMP_ECHOREPLY: /* type 0 */ send_icmp_echo(); break; case ICMP_DEST_UNREACH: /* type 3 */ case ICMP_SOURCE_QUENCH: /* type 4 */ case ICMP_REDIRECT: /* type 5 */ case ICMP_TIME_EXCEEDED: /* type 11 */ send_icmp_other(); break; case ICMP_TIMESTAMP: case ICMP_TIMESTAMPREPLY: send_icmp_timestamp(); break; case ICMP_ADDRESS: case ICMP_ADDRESSREPLY: send_icmp_address(); break; default: if (opt_force_icmp) { send_icmp_other(); break; } else { printf("[send_icmp] Unsupported icmp type!\n"); exit(1); } } }
void sr_handlepacket(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */) { /* Function implemented by g1izzyw and gustan50404 */ /* REQUIRES */ assert(sr); assert(packet); assert(interface); struct sr_if *ether_interface = (struct sr_if *) sr_get_interface(sr, interface); /* Check if it an ethernet interface. */ if (ether_interface) { /* Now we deal with the ethernet header */ struct sr_ethernet_hdr *ether_hdr = (struct sr_ethernet_hdr *) packet; /* Check to see if we are dealing with an ARP request/reply */ if (ether_hdr->ether_type == htons(ethertype_arp)) { fprintf(stderr, "We Got an ARP Packet\n"); /* Handle ARP for ethernet */ struct sr_arp_hdr * arp_hdr = (struct sr_arp_hdr *)(packet + sizeof(struct sr_ethernet_hdr)); if (arp_hdr->ar_hrd == htons(arp_hrd_ethernet)) { if (arp_hdr->ar_op == htons(arp_op_request)) { /* arp request */ struct sr_if *interface_for_ip = get_interface_for_ip(sr, arp_hdr->ar_tip); if (interface_for_ip) { /* Target ip is one of the router interfaces */ fprintf(stderr, "ARP req for one of our interfaces\n"); /* Now we want to make an arp reply and send it back */ uint8_t *buf = (uint8_t *) malloc(len); memcpy(buf, packet, len); /*Make Arp Header*/ make_arprply_hdr(interface_for_ip->addr, arp_hdr->ar_sha, interface_for_ip->ip, arp_hdr->ar_sip, buf); /*Make Ethernet Header*/ make_ether_hdr(interface_for_ip->addr, ether_hdr->ether_shost, ethertype_arp, buf); /* Now we send the packet */ sr_send_packet(sr, buf, len, interface_for_ip->name); free(buf); fprintf(stderr, "ARP reply sent\n"); } } else if (arp_hdr->ar_op == htons(arp_op_reply)) { fprintf(stderr, "We got an ARP Reply, need to check for intfc tho \n"); /* arp reply */ struct sr_if *interface_for_ip = get_interface_for_ip(sr, arp_hdr->ar_tip); if (interface_for_ip) { fprintf(stderr, "We got an ARP Reply for one of our interfaces\n"); /*We first want to insert into Arp cache*/ struct sr_arpreq *request = sr_arpcache_insert(&(sr->cache), arp_hdr->ar_sha, arp_hdr->ar_sip); fprintf(stderr, "Signalling all waiting packets\n"); if (request) { struct sr_packet *cur_packet = request->packets; while(cur_packet) { fprintf(stderr, "About to forward \n"); print_hdrs(cur_packet->buf, cur_packet->len); forward_packet(sr, cur_packet->iface, arp_hdr->ar_sha, cur_packet->len, cur_packet->buf); fprintf(stderr, "Packet Forwarded\n"); cur_packet = cur_packet->next; } } } } } } else if (ether_hdr->ether_type == htons(ethertype_ip)) { /* Get the ip header from the ethernet header*/ sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t)); /*IP Checksum Stuff*/ uint16_t temp_ip_sum = ip_hdr->ip_sum; ip_hdr->ip_sum = 0; ip_hdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t)); if (temp_ip_sum == ip_hdr->ip_sum) { /*We got here means IP Cheksum is alright, so we extract the interface*/ struct sr_if *interface_for_ip = get_interface_for_ip(sr, ip_hdr->ip_dst); /*Check to make sure interface is one of ours*/ if (interface_for_ip) { fprintf(stderr, "IP Packet destined towards our interface\n"); /*Check if our IP packet is UDP or TCP*/ if (ip_hdr->ip_p == 6 || ip_hdr->ip_p == 17) { fprintf(stderr, "We Got TCP or UDP, sending ICMP error msg\n"); send_icmp_error(3, 3, sr, interface, len, packet); } else { /* Get the ICMP header */ sr_icmp_hdr_t *icmp_hdr = (struct sr_icmp_hdr *) (packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t)); /*Now we do the ICMP checksum chek*/ /*This covers the ICMP echo case*/ uint16_t temp_icmp_sum = icmp_hdr->icmp_sum; temp_icmp_sum = icmp_hdr->icmp_sum; icmp_hdr->icmp_sum = 0; if (temp_icmp_sum == cksum(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t))) { /*Everything is fine so we send an ICMP echo back*/ fprintf(stderr, "Sending ICMP echo reply\n"); send_icmp_echo(sr, interface, len, packet); } } } else { /*IP Packet not destined towards one of our interfaces*/ fprintf(stderr, "IP packet not destined to our interface\n"); /*Decremenrt TTL by 1*/ fprintf(stderr, "TTL modified \n"); print_hdrs(packet, len); if (ip_hdr->ip_ttl <= 1) { fprintf(stderr, "Packte with TTL < 0 found, sending ICMP error \n"); /*TTL is less than 0 so send an ICMP ERROR*/ send_icmp_error(11, 0, sr, interface, len, packet); } else { /*Recompute Checksum over new header TTL is fine*/ /*Check if it exists in the routing table*/ ip_hdr->ip_ttl = ip_hdr->ip_ttl - 1; fprintf(stderr, "Recomputing Checksum after modifying TTl\n"); ip_hdr->ip_sum = 0; ip_hdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t)); struct sr_if *dst_if = (struct sr_if *)malloc(sizeof(struct sr_if)); dst_if = next_hop(sr, interface, ip_hdr->ip_dst); if (!(dst_if)) { fprintf(stderr, "IP packet has no longest matching prefix sending ICMP error\n"); /*dst ip has no longest macthing prefix*/ /*So we send a type 3 code 0 ICMP error*/ send_icmp_error(3, 0, sr, interface, len, packet); } else { /*This is the case where we do have a longest macthing prefix*/ fprintf(stderr, "Found Longest mathcing prefix in RT\n"); struct sr_arpcache *cache = &(sr->cache); struct sr_arpentry *in_cache = sr_arpcache_lookup(cache, ip_hdr->ip_dst); if (in_cache) { fprintf(stderr, "Found IP->MAC mapping in ARP cache forwarding packet \n"); /*this is the case where ip->mac maping is already in cache*/ forward_packet(sr, dst_if->name, in_cache->mac, len, packet); free(in_cache); } else { fprintf(stderr, "IP->MAC mapping not in ARP cache %u \n", ip_hdr->ip_dst); /*Case where ip->mapping is not in cache*/ sr_arpcache_queuereq(cache, ip_hdr->ip_dst, packet, len, dst_if->name); fprintf(stderr, "Added Arp Req to queu \n"); } } } } } } } } /* end sr_ForwardPacket */