Пример #1
0
static void nl_parse_addr_msg(struct nlmsghdr *nlp, struct nl_cb *cb)
{
	struct ifaddrmsg *ifaddr;
	struct rtattr *rtap;
	nl_addr_cb addr_cb;
	size_t len;
	in_addr_t *addr;
	struct nl_addr nl_addr;

	addr = NULL;
	ifaddr = NLMSG_DATA(nlp);
	rtap = IFLA_RTA(ifaddr);
	len = IFLA_PAYLOAD(nlp);

	for (; RTA_OK(rtap, len); rtap = RTA_NEXT(rtap, len)) {
		switch (rtap->rta_type) {
		case IFA_LOCAL:
			addr = (in_addr_t*)RTA_DATA(rtap);
			break;
		default:
			break;
		}
	}

	if (!addr) {
		XLOG_ERR("could not get addr for link %u", ifaddr->ifa_index);
		return;
	}

	addr_cb = (nl_addr_cb) cb->parse_cb;
	nl_addr.ifindex = ifaddr->ifa_index;
	nl_addr.ifaddr = *addr;
	addr_cb(&nl_addr , cb->aux);
}
Пример #2
0
void linux_unicast_router::handle_intf_event(bool isnew, nlmsghdr *hdr) {
    ifinfomsg *ifi = (ifinfomsg *)NLMSG_DATA(hdr);

    if (isnew) {
        rtattr *tb[IFLA_MAX + 1];
        memset(tb, 0, sizeof(tb));

        netlink_msg::parse_rtatable(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(hdr));

        if (tb[IFLA_IFNAME] && tb[IFLA_MTU]) {
            interface_desc desc;

            desc.index = ifi->ifi_index;
            desc.name = (const char *)RTA_DATA(tb[IFLA_IFNAME]);
            desc.mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
            desc.flags = ifi->ifi_flags;
            desc.type = _conv_intf(ifi->ifi_type, ifi->ifi_flags);
            desc.up = ((ifi->ifi_flags & IFF_UP) == IFF_UP);

            if (rt_dumping) {
                _interfaces.push_back(desc);
            } else {
                _install_interface(desc);
            }
        }
    } else {
        g_mrd->lost_interface(ifi->ifi_index);
    }
}
Пример #3
0
static void test_container(void) {
        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
        uint16_t type;
        uint32_t u32_data;
        void *data;
        int r;
        struct ifinfomsg *ifi;

        assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);

        assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
        assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
        assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
        assert_se(sd_rtnl_message_close_container(m) >= 0);
        assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
        assert_se(sd_rtnl_message_close_container(m) >= 0);
        assert_se(sd_rtnl_message_close_container(m) == -EINVAL);

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

        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_LINKINFO);
        assert_se(data == NULL);
/*
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_KIND);
        assert_se(streq("kind", (char *)data));
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_DATA);
        assert_se(data == NULL);
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_VLAN_ID);
        assert_se(*(uint16_t *)data == 100);
        assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
        assert_se(sd_rtnl_message_exit_container(m) >= 0);
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_KIND);
        assert_se(streq("kind", (char *)data));
        assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
        assert_se(sd_rtnl_message_exit_container(m) >= 0);
*/

        ifi = NLMSG_DATA(m->hdr);
        r = rtnl_message_parse(m,
                               &m->rta_offset_tb,
                               &m->rta_tb_size,
                               IFLA_MAX,
                               IFLA_RTA(ifi),
                               IFLA_PAYLOAD(m->hdr));
        if(r < 0)
                return;

        assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);

        assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
}
Пример #4
0
int if_info_save_interface(struct nlmsghdr *hdr, void *arg)
{
    struct rtattr *attrs[IFLA_MAX + 1];
    struct ifinfomsg *info = NLMSG_DATA(hdr);

    parse_rtattrs(attrs, IFLA_MAX, IFLA_RTA(info), IFLA_PAYLOAD(hdr));

    return if_info_update_interface(hdr, attrs) ? 0 : -1;
}
Пример #5
0
static void ril_mtu_watch_handle_nlmsg(struct ril_mtu_watch *self,
					const struct nlmsghdr *hdr, int len)
{
	while (len > 0 && NLMSG_OK(hdr, len)) {
		if (hdr->nlmsg_type == RTM_NEWLINK) {
			ril_mtu_watch_handle_ifinfomsg(self, NLMSG_DATA(hdr),
						IFLA_PAYLOAD(hdr));
		}
		hdr = NLMSG_NEXT(hdr, len);
        }
}
Пример #6
0
int ll_remember_index(const struct sockaddr_nl *who,
		      struct nlmsghdr *n, void *arg)
{
	int h;
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	struct ll_cache *im, **imp;
	struct rtattr *tb[IFLA_MAX+1];

	UNUSED(who);
	UNUSED(arg);

	if (n->nlmsg_type != RTM_NEWLINK)
		return 0;

	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
		return -1;

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
	if (tb[IFLA_IFNAME] == NULL)
		return 0;

	h = ifi->ifi_index & (IDXMAP_SIZE - 1);
	for (imp = &idx_head[h]; (im=*imp)!=NULL; imp = &im->idx_next)
		if (im->index == ifi->ifi_index)
			break;

	if (im == NULL) {
		im = malloc(sizeof(*im));
		if (im == NULL)
			return 0;
		im->idx_next = *imp;
		im->index = ifi->ifi_index;
		*imp = im;
	}

	im->type = ifi->ifi_type;
	im->flags = ifi->ifi_flags;
	if (tb[IFLA_ADDRESS]) {
		size_t alen;
		im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
		if (alen > sizeof(im->addr))
			alen = sizeof(im->addr);
		memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
	} else {
		im->alen = 0;
		memset(im->addr, 0, sizeof(im->addr));
	}
	strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
	return 0;
}
Пример #7
0
static int handle_link_msg(struct nlmsghdr *nlh, int n)
{
	struct ifinfomsg *ifla_msg = NLMSG_DATA(nlh);
	struct rtattr *tb[IFLA_MAX];


	int atts = parse_rt_attrs(tb, IFLA_MAX, IFLA_RTA(ifla_msg), IFLA_PAYLOAD(nlh));

	parse_ifinfomsg(ifla_msg);

	handle_link_attrs(ifla_msg, tb, nlh->nlmsg_type);

	return 0;
}
Пример #8
0
rtnetlink::if_addr& rtnetlink::if_addr::operator=(message& msg)
{
	static_cast<data&>(*this) = msg;

	std::pair<const void*, size_t> pl = msg.payload();

	if (msg.type() < 20 || msg.type() > 23 || pl.second < sizeof(::ifaddrmsg))
		throw "bad msg type";

	const ::ifaddrmsg* ifa = reinterpret_cast<const ifaddrmsg*>(pl.first);

	_family = ifa->ifa_family;
	_prefixlen = ifa->ifa_prefixlen;
	_scope = ifa->ifa_scope;
	_flags = ifa->ifa_flags;
	_index = ifa->ifa_index;

	const ::rtattr* rta = IFLA_RTA(ifa);
	size_t attrlen = IFLA_PAYLOAD(reinterpret_cast<const ::nlmsghdr*>(_msg->header()));

	for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {
		switch (rta->rta_type) {
		case IFA_ADDRESS:
			_address = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_LOCAL:
			_local = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_LABEL:
			_label = attr<char>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_BROADCAST:
			_broadcast = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_ANYCAST:
			_anycast = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		default:
			std::cout << "IFA_UNSPEC(" << rta->rta_type << ", " << RTA_PAYLOAD(rta) << ")\n";
		}
	}

	return *this;
}
Пример #9
0
static void nl_parse_link_msg(struct nlmsghdr *nlp, struct nl_cb *cb)
{
	nl_link_cb link_cb;
	struct ifinfomsg *ifinfo;
	struct rtattr *rtap;
	struct nl_link link;
	size_t len;

	memset(&link, 0, sizeof(struct nl_link));
	ifinfo = NLMSG_DATA(nlp);
	rtap = IFLA_RTA(ifinfo);
	len = IFLA_PAYLOAD(nlp);

	for (; RTA_OK(rtap, len); rtap = RTA_NEXT(rtap, len)) {
		switch (rtap->rta_type) {
		case IFLA_IFNAME:
			link.ifname = (char *)RTA_DATA(rtap);
			break;
		case IFLA_ADDRESS:
			if (RTA_PAYLOAD(rtap) != sizeof(struct ether_addr)) {
				XLOG_ERR("invalid ll address for %u", ifinfo->ifi_index);
				return;
			}
			link.ifaddr = (struct ether_addr *)RTA_DATA(rtap);
			break;
		default:
			/* XLOG_DEBUG("attr: %u", rtap->rta_type); */
			break;
		}
	}

	if (!link.ifname) {
		XLOG_ERR("could not get name for link %u", ifinfo->ifi_index);
		return;
	}

	if (!link.ifaddr) {
		XLOG_ERR("could not get ll addr for link %u", ifinfo->ifi_index);
		return;
	}

	link.ifindex = ifinfo->ifi_index;
	link.iftype = ifinfo->ifi_type;
	link.ifflags = ifinfo->ifi_flags;

	link_cb = (nl_link_cb) cb->parse_cb;
	link_cb(&link, cb->aux);
}
Пример #10
0
static inline
uint8_t process_data ( bt_addresses * addresses, struct nlmsghdr * data, bool add )
{
    bt_address * address = parse_address ( addresses, NLMSG_DATA ( data ), IFLA_PAYLOAD ( data ) );
    if ( address == NULL ) {
        return 1;
    }
    
    if ( add ) {
        ;
    } else {
        ;
    }

    return 0;
}
Пример #11
0
static gboolean
is_wireless_status_message (struct nlmsghdr *header)
{
        int rt_attr_len;
        struct rtattr *rt_attr;

        rt_attr = IFLA_RTA (NLMSG_DATA (header));
        rt_attr_len = IFLA_PAYLOAD (header);
        while (RT_ATTR_OK (rt_attr, rt_attr_len)) {
                if (rt_attr->rta_type == IFLA_WIRELESS)
                        return TRUE;

                rt_attr = RTA_NEXT (rt_attr, rt_attr_len);
        }

        return FALSE;
}
Пример #12
0
static void
extract_info (struct nlmsghdr *header, char **label)
{
        int rt_attr_len;
        struct rtattr *rt_attr;

        rt_attr = IFLA_RTA (NLMSG_DATA (header));
        rt_attr_len = IFLA_PAYLOAD (header);
        while (RT_ATTR_OK (rt_attr, rt_attr_len)) {
                if (rt_attr->rta_type == IFA_LABEL) {
                        *label = g_strdup ((char *) RTA_DATA (rt_attr));

                        break;
                }
                rt_attr = RTA_NEXT (rt_attr, rt_attr_len);
        }
}
Пример #13
0
/* iftable_del - Delete an entry from the interface table
 * @n:		netlink message header of a RTM_DELLINK nlmsg
 * @arg:	not used
 *
 * Delete an entry from the interface table.  
 * Returns -1 on error, 0 if no matching entry was found or 1 on success.
 */
static int iftable_del(struct nlmsghdr *n, void *arg)
{
	struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
	struct rtattr *cb[IFLA_MAX+1];
	struct nlif_handle *nlif_handle = (struct nlif_handle *)arg;
	struct ifindex_map *im, *ima, **imp;
	unsigned int hash;

	if (n->nlmsg_type != RTM_DELLINK) {
		iftb_log(LOG_ERROR,
			 "called with wrong nlmsg_type %u", n->nlmsg_type);
		return -1;
	}

	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg))) {
		iftb_log(LOG_ERROR, "short message (%u < %u)",
			 n->nlmsg_len, NLMSG_LENGTH(sizeof(ifi_msg)));
		return -1;
	}

	memset(&cb, 0, sizeof(cb));
	rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));

	/* \todo Really suppress entry */
	hash = ifi_msg->ifi_index&0xF;
	for (ima = NULL, imp = &((nlif_handle->ifindex_map)[hash]); 
	     (im=*imp)!=NULL; imp = &im->next, ima=im) {
		if (im->index == ifi_msg->ifi_index) {
			iftb_log(LOG_DEBUG,
				 "deleting iftable (ifindex=%u)", im->index);
			break;
		}
	}

	if (!im)
		return 0;

	if (ima)
		ima->next = *imp;
	else
		(nlif_handle->ifindex_map)[hash] = *imp;
	free(im);

	return 1;
}
Пример #14
0
static void __if_nameindex_callback(void* context, nlmsghdr* hdr) {
  if_list** list = reinterpret_cast<if_list**>(context);
  if (hdr->nlmsg_type == RTM_NEWLINK) {
    ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));

    // Create a new entry and set the interface index.
    if_list* new_link = new if_list(list);
    new_link->data.if_index = ifi->ifi_index;

    // Go through the various bits of information and find the name.
    rtattr* rta = IFLA_RTA(ifi);
    size_t rta_len = IFLA_PAYLOAD(hdr);
    while (RTA_OK(rta, rta_len)) {
      if (rta->rta_type == IFLA_IFNAME) {
        new_link->data.if_name = strndup(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta));
      }
      rta = RTA_NEXT(rta, rta_len);
    }
  }
}
Пример #15
0
/*
 * Parse a RTM_NEWLINK message.
 */
bool NetlinkEvent::parseIfInfoMessage(const struct nlmsghdr *nh) {
    struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(nh);
    if (!checkRtNetlinkLength(nh, sizeof(*ifi)))
        return false;

    if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) {
        return false;
    }

    int len = IFLA_PAYLOAD(nh);
    struct rtattr *rta;
    for (rta = IFLA_RTA(ifi); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
        switch(rta->rta_type) {
            case IFLA_IFNAME:
                asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta));
                mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?  NlActionLinkUp :
                                                             NlActionLinkDown;
                mSubsystem = strdup("net");
                return true;
        }
    }

    return false;
}
Пример #16
0
static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {
  if (hdr->nlmsg_type == RTM_NEWLINK) {
    ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));

    // Create a new ifaddr entry, and set the interface index and flags.
    ifaddrs_storage* new_addr = new ifaddrs_storage(out);
    new_addr->interface_index = ifi->ifi_index;
    new_addr->ifa.ifa_flags = ifi->ifi_flags;

    // Go through the various bits of information and find the name.
    rtattr* rta = IFLA_RTA(ifi);
    size_t rta_len = IFLA_PAYLOAD(hdr);
    while (RTA_OK(rta, rta_len)) {
      if (rta->rta_type == IFLA_ADDRESS) {
          if (RTA_PAYLOAD(rta) < sizeof(new_addr->addr)) {
            new_addr->SetAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));
            new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));
          }
      } else if (rta->rta_type == IFLA_BROADCAST) {
          if (RTA_PAYLOAD(rta) < sizeof(new_addr->ifa_ifu)) {
            new_addr->SetBroadcastAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));
            new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));
          }
      } else if (rta->rta_type == IFLA_IFNAME) {
          if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) {
            memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta));
            new_addr->ifa.ifa_name = new_addr->name;
          }
      }
      rta = RTA_NEXT(rta, rta_len);
    }
  } else if (hdr->nlmsg_type == RTM_NEWADDR) {
    ifaddrmsg* msg = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));

    // We should already know about this from an RTM_NEWLINK message.
    const ifaddrs_storage* addr = reinterpret_cast<const ifaddrs_storage*>(*out);
    while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
      addr = reinterpret_cast<const ifaddrs_storage*>(addr->ifa.ifa_next);
    }
    // If this is an unknown interface, ignore whatever we're being told about it.
    if (addr == nullptr) return;

    // Create a new ifaddr entry and copy what we already know.
    ifaddrs_storage* new_addr = new ifaddrs_storage(out);
    // We can just copy the name rather than look for IFA_LABEL.
    strcpy(new_addr->name, addr->name);
    new_addr->ifa.ifa_name = new_addr->name;
    new_addr->ifa.ifa_flags = addr->ifa.ifa_flags;
    new_addr->interface_index = addr->interface_index;

    // Go through the various bits of information and find the address
    // and any broadcast/destination address.
    rtattr* rta = IFA_RTA(msg);
    size_t rta_len = IFA_PAYLOAD(hdr);
    while (RTA_OK(rta, rta_len)) {
      if (rta->rta_type == IFA_ADDRESS) {
        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
          new_addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
          new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);
        }
      } else if (rta->rta_type == IFA_BROADCAST) {
        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
          new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
        }
      }
      rta = RTA_NEXT(rta, rta_len);
    }
  }
}
Пример #17
0
static int print_interfaces() {
	int sock, len;
	struct nlmsghdr *nlm;
	struct iovec iov;
	struct msghdr rtnl_msg;
	struct sockaddr_nl s_nl;
	struct {
		struct nlmsghdr nh;
		struct rtgenmsg rtgm;
	} req;
	char buf[8192];

	printf("Network interfaces:\n");

	/* open netlink socket */
	sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
	if (sock < 0) {
		perror("sock");
		return 1;
	}

	/* initialize request */
	memset(&req, 0, sizeof(req));
	req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rtgm));
	req.nh.nlmsg_type = RTM_GETLINK;
	req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
	req.nh.nlmsg_seq = 1;
	req.nh.nlmsg_pid = getpid();
	req.rtgm.rtgen_family = AF_PACKET;

	memset(&s_nl, 0, sizeof(s_nl));
	s_nl.nl_family = AF_NETLINK;

	iov.iov_base = &req;
	iov.iov_len = req.nh.nlmsg_len;

	memset(&rtnl_msg, 0, sizeof(rtnl_msg));
	rtnl_msg.msg_iov = &iov;
	rtnl_msg.msg_iovlen = 1;
	rtnl_msg.msg_name = &s_nl;
	rtnl_msg.msg_namelen = sizeof(s_nl);

	/* send request */
	len = sendmsg(sock, &rtnl_msg, 0);
	if (len < 0) {
		perror("sendmsg");
		close(sock);
		return 1;
	}

	int end = 0;
	while (!end) {
		iov.iov_base = buf;
		iov.iov_len = sizeof(buf);

		memset(&rtnl_msg, 0, sizeof(rtnl_msg));
		rtnl_msg.msg_iov = &iov;
		rtnl_msg.msg_iovlen = 1;
		rtnl_msg.msg_name = &s_nl;
		rtnl_msg.msg_namelen = sizeof(s_nl);

		/* receive response */
		len = recvmsg(sock, &rtnl_msg, 0);
		if (len < 0) {
			perror("recvmsg");
			close(sock);
			return 1;
		}

		/* read response */
		nlm = (struct nlmsghdr*)buf;
		while (NLMSG_OK(nlm, len)) {
			if (nlm->nlmsg_type == NLMSG_DONE) {
				end = 1;
				break;
			} else if (nlm->nlmsg_type == RTM_NEWLINK) {
				struct ifinfomsg *ifinfo;
				struct rtattr *rta;
				int iflen;

				ifinfo = NLMSG_DATA(nlm);
				rta = IFLA_RTA(ifinfo);
				iflen = IFLA_PAYLOAD(nlm);

				while (RTA_OK(rta, iflen)) {
					if (rta->rta_type == IFLA_IFNAME)
						printf("  %s\n", (char*)RTA_DATA(rta));
					rta = RTA_NEXT(rta, iflen);
				}
			}
			nlm = NLMSG_NEXT(nlm, len);
		}
	}

	close(sock);
	return 0;
}
Пример #18
0
Файл: inarpd.c Проект: ago/inarp
void read_ifaces(void)
{
	struct sockaddr_nl addr;
	socklen_t addr_len = sizeof(addr);
	unsigned char buffer[4096];
	int sock, len;

	struct { 
                struct nlmsghdr nlh;
                struct rtgenmsg g;
        }req;

	print_dbg(0, "Searching for network interfaces...\n");

        sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        if (sock < 0) {
                perror("socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE) failed");
		exit(1);
	}

        memset(&addr, 0, sizeof(addr)); 
	addr.nl_family = AF_NETLINK;

	if (bind(sock, (struct sockaddr*)&addr, addr_len) < 0) {
		perror("bind(AF_NETLINK) failed");
		exit(1);
	}

	req.nlh.nlmsg_len = sizeof(req);
        req.nlh.nlmsg_type = RTM_GETLINK;
        req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
        req.nlh.nlmsg_pid = 0;
        req.nlh.nlmsg_seq = 1;
        req.g.rtgen_family = AF_PACKET;

        if (sendto(sock, (void*)&req, sizeof(req), 0,
		   (struct sockaddr*)&addr, sizeof(addr)) < 0) {
		perror("inarpd: sendto(RTM_GETLINK) failed");
		exit(1);
	}

	while(1) {
		struct nlmsghdr *h = (struct nlmsghdr*)buffer;
		if ((len = recv(sock, buffer, sizeof(buffer), 0)) < 0) {
			perror("recv() failed");
			exit(1);
		}

		while (len > 0) {
			if (!NLMSG_OK(h, (unsigned) len)) {
				error("NLMSG 0x%X not OK\n", h->nlmsg_type);
				break;
			}

			print_dbg(2, "NLMSG 0x%X\n", h->nlmsg_type);

			if (h->nlmsg_type == RTM_NEWLINK)
				parse_link(NLMSG_DATA(h), IFLA_PAYLOAD(h));

			else if (h->nlmsg_type == RTM_NEWADDR)
				parse_addr(NLMSG_DATA(h), IFA_PAYLOAD(h));

			else if (h->nlmsg_type == NLMSG_DONE) {
				if (req.nlh.nlmsg_type == RTM_GETADDR) {
					close(sock);
					return;
				}
				req.nlh.nlmsg_type = RTM_GETADDR;
				if (sendto(sock, (void*)&req, sizeof(req), 0,
					   (struct sockaddr*)&addr,
					   sizeof(addr)) < 0) {
					perror("inarpd: sendto(RTM_GETADDR)"
					       " failed");
					exit(1);
				}
				break;

			} else
				error("Unknown netlink message type 0x%X\n",
				       h->nlmsg_type);

			h = NLMSG_NEXT(h, len);
		}
	}
}
Пример #19
0
static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
{
	struct ifinfomsg *ifi = NLMSG_DATA(hdr);
	struct rtattr *attr = IFLA_RTA(ifi);
	uint32_t attrs_len = IFLA_PAYLOAD(hdr);
	char flags[256];
	char if_addr[64] = {};
	char *af_link = "unknown";

	if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
		return;

	if (ifi->ifi_family == AF_UNSPEC)
		af_link = "unspec";
	else if (ifi->ifi_family == AF_BRIDGE)
		af_link = "bridge";

	tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
			colorize_start(bold), af_link, colorize_end());
	tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
			colorize_start(bold),
			device_type2str(ifi->ifi_type),
			colorize_end());
	tprintf(", Index %d", ifi->ifi_index);
	tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
			colorize_start(bold),
			rtnl_link_flags2str(ifi->ifi_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
			colorize_start(bold),
			rtnl_link_flags2str(ifi->ifi_change, flags,
				sizeof(flags)),
			colorize_end());

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case IFLA_ADDRESS:
			rta_fmt(attr, "Address %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), ifi->ifi_type,
						if_addr, sizeof(if_addr)));
			break;
		case IFLA_BROADCAST:
			rta_fmt(attr, "Broadcast %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), ifi->ifi_type,
						if_addr, sizeof(if_addr)));
			break;
		case IFLA_IFNAME:
			rta_fmt(attr, "Name %s%s%s",
					colorize_start(bold), RTA_STR(attr),
					colorize_end());
			break;
		case IFLA_MTU:
			rta_fmt(attr, "MTU %d", RTA_INT(attr));
			break;
		case IFLA_LINK:
			rta_fmt(attr, "Link %d", RTA_INT(attr));
			break;
		case IFLA_QDISC:
			rta_fmt(attr, "QDisc %s", RTA_STR(attr));
			break;
		case IFLA_OPERSTATE:
			{
				uint8_t st = RTA_UINT8(attr);
				char states[256];

				rta_fmt(attr, "Operation state 0x%x (%s%s%s)",
						st,
						colorize_start(bold),
						rtnl_link_operstate2str(st,
							states, sizeof(states)),
						colorize_end());
			}
			break;
		case IFLA_LINKMODE:
			{
				uint8_t mode = RTA_UINT8(attr);
				char str[32];

				rta_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
						colorize_start(bold),
						rtnl_link_mode2str(mode, str,
							sizeof(str)),
						colorize_end());
			}
			break;
		case IFLA_GROUP:
			rta_fmt(attr, "Group %d", RTA_INT(attr));
			break;
		case IFLA_TXQLEN:
			rta_fmt(attr, "Tx queue len %d", RTA_INT(attr));
			break;
		case IFLA_NET_NS_PID:
			rta_fmt(attr, "Network namespace pid %d",
					RTA_INT(attr));
			break;
		case IFLA_NET_NS_FD:
			rta_fmt(attr, "Network namespace fd %d", RTA_INT(attr));
			break;
		default:
			rta_fmt(attr, "0x%x", attr->rta_type);
			break;
		}
	}
}
Пример #20
0
static int netlink_receive(struct netlink_fd *fd, struct nlmsghdr *reply)
{
	struct sockaddr_nl nladdr;
	struct iovec iov;
	struct msghdr msg = {
		.msg_name = &nladdr,
		.msg_namelen = sizeof(nladdr),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	int got_reply = FALSE, len;
	char buf[16*1024];

	iov.iov_base = buf;
	while (!got_reply) {
		int status;
		struct nlmsghdr *h;

		iov.iov_len = sizeof(buf);
		status = recvmsg(fd->fd, &msg, MSG_DONTWAIT);
		if (status < 0) {
			if (errno == EINTR)
				continue;
			if (errno == EAGAIN)
				return reply == NULL;
			fprintf(stderr, "Netlink overrun\n");
			continue;
		}

		if (status == 0) {
			fprintf(stderr, "Netlink returned EOF\n");
			return FALSE;
		}

		h = (struct nlmsghdr *) buf;
		while (NLMSG_OK(h, status)) {
			if (reply != NULL &&
			    h->nlmsg_seq == reply->nlmsg_seq) {
				len = h->nlmsg_len;
				if (len > reply->nlmsg_len) {
					fprintf(stderr, "Netlink message "
						"truncated\n");
					len = reply->nlmsg_len;
				}
				memcpy(reply, h, len);
				got_reply = TRUE;
			} else if (h->nlmsg_type != NLMSG_DONE) {
				fprintf(stderr,
					"Unknown NLmsg: 0x%08x, len %d\n",
					h->nlmsg_type, h->nlmsg_len);
			}
			h = NLMSG_NEXT(h, status);
		}
	}

	return TRUE;
}

static int netlink_send(struct netlink_fd *fd, struct nlmsghdr *req)
{
	struct sockaddr_nl nladdr;
	struct iovec iov = {
		.iov_base = (void*) req,
		.iov_len = req->nlmsg_len
	};
	struct msghdr msg = {
		.msg_name = &nladdr,
		.msg_namelen = sizeof(nladdr),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	int status;

	memset(&nladdr, 0, sizeof(nladdr));
	nladdr.nl_family = AF_NETLINK;

	req->nlmsg_seq = ++fd->seq;

	status = sendmsg(fd->fd, &msg, 0);
	if (status < 0) {
		fprintf(stderr, "Cannot talk to rtnetlink\n");
		return FALSE;
	}
	return TRUE;
}

static int netlink_talk(struct nlmsghdr *req, size_t replysize,
			struct nlmsghdr *reply)
{
	struct netlink_fd fd;
	int ret = FALSE;

	if (!netlink_open(&fd))
		return FALSE;

	if (reply == NULL)
		req->nlmsg_flags |= NLM_F_ACK;

	if (!netlink_send(&fd, req))
		goto out;

	if (reply != NULL) {
		reply->nlmsg_len = replysize;
		ret = netlink_receive(&fd, reply);
	} else {
		ret = TRUE;
	}
out:
	netlink_close(&fd);
	return ret;
}

int netlink_route_get(struct sockaddr *dst, u_int16_t *mtu, char *ifname)
{
	struct {
		struct nlmsghdr 	n;
		union {
			struct rtmsg		r;
			struct ifinfomsg	i;
		};
		char   			buf[1024];
	} req;
	struct rtmsg *r = NLMSG_DATA(&req.n);
	struct rtattr *rta[RTA_MAX+1];
	struct rtattr *rtax[RTAX_MAX+1];
	struct rtattr *ifla[IFLA_MAX+1];
	int index;

	memset(&req, 0, sizeof(req));
	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_GETROUTE;
	req.r.rtm_family = dst->sa_family;

	netlink_add_rtaddr_l(&req.n, sizeof(req), RTA_DST, dst);
	req.r.rtm_dst_len = 32;

	if (!netlink_talk(&req.n, sizeof(req), &req.n))
		return FALSE;

	netlink_parse_rtattr(rta, RTA_MAX, RTM_RTA(r),
			     RTM_PAYLOAD(&req.n));

	if (mtu != NULL) {
		if (rta[RTA_METRICS] == NULL)
			return FALSE;

		netlink_parse_rtattr(rtax, RTAX_MAX,
				     RTA_DATA(rta[RTA_METRICS]),
				     RTA_PAYLOAD(rta[RTA_METRICS]));
		if (rtax[RTAX_MTU] == NULL)
			return FALSE;

		*mtu = *(int*) RTA_DATA(rtax[RTAX_MTU]);
	}

	if (ifname != NULL) {
		if (rta[RTA_OIF] == NULL)
			return FALSE;

		index = *(int*) RTA_DATA(rta[RTA_OIF]);

		memset(&req, 0, sizeof(req));
		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETLINK;
		req.i.ifi_index = index;
		if (!netlink_talk(&req.n, sizeof(req), &req.n))
			return FALSE;

		netlink_parse_rtattr(ifla, IFLA_MAX, IFLA_RTA(r),
				     IFLA_PAYLOAD(&req.n));
		if (ifla[IFLA_IFNAME] == NULL)
			return FALSE;

		memcpy(ifname, RTA_DATA(ifla[IFLA_IFNAME]),
		       RTA_PAYLOAD(ifla[IFLA_IFNAME]));
	}

	return TRUE;
}
Пример #21
0
/* iftable_add - Add/Update an entry to/in the interface table
 * @n:		netlink message header of a RTM_NEWLINK message
 * @arg:	not used
 *
 * This function adds/updates an entry in the intrface table.
 * Returns -1 on error, 1 on success.
 */
static int iftable_add(struct nlmsghdr *n, void *arg)
{
	unsigned int hash;
	struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
	struct ifindex_map *im, **imp;
	struct rtattr *cb[IFLA_MAX+1];
	struct nlif_handle *nlif_handle = (struct nlif_handle *)arg;

	if (n->nlmsg_type != RTM_NEWLINK)
		return -1;

	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg))) {
		iftb_log(LOG_ERROR, "short message (%u < %u)",
			 n->nlmsg_len, NLMSG_LENGTH(sizeof(ifi_msg)));
		return -1;
	}

	memset(&cb, 0, sizeof(cb));
	rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
	if (!cb[IFLA_IFNAME]) {
		iftb_log(LOG_ERROR, "interface without name?");
		return -1;
	}

	hash = ifi_msg->ifi_index&0xF;
	for (imp = &((nlif_handle->ifindex_map)[hash]); 
	     (im=*imp)!=NULL; imp = &im->next) {
		if (im->index == ifi_msg->ifi_index) {
			iftb_log(LOG_DEBUG,
				 "updating iftable (ifindex=%u)", im->index);
			break;
		}
	}

	if (!im) {
		im = malloc(sizeof(*im));
		if (!im) {
			iftb_log(LOG_ERROR,
				 "ENOMEM while allocating ifindex_map");
			return 0;
		}
		im->next = *imp;
		im->index = ifi_msg->ifi_index;
		*imp = im;
		iftb_log(LOG_DEBUG, "creating new iftable (ifindex=%u)",
			 im->index);
	}
	
	im->type = ifi_msg->ifi_type;
	im->flags = ifi_msg->ifi_flags;
	if (cb[IFLA_ADDRESS]) {
		unsigned int alen;
		im->alen = alen = RTA_PAYLOAD(cb[IFLA_ADDRESS]);
		if (alen > sizeof(im->addr))
			alen = sizeof(im->addr);
		memcpy(im->addr, RTA_DATA(cb[IFLA_ADDRESS]), alen);
	} else {
		im->alen = 0;
		memset(im->addr, 0, sizeof(im->addr));
	}
	strcpy(im->name, RTA_DATA(cb[IFLA_IFNAME]));
	return 1;
}
Пример #22
0
static NOINLINE int check_existence_through_netlink(void)
{
	int iface_len;
	/* Buffer was 1K, but on linux-3.9.9 it was reported to be too small.
	 * netlink.h: "limit to 8K to avoid MSG_TRUNC when PAGE_SIZE is very large".
	 * Note: on error returns (-1) we exit, no need to free replybuf.
	 */
	enum { BUF_SIZE = 8 * 1024 };
	char *replybuf = xmalloc(BUF_SIZE);

	iface_len = strlen(G.iface);
	while (1) {
		struct nlmsghdr *mhdr;
		ssize_t bytes;

		bytes = recv(netlink_fd, replybuf, BUF_SIZE, MSG_DONTWAIT);
		if (bytes < 0) {
			if (errno == EAGAIN)
				goto ret;
			if (errno == EINTR)
				continue;
			bb_perror_msg("netlink: recv");
			return -1;
		}

		mhdr = (struct nlmsghdr*)replybuf;
		while (bytes > 0) {
			if (!NLMSG_OK(mhdr, bytes)) {
				bb_error_msg("netlink packet too small or truncated");
				return -1;
			}

			if (mhdr->nlmsg_type == RTM_NEWLINK || mhdr->nlmsg_type == RTM_DELLINK) {
				struct rtattr *attr;
				int attr_len;

				if (mhdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
					bb_error_msg("netlink packet too small or truncated");
					return -1;
				}

				attr = IFLA_RTA(NLMSG_DATA(mhdr));
				attr_len = IFLA_PAYLOAD(mhdr);

				while (RTA_OK(attr, attr_len)) {
					if (attr->rta_type == IFLA_IFNAME) {
						int len = RTA_PAYLOAD(attr);
						if (len > IFNAMSIZ)
							len = IFNAMSIZ;
						if (iface_len <= len
						 && strncmp(G.iface, RTA_DATA(attr), len) == 0
						) {
							G.iface_exists = (mhdr->nlmsg_type == RTM_NEWLINK);
						}
					}
					attr = RTA_NEXT(attr, attr_len);
				}
			}

			mhdr = NLMSG_NEXT(mhdr, bytes);
		}
	}

 ret:
	free(replybuf);
	return G.iface_exists;
}
Пример #23
0
int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
{
	int index, len, link_up;
	int slave_index = -1;
	struct iovec iov;
	struct sockaddr_nl sa;
	struct msghdr msg;
	struct nlmsghdr *nh;
	struct ifinfomsg *info = NULL;
	struct rtattr *tb[IFLA_MAX+1];

	index = if_nametoindex(device);
	if (!rtnl_buf) {
		rtnl_len = 4096;
		rtnl_buf = malloc(rtnl_len);
		if (!rtnl_buf) {
			pr_err("rtnl: low memory");
			return -1;
		}
	}

	iov.iov_base = rtnl_buf;
	iov.iov_len = rtnl_len;
	memset(&msg, 0, sizeof(msg));
	msg.msg_name = &sa;
	msg.msg_namelen = sizeof(sa);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	len = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
	if (len < 1) {
		pr_err("rtnl: recvmsg: %m");
		return -1;
	}
	if (len > rtnl_len) {
		free(rtnl_buf);
		rtnl_len = len;
		rtnl_buf = malloc(len);
		if (!rtnl_buf) {
			pr_err("rtnl: failed to resize to %d bytes", len);
			return -1;
		}
		iov.iov_base = rtnl_buf;
		iov.iov_len = rtnl_len;
	}

	len = recvmsg(fd, &msg, 0);
	if (len < 1) {
		pr_err("rtnl: recvmsg: %m");
		return -1;
	}
	nh = (struct nlmsghdr *) rtnl_buf;

	for ( ; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
		if (nh->nlmsg_type != RTM_NEWLINK)
			continue;

		info = NLMSG_DATA(nh);
		if (index != info->ifi_index)
			continue;

		link_up = info->ifi_flags & IFF_RUNNING ? 1 : 0;
		pr_debug("interface index %d is %s", index,
			 link_up ? "up" : "down");

		rtnl_rtattr_parse(tb, IFLA_MAX, IFLA_RTA(info),
				  IFLA_PAYLOAD(nh));

		if (tb[IFLA_LINKINFO])
			slave_index = rtnl_linkinfo_parse(tb[IFLA_LINKINFO]);

		if (cb)
			cb(ctx, link_up, slave_index);
	}

	return 0;
}
Пример #24
0
/* Create a linked list of `struct ifaddrs' structures, one for each
   network interface on the host machine.  If successful, store the
   list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
int
getifaddrs (struct ifaddrs **ifap)
{
  struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
  struct netlink_res *nlp;
  struct ifaddrs_storage *ifas;
  unsigned int i, newlink, newaddr, newaddr_idx;
  int *map_newlink_data;
  size_t ifa_data_size = 0;  /* Size to allocate for all ifa_data.  */
  char *ifa_data_ptr;	/* Pointer to the unused part of memory for
				ifa_data.  */
  int result = 0;

  if (ifap)
    *ifap = NULL;

  if (! __no_netlink_support && __netlink_open (&nh) < 0)
    {
#if __ASSUME_NETLINK_SUPPORT != 0
      return -1;
#endif
    }

#if __ASSUME_NETLINK_SUPPORT == 0
  if (__no_netlink_support)
    return fallback_getifaddrs (ifap);
#endif

  /* Tell the kernel that we wish to get a list of all
     active interfaces, collect all data for every interface.  */
  if (__netlink_request (&nh, RTM_GETLINK) < 0)
    {
      result = -1;
      goto exit_free;
    }

  /* Now ask the kernel for all addresses which are assigned
     to an interface and collect all data for every interface.
     Since we store the addresses after the interfaces in the
     list, we will later always find the interface before the
     corresponding addresses.  */
  ++nh.seq;
  if (__netlink_request (&nh, RTM_GETADDR) < 0)
    {
      result = -1;
      goto exit_free;
    }

  /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
     enough memory.  */
  newlink = newaddr = 0;
  for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through all entries we got from the kernel and look, which
	 message type they contain.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  /* Check if the message is what we want.  */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    {
	      /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
		 know the size before creating the list to allocate enough
		 memory.  */
	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
	      struct rtattr *rta = IFLA_RTA (ifim);
	      size_t rtasize = IFLA_PAYLOAD (nlh);

	      while (RTA_OK (rta, rtasize))
		{
		  size_t rta_payload = RTA_PAYLOAD (rta);

		  if (rta->rta_type == IFLA_STATS)
		    {
		      ifa_data_size += rta_payload;
		      break;
		    }
		  else
		    rta = RTA_NEXT (rta, rtasize);
		}
	      ++newlink;
	    }
	  else if (nlh->nlmsg_type == RTM_NEWADDR)
	    ++newaddr;
	}
    }

  /* Return if no interface is up.  */
  if ((newlink + newaddr) == 0)
    goto exit_free;

  /* Allocate memory for all entries we have and initialize next
     pointer.  */
  ifas = (struct ifaddrs_storage *) calloc (1,
					    (newlink + newaddr)
					    * sizeof (struct ifaddrs_storage)
					    + ifa_data_size);
  if (ifas == NULL)
    {
      result = -1;
      goto exit_free;
    }

  /* Table for mapping kernel index to entry in our list.  */
  map_newlink_data = alloca (newlink * sizeof (int));
  memset (map_newlink_data, '\xff', newlink * sizeof (int));

  ifa_data_ptr = (char *) &ifas[newlink + newaddr];
  newaddr_idx = 0;		/* Counter for newaddr index.  */

  /* Walk through the list of data we got from the kernel.  */
  for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through one message and look at the type: If it is our
	 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
	 the end or we find the end marker (in this case we ignore the
	 following data.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  int ifa_index = 0;

	  /* Check if the message is the one we want */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    {
	      /* We found a new interface. Now extract everything from the
		 interface data we got and need.  */
	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
	      struct rtattr *rta = IFLA_RTA (ifim);
	      size_t rtasize = IFLA_PAYLOAD (nlh);

	      /* Interfaces are stored in the first "newlink" entries
		 of our list, starting in the order as we got from the
		 kernel.  */
	      ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
				       map_newlink_data, newlink);
	      ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;

	      while (RTA_OK (rta, rtasize))
		{
		  char *rta_data = RTA_DATA (rta);
		  size_t rta_payload = RTA_PAYLOAD (rta);

		  switch (rta->rta_type)
		    {
		    case IFLA_ADDRESS:
		      if (rta_payload <= sizeof (ifas[ifa_index].addr))
			{
			  ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
			  memcpy (ifas[ifa_index].addr.sl.sll_addr,
				  (char *) rta_data, rta_payload);
			  ifas[ifa_index].addr.sl.sll_halen = rta_payload;
			  ifas[ifa_index].addr.sl.sll_ifindex
			    = ifim->ifi_index;
			  ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;

			  ifas[ifa_index].ifa.ifa_addr
			    = &ifas[ifa_index].addr.sa;
			}
		      break;

		    case IFLA_BROADCAST:
		      if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
			{
			  ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
			  memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
				  (char *) rta_data, rta_payload);
			  ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
			  ifas[ifa_index].broadaddr.sl.sll_ifindex
			    = ifim->ifi_index;
			  ifas[ifa_index].broadaddr.sl.sll_hatype
			    = ifim->ifi_type;

			  ifas[ifa_index].ifa.ifa_broadaddr
			    = &ifas[ifa_index].broadaddr.sa;
			}
		      break;

		    case IFLA_IFNAME:	/* Name of Interface */
		      if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
			{
			  ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
			  *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
					       rta_payload) = '\0';
			}
		      break;

		    case IFLA_STATS:	/* Statistics of Interface */
		      ifas[ifa_index].ifa.ifa_data = ifa_data_ptr;
		      ifa_data_ptr += rta_payload;
		      memcpy (ifas[ifa_index].ifa.ifa_data, rta_data,
			      rta_payload);
		      break;

		    case IFLA_UNSPEC:
		      break;
		    case IFLA_MTU:
		      break;
		    case IFLA_LINK:
		      break;
		    case IFLA_QDISC:
		      break;
		    default:
		      break;
		    }

		  rta = RTA_NEXT (rta, rtasize);
		}
	    }
	  else if (nlh->nlmsg_type == RTM_NEWADDR)
	    {
	      struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
	      struct rtattr *rta = IFA_RTA (ifam);
	      size_t rtasize = IFA_PAYLOAD (nlh);

	      /* New Addresses are stored in the order we got them from
		 the kernel after the interfaces. Theoretically it is possible
		 that we have holes in the interface part of the list,
		 but we always have already the interface for this address.  */
	      ifa_index = newlink + newaddr_idx;
	      ifas[ifa_index].ifa.ifa_flags
		= ifas[map_newlink (ifam->ifa_index - 1, ifas,
				    map_newlink_data, newlink)].ifa.ifa_flags;
	      if (ifa_index > 0)
		ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
	      ++newaddr_idx;

	      while (RTA_OK (rta, rtasize))
		{
		  char *rta_data = RTA_DATA (rta);
		  size_t rta_payload = RTA_PAYLOAD (rta);

		  switch (rta->rta_type)
		    {
		    case IFA_ADDRESS:
		      {
			struct sockaddr *sa;

			if (ifas[ifa_index].ifa.ifa_addr != NULL)
			  {
			    /* In a point-to-poing network IFA_ADDRESS
			       contains the destination address, local
			       address is supplied in IFA_LOCAL attribute.
			       destination address and broadcast address
			       are stored in an union, so it doesn't matter
			       which name we use.  */
			    ifas[ifa_index].ifa.ifa_broadaddr
			      = &ifas[ifa_index].broadaddr.sa;
			    sa = &ifas[ifa_index].broadaddr.sa;
			  }
			else
			  {
			    ifas[ifa_index].ifa.ifa_addr
			      = &ifas[ifa_index].addr.sa;
			    sa = &ifas[ifa_index].addr.sa;
			  }

			sa->sa_family = ifam->ifa_family;

			switch (ifam->ifa_family)
			  {
			  case AF_INET:
			    /* Size must match that of an address for IPv4.  */
			    if (rta_payload == 4)
			      memcpy (&((struct sockaddr_in *) sa)->sin_addr,
				      rta_data, rta_payload);
			    break;

			  case AF_INET6:
			    /* Size must match that of an address for IPv6.  */
			    if (rta_payload == 16)
			      {
				memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
					rta_data, rta_payload);
				if (IN6_IS_ADDR_LINKLOCAL (rta_data)
				    || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
				  ((struct sockaddr_in6 *) sa)->sin6_scope_id
				    = ifam->ifa_index;
			      }
			    break;

			  default:
			    if (rta_payload <= sizeof (ifas[ifa_index].addr))
			      memcpy (sa->sa_data, rta_data, rta_payload);
			    break;
			  }
		      }
		      break;

		    case IFA_LOCAL:
		      if (ifas[ifa_index].ifa.ifa_addr != NULL)
			{
			  /* If ifa_addr is set and we get IFA_LOCAL,
			     assume we have a point-to-point network.
			     Move address to correct field.  */
			  ifas[ifa_index].broadaddr = ifas[ifa_index].addr;
			  ifas[ifa_index].ifa.ifa_broadaddr
			    = &ifas[ifa_index].broadaddr.sa;
			  memset (&ifas[ifa_index].addr, '\0',
				  sizeof (ifas[ifa_index].addr));
			}

		      ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
		      ifas[ifa_index].ifa.ifa_addr->sa_family
			= ifam->ifa_family;

		      switch (ifam->ifa_family)
			{
			case AF_INET:
			  /* Size must match that of an address for IPv4.  */
			  if (rta_payload == 4)
			    memcpy (&ifas[ifa_index].addr.s4.sin_addr,
				  rta_data, rta_payload);
			  break;

			case AF_INET6:
			  /* Size must match that of an address for IPv6.  */
			  if (rta_payload == 16)
			    {
			      memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
				      rta_data, rta_payload);
			      if (IN6_IS_ADDR_LINKLOCAL (rta_data)
				  || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
				ifas[ifa_index].addr.s6.sin6_scope_id =
				  ifam->ifa_index;
			    }
			  break;

			default:
			  if (rta_payload <= sizeof (ifas[ifa_index].addr))
			    memcpy (ifas[ifa_index].addr.sa.sa_data,
				    rta_data, rta_payload);
			  break;
			}
		      break;

		    case IFA_BROADCAST:
		      /* We get IFA_BROADCAST, so IFA_LOCAL was too much.  */
		      if (ifas[ifa_index].ifa.ifa_broadaddr != NULL)
			memset (&ifas[ifa_index].broadaddr, '\0',
				sizeof (ifas[ifa_index].broadaddr));

		      ifas[ifa_index].ifa.ifa_broadaddr
			= &ifas[ifa_index].broadaddr.sa;
		      ifas[ifa_index].ifa.ifa_broadaddr->sa_family
			= ifam->ifa_family;

		      switch (ifam->ifa_family)
			{
			case AF_INET:
			  /* Size must match that of an address for IPv4.  */
			  if (rta_payload == 4)
			    memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
				    rta_data, rta_payload);
			  break;

			case AF_INET6:
			  /* Size must match that of an address for IPv6.  */
			  if (rta_payload == 16)
			    {
			      memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
				      rta_data, rta_payload);
			      if (IN6_IS_ADDR_LINKLOCAL (rta_data)
				  || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
				ifas[ifa_index].broadaddr.s6.sin6_scope_id
				  = ifam->ifa_index;
			    }
			  break;

			default:
			  if (rta_payload <= sizeof (ifas[ifa_index].addr))
			    memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
				    rta_data, rta_payload);
			  break;
			}
		      break;

		    case IFA_LABEL:
		      if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
			{
			  ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
			  *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
					       rta_payload) = '\0';
			}
		      else
			abort ();
		      break;

		    case IFA_UNSPEC:
		      break;
		    case IFA_CACHEINFO:
		      break;
		    default:
		      break;
		    }

		  rta = RTA_NEXT (rta, rtasize);
		}

	      /* If we didn't get the interface name with the
		 address, use the name from the interface entry.  */
	      if (ifas[ifa_index].ifa.ifa_name == NULL)
		ifas[ifa_index].ifa.ifa_name
		  = ifas[map_newlink (ifam->ifa_index - 1, ifas,
				      map_newlink_data, newlink)].ifa.ifa_name;

	      /* Calculate the netmask.  */
	      if (ifas[ifa_index].ifa.ifa_addr
		  && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC
		  && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET)
		{
		  uint32_t max_prefixlen = 0;
		  char *cp = NULL;

		  ifas[ifa_index].ifa.ifa_netmask
		    = &ifas[ifa_index].netmask.sa;

		  switch (ifas[ifa_index].ifa.ifa_addr->sa_family)
		    {
		    case AF_INET:
		      cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr;
		      max_prefixlen = 32;
		      break;

		    case AF_INET6:
		      cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr;
		      max_prefixlen = 128;
		      break;
		    }

		  ifas[ifa_index].ifa.ifa_netmask->sa_family
		    = ifas[ifa_index].ifa.ifa_addr->sa_family;

		  if (cp != NULL)
		    {
		      char c;
		      unsigned int preflen;

		      if ((max_prefixlen > 0) &&
			  (ifam->ifa_prefixlen > max_prefixlen))
			preflen = max_prefixlen;
		      else
			preflen = ifam->ifa_prefixlen;

		      for (i = 0; i < (preflen / 8); i++)
			*cp++ = 0xff;
		      c = 0xff;
		      c <<= (8 - (preflen % 8));
		      *cp = c;
		    }
		}
	    }
	}
    }

  assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);

  if (newaddr_idx > 0)
    {
      for (i = 0; i < newlink; ++i)
	if (map_newlink_data[i] == -1)
	  {
	    /* We have fewer links then we anticipated.  Adjust the
	       forward pointer to the first address entry.  */
	    ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
	  }

      if (i == 0 && newlink > 0)
	/* No valid link, but we allocated memory.  We have to
	   populate the first entry.  */
	memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
    }

  if (ifap != NULL)
    *ifap = &ifas[0].ifa;

 exit_free:
  __netlink_free_handle (&nh);
  __netlink_close (&nh);

  return result;
}
static struct if_nameindex *
if_nameindex_netlink (void)
{
  struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
  struct if_nameindex *idx = NULL;

  if (__no_netlink_support || __netlink_open (&nh) < 0)
    return NULL;


  /* Tell the kernel that we wish to get a list of all
     active interfaces.  Collect all data for every interface.  */
  if (__netlink_request (&nh, RTM_GETLINK) < 0)
    goto exit_free;

  /* Count the interfaces.  */
  unsigned int nifs = 0;
  for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through all entries we got from the kernel and look, which
         message type they contain.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  /* Check if the message is what we want.  */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    ++nifs;
	}
    }

  idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
  if (idx == NULL)
    {
    nomem:
      __set_errno (ENOBUFS);
      goto exit_free;
    }

  /* Add the interfaces.  */
  nifs = 0;
  for (struct netlink_res *nlp = nh.nlm_list; nlp; nlp = nlp->next)
    {
      struct nlmsghdr *nlh;
      size_t size = nlp->size;

      if (nlp->nlh == NULL)
	continue;

      /* Walk through all entries we got from the kernel and look, which
         message type they contain.  */
      for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
	{
	  /* Check if the message is what we want.  */
	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
	    continue;

	  if (nlh->nlmsg_type == NLMSG_DONE)
	    break;		/* ok */

	  if (nlh->nlmsg_type == RTM_NEWLINK)
	    {
	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
	      struct rtattr *rta = IFLA_RTA (ifim);
	      size_t rtasize = IFLA_PAYLOAD (nlh);

	      idx[nifs].if_index = ifim->ifi_index;

	      while (RTA_OK (rta, rtasize))
		{
		  char *rta_data = RTA_DATA (rta);
		  size_t rta_payload = RTA_PAYLOAD (rta);

		  if (rta->rta_type == IFLA_IFNAME)
		    {
		      idx[nifs].if_name = __strndup (rta_data, rta_payload);
		      if (idx[nifs].if_name == NULL)
			{
			  idx[nifs].if_index = 0;
			  if_freenameindex (idx);
			  idx = NULL;
			  goto nomem;
			}
		      break;
		    }

		  rta = RTA_NEXT (rta, rtasize);
		}

	      ++nifs;
	    }
	}
    }

  idx[nifs].if_index = 0;
  idx[nifs].if_name = NULL;

 exit_free:
  __netlink_free_handle (&nh);
  __netlink_close (&nh);

  return idx;
}
Пример #26
0
rtnetlink::if_link& rtnetlink::if_link::operator=(message& msg)
{
	static_cast<data&>(*this) = msg;

	std::pair<const void*, size_t> pl = msg.payload();

	if (msg.type() < 16 || msg.type() > 19 || pl.second < sizeof(::ifinfomsg))
		throw "bad msg type";

	const ::ifinfomsg* ifi = reinterpret_cast<const ifinfomsg*>(pl.first);

	_type = ifi->ifi_type;
	_index = ifi->ifi_index;
	_flags = ifi->ifi_flags;

	const ::rtattr* rta = IFLA_RTA(ifi);
	size_t attrlen = IFLA_PAYLOAD(reinterpret_cast<const ::nlmsghdr*>(_msg->header()));

	for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {
		switch (rta->rta_type) {
		case IFLA_ADDRESS:
			_address = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFLA_BROADCAST:
			_bcast_addr = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFLA_IFNAME:
			_name = attr<char>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFLA_MTU:
			ODTONE_ASSERT(sizeof(odtone::uint) == RTA_PAYLOAD(rta));
			_mtu = reinterpret_cast<odtone::uint*>(RTA_DATA(rta));
			break;

		case IFLA_LINK:
			ODTONE_ASSERT(sizeof(odtone::sint) == RTA_PAYLOAD(rta));
			_link_type = reinterpret_cast<odtone::sint*>(RTA_DATA(rta));
			break;

		case IFLA_QDISC:
			_qdisc = attr<char>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFLA_STATS:
			ODTONE_ASSERT(sizeof(::rtnl_link_stats) == RTA_PAYLOAD(rta));
			_stats = RTA_DATA(rta);
			break;

		case IFLA_WIRELESS:
			std::cout << "IFLA_WIRELESS(" << rta->rta_type << ", " << RTA_PAYLOAD(rta) << ")\n";
			// std::cout	<< "\tcmd: "
			// 			<< reinterpret_cast<iw_event*>(RTA_DATA(rta))->cmd
			// 			<< "  len: "
			// 			<< reinterpret_cast<iw_event*>(RTA_DATA(rta))->len
			// 			<< std::endl;

			_wifi = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		default:
			std::cout << "IFLA_UNSPEC(" << rta->rta_type << ", " << RTA_PAYLOAD(rta) << ")\n";
		}
	}

	return *this;
}
/*

	Function : parse_msg_detail

	This function prints the details of a 
	RTM* message.

	@input mlmsghdr : The RTM message
*/
void parse_msg_detail (struct nlmsghdr* nl_msg)
{
	int rtl;
	struct ifinfomsg *linfo;
	struct rtattr *rtap;

	linfo = (struct ifinfomsg *)NLMSG_DATA(nl_msg);

	__android_log_print(
			ANDROID_LOG_INFO, 
			LOG_TAG,  
			"got a new link creation message: family (%d), type (%d), flags(%x) index(%d)\n", 
			linfo->ifi_family, 
			linfo->ifi_type, 
			linfo->ifi_flags, 
			linfo->ifi_index);

	/* determine the type and name of the link */
	rtap = IFLA_RTA(linfo);

	/* get length of attributes */
	rtl = IFLA_PAYLOAD(nl_msg);

	/* process attributes of the link info message */
	for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl)) {

		if (rtap->rta_type == IFLA_IFNAME) { /* get interface name */
			strncpy(iface, RTA_DATA(rtap), RTA_PAYLOAD(rtap));

			__android_log_print(
					ANDROID_LOG_INFO, 
					LOG_TAG,  
					"interface %s \n", iface);

		}

		else if (rtap->rta_type == IFLA_LINK) { /* link type */

			int x = *(int *)RTA_DATA(rtap);

			__android_log_print(
					ANDROID_LOG_INFO,
					LOG_TAG,  
					"interface linktype %x \n", x);

		}
		else if (rtap->rta_type == IFLA_LINKMODE) { /* link mode */

			int x = *(int *)RTA_DATA(rtap);

			__android_log_print(
					ANDROID_LOG_INFO, 
					LOG_TAG,  
					"interface linkmode %x \n", x);

		}
		else if (rtap->rta_type == IFLA_OPERSTATE) { /* link type */
			int x = *(int *)RTA_DATA(rtap);
			switch (x)
			{
				case (IF_OPER_DOWN):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_DOWN");
					break;
				case (IF_OPER_UP):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_UP");
					break;
				case (IF_OPER_LOWERLAYERDOWN):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_LOWERLAYERDOWN");
					break;
				case (IF_OPER_TESTING):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_TESTING");
					break;
				case (IF_OPER_DORMANT):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_DORMANT");
					break;
				case (IF_OPER_UNKNOWN):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_UNKNOWN");
					break;
				case (IF_OPER_NOTPRESENT):
					__android_log_print(
							ANDROID_LOG_INFO, 
							LOG_TAG,  
							"IF_OPER_NOTPRESENT");
					break;
			}
			__android_log_print(
					ANDROID_LOG_INFO, 
					LOG_TAG,  
					"interface new operstate %x \n", x);
		}
	}

}