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_init(struct sr_instance* sr) { printf(" ** sr_integ_init(..) called \n"); /* Register router state with global instance */ struct sr_router* subsystem = (struct sr_router*)malloc(sizeof(struct sr_router)); assert(subsystem); sr_set_subsystem(get_sr(), subsystem); } /* -- sr_integ_init -- */
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 -- */
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); } } }
static void proc_go(PD *p) { struct gouser_stack *sp; D(("BDOS: xexec - trying to load (and execute) a process on 0x%lx...\n", p->p_tbase)); p->p_parent = run; /* create a stack at the end of the TPA */ sp = (struct gouser_stack *) (p->p_hitpa - sizeof(struct gouser_stack)); sp->basepage = p; /* the stack contains the basepage */ sp->retaddr = p->p_tbase; /* return address a3 is text start */ sp->sr = get_sr() & 0x0700; /* the process will start in user mode, same IPL */ /* the other stack is the supervisor stack */ sp->other_sp = (long) &supstk[SUPSIZ]; /* store this new stack in the saved a7 field of the PD */ p->p_areg[7-3] = (long) sp; #if 1 /* the following settings are not documented, and hence theoretically * the assignments below are not necessary. * However, many programs test if A0 = 0 to check if they are running * as a normal program or as an accessory, so we need to clear at least * this register! */ { /* d1-d7/a0-a2 and dummy return address set to zero */ int i; for(i = 0; i < 11 ; i++) sp->fill[i] = 0; } p->p_areg[6-3] = (long) sp; /* a6 to hold a copy of the stack */ p->p_areg[5-3] = p->p_dbase; /* a5 to point to the DATA segt */ p->p_areg[4-3] = p->p_bbase; /* a4 to point to the BSS segt */ #endif /* the new process is the one to run */ run = (PD *) p; gouser(); }
void sr_integ_init(struct sr_instance* sr) { printf(" ** sr_integ_init(..) called \n"); sr_router* subsystem = (sr_router*)malloc(sizeof(sr_router)); assert(subsystem); sr_set_subsystem(get_sr(), subsystem); // initialize arp and interfaces and routing table arp_cache_init(subsystem); interface_init(subsystem); rrtable_init(subsystem); hw_rrtable_init(subsystem); //enable ospf by default toggle_ospf_status(subsystem, TRUE); //disable reroute/multipath toggle_reroute_multipath_status(subsystem, FALSE); //flush hw registers #ifdef _CPUMODE_ hw_init(subsystem); writeReg(&subsystem->hw_device, CPCI_REG_CTRL, 0x00010100); usleep(2000); #endif } /* -- sr_integ_init -- */
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); } }
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); } }