void CDiscoveryApp::SetDefaulRoute(in_addr_t gw) { in_addr_t def_dest=inet_addr("0.0.0.0"); in_addr_t def_mask=inet_addr("0.0.0.0"); in_addr addr={0}; char szDevice [64]; switch( get_default_gateway( &addr.s_addr, szDevice, sizeof(szDevice) ) ) { case DEFAULT_ETH_INTERF: LOG("REPLACING DefaultGW [%s] on %s", inet_ntoa(addr), m_szEthInterf); del_route(addr.s_addr); set_route(def_dest, gw, def_mask); break; case DEFAULT_NOT_ETH_INTERF: LOG("NOT REPLACING DefaultGW GW [%s] on %s", inet_ntoa(addr), szDevice ); break; case DEFAULT_NOT_SET: LOG("SETTING DefaultGW [%s] on %s", inet_ntoa(addr), m_szEthInterf); set_route(def_dest, gw, def_mask); break; } }
/* * Delete/retain addresses to list and handle the route entries. */ void install_address(struct preflist **plist, struct interface *ifp) { struct preflist *pl, **ppl, *temp; /* DELETE FIRST */ for (pl = *plist, ppl = plist; pl;) { temp = pl; pl = pl->pl_next; if (temp->pl_flag != PL_DELADDR) { ppl = &(temp->pl_next); continue; } else { *ppl = pl; del_route(temp, ifp); free(temp); } } /* AND THEN ADD */ for (pl = *plist, ppl = plist; pl;) { temp = pl; pl = pl->pl_next; if (temp->pl_flag == PL_NEWADDR) { if (ifp->if_flag & IFF_UP && ifp->if_lladdr != NULL) add_route(temp, ifp); } ppl = &(temp->pl_next); } return; }
int del_tun_default_route_v6() { /* * Assign route to ::/1 and 8000::/1 via tun interface */ lisp_addr_t dest; lisp_addr_t *src = NULL; lisp_addr_t gw; uint32_t prefix_len = 0; uint32_t metric = 0; prefix_len = 1; metric = 512; get_lisp_addr_from_char("::",&gw); get_lisp_addr_from_char("::",&dest); if (del_route(AF_INET6, tun_ifindex, &dest, src, NULL, prefix_len, metric, RT_TABLE_MAIN) != GOOD){ return (BAD); } get_lisp_addr_from_char("8000::",&dest); if (del_route(AF_INET6, tun_ifindex, &dest, src, NULL, prefix_len, metric, RT_TABLE_MAIN) != GOOD){ return (BAD); } return(GOOD); }
int ni_set_state(NET ifp, int opcode) { int err = 0; if ((opcode != NI_DOWN) && (opcode != NI_UP)) { return ENP_PARAM; } LOCK_NET_RESOURCE(NET_RESID); if (opcode == NI_DOWN) /* clean up system tables */ { #ifdef INCLUDE_TCP if_killsocks(ifp); /* kill this iface's sockets */ #endif /* INCLUDE_TCP */ del_route(0, 0, if_netnumber(ifp)); /* delete any IP routes */ clear_arp_entries(NULLIP, ifp); /* delete any ARP entries */ } /* force if-mib AdminStatus flag to correct setting. This will * keep devices without n_setstate() calls from receiving any * packet to send from ip2mac(). */ if (opcode == NI_UP) ifp->n_mib->ifAdminStatus = NI_UP; else ifp->n_mib->ifAdminStatus = NI_DOWN; ifp->n_mib->ifLastChange = cticks * (100/TPS); if (ifp->n_setstate) /* call state routine if any */ err = ifp->n_setstate(ifp, opcode); else err = 0; /* no routine == no error */ if(!err) { /* Get here if setstate was OK - set ifOperStatus */ if (opcode == NI_UP) ifp->n_mib->ifOperStatus = NI_UP; else ifp->n_mib->ifOperStatus = NI_DOWN; } UNLOCK_NET_RESOURCE(NET_RESID); return err; }
/* * Remove all the created rules to the source routing tables */ void remove_created_rules() { lispd_iface_list_elt *interface_list = NULL; lispd_iface_elt *iface = NULL; interface_list = head_interface_list; while (interface_list != NULL){ iface = interface_list->iface; if (iface->ipv4_address->afi != AF_UNSPEC){ if (iface->ipv4_gateway != NULL){ del_route(AF_INET,iface->iface_index,NULL,NULL,iface->ipv4_gateway,0,0,iface->iface_index); } del_rule(AF_INET,0,iface->iface_index,iface->iface_index,RTN_UNICAST,iface->ipv4_address,32,NULL,0,0); } if (iface->ipv6_address->afi != AF_UNSPEC){ if (iface->ipv6_gateway != NULL){ del_route(AF_INET6,iface->iface_index,NULL,NULL,iface->ipv6_gateway,0,0,iface->iface_index); } del_rule(AF_INET6,0,iface->iface_index,iface->iface_index,RTN_UNICAST,iface->ipv6_address,128,NULL,0,0); } interface_list = interface_list->next; } }
/* FUNCTION: netmain_route_del() * * Delete IP route table entry * * PARAM1: CLI_CTX CLI context * * RETURNS: int 0 or error code */ STATIC int netmain_route_del(CLI_CTX ctx) { struct cli_addr *cap; ip_addr dst; ip_addr mask; int ifindex; int rc; /* extract the destination IP address */ cap = (struct cli_addr *)CLI_VALUE(ctx, 'd'); if (cap->type == CLI_IPV4) { dst = *((ip_addr *)&cap->addr[0]); } else { /* failed to parse destination IP address */ return (CLI_ERR_PARAM); } /* extract the address mask */ cap = (struct cli_addr *)CLI_VALUE(ctx, 'm'); if (cap->type == CLI_IPV4) { mask = *((ip_addr *)&cap->addr[0]); } else { /* failed to parse address mask */ return (CLI_ERR_PARAM); } /* extract the interface identifier (zero-based) */ ifindex = (int)CLI_VALUE(ctx, 'i') - 1; if ((ifindex < 0) || (ifindex >= MAXNETS) || (if_getbynum(ifindex) == (NET)NULL)) { /* bad interface index */ return (CLI_ERR_PARAM); } /* del_route() returns the number of routes deleted */ rc = del_route(dst, mask, ifindex); return ((rc > 0) ? 0 : CLI_ERR_EXECUTE); }
void proxy_instance::refresh_all_traffic(int if_index, const addr_storage& g_addr){ HC_LOG_TRACE(""); upstream_src_state_map::iterator iter_uss; src_state_map::iterator iter_src; state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_group_state_pair* sgs_pair = 0; if(if_index == m_upstream){ HC_LOG_ERROR("the if_index:" << if_index << " mussnt be the upstream, upstream have no joined groups"); } //process upstream iter_uss = m_upstream_state.find(g_addr); if(iter_uss != m_upstream_state.end()){ //g_addr found for(iter_src = iter_uss->second.begin(); iter_src != iter_uss->second.end(); iter_src++){ if(!split_traffic(m_upstream, g_addr, iter_src->first)){ //have to check old upstream source because the have no default stream so they dont refresh themselve like downstreams iter_src->second.flag = src_state::UNUSED_SRC; del_route(if_index,g_addr,iter_src->first); } } } //process downstream for(iter_table = m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ if(if_index != iter_table->first){ iter_state = iter_table->second.find(g_addr); if(iter_state != iter_table->second.end()){ sgs_pair = &iter_state->second; for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ split_traffic(iter_table->first, g_addr, iter_src->first); } } } } }
int main( int argc, char **argv ) { uint8 anAddress[4]; uint8 anMask[4]; uint8 anGateway[4] = { 0, 0, 0, 0 }; const char *pzGateway = NULL, *pzProgram; const char *pzCommand, *pzNetAddr, *pzNetMask; struct rtentry sRoute; bool bLong = false; bool bNetSet = false, bMaskSet = false, bGwSet = false; int c; if ( (pzProgram = strrchr( *argv, '/' )) != NULL ) ++pzProgram; else pzProgram = *argv; memset( &sRoute, 0, sizeof( sRoute ) ); sRoute.rt_metric = 0; sRoute.rt_flags = RTF_UP | RTF_STATIC; /* Not necessary */ while ( ( c = getopt_long( argc, argv, "hlqvi:g:", long_opts, ( int * )0 ) ) != EOF ) { switch ( c ) { case 0: break; case 'l': bLong = true; break; case 'v': g_nShowVersion = true; break; case 'h': g_nShowHelp = true; break; default: usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } } argc -= optind; argv += optind; if ( (pzCommand = *argv++) == NULL ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } /* Check command is valid */ if ( strcmp( pzCommand, "list" ) == 0 ) { list_routes( bLong ); return ( EXIT_SUCCESS ); } else if ( strcmp( pzCommand, "add" ) != 0 && strcmp( pzCommand, "del" ) != 0 ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } /* Add or delete a route */ /* Look for address parameter */ while ( *argv ) { const char *pzInstruction = *argv++; char *pzArg = *argv++; if ( pzArg == NULL ) { /* No argument */ usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } if ( strcmp( pzInstruction, "net" ) == 0 ) { char *pzStr; if( bNetSet == true ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } if( strcmp( pzArg, "default" ) == 0 ) { bNetSet = true; bMaskSet = true; } else { if( (pzStr = strchr( pzArg, '/' )) != NULL ) { /* CIDR notation in address parameter */ int nBits; uint32 nIpAddr = 0xFFFFFFFF; *pzStr++ = 0; if( (nBits = atoi( pzStr )) < 32 ) nIpAddr <<= (32 - nBits); *((uint32 *)&((struct sockaddr_in *)&sRoute.rt_genmask)->sin_addr) = htonl( nIpAddr ); bMaskSet = true; } /* Interpret as IP address */ parse_ipaddress( (uint8*)&((struct sockaddr_in *)&sRoute.rt_dst)->sin_addr, pzArg ); bNetSet = true; } } else if ( strcmp( pzInstruction, "mask" ) == 0 ) { if( bMaskSet == true ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } parse_ipaddress( (uint8*)&((struct sockaddr_in *)&sRoute.rt_genmask)->sin_addr, pzArg ); bMaskSet = true; } else if ( strcmp( pzInstruction, "gw" ) == 0 ) { if( bGwSet == true ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } parse_ipaddress( (uint8*)&((struct sockaddr_in *)&sRoute.rt_gateway)->sin_addr, pzArg ); sRoute.rt_flags |= RTF_GATEWAY; bGwSet = true; } else { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } } /* Check for required arguments */ if( !bNetSet || !bMaskSet ) { usage( pzProgram, 0 ); return ( EXIT_FAILURE ); } /* Perform action */ if ( strcmp( pzCommand, "add" ) == 0 ) { add_route( &sRoute ); } else if ( strcmp( pzCommand, "del" ) == 0 ) { del_route( &sRoute ); } return ( EXIT_SUCCESS ); }
void proxy_instance::handle_config(struct config_msg* c){ HC_LOG_TRACE(""); switch(c->type){ case config_msg::ADD_DOWNSTREAM: { //if interface exist if(m_state_table.find(c->if_index) != m_state_table.end()){ HC_LOG_ERROR("failed to add downstream, interface " << c->if_index << " allready exist"); } m_state_table.insert(state_tabel_pair(c->if_index,g_state_map())); m_vif_map.insert(vif_pair(c->if_index,c->vif)); registrate_if(c->if_index); break; } case config_msg::DEL_DOWNSTREAM: { //if interface exist if(m_state_table.find(c->if_index) == m_state_table.end()){ HC_LOG_ERROR("failed to del downstream, interface " << c->if_index << " not exist"); } unregistrate_if(c->if_index); state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_group_state_pair* sgs_pair = NULL; src_state_map::iterator iter_src; iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) { HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); return; } vector<addr_storage> tmp_erase_group_vector; for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ sgs_pair = &iter_state->second; //remove all own sources (routes) for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ if(iter_src->second.flag == src_state::CACHED_SRC){ del_route(iter_table->first, iter_state->first, iter_src->first); } } //save all groups for remove tmp_erase_group_vector.push_back(iter_state->first); //refresh upstream if(!is_group_joined(c->if_index,iter_state->first)){ if(!m_sender->send_leave(m_upstream, iter_state->first)){ HC_LOG_ERROR("failed to leave on upstream group: " << iter_state->first); } } } //erase all groups for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ iter_table->second.erase(iter_state); //calculate the joined group roles refresh_all_traffic(c->if_index, tmp_erase_group_vector[i]); }else{ HC_LOG_ERROR("cant find downstream group: " << tmp_erase_group_vector[i]);} } //clean state table m_state_table.erase(iter_table); //clean vif map vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); if(it_vif_map == m_vif_map.end()) { HC_LOG_ERROR("faild to del downstream: cant find vif to if_index: " << c->if_index); return; } m_vif_map.erase(it_vif_map); //HC_LOG_ERROR("del downstream not implementeted"); break; } case config_msg::SET_UPSTREAM: { //remove current upstream unregistrate_if(c->if_index); vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); if(it_vif_map == m_vif_map.end()) { HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); return; } m_vif_map.erase(it_vif_map); //ToDo //refresh routes????????????????????????????????? HC_LOG_ERROR("set upstream not implementeted"); //set new upstream m_upstream = c->if_index; m_vif_map.insert(vif_pair(c->if_index,c->vif)); registrate_if(c->if_index); break; } default: HC_LOG_ERROR("unknown config message format"); } }
void proxy_instance::handle_clock(struct clock_msg* c){ HC_LOG_TRACE(""); proxy_msg msg; state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_state_map::iterator iter_src; src_group_state_pair* sgs_pair = NULL; switch(c->type){ case clock_msg::SEND_GQ_TO_ALL: { //send GQ send_gq_to_all(); m_check_source.check(); //reloade routing table //##-- dekrement all counter of all groups on all downstream interfaces in RUNNING state --## //##-- and dekrement all counter of all groups source addresses --## vector<addr_storage> tmp_erase_group_vector; //if group not joined and all sources are deleted for(iter_table= m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ sgs_pair = &iter_state->second; //-- process groups in RUNNING state -- if( sgs_pair->second.flag == src_state::RUNNING){ //if counter == 0 delete this group after query response if(--sgs_pair->second.robustness_counter == 0){ sgs_pair->second.flag= src_state::WAIT_FOR_DEL; sgs_pair->second.robustness_counter = PROXY_INSTANCE_DEL_IMMEDIATELY; msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); m_timing->add_time(MC_TV_QUERY_RESPONSE_INTERVAL*1000 /*msec*/,this,msg); } } //-- process sources in FOREIGN_SRC state -downstream- -- vector<addr_storage> tmp_erase_source_vector; for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ //del unused sources vif_map::iterator it_vif_map; if((it_vif_map = m_vif_map.find(iter_table->first)) == m_vif_map.end()){ HC_LOG_ERROR("cant find vif to if_index:" << iter_table->first); } if(m_check_source.is_src_unused(it_vif_map->second, iter_src->first, iter_state->first)){ iter_src->second.robustness_counter--; }else{ iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; } if(iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); //refresh routing if(iter_src->second.flag == src_state::CACHED_SRC){ del_route(iter_table->first, iter_state->first, iter_src->first); } } }else{ HC_LOG_ERROR("downstream source is in unknown state: " << iter_src->second.state_type_to_string()); } } //erase invalid sources for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ if((iter_src = sgs_pair->first.find(tmp_erase_source_vector[i]))!= sgs_pair->first.end()){ sgs_pair->first.erase(iter_src); }else{ HC_LOG_ERROR("cant find invalid downstream soruce: " << tmp_erase_source_vector[i]); } } //if group has no sources and is not joined (flag=INIT) remove the group if(sgs_pair->first.size() == 0){ if(sgs_pair->second.flag == src_state::INIT){ tmp_erase_group_vector.push_back(iter_state->first); } } } //erase unused groups for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ iter_table->second.erase(iter_state); }else{ HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); } } tmp_erase_group_vector.clear(); } //-- process sources in FOREIGN_SRC state -upstream- -- upstream_src_state_map::iterator tmp_it_up_ss_map; src_state_map* tmp_ss_map; tmp_erase_group_vector.clear(); //unused groups for(tmp_it_up_ss_map = m_upstream_state.begin(); tmp_it_up_ss_map != m_upstream_state.end(); tmp_it_up_ss_map++){ tmp_ss_map = &tmp_it_up_ss_map->second; vector<addr_storage> tmp_erase_source_vector; for(iter_src = tmp_ss_map->begin(); iter_src != tmp_ss_map->end(); iter_src++){ // if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ // //del old sources // if(--iter_src->second.robustness_counter == 0){ // //save invalid sources // tmp_erase_source_vector.push_back(iter_src->first); // //refresh routing // if(iter_src->second.flag == src_state::CACHED_SRC){ // del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); // } // } // }else{ // HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); // } if(iter_src->second.flag == src_state::UNUSED_SRC){ //del old sources if(--iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); } }else if(iter_src->second.flag == src_state::CACHED_SRC){ if(m_check_source.is_src_unused(m_upstream, iter_src->first, tmp_it_up_ss_map->first)){ if(--iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); } }else{ iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; } }else{ HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); } } //erase invalid sources for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ if((iter_src = tmp_ss_map->find(tmp_erase_source_vector[i])) != tmp_ss_map->end()){ tmp_ss_map->erase(iter_src); }else{ HC_LOG_ERROR("cant find invalid upstream soruce: " << tmp_erase_source_vector[i]); } } //if group has no sources remove the group if(tmp_it_up_ss_map->second.size() == 0){ tmp_erase_group_vector.push_back(tmp_it_up_ss_map->first); } } //erase unused groups for(unsigned int i=0; i < tmp_erase_group_vector.size(); i++){ tmp_it_up_ss_map = m_upstream_state.find(tmp_erase_group_vector[i]); if(tmp_it_up_ss_map != m_upstream_state.end()){ m_upstream_state.erase(tmp_it_up_ss_map); }else{ HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); } } //initiate new GQ msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::SEND_GQ_TO_ALL); m_timing->add_time(MC_TV_QUERY_INTERVAL*1000 /*msec*/,this,msg); break; } case clock_msg::SEND_GSQ: { iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(c->g_addr); if(iter_state == iter_table->second.end()) return; sgs_pair = &iter_state->second; if(sgs_pair->second.flag == src_state::RESPONSE_STATE){ m_sender->send_group_specific_query(c->if_index,c->g_addr); if(--sgs_pair->second.robustness_counter == PROXY_INSTANCE_DEL_IMMEDIATELY){ sgs_pair->second.flag = src_state::WAIT_FOR_DEL; msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); if(m_addr_family == AF_INET){ m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); }else if(m_addr_family == AF_INET6){ m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return; } }else{ msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::SEND_GSQ, iter_table->first, iter_state->first); if(m_addr_family == AF_INET){ m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); }else if(m_addr_family== AF_INET6){ m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return; } } } break; } case clock_msg::DEL_GROUP:{ iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(c->g_addr); if(iter_state == iter_table->second.end()) return; sgs_pair = &iter_state->second; if(sgs_pair->second.flag == src_state::WAIT_FOR_DEL){ HC_LOG_DEBUG("DEL_GROUP if_index: " << c->if_index << " group: " << c->g_addr); //refresh upstream if(!is_group_joined(c->if_index,c->g_addr)){ if(!m_sender->send_leave(m_upstream, c->g_addr)){ HC_LOG_ERROR("failed to leave on upstream group: " << c->g_addr); } } //del only if no FOREIGN_SRC available if(sgs_pair->first.size() == 0){ iter_table->second.erase(iter_state); }else{ //set groupstate to INIT sgs_pair->second.flag = src_state::INIT; } //refresh routing //cout << "in del group: refresh_all_traffic()..." << endl; refresh_all_traffic(c->if_index, c->g_addr); } break; } case clock_msg::SEND_GQ: break; //start up Query Interval vor new interfaces default: HC_LOG_ERROR("unknown clock message foramt"); } }
int configure (const options_t *options, interface_t *iface, const dhcp_t *dhcp) { route_t *route = NULL; route_t *new_route = NULL; route_t *old_route = NULL; struct hostent *he = NULL; char newhostname[HOSTNAME_MAX_LEN] = {0}; char curhostname[HOSTNAME_MAX_LEN] = {0}; char *dname = NULL; int dnamel = 0; if (! options || ! iface || ! dhcp) return -1; /* Remove old routes Always do this as the interface may have >1 address not added by us so the routes we added may still exist */ if (iface->previous_routes) { for (route = iface->previous_routes; route; route = route->next) if (route->destination.s_addr || options->dogateway) { int have = 0; if (dhcp->address.s_addr != 0) for (new_route = dhcp->routes; new_route; new_route = new_route->next) if (new_route->destination.s_addr == route->destination.s_addr && new_route->netmask.s_addr == route->netmask.s_addr && new_route->gateway.s_addr == route->gateway.s_addr) { have = 1; break; } if (! have) del_route (iface->name, route->destination, route->netmask, route->gateway, options->metric); } } /* If we don't have an address, then return */ if (dhcp->address.s_addr == 0) { if (iface->previous_routes) { free_route (iface->previous_routes); iface->previous_routes = NULL; } /* Only reset things if we had set them before */ if (iface->previous_address.s_addr != 0) { del_address (iface->name, iface->previous_address, iface->previous_netmask); memset (&iface->previous_address, 0, sizeof (struct in_addr)); memset (&iface->previous_netmask, 0, sizeof (struct in_addr)); restore_resolv (iface->name); /* we currently don't have a resolvconf style programs for ntp/nis */ exec_script (options->script, iface->infofile, "down"); } return 0; } if (add_address (iface->name, dhcp->address, dhcp->netmask, dhcp->broadcast) < 0 && errno != EEXIST) return -1; /* Now delete the old address if different */ if (iface->previous_address.s_addr != dhcp->address.s_addr && iface->previous_address.s_addr != 0) del_address (iface->name, iface->previous_address, iface->previous_netmask); #ifdef __linux__ /* On linux, we need to change the subnet route to have our metric. */ if (iface->previous_address.s_addr != dhcp->address.s_addr && options->metric > 0 && dhcp->netmask.s_addr != INADDR_BROADCAST) { struct in_addr td; struct in_addr tg; memset (&td, 0, sizeof (td)); memset (&tg, 0, sizeof (tg)); td.s_addr = dhcp->address.s_addr & dhcp->netmask.s_addr; add_route (iface->name, td, dhcp->netmask, tg, options->metric); del_route (iface->name, td, dhcp->netmask, tg, 0); } #endif /* Remember added routes */ if (dhcp->routes) { route_t *new_routes = NULL; int remember; for (route = dhcp->routes; route; route = route->next) { /* Don't set default routes if not asked to */ if (route->destination.s_addr == 0 && route->netmask.s_addr == 0 && ! options->dogateway) continue; remember = add_route (iface->name, route->destination, route->netmask, route->gateway, options->metric); /* If we failed to add the route, we may have already added it ourselves. If so, remember it again. */ if (remember < 0) for (old_route = iface->previous_routes; old_route; old_route = old_route->next) if (old_route->destination.s_addr == route->destination.s_addr && old_route->netmask.s_addr == route->netmask.s_addr && old_route->gateway.s_addr == route->gateway.s_addr) { remember = 1; break; } if (remember >= 0) { if (! new_routes) { new_routes = xmalloc (sizeof (route_t)); memset (new_routes, 0, sizeof (route_t)); new_route = new_routes; } else { new_route->next = xmalloc (sizeof (route_t)); new_route = new_route->next; } memcpy (new_route, route, sizeof (route_t)); new_route -> next = NULL; } } if (iface->previous_routes) free_route (iface->previous_routes); iface->previous_routes = new_routes; } if (options->dodns && dhcp->dnsservers) make_resolv(iface->name, dhcp); else logger (LOG_DEBUG, "no dns information to write"); if (options->dontp && dhcp->ntpservers) make_ntp(iface->name, dhcp); if (options->donis && (dhcp->nisservers || dhcp->nisdomain)) make_nis(iface->name, dhcp); /* Now we have made a resolv.conf we can obtain a hostname if we need one */ if (options->dohostname && ! dhcp->hostname) { he = gethostbyaddr (inet_ntoa (dhcp->address), sizeof (struct in_addr), AF_INET); if (he) { dname = he->h_name; while (*dname > 32) dname++; dnamel = dname - he->h_name; memcpy (newhostname, he->h_name, dnamel); newhostname[dnamel] = 0; } } gethostname (curhostname, sizeof (curhostname)); if (options->dohostname || strlen (curhostname) == 0 || strcmp (curhostname, "(none)") == 0 || strcmp (curhostname, "localhost") == 0) { if (dhcp->hostname) strcpy (newhostname, dhcp->hostname); if (*newhostname) { logger (LOG_INFO, "setting hostname to `%s'", newhostname); sethostname (newhostname, strlen (newhostname)); } } write_info (iface, dhcp, options); if (iface->previous_address.s_addr != dhcp->address.s_addr || iface->previous_netmask.s_addr != dhcp->netmask.s_addr) { memcpy (&iface->previous_address, &dhcp->address, sizeof (struct in_addr)); memcpy (&iface->previous_netmask, &dhcp->netmask, sizeof (struct in_addr)); exec_script (options->script, iface->infofile, "new"); } else exec_script (options->script, iface->infofile, "up"); return 0; }
int Handle_Update(unsigned short bgp_len) { //unsigned char *buf; unsigned char buf[1000]; u_int16_t *wr_len_p; u_int16_t wr_len; u_int16_t *pa_len_p; u_int16_t pa_len; u_int16_t nlri_len; u_int8_t *prefix_bits; unsigned int prefix_bytes; unsigned int pb; u_int32_t prefix; unsigned char *prefix_start; int shift; int n; unsigned int i; // make sure the length we were sent isn't outrageous long if (bgp_len > 1000) { // if (debug) fprintf(stderr,"Outrageous update length: %d\n", bgp_len); bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // but, make sure the length is long enough to contain the minimum update data // bgp header plus 2 bytes for the withdrawn routes length field and 2 bytes for the path attribute length field if (bgp_len < BGP_UPDATE_MIN_SIZE) { // if (debug) fprintf(stderr,"Too small update length: %d\n", bgp_len); bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // alloc memory to hold the bgp update message // if ((buf = (unsigned char *)calloc(1, bgp_len-BGP_SIZE)) == NULL) { // // not good... // if (debug) fprintf(stderr, "Shit...calloc failed\n"); // bgp_send_notification(BGP_NOTIFY_MAJOR_CEASE, BGP_NOTIFY_MINOR_CEASE_ADDOWN); // } // read in the rest of the bgp update message if ((n = read(STDIN_FILENO, buf, bgp_len-BGP_SIZE)) != bgp_len-BGP_SIZE) { // invalid size // if (debug) fprintf(stderr,"Update read failed: %d of %d\n", n, bgp_len); bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // // start parsing the update message // // first get the withdrawn routes length wr_len_p = (u_int16_t *)buf; wr_len = ntohs(*wr_len_p); // make sure the indicated length matches up with the packet length we've received if (bgp_len < BGP_UPDATE_MIN_SIZE + wr_len) { // invalid size // if (debug) fprintf(stderr,"Withdrawn routes length not valid: %d\n", wr_len); bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // next, get the total path attribute length //pa_len_p = (u_int16_t *)(buf+2+*wr_len_p); pa_len_p = (u_int16_t *)(buf+2+wr_len); pa_len = ntohs(*pa_len_p); // make sure the indicated length matches up with the packet length we've received if (bgp_len < BGP_UPDATE_MIN_SIZE + wr_len + pa_len) { // invalid size // if (debug) fprintf(stderr,"bgp_len (%d) != 2 + wr_len (%d) + pa_len (%d)\n", bgp_len, wr_len, pa_len); bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // finally, figure out the NLRI length nlri_len = bgp_len - BGP_UPDATE_MIN_SIZE - wr_len - pa_len; // if (debug) fprintf(stderr,"nlri_len %d\n", nlri_len); // at this point, we know the lengths of the various update message sections // so, start parsing each section // // first, parse the withdrawn routes // i = 0; while (i < wr_len) { // get the length of the prefix in bits // offset from beginning of buf = length of withdrawn routes length field + i // new check that sizeof works like we want here prefix_bits = (u_int8_t *)(buf + sizeof(wr_len_p) + i); // make sure prefix_bits are valid if (*prefix_bits > 32) { bgp_send_notification(BGP_NOTIFY_MAJOR_UPDATE, BGP_NOTIFY_MINOR_UPDATE_BADATTR); return(-1); } // round up to the octet boundry if (*prefix_bits % 8 == 0) { prefix_bytes = (int)(*prefix_bits/8); } else { prefix_bytes = (int)((*prefix_bits/8)+1); } // make sure the prefix length we're told isn't more than the // remaining size of the withdrawn routes field // i + prefix length byte + prefix length if (i+sizeof(prefix_bits)+prefix_bytes > wr_len) { bgp_send_notification(BGP_NOTIFY_MAJOR_MSG, BGP_NOTIFY_MINOR_MSG_LEN); return(-1); } // looks ok, so parse the prefix prefix = 0; shift = 24; prefix_start = (unsigned char *)(buf + sizeof(wr_len_p) + i + sizeof(prefix_bits)); pb = prefix_bytes; while (pb--) { prefix = prefix | ((*prefix_start)<<shift); shift -= 8; prefix_start += 1; } // remove this prefix from our routing table for this client // if (debug) fprintf(stderr,"Removing prefix %08x from routing table\n", prefix); del_route(ntohl(prefix), *prefix_bits); // move on to the next prefix //i += sizeof(prefix_bits)+prefix_bytes; i += 1+prefix_bytes; } // if (debug) fprintf(stderr,"Done parsing withdrawn routes\n"); // // next, parse the path attributes // if (pa_len == 0) { // nothing to do...only withdrawn routes are listed in this update return(0); } return(Parse_Path_Attributes(buf+sizeof(wr_len)+wr_len+sizeof(pa_len), pa_len, nlri_len)); }