/****************************************************** * SR_ICMP.H * Package for handling ICMP Protocols * *******************************************************/ #include "sr_checksum.h" #include "sr_icmp.h" /* * Author: Denny Chen Dai * ICMP Protocol Handling Function * * v1. Handling ICMP ECHO_REQUEST * */ void sr_handle_ICMP(struct sr_instance* sr, uint8_t * packet, unsigned int len, char* interface, struct ip *ip_header, struct sr_ethernet_hdr *ether_header){ puts("--sr_handle_ICMP--"); ip_header->ip_ttl = 64; struct in_addr temp_ip; struct sr_icmp *icmp_packet; /*icmp packet*/ struct sr_if* iface = sr_get_interface(sr, interface); /*Router Interface*/ /*pointer to ICMP body*/ icmp_packet = (struct sr_icmp *)( (uint8_t *)ip_header+ ip_header->ip_hl * sizeof(uint32_t)); /* printf("ICMP type: %d code: %d ID: %X seq: %X \n", icmp_packet->icmp_type, icmp_packet->icmp_code, icmp_packet->icmp_id, icmp_packet->icmp_seq); */ /*Validate ICMP checksum*/ if( !sr_checksum_receive((uint16_t *)icmp_packet, (ntohs(ip_header->ip_len) - ip_header->ip_hl * sizeof(uint32_t)) )) { puts("*** ICMP Checksum Error ***\n"); } if(icmp_packet->icmp_type == ICMP_ECHO_REQUEST) { /*if dst = me, then response with ICMP_REPLY*/ /*if(ip_header->ip_dst.s_addr == (unsigned long)iface->ip) {*/ /*puts("Pinging me ! ");*/ /*assemble ICMP REPLY data*/ icmp_packet->icmp_type = ICMP_ECHO_REPLY; icmp_packet->icmp_code = 0; /*assemble ICMP checksum*/ sr_checksum_send((uint16_t *)icmp_packet, &(icmp_packet->icmp_sum), (ntohs(ip_header->ip_len) - ip_header->ip_hl * sizeof(uint32_t)) ); /*assemble IP Header data*/ temp_ip = ip_header->ip_dst; ip_header->ip_dst = ip_header->ip_src; ip_header->ip_src = temp_ip; /*assemble IP checksum*/ sr_checksum_send((uint16_t *)ip_header, &(ip_header->ip_sum), ip_header->ip_hl * sizeof(uint32_t)); /*assemble ethernet header*/ memcpy(ether_header->ether_dhost, ether_header->ether_shost, sizeof(uint8_t) * ETHER_ADDR_LEN); /*dest MAC*/ memcpy(ether_header->ether_shost, iface->addr, sizeof(uint8_t) * ETHER_ADDR_LEN);/*src MAC*/ /*display_ICMP(packet);*/ if (sr_send_packet(sr, packet, len, interface) != 0){ puts("*** ICMP ECHO_REPLY Send Problem ***\n"); } /*}*//*if pinging me */ }/*if echo_request*/ else if(icmp_packet->icmp_type == ICMP_ECHO_REPLY) { /*ICMP echo reply, not handled within this function*/ } else{ /*other ICMP type, not being handled*/ } } /* * Author: Denny Chen Dai * Construction of ICMP Packet Data * * len: totol lenth of packet data created * dhost[]: destination MAC address * shost[]: src MAC address * dest_ip: dest ip * src_ip: src_ip * icmp_type: ICMP protocol type * icmp_code: ICMP protocol type code * ip_hdr: pointer to ip protocol header address */ uint8_t *sr_construct_ICMP(unsigned int *len, unsigned char dhost[ETHER_ADDR_LEN], unsigned char shost[ETHER_ADDR_LEN], uint32_t dst_ip, uint32_t src_ip, uint8_t icmp_type, uint8_t icmp_code, struct ip *ip_hdr){ /*puts("--sr_construct_ICMP()--");*/ *len = sizeof(struct sr_icmp_packet) + ip_hdr->ip_hl * sizeof(uint32_t) + 8; uint8_t *packet_buffer = (uint8_t *)malloc( *len *sizeof(uint8_t)); struct sr_icmp_packet *packet = (struct sr_icmp_packet *)packet_buffer; /*assemble ethernet header*/ memcpy(packet->ether_hdr.ether_dhost, dhost, sizeof(uint8_t) * ETHER_ADDR_LEN); /*dest MAC*/ memcpy(packet->ether_hdr.ether_shost, shost, sizeof(uint8_t) * ETHER_ADDR_LEN);/*src MAC*/ packet->ether_hdr.ether_type = 0x0008; /*assemble ip header*/ packet->ip_hdr.ip_v = 4; packet->ip_hdr.ip_hl = sizeof(struct ip) / sizeof(uint32_t); packet->ip_hdr.ip_tos = 0; packet->ip_hdr.ip_len = htons( sizeof(struct ip) + sizeof(struct sr_icmp) + ip_hdr->ip_hl *sizeof(uint32_t)+8); packet->ip_hdr.ip_id = rand() % 65535 + 1; /*packet->ip_hdr.ip_id = 0;*/ packet->ip_hdr.ip_off = 0; packet->ip_hdr.ip_ttl = 128; packet->ip_hdr.ip_p = 0x01; packet->ip_hdr.ip_src.s_addr = src_ip; packet->ip_hdr.ip_dst.s_addr = dst_ip; /*assemble ICMP body*/ packet->icmp_hdr.icmp_type = icmp_type; packet->icmp_hdr.icmp_code = icmp_code; packet->icmp_hdr.icmp_id = 0; packet->icmp_hdr.icmp_seq = 0; memcpy(packet_buffer + sizeof(struct sr_icmp_packet), ip_hdr, ip_hdr->ip_hl * sizeof(uint32_t) + 8); /*ICMP checksum*/ sr_checksum_send((uint16_t *)&(packet->icmp_hdr), &(packet->icmp_hdr.icmp_sum), sizeof(struct sr_icmp) + ip_hdr->ip_hl * sizeof(uint32_t) + 8); /*IP checksum*/ sr_checksum_send((uint16_t *)&(packet->ip_hdr), &(packet->ip_hdr.ip_sum), packet->ip_hdr.ip_hl * sizeof(uint32_t) ); return packet_buffer; } /* * Author: Nicholas, Denny * Display ICMP packet content * * base: pointer to the starting addr of ICMP packet */ void display_ICMP(uint8_t *base){ struct sr_icmp_packet *packet = (struct sr_icmp_packet *)base; int i; for(i=0; i< ETHER_ADDR_LEN; i++){ printf(" %X ", packet->ether_hdr.ether_shost[i]); } printf("\n"); printf("Dest MAC: "); for(i=0; i< ETHER_ADDR_LEN; i++){ printf(" %X ", packet->ether_hdr.ether_dhost[i]); } printf("\n"); printf("Ethernet Type: %X \n",packet->ether_hdr.ether_type); /*assemble ip header*/ printf("ip v: %X \n",packet->ip_hdr.ip_v); printf("ip hl: %d \n",packet->ip_hdr.ip_hl); printf("tos: %d \n",packet->ip_hdr.ip_tos); printf("len: %X \n",packet->ip_hdr.ip_len); printf("id: %d \n",packet->ip_hdr.ip_id); /*packet->ip_hdr.ip_id = 0;*/ printf("off: %d \n",packet->ip_hdr.ip_off); printf("ttl: %d \n",packet->ip_hdr.ip_ttl); printf("ip_p: %d \n",packet->ip_hdr.ip_p); char *src = inet_ntoa(packet->ip_hdr.ip_src); printf(" Source: %s \n", src); char *dst = inet_ntoa(packet->ip_hdr.ip_dst); printf(" Dest: %s \n", dst); /*assemble ICMP body*/ printf("icmp type: %d \n",packet->icmp_hdr.icmp_type); printf("icmp code: %d \n",packet->icmp_hdr.icmp_code); printf("icmp id: %d \n",packet->icmp_hdr.icmp_id); printf("icmp seq: %d \n",packet->icmp_hdr.icmp_seq); }