/********************************************************************** * file: sr_router.c * date: Mon Feb 18 12:50:42 PST 2002 * Contact: casado@stanford.edu * * Description: * * This file contains all the functions that interact directly * with the routing table, as well as the main entry method * for routing. * * * Modified by Nicholas & Denny * **********************************************************************/ #include #include #include "sr_if.h" #include "sr_rt.h" #include "sr_pq.h" #include "sr_router.h" #include "sr_protocol.h" #include "sr_arp.h" #include #include #include #include "stdlib.h" #include "sr_icmp.h" #include "sr_checksum.h" #include "sr_pwospf.h" /*--------------------------------------------------------------------- * * Modified by Nicholas * * Method: sr_init(void) * Scope: Global * * Initialize the routing subsystem * *---------------------------------------------------------------------*/ void sr_init(struct sr_instance* sr) { /* REQUIRES */ assert(sr); sr_print_routing_table(sr); /* Add initialization code here! */ pwospf_init(sr); /*Initializes the ARP Table Pointer*/ sr->arp_table = NULL; } /* -- sr_init -- */ /*--------------------------------------------------------------------- * * Created and Modified by Denny & Nichkolas * * Method: sr_handlepacket(uint8_t* p,char* interface) * Scope: Global * * This method is called each time the router receives a packet on the * interface. The packet buffer, the packet length and the receiving * interface are passed in as parameters. The packet is complete with * ethernet headers. * * Note: Both the packet buffer and the character's memory are handled * by sr_vns_comm.c that means do NOT delete either. Make a copy of the * packet instead if you intend to keep it around beyond the scope of * the method call. * *---------------------------------------------------------------------*/ void sr_handlepacket(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */){ /* REQUIRES */ assert(sr); assert(packet); assert(interface); struct sr_ethernet_hdr *ether_header = (struct sr_ethernet_hdr *)packet;/*Ethernet header*/ struct ip *ip_header; /*ip header*/ struct sr_if* iface = sr_get_interface(sr, interface); /*Router Interface*/ /*** Nicholas ****/ struct sr_pq *queue; uint8_t *packet_cp; sr_drop_arp_table_entries(sr); /*****************/ switch(ether_header->ether_type){ case ETHERTYPE_ARP: /*ERP Protocol Handling*/ sr_handle_ARP(sr, packet, len, interface, ether_header ); break; case ETHERTYPE_IP: ip_header = (struct ip *)(packet+sizeof(struct sr_ethernet_hdr));/*IP Header Pointer*/ /*IP checksum check*/ if( !sr_checksum_receive((uint16_t*)ip_header, ip_header->ip_hl * sizeof(uint32_t) ) ) { puts("*** IP Checksum error ***"); break; } /*IP TTL Decrease*/ ip_header->ip_ttl--; /** Check TTL > 0 Timeout**/ if(ip_header->ip_ttl <= 0) { unsigned int data_len; uint8_t *data; if(ip_header->ip_dst.s_addr == iface->ip){ /**Respond with icmp echo reply **/ data = sr_construct_ICMP(&data_len, ether_header->ether_shost, ether_header->ether_dhost, ip_header->ip_src.s_addr, iface->ip, 0, 0, ip_header); } else { /*Respond with icmp time out response*/ data = sr_construct_ICMP(&data_len, ether_header->ether_shost, ether_header->ether_dhost, ip_header->ip_src.s_addr, iface->ip, 11, 0, ip_header); } if (sr_send_packet(sr, data, data_len, interface) != 0){ puts("*** IMCP Timeout Responce Send Error ***"); } free(data); } /***** Nicholas *****/ /*IP Packet to be forwarded*/ sr_print_if_list(sr); if (!sr_ip_in_if_list(sr, ip_header->ip_dst.s_addr)){ /*if(ip_header->ip_dst.s_addr != iface->ip){*/ sr_ip_update_arp_table(sr, ether_header->ether_shost); queue = sr_arp_table_add_dest(sr, sr_get_gateway_ip(sr, ip_header->ip_dst.s_addr)); /*assemble new IP checksum*/ sr_checksum_send((uint16_t*)ip_header,&(ip_header->ip_sum),ip_header->ip_hl*sizeof(uint32_t) ); /*packet copy*/ packet_cp = malloc(sizeof(uint8_t) * len); memcpy(packet_cp, packet, len); /*store in queue*/ sr_enqueue_packet(queue, packet_cp, len); } /******* Nicholas *************/ /*IP Packet for us*/ else { /*Switching IP Protocol*/ switch(ip_header->ip_p){ case IPPROTO_ICMP: sr_handle_ICMP(sr, packet, len, interface, ip_header, ether_header); break; /* case IPPROTO_UDP: case IPPROTO_TCP: */ default: printf("*** Unkown IP Protocol :: %d ***\n", ip_header->ip_p); /*Send ICMP Host Unreachable Here*/ /**** construct ICMP Destination Port Unreachable packet ****/ unsigned int data_len; uint8_t *data = sr_construct_ICMP(&data_len, ether_header->ether_shost, ether_header->ether_dhost, ip_header->ip_src.s_addr, iface->ip, 3, 3, ip_header); /*display_ICMP(data);*/ if (sr_send_packet(sr, data, data_len, interface) != 0) { puts("*** ICMP Destination Port Unreachable Sending Error ***"); } free(data); break; }/*switch IP Protocol*/ }/*else packet for us*/ break; default: printf("*** Unkown Ethernet Protocol :: %d ***\n", ether_header->ether_type); break; }/****switch ethernet protocol***/ /*** Nicholas *****/ sr_print_arp_table(sr); /*sr_print_routing_table(sr);*/ sr_update_queues(sr); /*sr_print_arp_table(sr);*/ /******************/ }/* end sr_ForwardPacket */ /* * Created by Denny * UDP Protocol Handling * */ void sr_handle_UDP(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_UDP--"); struct sr_if* iface = sr_get_interface(sr, interface); /*Router Interface*/ display(ether_header, ip_header, iface); } /* * Created by Denny * TCP Protocol Handling * */ void sr_handle_TCP(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_TCP--"); struct sr_if* iface = sr_get_interface(sr, interface); /*Router Interface*/ display(ether_header, ip_header, iface); } /* * Author: Denny Chen Dai * Display ethernet header & IP header & interface MAC information * (for testing purpose) */ void display(struct sr_ethernet_hdr *ether_header, struct ip *ip_header, struct sr_if* iface){ printf("Time to live : %d \n", ip_header->ip_ttl); char *src = inet_ntoa(ip_header->ip_src); printf(" Source: %s \n", src); char *dst = inet_ntoa(ip_header->ip_dst); printf(" Dest: %s \n", dst); printf("Source MAC: "); int i; for(i=0; i< ETHER_ADDR_LEN; i++){ printf(" %X ", ether_header->ether_shost[i]); } printf("\n"); printf("Dest MAC: "); for(i=0; i< ETHER_ADDR_LEN; i++){ printf(" %X ", ether_header->ether_dhost[i]); } printf("\n"); printf("%d", ip_header->ip_p); printf("My MAC: "); for(i=0; i< ETHER_ADDR_LEN; i++){ printf(" %X ", iface->addr[i]); } printf("\n"); }