Пример #1
0
/* 
 * rule_flush_table_range_filter: rtnl_dump filter for
 * rule_flush_table_range() (see below)
 */
int
rule_flush_table_range_filter(const struct sockaddr_nl *who,
							  struct nlmsghdr *n, void *arg)
{
	struct rtnl_handle rth2;
	struct rtmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[RTA_MAX + 1];
	u_int a = *(u_int *) arg;
	u_int b = *((u_int *) arg + 1);

	len -= NLMSG_LENGTH(sizeof(*r));
	if (len < 0)
		return -1;

	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);

	if (tb[RTA_PRIORITY] && (r->rtm_table >= a && r->rtm_table <= b)) {
		n->nlmsg_type = RTM_DELRULE;
		n->nlmsg_flags = NLM_F_REQUEST;

		if (rtnl_open(&rth2, 0) < 0)
			return -1;

		if (rtnl_talk(&rth2, n, 0, 0, NULL, NULL, NULL) < 0)
			return -2;

		rtnl_close(&rth2);
	}

	return 0;
}
Пример #2
0
static void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) {
    struct rtmsg *rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

    if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
        return;

    struct rtattr *rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
    int rtLen = RTM_PAYLOAD(nlHdr);
    for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
        switch (rtAttr->rta_type) {
            case RTA_OIF:
                if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
                break;
            case RTA_GATEWAY:
                rtInfo->gateWay = *(in_addr *)RTA_DATA(rtAttr);
                break;
            case RTA_PREFSRC:
                rtInfo->srcAddr = *(in_addr *)RTA_DATA(rtAttr);
                break;
            case RTA_DST:
                rtInfo->dstAddr = *(in_addr *)RTA_DATA(rtAttr);
                break;
        }
    }
}
Пример #3
0
bool route_table_mgr::parse_enrty(nlmsghdr *nl_header, route_val *p_val)
{
	int len;
	struct rtmsg *rt_msg;
	struct rtattr *rt_attribute;

	// get route entry header
	rt_msg = (struct rtmsg *) NLMSG_DATA(nl_header);

	// we are not concerned about the local and default route table
	if (rt_msg->rtm_family != AF_INET || rt_msg->rtm_table == RT_TABLE_LOCAL || rt_msg->rtm_table == RT_TABLE_DEFAULT)
		return false;

	p_val->set_protocol(rt_msg->rtm_protocol);
	p_val->set_scope(rt_msg->rtm_scope);
	p_val->set_type(rt_msg->rtm_type);
	p_val->set_table_id(rt_msg->rtm_table);

	in_addr_t dst_mask = htonl(VMA_NETMASK(rt_msg->rtm_dst_len));
	p_val->set_dst_mask(dst_mask);
	p_val->set_dst_pref_len(rt_msg->rtm_dst_len);

	len = RTM_PAYLOAD(nl_header);
	rt_attribute = (struct rtattr *) RTM_RTA(rt_msg);

	for (;RTA_OK(rt_attribute, len);rt_attribute=RTA_NEXT(rt_attribute,len)) {
		parse_attr(rt_attribute, p_val);
	}
	p_val->set_state(true);
	p_val->set_str();
	return true;
}
Пример #4
0
static int resolve_mac_from_cache_parse(struct ndmsg *ndmsg, size_t len_payload,
					struct ether_addr *mac_addr,
					uint8_t *l3addr,
					size_t l3_len)
{
	int l3found, llfound;
	struct rtattr *rtattr;
	struct ether_addr mac_empty;

	l3found = 0;
	llfound = 0;
	memset(&mac_empty, 0, sizeof(mac_empty));

	for (rtattr = RTM_RTA(ndmsg); RTA_OK(rtattr, len_payload);
		rtattr = RTA_NEXT(rtattr, len_payload)) {
		switch (rtattr->rta_type) {
		case NDA_DST:
			memcpy(l3addr, RTA_DATA(rtattr), l3_len);
			l3found = 1;
			break;
		case NDA_LLADDR:
			memcpy(mac_addr, RTA_DATA(rtattr), ETH_ALEN);
			if (memcmp(mac_addr, &mac_empty,
					sizeof(mac_empty)) == 0)
				llfound = 0;
			else
				llfound = 1;
			break;
		}
	}

	return l3found && llfound;
}
Пример #5
0
static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct rtnl_handle rth2;
	struct rtmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[FRA_MAX+1];

	len -= NLMSG_LENGTH(sizeof(*r));
	if (len < 0)
		return -1;

	parse_rtattr(tb, FRA_MAX, RTM_RTA(r), len);

	if (tb[FRA_PRIORITY]) {
		n->nlmsg_type = RTM_DELRULE;
		n->nlmsg_flags = NLM_F_REQUEST;

		if (rtnl_open(&rth2, 0) < 0)
			return -1;

		if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0)
			return -2;

		rtnl_close(&rth2);
	}

	return 0;
}
Пример #6
0
/*
 * Add RTA_SRC or RTA_DST attribute to netlink query message.
 */
void netlink_query_add(char *msgbuf, int rta_type, ip_address *addr)
{
    struct nlmsghdr *nlmsg;
    struct rtmsg *rtmsg;
    struct rtattr *rtattr;
    int len, rtlen;
    void *p;

    nlmsg = (struct nlmsghdr *)msgbuf;
    rtmsg = (struct rtmsg *)NLMSG_DATA(nlmsg);

    /* Find first empty attribute slot */
    rtlen = RTM_PAYLOAD(nlmsg);
    rtattr = (struct rtattr *)RTM_RTA(rtmsg);
    while (RTA_OK(rtattr, rtlen))
	rtattr = RTA_NEXT(rtattr, rtlen);

    /* Add attribute */
    if (rtmsg->rtm_family == AF_INET) {
	len = 4;
	p = (void*)&addr->u.v4.sin_addr.s_addr;
    } else {
	len = 16;
	p = (void*)addr->u.v6.sin6_addr.s6_addr;
    }
    rtattr->rta_type = rta_type;
    rtattr->rta_len = sizeof(struct rtattr) + len; /* bytes */
    memmove(RTA_DATA(rtattr), p, len);
    if (rta_type == RTA_SRC)
	rtmsg->rtm_src_len = len * 8; /* bits */
    else
	rtmsg->rtm_dst_len = len * 8;
    nlmsg->nlmsg_len += rtattr->rta_len;
}
Пример #7
0
static int
getmsg(struct rtmsg *rtm, int msglen, struct rpfctl *rpf)
{
    mifi_t vifi;
    struct uvif *v;
    struct rtattr *rta[RTA_MAX + 1];
    
    if (rtm->rtm_type == RTN_LOCAL) {
	/* tracef(TRF_NETLINK, "NETLINK: local address"); */
	log_msg(LOG_DEBUG, 0, "NETLINK: local address");
	if ((rpf->iif = local_address(&rpf->source)) != MAXMIFS) {
	    rpf->rpfneighbor = rpf->source;
	    return TRUE;
	}
	return FALSE;
    }
    
    memset(&rpf->rpfneighbor, 0, sizeof(rpf->rpfneighbor));   /* initialized */
    if (rtm->rtm_type != RTN_UNICAST) {
	/* tracef(TRF_NETLINK, "NETLINK: route type is %d", rtm->rtm_type); */
	log_msg(LOG_DEBUG, 0, "NETLINK: route type is %d", rtm->rtm_type);
	return FALSE;
    }
    
    memset(rta, 0, sizeof(rta));
    
    parse_rtattr(rta, RTA_MAX, RTM_RTA(rtm), msglen - sizeof(*rtm));
    
    if (rta[RTA_OIF]) {
	int ifindex = *(int *) RTA_DATA(rta[RTA_OIF]);
	
	for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
	    if (v->uv_ifindex == ifindex)
		break;
	}
	if (vifi >= numvifs) {
	    log_msg(LOG_WARNING, 0, "NETLINK: ifindex=%d, but no vif", ifindex);
	    return FALSE;
	}
	/* tracef(TRF_NETLINK, "NETLINK: vif %d, ifindex=%d", vifi, ifindex);*/
	log_msg(LOG_DEBUG, 0, "NETLINK: vif %d, ifindex=%d", vifi, ifindex);
    } else {
	log_msg(LOG_WARNING, 0, "NETLINK: no interface");
	return FALSE;
    }
    if (rta[RTA_GATEWAY]) {
	struct in6_addr gw;
	memcpy(&gw,RTA_DATA(rta[RTA_GATEWAY]),sizeof(gw));
	/* __u32 gw = *(__u32 *) RTA_DATA(rta[RTA_GATEWAY]); */
	/* tracef(TRF_NETLINK, "NETLINK: gateway is %s", inet6_fmt(gw)); */
	log_msg(LOG_DEBUG, 0, "NETLINK: gateway is %s", inet6_fmt(&gw));
	init_sin6(&rpf->rpfneighbor);
	rpf->rpfneighbor.sin6_addr = gw;
	rpf->rpfneighbor.sin6_scope_id = v->uv_ifindex;
    } else
	rpf->rpfneighbor = rpf->source;
    rpf->iif = vifi;
    return TRUE;
}
Пример #8
0
// gw and iface[IF_NAMESIZE] MUST be allocated
int get_default_gw(struct in_addr *gw, char *iface)
{
	struct rtmsg req;
	unsigned int nl_len;
	char buf[8192];
	struct nlmsghdr *nlhdr;

	if (!gw || !iface) {
		return -1;
	}

	// Send RTM_GETROUTE request
	memset(&req, 0, sizeof(req));
	int sock = send_nl_req(RTM_GETROUTE, 0, &req, sizeof(req));

	// Read responses
	nl_len = read_nl_sock(sock, buf, sizeof(buf));
	if (nl_len <= 0) {
		return -1;
	}

	// Parse responses
	nlhdr = (struct nlmsghdr *)buf;
	while (NLMSG_OK(nlhdr, nl_len)) {
		struct rtattr *rt_attr;
		struct rtmsg *rt_msg;
		int rt_len;
		int has_gw = 0;

		rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr);
		
		if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) {
			return -1;
		}
	
		rt_attr = (struct rtattr *) RTM_RTA(rt_msg);
		rt_len = RTM_PAYLOAD(nlhdr);
		while (RTA_OK(rt_attr, rt_len)) {
			switch (rt_attr->rta_type) {
			case RTA_OIF:
				if_indextoname(*(int *) RTA_DATA(rt_attr), iface); 
				break;
			case RTA_GATEWAY:
				gw->s_addr = *(unsigned int *) RTA_DATA(rt_attr); 
				has_gw = 1;
				break;
			}
			rt_attr = RTA_NEXT(rt_attr, rt_len);
		}
	
		if (has_gw) {
			return 0;
		}
		nlhdr = NLMSG_NEXT(nlhdr, nl_len);	
	}
	return -1;
}
Пример #9
0
static int handle_neigh_msg(struct nlmsghdr *nlh, int n)
{
	struct rtattr *tb[NDA_MAX];
	struct ndmsg *ndm = NLMSG_DATA(nlh);

	parse_rt_attrs(tb, NDA_MAX, RTM_RTA(ndm), RTM_PAYLOAD(nlh));
	handle_neigh_attrs(ndm, tb, nlh->nlmsg_type);

	return 0;
}
Пример #10
0
static int handle_route_msg(struct nlmsghdr *nlh, int n)
{
	struct rtmsg *rtm = NLMSG_DATA(nlh);
	struct rtattr *tb[RTN_MAX];

	parse_rt_attrs(tb, RTN_MAX, RTM_RTA(rtm), RTM_PAYLOAD(nlh));
	handle_route_attrs(rtm, tb, nlh->nlmsg_type);

	return 0;
}
Пример #11
0
int read_reply()
{
	//string to hold content of the route
	// table (i.e. one entry)
	char dsts[24], gws[24], ifs[16], ms[24];
	// outer loop: loops thru all the NETLINK
	// headers that also include the route entry
	// header
	nlp = (struct nlmsghdr *) buf;
	for(; NLMSG_OK(nlp, nll); nlp = NLMSG_NEXT(nlp, nll))
	{
		// get route entry header
		rtp = (struct rtmsg *) NLMSG_DATA(nlp);
		// we are only concerned about the
		// main route table
		if(rtp->rtm_table != RT_TABLE_MAIN)
			continue;
		// init all the strings
		bzero(dsts, sizeof(dsts));
		bzero(gws, sizeof(gws));
		bzero(ifs, sizeof(ifs));
		bzero(ms, sizeof(ms));
		// inner loop: loop thru all the attributes of
		// one route entry
		rtap = (struct rtattr *) RTM_RTA(rtp);
		rtl = RTM_PAYLOAD(nlp);
		for( ; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap,rtl))
		{
			switch(rtap->rta_type)
			{
				// destination IPv4 address
				case RTA_DST:
					inet_ntop(AF_INET, RTA_DATA(rtap),
							dsts, 24);
					break;
					// next hop IPv4 address
				case RTA_GATEWAY:
					inet_ntop(AF_INET, RTA_DATA(rtap),
							gws, 24);
					break;
					// unique ID associated with the network
					// interface
				case RTA_OIF:
					sprintf(ifs, "%d",
							*((int *) RTA_DATA(rtap)));
				default:
					break;
			}
		}
		sprintf(ms, "%d", rtp->rtm_dst_len);
		test_msg("dst %s/%s gw %s if %s\n",
				dsts, ms, gws, ifs);
	}
	return 0;
}
Пример #12
0
static void test_route(void) {
        _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
        struct in_addr addr;
        uint32_t index = 2;
        uint16_t type;
        void *data;
        uint32_t u32_data;
        int r;
        struct rtmsg *rtm;

        r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
        if (r < 0) {
                log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
                return;
        }

        addr.s_addr = htonl(INADDR_LOOPBACK);

        r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
        if (r < 0) {
                log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
                return;
        }

        r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
        if (r < 0) {
                log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
                return;
        }

        assert_se(rtnl_message_seal(NULL, req) >= 0);

        assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
        assert_se(type == RTA_GATEWAY);
        assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);

        assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
        assert_se(type == RTA_OIF);
        assert_se(*(uint32_t *) data == index);

        rtm = NLMSG_DATA(req->hdr);
        r = rtnl_message_parse(req,
                               &req->rta_offset_tb,
                               &req->rta_tb_size,
                               RTA_MAX,
                               RTM_RTA(rtm),
                               RTM_PAYLOAD(req->hdr));

        assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0);
        assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0);

        assert_se((req = sd_rtnl_message_unref(req)) == NULL);
}
Пример #13
0
struct ip4_routing_table *parse_nlmsg(struct nlmsghdr *msg) {
	char dst_temp[IP4_ALEN];
	char gw_temp[IP4_ALEN];
	uint32_t priority;
	uint32_t interface;
	struct ip4_routing_table *table_pointer = NULL;

	switch (msg->nlmsg_type) {
	case NLMSG_ERROR: {
		struct nlmsgerr* errorMsg = (struct nlmsgerr*) NLMSG_DATA(msg);
		PRINT_DEBUG("recvd NLMSG_ERROR error seq:%d code:%d...", msg->nlmsg_seq, errorMsg->error);
		break;
	}
	case RTM_NEWROUTE: {
		struct rtmsg* rtm = (struct rtmsg*) NLMSG_DATA(msg);
		struct rtattr* rta = RTM_RTA(rtm);
		int rtaLen = msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
		if (rtm->rtm_type == RTN_UNICAST) // don't consider local, broadcast and unreachable routes
				{
			table_pointer = (struct ip4_routing_table*) secure_malloc(sizeof(struct ip4_routing_table));
			for (; RTA_OK(rta, rtaLen); rta = RTA_NEXT(rta, rtaLen)) {
				switch (rta->rta_type) {
				case RTA_DST: //destination
					table_pointer->mask = rtm->rtm_dst_len;
					memcpy(dst_temp, RTA_DATA(rta), IP4_ALEN);
					//PRINT_DEBUG("received RTA_DST");
					PRINT_DEBUG("dst_str = %u.%u.%u.%u", dst_temp[0] & 0xFF, dst_temp[1] & 0xFF, dst_temp[2] & 0xFF, dst_temp[3] & 0xFF);
					table_pointer->dst = IP4_ADR_P2H(dst_temp[0]&0xFF, dst_temp[1]&0xFF, dst_temp[2]&0xFF, dst_temp[3]&0xFF);
					break;
				case RTA_GATEWAY: //next hop
					table_pointer->mask = rtm->rtm_dst_len;
					memcpy(gw_temp, RTA_DATA(rta), IP4_ALEN);
					//PRINT_DEBUG("received RTA_GATEWAY");
					PRINT_DEBUG("gw_str = %u.%u.%u.%u", gw_temp[0] & 0xFF, gw_temp[1] & 0xFF, gw_temp[2] & 0xFF, gw_temp[3] & 0xFF);
					table_pointer->gw = IP4_ADR_P2H(gw_temp[0]&0xFF, gw_temp[1]&0xFF, gw_temp[2]&0xFF, gw_temp[3]&0xFF);
					break;
				case RTA_OIF: //interface
					memcpy(&table_pointer->interface, RTA_DATA(rta), sizeof(interface)); //TODO won't work with current hack
					PRINT_DEBUG("interface:%u", table_pointer->interface);
					break;
				case RTA_PRIORITY: //metric
					memcpy(&table_pointer->metric, RTA_DATA(rta), sizeof(priority));
					PRINT_DEBUG("metric:%u", table_pointer->metric);
					break;
				} //switch(rta->)
			} // for()
		} // if RTN_UNICAST
		return (table_pointer);
	}
	} //switch (msg->nlmsg_type)
	return (NULL);
}
Пример #14
0
/* For parsing the route info returned */
static int parseRoutes(const char* ifName, struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
    struct rtmsg *rtMsg;
    struct rtattr *rtAttr;
    int rtLen;
    int i_ret = ZQERROR;

    rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);


    /* If the route is not for AF_INET or does not belong to main routing table
        then return. */
    if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
    {
        ///NOTE , free must be called , otherwise memory leak will occur
        goto ExitPoint;
    }

    /* get the rtattr field */
    rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
    rtLen = RTM_PAYLOAD(nlHdr);
    for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen))
    {
        switch(rtAttr->rta_type)
        {
        case RTA_OIF:
            if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
            break;
        case RTA_GATEWAY:
            rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
            break;
        case RTA_PREFSRC:
            rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
            break;
        case RTA_DST:
            rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
            break;
        }
    }
    struct in_addr* p_dstAddr = (struct in_addr*)&rtInfo->dstAddr;
    struct in_addr* p_gateWay = (struct in_addr*)&rtInfo->gateWay;
    if ( !strcmp( ifName, rtInfo->ifName ) &&
            strstr((char *)inet_ntoa(*p_dstAddr), "0.0.0.0"))
    {
        sprintf(gateway, (char *)inet_ntoa(*p_gateWay));
        i_ret = ZQSUCCESS;
    }

ExitPoint:
    return i_ret;
}
Пример #15
0
/* function: get_default_route_cb
 * finds the default route with the request family and out interface and saves the gateway
 * msg  - netlink message
 * data - (struct default_route_data) requested filters and response storage
 */
static int get_default_route_cb(struct nl_msg *msg, void *data) {
  struct rtmsg *rt_p;
  struct rtattr *rta_p;
  int rta_len;
  struct default_route_data *default_route = data;
  union anyip *this_gateway = NULL;
  ssize_t this_gateway_size;
  int this_interface_id = -1;

  if(default_route->reply_found_route) { // we already found our route
    return NL_OK;
  }

  rt_p = (struct rtmsg *)nlmsg_data(nlmsg_hdr(msg));
  if(rt_p->rtm_dst_len != 0) { // not a default route
    return NL_OK;
  }
  if((rt_p->rtm_family != default_route->request_family) || (rt_p->rtm_table != RT_TABLE_MAIN)) { // not a route we care about
    return NL_OK;
  }

  rta_p = (struct rtattr *)RTM_RTA(rt_p);
  rta_len = RTM_PAYLOAD(nlmsg_hdr(msg));
  for(; RTA_OK(rta_p, rta_len); rta_p = RTA_NEXT(rta_p, rta_len)) {
    switch(rta_p->rta_type) {
      case RTA_GATEWAY:
        this_gateway = RTA_DATA(rta_p);
        this_gateway_size = RTA_PAYLOAD(rta_p);
        break;
      case RTA_OIF:
        this_interface_id = *(int *)RTA_DATA(rta_p);
        break;
      default:
        break;
    }
  }

  if(this_interface_id == default_route->request_interface_id) {
    default_route->reply_found_route = 1;
    if(this_gateway != NULL) {
      memcpy(&default_route->reply_gateway, this_gateway, this_gateway_size);
      default_route->reply_has_gateway = 1;
    } else {
      default_route->reply_has_gateway = 0;
    }
  }
  return NL_OK;
}
Пример #16
0
void
parseRoutes (struct nlmsghdr *nlHdr, struct route_info *rtInfo, char *gateway)
{
	struct rtmsg *rtMsg;
	struct rtattr *rtAttr;
	int rtLen;
	char *tempBuf = NULL;
	//2007-12-10
	struct in_addr dst;
	struct in_addr gate;

	tempBuf = (char *)malloc (100);
	rtMsg = (struct rtmsg *)NLMSG_DATA (nlHdr);
	// If the route is not for AF_INET or does not belong to main routing table
	//then return.
	if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) {
		free (tempBuf);
		return;
	}
	/* get the rtattr field */
	rtAttr = (struct rtattr *)RTM_RTA (rtMsg);
	rtLen = RTM_PAYLOAD (nlHdr);
	for (; RTA_OK (rtAttr, rtLen); rtAttr = RTA_NEXT (rtAttr, rtLen)) {
		switch (rtAttr->rta_type) {
		case RTA_OIF:
			if_indextoname (*(int *)RTA_DATA (rtAttr), rtInfo->ifName);
			break;
		case RTA_GATEWAY:
			rtInfo->gateWay = *(u_int *) RTA_DATA (rtAttr);
			break;
		case RTA_PREFSRC:
			rtInfo->srcAddr = *(u_int *) RTA_DATA (rtAttr);
			break;
		case RTA_DST:
			rtInfo->dstAddr = *(u_int *) RTA_DATA (rtAttr);
			break;
		}
	}
	//2007-12-10
	dst.s_addr = rtInfo->dstAddr;   /*lint  !e632*/
	if (strstr ((char *)inet_ntoa (dst), "0.0.0.0")) {
		gate.s_addr = rtInfo->gateWay;  /*lint  !e632*/
		sprintf (gateway, (char *)inet_ntoa (gate));
	}
	free (tempBuf);
	return;
}
Пример #17
0
/**
 * Extract each route table entry and print
 */
static void netlink_parse_routes(struct rtmon_t *rtmon, char *b, int blen) {
  struct nlmsghdr *hdr = (struct nlmsghdr *) b;
  struct rtattr * attr;
  struct rtmon_route rt;
  int payload;

  for(; NLMSG_OK(hdr, blen); hdr = NLMSG_NEXT(hdr, blen)) {
    struct rtmsg * rtm = (struct rtmsg *) NLMSG_DATA(hdr);

    if (rtm->rtm_table != RT_TABLE_MAIN)
      continue;

    attr = (struct rtattr *) RTM_RTA(rtm);
    payload = RTM_PAYLOAD(hdr);

    memset(&rt, 0, sizeof(rt));

    for (;RTA_OK(attr, payload); attr = RTA_NEXT(attr, payload)) {
      switch(attr->rta_type) {
        case RTA_DST:
          rt.destination = *(struct in_addr *)RTA_DATA(attr);
          break;
        case RTA_GATEWAY:
          rt.gateway = *(struct in_addr *)RTA_DATA(attr);
          break;
        case RTA_OIF:
          rt.if_index = *((int *) RTA_DATA(attr));
        default:
          break;
      }
    }

    {
      uint32_t mask = 0;
      int i;

      for (i=0; i<rtm->rtm_dst_len; i++) {
	mask |= (1 << (32-i-1));
      }

      rt.netmask.s_addr = htonl(mask);
    }

    rtmon_add_route(rtmon, &rt);
  }
}
Пример #18
0
/*
 * parse_route_msg
 */
int
parse_route_msg (netlink_msg_ctx_t *ctx)
{
  int len;
  struct rtattr **rtattrs, *rtattr, *gateway, *oif;
  int if_index;

  ctx->rtmsg = NLMSG_DATA(ctx->hdr);

  len = ctx->hdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
  if (len < 0) {
    netlink_msg_ctx_set_err(ctx, "Bad message length");    
    return 0;
  }

  if (!parse_rtattrs(ctx, RTM_RTA(ctx->rtmsg), len)) {
    return 0;
  }

  rtattrs = ctx->rtattrs;

  ctx->dest = rtattrs[RTA_DST];
  ctx->src = rtattrs[RTA_PREFSRC];

  rtattr = rtattrs[RTA_PRIORITY];
  if (rtattr) {
    ctx->metric = (int *) RTA_DATA(rtattr);
  }

  gateway = rtattrs[RTA_GATEWAY];
  oif = rtattrs[RTA_OIF];
  if (gateway || oif) {
    if_index = 0;
    if (oif) {
      if_index = *((int *) RTA_DATA(oif));
    }
    netlink_msg_ctx_add_nh(ctx, if_index, gateway);
  }

  rtattr = rtattrs[RTA_MULTIPATH];
  if (rtattr) {
    parse_multipath_attr(ctx, rtattr);
  }

  return 1;
}
Пример #19
0
static void nl_route(struct nlmsghdr *nlmsg)
{
	struct rtmsg *r;
	struct rtattr *a;
	int la;
	int gw = 0, dst = 0, mask = 0, idx = 0;

	if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
		_e("Packet too small or truncated!");
		return;
	}

	r  = NLMSG_DATA(nlmsg);
	a  = RTM_RTA(r);
	la = RTM_PAYLOAD(nlmsg);
	while (RTA_OK(a, la)) {
		void *data = RTA_DATA(a);
		switch (a->rta_type) {
		case RTA_GATEWAY:
			gw = *((int *)data);
			//_d("GW: 0x%04x", gw);
			break;

		case RTA_DST:
			dst = *((int *)data);
			mask = r->rtm_dst_len;
			//_d("MASK: 0x%04x", mask);
			break;

		case RTA_OIF:
			idx = *((int *)data);
			//_d("IDX: 0x%04x", idx);
			break;
		}

		a = RTA_NEXT(a, la);
	}

	if ((!dst && !mask) && (gw || idx)) {
		if (nlmsg->nlmsg_type == RTM_DELROUTE)
			cond_clear("net/route/default");
		else
			cond_set("net/route/default");
	}
}
Пример #20
0
/* For parsing the route info returned */
void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo,char *gateway)
{
	 struct rtmsg *rtMsg;
	  struct rtattr *rtAttr;
	   int rtLen;
	    char *tempBuf = NULL;

		 tempBuf = (char *)malloc(100);
		  rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

		   /* If the route is not for AF_INET or does not belong to main routing table
			   then return. */
		   if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
			    return;

		    /* get the rtattr field */
		    rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
			 rtLen = RTM_PAYLOAD(nlHdr);
			  for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)){
				    switch(rtAttr->rta_type) {
						  case RTA_OIF:
							     if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
								    break;
									  case RTA_GATEWAY:
									   rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
									      break;
										    case RTA_PREFSRC:
										     rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
											    break;
												  case RTA_DST:
												   rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
												      break;
													    }
					 }
			   //printf("%s\n", (char *)inet_ntoa(rtInfo->dstAddr));

			   // ADDED BY BOB - ALSO COMMENTED printRoute

			   if (strstr((char *)inet_ntoa(rtInfo->dstAddr), "0.0.0.0"))
				     sprintf(gateway, (char *)inet_ntoa(rtInfo->gateWay));
			     printRoute(rtInfo);

			    free(tempBuf);
				 return;
}
Пример #21
0
bool route_table_mgr::rt_mgr_parse_enrty(nlmsghdr *nl_header, route_val *p_rtv)
{
	int len;
	struct rtmsg *rt_msg;
	struct rtattr *rt_attribute;

	// get route entry header
	rt_msg = (struct rtmsg *) NLMSG_DATA(nl_header);

	// we are only concerned about the main route table
	if (rt_msg->rtm_family != AF_INET || rt_msg->rtm_table != RT_TABLE_MAIN)
		return false;

	p_rtv->set_protocol(rt_msg->rtm_protocol);
	p_rtv->set_scope(rt_msg->rtm_scope);
	p_rtv->set_type(rt_msg->rtm_type);

	in_addr_t dst_mask = htonl(VMA_NETMASK(rt_msg->rtm_dst_len));
	p_rtv->set_dst_mask(dst_mask);
	p_rtv->set_dst_pref_len(rt_msg->rtm_dst_len);

	len = RTM_PAYLOAD(nl_header);
	rt_attribute = (struct rtattr *) RTM_RTA(rt_msg);

	for (;RTA_OK(rt_attribute, len);rt_attribute=RTA_NEXT(rt_attribute,len)) {
		rt_mgr_parse_attr(rt_attribute, p_rtv);
	}
	p_rtv->set_state(true);

	if (!p_rtv->get_src_addr()) {
		struct sockaddr_in src_addr;
		char *if_name = (char *)p_rtv->get_if_name();
		if (!get_ipv4_from_ifname(if_name, &src_addr)) {
			p_rtv->set_src_addr(src_addr.sin_addr.s_addr);
		}
		else {
			// Failed mapping if_name to IPv4 address
			// Should we log or return error also from here?
		}
	}

	p_rtv->set_str();
	return true;
}
Пример #22
0
/* For parsing the route info returned */
void route_parse(struct nlmsghdr *nl_msg, struct route_info *rt_info)
{
	struct rtmsg *rt_msg;
	struct rtattr *rt_attr;
	int rt_len = 0;
	
	rt_msg = (struct rtmsg *) NLMSG_DATA(nl_msg);
	
	/* If the route is not for AF_INET or does not belong to main routing table then return. */
	if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) {
		return;
	}
	
	/* get the rtattr field */
	rt_attr = (struct rtattr *) RTM_RTA(rt_msg);
	rt_len = RTM_PAYLOAD(nl_msg);
	for (  ; RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr, rt_len)) {
		switch (rt_attr->rta_type) {
			case RTA_OIF:
				if_indextoname(*(int *) RTA_DATA(rt_attr), rt_info->if_name);
				break;
			case RTA_GATEWAY:
				rt_info->gateway.s_addr= *(u_int *) RTA_DATA(rt_attr);
				break;
			case RTA_PREFSRC:
				rt_info->src_addr.s_addr= *(u_int *) RTA_DATA(rt_attr);
				break;
			case RTA_DST:
				rt_info->dst_addr .s_addr= *(u_int *) RTA_DATA(rt_attr);
				break;
		}
	}
	
	//printf("%s\n", inet_ntoa(rt_info->dst_addr));
	
	if (rt_info->dst_addr.s_addr == 0) {
		sprintf(gateway, "%s", (char *) inet_ntoa(rt_info->gateway));
	}
	
	route_print(rt_info);
	
	return;
}
Пример #23
0
static int
link_neigh(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
    struct nlmsghdr *nlm)
{
	struct ndmsg *r;
	struct rtattr *rta;
	size_t len;
	struct in6_addr addr6;
	int flags;

	if (nlm->nlmsg_type != RTM_NEWNEIGH && nlm->nlmsg_type != RTM_DELNEIGH)
		return 0;
	if (nlm->nlmsg_len < sizeof(*r))
		return -1;

	r = NLMSG_DATA(nlm);
	rta = (struct rtattr *)RTM_RTA(r);
	len = RTM_PAYLOAD(nlm);
        if (r->ndm_family == AF_INET6) {
		flags = 0;
		if (r->ndm_flags & NTF_ROUTER)
			flags |= IPV6ND_ROUTER;
		if (nlm->nlmsg_type == RTM_NEWNEIGH &&
		    r->ndm_state &
		    (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE |
		     NUD_PERMANENT))
		        flags |= IPV6ND_REACHABLE;
		memset(&addr6, 0, sizeof(addr6));
		while (RTA_OK(rta, len)) {
			switch (rta->rta_type) {
			case NDA_DST:
				memcpy(&addr6.s6_addr, RTA_DATA(rta),
				       sizeof(addr6.s6_addr));
				break;
			}
			rta = RTA_NEXT(rta, len);
		}
		ipv6nd_neighbour(ctx, &addr6, flags);
	}

	return 0;
}
Пример #24
0
/**
 * Handle a netlink message. If this message is a routing table message and it
 * contains the default route, then either:
 *   i) default_gateway is updated with the address of the gateway.
 *   ii) if_index is updated with the interface index for the default route.
 * @param if_index[out] possibly updated with interface index for the default
 *   route.
 * @param default_gateway[out] possibly updated with the default gateway.
 * @param nl_hdr the netlink message.
 */
void MessageHandler(int32_t *if_index,
                    IPV4Address *default_gateway,
                    const struct nlmsghdr *nl_hdr) {
  // Unless RTA_DST is provided, an RTA_GATEWAY or RTA_OIF attribute implies
  // it's the default route.
  IPV4Address gateway;
  int32_t index = Interface::DEFAULT_INDEX;

  bool is_default_route = true;

  // Loop over the attributes looking for RTA_GATEWAY and/or RTA_DST
  const rtmsg *rt_msg = reinterpret_cast<const rtmsg*>(NLMSG_DATA(nl_hdr));
  if (rt_msg->rtm_family == AF_INET && rt_msg->rtm_table == RT_TABLE_MAIN) {
    int rt_len = RTM_PAYLOAD(nl_hdr);

    for (const rtattr* rt_attr = reinterpret_cast<const rtattr*>(
            RTM_RTA(rt_msg));
         RTA_OK(rt_attr, rt_len);
         rt_attr = RTA_NEXT(rt_attr, rt_len)) {
      switch (rt_attr->rta_type) {
        case RTA_OIF:
          index = *(reinterpret_cast<int32_t*>(RTA_DATA(rt_attr)));
          break;
        case RTA_GATEWAY:
          gateway = IPV4Address(
              reinterpret_cast<const in_addr*>(RTA_DATA(rt_attr))->s_addr);
          break;
        case RTA_DST:
          IPV4Address dest(
              reinterpret_cast<const in_addr*>(RTA_DATA(rt_attr))->s_addr);
          is_default_route = dest.IsWildcard();
          break;
      }
    }
  }

  if (is_default_route &&
      (!gateway.IsWildcard() || index != Interface::DEFAULT_INDEX)) {
    *default_gateway = gateway;
    *if_index = index;
  }
}
Пример #25
0
void linux_unicast_router::handle_route_event(bool isnew, nlmsghdr *hdr) {
    rtattr *tb[RTA_MAX + 1];
    memset(tb, 0, sizeof(tb));

    netlink_msg *msg = (netlink_msg *)hdr;

    if (msg->r.rtm_family != AF_INET6 || (msg->r.rtm_flags & RTM_F_CLONED) == RTM_F_CLONED) {
        return;
    }

    netlink_msg::parse_rtatable(tb, RTA_MAX, RTM_RTA(NLMSG_DATA(hdr)),
                                hdr->nlmsg_len - NLMSG_LENGTH(sizeof(rtmsg)));

    if (tb[RTA_DST]) {
        lookup_result res;

        parse_prefix_rec(tb, msg->r.rtm_dst_len,
                         msg->r.rtm_protocol, res);

        if (g_mrd->should_log(MESSAGE_SIG)) {
            g_mrd->log().xprintf(
                "(NETLINK) route event: %s route for "
                "%{Addr} with dev %i gw %{addr} prefsrc "
                "%{addr}\n", isnew ? "new" : "lost",
                res.dst, res.dev, res.nexthop, res.source);
        }

        if (res.protocol == RTPROT_UNSPEC || res.protocol == RTPROT_REDIRECT)
            return;

        if (filter_protos.find(res.protocol) != filter_protos.end()) {
            if (g_mrd->should_log(INTERNAL_FLOW))
                g_mrd->log().xprintf("(LINUX) Filtered %s route for "
                                     "%{Addr} with dev %i gw %{addr} prefsrc "
                                     "%{addr} by policy.\n", isnew ? "new" : "lost",
                                     res.dst, res.dev, res.nexthop, res.source);
        }

        prefix_changed(isnew, res);
    }
}
Пример #26
0
/* For parsing the route info returned */
static int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
    struct rtmsg *rtMsg;
    struct rtattr *rtAttr;
    int rtLen = 0;

    rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr);

    /* This must be an IPv4 (AF_INET) route */
    if (rtMsg->rtm_family != AF_INET)
        return 1;

    /* This must be in main routing table */
    if (rtMsg->rtm_table != RT_TABLE_MAIN)
        return 1;

    /* Attributes field*/
    rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
    rtLen = RTM_PAYLOAD(nlHdr);
    for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
        switch (rtAttr->rta_type) {
        case RTA_OIF:
            if_indextoname(*(int *) RTA_DATA(rtAttr), rtInfo->ifName);
            break;
        case RTA_GATEWAY:
            rtInfo->gateWay.s_addr = *(u_int *)RTA_DATA(rtAttr);
            break;
        case RTA_PREFSRC:
            rtInfo->srcAddr.s_addr = *(u_int *)RTA_DATA(rtAttr);
            break;
        case RTA_DST:
            rtInfo->dstAddr .s_addr = *(u_int *)RTA_DATA(rtAttr);
            break;
        }
    }

    return 0;
}
Пример #27
0
void
notify(const struct sockaddr_nl *nlp, struct nlmsghdr *nlmsgp)
{
    int len;
    int host_len;
    unsigned char cmd;
    struct in_addr any;
    struct iovec iov[NUM_RESP];
    struct rtmsg *rtmp;
    struct rtattr *attrs[RTA_MAX + 1];

    switch (nlmsgp->nlmsg_type) {
    case RTM_NEWROUTE:
        cmd = RTM_CMD_ROUTE_ADD;
        break;
    case RTM_DELROUTE:
        cmd = RTM_CMD_ROUTE_DEL;
        break;
    default:
        error_reply("not a route");
        return;
    }

    len = nlmsgp->nlmsg_len - NLMSG_LENGTH(sizeof(*nlmsgp));
    if (len < 0) {
        error_reply("wrong message length");
        return;
    }

    rtmp = NLMSG_DATA(nlmsgp);

    /* Don't notify routes added by ourselves. */
    if (rtmp->rtm_protocol == RTPROT_ROUTEMACHINE)
        return;

    if (rtmp->rtm_table != RT_TABLE_MAIN)
        return;

    switch (rtmp->rtm_family) {
    case AF_INET:
        host_len = 4;
        break;
    case AF_INET6:
        host_len = 16;
        break;
    default:
        error_reply("bad message family");
        return;
    }

    parse_attrs(attrs, RTM_RTA(rtmp), len);

    iov[CMD].iov_base = &cmd;
    iov[CMD].iov_len  = 1;

    iov[MASK].iov_base = &rtmp->rtm_dst_len;
    iov[MASK].iov_len  = 1;

    any.s_addr = INADDR_ANY;

    if (attrs[RTA_DST] != NULL) {
        iov[DST].iov_base = RTA_DATA(attrs[RTA_DST]);
        iov[DST].iov_len  = (rtmp->rtm_dst_len + 7)/8;
    } else {
        iov[DST].iov_base = &any;
        iov[DST].iov_len  = sizeof(any);
    }

    if (attrs[RTA_GATEWAY] != NULL) {
        iov[GW].iov_base = RTA_DATA(attrs[RTA_GATEWAY]);
        iov[GW].iov_len  = host_len;
    } else {
        iov[GW].iov_base = &any;
        iov[GW].iov_len  = sizeof(any);
    }

    if (attrs[RTA_PRIORITY] != NULL) {
        uint32_t prio = htonl(*(uint32_t *)RTA_DATA(attrs[RTA_PRIORITY]));
        iov[PRIO].iov_base = &prio;
        iov[PRIO].iov_len = 4;
    } else {
        uint32_t prio = htonl(0);
        iov[PRIO].iov_base = &prio;
        iov[PRIO].iov_len = 4;
    }

    writev(STDOUT_FILENO, iov, NUM_RESP);
}
Пример #28
0
static int parse_v4_route(
        orc_options_t * options,
        struct nlmsghdr * nl_msg,
        orc_v4_route_t * entry)
{
    struct rtmsg * rt_msg;
    struct rtattr * attr;
    int rtattr_len;
    int found_dst = 0;
    int found_dst_if = 0;


    rt_msg = (struct rtmsg *) NLMSG_DATA(nl_msg);
    /* extract the first attribute */
    attr = (struct rtattr *) RTM_RTA(rt_msg);
    rtattr_len = RTM_PAYLOAD(nl_msg);

    if (rt_msg->rtm_family == AF_INET6)
    {
        /* TODO: add IPv6 support */
        orc_debug("Ignoring IPv6 route update: IPv6 unsupported\n");
        return 0;
    }

    /** FIXME: figure out if we should qualify on
     * rt_msg -> rtm_table == RT_TABLE_DEFAULT _or_
     * rt_msg -> rtm_protocol == ???  _or_
     * rt_msg -> rtm_scope == ???
     */


    /** ignore BROADCAST, LOCAL, ANYCAST, MULTICAST routes updates;
     * for now, just accept unicast routes
     */
    if ( rt_msg -> rtm_type != RTN_UNICAST)
        return 0;

    orc_debug("Parsed IPv4 route Update: \n"
            "       rtm_family      = 0x%x\n"
            "       rtm_dst_len     = %d\n"
            "       rtm_src_len     = %d\n"
            "       rtm_tos         = 0x%x\n"
            "       rtm_table       = 0x%x\n"
            "       rtm_protocol    = 0x%x\n"
            "       rtm_scope       = 0x%x\n"
            "       rtm_type        = 0x%x\n"
            "       rtm_flags       = 0x%x\n",
            rt_msg -> rtm_family,
            rt_msg -> rtm_dst_len,
            rt_msg -> rtm_src_len,
            rt_msg -> rtm_tos,
            rt_msg -> rtm_table,
            rt_msg -> rtm_protocol,
            rt_msg -> rtm_scope,
            rt_msg -> rtm_type,
            rt_msg -> rtm_flags);

    bzero(entry, sizeof(*entry));
    /* get the dest mask from main msg */
    entry->dst_mask_len = rt_msg->rtm_dst_len;
    entry->src_mask_len = rt_msg->rtm_src_len;

    /** note: the RTA_NEXT() macro decrements rtattr_len each time */
    for(; RTA_OK(attr, rtattr_len); attr = RTA_NEXT(attr, rtattr_len))
    {
        switch (attr->rta_type)
        {
            case RTA_DST:
                memcpy( &entry->dst_ip, RTA_DATA(attr), sizeof(entry->dst_ip));
                found_dst = 1;
                orc_debug("Parsed IPv4 route dst: " IPV4_FORMAT "/%d\n",
                        IPV4_ADDR_PRINT(entry->dst_ip), entry->dst_mask_len);
                break;
            case RTA_SRC:
                memcpy( &entry->src_ip, RTA_DATA(attr), sizeof(entry->src_ip));
                entry->src_route_valid = 1; /* FIXME: check RTA_IIF as well */
                orc_debug("Parsed IPv4 route src: " IPV4_FORMAT "/%d\n",
                        IPV4_ADDR_PRINT(entry->src_ip), entry->src_mask_len);
                break;
            case RTA_IIF:
                memcpy( &entry->src_if_index, RTA_DATA(attr),
                        sizeof(entry->src_if_index));
                orc_debug("Parsed IPv4 route IIF index: %d\n",
                        entry->src_if_index);
                break;
            case RTA_OIF:
                memcpy( &entry->dst_if_index, RTA_DATA(attr),
                        sizeof(entry->dst_if_index));
                found_dst_if = 1;
                orc_debug("Parsed IPv4 route OIF index: %d\n",
                        entry->dst_if_index);
                break;
            case RTA_GATEWAY:
                memcpy( &entry->gateway, RTA_DATA(attr),
                        sizeof(entry->gateway));
                entry->gateway_valid = 1;
                orc_debug("Parsed IPv4 route gateway: " IPV4_FORMAT "\n",
                    IPV4_ADDR_PRINT(entry->gateway));
                break;
            case RTA_PREFSRC:
                orc_trace("Skipping unhandled RTA_PREFSRC route attr\n");
                break;
            case RTA_TABLE:
                orc_trace("Skipping unhandled RTA_TABLE route attr\n");
                break;
            default:
            /** TODO: decide if we actually need anything else from here */
                orc_warn("Skipping unhandled ipv4 route attr: %d\n",
                        attr->rta_type);
        }
    }
    if (found_dst && found_dst_if)
        entry->dst_route_valid = 1;

    return entry->dst_route_valid;
}
Пример #29
0
/* Our rt netlink filter */
int rt_filter(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct rt_entry *rtarg;
	struct rtmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[RTA_MAX+1];
	struct rt_entry *entry;

	rtarg = (struct rt_entry *)arg;

	/* Just lookup the Main routing table */
	if (r->rtm_table != RT_TABLE_MAIN)
		return 0;

	/* init len value  */
	len -= NLMSG_LENGTH(sizeof(*r));
	if (len <0) {
		printf("BUG: wrong nlmsg len %d\n", len);
		return -1;
	}

	/* init the parse attribute space */
	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);

	/*
	 * we return from filter when route is
	 * cloned from another route, learn by an
	 * ICMP redirect or set by kernel.
	 * Return too when rt type != gateway or direct route.
	 */
	if (r->rtm_flags & RTM_F_CLONED)
		return 0;
	if (r->rtm_protocol == RTPROT_REDIRECT)
		return 0;
	if (r->rtm_protocol == RTPROT_KERNEL)
		return 0;
	if (r->rtm_type != RTN_UNICAST)
		return 0;

	if (tb[RTA_OIF]) {
		/* alloc new memory entry */
		entry = rt_new();

		/* copy the rtmsg infos */
		memcpy(entry->rtm, r, sizeof(struct rtmsg));

		/*
		 * can use RTA_PAYLOAD(tb[RTA_SRC])
		 * but ipv4 addr are 4 bytes coded
		 */
		entry->oif = *(int *) RTA_DATA(tb[RTA_OIF]);
		if (tb[RTA_SRC]) memcpy(&entry->src, RTA_DATA(tb[RTA_SRC]), 4);
		if (tb[RTA_PREFSRC]) memcpy(&entry->psrc, RTA_DATA(tb[RTA_PREFSRC]), 4);
		if (tb[RTA_DST]) memcpy(&entry->dest, RTA_DATA(tb[RTA_DST]), 4);
		if (tb[RTA_GATEWAY]) memcpy(&entry->gate, RTA_DATA(tb[RTA_GATEWAY]), 4);
		if (tb[RTA_FLOW]) memcpy(&entry->flow, RTA_DATA(tb[RTA_FLOW]), 4);
		if (tb[RTA_IIF]) entry->iif = *(int *) RTA_DATA(tb[RTA_IIF]);
		if (tb[RTA_PRIORITY]) entry->prio = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
		if (tb[RTA_METRICS]) entry->metrics = *(int *) RTA_DATA(tb[RTA_METRICS]);

		/* save this entry */
		rtarg = rt_append(rtarg, entry);
	}


	return 0;
}
Пример #30
-1
static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct rtnl_handle rth2;
	struct rtmsg *r = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr * tb[IFAL_MAX+1];

	len -= NLMSG_LENGTH(sizeof(*r));
	if (len < 0)
		return -1;

	parse_rtattr(tb, IFAL_MAX, RTM_RTA(r), len);

	if (tb[IFAL_ADDRESS]) {
		n->nlmsg_type = RTM_DELADDRLABEL;
		n->nlmsg_flags = NLM_F_REQUEST;

		if (rtnl_open(&rth2, 0) < 0)
			return -1;

		if (rtnl_talk(&rth2, n, NULL, 0) < 0)
			return -2;

		rtnl_close(&rth2);
	}

	return 0;
}