Exemplo n.º 1
0
/*
 * returns: -1 - address not found, 0 - addr is ok, 1 - addr is tentative
 */
int is_addr_tentative(char * ifacename, int iface, char * addr)
{
    char buf[256];
    char packed1[16];
    char packed2[16];
    struct rtattr * rta_tb[IFA_MAX+1];
    struct nlmsg_list *ainfo = NULL;
    struct nlmsg_list *head = NULL;
    struct rtnl_handle rth;

    int tentative = LOWLEVEL_TENTATIVE_DONT_KNOW;

    inet_pton6(addr,packed1);

    rtnl_open(&rth, 0);

    /* 2nd attribute: AF_UNSPEC, AF_INET, AF_INET6 */
    /* rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETLINK); */
    rtnl_wilddump_request(&rth, AF_INET6, RTM_GETADDR);
    rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL);

    head = ainfo;
    while (ainfo) {
	struct nlmsghdr *n = &ainfo->h;
	struct ifaddrmsg *ifa = NLMSG_DATA(n);
	
	memset(rta_tb, 0, sizeof(*rta_tb));
	
	if (ifa->ifa_index == iface && ifa->ifa_family==AF_INET6) {
	    parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
	    if (!rta_tb[IFA_LOCAL])   rta_tb[IFA_LOCAL]   = rta_tb[IFA_ADDRESS];
	    if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
	    
	    inet_ntop6(RTA_DATA(rta_tb[IFA_LOCAL]), buf /*, sizeof(buf)*/);
	    memcpy(packed2,RTA_DATA(rta_tb[IFA_LOCAL]),16);

	    /* print_packed(packed1); printf(" "); print_packed(packed2); printf("\n"); */

	    /* is this addr which are we looking for? */
	    if (!memcmp(packed1,packed2,16) ) {
		if (ifa->ifa_flags & IFA_F_TENTATIVE)
		    tentative = LOWLEVEL_TENTATIVE_YES;
		else
		    tentative = LOWLEVEL_TENTATIVE_NO;
	    }
	}
	ainfo = ainfo->next;
    }

    /* now delete list */
    while (head) {
	ainfo = head;
	head = head->next;
	free(ainfo);
    }
    
    rtnl_close(&rth);

    return tentative;
}
Exemplo n.º 2
0
static void g_pn_nl_addr(GPhonetNetlink *self, struct nlmsghdr *nlh)
{
	int len;
	uint8_t local = 0xff;
	uint8_t remote = 0xff;

	const struct ifaddrmsg *ifa;
	const struct rtattr *rta;

	ifa = NLMSG_DATA(nlh);
	len = IFA_PAYLOAD(nlh);

	/* If Phonet is absent, kernel transmits other families... */
	if (ifa->ifa_family != AF_PHONET)
		return;

	if (ifa->ifa_index != self->interface)
		return;

	for (rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {

		if (rta->rta_type == IFA_LOCAL)
			local = *(uint8_t *)RTA_DATA(rta);
		else if (rta->rta_type == IFA_ADDRESS)
			remote = *(uint8_t *)RTA_DATA(rta);
	}
}
Exemplo n.º 3
0
void linux_unicast_router::handle_addr_event(bool isnew, nlmsghdr *hdr) {
    ifaddrmsg *ifa = (ifaddrmsg *)NLMSG_DATA(hdr);

    if (ifa->ifa_family == AF_INET6) {
        rtattr *tb[IFA_MAX + 1];
        memset(tb, 0, sizeof(tb));

        netlink_msg::parse_rtatable(tb, IFA_MAX, IFA_RTA(ifa),
                                    hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

        rtattr *arta = tb[IFA_LOCAL];
        if (!arta)
            arta = tb[IFA_ADDRESS];
        if (arta) {
            inet6_addr addr;
            memcpy(&addr.addr, RTA_DATA(arta), RTA_PAYLOAD(arta));
            addr.prefixlen = ifa->ifa_prefixlen;

            if (addr.type() & (inet6_addr::multicast | inet6_addr::network))
                return;

            if (addr.is_any())
                return;

            interface *intf = g_mrd->get_interface_by_index(ifa->ifa_index);
            if (intf) {
                intf->address_added_or_removed(isnew, addr);
            }
        }
    }
}
Exemplo n.º 4
0
int
TunnelIPv6Interface::process(void)
{
	uint8_t buffer[1024];
	ssize_t buffer_len(-1);

	if (mNetlinkFD >= 0) {
		buffer_len = recv(mNetlinkFD, buffer, sizeof(buffer), 0);
	}

	if (buffer_len > 0) {
		struct nlmsghdr *nlp;
		struct rtmsg *rtp;
		int rta_len;
		struct rtattr *rta;

		nlp = (struct nlmsghdr *)buffer;
		for (;NLMSG_OK(nlp, buffer_len); nlp=NLMSG_NEXT(nlp, buffer_len))
		{
			if (nlp->nlmsg_type == RTM_NEWADDR || nlp->nlmsg_type == RTM_DELADDR) {
				struct ifaddrmsg *ifaddr = (struct ifaddrmsg *)NLMSG_DATA(nlp);
				char ifnamebuf[IF_NAMESIZE];
				const char *ifname = if_indextoname(ifaddr->ifa_index, ifnamebuf);
				struct in6_addr addr;

				if ((ifname == NULL) || (get_interface_name() != ifname)) {
					continue;
				}

				// get RTNETLINK message header
				// get start of attributes
				rta = (struct rtattr *) IFA_RTA(ifaddr);

				// get length of attributes
				rta_len = IFA_PAYLOAD(nlp);

				for(;RTA_OK(rta, rta_len); rta = RTA_NEXT(rta, rta_len)) {
					switch(rta->rta_type) {
					case IFA_ADDRESS:
					case IFA_LOCAL:
					case IFA_BROADCAST:
					case IFA_ANYCAST:
						memcpy(addr.s6_addr, RTA_DATA(rta), sizeof(addr));

						if (nlp->nlmsg_type == RTM_NEWADDR) {
							mAddressWasAdded(addr, ifaddr->ifa_prefixlen);
						} else if (nlp->nlmsg_type == RTM_DELADDR) {
							mAddressWasRemoved(addr, ifaddr->ifa_prefixlen);
						}
						break;
					default:
						break;
					}
				}
			}
		}
	}

	return nl::UnixSocket::process();
}
Exemplo n.º 5
0
static int
parse_addr_rta(struct ifaddrmsg *addr, int len, struct in6_addr *res)
{
    struct rtattr *rta;
    len -= NLMSG_ALIGN(sizeof(*addr));
    rta = IFA_RTA(addr);

    while (RTA_OK(rta, len)) {
        switch(rta->rta_type) {
            case IFA_LOCAL:
            case IFA_ADDRESS:
                switch (addr->ifa_family) {
                    case AF_INET:
                        if (res)
                            v4tov6(res->s6_addr, RTA_DATA(rta));
                        break;
                    case AF_INET6:
                        if (res)
                            memcpy(res->s6_addr, RTA_DATA(rta), 16);
                        break;
                    default:
                        kdebugf("ifaddr: unexpected address family %d\n", addr->ifa_family);
                        return -1;
                        break;
                }
                break;
            default:
                break;
        }
        rta = RTA_NEXT(rta, len);
    }
    return 0;
}
Exemplo n.º 6
0
/* Add remote address */
static int netlink_addroute(uint32_t ifa_index, uint8_t remote)
{
	struct rtmsg *rtm;
	struct rtattr *rta;
	uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*rtm)) +
				RTA_SPACE(1) +
				RTA_SPACE(sizeof(ifa_index)));
	struct req {
		struct nlmsghdr nlh;
		char buf[512];
	} req = {
		.nlh = {
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK
					| NLM_F_CREATE | NLM_F_APPEND,
			.nlmsg_type = RTM_NEWROUTE,
			.nlmsg_pid = getpid(),
			.nlmsg_len = reqlen,
		},
	};
	size_t buflen = sizeof(req.buf) - sizeof(*rtm);
	int fd;
	int error;
	struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };

	rtm = NLMSG_DATA(&req.nlh);
	rtm->rtm_family = AF_PHONET;
	rtm->rtm_dst_len = 6;
	rtm->rtm_src_len = 0;
	rtm->rtm_tos = 0;

	rtm->rtm_table = RT_TABLE_MAIN;
	rtm->rtm_protocol = RTPROT_STATIC;
	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
	rtm->rtm_type = RTN_UNICAST;
	rtm->rtm_flags = 0;

	rta = IFA_RTA(rtm);
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(1);
	*(uint8_t *)RTA_DATA(rta) = remote;

	rta = RTA_NEXT(rta, buflen);
	rta->rta_type = RTA_OIF;
	rta->rta_len = RTA_LENGTH(sizeof(ifa_index));
	*(uint32_t *)RTA_DATA(rta) = ifa_index;

	fd = netlink_socket();
	if (fd == -1)
		return -errno;

	if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
		error = -errno;
	else
		error = netlink_getack(fd);

	close(fd);

	return error;
}
int addr_do(const struct in6_addr *addr, int plen, int ifindex, void *arg,
	    int (*do_callback)(struct ifaddrmsg *ifa,
			       struct rtattr *rta_tb[], void *arg))
{
	uint8_t sbuf[256];
	uint8_t rbuf[256];
	struct nlmsghdr *sn, *rn;
	struct ifaddrmsg *ifa;
	int err;
	struct rtattr *rta_tb[IFA_MAX+1];

	memset(sbuf, 0, sizeof(sbuf));
	sn = (struct nlmsghdr *)sbuf;
	sn->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	sn->nlmsg_flags = NLM_F_REQUEST;
	sn->nlmsg_type = RTM_GETADDR;

	ifa = NLMSG_DATA(sn);
	ifa->ifa_family = AF_INET6;
	ifa->ifa_prefixlen = plen;
	ifa->ifa_scope = RT_SCOPE_UNIVERSE;
	ifa->ifa_index = ifindex;

	addattr_l(sn, sizeof(sbuf), IFA_LOCAL, addr, sizeof(*addr));

	memset(rbuf, 0, sizeof(rbuf));
	rn = (struct nlmsghdr *)rbuf;
	err = rtnl_route_do(sn, rn);
	if (err < 0) {
		rn = sn;
		ifa = NLMSG_DATA(rn);
	} else {
		ifa = NLMSG_DATA(rn);

		if (rn->nlmsg_type != RTM_NEWADDR ||
		    rn->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa)) ||
		    ifa->ifa_family != AF_INET6) {
			return -EINVAL;
		}
	}
	memset(rta_tb, 0, sizeof(rta_tb));
	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
		     rn->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

	if (!rta_tb[IFA_ADDRESS])
		rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];

	if (!rta_tb[IFA_ADDRESS] ||
	    !IN6_ARE_ADDR_EQUAL(RTA_DATA(rta_tb[IFA_ADDRESS]), addr)) {
		return -EINVAL;
	}
	if (do_callback)
		err = do_callback(ifa, rta_tb, arg);

	return err;

}
Exemplo n.º 8
0
static int read_iface_prefix(const char *ip_str, int is_ipv6)
{
	uint8_t family = is_ipv6 ? AF_INET6 : AF_INET;

	char buf[16384];
	unsigned int len;

	struct {
		struct nlmsghdr nlhdr;
		struct ifaddrmsg addrmsg;
	} msg;

	struct nlmsghdr *retmsg;

	int sock = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);

	memset(&msg, 0, sizeof(msg));
	msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
	msg.nlhdr.nlmsg_type = RTM_GETADDR;
	msg.addrmsg.ifa_family = family;

	SAFE_SEND(1, sock, &msg, msg.nlhdr.nlmsg_len, 0);
	len = recv(sock, buf, sizeof(buf), 0);
	retmsg = (struct nlmsghdr *)buf;

	while NLMSG_OK(retmsg, len) {
		char ifname[IFNAMSIZ];
		struct ifaddrmsg *retaddr;
		struct rtattr *retrta;
		char pradd[128];
		int attlen;

		retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg);
		retrta = (struct rtattr *)IFA_RTA(retaddr);
		attlen = IFA_PAYLOAD(retmsg);

		while RTA_OK(retrta, attlen) {
			if (retrta->rta_type == IFA_ADDRESS) {
				inet_ntop(family, RTA_DATA(retrta), pradd,
					  sizeof(pradd));

				if_indextoname(retaddr->ifa_index, ifname);

				if (!strcmp(pradd, ip_str)) {
					prefix = retaddr->ifa_prefixlen;
					iface = strdup(ifname);
					return 0;
				}
			}
			retrta = RTA_NEXT(retrta, attlen);
		}
		retmsg = NLMSG_NEXT(retmsg, len);
	}

	return -1;
}
Exemplo n.º 9
0
// Returns AF_MAX (with errno set) if error, AF_UNSPEC if no more addrs (socket closed)
struct IPAddr nextAddr(struct AddrFilter const filter, struct MonitorState * const state){
	// NLMSG_OK checks length first, so safe to call with state->nlh == NULL iff
	// state->nlmsg_len < (int) sizeof(struct nlmsghdr)
	if (NLMSG_OK(state->nlh, state->nlmsg_len) && (state->nlh->nlmsg_type != NLMSG_DONE)){
		struct nlmsghdr * nlh = state->nlh;
		state->nlh = NLMSG_NEXT(state->nlh, state->nlmsg_len);
		switch(nlh->nlmsg_type){
		case NLMSG_ERROR:
			errno = -((struct nlmsgerr *) NLMSG_DATA(nlh))->error;
			struct IPAddr addr = {.af = AF_MAX};
			return addr;
		case RTM_NEWADDR: {
			struct ifaddrmsg * ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
			if (!filterIfAddrMsg(*ifa, filter))
				return nextAddr(filter, state);
			{
			struct rtattr * rth;
			size_t rtmsg_len;
			for (rth = IFA_RTA(ifa), rtmsg_len = IFA_PAYLOAD(nlh);
			     RTA_OK(rth, rtmsg_len); RTA_NEXT(rth, rtmsg_len)){
				if (rth->rta_type != IFA_ADDRESS)
					continue;
				// family checked in filterIfAddrMsg, so always valid.
				struct IPAddr addr = {.af = ifa->ifa_family};
				switch (ifa->ifa_family) {
				case AF_INET:
					addr.ipv4 = *((struct in_addr *) RTA_DATA(rth));
					break;
				case AF_INET6:
					addr.ipv6 = *((struct in6_addr *) RTA_DATA(rth));
					break;
				}
				if (addrIsPrivate(addr) && !filter.allow_private)
					return nextAddr(filter, state);
				else
					return addr;
			}
			}
			// Recieved RTM_NEWADDR without any address.
			errno = EBADMSG;
			struct IPAddr addr = {.af = AF_MAX};
			return addr;
		}
		default:
			return nextAddr(filter, state);
		}
	} else {
		state->nlmsg_len = nextMessage(filter, state->socket, &state->buf, &state->buf_len);
		if (state->nlmsg_len == 0) {
			// Socket closed by kernel
			struct IPAddr addr = {.af = AF_UNSPEC};
			return addr;
		} else if (state->nlmsg_len < 0) {
			// Socket error
			struct IPAddr addr = {.af = AF_MAX};
			return addr;
		} else  {
Exemplo n.º 10
0
boost::asio::ip::address_v6 get_ipv6_address(const nlmsghdr *in, const nlmsghdr *an)
{
	boost::asio::ip::address_v6 unspec;
	if (in->nlmsg_type != RTM_NEWLINK)
		return unspec;
	if (an->nlmsg_type != RTM_NEWADDR)
		return unspec;

	ifinfomsg* ifi = (ifinfomsg*)NLMSG_DATA(in);
	ifaddrmsg* ifa = (ifaddrmsg*)NLMSG_DATA(an);

	__u32 ilen = in->nlmsg_len;
	if (ilen < NLMSG_LENGTH(sizeof(*ifi)))
		return unspec;
	ilen -= NLMSG_LENGTH(sizeof(*ifi));

	__u32 alen = an->nlmsg_len;
	if (alen < NLMSG_LENGTH(sizeof(*ifa)))
		return unspec;
	alen -= NLMSG_LENGTH(sizeof(*ifa));

	/* NOTE: ifi_index and ifa_index should have the same type (int), but for
	 * some reason they are not... So instead of a normal (in)equality comparison
	 * we do a bit-wise compare.
	 */
	if (ifi->ifi_index ^ ifa->ifa_index)
		return unspec;

	if (ifi->ifi_family != AF_INET6 || ifa->ifa_family != AF_INET6)
		return unspec;

	rtattr* tbi[IFLA_MAX+1];
	memset(tbi, 0, sizeof(tbi));
	parse_rtattr(tbi, IFLA_MAX, IFLA_RTA(ifi), ilen);

	if (tbi[IFLA_IFNAME] == NULL)
		return unspec;

	rtattr* tba[IFA_MAX+1];
	memset(tba, 0, sizeof(tba));
	parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), alen);

	char abuf[256];
	rt_addr_n2a(ifa->ifa_family,
			RTA_PAYLOAD(tba[IFA_ADDRESS]),
			RTA_DATA(tba[IFA_ADDRESS]),
			abuf, sizeof(abuf));
	std::string ipaddr = abuf;

	try {
		boost::asio::ip::address_v6 addr(boost::asio::ip::address_v6::from_string(ipaddr));
		addr.scope_id(ifi->ifi_index);
		return addr;
	} catch(...) {
		return unspec;
	}
}
Exemplo n.º 11
0
/*
 * Netlink interface address lookup filter
 * We need to handle multiple primary address and
 * multiple secondary address to the same interface.
 */
static int
netlink_if_address_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifaddrmsg *ifa;
	struct rtattr *tb[IFA_MAX + 1];
	interface_t *ifp;
	int len;
	void *addr;

	ifa = NLMSG_DATA(h);

	/* Only IPV4 are valid us */
	if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)
		return 0;

	if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
	if (len < 0)
		return -1;

	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);

	/* Fetch interface_t */
	ifp = if_get_by_ifindex(ifa->ifa_index);
	if (!ifp)
		return 0;
	if (tb[IFA_LOCAL] == NULL)
		tb[IFA_LOCAL] = tb[IFA_ADDRESS];
	if (tb[IFA_ADDRESS] == NULL)
		tb[IFA_ADDRESS] = tb[IFA_LOCAL];

	/* local interface address */
	addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);

	if (addr == NULL)
		return -1;

	/* If no address is set on interface then set the first time */
	if (ifa->ifa_family == AF_INET) {
		if (!ifp->sin_addr.s_addr)
			ifp->sin_addr = *(struct in_addr *) addr;
	} else {
		if (!ifp->sin6_addr.s6_addr16[0] && ifa->ifa_scope == RT_SCOPE_LINK)
			ifp->sin6_addr = *(struct in6_addr *) addr;
	}

#ifdef _WITH_LVS_
	/* Refresh checkers state */
	update_checker_activity(ifa->ifa_family, addr,
				(h->nlmsg_type == RTM_NEWADDR) ? 1 : 0);
#endif
	return 0;
}
Exemplo n.º 12
0
static int handle_addr_msg(struct nlmsghdr *nlh, int n)
{
	struct ifaddrmsg *ifa_msg = NLMSG_DATA(nlh);
	struct rtattr *tb[IFA_MAX];

	parse_rt_attrs(tb, IFA_MAX, IFA_RTA(ifa_msg), IFA_PAYLOAD(nlh));
	handle_addr_attrs(ifa_msg, tb, nlh->nlmsg_type);

	return 0;
}
Exemplo n.º 13
0
void process_nl_del_address (struct nlmsghdr *nlh)
{
    struct ifaddrmsg    *ifa            = NULL;
    struct rtattr       *rth            = NULL;
    int                 iface_index     = 0;
    int                 rt_length       = 0;
    lispd_iface_elt     *iface          = NULL;
    lisp_addr_t         new_addr;
    char                iface_name[IF_NAMESIZE];

    ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh);
    iface_index = ifa->ifa_index;

    iface = get_interface_from_index(iface_index);

    if (iface == NULL) {
        if_indextoname(iface_index, iface_name);
        lispd_log_msg(LISP_LOG_DEBUG_2, "process_nl_add_address: the netlink message is not for any interface associated with RLOCs (%s)",
                      iface_name);
        return;
    }
    rth = IFA_RTA (ifa);

    rth = IFA_RTA (ifa);
    rt_length = IFA_PAYLOAD (nlh);
    for (; rt_length && RTA_OK (rth, rt_length); rth = RTA_NEXT (rth,rt_length))
    {
        if (rth->rta_type == IFA_ADDRESS) {
            if (ifa->ifa_family == AF_INET) {
                memcpy (&(new_addr.address),(struct in_addr *)RTA_DATA(rth),sizeof(struct in_addr));
                new_addr.afi = AF_INET;
            } else if (ifa->ifa_family == AF_INET6) {
                memcpy (&(new_addr.address),(struct in6_addr *)RTA_DATA(rth),sizeof(struct in6_addr));
                new_addr.afi = AF_INET6;
            }
            break;
        }
    }
    /* Actions to be done when address is removed */
    lispd_log_msg(LISP_LOG_DEBUG_2,"   deleted address: %s\n", get_char_from_lisp_addr_t(new_addr));
}
Exemplo n.º 14
0
int
main()
{
  struct sockaddr_nl addr;
  int sock, len;
  char buffer[4096];
  struct nlmsghdr *nlh;

  if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
    perror("couldn't open NETLINK_ROUTE socket");
    return 1;
  }

  fprintf(stderr,"socket: f%d\n",sock);
  memset(&addr, 0, sizeof(addr));
  addr.nl_family = AF_NETLINK;
  addr.nl_groups = RTMGRP_IPV4_IFADDR;

  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
    perror("couldn't bind");
    return 1;
  }

  fprintf(stderr,"bound\n");
  nlh = (struct nlmsghdr *)buffer;
  while ((len = recv(sock, nlh, 4096, 0)) > 0) {
    fprintf(stderr,"recv returned %db (%d %s)\n",len,errno,strerror(errno));
    while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) {
      if (nlh->nlmsg_type == RTM_NEWADDR) {
	struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
	struct rtattr *rth = IFA_RTA(ifa);
	int rtl = IFA_PAYLOAD(nlh);

	while (rtl && RTA_OK(rth, rtl)) {
	  if (rth->rta_type == IFA_LOCAL) {
	    uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth)));
	    char name[IFNAMSIZ];
	    if_indextoname(ifa->ifa_index, name);
	    printf("%s is now %d.%d.%d.%d\n",
		   name,
		   (ipaddr >> 24) & 0xff,
		   (ipaddr >> 16) & 0xff,
		   (ipaddr >> 8) & 0xff,
		   ipaddr & 0xff);
	  }
	  rth = RTA_NEXT(rth, rtl);
	}
      }
      nlh = NLMSG_NEXT(nlh, len);
    }
  }
Exemplo n.º 15
0
static void easycwmp_netlink_interface(struct nlmsghdr *nlh)
{
	struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
	struct rtattr *rth = IFA_RTA(ifa);
	int rtl = IFA_PAYLOAD(nlh);
	char if_name[IFNAMSIZ], if_addr[INET_ADDRSTRLEN];
	static old_addr=0;

	memset(&if_name, 0, sizeof(if_name));
	memset(&if_addr, 0, sizeof(if_addr));

	while (rtl && RTA_OK(rth, rtl)) {
		if (rth->rta_type != IFA_LOCAL) {
			rth = RTA_NEXT(rth, rtl);
			continue;
		}

		uint32_t addr = htonl(* (uint32_t *)RTA_DATA(rth));
		if (htonl(13) == 13) {
			// running on big endian system
		} else {
			// running on little endian system
			addr = __bswap_32(addr);
		}

		if_indextoname(ifa->ifa_index, if_name);
		if (strncmp(config->local->interface, if_name, IFNAMSIZ)) {
			rth = RTA_NEXT(rth, rtl);
			continue;
		}

		if ((addr != old_addr) && (old_addr != 0)) {
			log_message(NAME, L_DEBUG, "ip address of the interface %s is changed\n",	if_name);
			cwmp_add_event(EVENT_VALUE_CHANGE, NULL, 0, EVENT_NO_BACKUP);
			cwmp_add_inform_timer();
		}
		old_addr = addr;

		inet_ntop(AF_INET, &(addr), if_addr, INET_ADDRSTRLEN);

		if (config->local) FREE(config->local->ip);
		config->local->ip = strdup(if_addr);
		break;
	}

	if (strlen(if_addr) == 0) return;

	log_message(NAME, L_DEBUG, "interface %s has ip %s\n",
			if_name, if_addr);
}
Exemplo n.º 16
0
/*
 ******************************************************************************
 * dcs_local_ip_monitor_process                                           *//**
 *
 * \brief - Called by the polling thread that gets an indication that the local
 *          IP address has changed. The function sets the Local IP Address in 
 *          the dcs_local_ip variable
 *
 * \param[in] socket - The socket on which the information arrived
 * \param[in] context - NULL
 *
 * \retval DOVE_STATUS_OK
 *
 ******************************************************************************
 */
static int dcs_local_ip_monitor_process(int socket, void *context)
{
	struct nlmsghdr *nlh;
	char buf[4096];
	int len;
	dove_status status = DOVE_STATUS_OK;

	while ((len = recv(dps_monitor_socket, buf, sizeof(buf), 0)) > 0)
	{

		nlh = (struct nlmsghdr *)buf;
		while ((NLMSG_OK(nlh, (uint32_t)len)) && (nlh->nlmsg_type != NLMSG_DONE))
		{
			if (nlh->nlmsg_type == RTM_NEWADDR || nlh->nlmsg_type == RTM_DELADDR)
			{
				struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
				struct rtattr *rth = IFA_RTA(ifa);
				int rtl = IFA_PAYLOAD(nlh);

				while (rtl && RTA_OK(rth, rtl))
				{
					if (rth->rta_type == IFA_LOCAL)
					{
						char ifname[IFNAMSIZ];

						if_indextoname(ifa->ifa_index, ifname);

						if (!strcmp(ifname, SVA_INTERFACE_NAME) && (nlh->nlmsg_type == RTM_NEWADDR))
						{
							status = set_local_ip();
							if (status != DOVE_STATUS_OK)
							{
								log_warn(PythonDataHandlerLogLevel,
								         "Cannot get IP Address of SVA");
								break;
							}
							// Register the Local DPS Node with the Cluster
							dcs_set_service_role(dcs_role_assigned);
						}
					}
					rth = RTA_NEXT(rth, rtl);
				}
			}
			nlh = NLMSG_NEXT(nlh, len);
		}
	}

	return DOVE_STATUS_OK;
}
Exemplo n.º 17
0
/* return true if there is a known address with 'tentative' flag set */
static bool
virNetDevIPParseDadStatus(struct nlmsghdr *nlh, int len,
                          virSocketAddrPtr *addrs, size_t count)
{
    struct ifaddrmsg *ifaddrmsg_ptr;
    unsigned int ifaddrmsg_len;
    struct rtattr *rtattr_ptr;
    size_t i;
    struct in6_addr *addr;

    VIR_WARNINGS_NO_CAST_ALIGN
    for (; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
        VIR_WARNINGS_RESET
        if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifaddrmsg)) {
            /* Message without payload is the last one. */
            break;
        }

        ifaddrmsg_ptr = (struct ifaddrmsg *)NLMSG_DATA(nlh);
        if (!(ifaddrmsg_ptr->ifa_flags & IFA_F_TENTATIVE)) {
            /* Not tentative: we are not interested in this entry. */
            continue;
        }

        ifaddrmsg_len = IFA_PAYLOAD(nlh);
        VIR_WARNINGS_NO_CAST_ALIGN
        rtattr_ptr = (struct rtattr *) IFA_RTA(ifaddrmsg_ptr);
        for (; RTA_OK(rtattr_ptr, ifaddrmsg_len);
            rtattr_ptr = RTA_NEXT(rtattr_ptr, ifaddrmsg_len)) {
            VIR_WARNINGS_RESET
            if (RTA_PAYLOAD(rtattr_ptr) != sizeof(struct in6_addr)) {
                /* No address: ignore. */
                continue;
            }

            /* We check only known addresses. */
            for (i = 0; i < count; i++) {
                addr = &addrs[i]->data.inet6.sin6_addr;
                if (!memcmp(addr, RTA_DATA(rtattr_ptr),
                            sizeof(struct in6_addr))) {
                    /* We found matching tentative address. */
                    return true;
                }
            }
        }
    }
    return false;
}
Exemplo n.º 18
0
static int parse_v4_addr_msg(orc_options_t * options, struct nlmsghdr * nl_msg,
        u32 * ipv4_addr, int * if_index, char ifnam[IFNAMSIZ])
{
    struct ifaddrmsg * ifaddr_msg;
    struct rtattr * attr;
    int rtattr_len;
    int found_addr = 0;
    int found_ifnam = 0;


    ifaddr_msg = (struct ifaddrmsg *) NLMSG_DATA(nl_msg);
    /* extract the first attribute */
    attr = (struct rtattr *) IFA_RTA(ifaddr_msg);
    rtattr_len = IFA_PAYLOAD(nl_msg);

    *if_index = ifaddr_msg->ifa_index;
    if (ifaddr_msg->ifa_family == AF_INET6)
    {
        /* TODO: add IPv6 support */
        orc_debug("Ignoring new IPv6 address: IPv6 unsupported\n");
        return 0;
    }

    /** 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 IFA_ADDRESS:
                memcpy(ipv4_addr, RTA_DATA(attr), sizeof(*ipv4_addr));
                found_addr = 1;     /* probably always there, but... */
                break;
            case IFA_LABEL:
                snprintf(ifnam, IFNAMSIZ, "%s", (char *) RTA_DATA(attr));
                found_ifnam = 1;
                break;
            case IFA_LOCAL:
            case IFA_BROADCAST:
                orc_trace("Intentionally ignoring address update %s - not needed\n",
                    attr->rta_type == IFA_LOCAL? "IFA_LOCAL" : "IFA_BROADCAST");
                break;
            default:
                orc_warn("Skipping unhandled ipv4 address attr: %d\n", attr->rta_type);
        }
    }

    return found_addr && found_ifnam;
}
Exemplo n.º 19
0
static int fill_if_addr(struct if_entry *dest, struct nlmsg_entry *ainfo)
{
    struct if_addr *entry;
    struct nlmsghdr *n;
    struct ifaddrmsg *ifa;
    struct rtattr *rta_tb[IFA_MAX + 1];
    int len, err;

    for (; ainfo; ainfo = ainfo->next) {
        n = &ainfo->h;
        ifa = NLMSG_DATA(n);
        if (ifa->ifa_index != dest->if_index)
            continue;
        if (n->nlmsg_type != RTM_NEWADDR)
            continue;
        len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
        if (len < 0)
            continue;
        if (ifa->ifa_family != AF_INET &&
                ifa->ifa_family != AF_INET6)
            /* only IP addresses supported (at least for now) */
            continue;
        rtnl_parse(rta_tb, IFA_MAX, IFA_RTA(ifa), len);
        if (!rta_tb[IFA_LOCAL] && !rta_tb[IFA_ADDRESS])
            /* don't care about broadcast and anycast adresses */
            continue;

        entry = calloc(sizeof(struct if_addr), 1);
        if (!entry)
            return ENOMEM;

        if (!rta_tb[IFA_LOCAL]) {
            rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
            rta_tb[IFA_ADDRESS] = NULL;
        }
        if ((err = addr_init_netlink(&entry->addr, ifa, rta_tb[IFA_LOCAL])))
            return err;
        if (rta_tb[IFA_ADDRESS] &&
                memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]),
                       ifa->ifa_family == AF_INET ? 4 : 16)) {
            if ((err = addr_init_netlink(&entry->peer, ifa, rta_tb[IFA_ADDRESS])))
                return err;
        }

        list_append(&dest->addr, node(entry));
    }
    return 0;
}
Exemplo n.º 20
0
int main(int argc, const char *argv[])
{
 struct sockaddr_nl addr;
 int nls,len,rtl;
 char buffer[4096];
 struct nlmsghdr *nlh;
 struct ifaddrmsg *ifa;
 struct rtattr *rth;

 if ((nls = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)   perror ("socket failure\n");

 memset (&addr,0,sizeof(addr));
 addr.nl_family = AF_NETLINK;
 //addr.nl_groups = RTMGRP_IPV4_IFADDR;
 addr.nl_groups = RTNLGRP_IPV4_IFADDR;

 if (bind(nls, (struct sockaddr *)&addr, sizeof(addr)) == -1)    perror ("bind failure\n");

 nlh = (struct nlmsghdr *)buffer;
 while ((len = recv (nls,nlh,4096,0)) > 0)
 {
     for (;(NLMSG_OK (nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE); nlh = NLMSG_NEXT(nlh, len))
     {
         if (nlh->nlmsg_type != RTM_NEWADDR) {printf("\nsomething....\n");continue; }/* some other kind of announcement */

         ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh);

         rth = IFA_RTA (ifa);
         rtl = IFA_PAYLOAD (nlh);
         for (;rtl && RTA_OK (rth, rtl); rth = RTA_NEXT (rth,rtl))
         {
             char name[IFNAMSIZ];
             uint32_t ipaddr;

             if (rth->rta_type != IFA_LOCAL) continue;

             ipaddr = * ((uint32_t *)RTA_DATA(rth));
             ipaddr = htonl(ipaddr);

             fprintf (stdout,"%s is now %X\n",if_indextoname(ifa->ifa_index,name),ipaddr);
         }
     }
 }
}
Exemplo n.º 21
0
int TunManager::getAddrRespParser(const struct sockaddr_nl *who,
                                  struct nlmsghdr *n,
                                  void *arg) {
  // only cares about RTM_NEWADDR
  if (n->nlmsg_type != RTM_NEWADDR) {
    return 0;
  }
  struct ifaddrmsg *ifa = static_cast<struct ifaddrmsg *>(NLMSG_DATA(n));
  struct rtattr *tb[IFA_MAX + 1];
  int len = n->nlmsg_len;
  len -= NLMSG_LENGTH(sizeof(*ifa));
  if (len < 0) {
    throw FbossError("Wrong length for RTM_GETADDR response ", len, " vs ",
                     NLMSG_LENGTH(sizeof(*ifa)));
  }
  // only care about v4 and v6 address
  if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
    VLOG(3) << "Skip address from device @ index "
            << static_cast<int>(ifa->ifa_index)
            << " because of its address family "
            << static_cast<int>(ifa->ifa_family);
    return 0;
  }

  parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
  if (tb[IFA_ADDRESS] == nullptr) {
    VLOG(3) << "Device @ index " << static_cast<int>(ifa->ifa_index)
            << " does not have address at family "
            << static_cast<int>(ifa->ifa_family);
    return 0;
  }
  IPAddress addr;
  const void *data = RTA_DATA(tb[IFA_ADDRESS]);
  if (ifa->ifa_family == AF_INET) {
    addr = IPAddress(*static_cast<const in_addr *>(data));
  } else {
    addr = IPAddress(*static_cast<const in6_addr *>(data));
  }

  TunManager *mgr = static_cast<TunManager *>(arg);
  mgr->addProbedAddr(ifa->ifa_index, addr, ifa->ifa_prefixlen);
  return 0;
}
Exemplo n.º 22
0
void process_nl_add_address (struct nlmsghdr *nlh)
{
    struct ifaddrmsg            *ifa                = NULL;
    struct rtattr               *rth                = NULL;
    int                         iface_index         = 0;
    int                         rt_length           = 0;
    lispd_iface_elt             *iface              = NULL;
    lisp_addr_t                 new_addr;
    char                        iface_name[IF_NAMESIZE];

    /*
     * Get the new address from the net link message
     */
    ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh);
    iface_index = ifa->ifa_index;

    iface = get_interface_from_index(iface_index);

    if (iface == NULL){
        if_indextoname(iface_index, iface_name);
        lispd_log_msg(LISP_LOG_DEBUG_2, "process_nl_add_address: the netlink message is not for any interface associated with RLOCs  (%s / %d)",
                iface_name, iface_index);
        return;
    }
    rth = IFA_RTA (ifa);

    rt_length = IFA_PAYLOAD (nlh);
    for (;rt_length && RTA_OK (rth, rt_length); rth = RTA_NEXT (rth,rt_length))
    {
    	if (ifa->ifa_family == AF_INET && rth->rta_type == IFA_LOCAL){
    		memcpy (&(new_addr.address),(struct in_addr *)RTA_DATA(rth),sizeof(struct in_addr));
    		new_addr.afi = AF_INET;
    		process_address_change (iface, new_addr);
    	}
    	if (ifa->ifa_family == AF_INET6 && rth->rta_type == IFA_ADDRESS){
    		memcpy (&(new_addr.address),(struct in6_addr *)RTA_DATA(rth),sizeof(struct in6_addr));
    		new_addr.afi = AF_INET6;
    		process_address_change (iface, new_addr);
    	}
    }
}
Exemplo n.º 23
0
/**
 * returns non-local addresses for specified interface
 */
void ipaddr_global_get(int *count, char **bufPtr, int ifindex, struct nlmsg_list *ainfo) {
    int cnt=0;
    char * buf=0, * tmpbuf=0;
    char addr[16];
    struct rtattr * rta_tb[IFA_MAX+1];
    int pos;

    for ( ;ainfo ;  ainfo = ainfo->next) {
	struct nlmsghdr *n = &ainfo->h;
	struct ifaddrmsg *ifa = NLMSG_DATA(n);
	if ( (ifa->ifa_family == AF_INET6) && (ifa->ifa_index == ifindex) ) {
	    memset(rta_tb, 0, sizeof(*rta_tb));
	    parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
	    if (!rta_tb[IFA_LOCAL])   rta_tb[IFA_LOCAL]   = rta_tb[IFA_ADDRESS];
	    if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
	    
	    memcpy(addr,(char*)RTA_DATA(rta_tb[IFLA_ADDRESS]),16);
	    if ( (addr[0]==0xfe && addr[1]==0x80) || /* link local */
		 (addr[0]==0xff) ) { /* multicast */
		continue; /* ignore non link-scoped addrs */
	    }
	    
	    /* ifa->ifa_flags & 128 - permenent */
	    /* printf("flags:%d : ",ifa->ifa_flags); */

	    pos = cnt*16;
	    buf = (char*) malloc( pos + 16);
            if (pos > 0) {
                memcpy(buf,tmpbuf, pos); /* copy old addrs */
            }
	    memcpy(buf+pos,addr,16); /* copy new addr */
	    if (pos > 0) {
                free(tmpbuf);
            }
	    tmpbuf = buf;
	    cnt++;
	}
    }
    *count = cnt;
    *bufPtr = buf;
}
Exemplo n.º 24
0
static int rtnl_ifaddr_get(struct nlmsghdr *h, 
			   int (*if_callback)(int, struct in_ifaddr *))
{
	struct rtattr *tb[IFA_MAX + 1];
	struct ifaddrmsg *ifaddr;
	int len;
	
	struct in_ifaddr in_ifaddr;
	
	if (h->nlmsg_type != RTM_NEWADDR)
		return 0;
	
	ifaddr = NLMSG_DATA(h);
	
	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	if (len < 0)
		return -1;

	netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifaddr), len);
	
	strcpy(in_ifaddr.ifa_label, (char *)RTA_DATA(tb[IFA_LABEL]));
	
	in_ifaddr.ifa_address	= *(uint32_t *)RTA_DATA(tb[IFA_ADDRESS]);
	in_ifaddr.ifa_local	= *(uint32_t *)RTA_DATA(tb[IFA_LOCAL]);
	
	if (tb[IFA_BROADCAST]) 
		in_ifaddr.ifa_broadcast	= *(uint32_t *)RTA_DATA(tb[IFA_BROADCAST]);
	
	if (tb[IFA_ANYCAST])
		in_ifaddr.ifa_anycast = *(uint32_t *)RTA_DATA(tb[IFA_ANYCAST]);

	in_ifaddr.ifa_family	= ifaddr->ifa_family;
	in_ifaddr.ifa_prefixlen = ifaddr->ifa_prefixlen;
	
	in_ifaddr.ifa_flags 	= ifaddr->ifa_flags;
	in_ifaddr.ifa_scope	= ifaddr->ifa_scope;
	
	return if_callback(ifaddr->ifa_index, &in_ifaddr);
}
Exemplo n.º 25
0
/****************************************************************
 NAME	: print_addr				00/06/02 18:24:09
 AIM	: 
 REMARK	:
****************************************************************/
static int get_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct ifaddrmsg *ifa 	= NLMSG_DATA(n);
	int		len	= n->nlmsg_len;
	iplist_ctx	*ctx	= (iplist_ctx *)arg;
	struct rtattr 	*rta_tb[IFA_MAX+1];
	/* sanity check */
	len -= NLMSG_LENGTH(sizeof(*ifa));
	if (len < 0) {
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
		return -1;
	}
	/* check the message type */
	if (n->nlmsg_type != RTM_NEWADDR )
		return 0;
	/* check it is ipv4 */
	if( ifa->ifa_family != AF_INET)
		return 0;
	/* check it is the good interface */
	if( ifa->ifa_index != ctx->ifindex )
		return 0;
		
	/* parse the attribute */
	memset(rta_tb, 0, sizeof(rta_tb));
	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), len);

	if (!rta_tb[IFA_LOCAL])
		rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];

	if (rta_tb[IFA_LOCAL]) {
		u_char *src = RTA_DATA(rta_tb[IFA_LOCAL]);
		if( ctx->nb_elem >= ctx->max_elem )
			return 0;
		ctx->addr[ctx->nb_elem++] = 	(src[0]<<24) + (src[1]<<16) +
						(src[2]<<8) + src[3];
	}
	return 0;
}
Exemplo n.º 26
0
/* function: getaddr_cb
 * callback for getinterface_ip
 * msg  - netlink message
 * data - (struct target) info for which address we're looking for
 */
static int getaddr_cb(struct nl_msg *msg, void *data) {
  struct ifaddrmsg *ifa_p;
  struct rtattr *rta_p;
  int rta_len;
  struct target *targ_p = (struct target *)data;

  ifa_p = (struct ifaddrmsg *)nlmsg_data(nlmsg_hdr(msg));
  rta_p = (struct rtattr *)IFA_RTA(ifa_p);

  if(ifa_p->ifa_index != targ_p->ifindex)
    return NL_OK;

  if(ifa_p->ifa_scope != RT_SCOPE_UNIVERSE)
    return NL_OK;

  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 IFA_ADDRESS:
        if((targ_p->family == AF_INET6) && !(ifa_p->ifa_flags & IFA_F_SECONDARY)) {
          memcpy(&targ_p->ip.ip6, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
          targ_p->foundip = 1;
          return NL_OK;
        }
        break;
      case IFA_LOCAL:
        if(targ_p->family == AF_INET) {
          memcpy(&targ_p->ip.ip4, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
          targ_p->foundip = 1;
          return NL_OK;
        }
        break;
    }
  }

  return NL_OK;
}
Exemplo n.º 27
0
    void dispatch_ifaddr_v6(Tag, struct ifaddrmsg * ifa, std::size_t len)
    {
        acqua::network::internet6_address addr;
        std::string label;
        uint prefixlen = ifa->ifa_prefixlen;
        uint flags = ifa->ifa_flags;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"

        for(auto * rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
            switch(rta->rta_type) {
                case IFA_ADDRESS:
                    addr = addr.from_voidptr(RTA_DATA(rta));
                    break;
                case IFA_LABEL:
                    label = static_cast<char const *>(RTA_DATA(rta));
                    break;
            }
        }

#pragma GCC diagnostic pop
        static_cast<Derived *>(this)->on_ifaddr(addr, label, prefixlen, flags);
    }
Exemplo n.º 28
0
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
		   void *arg)
{
	FILE *fp = arg;
	struct ifaddrmsg *ifa = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	int deprecated = 0;
	/* Use local copy of ifa_flags to not interfere with filtering code */
	unsigned int ifa_flags;
	struct rtattr * rta_tb[IFA_MAX+1];
	char abuf[256];
	SPRINT_BUF(b1);

	if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
		return 0;
	len -= NLMSG_LENGTH(sizeof(*ifa));
	if (len < 0) {
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
		return -1;
	}

	if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
		return 0;

	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
		     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

	ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]);

	if (!rta_tb[IFA_LOCAL])
		rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
	if (!rta_tb[IFA_ADDRESS])
		rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];

	if (filter.ifindex && filter.ifindex != ifa->ifa_index)
		return 0;
	if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
		return 0;
	if ((filter.flags ^ ifa_flags) & filter.flagmask)
		return 0;
	if (filter.label) {
		SPRINT_BUF(b1);
		const char *label;
		if (rta_tb[IFA_LABEL])
			label = RTA_DATA(rta_tb[IFA_LABEL]);
		else
			label = ll_idx_n2a(ifa->ifa_index, b1);
		if (fnmatch(filter.label, label, 0) != 0)
			return 0;
	}
	if (filter.pfx.family) {
		if (rta_tb[IFA_LOCAL]) {
			inet_prefix dst;
			memset(&dst, 0, sizeof(dst));
			dst.family = ifa->ifa_family;
			memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
			if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
				return 0;
		}
	}

	if (filter.family && filter.family != ifa->ifa_family)
		return 0;

	if (filter.flushb) {
		struct nlmsghdr *fn;
		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
			if (flush_update())
				return -1;
		}
		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
		memcpy(fn, n, n->nlmsg_len);
		fn->nlmsg_type = RTM_DELADDR;
		fn->nlmsg_flags = NLM_F_REQUEST;
		fn->nlmsg_seq = ++rth.seq;
		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
		filter.flushed++;
		if (show_stats < 2)
			return 0;
	}

	if (n->nlmsg_type == RTM_DELADDR)
		fprintf(fp, "Deleted ");

	if (filter.oneline || filter.flushb)
		fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
	if (ifa->ifa_family == AF_INET)
		fprintf(fp, "    inet ");
	else if (ifa->ifa_family == AF_INET6)
		fprintf(fp, "    inet6 ");
	else if (ifa->ifa_family == AF_DECnet)
		fprintf(fp, "    dnet ");
	else if (ifa->ifa_family == AF_IPX)
		fprintf(fp, "     ipx ");
	else
		fprintf(fp, "    family %d ", ifa->ifa_family);

	if (rta_tb[IFA_LOCAL]) {
		if (ifa->ifa_family == AF_INET)
			color_fprintf(fp, COLOR_INET, "%s", format_host(ifa->ifa_family,
						RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
						RTA_DATA(rta_tb[IFA_LOCAL]),
						abuf, sizeof(abuf)));
		else if (ifa->ifa_family == AF_INET6)
			color_fprintf(fp, COLOR_INET6, "%s", format_host(ifa->ifa_family,
						RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
						RTA_DATA(rta_tb[IFA_LOCAL]),
						abuf, sizeof(abuf)));
		else
			fprintf(fp, "%s", format_host(ifa->ifa_family,
						RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
						RTA_DATA(rta_tb[IFA_LOCAL]),
						abuf, sizeof(abuf)));

		if (rta_tb[IFA_ADDRESS] == NULL ||
		    memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]),
			   ifa->ifa_family == AF_INET ? 4 : 16) == 0) {
			fprintf(fp, "/%d ", ifa->ifa_prefixlen);
		} else {
			fprintf(fp, " peer %s/%d ",
				format_host(ifa->ifa_family,
					    RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
					    RTA_DATA(rta_tb[IFA_ADDRESS]),
					    abuf, sizeof(abuf)),
				ifa->ifa_prefixlen);
		}
	}

	if (rta_tb[IFA_BROADCAST]) {
		fprintf(fp, "brd %s ",
			format_host(ifa->ifa_family,
				    RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
				    RTA_DATA(rta_tb[IFA_BROADCAST]),
				    abuf, sizeof(abuf)));
	}
	if (rta_tb[IFA_ANYCAST]) {
		fprintf(fp, "any %s ",
			format_host(ifa->ifa_family,
				    RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
				    RTA_DATA(rta_tb[IFA_ANYCAST]),
				    abuf, sizeof(abuf)));
	}
	fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
	if (ifa_flags & IFA_F_SECONDARY) {
		ifa_flags &= ~IFA_F_SECONDARY;
		if (ifa->ifa_family == AF_INET6)
			fprintf(fp, "temporary ");
		else
			fprintf(fp, "secondary ");
	}
	if (ifa_flags & IFA_F_TENTATIVE) {
		ifa_flags &= ~IFA_F_TENTATIVE;
		fprintf(fp, "tentative ");
	}
	if (ifa_flags & IFA_F_DEPRECATED) {
		ifa_flags &= ~IFA_F_DEPRECATED;
		deprecated = 1;
		fprintf(fp, "deprecated ");
	}
	if (ifa_flags & IFA_F_HOMEADDRESS) {
		ifa_flags &= ~IFA_F_HOMEADDRESS;
		fprintf(fp, "home ");
	}
	if (ifa_flags & IFA_F_NODAD) {
		ifa_flags &= ~IFA_F_NODAD;
		fprintf(fp, "nodad ");
	}
	if (ifa_flags & IFA_F_MANAGETEMPADDR) {
		ifa_flags &= ~IFA_F_MANAGETEMPADDR;
		fprintf(fp, "mngtmpaddr ");
	}
	if (ifa_flags & IFA_F_NOPREFIXROUTE) {
		ifa_flags &= ~IFA_F_NOPREFIXROUTE;
		fprintf(fp, "noprefixroute ");
	}
	if (ifa_flags & IFA_F_MCAUTOJOIN) {
		ifa_flags &= ~IFA_F_MCAUTOJOIN;
		fprintf(fp, "autojoin ");
	}
	if (!(ifa_flags & IFA_F_PERMANENT)) {
		fprintf(fp, "dynamic ");
	} else
		ifa_flags &= ~IFA_F_PERMANENT;
	if (ifa_flags & IFA_F_DADFAILED) {
		ifa_flags &= ~IFA_F_DADFAILED;
		fprintf(fp, "dadfailed ");
	}
	if (ifa_flags)
		fprintf(fp, "flags %02x ", ifa_flags);
	if (rta_tb[IFA_LABEL])
		fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL]));
	if (rta_tb[IFA_CACHEINFO]) {
		struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "       valid_lft ");
		if (ci->ifa_valid == INFINITY_LIFE_TIME)
			fprintf(fp, "forever");
		else
			fprintf(fp, "%usec", ci->ifa_valid);
		fprintf(fp, " preferred_lft ");
		if (ci->ifa_prefered == INFINITY_LIFE_TIME)
			fprintf(fp, "forever");
		else {
			if (deprecated)
				fprintf(fp, "%dsec", ci->ifa_prefered);
			else
				fprintf(fp, "%usec", ci->ifa_prefered);
		}
	}
	fprintf(fp, "\n");
	fflush(fp);
	return 0;
}
Exemplo n.º 29
0
static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
{
	struct nlmsg_list *l, **lp;

	lp = &linfo->head;
	while ( (l = *lp) != NULL) {
		int ok = 0;
		int missing_net_address = 1;
		struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
		struct nlmsg_list *a;

		for (a = ainfo->head; a; a = a->next) {
			struct nlmsghdr *n = &a->h;
			struct ifaddrmsg *ifa = NLMSG_DATA(n);
			struct rtattr *tb[IFA_MAX + 1];
			unsigned int ifa_flags;

			if (ifa->ifa_index != ifi->ifi_index)
				continue;
			missing_net_address = 0;
			if (filter.family && filter.family != ifa->ifa_family)
				continue;
			if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
				continue;

			parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
			ifa_flags = get_ifa_flags(ifa, tb[IFA_FLAGS]);

			if ((filter.flags ^ ifa_flags) & filter.flagmask)
				continue;
			if (filter.pfx.family || filter.label) {
				if (!tb[IFA_LOCAL])
					tb[IFA_LOCAL] = tb[IFA_ADDRESS];

				if (filter.pfx.family && tb[IFA_LOCAL]) {
					inet_prefix dst;
					memset(&dst, 0, sizeof(dst));
					dst.family = ifa->ifa_family;
					memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
					if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
						continue;
				}
				if (filter.label) {
					SPRINT_BUF(b1);
					const char *label;
					if (tb[IFA_LABEL])
						label = RTA_DATA(tb[IFA_LABEL]);
					else
						label = ll_idx_n2a(ifa->ifa_index, b1);
					if (fnmatch(filter.label, label, 0) != 0)
						continue;
				}
			}

			ok = 1;
			break;
		}
		if (missing_net_address &&
		    (filter.family == AF_UNSPEC || filter.family == AF_PACKET))
			ok = 1;
		if (!ok) {
			*lp = l->next;
			free(l);
		} else
			lp = &l->next;
	}
}
Exemplo n.º 30
0
/* Return value becomes exitcode. It's okay to not return at all */
int ipaddr_list_or_flush(int argc, char **argv, int flush)
{
	static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0";

	struct nlmsg_list *linfo = NULL;
	struct nlmsg_list *ainfo = NULL;
	struct nlmsg_list *l;
	struct rtnl_handle rth;
	char *filter_dev = NULL;
	int no_link = 0;

	ipaddr_reset_filter(oneline);
	filter.showqueue = 1;

	if (filter.family == AF_UNSPEC)
		filter.family = preferred_family;

	if (flush) {
		if (argc <= 0) {
			bb_error_msg_and_die(bb_msg_requires_arg, "flush");
		}
		if (filter.family == AF_PACKET) {
			bb_error_msg_and_die("cannot flush link addresses");
		}
	}

	while (argc > 0) {
		const int option_num = index_in_strings(option, *argv);
		switch (option_num) {
			case 0: /* to */
				NEXT_ARG();
				get_prefix(&filter.pfx, *argv, filter.family);
				if (filter.family == AF_UNSPEC) {
					filter.family = filter.pfx.family;
				}
				break;
			case 1: /* scope */
			{
				uint32_t scope = 0;
				NEXT_ARG();
				filter.scopemask = -1;
				if (rtnl_rtscope_a2n(&scope, *argv)) {
					if (strcmp(*argv, "all") != 0) {
						invarg(*argv, "scope");
					}
					scope = RT_SCOPE_NOWHERE;
					filter.scopemask = 0;
				}
				filter.scope = scope;
				break;
			}
			case 2: /* up */
				filter.up = 1;
				break;
			case 3: /* label */
				NEXT_ARG();
				filter.label = *argv;
				break;
			case 4: /* dev */
				NEXT_ARG();
			default:
				if (filter_dev) {
					duparg2("dev", *argv);
				}
				filter_dev = *argv;
		}
		argv++;
		argc--;
	}

	xrtnl_open(&rth);

	xrtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK);
	xrtnl_dump_filter(&rth, store_nlmsg, &linfo);

	if (filter_dev) {
		filter.ifindex = xll_name_to_index(filter_dev);
	}

	if (flush) {
		char flushb[4096-512];

		filter.flushb = flushb;
		filter.flushp = 0;
		filter.flushe = sizeof(flushb);
		filter.rth = &rth;

		for (;;) {
			xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR);
			filter.flushed = 0;
			xrtnl_dump_filter(&rth, print_addrinfo, stdout);
			if (filter.flushed == 0) {
				return 0;
			}
			if (flush_update() < 0)
				return 1;
		}
	}

	if (filter.family != AF_PACKET) {
		xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR);
		xrtnl_dump_filter(&rth, store_nlmsg, &ainfo);
	}


	if (filter.family && filter.family != AF_PACKET) {
		struct nlmsg_list **lp;
		lp=&linfo;

		if (filter.oneline)
			no_link = 1;

		while ((l=*lp)!=NULL) {
			int ok = 0;
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			struct nlmsg_list *a;

			for (a=ainfo; a; a=a->next) {
				struct nlmsghdr *n = &a->h;
				struct ifaddrmsg *ifa = NLMSG_DATA(n);

				if (ifa->ifa_index != ifi->ifi_index ||
				    (filter.family && filter.family != ifa->ifa_family))
					continue;
				if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
					continue;
				if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
					continue;
				if (filter.pfx.family || filter.label) {
					struct rtattr *tb[IFA_MAX+1];
					memset(tb, 0, sizeof(tb));
					parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
					if (!tb[IFA_LOCAL])
						tb[IFA_LOCAL] = tb[IFA_ADDRESS];

					if (filter.pfx.family && tb[IFA_LOCAL]) {
						inet_prefix dst;
						memset(&dst, 0, sizeof(dst));
						dst.family = ifa->ifa_family;
						memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
						if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
							continue;
					}
					if (filter.label) {
						SPRINT_BUF(b1);
						const char *label;
						if (tb[IFA_LABEL])
							label = RTA_DATA(tb[IFA_LABEL]);
						else
							label = ll_idx_n2a(ifa->ifa_index, b1);
						if (fnmatch(filter.label, label, 0) != 0)
							continue;
					}
				}

				ok = 1;
				break;
			}
			if (!ok)
				*lp = l->next;
			else
				lp = &l->next;
		}
	}

	for (l = linfo; l; l = l->next) {
		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
			if (filter.family != AF_PACKET)
				print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
		}
		fflush(stdout); /* why? */
	}

	return 0;
}