nano_mesh_response_t nano_mesh_forward(addrtype_t type, address_t address, route_check_t *r_check ) { dest_delivery_t table_check; nano_mesh_response_t forward_response = NANOMESH_NO_ROUTE; if( xSemaphoreTake( table_lock, ( portTickType ) 5 ) == pdTRUE ) { table_check = check_neighbour_table(type, address); switch (table_check) { case BROADCAST: forward_response = NANOMESH_BROADCAST; break; case NEIGHBOR: forward_response = NANOMESH_NEIGHBOUR; break; case NEIGHBOR_LOW_RSSI: case NOT_NEIGHBOR: if(r_check != NULL) { #ifdef HAVE_ROUTING if(check_routing_table(type, address, r_check ) == pdTRUE) forward_response = NANOMESH_FORWARD; else { if(table_check==NEIGHBOR_LOW_RSSI) forward_response = NANOMESH_NEIGHBOUR; else forward_response = NANOMESH_NO_ROUTE; } #else if(table_check==NEIGHBOR_LOW_RSSI) forward_response = NANOMESH_NEIGHBOUR; else forward_response = NANOMESH_NO_ROUTE; #endif } else forward_response = NANOMESH_NO_ROUTE; break; default: break; } xSemaphoreGive( table_lock ); /*free lock*/ } return forward_response; }
/*Returns 0 on success and error code on fail*/ int sr_handleip(struct sr_instance* sr, uint8_t* packet, unsigned int len, struct sr_if* in_f, uint8_t** ethernet_data_addr){ sr_ip_hdr_t* ip_header_buffer = (sr_ip_hdr_t*) *ethernet_data_addr; /* Get headers from packet */ /*sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*) packet; uint8_t * ip_pkt_buf = packet + sizeof(sr_ethernet_hdr_t); sr_ip_hdr_t* ip_hdr = (sr_ip_hdr_t*) (packet + sizeof(sr_ethernet_hdr_t)); */ uint8_t * icmp_pkt_buf = packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t); sr_icmp_hdr_t* icmp_hdr = (sr_icmp_hdr_t*) icmp_pkt_buf; struct sr_if* ret_if; /* return interface */ if (check_ip_sum(ip_header_buffer) == 0) { /*Pass Checksum*/ printf("Checksum Pass\n"); } else { /*Fail Checksum*/ printf("Checksum Fail\n"); return -1; } /*If the TTL went to 0*/ if (decrement_ttl(ip_header_buffer) == -1) { /*Send ICMP with the proper TTL decrease type and icmp code*/ printf("TTL reached 0\n"); send_icmp(sr, packet, len, in_f, time_exceed_type, time_exceed_code); return -1; } /*Check if the IP packet is for us and not a echo request*/ ret_if = sr_get_interface_from_ip(sr, ip_header_buffer->ip_dst); if(ret_if && !(ip_header_buffer->ip_p == ip_protocol_icmp && icmp_hdr->icmp_type == echo_req_type && icmp_hdr->icmp_code == echo_req_code)) { /* The IP packet is FOR US */ printf("FOR US, NOT ECHO REQ"); /* Check if it is an echo request */ if (ip_header_buffer->ip_p == ip_protocol_tcp || ip_header_buffer->ip_p == ip_protocol_udp) { /* It is TCP/UDP send ICMP port unreachable SEND: an ICMP port unreachable to sending host*/ send_icmp(sr, packet, len, in_f, port_unreach_type, port_unreach_code); } else { ; /* According to the Assignment: IGNORE THE PACKET*/ } } else { /*If it's not in the routing table, send ICMP net unreachable*/ struct sr_rt * routing_node; uint32_t ip_dest; /*If it's for us, we want to send back to the source, so check for the source in the routing table*/ if (ret_if) { /* The IP packet is FOR US */ printf("FOR US\n"); ip_dest = ip_header_buffer->ip_src; } /*If not for us, we want to keep forwarding to the destination so check for that in the routing table*/ else { /* The IP packet is NOT FOR US */ printf("NOT FOR US\n"); ip_dest = ip_header_buffer->ip_dst; } if ((routing_node = check_routing_table(sr, ip_dest)) == NULL) { printf("NOT in routing table\n"); send_icmp(sr, packet, len, in_f, dest_net_unreach_type, dest_net_unreach_code); } else { printf("In routing table\n"); /*Got the routing table node in routing_node */ /*Next hop IP address is in gateway *Look it up in arpcache_lookup to see if we know the MAC address */ uint32_t nexthopIP = routing_node->gw.s_addr; struct sr_arpentry *arp_dest = sr_arpcache_lookup(&(sr->cache), nexthopIP); struct sr_if* nexthopInterface = sr_get_interface(sr, routing_node->interface); /*Create an ethernet header in front of the packet to forward regardless of whether or not we've found the next hop IP: need it in both cases*/ /*Allocate space for ethernet header and packet, copy in contents of packet*/ uint8_t* eth_header_packet = malloc(len); uint8_t* ip_header = eth_header_packet + sizeof(sr_ethernet_hdr_t); uint8_t* only_packet = eth_header_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t); memcpy(ip_header, ip_header_buffer, sizeof(sr_ip_hdr_t)); memcpy(only_packet, (packet+sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)), len-sizeof(sr_ethernet_hdr_t)-sizeof(sr_ip_hdr_t)); /*Save it in struct form*/ sr_ethernet_hdr_t* packet_to_forward = (sr_ethernet_hdr_t*)eth_header_packet; /*Now set the actual ethernet header for the packet*/ packet_to_forward->ether_type = htons(ethertype_ip); memcpy(packet_to_forward->ether_shost, nexthopInterface->addr, ETHER_ADDR_LEN); /*If NULL, send out the arp request*/ if(arp_dest == NULL){ printf("Not in arp cache: need to send an ARP request!\n"); broadcast_arp_req(sr, nexthopIP, packet_to_forward, len, routing_node, nexthopInterface); } /*Otherwise just forward the packet to arp_dest's MAC address*/ else { /*It's for us, it must be an echo request*/ if (ret_if) { /*Doesn't have a code so just passing 0 as code*/ struct sr_if *interface = sr_get_interface(sr, routing_node->interface); send_icmp_echo_reply(sr, packet, len, interface, arp_dest->mac, echo_reply_type, 0); } else { printf("In arp cache: just forwarding the packet\n"); memcpy(packet_to_forward->ether_dhost, arp_dest->mac, ETHER_ADDR_LEN); sr_send_packet(sr, (uint8_t*)packet_to_forward, len, routing_node->interface); /*Free the arp_dest that sr_arpcache_lookup created*/ free(arp_dest); } } } } return 0; }