void route_table_mgr::rt_mgr_build_request(rt_req_type_t type, rt_req_info_t *req_info, struct nlmsghdr **nl_msg) { struct rtmsg *rt_msg; memset(m_msg_buf, 0, m_buff_size); // point the header and the msg structure pointers into the buffer *nl_msg = (struct nlmsghdr *)m_msg_buf; rt_msg = (struct rtmsg *)NLMSG_DATA(*nl_msg); //Fill in the nlmsg header (*nl_msg)->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); (*nl_msg)->nlmsg_seq = m_seq_num++; (*nl_msg)->nlmsg_pid = m_pid; rt_msg->rtm_family = AF_INET; switch (type) { case RT_TYPE_GET_RT: (*nl_msg)->nlmsg_type = RTM_GETROUTE; (*nl_msg)->nlmsg_flags = NLM_F_REQUEST; if (req_info->dst.s_addr && req_info->dst_pref_len) { rt_mgr_add_attr(*nl_msg, m_buff_size, RTA_DST, &req_info->dst, req_info->dst_pref_len); } if (req_info->src.s_addr && req_info->src_pref_len) { rt_mgr_add_attr(*nl_msg, m_buff_size, RTA_SRC, &req_info->src, req_info->src_pref_len); } break; case RT_TYPE_DUMP_RT: (*nl_msg)->nlmsg_type = RTM_GETROUTE; (*nl_msg)->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; break; BULLSEYE_EXCLUDE_BLOCK_START default: rt_mgr_logwarn("Unknown netlink route request type."); break; BULLSEYE_EXCLUDE_BLOCK_END } }
void route_table_mgr::rt_mgr_update_source_ip() { route_val *p_val; //for route entries which still have no src ip and no gw for (int i = 0; i < m_tab.entries_num; i++) { p_val = &m_tab.value[i]; if (p_val->get_src_addr() || p_val->get_gw_addr()) continue; if (g_p_net_device_table_mgr) { //try to get src ip from net_dev list of the interface in_addr_t longest_prefix = 0; in_addr_t correct_src = 0; net_dev_lst_t* nd_lst = g_p_net_device_table_mgr->get_net_device_val_lst_from_index(p_val->get_if_index()); if (nd_lst) { net_dev_lst_t::iterator iter = nd_lst->begin(); while (iter != nd_lst->end()) { if((p_val->get_dst_addr() & (*iter)->get_netmask()) == ((*iter)->get_local_addr() & (*iter)->get_netmask())) { //found a match in routing table if(((*iter)->get_netmask() | longest_prefix) != longest_prefix){ longest_prefix = (*iter)->get_netmask(); // this is the longest prefix match correct_src = (*iter)->get_local_addr(); } } iter++; } if (correct_src) { p_val->set_src_addr(correct_src); continue; } } } // if still no src ip, get it from ioctl struct sockaddr_in src_addr; char *if_name = (char *)p_val->get_if_name(); if (!get_ipv4_from_ifname(if_name, &src_addr)) { p_val->set_src_addr(src_addr.sin_addr.s_addr); } else { // Failed mapping if_name to IPv4 address rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str()); } } //for route entries with gateway, do recursive search for src ip int num_unresolved_src = m_tab.entries_num; int prev_num_unresolved_src = 0; do { prev_num_unresolved_src = num_unresolved_src; num_unresolved_src = 0; for (int i = 0; i < m_tab.entries_num; i++) { p_val = &m_tab.value[i]; if (p_val->get_gw_addr() && !p_val->get_src_addr()) { route_val* p_val_dst; in_addr_t in_addr = p_val->get_gw_addr(); unsigned char table_id = p_val->get_table_id(); if (find_route_val(in_addr, table_id, p_val_dst)) { if (p_val_dst->get_src_addr()) { p_val->set_src_addr(p_val_dst->get_src_addr()); } else if (p_val == p_val_dst) { //gateway of the entry lead to same entry net_dev_lst_t* nd_lst = g_p_net_device_table_mgr->get_net_device_val_lst_from_index(p_val->get_if_index()); if (nd_lst) { net_dev_lst_t::iterator iter = nd_lst->begin(); while (iter != nd_lst->end()) { if(p_val->get_gw_addr() == (*iter)->get_local_addr()) { p_val->set_gw(0); p_val->set_src_addr((*iter)->get_local_addr()); break; } iter++; } } if (!p_val->get_src_addr()) num_unresolved_src++; } else { num_unresolved_src++; } // gateway and source are equal, no need of gw. if (p_val->get_src_addr() == p_val->get_gw_addr()) { p_val->set_gw(0); } } else { num_unresolved_src++; } } } } while (num_unresolved_src && prev_num_unresolved_src > num_unresolved_src); //for route entries which still have no src ip for (int i = 0; i < m_tab.entries_num; i++) { p_val = &m_tab.value[i]; if (p_val->get_src_addr()) continue; if (p_val->get_gw_addr()) { rt_mgr_logdbg("could not figure out source ip for gw address. rtv = %s", p_val->to_str()); } // if still no src ip, get it from ioctl struct sockaddr_in src_addr; char *if_name = (char *)p_val->get_if_name(); if (!get_ipv4_from_ifname(if_name, &src_addr)) { p_val->set_src_addr(src_addr.sin_addr.s_addr); } else { // Failed mapping if_name to IPv4 address rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str()); } } }