void sr_add_interface(struct sr_instance* sr, const char* name) { struct sr_vns_if* if_walker = 0; /* -- REQUIRES -- */ assert(name); assert(sr); struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); /* -- empty list special case -- */ if(sub->if_list == 0) { sub->if_list = (struct sr_vns_if*)malloc(sizeof(struct sr_vns_if)); assert(sub->if_list); sub->if_list->next = 0; strncpy(sub->if_list->name,name,SR_NAMELEN); return; } /* -- find the end of the list -- */ if_walker = sub->if_list; while(if_walker->next) {if_walker = if_walker->next; } if_walker->next = (struct sr_vns_if*)malloc(sizeof(struct sr_vns_if)); assert(if_walker->next); if_walker = if_walker->next; strncpy(if_walker->name,name,SR_NAMELEN); if_walker->next = 0; } /* -- sr_add_interface -- */
int sr_cpu_output(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { /* REQUIRES */ assert(sr); assert(buf); assert(iface); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); fprintf(stderr, "!!! sr_cpu_output(..) (sr_cpu_extension_nf2.c) called while running in cpu mode !!!\n"); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); router_t* router = sr_get_subsystem(sr); int written_length = 0; int i = 0; /* log the packet */ // pthread_mutex_lock(rs->log_dumper_mutex);//TODO: lock sr_log_packet(sr, buf, len); // pthread_mutex_unlock(rs->log_dumper_mutex); char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"}; for (i = 0; i < 4; ++i) { if (strcmp(iface, internal_names[i]) == 0) { break; } } /* setup select */ fd_set write_set; FD_ZERO(&write_set); while (written_length < len) { FD_SET(router->sockfd[i], &write_set); // struct timeval t; // t.tv_sec = 0; // t.tv_usec = 500; // timeout every half a millisecond if (select(router->sockfd[i]+1, NULL, &write_set, NULL, NULL) < 0) { perror("select"); exit(1); } if (FD_ISSET(router->sockfd[i], &write_set)) { int w = 0; if ((w = write(router->sockfd[i], &buf[written_length], len - written_length)) == -1) { perror("write"); exit(1); } written_length += w; } } /* Return the length of the packet on success, -1 on failure */ return len; } /* -- sr_cpu_output -- */
void sr_integ_input(struct sr_instance* sr, const uint8_t * packet/* borrowed */, unsigned int len, const char* interface/* borrowed */) { /* -- INTEGRATION PACKET ENTRY POINT!-- */ printf(" ** sr_integ_input(..) called \n"); // get global router instance struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(sr); // get interface object for this interface name interface_t *intf = get_interface_name(subsystem, interface); printf(" ********************* new packet received with length %u on interface: %s\n", len, intf->name); // check if interface is active if(intf->enabled == TRUE) { // create a copy of the packet uint8_t* packet_copy = (uint8_t*) malloc_or_die(len); memcpy(packet_copy, packet, len); // send to ethernet frame handler ethernet_handle_frame(subsystem, packet_copy, len, intf); } else { printf(" ** sr_integ_input(..): interface: %s is down. Dropping packet\n", intf->name); } } /* -- sr_integ_input -- */
void sr_integ_hw_setup(struct sr_instance* sr) { printf(" ** sr_integ_hw(..) called \n"); struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(sr); printf(" ** sr_integ_hw(..) adding entries to static rtable \n"); // read rtable file sr_load_rt(sr, sr->rtable); // add static entries to routing table printf(" ** sr_integ_hw(..) initial state of routing table\n"); llist_display_all(subsystem->rtable->rtable_list, display_route_t); // set link state info uint32_t area_id = PWOSPF_AREA_ID; uint16_t lsuint = PWOSPF_LSU_INTERVAL; set_ls_info_id(subsystem, area_id, lsuint); // get hardware fds for each hw interface #ifdef _CPUMODE_ sr_cpu_init_interface_socket(subsystem); #endif // initialize neighbor db neighbor_db_init(subsystem); // display initial state of neighbor db printf(" ** sr_integ_hw(..) initial state of neighbor db\n"); display_neighbor_vertices(subsystem); // initialize pwospf pwospf_init(subsystem); } /* -- sr_integ_hw_setup -- */
void pwospf_flood_lsu(struct ip* ip_header, pwospf_header_t* pwospf_header, pwospf_lsu_packet_t* lsu_packet, neighbor_t* sending_neighbor, interface_t* intf) { printf(" ** pwospf_flood_lsu(..) called\n"); // decrement ttl uint16_t ttl = 0; ttl = htons(lsu_packet->ttl); ttl = ttl - 1; ttl = ntohs(ttl); lsu_packet->ttl = ttl; pwospf_header->checksum = 0; uint16_t pwospf_packet_len = pwospf_header->len; // correct order pwospf_header->len = htons(pwospf_header->len); // generate raw packet byte* pwospf_packet = (byte*) malloc_or_die(pwospf_packet_len); memcpy(pwospf_packet, pwospf_header, sizeof(pwospf_header_t)); memcpy(pwospf_packet + sizeof(pwospf_header_t), lsu_packet, pwospf_packet_len - sizeof(pwospf_header_t)); printf(" ** pwospf_flood_lsu(..) pwospf packet with len %u generated \n", pwospf_packet_len); // generate checksum pwospf_header->checksum = htons(htons(inet_chksum((void*) pwospf_packet, pwospf_packet_len))); memcpy(pwospf_packet, pwospf_header, sizeof(pwospf_header_t)); // check if ttl expired if(lsu_packet->ttl < 1) { printf(" ** pwospf_flood_lsu(..) ttl expired, not flooding\n"); } else { // get instance of router struct sr_instance* sr_inst = get_sr(); struct sr_router* router = (struct sr_router*)sr_get_subsystem(sr_inst); node* first = NULL; neighbor_t* neighbor = NULL; int i; // now iterate through each interface for( i = 0; i < router->num_interfaces ; i++) { // now iterate this interface's neighbors list first = router->interface[i].neighbor_list; pthread_mutex_lock(&router->interface[i].neighbor_lock); while(first != NULL) { // get neighbor neighbor = (neighbor_t*) first->data; if(neighbor != NULL) { // ensure that the sending neighbour is excluded if(neighbor->id != sending_neighbor->id) { byte* ip_packet = (byte*) malloc_or_die(ip_header->ip_len); ip_header->ip_dst.s_addr = neighbor->ip; ip_header->ip_len = htons((ip_header->ip_len)); ip_header->ip_off = htons((ip_header->ip_off)); ip_header->ip_id = htons((ip_header->ip_id)); ip_header->ip_sum = htons((ip_header->ip_sum)); memcpy(ip_packet, ip_header, ip_header->ip_hl * 4); memcpy(ip_packet + ip_header->ip_hl * 4, pwospf_packet, pwospf_packet_len); ip_look_up_reply(ip_packet, ip_header, intf); } } first = first->next; } pthread_mutex_unlock(&router->interface[i].neighbor_lock); } } }
void ip_look_up_reply(byte* ip_packet, struct ip* ip_header, interface_t* intf) { printf(" ** ip_lookup_reply(..) called \n"); // get ptr to global router instance struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(get_sr()); // get dst ip object addr_ip_t dst_ip; memcpy(&dst_ip, &ip_header->ip_dst, 4); // look up in routing table route_info_t route_info = rrtable_find_route(subsystem->rtable, dst_ip); if(route_info.intf == NULL) { printf(" ** ip_lookup_reply(..) Error! No route found \n"); } else { // display output interface printf(" ** ip_lookup_reply(..) output interface for ip: %s\n", quick_ip_to_string(dst_ip)); display_interface(route_info.intf); // check if destination same as ip of the source interface and packet didn't originate from one of my interfaces if(strcmp(route_info.intf->name, intf->name) == 0 && check_packet_source(ip_header->ip_src, subsystem) == FALSE) { printf(" ** make_ip_packet_reply(..) error! destination interface same as source \n"); // send icmp destination host unreachable uint8_t code = ICMP_TYPE_CODE_DST_UNREACH_HOST; // reverse order ip_header->ip_len = ntohs((ip_header->ip_len)); ip_header->ip_off = ntohs((ip_header->ip_off)); ip_header->ip_id = ntohs((ip_header->ip_id)); ip_header->ip_sum = ntohs((ip_header->ip_sum)); uint16_t packet_len = ip_header->ip_len; icmp_type_dst_unreach_send(&code, ip_packet, &packet_len, ip_header); } else { // check if ttl expired if(ip_header->ip_ttl == 1) { printf(" ** ip_lookup_reply(..) ttl expired, sending ICMP ttl error message \n"); // reverse order ip_header->ip_len = ntohs((ip_header->ip_len)); ip_header->ip_off = ntohs((ip_header->ip_off)); ip_header->ip_id = ntohs((ip_header->ip_id)); ip_header->ip_sum = ntohs((ip_header->ip_sum)); uint8_t code = ICMP_TYPE_CODE_TTL_TRANSIT; uint16_t len = ip_header->ip_len; icmp_type_ttl_send(&code, ip_packet, &len, ip_header); } else { printf(" ** ip_lookup_reply(..) decrementing ttl \n"); // create new ip header struct ip* ip_header_ttl = (struct ip*) malloc_or_die(ip_header->ip_hl * 4); memcpy(ip_header_ttl, ip_header, ip_header->ip_hl * 4); // decrement ttl ip_header_ttl->ip_ttl = ip_header_ttl->ip_ttl - 1; // generate checksum ip_header_ttl->ip_sum = 0; ip_header_ttl->ip_sum = htons(htons(inet_chksum((void*)ip_header_ttl, ip_header_ttl->ip_hl * 4))); // get payload uint16_t payload_len = ntohs(ip_header_ttl->ip_len) - (ip_header_ttl->ip_hl * 4); printf(" ** ip_lookup_reply(..) Payload size %u bytes \n", payload_len); memcpy(ip_packet, ip_header_ttl, ip_header_ttl->ip_hl * 4); // make new ip packet send_ip_packet(ip_packet, ip_header_ttl, route_info); } } } }
void sr_integ_hw_setup(struct sr_instance* sr) { printf(" ** sr_integ_hw(..) called \n"); /* Get router subsystem */ struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); sr_load_rt(sub,const char*); } /* -- sr_integ_hw_setup -- */
void sr_integ_add_interface(struct sr_instance* sr, struct sr_vns_if* vns_if/* borrowed */) { printf(" ** sr_integ_add_interface(..) called \n"); /* Get router subsystem */ struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); /* Add the interface to our internal router state */ sr_add_iface_from_vns(sub, vns_if); } /* -- sr_integ_add_interface -- */
void sr_integ_add_interface(struct sr_instance* sr, struct sr_vns_if* vns_if/* borrowed */) { printf(" ** sr_integ_add_interface(..) called \n"); struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(sr); subsystem->interface[subsystem->num_interfaces] = set_interface(vns_if, subsystem->num_interfaces); #ifdef _CPUMODE_ write_interface_hw(subsystem); #endif subsystem->num_interfaces = subsystem->num_interfaces + 1; printf(" ** sr_integ_add_interface(..) current no. of interfaces: %u\n", subsystem->num_interfaces); } /* -- sr_integ_add_interface -- */
void sr_set_ether_addr(struct sr_instance* sr, const unsigned char* addr) { struct sr_vns_if* if_walker = 0; struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); /* -- REQUIRES -- */ assert(sub->if_list); if_walker = sub->if_list; while(if_walker->next) {if_walker = if_walker->next; } /* -- copy address -- */ memcpy(if_walker->addr,addr,6); } /* -- sr_set_ether_addr -- */
void sr_set_ether_ip(struct sr_instance* sr, uint32_t ip_nbo) { struct sr_vns_if* if_walker = 0; struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); /* -- REQUIRES -- */ assert(sub->if_list); if_walker = sub->if_list; while(if_walker->next) {if_walker = if_walker->next; } /* -- copy address -- */ if_walker->ip = ip_nbo; } /* -- sr_set_ether_ip -- */
uint32_t sr_integ_findsrcip(uint32_t dest /* nbo */) { /* -- * e.g. * * struct sr_instance* sr = sr_get_global_instance(); * struct my_router* mr = (struct my_router*) * sr_get_subsystem(sr); * return my_findsrcip(mr, dest); * -- */ struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(get_sr()); // look up in routing table route_info_t route_info = rrtable_find_route(subsystem->rtable, dest); return route_info.intf->ip; } /* -- ip_findsrcip -- */
struct sr_vns_if* find_interface(struct sr_instance* sr, uint32_t IP){ //step through the list trying to find IP, then return name struct sr_vns_if* if_walker = 0; assert(sr); struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); assert(sub); if_walker = sub->if_list; while(if_walker) { if(if_walker->ip == IP) { return if_walker; } if_walker = if_walker->next; } return 0; }
void pwospf_hello_type(struct ip* ip_header, byte* payload, uint16_t payload_len, pwospf_header_t* pwospf_header, interface_t* intf) { printf(" ** pwospf_hello_type(..) called \n"); printf(" ** pwospf_hello_type(..) packet with length: %u \n", payload_len); // make hello packet pwospf_hello_packet_t* hello_packet = (pwospf_hello_packet_t*) malloc_or_die(sizeof(pwospf_hello_packet_t)); memcpy(&hello_packet->network_mask, payload, 4); memcpy(&hello_packet->helloint, payload + 4, 2); memcpy(&hello_packet->padding, payload + 6, 2); // display packet printf(" ** pwospf_hello_type(..) displayed header contents:\n"); display_hello_packet(hello_packet); // check mask and hello interval if(intf->subnet_mask == hello_packet->network_mask && intf->helloint == ntohs(hello_packet->helloint)) { printf(" ** pwospf_hello_type(..) network mask and hello interval correct\n"); // if the interface has no neighbors if(intf->neighbor_list == NULL) { printf(" ** pwospf_hello_type(..) interface has no neighbors, adding new neighbor\n"); add_neighbor(intf, pwospf_header->router_id, ip_header->ip_src.s_addr, hello_packet->helloint, hello_packet->network_mask); } else { // interface has existing neighbors // generate neighbor object neighbor_t* neighbor = make_neighbor(pwospf_header->router_id, ip_header->ip_src.s_addr, hello_packet->helloint, hello_packet->network_mask); // get last instance so that lsu info can be put back pthread_mutex_lock(&intf->neighbor_lock); node* ret = llist_find( intf->neighbor_list, predicate_id_neighbor_t,(void*) &pwospf_header->router_id); pthread_mutex_unlock(&intf->neighbor_lock); if( ret!= NULL) { neighbor_t *neighbor_ret = (neighbor_t*) ret->data; neighbor->last_adverts = neighbor_ret->last_adverts; neighbor->last_lsu_packet = neighbor_ret->last_lsu_packet; } // lock neighbor list pthread_mutex_lock(&intf->neighbor_lock); // if exists, then update, otherwise add intf->neighbor_list = llist_update_beginning_delete(intf->neighbor_list, predicate_neighbor_t, (void*) neighbor); pthread_mutex_unlock(&intf->neighbor_lock); } // update info in neighbor db // get instance of router struct sr_instance* sr_inst = get_sr(); struct sr_router* router = (struct sr_router*)sr_get_subsystem(sr_inst); update_neighbor_vertex_t_rid(router, ip_header->ip_src.s_addr, pwospf_header->router_id); } else { printf(" ** pwospf_hello_type(..) network mask or hello interval incorrect\n"); } }
void send_ip_packet(byte* ip_packet, struct ip* ip_header, route_info_t route_info) { printf(" ** send_ip_packet(..) called \n"); // display generated packet len addr_ip_t dst_ip, src_ip; memcpy(&dst_ip, &ip_header->ip_dst, 4); memcpy(&src_ip, &ip_header->ip_src, 4); if(check_if_local_subnet(dst_ip, src_ip, route_info.intf->subnet_mask) == FALSE) { // non local subnet printf(" ** send_ip_packet(..) destination on non-local subnet\n"); // check if dst directly connected if(route_info.ip == 0) printf(" ** send_ip_packet(..) destination directly connected\n"); else dst_ip = route_info.ip; } else printf(" ** send_ip_packet(..) destination on local subnet\n"); struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(get_sr()); arp_cache_handle_partial_frame(subsystem, route_info.intf, dst_ip, ip_packet, ntohs(ip_header->ip_len), ETHERTYPE_IP); }
void ip_look_up(byte* ip_packet, struct ip* ip_header) { printf(" ** ip_lookup(..) called \n"); // get ptr to global router instance struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(get_sr()); // get dst ip object addr_ip_t dst_ip; memcpy(&dst_ip, &ip_header->ip_dst, 4); // look up in routing table route_info_t route_info = rrtable_find_route(subsystem->rtable, dst_ip); if(route_info.intf == NULL) { printf(" ** ip_lookup(..) Error! No route found \n"); } else { // display output interface printf(" ** ip_lookup(..) output interface for ip: %s\n", quick_ip_to_string(dst_ip)); display_interface(route_info.intf); // set src ip as the ip of the output interface memcpy(&ip_header->ip_src, &route_info.intf->ip, 4); memcpy(ip_packet, ip_header, ip_header->ip_hl); // check if ttl expired if(ip_header->ip_ttl == 1) { printf(" ** ip_lookup(..) ttl expired, sending ICMP ttl error message \n"); uint8_t code = ICMP_TYPE_CODE_TTL_TRANSIT; uint16_t len = ntohs(ip_header->ip_len); icmp_type_ttl_send(&code, ip_packet, &len, ip_header); } else { printf(" ** ip_lookup(..) decrementing ttl \n"); // create new ip header struct ip* ip_header_ttl = (struct ip*) malloc_or_die(ip_header->ip_hl * 4); memcpy(ip_header_ttl, ip_header, ip_header->ip_hl * 4); // decrement ttl ip_header_ttl->ip_ttl = ip_header_ttl->ip_ttl - 1; // generate checksum ip_header_ttl->ip_sum = 0; ip_header_ttl->ip_sum = htons(htons(inet_chksum((void*)ip_header_ttl, ip_header_ttl->ip_hl * 4))); // get payload uint16_t payload_len = ntohs(ip_header_ttl->ip_len) - (ip_header_ttl->ip_hl * 4); printf(" ** ip_lookup(..) Payload size %u bytes \n", payload_len); memcpy(ip_packet, ip_header_ttl, ip_header_ttl->ip_hl * 4); // make new ip packet send_ip_packet(ip_packet, ip_header_ttl, route_info); } } }
struct sr_vns_if* sr_get_interface(struct sr_instance* sr, const char* name) { struct sr_vns_if* if_walker = 0; /* -- REQUIRES -- */ assert(name); assert(sr); struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); assert(sub); if_walker = sub->if_list; while(if_walker) { if(!strncmp(if_walker->name,name,SR_NAMELEN)) { return if_walker; } if_walker = if_walker->next; } return 0; } /* -- sr_get_interface -- */
void sr_print_if_list(struct sr_instance* sr) { struct sr_vns_if* if_walker = 0; struct sr_router* sub = (struct sr_router*)sr_get_subsystem(sr); if(sub->if_list == 0) { printf(" Interface list empty \n"); return; } if_walker = sub->if_list; sr_print_if(if_walker); while(if_walker->next) { if_walker = if_walker->next; sr_print_if(if_walker); } } /* -- sr_print_if_list -- */
void pwospf_send_lsu() { printf(" ** pwospf_send_lsu(..) called\n"); // get instance of router struct sr_instance* sr_inst = get_sr(); struct sr_router* router = (struct sr_router*)sr_get_subsystem(sr_inst); int num_adverts = 0; byte* ls_adverts = get_ls_adverts_src(router, &num_adverts); int i = 0; node* first = NULL; neighbor_t* neighbor = NULL; printf(" ** pwospf_send_lsu(..) number of adverts: %d\n", num_adverts); printf(" ** pwospf_send_lsu(..) adverts:\n"); display_neighbor_vertices_src(router); // now create lsu_packet pwospf_lsu_packet_t *lsu_packet = (pwospf_lsu_packet_t*) malloc_or_die(sizeof(pwospf_lsu_packet_t)); //increment lsu sequence router->ls_info.lsu_seq = router->ls_info.lsu_seq + 1; lsu_packet->seq = htons(router->ls_info.lsu_seq); uint16_t ttl = PWOSPF_LSU_TTL; lsu_packet->ttl = htons(ttl); lsu_packet->no_of_adverts = htonl(num_adverts); // calculate length of entire pwospf packet uint16_t pwospf_packet_len = sizeof(pwospf_lsu_packet_t) + sizeof(pwospf_header_t) + sizeof(pwospf_ls_advert_t) * num_adverts; //make pwospf header pwospf_header_t* pwospf_header = (pwospf_header_t*) malloc_or_die(sizeof(pwospf_header_t)); pwospf_header->version = PWOSPF_VER; pwospf_header->type = PWOSPF_TYPE_LSU; pwospf_header->len = htons(pwospf_packet_len); pwospf_header->router_id = router->ls_info.router_id; pwospf_header->area_id = router->ls_info.area_id; pwospf_header->checksum = 0; pwospf_header->au_type = PWOSPF_AU_TYPE; pwospf_header->authentication = PWOSPF_AUTHEN; // generate raw packet byte* pwospf_packet = (byte*) malloc_or_die(pwospf_packet_len); memcpy(pwospf_packet, pwospf_header, sizeof(pwospf_header_t)); memcpy(pwospf_packet + sizeof(pwospf_header_t), lsu_packet, sizeof(pwospf_lsu_packet_t)); memcpy(pwospf_packet + sizeof(pwospf_header_t) + sizeof(pwospf_lsu_packet_t), ls_adverts, sizeof(pwospf_ls_advert_t) * num_adverts); // generate checksum pwospf_header->checksum = htons(htons(inet_chksum((void*) pwospf_packet, pwospf_packet_len))); memcpy(pwospf_packet, pwospf_header, sizeof(pwospf_header_t)); free(ls_adverts); free(lsu_packet); free(pwospf_header); printf(" ** pwospf_send_lsu(..) pwospf packet with length %u generated\n", pwospf_packet_len); // now iterate through each interface for( i = 0; i < router->num_interfaces ; i++) { // now iterate this interface's neighbors list first = router->interface[i].neighbor_list; pthread_mutex_lock(&router->interface[i].neighbor_lock); while(first != NULL) { // get neighbor neighbor = (neighbor_t*) first->data; if(neighbor != NULL) { struct in_addr src, dst; src.s_addr = router->interface[i].ip; dst.s_addr = neighbor->ip; make_ip_packet(pwospf_packet, pwospf_packet_len, dst, src, IP_PROTOCOL_OSPF); } first = first->next; } pthread_mutex_unlock(&router->interface[i].neighbor_lock); } }
int sr_cpu_input(struct sr_instance* sr) { /* REQUIRES */ assert(sr); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); fprintf(stderr, "!!! sr_cpu_input(..) (sr_cpu_extension_nf2.c) called while running in cpu mode !!!\n"); // fprintf(stderr, "!!! you need to implement this function to read from the hardware !!!\n"); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); //while (1); router_t* router = (router_t*) sr_get_subsystem(sr); int i; char* internal_names[NUM_INTERFACES] = {"eth0", "eth1", "eth2", "eth3"}; /* setup select */ fd_set read_set; FD_ZERO(&read_set); int READ_BUF_SIZE = 16384; unsigned char readBuf[READ_BUF_SIZE]; while (1) { for (i = 0; i < NUM_INTERFACES; ++i) { FD_SET(router->sockfd[i], &read_set); } // struct timeval t; // t.tv_usec = 500; // timeout every half a millisecond int nfd = array_max(router->sockfd, NUM_INTERFACES) + 1; if (select(nfd, &read_set, NULL, NULL, NULL) < 0) { perror("select"); exit(1); } for (i = 0; i < NUM_INTERFACES; ++i) { if (FD_ISSET(router->sockfd[i], &read_set)) { printf("\n\n Something on %s \n", internal_names[i]); // assume each read is a full packet int read_bytes = read(router->sockfd[i], readBuf, READ_BUF_SIZE); /* log packet */ // pthread_mutex_lock(rs->log_dumper_mutex); //TODO: lock sr_log_packet(sr, (unsigned char*)readBuf, read_bytes); // pthread_mutex_unlock(rs->log_dumper_mutex); /* send packet */ sr_integ_input(sr, readBuf, read_bytes, internal_names[i]); } } } //assert(0); /* * TODO: Read packet from the hardware and pass to sr_integ_input(..) * e.g. * * sr_integ_input(sr, * packet, * lent * * len, * "eth2" ); * lent * */ /* * Note: To log incoming packets, use sr_log_packet from sr_dumper.[c,h] */ /* RETURN 1 on success, 0 on failure. * Note: With a 0 result, the router will shut-down */ return 1; } /* -- sr_cpu_input -- */
void pwospf_lsu_type(struct ip* ip_header, byte* payload, uint16_t payload_len, pwospf_header_t* pwospf_header, interface_t* intf) { printf(" ** pwospf_lsu_type(..) called \n"); printf(" ** pwospf_lsu_type(..) packet with length: %u \n", payload_len); struct sr_instance* sr_inst = get_sr(); struct sr_router* router = (struct sr_router*)sr_get_subsystem(sr_inst); // make lsu packet pwospf_lsu_packet_t* lsu_packet = (pwospf_lsu_packet_t*) malloc_or_die(sizeof(pwospf_lsu_packet_t)); memcpy(&lsu_packet->seq, payload, 2); memcpy(&lsu_packet->ttl, payload + 2, 2); memcpy(&lsu_packet->no_of_adverts, payload + 4, 4); // display packet printf(" ** pwospf_lsu_type(..) displayed header contents:\n"); display_lsu_packet(lsu_packet); // calculate number of adverts int num_adverts = ((payload_len - 8)/sizeof(pwospf_ls_advert_t)); printf(" ** pwospf_lsu_type(..) number of adverts: %d\n", num_adverts); // check if I generated the LSU if(pwospf_header->router_id != intf->router_id) { // not generated by self // check if neighbor ever sent hello packet pthread_mutex_lock(&intf->neighbor_lock); node* ret = llist_find( intf->neighbor_list, predicate_id_neighbor_t,(void*) &pwospf_header->router_id); pthread_mutex_unlock(&intf->neighbor_lock); if(ret != NULL) { // have received a hello packet from this neighbor in the recent past neighbor_t *neighbor = (neighbor_t*) ret->data; display_neighbor_t((void*) neighbor); // check if lsu received for first time if(neighbor->last_adverts == NULL) { printf(" ** pwospf_lsu_type(..) first lsu received from this neighbor\n"); neighbor->last_lsu_packet = *lsu_packet; neighbor->last_adverts = (byte*) malloc_or_die(payload_len - 8); memcpy(neighbor->last_adverts, payload + 8, payload_len - 8); // add to list pthread_mutex_lock(&intf->neighbor_lock); intf->neighbor_list = llist_update_beginning_delete(intf->neighbor_list, predicate_id_neighbor_t_neighbor_t, (void*) neighbor); pthread_mutex_unlock(&intf->neighbor_lock); display_neighbor_t((void*) neighbor); // create router entry router_entry_t router_entry; router_entry.router_id = neighbor->id; router_entry.area_id = 0; //add vertex with router entry info add_neighbor_vertex_t(router, router_entry); //create subnet entry subnet_entry_t* subnet_entry; //add adverts to db printf(" ** pwospf_lsu_type(..) adding adverts to neighbor db\n"); int i; pwospf_ls_advert_t* ls_advert = (pwospf_ls_advert_t*) malloc_or_die(sizeof(pwospf_ls_advert_t)); for(i = 0; i < ntohl(lsu_packet->no_of_adverts) ; i++) { memcpy(&ls_advert->subnet, payload + sizeof(pwospf_lsu_packet_t) + sizeof(pwospf_ls_advert_t) * i, 4); memcpy(&ls_advert->mask, payload + sizeof(pwospf_lsu_packet_t) + 4 + sizeof(pwospf_ls_advert_t) * i, 4); memcpy(&ls_advert->router_id, payload + sizeof(pwospf_lsu_packet_t) + 8 + sizeof(pwospf_ls_advert_t) * i, 4); display_ls_advert(ls_advert); subnet_entry = create_subnet_entry_t_advert(ls_advert); add_subnet_entry_t(router, router_entry, subnet_entry); } // update vertices update_neighbor_vertex_t(router, router_entry); //calculate new routing table via Dijkstra calculate_routing_table(router); //check if route/multipath is enabled if(router->reroute_multipath_status == TRUE) { //run multipath reroute_multipath(router); } //dijkstra2(router); //free(lsu_packet); //free(ret); //free(neighbor); //free(ls_advert); } else { // check if the previous seq was same if(neighbor->last_lsu_packet.seq != lsu_packet->seq) { // nope, new seq neighbor->last_lsu_packet = *lsu_packet; // flood to all neighbors pwospf_flood_lsu(ip_header, pwospf_header, lsu_packet, neighbor, intf); // check if content the same printf("last adverts :%s\n", (char*) neighbor->last_adverts); printf("new: %s\n", (char*) (payload + 8)); if(memcmp(neighbor->last_adverts, payload + 8, payload_len - 8) != 0) { // nope new content printf(" ** pwospf_lsu_type(..) new content neighbor db\n"); if(ntohl(neighbor->last_lsu_packet.no_of_adverts) != ntohl(lsu_packet->no_of_adverts)) { // free mem, as new adverts might need different memory free(neighbor->last_adverts); // now allocate new mem space neighbor->last_adverts = (byte*) malloc_or_die(payload_len - 8); } memcpy(neighbor->last_adverts, payload + 8, payload_len - 8); neighbor->last_lsu_packet = *lsu_packet; // update packet info in neighbor list pthread_mutex_lock(&intf->neighbor_lock); intf->neighbor_list = llist_update_beginning_delete(intf->neighbor_list, predicate_id_neighbor_t_neighbor_t, (void*) neighbor); pthread_mutex_unlock(&intf->neighbor_lock); // check if entry exists in DB // create router entry router_entry_t router_entry; router_entry.router_id = neighbor->id; router_entry.area_id = 0; //refresh vertex with router entry info, clear previous subnets refresh_neighbor_vertex_t(router, router_entry); //create subnet entry subnet_entry_t* subnet_entry; int i; pwospf_ls_advert_t* ls_advert = (pwospf_ls_advert_t*) malloc_or_die(sizeof(pwospf_ls_advert_t)); if(check_neighbor_vertex_t_router_entry_t_id(router, neighbor->id) == 1) { printf(" ** pwospf_lsu_type(..) neighbor already known, checking if any new adverts\n"); //neighbor present in db, check if any new adverts for(i = 0; i < ntohl(lsu_packet->no_of_adverts) ; i++) { memcpy(&ls_advert->subnet, payload + sizeof(pwospf_lsu_packet_t) + sizeof(pwospf_ls_advert_t) * i, 4); memcpy(&ls_advert->mask, payload + sizeof(pwospf_lsu_packet_t) + 4 + sizeof(pwospf_ls_advert_t) * i, 4); memcpy(&ls_advert->router_id, payload + sizeof(pwospf_lsu_packet_t) + 8 + sizeof(pwospf_ls_advert_t) * i, 4); display_ls_advert(ls_advert); subnet_entry = create_subnet_entry_t_advert(ls_advert); add_subnet_entry_t(router, router_entry, subnet_entry); } // update vertices update_neighbor_vertex_t(router, router_entry); } //run Djikstra's algo to calculate new routing table calculate_routing_table(router); //check if route/multipath is enabled if(router->reroute_multipath_status == TRUE) { //run multipath reroute_multipath(router); } //dijkstra2(router); } else { printf(" ** pwospf_lsu_type(..) error, content same as previous from this neighbor, only updating time stamp in DB\n"); // update timestamp // create router entry router_entry_t router_entry; router_entry.router_id = neighbor->id; router_entry.area_id = 0; update_neighbor_vertex_t_timestamp(router, router_entry); } } else { printf(" ** pwospf_lsu_type(..) error, seq same as previous one from this neighbor, dropping\n"); } } } else { printf(" ** pwospf_lsu_type(..) error, neighbor hasn't said hello recently, dropping\n"); } } else { //drop packet printf(" ** pwospf_lsu_type(..) error, LSU generated by self. dropping\n"); //free stuff free(lsu_packet); } }
int sr_load_rt(struct sr_instance* sr,const char* filename) { FILE* fp; char line[BUFSIZ]; char dest[32]; char gw[32]; char mask[32]; char iface[32]; struct in_addr dest_addr; struct in_addr gw_addr; struct in_addr mask_addr; interface_t* intf; /* -- REQUIRES -- */ assert(filename); if( access(filename,R_OK) != 0) { perror("access"); return -1; } fp = fopen(filename,"r"); struct sr_router* subsystem = (struct sr_router*)sr_get_subsystem(sr); while( fgets(line,BUFSIZ,fp) != 0) { printf("%s\n", line); sscanf(line,"%s %s %s %s",dest,gw,mask,iface); if(inet_aton(dest,&dest_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", dest); return -1; } if(inet_aton(gw,&gw_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", gw); return -1; } if(inet_aton(mask,&mask_addr) == 0) { fprintf(stderr, "Error loading routing table, cannot convert %s to valid IP\n", mask); return -1; } intf = get_interface_name(subsystem, iface); if(intf == NULL) { fprintf(stderr, "Error! Invalid interface: %s\n", iface); } else { rrtable_route_add( subsystem->rtable, dest_addr.s_addr, gw_addr.s_addr, mask_addr.s_addr, intf, 's' ); } } /* -- while -- */ return 0; /* -- success -- */ } /* -- sr_load_rt -- */