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
	}
}
Beispiel #2
0
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());
		}
	}
}