示例#1
0
static void rtnl_print_route(struct nlmsghdr *hdr)
{
	struct rtmsg *rtm = NLMSG_DATA(hdr);
	uint32_t attrs_len = RTM_PAYLOAD(hdr);
	struct rtattr *attr = RTM_RTA(rtm);
	struct rta_cacheinfo *ci;
	int hz = get_user_hz();
	char addr_str[256];
	char flags[256];

	tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
			colorize_start(bold),
			addr_family2str(rtm->rtm_family),
			colorize_end());
	tprintf(", Dst Len %d", rtm->rtm_dst_len);
	tprintf(", Src Len %d", rtm->rtm_src_len);
	tprintf(", ToS %d", rtm->rtm_tos);
	tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
			colorize_start(bold),
			route_table2str(rtm->rtm_table),
			colorize_end());
	tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
			colorize_start(bold),
			route_proto2str(rtm->rtm_protocol),
			colorize_end());
	tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
			colorize_start(bold),
			scope2str(rtm->rtm_scope),
			colorize_end());
	tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
			colorize_start(bold),
			route_type2str(rtm->rtm_type),
			colorize_end());
	tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
			colorize_start(bold),
			flags2str(route_flags, rtm->rtm_flags, flags,
				sizeof(flags)),
			colorize_end());

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case RTA_DST:
			attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_SRC:
			attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_IIF:
			attr_fmt(attr, "Iif %d", RTA_INT(attr));
			break;
		case RTA_OIF:
			attr_fmt(attr, "Oif %d", RTA_INT(attr));
			break;
		case RTA_GATEWAY:
			attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_PRIORITY:
			attr_fmt(attr, "Priority %u", RTA_UINT32(attr));
			break;
		case RTA_PREFSRC:
			attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case RTA_MARK:
			attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
			break;
		case RTA_FLOW:
			attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
			break;
		case RTA_TABLE:
			attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
				colorize_start(bold),
				route_table2str(RTA_UINT32(attr)),
				colorize_end());
			break;
		case RTA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");
			tprintf("expires(%ds)", ci->rta_expires / hz);
			tprintf(", error(%d)", ci->rta_error);
			tprintf(", users(%d)", ci->rta_clntref);
			tprintf(", used(%d)", ci->rta_used);
			tprintf(", last use(%ds)", ci->rta_lastuse / hz);
			tprintf(", id(%d)", ci->rta_id);
			tprintf(", ts(%d)", ci->rta_ts);
			tprintf(", ts age(%ds))", ci->rta_tsage);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}
示例#2
0
文件: get-bind.c 项目: LazyZhu/srelay
int get_bind_addr(bin_addr *dest, struct addrinfo *ba)
{
  int s;
  int len;
  struct rtattr *rta;
  struct {
    struct nlmsghdr         n;
    struct rtmsg            r;
    char                    buf[1024];
  } rreq;

  int status;
  unsigned seq;
  struct nlmsghdr *h;
  struct sockaddr_nl nladdr;
  struct iovec iov;
  char   buf[8192];
  struct msghdr msg = {
    (void*)&nladdr, sizeof(nladdr),
    &iov,   1,
    NULL,   0,
    0
  };
  pid_t pid;
  struct rtattr * tb[RTA_MAX+1];
  struct rtmsg *r;
  struct sockaddr_in *sin;
  struct in_addr      ia;

  struct addrinfo hints, *res, *res0;
  int    error;
  char   host[256];
  int found = 0;
  unsigned *d;

  /* IPv6 routing is not implemented yet */
  switch (dest->atype) {
  case S5ATIPV4:
    memcpy(&ia, &(dest->v4_addr), 4);
    break;
  case S5ATIPV6:
    return -1;
  case S5ATFQDN:
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_INET;
    memcpy(host, &dest->fqdn, dest->len_fqdn);
    host[dest->len_fqdn] = '\0';
    error = getaddrinfo(host, NULL, &hints, &res0);
    if (error) {
      return -1;
    }
    for (res = res0; res; res = res->ai_next) {
      if (res->ai_family != AF_INET)
	continue;
      sin = (struct sockaddr_in *)res->ai_addr;
      memcpy(&ia, &(sin->sin_addr), sizeof(ia));
      found++; break;
    }
    freeaddrinfo(res0);
    if (!found)
      return -1;
    break;
  default:
    return -1;
  }

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

  rreq.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  rreq.n.nlmsg_flags = NLM_F_REQUEST;
  rreq.n.nlmsg_type = RTM_GETROUTE;
  rreq.r.rtm_family = AF_INET;

  len = RTA_LENGTH(4);
  if (NLMSG_ALIGN(rreq.n.nlmsg_len) + len > sizeof(rreq))
    return(-1);
  rta = (struct rtattr*)((char *)&rreq.n + NLMSG_ALIGN(rreq.n.nlmsg_len));
  rta->rta_type = RTA_DST;
  rta->rta_len = len;
  memcpy(RTA_DATA(rta), &ia, 4);
  rreq.n.nlmsg_len = NLMSG_ALIGN(rreq.n.nlmsg_len) + len;
  rreq.r.rtm_dst_len = 32;  /* 32 bit */

  s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);

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

  rreq.n.nlmsg_seq = seq = 9999;

  iov.iov_base = (void*)&rreq.n;
  iov.iov_len  = rreq.n.nlmsg_len;

  status = sendmsg(s, &msg, 0);

  if (status < 0) {
    /* perror("Cannot talk to rtnetlink"); */
    return -1;
  }

  pid = getpid();
  iov.iov_base = buf;
  do {
    iov.iov_len = sizeof(buf);
    status = recvmsg(s, &msg, 0);
    h = (struct nlmsghdr*)buf;
  } while (h->nlmsg_pid != pid || h->nlmsg_seq != seq);

  close(s);
  /*
  msg_out(norm,"nlmsg_pid: %d, nlmsg_seq: %d",
	  h->nlmsg_pid, h->nlmsg_seq);
  */
  len = h->nlmsg_len;
  r = NLMSG_DATA(buf);
  rta = RTM_RTA(r);
  while (RTA_OK(rta, len)) {
    if (rta->rta_type <= RTA_MAX)
      tb[rta->rta_type] = rta;
    rta = RTA_NEXT(rta,len);
  }
  /*
  if (tb[RTA_DST]) {
    inet_ntop(AF_INET, RTA_DATA(tb[RTA_DST]), str, sizeof(str));
    msg_out(norm, "DST %s", str);
  }
  if (tb[RTA_GATEWAY]) {
    inet_ntop(AF_INET, RTA_DATA(tb[RTA_GATEWAY]), str, sizeof(str));
    msg_out(norm, "GW %s", str);
  }
  */
  if (tb[RTA_OIF]) {
    d = RTA_DATA(tb[RTA_OIF]);
    return(get_ifconf(*d, ba));
  }
  return(-1);
}
示例#3
0
static int process_nlmsg(struct nlmsghdr *n) {
    assert(n);

    if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
        /* A link appeared or was removed */

        struct ifinfomsg *ifi;
        ifi = NLMSG_DATA(n);

        if (ifi->ifi_family != AF_UNSPEC || (int) ifi->ifi_index != ifindex)
            return 0;
        
        if (n->nlmsg_type == RTM_DELLINK) {
            daemon_log(LOG_ERR, "Interface vanished.");
            return -1;
        }

        assert(n->nlmsg_type == RTM_NEWLINK);
        
        if ((ifi->ifi_flags & IFF_LOOPBACK) ||
            (ifi->ifi_flags & IFF_NOARP) ||
            ifi->ifi_type != ARPHRD_ETHER) {
            daemon_log(LOG_ERR, "Interface not suitable.");
            return -1;
        }

    } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {

        /* An address was added or removed */

        struct rtattr *a = NULL;
        struct ifaddrmsg *ifa;
        int l;
        uint32_t address = 0;
        Address *i;
        
        ifa = NLMSG_DATA(n);

        if (ifa->ifa_family != AF_INET || (int) ifa->ifa_index != ifindex)
            return 0;

        l = NLMSG_PAYLOAD(n, sizeof(*ifa));
        a = IFLA_RTA(ifa);

        while(RTA_OK(a, l)) {

            switch(a->rta_type) {
                case IFA_LOCAL:
                case IFA_ADDRESS:
                    assert(RTA_PAYLOAD(a) == 4);
                    memcpy(&address, RTA_DATA(a), sizeof(uint32_t));
                    break;
            }
            
            a = RTA_NEXT(a, l);
        }

        if (!address || is_ll_address(address))
            return 0;

        for (i = addresses; i; i = i->addresses_next)
            if (i->address == address)
                break;

        if (n->nlmsg_type == RTM_DELADDR && i) {
            AVAHI_LLIST_REMOVE(Address, addresses, addresses, i);
            avahi_free(i);
        } if (n->nlmsg_type == RTM_NEWADDR && !i) {
            i = avahi_new(Address, 1);
            i->address = address;
            AVAHI_LLIST_PREPEND(Address, addresses, addresses, i);
        }
    }

    return 0;
}
示例#4
0
文件: ifaddrs.c 项目: Altiscale/lxc
static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
    struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);

    size_t l_nameSize = 0;
    size_t l_addrSize = 0;

    int l_addedNetmask = 0;

    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
    struct rtattr *l_rta;
    for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        if(l_info->ifa_family == AF_PACKET)
        {
            continue;
        }

        switch(l_rta->rta_type)
        {
            case IFA_ADDRESS:
            case IFA_LOCAL:
                if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
                { // make room for netmask
                    l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
                    l_addedNetmask = 1;
                }
            case IFA_BROADCAST:
                l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
                break;
            case IFA_LABEL:
                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
                break;
            default:
                break;
        }
    }

    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
    memset(l_entry, 0, sizeof(struct ifaddrs));
    l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;

    char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
    char *l_addr = l_name + l_nameSize;

    l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
    for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        void *l_rtaData = RTA_DATA(l_rta);
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
            case IFA_ADDRESS:
            case IFA_BROADCAST:
            case IFA_LOCAL:
            {
                size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
                makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
                if(l_info->ifa_family == AF_INET6)
                {
                    if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
                    {
                        ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
                    }
                }

                if(l_rta->rta_type == IFA_ADDRESS)
                { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
                    if(l_entry->ifa_addr)
                    {
                        l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
                    }
                    else
                    {
                        l_entry->ifa_addr = (struct sockaddr *)l_addr;
                    }
                }
                else if(l_rta->rta_type == IFA_LOCAL)
                {
                    if(l_entry->ifa_addr)
                    {
                        l_entry->ifa_dstaddr = l_entry->ifa_addr;
                    }
                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
                }
                else
                {
                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
                }
                l_addr += NLMSG_ALIGN(l_addrLen);
                break;
            }
            case IFA_LABEL:
                strncpy(l_name, l_rtaData, l_rtaDataSize);
                l_name[l_rtaDataSize] = '\0';
                l_entry->ifa_name = l_name;
                break;
            default:
                break;
        }
    }

    if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
    {
        unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
        unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
        char l_mask[16] = {0};
        unsigned i;
        for(i=0; i<(l_prefix/8); ++i)
        {
            l_mask[i] = 0xff;
        }
        l_mask[i] = 0xff << (8 - (l_prefix % 8));

        makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
        l_entry->ifa_netmask = (struct sockaddr *)l_addr;
    }

    addToEnd(p_resultList, l_entry);
}
示例#5
0
/**
 * @brief Handle an RTM_NEWLINK message from the driver, generating the
 *        appropriate events from it.
 *
 * @param [in] state  the internal state for this instance
 * @param [in] hdr  the netlink message header; the length field has
 *                  already been validated
 * @param [in] payloadLen  the length of the payload (not including the
 *                         netlink header)
 */
static void wlanifLinkEventsHandleNewLink(wlanifLinkEventsHandle_t state,
                                          const struct nlmsghdr *hdr,
                                          u_int32_t payloadLen) {
    const struct ifinfomsg *ifaceInfo = NLMSG_DATA(hdr);

    size_t ifaceLen = NLMSG_ALIGN(sizeof(*ifaceInfo));
    if (payloadLen < ifaceLen) {
        dbgf(state->dbgModule, DBGERR, "%s: Malformed netlink payload "
                                       "length %u", __func__, payloadLen);
        return;
    }

    wlanif_band_e band =
        wlanifBSteerControlResolveBandFromSystemIndex(state->bsteerControlHandle,
                                                      ifaceInfo->ifi_index);
    if (wlanif_band_invalid == band) {
        dbgf(state->dbgModule, DBGDUMP,
             "%s: Received message from ifindex %u not managed by lbd",
             __func__, ifaceInfo->ifi_index);
        return;
    }

    const struct rtattr *attr = IFLA_RTA(ifaceInfo);
    const size_t RTATTR_LEN = RTA_ALIGN(sizeof(*attr));

    // This will keep track of the amount of data remaining in the payload
    // for the RT attributes.
    size_t attrLen = payloadLen - ifaceLen;

    // Iterate over all of the RT attributes, looking for a wireless one
    // and then dispatch to a separate function to parse the event.
    while (RTA_OK(attr, attrLen)) {
        const u_int8_t *data =
            ((const u_int8_t *) attr) + RTATTR_LEN;
        switch (attr->rta_type) {
            case IFLA_WIRELESS:
            {
                wlanifLinkEventsHandleIWEvent(state, data,
                                              attr->rta_len - RTATTR_LEN,
                                              band, ifaceInfo->ifi_index);
                break;
            }

            case IFLA_OPERSTATE:
            {
                wlanifLinkEventsHandleOperState(state, data,
                                                attr->rta_len - RTATTR_LEN,
                                                band, ifaceInfo->ifi_index);
                break;
            }

            default:
            {
                // Nop (other than a log)
                dbgf(state->dbgModule, DBGDUMP,
                     "%s: Unhandled attribute: type=%04x len=%u",
                     __func__, attr->rta_type, attr->rta_len);
                break;
            }
        }

        attr = RTA_NEXT(attr, attrLen);
    }

    if (attrLen != 0) {
        dbgf(state->dbgModule, DBGERR, "%s: Did not consume all attributes: %u bytes left",
             __func__, attrLen);
    }
}
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;
}
示例#7
0
int reportRoutinTable( int route_sock, FILE * fpRouting , struct timespec tv , char * ifNameVar)
{
	int i,j;
	route_request *request = (route_request *)malloc(sizeof(route_request));
	int retValue = -1,nbytes = 0,reply_len = 0;
	char reply_ptr[1024];
	ssize_t counter = 1024;
	// int count 		= 0;
	struct rtmsg *rtp;
	struct rtattr *rtap;
	struct nlmsghdr *nlp;
	int rtl;
	struct RouteInfo route[24];
	char* buf = reply_ptr;
	unsigned long bufsize ;
	char * outputRouting ;
    outputRouting = (char *)malloc(sizeof(char) * 1024);

	   
	bzero(request,sizeof(route_request));

	// Fill in the NETLINK header
	request->nlMsgHdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	request->nlMsgHdr.nlmsg_type = RTM_GETROUTE;
	request->nlMsgHdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;

	// set the routing message header
	request->rtMsg.rtm_family = AF_INET;
	request->rtMsg.rtm_table = 254; 

	// Send routing request
	if ((retValue = send(route_sock, request, sizeof(route_request), 0)) < 0)
	{
		perror("send");
		exit(1);
	}

	for(;;)
	{
		if( counter < sizeof( struct nlmsghdr))
		{
			printf("Routing table is bigger than 1024\n");
			exit(1);
		}

		nbytes = recv(route_sock, &reply_ptr[reply_len], counter, 0);

		if(nbytes < 0 )
		{
			printf("Error in recv\n");
			break;
		}
	
		if(nbytes == 0)
			printf("EOF in netlink\n");

		nlp = (struct nlmsghdr*)(&reply_ptr[reply_len]);

		if (nlp->nlmsg_type == NLMSG_DONE)
		{
	// All data has been received.
	// Truncate the reply to exclude this message,
	// i.e. do not increase reply_len.
		break;
		}

		if (nlp->nlmsg_type == NLMSG_ERROR)
		{
		printf("Error in msg\n");
		exit(1);
		}

		reply_len += nbytes;
		counter -= nbytes;
	}

	/*======================================================*/
	bufsize = reply_len;
	// string to hold content of the route
	// table (i.e. one entry)
	// unsigned int flags;

	// outer loop: loops thru all the NETLINK
	// headers that also include the route entry
	// header
	nlp = (struct nlmsghdr *) buf;

	for(i= -1; NLMSG_OK(nlp, bufsize); nlp=NLMSG_NEXT(nlp, bufsize))
	{
	// 	// get route entry header
		rtp = (struct rtmsg *) NLMSG_DATA(nlp);
		// we are only concerned about the
		// tableId route table
		if(rtp->rtm_table != 254)
			continue;
		i++;
		// init all the strings
		bzero(&route[i], sizeof(struct RouteInfo));
		// flags = rtp->rtm_flags;
		// route[i].proto = rtp->rtm_protocol;

	// // inner loop: loop thru all the attributes of
	// // one route entry
		rtap = (struct rtattr *) RTM_RTA(rtp);
		rtl = RTM_PAYLOAD(nlp);
		for( ; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap, rtl))
		{
			switch(rtap->rta_type)
			{
			// destination IPv4 address
				case RTA_DST:
					// count = 32 - rtp->rtm_dst_len;
					route[i].dstAddr = *(unsigned long *) RTA_DATA(rtap);
				break;
				case RTA_GATEWAY:
					route[i].gateWay = *(unsigned long *) RTA_DATA(rtap);
					//printf("gw:%s\t",inet_ntoa(route[i].gateWay));
				break;
				// // unique ID associated with the network
				// // interface
				case RTA_OIF:
					ifname(*((int *) RTA_DATA(rtap)),route[i].ifName);
					//printf( "ifname %s\n", route[i].ifName);
				break;
				default:
				break;
			}

		}
	} 
	

	
	for( j = 0; j<= i; j++)
	{

		if(strcmp(route[j].ifName, ifNameVar)==0)
		{
                   
			char ipbuf[INET_ADDRSTRLEN];	   
			char ipbuf2[INET_ADDRSTRLEN];	   
			inet_ntop(AF_INET, &route[j].dstAddr, ipbuf, INET_ADDRSTRLEN);
			inet_ntop(AF_INET, &route[j].gateWay, ipbuf2, INET_ADDRSTRLEN);
			sprintf(outputRouting, "%lu.%lu:%s:%s", (unsigned long) tv.tv_sec,(unsigned long) tv.tv_nsec, ipbuf ,ipbuf2);
			fprintf(fpRouting, "%s\n" ,outputRouting);
		}
	}
    fflush(fpRouting);
	// close(route_sock);
	return 0;
}
示例#8
0
static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdata) {
    AvahiInterfaceMonitor *m = userdata;

    /* This routine is called for every RTNETLINK response packet */

    assert(m);
    assert(n);
    assert(m->osdep.netlink == nl);

    if (n->nlmsg_type == RTM_NEWLINK) {

        /* A new interface appeared or an existing one has been modified */

        struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
        AvahiHwInterface *hw;
        struct rtattr *a = NULL;
        size_t l;

        /* A (superfluous?) sanity check */
        if (ifinfomsg->ifi_family != AF_UNSPEC)
            return;

        /* Check whether there already is an AvahiHwInterface object
         * for this link, so that we can update its data. Note that
         * Netlink sends us an RTM_NEWLINK not only when a new
         * interface appears, but when it changes, too */

        if (!(hw = avahi_interface_monitor_get_hw_interface(m, ifinfomsg->ifi_index)))

            /* No object found, so let's create a new
             * one. avahi_hw_interface_new() will call
             * avahi_interface_new() internally twice for IPv4 and
             * IPv6, so there is no need for us to do that
             * ourselves */
            if (!(hw = avahi_hw_interface_new(m, (AvahiIfIndex) ifinfomsg->ifi_index)))
                return; /* OOM */

        /* Check whether the flags of this interface are OK for us */
        hw->flags_ok =
            (ifinfomsg->ifi_flags & IFF_UP) &&
            (!m->server->config.use_iff_running || (ifinfomsg->ifi_flags & IFF_RUNNING)) &&
            !(ifinfomsg->ifi_flags & IFF_LOOPBACK) &&
            (ifinfomsg->ifi_flags & IFF_MULTICAST) &&
            (m->server->config.allow_point_to_point || !(ifinfomsg->ifi_flags & IFF_POINTOPOINT));

        /* Handle interface attributes */
        l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
        a = IFLA_RTA(ifinfomsg);

        while (RTA_OK(a, l)) {
            switch(a->rta_type) {
                case IFLA_IFNAME:

                    /* Fill in interface name */
                    avahi_free(hw->name);
                    hw->name = avahi_strndup(RTA_DATA(a), RTA_PAYLOAD(a));
                    break;

                case IFLA_MTU:

                    /* Fill in MTU */
                    assert(RTA_PAYLOAD(a) == sizeof(unsigned int));
                    hw->mtu = *((unsigned int*) RTA_DATA(a));
                    break;

                case IFLA_ADDRESS:

                    /* Fill in hardware (MAC) address */
                    hw->mac_address_size = RTA_PAYLOAD(a);
                    if (hw->mac_address_size > AVAHI_MAC_ADDRESS_MAX)
                        hw->mac_address_size = AVAHI_MAC_ADDRESS_MAX;

                    memcpy(hw->mac_address, RTA_DATA(a), hw->mac_address_size);
                    break;

                default:
                    ;
            }

            a = RTA_NEXT(a, l);
        }

        /* Check whether this interface is now "relevant" for us. If
         * it is Avahi will start to announce its records on this
         * interface and send out queries for subscribed records on
         * it */
        avahi_hw_interface_check_relevant(hw, AVAHI_MDNS);
        avahi_hw_interface_check_relevant(hw, AVAHI_LLMNR);

        /* Update any associated RRs of this interface. (i.e. the
         * _workstation._tcp record containing the MAC address) */
        avahi_hw_interface_update_rrs(hw, 0);

    } else if (n->nlmsg_type == RTM_DELLINK) {

        /* An interface has been removed */

        struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
        AvahiHwInterface *hw;

        /* A (superfluous?) sanity check */
        if (ifinfomsg->ifi_family != AF_UNSPEC)
            return;

        /* Get a reference to our AvahiHwInterface object of this interface */
        if (!(hw = avahi_interface_monitor_get_hw_interface(m, (AvahiIfIndex) ifinfomsg->ifi_index)))
            return;

        /* Free our object */
        avahi_hw_interface_free(hw, 0);

    } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {

        /* An address has been added, modified or removed */

        struct ifaddrmsg *ifaddrmsg = NLMSG_DATA(n);
        AvahiInterface *i;
        struct rtattr *a = NULL;
        size_t l;
        AvahiAddress raddr, rlocal, *r;
        int raddr_valid = 0, rlocal_valid = 0;

        /* We are only interested in IPv4 and IPv6 */
        if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6)
            return;

        /* Try to get a reference to our AvahiInterface object for the
         * interface this address is assigned to. If ther is no object
         * for this interface, we ignore this address. */
        if (!(i = avahi_interface_monitor_get_interface(m, (AvahiIfIndex) ifaddrmsg->ifa_index, avahi_af_to_proto(ifaddrmsg->ifa_family))))
            return;

        /* Fill in address family for our new address */
        rlocal.proto = raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family);

        l = NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg));
        a = IFA_RTA(ifaddrmsg);

        while (RTA_OK(a, l)) {

            switch(a->rta_type) {

                case IFA_ADDRESS:

                    if ((rlocal.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
                        (rlocal.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
                        return;

                    memcpy(rlocal.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
                    rlocal_valid = 1;

                    break;

                case IFA_LOCAL:

                    /* Fill in local address data. Usually this is
                     * preferable over IFA_ADDRESS if both are set,
                     * since this refers to the local address of a PPP
                     * link while IFA_ADDRESS refers to the other
                     * end. */

                    if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
                        (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
                        return;

                    memcpy(raddr.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
                    raddr_valid = 1;

                    break;

                default:
                    ;
            }

            a = RTA_NEXT(a, l);
        }

        /* If there was no adress attached to this message, let's quit. */
        if (rlocal_valid)
            r = &rlocal;
        else if (raddr_valid)
            r = &raddr;
        else
            return;

        if (n->nlmsg_type == RTM_NEWADDR) {
            AvahiInterfaceAddress *addr;

            /* This address is new or has been modified, so let's get an object for it */
            if (!(addr = avahi_interface_monitor_get_address(m, i, r)))

                /* Mmm, no object existing yet, so let's create a new one */
                if (!(addr = avahi_interface_address_new(m, i, r, ifaddrmsg->ifa_prefixlen)))
                    return; /* OOM */

            /* Update the scope field for the address */
            addr->global_scope = ifaddrmsg->ifa_scope == RT_SCOPE_UNIVERSE || ifaddrmsg->ifa_scope == RT_SCOPE_SITE;
            addr->deprecated = !!(ifaddrmsg->ifa_flags & IFA_F_DEPRECATED);
        } else {
            AvahiInterfaceAddress *addr;
            assert(n->nlmsg_type == RTM_DELADDR);

            /* Try to get a reference to our AvahiInterfaceAddress object for this address */
            if (!(addr = avahi_interface_monitor_get_address(m, i, r)))
                return;

            /* And free it */
            avahi_interface_address_free(addr);
        }

        /* Avahi only considers interfaces with at least one address
         * attached relevant. Since we migh have added or removed an
         * address, let's have it check again whether the interface is
         * now relevant */
        avahi_interface_check_relevant(i, AVAHI_MDNS);
        avahi_interface_check_relevant(i, AVAHI_LLMNR);

        /* Update any associated RRs, like A or AAAA for our new/removed address */
        avahi_interface_update_rrs(i, 0);

    } else if (n->nlmsg_type == NLMSG_DONE) {

        /* This wild dump request ended, so let's see what we do next */

        if (m->osdep.list == LIST_IFACE) {

            /* Mmmm, interfaces have been wild dumped already, so
             * let's go on with wild dumping the addresses */

            if (netlink_list_items(m->osdep.netlink, RTM_GETADDR, &m->osdep.query_addr_seq) < 0) {
                avahi_log_warn("NETLINK: Failed to list addrs: %s", strerror(errno));
                m->osdep.list = LIST_DONE;
            } else

                /* Update state information */
                m->osdep.list = LIST_ADDR;

        } else
            /* We're done. Tell avahi_interface_monitor_sync() to finish. */
            m->osdep.list = LIST_DONE;

        if (m->osdep.list == LIST_DONE) {

            /* Only after this boolean variable has been set, Avahi
             * will start to announce or browse on all interfaces. It
             * is originaly set to 0, which means that relevancy
             * checks and RR updates are disabled during the wild
             * dumps. */
            m->list_complete = 1;

            /* So let's check if any interfaces are relevant now */
            avahi_interface_monitor_check_relevant(m, AVAHI_MDNS);
            avahi_interface_monitor_check_relevant(m, AVAHI_LLMNR);

            /* And update all RRs attached to any interface */
            avahi_interface_monitor_update_rrs(m, 0);

            /* Tell the user that the wild dump is complete */
            avahi_log_info("Network interface enumeration completed.");
        }

    } else if (n->nlmsg_type == NLMSG_ERROR &&
               (n->nlmsg_seq == m->osdep.query_link_seq || n->nlmsg_seq == m->osdep.query_addr_seq)) {
        struct nlmsgerr *e = NLMSG_DATA (n);

        /* Some kind of error happened. Let's just tell the user and
         * ignore it otherwise */

        if (e->error)
            avahi_log_warn("NETLINK: Failed to browse: %s", strerror(-e->error));
    }
}
示例#9
0
文件: netlink.c 项目: NieHao/R7000
static void
get_if_prefix(struct nlmsghdr *nlm, int nlm_len, int request,
	      struct dhcp6_if *ifp)
{
	struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(nlm);
	struct rtattr *rta;
	size_t rtasize, rtapayload;
	void *rtadata;
	struct ra_info *rainfo;
	char addr[64];

	if (rtm->rtm_family != AF_INET6 || nlm->nlmsg_type != request)
		return;

	if (!(rtm->rtm_flags & RTM_F_PREFIX)) 
		return;

	rtasize = NLMSG_PAYLOAD(nlm, nlm_len) - NLMSG_ALIGN(sizeof(*rtm));
	rta = (struct rtattr *) (((char *) NLMSG_DATA(nlm)) +
	      NLMSG_ALIGN(sizeof(*rtm)));
	if (!RTA_OK(rta, rtasize))
		return;
	rtadata = RTA_DATA(rta);
	rtapayload = RTA_PAYLOAD(rta);
	switch(rta->rta_type) {
	case RTA_OIF:
		break;
	default:
		break; 
	}
	switch (rta->rta_type) {	
	case RTA_DST:
		rainfo = (struct ra_info *)malloc(sizeof(*rainfo));
		if (rainfo == NULL)
			return;
		memset(rainfo, 0, sizeof(rainfo));
		memcpy(&(rainfo->prefix), (struct in6_addr *)rtadata, 
		       sizeof(struct in6_addr));
		rainfo->plen = rtm->rtm_dst_len;
		if (ifp->ralist == NULL) {
			ifp->ralist = rainfo;
			rainfo->next = NULL;
		} else {
			struct ra_info *ra, *ra_prev;
			ra_prev = ifp->ralist;
			for (ra = ifp->ralist; ra; ra = ra->next) {
				if (rainfo->plen >= ra->plen) {
					if (ra_prev == ra) {
						ifp->ralist = rainfo;
						rainfo->next = ra;
					} else {
						ra_prev->next = rainfo;
						rainfo->next = ra;
					}
					break;
				} else {
					if (ra->next == NULL) {
						ra->next = rainfo;
						rainfo->next = NULL;
						break;
					} else {
						ra_prev = ra;
						continue;
					}
				}
			}
		}
		inet_ntop(AF_INET6, &(rainfo->prefix), addr, INET6_ADDRSTRLEN);
		dprintf(LOG_DEBUG, "get prefix address %s", addr);
		dprintf(LOG_DEBUG, "get prefix plen %d",rtm->rtm_dst_len);
		break;
	case RTA_CACHEINFO:
		dprintf(LOG_DEBUG, "prefix route life time is %d\n",
		      ((struct rta_cacheinfo *)rtadata)->rta_expires);
		break;
	default:
		break;
	}
	return;
}
示例#10
0
void process_nl_new_route (struct nlmsghdr *nlh)
{
    struct rtmsg             *rtm                       = NULL;
    struct rtattr            *rt_attr                   = NULL;
    int                      rt_length                  = 0;
    lispd_iface_elt          *iface                     = NULL;
    int                      iface_index                = 0;
    char                     iface_name[IF_NAMESIZE];
    lisp_addr_t              gateway                    = {.afi=AF_UNSPEC};
    lisp_addr_t              dst                        = {.afi=AF_UNSPEC};;


    rtm = (struct rtmsg *) NLMSG_DATA (nlh);

    if ((rtm->rtm_family != AF_INET) && (rtm->rtm_family != AF_INET6)) {
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_nl_new_route: Unknown adddress family");
        return;
    }

    if (rtm->rtm_table != RT_TABLE_MAIN) {
        /* Not interested in routes/gateways affecting tables other the main routing table */
        return;
    }

    rt_attr = (struct rtattr *)RTM_RTA(rtm);
    rt_length = RTM_PAYLOAD(nlh);

    for (; RTA_OK(rt_attr, rt_length); rt_attr = RTA_NEXT(rt_attr, rt_length)) {
        switch (rt_attr->rta_type) {
        case RTA_OIF:
            iface_index = *(int *)RTA_DATA(rt_attr);
            iface = get_interface_from_index(iface_index);
            if_indextoname(iface_index, iface_name);
            if (iface == NULL) {
                lispd_log_msg(LISP_LOG_DEBUG_2, "process_nl_new_route: the netlink message is not for any interface associated with RLOCs (%s)",
                              iface_name);
                return;
            }
            break;
        case RTA_GATEWAY:
            gateway.afi = rtm->rtm_family;
            switch (gateway.afi) {
            case AF_INET:
                memcpy(&(gateway.address),(struct in_addr *)RTA_DATA(rt_attr), sizeof(struct in_addr));
                break;
            case AF_INET6:
                memcpy(&(gateway.address),(struct in6_addr *)RTA_DATA(rt_attr), sizeof(struct in6_addr));
                break;
            default:
                break;
            }
            break;
        case RTA_DST: // We check if the new route message contains a destintaion. If it is, then the gateway address is not a default route. Discard it
            dst.afi = rtm->rtm_family;
            switch (dst.afi) {
            case AF_INET:
                memcpy(&(dst.address),(struct in_addr *)RTA_DATA(rt_attr), sizeof(struct in_addr));
                break;
            case AF_INET6:
                memcpy(&(dst.address),(struct in6_addr *)RTA_DATA(rt_attr), sizeof(struct in6_addr));
                break;
            default:
                break;
            }
            break;
        default:
            break;
        }
    }
    if (gateway.afi != AF_UNSPEC && iface_index != 0 && dst.afi == AF_UNSPEC) {
        /* Check default afi*/
        if (default_rloc_afi != AF_UNSPEC && default_rloc_afi != gateway.afi) {
            lispd_log_msg(LISP_LOG_DEBUG_1,  "process_nl_new_route: Default RLOC afi defined (-a #): Skipped %s gateway in iface %s",
                          (gateway.afi == AF_INET) ? "IPv4" : "IPv6",iface->iface_name);
            return;
        }

        /* Check if the addres is a global address*/
        if (is_link_local_addr(gateway) == TRUE) {
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_nl_new_route: the extractet address from the netlink "
                          "messages is a local link address: %s discarded", get_char_from_lisp_addr_t(gateway));
            return;
        }

        /* Process the new gateway */
        lispd_log_msg(LISP_LOG_DEBUG_1,  "process_nl_new_route: Process new gateway associated to the interface %s:  %s",
                      iface_name, get_char_from_lisp_addr_t(gateway));
        process_new_gateway(gateway,iface);
    }
}
示例#11
0
static __inline__ int
rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
{
	struct rtnetlink_link *link;
	struct rtnetlink_link *link_tab;
	int sz_idx, kind;
	int min_len;
	int family;
	int type;
	int err;

	/* Only requests are handled by kernel now */
	if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
		return 0;

	type = nlh->nlmsg_type;

	/* A control message: ignore them */
	if (type < RTM_BASE)
		return 0;

	/* Unknown message: reply with EINVAL */
	if (type > RTM_MAX)
		goto err_inval;

	type -= RTM_BASE;

	/* All the messages must have at least 1 byte length */
	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
		return 0;

	family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
	if (family >= NPROTO) {
		*errp = -EAFNOSUPPORT;
		return -1;
	}

	link_tab = rtnetlink_links[family];
	if (link_tab == NULL)
		link_tab = rtnetlink_links[PF_UNSPEC];
	link = &link_tab[type];

	sz_idx = type>>2;
	kind = type&3;

	if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) {
		*errp = -EPERM;
		return -1;
	}

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		if (link->dumpit == NULL)
			link = &(rtnetlink_links[PF_UNSPEC][type]);

		if (link->dumpit == NULL)
			goto err_inval;

		if ((*errp = netlink_dump_start(rtnl, skb, nlh,
						link->dumpit, NULL)) != 0) {
			return -1;
		}

		netlink_queue_skip(nlh, skb);
		return -1;
	}

	memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));

	min_len = rtm_min[sz_idx];
	if (nlh->nlmsg_len < min_len)
		goto err_inval;

	if (nlh->nlmsg_len > min_len) {
		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
		struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len);

		while (RTA_OK(attr, attrlen)) {
			unsigned flavor = attr->rta_type;
			if (flavor) {
				if (flavor > rta_max[sz_idx])
					goto err_inval;
				rta_buf[flavor-1] = attr;
			}
			attr = RTA_NEXT(attr, attrlen);
		}
	}

	if (link->doit == NULL)
		link = &(rtnetlink_links[PF_UNSPEC][type]);
	if (link->doit == NULL)
		goto err_inval;
	err = link->doit(skb, nlh, (void *)&rta_buf[0]);

	*errp = err;
	return err;

err_inval:
	*errp = -EINVAL;
	return -1;
}
示例#12
0
文件: ifplugd.c 项目: nawawi/busybox
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;
}
示例#13
0
static __inline__ int
rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
{
	struct rtnetlink_link *link;
	struct rtnetlink_link *link_tab;
	struct rtattr	*rta[RTATTR_MAX];

	int exclusive = 0;
	int sz_idx, kind;
	int min_len;
	int family;
	int type;
	int err;

	/* Only requests are handled by kernel now */
	if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
		return 0;

	type = nlh->nlmsg_type;

	/* A control message: ignore them */
	if (type < RTM_BASE)
		return 0;

	/* Unknown message: reply with EINVAL */
	if (type > RTM_MAX)
		goto err_inval;

	type -= RTM_BASE;

	/* All the messages must have at least 1 byte length */
	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
		return 0;

	family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
	if (family > NPROTO) {
		*errp = -EAFNOSUPPORT;
		return -1;
	}

	link_tab = rtnetlink_links[family];
	if (link_tab == NULL)
		link_tab = rtnetlink_links[PF_UNSPEC];
	link = &link_tab[type];

	sz_idx = type>>2;
	kind = type&3;

	if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
		*errp = -EPERM;
		return -1;
	}

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		u32 rlen;

		if (link->dumpit == NULL)
			link = &(rtnetlink_links[PF_UNSPEC][type]);

		if (link->dumpit == NULL)
			goto err_inval;

		if ((*errp = netlink_dump_start(rtnl, skb, nlh,
						link->dumpit,
						rtnetlink_done)) != 0) {
			return -1;
		}
		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
		if (rlen > skb->len)
			rlen = skb->len;
		skb_pull(skb, rlen);
		return -1;
	}

	if (kind != 2) {
		if (rtnl_exlock_nowait()) {
			*errp = 0;
			return -1;
		}
		exclusive = 1;
	}

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

	min_len = rtm_min[sz_idx];
	if (nlh->nlmsg_len < min_len)
		goto err_inval;

	if (nlh->nlmsg_len > min_len) {
		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
		struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len);

		while (RTA_OK(attr, attrlen)) {
			unsigned flavor = attr->rta_type;
			if (flavor) {
				if (flavor > rta_max[sz_idx])
					goto err_inval;
				rta[flavor-1] = attr;
			}
			attr = RTA_NEXT(attr, attrlen);
		}
	}

	if (link->doit == NULL)
		link = &(rtnetlink_links[PF_UNSPEC][type]);
	if (link->doit == NULL)
		goto err_inval;
	err = link->doit(skb, nlh, (void *)&rta);

	if (exclusive)
		rtnl_exunlock();
	*errp = err;
	return err;

err_inval:
	if (exclusive)
		rtnl_exunlock();
	*errp = -EINVAL;
	return -1;
}
示例#14
0
static void rtnl_print_neigh(struct nlmsghdr *hdr)
{
	struct ndmsg *ndm = NLMSG_DATA(hdr);
	uint32_t attrs_len = NDA_PAYLOAD(hdr);
	struct rtattr *attr = NDA_RTA(ndm);
	struct nda_cacheinfo *ci;
	int hz = get_user_hz();
	char addr_str[256];
	char hw_addr[30];
	char states[256];
	char flags[256];

	tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
			colorize_start(bold),
			addr_family2str(ndm->ndm_family),
			colorize_end());
	tprintf(", Link Index %d", ndm->ndm_ifindex);
	tprintf(", State %d (%s%s%s)", ndm->ndm_state,
			colorize_start(bold),
			flags2str(neigh_states, ndm->ndm_state, states,
				sizeof(states)),
			colorize_end());
	tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
			colorize_start(bold),
			flags2str(neigh_flags, ndm->ndm_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
			colorize_start(bold),
			route_type2str(ndm->ndm_type),
			colorize_end());
	tprintf(" ]\n");

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case NDA_DST:
			attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case NDA_LLADDR:
			attr_fmt(attr, "HW Address %s",
					device_addr2str(RTA_DATA(attr),
						RTA_LEN(attr), 0, hw_addr,
						sizeof(hw_addr)));
			break;
		case NDA_PROBES:
			attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
			break;
		case NDA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");
			tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
			tprintf(", used(%ds)", ci->ndm_used / hz);
			tprintf(", updated(%ds)", ci->ndm_updated / hz);
			tprintf(", refcnt(%d))", ci->ndm_refcnt);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}
/** 
 *  @brief              This function parses for IWEVENT events 
 *
 *  @param h            Pointer to Netlink message header
 *  @param left         Number of bytes to be read
 *  @param evt_conn     A pointer to a output buffer. It sets TRUE when it gets
 *  					the event CUS_EVT_OBSS_SCAN_PARAM, otherwise FALSE
 *  @return             Number of bytes left to be read
 */
static int
drv_iwevt_handler(struct nlmsghdr *h, int left, int *evt_conn)
{
    int len, plen, attrlen, nlmsg_len, rta_len;
    struct ifinfomsg *ifi;
    struct rtattr *attr;

    *evt_conn = FALSE;
    while (left >= sizeof(*h)) {
        len = h->nlmsg_len;
        plen = len - sizeof(*h);
        if (len > left || plen < 0) {
            /* malformed netlink message */
            break;
        }
        if (plen < sizeof(*ifi)) {
            break;
        }
        ifi = NLMSG_DATA(h);
        nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
        attrlen = h->nlmsg_len - nlmsg_len;
        if (attrlen < 0) {
            break;
        }

        attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
        rta_len = RTA_ALIGN(sizeof(struct rtattr));
        while (RTA_OK(attr, attrlen)) {
            if (attr->rta_type == IFLA_WIRELESS) {
                struct iw_event *iwe;
                char *pos = ((char *) attr) + rta_len;
                char *end = pos + (attr->rta_len - rta_len);
                unsigned short dlen;

                while (pos + IW_EV_LCP_LEN <= end) {
                    iwe = (struct iw_event *) pos;
                    if (iwe->len <= IW_EV_LCP_LEN)
                        break;

                    switch (iwe->cmd) {
                    case SIOCGIWAP:
                        {
                            struct ether_addr *wap;
                            struct ether_addr etherzero =
                                { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
                            char buf[32];

                            wap = (struct ether_addr *)
                                ((struct sockaddr *) (&iwe->u.ap_addr))->
                                sa_data;

                            if (!memcmp
                                (wap, &etherzero, sizeof(struct ether_addr))) {
                                printf("---< Disconnected from AP >---\n");
                                memset(&cur_obss_scan_param, 0,
                                       sizeof(cur_obss_scan_param));
                                assoc_flag = FALSE;
                                is_ht_ap = FALSE;
                            } else {
                                memset(buf, 0, sizeof(buf));
                                sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
                                        wap->ether_addr_octet[0],
                                        wap->ether_addr_octet[1],
                                        wap->ether_addr_octet[2],
                                        wap->ether_addr_octet[3],
                                        wap->ether_addr_octet[4],
                                        wap->ether_addr_octet[5]);
                                printf("---< Connected to AP: %s >---\n", buf);
                                /** set TRUE, if connected */
                                assoc_flag = TRUE;
                            }
                            pos += iwe->len;
                        }
                        break;
                    case IWEVCUSTOM:
                        {
                            char *custom;
                            custom = pos + IW_EV_POINT_LEN;
                            if (IW_EV_POINT_LEN ==
                                IW_EV_LCP_LEN + sizeof(struct iw_point)) {
                                dlen = iwe->u.data.length;
                            } else {    /* WIRELESS_EXT >= 19 */
                                dlen =
                                    *((unsigned short *) (pos + IW_EV_LCP_LEN));
                            }
                            if (custom + dlen > end)
                                break;

                            printf("---< %s >---\n", custom);
                            if (!strncmp
                                (CUS_EVT_OBSS_SCAN_PARAM, custom,
                                 strlen(CUS_EVT_OBSS_SCAN_PARAM))) {
                                memset(&cur_obss_scan_param, 0,
                                       sizeof(cur_obss_scan_param));
                                memcpy(&cur_obss_scan_param,
                                       (custom +
                                        strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1),
                                       sizeof(cur_obss_scan_param));
                                /** set TRUE, since it is an HT AP */
                                is_ht_ap = TRUE;
                                *evt_conn = TRUE;
                            }
                            pos += iwe->len;
                        }
                        break;
                    default:
                        pos += iwe->len;
                        break;
                    }
                }
            }
            attr = RTA_NEXT(attr, attrlen);
        }

        len = NLMSG_ALIGN(len);
        left -= len;
        h = (struct nlmsghdr *) ((char *) h + len);
    }
    return left;
}
示例#16
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;
}
示例#17
0
int netlink_input_packet(struct rproto *netlink,
                         void *buf,
			 unsigned int len,
			 struct sockaddr *from,
			 int fromlen) {
//	struct rtable *learn_table,*unlearn_table;
//	struct sockaddr_nl *origin = (struct sockaddr_nl *)from;

	struct nlmsghdr *nh;
	char content[128] = "";
	struct ifinfomsg *ifinfo;
/*	struct ifaddrmsg *addrinfo;
	struct rtmsg *rtinfo;*/

	nh = (struct nlmsghdr *)buf;
	switch(nh->nlmsg_type) {
		case RTM_NEWLINK:
			ifinfo = (struct ifinfomsg *)NLMSG_DATA(nh);
#ifdef DEBUG
			{
			int rtlen;
			struct rtattr *rta;
			
			rtlen=RTM_PAYLOAD(nh);
			rta=RTM_RTA(ifinfo);
			
			/* little hack.. UNSPEC has len==1. This doesn't go well with 
			 * RTA_OK macro..
			 */
			if (rta->rta_type == IFLA_UNSPEC)
				rta->rta_len=4;
			while (RTA_OK(rta, rtlen)) {
				if (rta->rta_type == IFLA_IFNAME)
					log_msg("Netlink interface: %s", RTA_DATA(rta));
				rta=RTA_NEXT(rta,rtlen);
			}
			}
#endif			
			if((ifinfo->ifi_flags & IFF_UP) && (ifinfo->ifi_flags & IFF_RUNNING)) {
				linklist_update();
				snprintf(content,sizeof(content),"Iface %d is going up",ifinfo->ifi_index);
			}else{
				linklist_update();
				snprintf(content,sizeof(content),"Iface %d is going down",ifinfo->ifi_index);
			}
			break;
		default:
			return 0;
	}
	log_msg("Netlink: %s",content);
	
/*	learn_table = new_rtable();
	unlearn_table = new_rtable();
	
	if(learn_table->num_routes != 0)
		learn_routes(netlink,learn_table);
	if(unlearn_table->num_routes != 0)
		unlearn_routes(netlink,unlearn_table);
	
	free_rtable(learn_table);
	free_rtable(unlearn_table);*/
	
	return 0;
}
示例#18
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);
    }
  }
}
示例#19
0
static int aead_authenc_setkey(struct crypto_aead *aead,
			       const u8 *key, unsigned int keylen)
{
	/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
	static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
	struct caam_ctx *ctx = crypto_aead_ctx(aead);
	struct device *dev = ctx->dev;
	struct rtattr *rta = (void *)key;
	struct crypto_authenc_key_param *param;
	unsigned int authkeylen;
	unsigned int enckeylen;
	int ret = 0;

	if (!RTA_OK(rta, keylen))
		goto badkey;

	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
		goto badkey;

	if (RTA_PAYLOAD(rta) < sizeof(*param))
		goto badkey;

	param = RTA_DATA(rta);
	enckeylen = be32_to_cpu(param->enckeylen);

	key += RTA_ALIGN(rta->rta_len);
	keylen -= RTA_ALIGN(rta->rta_len);

	if (keylen < enckeylen)
		goto badkey;

	authkeylen = keylen - enckeylen;

	if (keylen > CAAM_MAX_KEY_SIZE)
		goto badkey;

	/* Pick class 2 key length from algorithm submask */
	ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
				      OP_ALG_ALGSEL_SHIFT] * 2;
	ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);

#ifdef DEBUG
	printk(KERN_ERR "keylen %d enckeylen %d authkeylen %d\n",
	       keylen, enckeylen, authkeylen);
	printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
	       ctx->split_key_len, ctx->split_key_pad_len);
	print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
		       DUMP_PREFIX_ADDRESS, 16, 4, key,
		       CAAM_MAX_KEY_SIZE, 1);
#endif
	ctx->key = kzalloc(ctx->split_key_pad_len + enckeylen,
			   GFP_KERNEL | GFP_DMA);
	if (!ctx->key) {
		dev_err(ctx->dev, "could not allocate key output memory\n");
		return -ENOMEM;
	}

	ret = gen_split_key(dev, ctx, key, authkeylen);
	if (ret)
		goto badkey;

	/* postpend encryption key to auth split key */
	memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);

	ctx->key_phys = dma_map_single(dev, ctx->key, ctx->split_key_pad_len +
				       enckeylen, DMA_TO_DEVICE);
	if (dma_mapping_error(dev, ctx->key_phys)) {
		dev_err(dev, "unable to map key i/o memory\n");
		return -ENOMEM;
	}
#ifdef DEBUG
	print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
		       DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
		       CAAM_MAX_KEY_SIZE, 1);
#endif

	ctx->keylen = keylen;
	ctx->enckeylen = enckeylen;
	ctx->authkeylen = authkeylen;

	return ret;
badkey:
	crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
	return -EINVAL;
}
示例#20
0
/**
 * Scan netlink message in the buffer for IPv6 default route changes.
 */
static int
rtmon_check_defaults(const void *buf, size_t len)
{
    struct nlmsghdr *nh;
    int dfltdiff = 0;

    for (nh = (struct nlmsghdr *)buf;
         NLMSG_OK(nh, len);
         nh = NLMSG_NEXT(nh, len))
    {
        struct rtmsg *rtm;
        struct rtattr *rta;
        int attrlen;
        int delta = 0;
        const void *gwbuf;
        size_t gwlen;
        int oif;

        DPRINTF2(("nlmsg type %d flags 0x%x\n",
                  nh->nlmsg_seq, nh->nlmsg_type, nh->nlmsg_flags));

        if (nh->nlmsg_type == NLMSG_DONE) {
            break;
        }

        if (nh->nlmsg_type == NLMSG_ERROR) {
            struct nlmsgerr *ne = (struct nlmsgerr *)NLMSG_DATA(nh);
            DPRINTF2(("> error %d\n", ne->error));
            LWIP_UNUSED_ARG(ne);
            break;
        }

        if (nh->nlmsg_type < RTM_BASE || RTM_MAX <= nh->nlmsg_type) {
            /* shouldn't happen */
            DPRINTF2(("> not an RTM message!\n"));
            continue;
        }


        rtm = (struct rtmsg *)NLMSG_DATA(nh);
        attrlen = RTM_PAYLOAD(nh);

        if (nh->nlmsg_type == RTM_NEWROUTE) {
            delta = +1;
        }
        else if (nh->nlmsg_type == RTM_DELROUTE) {
            delta = -1;
        }
        else {
            /* shouldn't happen */
            continue;
        }

        /*
         * Is this an IPv6 default route in the main table?  (Local
         * table always has ::/0 reject route, hence the last check).
         */
        if (rtm->rtm_family == AF_INET6 /* should always be true */
            && rtm->rtm_dst_len == 0
            && rtm->rtm_table == RT_TABLE_MAIN)
        {
            dfltdiff += delta;
        }
        else {
            /* some other route change */
            continue;
        }


        gwbuf = NULL;
        gwlen = 0;
        oif = -1;

        for (rta = RTM_RTA(rtm);
             RTA_OK(rta, attrlen);
             rta = RTA_NEXT(rta, attrlen))
        {
            if (rta->rta_type == RTA_GATEWAY) {
                gwbuf = RTA_DATA(rta);
                gwlen = RTA_PAYLOAD(rta);
            }
            else if (rta->rta_type == RTA_OIF) {
                /* assert RTA_PAYLOAD(rta) == 4 */
                memcpy(&oif, RTA_DATA(rta), sizeof(oif));
            }
        }

        /* XXX: TODO: note that { oif, gw } was added/removed */
        LWIP_UNUSED_ARG(gwbuf);
        LWIP_UNUSED_ARG(gwlen);
        LWIP_UNUSED_ARG(oif);
    }

    return dfltdiff;
}
示例#21
0
文件: ifaddrs.c 项目: Altiscale/lxc
static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
{
    struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);

    size_t l_nameSize = 0;
    size_t l_addrSize = 0;
    size_t l_dataSize = 0;

    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    struct rtattr *l_rta;
    for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
            case IFLA_ADDRESS:
            case IFLA_BROADCAST:
                l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
                break;
            case IFLA_IFNAME:
                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
                break;
            case IFLA_STATS:
                l_dataSize += NLMSG_ALIGN(l_rtaSize);
                break;
            default:
                break;
        }
    }

    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
    memset(l_entry, 0, sizeof(struct ifaddrs));
    l_entry->ifa_name = "";

    char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
    char *l_addr = l_name + l_nameSize;
    char *l_data = l_addr + l_addrSize;

    l_entry->ifa_flags = l_info->ifi_flags;

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        void *l_rtaData = RTA_DATA(l_rta);
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
            case IFLA_ADDRESS:
            case IFLA_BROADCAST:
            {
                size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
                makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
                ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
                ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
                if(l_rta->rta_type == IFLA_ADDRESS)
                {
                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
                }
                else
                {
                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
                }
                l_addr += NLMSG_ALIGN(l_addrLen);
                break;
            }
            case IFLA_IFNAME:
                strncpy(l_name, l_rtaData, l_rtaDataSize);
                l_name[l_rtaDataSize] = '\0';
                l_entry->ifa_name = l_name;
                break;
            case IFLA_STATS:
                memcpy(l_data, l_rtaData, l_rtaDataSize);
                l_entry->ifa_data = l_data;
                break;
            default:
                break;
        }
    }

    addToEnd(p_resultList, l_entry);
    p_links[l_info->ifi_index - 1] = l_entry;
}
示例#22
0
// Detect an IPV6-address currently assigned to the given interface
ssize_t relayd_get_interface_addresses(int ifindex,
		struct relayd_ipaddr *addrs, size_t cnt)
{
	struct {
		struct nlmsghdr nhm;
		struct ifaddrmsg ifa;
	} req = {{sizeof(req), RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP,
			++rtnl_seq, 0}, {AF_INET6, 0, 0, 0, ifindex}};
	if (send(rtnl_socket, &req, sizeof(req), 0) < (ssize_t)sizeof(req))
		return 0;

	uint8_t buf[8192];
	ssize_t len = 0, ret = 0;

	for (struct nlmsghdr *nhm = NULL; ; nhm = NLMSG_NEXT(nhm, len)) {
		while (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
			len = recv(rtnl_socket, buf, sizeof(buf), 0);
			nhm = (struct nlmsghdr*)buf;
			if (len < 0 || !NLMSG_OK(nhm, (size_t)len)) {
				if (errno == EINTR)
					continue;
				else
					return ret;
			}
		}

		if (nhm->nlmsg_type != RTM_NEWADDR)
			break;

		// Skip address but keep clearing socket buffer
		if (ret >= (ssize_t)cnt)
			continue;

		struct ifaddrmsg *ifa = NLMSG_DATA(nhm);
		if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
				ifa->ifa_index != (unsigned)ifindex)
			continue;

		struct rtattr *rta = (struct rtattr*)&ifa[1];
		size_t alen = NLMSG_PAYLOAD(nhm, sizeof(*ifa));
		memset(&addrs[ret], 0, sizeof(addrs[ret]));
		addrs[ret].prefix = ifa->ifa_prefixlen;

		while (RTA_OK(rta, alen)) {
			if (rta->rta_type == IFA_ADDRESS) {
				memcpy(&addrs[ret].addr, RTA_DATA(rta),
						sizeof(struct in6_addr));
			} else if (rta->rta_type == IFA_CACHEINFO) {
				struct ifa_cacheinfo *ifc = RTA_DATA(rta);
				addrs[ret].preferred = ifc->ifa_prefered;
				addrs[ret].valid = ifc->ifa_valid;
			}

			rta = RTA_NEXT(rta, alen);
		}

		if (ifa->ifa_flags & IFA_F_DEPRECATED)
			addrs[ret].preferred = 0;

		++ret;
	}

	return ret;
}
示例#23
0
static bool
receive_responses(struct tcb *tcp, const int fd, const unsigned long inode,
		  const unsigned long expected_msg_type,
		  int (*parser)(const void *, int,
				unsigned long, void *),
		  void *opaque_data)
{
	static union {
		struct nlmsghdr hdr;
		long buf[8192 / sizeof(long)];
	} hdr_buf;

	struct sockaddr_nl nladdr = {
		.nl_family = AF_NETLINK
	};
	struct iovec iov = {
		.iov_base = hdr_buf.buf,
		.iov_len = sizeof(hdr_buf.buf)
	};
	int flags = 0;

	for (;;) {
		struct msghdr msg = {
			.msg_name = &nladdr,
			.msg_namelen = sizeof(nladdr),
			.msg_iov = &iov,
			.msg_iovlen = 1
		};

		ssize_t ret = recvmsg(fd, &msg, flags);
		if (ret < 0) {
			if (errno == EINTR)
				continue;
			return false;
		}

		const struct nlmsghdr *h = &hdr_buf.hdr;
		if (!NLMSG_OK(h, ret))
			return false;
		for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
			if (h->nlmsg_type != expected_msg_type)
				return false;
			const int rc = parser(NLMSG_DATA(h),
					      h->nlmsg_len, inode, opaque_data);
			if (rc > 0)
				return true;
			if (rc < 0)
				return false;
		}
		flags = MSG_DONTWAIT;
	}
}

static bool
unix_send_query(struct tcb *tcp, const int fd, const unsigned long inode)
{
	/*
	 * The kernel bug was fixed in mainline by commit v4.5-rc6~35^2~11
	 * and backported to stable/linux-4.4.y by commit v4.4.4~297.
	 */
	const uint16_t dump_flag =
		os_release < KERNEL_VERSION(4, 4, 4) ? NLM_F_DUMP : 0;

	struct {
		const struct nlmsghdr nlh;
		const struct unix_diag_req udr;
	} req = {
		.nlh = {
			.nlmsg_len = sizeof(req),
			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
			.nlmsg_flags = NLM_F_REQUEST | dump_flag
		},
		.udr = {
			.sdiag_family = AF_UNIX,
			.udiag_ino = inode,
			.udiag_states = -1,
			.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER,
			.udiag_cookie = { ~0U, ~0U }
		}
	};
	return send_query(tcp, fd, &req, sizeof(req));
}

static int
unix_parse_response(const void *data, const int data_len,
		    const unsigned long inode, void *opaque_data)
{
	const char *proto_name = opaque_data;
	const struct unix_diag_msg *diag_msg = data;
	struct rtattr *attr;
	int rta_len = data_len - NLMSG_LENGTH(sizeof(*diag_msg));
	uint32_t peer = 0;
	size_t path_len = 0;
	char path[UNIX_PATH_MAX + 1];

	if (rta_len < 0)
		return -1;
	if (diag_msg->udiag_ino != inode)
		return 0;
	if (diag_msg->udiag_family != AF_UNIX)
		return -1;

	for (attr = (struct rtattr *) (diag_msg + 1);
	     RTA_OK(attr, rta_len);
	     attr = RTA_NEXT(attr, rta_len)) {
		switch (attr->rta_type) {
		case UNIX_DIAG_NAME:
			if (!path_len) {
				path_len = RTA_PAYLOAD(attr);
				if (path_len > UNIX_PATH_MAX)
					path_len = UNIX_PATH_MAX;
				memcpy(path, RTA_DATA(attr), path_len);
				path[path_len] = '\0';
			}
			break;
		case UNIX_DIAG_PEER:
			if (RTA_PAYLOAD(attr) >= 4)
				peer = *(uint32_t *) RTA_DATA(attr);
			break;
		}
	}

	/*
	 * print obtained information in the following format:
	 * "UNIX:[" SELF_INODE [ "->" PEER_INODE ][ "," SOCKET_FILE ] "]"
	 */
	if (!peer && !path_len)
		return -1;

	char peer_str[3 + sizeof(peer) * 3];
	if (peer)
		xsprintf(peer_str, "->%u", peer);
	else
		peer_str[0] = '\0';

	const char *path_str;
	if (path_len) {
		char *outstr = alloca(4 * path_len + 4);

		outstr[0] = ',';
		if (path[0] == '\0') {
			outstr[1] = '@';
			string_quote(path + 1, outstr + 2,
				     path_len - 1, QUOTE_0_TERMINATED, NULL);
		} else {
			string_quote(path, outstr + 1,
				     path_len, QUOTE_0_TERMINATED, NULL);
		}
		path_str = outstr;
	} else {
		path_str = "";
	}

	char *details;
	if (asprintf(&details, "%s:[%lu%s%s]", proto_name, inode,
		     peer_str, path_str) < 0)
		return -1;

	return cache_inode_details(inode, details);
}

static bool
netlink_send_query(struct tcb *tcp, const int fd, const unsigned long inode)
{
	struct {
		const struct nlmsghdr nlh;
		const struct netlink_diag_req ndr;
	} req = {
		.nlh = {
			.nlmsg_len = sizeof(req),
			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
			.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
		},
		.ndr = {
			.sdiag_family = AF_NETLINK,
			.sdiag_protocol = NDIAG_PROTO_ALL
		}
	};
	return send_query(tcp, fd, &req, sizeof(req));
}
static void rtsock_parsemsg(uint8_t *buf, size_t len)
{
  struct nlmsghdr *nlmsg;
  struct nlmsgerr *nlerr;
  struct rtmsg    *rtmsg;
  struct rtattr   *rta;
  void            *gwa = NULL;
  int              ifindex = -1;
  scamper_addr_t  *gw = NULL;
  rtsock_pair_t   *pair = NULL;
  scamper_route_t *route = NULL;

  if(len < sizeof(struct nlmsghdr))
    {
      scamper_debug(__func__, "len %d != %d", len, sizeof(struct nlmsghdr));
      return;
    }

  nlmsg = (struct nlmsghdr *)buf;

  /* if the message isn't addressed to this pid, drop it */
  if(nlmsg->nlmsg_pid != pid)
    return;

  if((pair = rtsock_pair_get(nlmsg->nlmsg_seq)) == NULL)
    return;
  route = pair->route;
  rtsock_pair_free(pair);

  if(nlmsg->nlmsg_type == RTM_NEWROUTE)
    {
      rtmsg = NLMSG_DATA(nlmsg);

      /* this is the payload length of the response packet */
      len = nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));

      /* hunt through the payload for the RTA_OIF entry */
      rta = RTM_RTA(rtmsg);
      while(RTA_OK(rta, len))
	{
	  switch(rta->rta_type)
	    {
	    case RTA_OIF:
	      ifindex = *(unsigned *)RTA_DATA(rta);
	      break;

	    case RTA_GATEWAY:
	      gwa = RTA_DATA(rta);
	      break;
	    }
	  rta = RTA_NEXT(rta, len);
	}

      if(gwa != NULL)
	{
	  if(rtmsg->rtm_family == AF_INET)
	    gw = scamper_addrcache_get_ipv4(addrcache, gwa);
	  else if(rtmsg->rtm_family == AF_INET6)
	    gw = scamper_addrcache_get_ipv6(addrcache, gwa);
	  else
	    route->error = EINVAL;
	}
    }
  else if(nlmsg->nlmsg_type == NLMSG_ERROR)
    {
      nlerr = NLMSG_DATA(nlmsg);
      route->error = nlerr->error;
    }
  else goto skip;

  route->gw = gw;
  route->ifindex = ifindex;
  route->cb(route);

  return;

 skip:
  if(route != NULL) scamper_route_free(route);
  return;
}
示例#25
0
/**
 * Process the message and add/drop multicast membership if needed
 */
int
ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6)
{
	struct lan_addr_s * lan_addr;
	ssize_t len;
	char buffer[4096];
#ifdef __linux__
	struct iovec iov;
	struct msghdr hdr;
	struct nlmsghdr *nlhdr;
	struct ifaddrmsg *ifa;
	struct rtattr *rta;
	int ifa_len;

	iov.iov_base = buffer;
	iov.iov_len = sizeof(buffer);

	memset(&hdr, 0, sizeof(hdr));
	hdr.msg_iov = &iov;
	hdr.msg_iovlen = 1;

	len = recvmsg(s, &hdr, 0);
	if(len < 0) {
		syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m");
		return -1;
	}

	for(nlhdr = (struct nlmsghdr *)buffer;
		NLMSG_OK(nlhdr, len);
		nlhdr = NLMSG_NEXT(nlhdr, len)) {
		int is_del = 0;
		char address[48];
		char ifname[IFNAMSIZ];
		address[0] = '\0';
		ifname[0] = '\0';
		if(nlhdr->nlmsg_type == NLMSG_DONE)
			break;
		switch(nlhdr->nlmsg_type) {
		/* case RTM_NEWLINK: */
		/* case RTM_DELLINK: */
		case RTM_DELADDR:
			is_del = 1;
		case RTM_NEWADDR:
			/* http://linux-hacks.blogspot.fr/2009/01/sample-code-to-learn-netlink.html */
			ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
			rta = (struct rtattr *)IFA_RTA(ifa);
			ifa_len = IFA_PAYLOAD(nlhdr);
			syslog(LOG_DEBUG, "%s %s index=%d fam=%d prefixlen=%d flags=%d scope=%d",
			       "ProcessInterfaceWatchNotify", is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
			       ifa->ifa_index, ifa->ifa_family, ifa->ifa_prefixlen,
			       ifa->ifa_flags, ifa->ifa_scope);
			for(;RTA_OK(rta, ifa_len); rta = RTA_NEXT(rta, ifa_len)) {
				/*RTA_DATA(rta)*/
				/*rta_type : IFA_ADDRESS, IFA_LOCAL, etc. */
				char tmp[128];
				memset(tmp, 0, sizeof(tmp));
				switch(rta->rta_type) {
				case IFA_ADDRESS:
				case IFA_LOCAL:
				case IFA_BROADCAST:
				case IFA_ANYCAST:
					inet_ntop(ifa->ifa_family, RTA_DATA(rta), tmp, sizeof(tmp));
					if(rta->rta_type == IFA_ADDRESS)
						strncpy(address, tmp, sizeof(address));
					break;
				case IFA_LABEL:
					strncpy(tmp, RTA_DATA(rta), sizeof(tmp));
					strncpy(ifname, tmp, sizeof(ifname));
					break;
				case IFA_CACHEINFO:
					{
						struct ifa_cacheinfo *cache_info;
						cache_info = RTA_DATA(rta);
						snprintf(tmp, sizeof(tmp), "valid=%u prefered=%u",
						         cache_info->ifa_valid, cache_info->ifa_prefered);
					}
					break;
				default:
					strncpy(tmp, "*unknown*", sizeof(tmp));
				}
				syslog(LOG_DEBUG, " rta_len=%d rta_type=%d '%s'", rta->rta_len, rta->rta_type, tmp);
			}
			syslog(LOG_INFO, "%s: %s/%d %s",
			       is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
			       address, ifa->ifa_prefixlen, ifname);
			for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) {
				if((0 == strcmp(address, lan_addr->str)) ||
				   (0 == strcmp(ifname, lan_addr->ifname)) ||
				   (ifa->ifa_index == lan_addr->index)) {
					if(ifa->ifa_family == AF_INET)
						AddDropMulticastMembership(s_ssdp, lan_addr, 0, is_del);
					else if(ifa->ifa_family == AF_INET6)
						AddDropMulticastMembership(s_ssdp6, lan_addr, 1, is_del);
					break;
				}
			}
			break;
		default:
			syslog(LOG_DEBUG, "unknown nlmsg_type=%d", nlhdr->nlmsg_type);
		}
	}
#else /* __linux__ */
	struct rt_msghdr * rtm;
	struct ifa_msghdr * ifam;
	int is_del = 0;
	char tmp[64];
	char * p;
	struct sockaddr * sa;
	int addr;
	char address[48];
	char ifname[IFNAMSIZ];
	int family = AF_UNSPEC;
	int prefixlen = 0;

	address[0] = '\0';
	ifname[0] = '\0';

	len = recv(s, buffer, sizeof(buffer), 0);
	if(len < 0) {
		syslog(LOG_ERR, "%s recv: %m", "ProcessInterfaceWatchNotify");
		return -1;
	}
	rtm = (struct rt_msghdr *)buffer;
	switch(rtm->rtm_type) {
	case RTM_DELADDR:
		is_del = 1;
	case RTM_NEWADDR:
		ifam = (struct ifa_msghdr *)buffer;
		syslog(LOG_DEBUG, "%s %s len=%d/%hu index=%hu addrs=%x flags=%x",
		       "ProcessInterfaceWatchNotify", is_del?"RTM_DELADDR":"RTM_NEWADDR",
		       (int)len, ifam->ifam_msglen,
		       ifam->ifam_index, ifam->ifam_addrs, ifam->ifam_flags);
		p = buffer + sizeof(struct ifa_msghdr);
		addr = 1;
		while(p < buffer + len) {
			sa = (struct sockaddr *)p;
			while(!(addr & ifam->ifam_addrs) && (addr <= ifam->ifam_addrs))
				addr = addr << 1;
			sockaddr_to_string(sa, tmp, sizeof(tmp));
			syslog(LOG_DEBUG, " %s", tmp);
			switch(addr) {
			case RTA_DST:
			case RTA_GATEWAY:
				break;
			case RTA_NETMASK:
				if(sa->sa_family == AF_INET
#if defined(__OpenBSD__)
				   || (sa->sa_family == 0 &&
				       sa->sa_len <= sizeof(struct sockaddr_in))
#endif
				   ) {
					uint32_t sin_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
					while((prefixlen < 32) &&
					      ((sin_addr & (1 << (31 - prefixlen))) != 0))
						prefixlen++;
				} else if(sa->sa_family == AF_INET6
#if defined(__OpenBSD__)
				          || (sa->sa_family == 0 &&
				              sa->sa_len == sizeof(struct sockaddr_in6))
#endif
				          ) {
					int i = 0;
					uint8_t * q =  ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
					while((*q == 0xff) && (i < 16)) {
						prefixlen += 8;
						q++; i++;
					}
					if(i < 16) {
						i = 0;
						while((i < 8) &&
						      ((*q & (1 << (7 - i))) != 0))
							i++;
						prefixlen += i;
					}
				}
				break;
			case RTA_GENMASK:
				break;
			case RTA_IFP:
#ifdef AF_LINK
				if(sa->sa_family == AF_LINK) {
					struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa;
					memset(ifname, 0, sizeof(ifname));
					memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
				}
#endif
				break;
			case RTA_IFA:
				family = sa->sa_family;
				if(sa->sa_family == AF_INET) {
					inet_ntop(sa->sa_family,
					          &((struct sockaddr_in *)sa)->sin_addr,
					          address, sizeof(address));
				} else if(sa->sa_family == AF_INET6) {
					inet_ntop(sa->sa_family,
					          &((struct sockaddr_in6 *)sa)->sin6_addr,
					          address, sizeof(address));
				}
				break;
			case RTA_AUTHOR:
				break;
			case RTA_BRD:
				break;
			}
#if 0
			syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
			       (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3],
			       (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]); 
			syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
			       (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7],
			       (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7]); 
#endif
			p += SA_RLEN(sa);
			addr = addr << 1;
		}
		syslog(LOG_INFO, "%s: %s/%d %s",
		       is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
		       address, prefixlen, ifname);
		for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) {
			if((0 == strcmp(address, lan_addr->str)) ||
			   (0 == strcmp(ifname, lan_addr->ifname)) ||
			   (ifam->ifam_index == lan_addr->index)) {
				if(family == AF_INET)
					AddDropMulticastMembership(s_ssdp, lan_addr, 0, is_del);
				else if(family == AF_INET6)
					AddDropMulticastMembership(s_ssdp6, lan_addr, 1, is_del);
				break;
			}
		}
		break;
	default:
		syslog(LOG_DEBUG, "Unknown RTM message : rtm->rtm_type=%d len=%d",
		       rtm->rtm_type, (int)len);
	}
#endif
	return 0;
}
示例#26
0
文件: ifaddrs.c 项目: AllardJ/Tomato
/* ====================================================================== */
int
getifaddrs_local (struct ifaddrs **ifap)
{
  int sd;
  struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
  /* - - - - - - - - - - - - - - - */
  int icnt;
  size_t dlen, xlen, nlen;
  uint32_t max_ifindex = 0;

  pid_t pid = getpid ();
  int seq;
  int result;
  int build;			/* 0 or 1 */

/* ---------------------------------- */
  /* initialize */
  icnt = dlen = xlen = nlen = 0;
  nlmsg_list = nlmsg_end = NULL;

  if (ifap)
    *ifap = NULL;

/* ---------------------------------- */
  /* open socket and bind */
  sd = nl_open ();
  if (sd < 0)
    return -1;

/* ---------------------------------- */
  /* gather info */
  if ((seq = nl_getlist (sd, 0, RTM_GETLINK, &nlmsg_list, &nlmsg_end)) < 0)
    {
      free_nlmsglist (nlmsg_list);
      nl_close (sd);
      return -1;
    }
  if ((seq = nl_getlist (sd, seq + 1, RTM_GETADDR,
			 &nlmsg_list, &nlmsg_end)) < 0)
    {
      free_nlmsglist (nlmsg_list);
      nl_close (sd);
      return -1;
    }

/* ---------------------------------- */
  /* Estimate size of result buffer and fill it */
  for (build = 0; build <= 1; build++)
    {
      struct ifaddrs *ifl = NULL, *ifa = NULL;
      struct nlmsghdr *nlh, *nlh0;
      void *data = NULL, *xdata = NULL, *ifdata = NULL;
      char *ifname = NULL, **iflist = NULL;
      uint16_t *ifflist = NULL;
      struct rtmaddr_ifamap ifamap;

      if (build)
	{
	  ifa = data = calloc (1,
			       NLMSG_ALIGN (sizeof (struct ifaddrs[icnt]))
			       + dlen + xlen + nlen);
	  ifdata = calloc (1,
			   NLMSG_ALIGN (sizeof (char *[max_ifindex + 1]))
			   +
			   NLMSG_ALIGN (sizeof (uint16_t[max_ifindex + 1])));
	  if (ifap != NULL)
	    *ifap = (ifdata != NULL) ? ifa : NULL;
	  else
	    {
	      free_data (data, ifdata);
	      result = 0;
	      break;
	    }
	  if (data == NULL || ifdata == NULL)
	    {
	      free_data (data, ifdata);
	      result = -1;
	      break;
	    }
	  ifl = NULL;
	  data += NLMSG_ALIGN (sizeof (struct ifaddrs)) * icnt;
	  xdata = data + dlen;
	  ifname = xdata + xlen;
	  iflist = ifdata;
	  ifflist =
	    ((void *) iflist) +
	    NLMSG_ALIGN (sizeof (char *[max_ifindex + 1]));
	}

      for (nlm = nlmsg_list; nlm; nlm = nlm->nlm_next)
	{
	  int nlmlen = nlm->size;
	  if (!(nlh0 = nlm->nlh))
	    continue;
	  for (nlh = nlh0;
	       NLMSG_OK (nlh, nlmlen); nlh = NLMSG_NEXT (nlh, nlmlen))
	    {
	      struct ifinfomsg *ifim = NULL;
	      struct ifaddrmsg *ifam = NULL;
	      struct rtattr *rta;

	      size_t nlm_struct_size = 0;
	      sa_family_t nlm_family = 0;
	      uint32_t nlm_scope = 0, nlm_index = 0;
#ifndef IFA_NETMASK
	      size_t sockaddr_size = 0;
	      uint32_t nlm_prefixlen = 0;
#endif
	      size_t rtasize;

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

	      /* check if the message is what we want */
	      if (nlh->nlmsg_pid != pid || nlh->nlmsg_seq != nlm->seq)
		continue;
	      if (nlh->nlmsg_type == NLMSG_DONE)
		{
		  break;	/* ok */
		}
	      switch (nlh->nlmsg_type)
		{
		case RTM_NEWLINK:
		  ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
		  nlm_struct_size = sizeof (*ifim);
		  nlm_family = ifim->ifi_family;
		  nlm_scope = 0;
		  nlm_index = ifim->ifi_index;
		  nlm_prefixlen = 0;
		  if (build)
		    ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags;
		  break;
		case RTM_NEWADDR:
		  ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
		  nlm_struct_size = sizeof (*ifam);
		  nlm_family = ifam->ifa_family;
		  nlm_scope = ifam->ifa_scope;
		  nlm_index = ifam->ifa_index;
		  nlm_prefixlen = ifam->ifa_prefixlen;
		  if (build)
		    ifa->ifa_flags = ifflist[nlm_index];
		  break;
		default:
		  continue;
		}

	      if (!build)
		{
		  if (max_ifindex < nlm_index)
		    max_ifindex = nlm_index;
		}
	      else
		{
		  if (ifl != NULL)
		    ifl->ifa_next = ifa;
		}

	      rtasize =
		NLMSG_PAYLOAD (nlh, nlmlen) - NLMSG_ALIGN (nlm_struct_size);
	      for (rta =
		   (struct rtattr *) (((char *) NLMSG_DATA (nlh)) +
				      NLMSG_ALIGN (nlm_struct_size));
		   RTA_OK (rta, rtasize); rta = RTA_NEXT (rta, rtasize))
		{
		  struct sockaddr **sap = NULL;
		  void *rtadata = RTA_DATA (rta);
		  size_t rtapayload = RTA_PAYLOAD (rta);
		  socklen_t sa_len;

		  switch (nlh->nlmsg_type)
		    {
		    case RTM_NEWLINK:
		      switch (rta->rta_type)
			{
			case IFLA_ADDRESS:
			case IFLA_BROADCAST:
			  if (build)
			    {
			      sap =
				(rta->rta_type ==
				 IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa->
				ifa_broadaddr;
			      *sap = (struct sockaddr *) data;
			    }
			  sa_len = ifa_sa_len (AF_PACKET, rtapayload);
			  if (rta->rta_type == IFLA_ADDRESS)
			    sockaddr_size = NLMSG_ALIGN (sa_len);
			  if (!build)
			    {
			      dlen += NLMSG_ALIGN (sa_len);
			    }
			  else
			    {
			      memset (*sap, 0, sa_len);
			      ifa_make_sockaddr (AF_PACKET, *sap, rtadata,
						 rtapayload, 0, 0);
			      ((struct sockaddr_ll *) *sap)->sll_ifindex =
				nlm_index;
			      ((struct sockaddr_ll *) *sap)->sll_hatype =
				ifim->ifi_type;
			      data += NLMSG_ALIGN (sa_len);
			    }
			  break;
			case IFLA_IFNAME:	/* Name of Interface */
			  if (!build)
			    nlen += NLMSG_ALIGN (rtapayload + 1);
			  else
			    {
			      ifa->ifa_name = ifname;
			      if (iflist[nlm_index] == NULL)
				iflist[nlm_index] = ifa->ifa_name;
			      strncpy (ifa->ifa_name, rtadata, rtapayload);
			      ifa->ifa_name[rtapayload] = '\0';
			      ifname += NLMSG_ALIGN (rtapayload + 1);
			    }
			  break;
			case IFLA_STATS:	/* Statistics of Interface */
			  if (!build)
			    xlen += NLMSG_ALIGN (rtapayload);
			  else
			    {
			      ifa->ifa_data = xdata;
			      memcpy (ifa->ifa_data, rtadata, rtapayload);
			      xdata += NLMSG_ALIGN (rtapayload);
			    }
			  break;
			case IFLA_UNSPEC:
			  break;
			case IFLA_MTU:
			  break;
			case IFLA_LINK:
			  break;
			case IFLA_QDISC:
			  break;
			default:
				;
			}
		      break;
		    case RTM_NEWADDR:
		      if (nlm_family == AF_PACKET)
			break;
		      switch (rta->rta_type)
			{
			case IFA_ADDRESS:
			  ifamap.address = rtadata;
			  ifamap.address_len = rtapayload;
			  break;
			case IFA_LOCAL:
			  ifamap.local = rtadata;
			  ifamap.local_len = rtapayload;
			  break;
			case IFA_BROADCAST:
			  ifamap.broadcast = rtadata;
			  ifamap.broadcast_len = rtapayload;
			  break;
#ifdef HAVE_IFADDRS_IFA_ANYCAST
			case IFA_ANYCAST:
			  ifamap.anycast = rtadata;
			  ifamap.anycast_len = rtapayload;
			  break;
#endif
			case IFA_LABEL:
			  if (!build)
			    nlen += NLMSG_ALIGN (rtapayload + 1);
			  else
			    {
			      ifa->ifa_name = ifname;
			      if (iflist[nlm_index] == NULL)
				iflist[nlm_index] = ifname;
			      strncpy (ifa->ifa_name, rtadata, rtapayload);
			      ifa->ifa_name[rtapayload] = '\0';
			      ifname += NLMSG_ALIGN (rtapayload + 1);
			    }
			  break;
			case IFA_UNSPEC:
			  break;
			case IFA_CACHEINFO:
			  break;
			default:
				;
			}
		    }
		}
	      if (nlh->nlmsg_type == RTM_NEWADDR && nlm_family != AF_PACKET)
		{
		  if (!ifamap.local)
		    {
		      ifamap.local = ifamap.address;
		      ifamap.local_len = ifamap.address_len;
		    }
		  if (!ifamap.address)
		    {
		      ifamap.address = ifamap.local;
		      ifamap.address_len = ifamap.local_len;
		    }
		  if (ifamap.address_len != ifamap.local_len ||
		      (ifamap.address != NULL &&
		       memcmp (ifamap.address, ifamap.local,
			       ifamap.address_len)))
		    {
		      /* p2p; address is peer and local is ours */
		      ifamap.broadcast = ifamap.address;
		      ifamap.broadcast_len = ifamap.address_len;
		      ifamap.address = ifamap.local;
		      ifamap.address_len = ifamap.local_len;
		    }
		  if (ifamap.address)
		    {
#ifndef IFA_NETMASK
		      sockaddr_size =
			NLMSG_ALIGN (ifa_sa_len
				     (nlm_family, ifamap.address_len));
#endif
		      if (!build)
			dlen +=
			  NLMSG_ALIGN (ifa_sa_len
				       (nlm_family, ifamap.address_len));
		      else
			{
			  ifa->ifa_addr = (struct sockaddr *) data;
			  ifa_make_sockaddr (nlm_family, ifa->ifa_addr,
					     ifamap.address,
					     ifamap.address_len, nlm_scope,
					     nlm_index);
			  data +=
			    NLMSG_ALIGN (ifa_sa_len
					 (nlm_family, ifamap.address_len));
			}
		    }
#ifdef IFA_NETMASK
		  if (ifamap.netmask)
		    {
		      if (!build)
			dlen +=
			  NLMSG_ALIGN (ifa_sa_len
				       (nlm_family, ifamap.netmask_len));
		      else
			{
			  ifa->ifa_netmask = (struct sockaddr *) data;
			  ifa_make_sockaddr (nlm_family, ifa->ifa_netmask,
					     ifamap.netmask,
					     ifamap.netmask_len, nlm_scope,
					     nlm_index);
			  data +=
			    NLMSG_ALIGN (ifa_sa_len
					 (nlm_family, ifamap.netmask_len));
			}
		    }
#endif
		  if (ifamap.broadcast)
		    {
		      if (!build)
			dlen +=
			  NLMSG_ALIGN (ifa_sa_len
				       (nlm_family, ifamap.broadcast_len));
		      else
			{
			  ifa->ifa_broadaddr = (struct sockaddr *) data;
			  ifa_make_sockaddr (nlm_family, ifa->ifa_broadaddr,
					     ifamap.broadcast,
					     ifamap.broadcast_len, nlm_scope,
					     nlm_index);
			  data +=
			    NLMSG_ALIGN (ifa_sa_len
					 (nlm_family, ifamap.broadcast_len));
			}
		    }
#ifdef HAVE_IFADDRS_IFA_ANYCAST
		  if (ifamap.anycast)
		    {
		      if (!build)
			dlen +=
			  NLMSG_ALIGN (ifa_sa_len
				       (nlm_family, ifamap.anycast_len));
		      else
			{
			  ifa->ifa_anycast = (struct sockaddr *) data;
			  ifa_make_sockaddr (nlm_family, ifa->ifa_anyaddr,
					     ifamap.anycast,
					     ifamap.anycast_len, nlm_scope,
					     nlm_index);
			  data +=
			    NLMSG_ALIGN (ifa_sa_len
					 (nlm_family, ifamap.anycast_len));
			}
		    }
#endif
		}
	      if (!build)
		{
#ifndef IFA_NETMASK
		  dlen += sockaddr_size;
#endif
		  icnt++;
		}
	      else
		{
		  if (ifa->ifa_name == NULL)
		    ifa->ifa_name = iflist[nlm_index];
#ifndef IFA_NETMASK
		  if (ifa->ifa_addr &&
		      ifa->ifa_addr->sa_family != AF_UNSPEC &&
		      ifa->ifa_addr->sa_family != AF_PACKET)
		    {
		      ifa->ifa_netmask = (struct sockaddr *) data;
		      ifa_make_sockaddr_mask (ifa->ifa_addr->sa_family,
					      ifa->ifa_netmask,
					      nlm_prefixlen);
		    }
		  data += sockaddr_size;
#endif
		  ifl = ifa++;
		}
	    }
	}
      if (!build)
	{
	  if (icnt == 0 && (dlen + nlen + xlen == 0))
	    {
	      if (ifap != NULL)
		*ifap = NULL;
	      break;		/* cannot found any addresses */
	    }
	}
      else
	free_data (NULL, ifdata);
    }

/* ---------------------------------- */
  /* Finalize */
  free_nlmsglist (nlmsg_list);
  nl_close (sd);
  return 0;
}
示例#27
0
文件: get-bind.c 项目: LazyZhu/srelay
int get_ifconf(int index, struct addrinfo *ba)
{
  int s;
  struct {
    struct nlmsghdr n;
    struct rtgenmsg g;
  } rreq;
  struct sockaddr_nl nladdr;
  char   buf[8192];
  struct iovec iov;
  struct msghdr msg = {
    (void*)&nladdr, sizeof(nladdr),
    &iov,   1,
    NULL,   0,
    0
  };
  pid_t pid;
  unsigned seq;
  int len;
  struct rtattr * rta;
  struct rtattr * tb[IFA_MAX+1];
  struct nlmsghdr *h;
  struct ifaddrmsg *ifa;
  int status;
  struct sockaddr_in *sin;

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

  rreq.n.nlmsg_len = sizeof(rreq);
  rreq.n.nlmsg_type = RTM_GETADDR;
  rreq.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
  rreq.n.nlmsg_pid = 0;
  rreq.n.nlmsg_seq = seq = 9998;
  rreq.g.rtgen_family = AF_INET;

  s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
  sendto(s, (void*)&rreq, sizeof(rreq), 0,
	 (struct sockaddr*)&nladdr, sizeof(nladdr));

  pid = getpid();
  iov.iov_base = buf;
  do {
    iov.iov_len = sizeof(buf);
    status = recvmsg(s, &msg, 0);
    h = (struct nlmsghdr*)buf;
  } while (h->nlmsg_pid != pid || h->nlmsg_seq != seq);

  close(s);
  /*
  msg_out(norm,"nlmsg_pid: %d, nlmsg_seq: %d",
	  h->nlmsg_pid, h->nlmsg_seq);
  */
  while (NLMSG_OK(h, status)) {
    memset(&tb, 0, sizeof(tb));
    len = h->nlmsg_len;
    ifa = NLMSG_DATA(h);
    rta = IFA_RTA(ifa);
    if (ifa->ifa_index == index) {
      while (RTA_OK(rta, len)) {
	if (rta->rta_type <= IFA_MAX)
	  tb[rta->rta_type] = rta;
	rta = RTA_NEXT(rta,len);
      }
      if (tb[IFA_ADDRESS]) {
	/*
	  char str[128];
	  inet_ntop(AF_INET, RTA_DATA(tb[IFA_ADDRESS]), str, sizeof(str));
	  msg_out(norm, "ADDRESS %s", str);
	*/
	ba->ai_family = AF_INET;         /* IPv4 */
	ba->ai_socktype = SOCK_STREAM;
	ba->ai_protocol = IPPROTO_IP;
	ba->ai_addrlen = sizeof(struct sockaddr_in);
	sin = (struct sockaddr_in *)ba->ai_addr;
	sin->sin_family = AF_INET;
	memcpy(&(sin->sin_addr), RTA_DATA(tb[IFA_ADDRESS]), 4);
	return(0);
      }
      /*
	if (tb[IFA_LOCAL]) {
	unsigned *d = RTA_DATA(tb[IFA_LOCAL]);
	msg_out(norm, "LOCAL %08x", *d);
	}
      */
    }
    h = NLMSG_NEXT(h, status);
  }
  return(-1);
}
示例#28
0
/**
 * In case one binds to 0.0.0.0/INADDR_ANY and wants to know which source
 * address will be used when sending a message this function can be used.
 * It will ask the routing code of the kernel for the PREFSRC
 */
int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source)
{
	int fd, rc;
	struct rtmsg *r;
	struct rtattr *rta;
        struct {
		struct nlmsghdr         n;
		struct rtmsg            r;
		char                    buf[1024];
        } req;

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

	fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
	if (fd < 0) {
		perror("nl socket");
		return -1;
	}

	/* Send a rtmsg and ask for a response */
        req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
        req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        req.n.nlmsg_type = RTM_GETROUTE;
        req.n.nlmsg_seq = 1;

	/* Prepare the routing request */
        req.r.rtm_family = AF_INET;

	/* set the dest */
	rta = NLMSG_TAIL(&req.n);
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(sizeof(*dest));
	memcpy(RTA_DATA(rta), dest, sizeof(*dest));

	/* update sizes for dest */
	req.r.rtm_dst_len = sizeof(*dest) * 8;
	req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_ALIGN(rta->rta_len);

	rc = send(fd, &req, req.n.nlmsg_len, 0);
	if (rc != req.n.nlmsg_len) {
		perror("short write");
		close(fd);
		return -2;
	}


	/* now receive a response and parse it */
	rc = recv(fd, &req, sizeof(req), 0);
	if (rc <= 0) {
		perror("short read");
		close(fd);
		return -3;
	}

	if (!NLMSG_OK(&req.n, rc) || req.n.nlmsg_type != RTM_NEWROUTE) {
		close(fd);
		return -4;
	}

	r = NLMSG_DATA(&req.n);
	rc -= NLMSG_LENGTH(sizeof(*r));
	rta = RTM_RTA(r);
	while (RTA_OK(rta, rc)) {
		if (rta->rta_type != RTA_PREFSRC) {
			rta = RTA_NEXT(rta, rc);
			continue;
		}

		/* we are done */
		memcpy(loc_source, RTA_DATA(rta), RTA_PAYLOAD(rta));
		close(fd);
		return 0;
	}

	close(fd);
	return -5;
}
示例#29
0
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
{
    struct ifaddrs *l_entry;

    char *l_index;
    char *l_name;
    char *l_addr;
    char *l_data;

    struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);

    size_t l_nameSize = 0;
    size_t l_addrSize = 0;
    size_t l_dataSize = 0;

    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    struct rtattr *l_rta;
    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
            case IFLA_ADDRESS:
            case IFLA_BROADCAST:
                l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
                break;
            case IFLA_IFNAME:
                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
                break;
            case IFLA_STATS:
                l_dataSize += NLMSG_ALIGN(l_rtaSize);
                break;
            default:
                break;
        }
    }

    l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
    if (l_entry == NULL)
    {
        return -1;
    }
    memset(l_entry, 0, sizeof(struct ifaddrs));
    l_entry->ifa_name = "";

    l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
    l_name = l_index + sizeof(int);
    l_addr = l_name + l_nameSize;
    l_data = l_addr + l_addrSize;

    /* Save the interface index so we can look it up when handling the
     * addresses.
     */
    memcpy(l_index, &l_info->ifi_index, sizeof(int));

    l_entry->ifa_flags = l_info->ifi_flags;

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
    {
        void *l_rtaData = RTA_DATA(l_rta);
        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
        switch(l_rta->rta_type)
        {
            case IFLA_ADDRESS:
            case IFLA_BROADCAST:
            {
                size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
                makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
                ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
                ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
                if(l_rta->rta_type == IFLA_ADDRESS)
                {
                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
                }
                else
                {
                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
                }
                l_addr += NLMSG_ALIGN(l_addrLen);
                break;
            }
            case IFLA_IFNAME:
                strncpy(l_name, l_rtaData, l_rtaDataSize);
                l_name[l_rtaDataSize] = '\0';
                l_entry->ifa_name = l_name;
                break;
            case IFLA_STATS:
                memcpy(l_data, l_rtaData, l_rtaDataSize);
                l_entry->ifa_data = l_data;
                break;
            default:
                break;
        }
    }

    addToEnd(p_resultList, l_entry);
    return 0;
}
示例#30
0
static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
{
	struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
	uint32_t attrs_len = IFA_PAYLOAD(hdr);
	struct rtattr *attr = IFA_RTA(ifa);
	struct ifa_cacheinfo *ci;
	char addr_str[256];
	char flags[256];

	tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
			colorize_start(bold),
			addr_family2str(ifa->ifa_family),
			colorize_end());
	tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
	tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
			colorize_start(bold),
			rtnl_addr_flags2str(ifa->ifa_flags, flags,
				sizeof(flags)),
			colorize_end());
	tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
			colorize_start(bold),
			scope2str(ifa->ifa_scope),
			colorize_end());
	tprintf(", Link Index %d ]\n", ifa->ifa_index);

	for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
		switch (attr->rta_type) {
		case IFA_LOCAL:
			attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case IFA_ADDRESS:
			attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
		case IFA_BROADCAST:
			attr_fmt(attr, "Broadcast %s",
					addr2str(ifa->ifa_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case IFA_MULTICAST:
			attr_fmt(attr, "Multicast %s",
					addr2str(ifa->ifa_family,
						RTA_DATA(attr), addr_str,
						sizeof(addr_str)));
			break;
		case IFA_ANYCAST:
			attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
				RTA_DATA(attr), addr_str, sizeof(addr_str)));
			break;
#ifdef IFA_FLAGS
		case IFA_FLAGS:
			attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
				colorize_start(bold),
				rtnl_addr_flags2str(RTA_INT(attr),
					flags, sizeof(flags)),
				colorize_end());
			break;
#endif
		case IFA_LABEL:
			attr_fmt(attr, "Label %s", RTA_STR(attr));
			break;
		case IFA_CACHEINFO:
			ci = RTA_DATA(attr);
			tprintf("\tA: Cache (");

			if (ci->ifa_valid == INFINITY)
				tprintf("valid lft(forever)");
			else
				tprintf("valid lft(%us)", ci->ifa_valid);

			if (ci->ifa_prefered == INFINITY)
				tprintf(", prefrd lft(forever)");
			else
				tprintf(", prefrd lft(%us)", ci->ifa_prefered);

			tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
			tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
			tprintf(", Len %lu\n", RTA_LEN(attr));
			break;
		}
	}
}