示例#1
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;
}
示例#2
0
int main(){
	int soc;
	struct sockaddr_nl sa;
	
	struct {
		struct nlmsghdr nh;
		struct ifinfomsg ifi;
	} request;

	int seq = 100;
	int n;
	char buf[4096];
	struct nlmsghdr *nlhdr;

	/* Netlinkソケットの作成 */
	soc = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);

	/* sockaddr_nlの準備 */
	memset(&sa, 0, sizeof(sa));
	sa.nl_family = AF_NETLINK;
	sa.nl_pid = 0; /* kernel */
	sa.nl_groups = 0; /* ユニキャスト */

	/* カーネルへのリクエストメッセージの生成 */
	memset(&request, 0, sizeof(request));
	request.nh.nlmsg_len = sizeof(request);
	request.nh.nlmsg_type = RTM_GETLINK;
	request.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
	request.nh.nlmsg_pid = 0; /* 0なので宛先はカーネル */
	request.nh.nlmsg_seq = seq; /* 必要に応じて適切にseqを設定してください */
	request.ifi.ifi_family = ARPHRD_ETHER;

	/* カーネルへNetlinkメッセージを送信 */
	n = sendto(soc, (void *)&request, sizeof(request), 0,
			(struct sockaddr *)&sa, sizeof(sa));
	if (n < 0) {
		perror("sendto");
		return 1;
	}

	/* カーネルからの返答を受信する */
	n = recv(soc, buf, sizeof(buf), 0);
	if (n < 0) {
		perror("recvmsg");
		return 1;
	}

	//printf("recv\n");

	/* 受信したNetlinkメッセージを解析する */
	for (nlhdr = (struct nlmsghdr *)buf; NLMSG_OK(nlhdr, n);
			nlhdr = NLMSG_NEXT(nlhdr, n)) {
		struct ifinfomsg *ifimsg;
		struct rtattr *rta;
		int rtalist_len;

		/* Netlinkメッセージの長さとタイプを表示 */
		printf("=================================\n");
		printf("len : %d\n", nlhdr->nlmsg_len);
		printf("type : %d\n", nlhdr->nlmsg_type);

		/* RTM_NEWLINKというメッセージでリンク情報が返ってくる */
		if (nlhdr->nlmsg_type != RTM_NEWLINK) {
			printf("error : %d\n", nlhdr->nlmsg_type);
			continue;
		}

		/* Netlinkメッセージのデータ部分をifinfomsgとして処理 */
		ifimsg = NLMSG_DATA(nlhdr);
		if (ifimsg->ifi_family != AF_UNSPEC && ifimsg->ifi_family != AF_INET6) {
			printf("error family : %d\n", ifimsg->ifi_family);
			continue;
		}

		/* 各種パラメータを表示 */
	//	printf(" family : %d\n", ifimsg->ifi_family);
	//	printf(" type : %d\n", ifimsg->ifi_type);
		printf(" index : %d\n", ifimsg->ifi_index);
	//	printf(" flags : %d\n", ifimsg->ifi_flags);
	//	printf(" change : %d\n", ifimsg->ifi_change);

		/* ifinfomsgの次に付加されているrtattrメッセージを解析 */
		rtalist_len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
		for (rta = IFLA_RTA(ifimsg); RTA_OK(rta, rtalist_len);
				rta = RTA_NEXT(rta, rtalist_len)) {

//			printf(" type : %d\n", rta->rta_type);

			switch (rta->rta_type) {
				case IFLA_IFNAME:
					printf(" + %s\n", (char *)RTA_DATA(rta));
					break;

				case IFLA_MTU:
					printf(" + MTU : %d\n", *(int *)RTA_DATA(rta));
					break;

				case IFLA_LINK:
					printf(" + Link Type : %d\n", *(int *)RTA_DATA(rta));
					break;

				case IFLA_ADDRESS:
				case IFLA_BROADCAST:
					{
						unsigned char *a = RTA_DATA(rta);
						if (RTA_PAYLOAD(rta) == 6) {
							printf(" + %s : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
									rta->rta_type==IFLA_ADDRESS ? "Address" : "Broadcast",
									a[0], a[1], a[2], a[3], a[4], a[5]);
						}
					}
					break;

				case IFLA_STATS:
					{
						struct net_device_stats *nds = RTA_DATA(rta);
						if (RTA_PAYLOAD(rta) != (int)sizeof(struct net_device_stats)) {
						//	printf("SOMETHING WRONG!\n");
							break;
						}

						printf(" + stats : rxpkt=%ld, txpkt=%ld\n",
								nds->rx_packets, nds->tx_packets);
					}
					break;

				default:
				//	printf(" + other type : %d\n", rta->rta_type);
					break;
			}
		}
	}

	close(soc);
	return 0;
}
示例#3
0
static void
vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
		  struct hostapd_data *hapd)
{
	struct ifinfomsg *ifi;
	int attrlen, nlmsg_len, rta_len;
	struct rtattr *attr;
	char ifname[IFNAMSIZ + 1];

	if (len < sizeof(*ifi))
		return;

	ifi = NLMSG_DATA(h);

	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));

	attrlen = h->nlmsg_len - nlmsg_len;
	if (attrlen < 0)
		return;

	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);

	os_memset(ifname, 0, sizeof(ifname));
	rta_len = RTA_ALIGN(sizeof(struct rtattr));
	while (RTA_OK(attr, attrlen)) {
		if (attr->rta_type == IFLA_IFNAME) {
			int n = attr->rta_len - rta_len;
			if (n < 0)
				break;

			if ((size_t) n >= sizeof(ifname))
				n = sizeof(ifname) - 1;
			os_memcpy(ifname, ((char *) attr) + rta_len, n);

		}

		attr = RTA_NEXT(attr, attrlen);
	}

	if (!ifname[0])
		return;
	if (del && if_nametoindex(ifname)) {
		 /* interface still exists, race condition ->
		  * iface has just been recreated */
		return;
	}

	wpa_printf(MSG_DEBUG,
		   "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
		   del ? "DEL" : "NEW",
		   ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");

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

  if (ifap)
    *ifap = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			sa->sa_family = ifam->ifa_family;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		  rta = RTA_NEXT (rta, rtasize);
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return result;
}
static gboolean
read_netlink_messages (GSocket      *socket,
                       GIOCondition  condition,
                       gpointer      user_data)
{
  GNetworkMonitorNetlink *nl = user_data;
  GInputVector iv;
  gssize len;
  GSocketControlMessage **cmsgs = NULL;
  gint num_cmsgs = 0, i, flags;
  GError *error = NULL;
  GCredentials *creds;
  uid_t sender;
  struct nlmsghdr *msg;
  struct rtmsg *rtmsg;
  struct rtattr *attr;
  gsize attrlen;
  guint8 *dest, *gateway;
  gboolean retval = TRUE;

  iv.buffer = NULL;
  iv.size = 0;

  flags = MSG_PEEK | MSG_TRUNC;
  len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
                                  NULL, NULL, &flags, NULL, &error);
  if (len < 0)
    {
      g_warning ("Error on netlink socket: %s", error->message);
      g_error_free (error);
      if (nl->priv->dump_networks)
        finish_dump (nl);
      return FALSE;
    }

  iv.buffer = g_malloc (len);
  iv.size = len;
  len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
                                  &cmsgs, &num_cmsgs, NULL, NULL, &error);
  if (len < 0)
    {
      g_warning ("Error on netlink socket: %s", error->message);
      g_error_free (error);
      if (nl->priv->dump_networks)
        finish_dump (nl);
      return FALSE;
    }

  if (num_cmsgs != 1 || !G_IS_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]))
    goto done;

  creds = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]));
  sender = g_credentials_get_unix_user (creds, NULL);
  if (sender != 0)
    goto done;

  msg = (struct nlmsghdr *) iv.buffer;
  for (; len > 0; msg = NLMSG_NEXT (msg, len))
    {
      if (!NLMSG_OK (msg, (size_t) len))
        {
          g_warning ("netlink message was truncated; shouldn't happen...");
          retval = FALSE;
          goto done;
        }

      switch (msg->nlmsg_type)
        {
        case RTM_NEWROUTE:
        case RTM_DELROUTE:
          rtmsg = NLMSG_DATA (msg);

          if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6)
            continue;
          if (rtmsg->rtm_type == RTN_UNREACHABLE)
            continue;

          attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
          attr = RTM_RTA (rtmsg);
          dest = gateway = NULL;
          while (RTA_OK (attr, attrlen))
            {
              if (attr->rta_type == RTA_DST)
                dest = RTA_DATA (attr);
              else if (attr->rta_type == RTA_GATEWAY)
                gateway = RTA_DATA (attr);
              attr = RTA_NEXT (attr, attrlen);
            }

          if (dest || gateway)
            {
              if (msg->nlmsg_type == RTM_NEWROUTE)
                add_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
              else
                remove_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway);
              queue_request_dump (nl);
            }
          break;

        case NLMSG_DONE:
          finish_dump (nl);
          goto done;

        case NLMSG_ERROR:
          {
            struct nlmsgerr *e = NLMSG_DATA (msg);

            g_warning ("netlink error: %s", g_strerror (-e->error));
          }
          retval = FALSE;
          goto done;

        default:
          g_warning ("unexpected netlink message %d", msg->nlmsg_type);
          retval = FALSE;
          goto done;
        }
    }

 done:
  for (i = 0; i < num_cmsgs; i++)
    g_object_unref (cmsgs[i]);
  g_free (cmsgs);

  g_free (iv.buffer);

  if (!retval && nl->priv->dump_networks)
    finish_dump (nl);
  return retval;
}
示例#6
0
/* ====================================================================== */
int
getifaddrs (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;
}
示例#7
0
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	rtnl_doit_func doit;
	int sz_idx, kind;
	int min_len;
	int family;
	int type;
	int err;

	type = nlh->nlmsg_type;
	if (type > RTM_MAX)
		return -EOPNOTSUPP;

	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)
		return -EAFNOSUPPORT;

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

	if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN))
		return -EPERM;

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		rtnl_dumpit_func dumpit;

		dumpit = rtnl_get_dumpit(family, type);
		if (dumpit == NULL)
			return -EOPNOTSUPP;

		__rtnl_unlock();
		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
		rtnl_lock();
		return err;
	}

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

	min_len = rtm_min[sz_idx];
	if (nlh->nlmsg_len < min_len)
		return -EINVAL;

	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])
					return -EINVAL;
				rta_buf[flavor-1] = attr;
			}
			attr = RTA_NEXT(attr, attrlen);
		}
	}

	doit = rtnl_get_doit(family, type);
	if (doit == NULL)
		return -EOPNOTSUPP;

	return doit(skb, nlh, (void *)&rta_buf[0]);
}
示例#8
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);
}
示例#9
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);
}
示例#10
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);
    }
}
示例#11
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;
}
示例#12
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;
}
示例#13
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;
}
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;
}
示例#15
0
/* return value: 1 not valid, 0 valid, -1 error */
int iface_address_valid(union mysockaddr *maddr, int (*ipv4_callback)(), int (*ipv6_callback)())
{
  struct sockaddr_nl addr;
  struct nlmsghdr *h;
  ssize_t len;
  static unsigned int seq = 0;
  int family = AF_INET;

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

  addr.nl_family = AF_NETLINK;
  addr.nl_pad = 0;
  addr.nl_groups = 0;
  addr.nl_pid = 0; /* address to kernel */

 again:
  req.nlh.nlmsg_len = sizeof(req);
  req.nlh.nlmsg_type = RTM_GETADDR;
  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK;
  req.nlh.nlmsg_pid = 0;
  req.nlh.nlmsg_seq = ++seq;
  req.g.rtgen_family = family;

  /* Don't block in recvfrom if send fails */
  while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
		      (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());

  if (len == -1)
    return -1;

  while (1)
    {
      if ((len = netlink_recv()) == -1)
	{
	  if (errno == ENOBUFS)
	    {
	      sleep(1);
	      goto again;
	    }
	  return -1;
	}

      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
	if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid)
	  nl_routechange(h); /* May be multicast arriving async */
	else if (h->nlmsg_type == NLMSG_ERROR)
	  nl_err(h);
	else if (h->nlmsg_type == NLMSG_DONE)
	  {
#ifdef HAVE_IPV6
	    if (family == AF_INET && ipv6_callback)
	      {
		family = AF_INET6;
		goto again;
	      }
#endif
	    return 1;
	  }
	else if (h->nlmsg_type == RTM_NEWADDR)
	  {
	    struct ifaddrmsg *ifa = NLMSG_DATA(h);
	    struct rtattr *rta = IFA_RTA(ifa);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));

	    if (ifa->ifa_family == AF_INET)
	      {
		struct in_addr netmask, addr, broadcast;

		netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
		addr.s_addr = 0;
		broadcast.s_addr = 0;

		while (RTA_OK(rta, len1))
		  {
		    if (rta->rta_type == IFA_LOCAL)
		      addr = *((struct in_addr *)(rta+1));
		    else if (rta->rta_type == IFA_BROADCAST)
		      broadcast = *((struct in_addr *)(rta+1));

		    rta = RTA_NEXT(rta, len1);
		  }

		if (addr.s_addr && ipv4_callback)
		  if (!((*ipv4_callback)(addr, ifa->ifa_index, maddr, broadcast)))
		    return 0;
	      }
#ifdef HAVE_IPV6
	    else if (ifa->ifa_family == AF_INET6)
	      {
		struct in6_addr *addrp = NULL;
		while (RTA_OK(rta, len1))
		  {
		    if (rta->rta_type == IFA_ADDRESS)
		      addrp = ((struct in6_addr *)(rta+1));

		    rta = RTA_NEXT(rta, len1);
		  }

		if (addrp && ipv6_callback)
		  if (!((*ipv6_callback)(addrp, ifa->ifa_index, ifa->ifa_index, maddr)))
		    return 0;
	      }
#endif
	  }
    }
}
示例#16
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;
}
示例#17
0
static int
fillup_entry_info(netsnmp_arp_entry *entry, struct nlmsghdr *nlmp)
{
    struct ndmsg   *rtmp;
    struct rtattr  *tb[NDA_MAX + 1], *rta;
    int             length;

    rtmp = (struct ndmsg *) NLMSG_DATA(nlmp);
    switch (nlmp->nlmsg_type) {
    case RTM_NEWNEIGH:
        if (rtmp->ndm_state == NUD_FAILED)
            entry->flags = NETSNMP_ACCESS_ARP_ENTRY_FLAG_DELETE;
        else
            entry->flags = 0;
        break;
    case RTM_DELNEIGH:
        entry->flags = NETSNMP_ACCESS_ARP_ENTRY_FLAG_DELETE;
        break;
    case RTM_GETNEIGH:
        return 0;
    default:
        DEBUGMSGTL(("access:netlink:arp",
                    "Wrong Netlink message type %d\n", nlmp->nlmsg_type));
        return -1;
    }

    if (rtmp->ndm_state == NUD_NOARP) {
        /* NUD_NOARP is for broadcast addresses and similar,
         * drop them silently */
        return 0;
    }

    memset(tb, 0, sizeof(struct rtattr *) * (NDA_MAX + 1));
    length = nlmp->nlmsg_len - NLMSG_LENGTH(sizeof(*rtmp));
    rta = ((struct rtattr *) (((char *) (rtmp)) + NLMSG_ALIGN(sizeof(struct ndmsg))));
    while (RTA_OK(rta, length)) {
        if (rta->rta_type <= NDA_MAX)
            tb[rta->rta_type] = rta;
        rta = RTA_NEXT(rta, length);
    }

    /*
     * Fill up the index and addresses
     */
    entry->if_index = rtmp->ndm_ifindex;
    if (tb[NDA_DST]) {
        entry->arp_ipaddress_len = RTA_PAYLOAD(tb[NDA_DST]);
        if (entry->arp_ipaddress_len > sizeof(entry->arp_ipaddress)) {
            snmp_log(LOG_ERR, "netlink ip address length %d is too long\n",
                     entry->arp_ipaddress_len);
            return -1;
        }
        memcpy(entry->arp_ipaddress, RTA_DATA(tb[NDA_DST]),
               entry->arp_ipaddress_len);
    }
    if (tb[NDA_LLADDR]) {
        entry->arp_physaddress_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
        if (entry->arp_physaddress_len > sizeof(entry->arp_physaddress)) {
            snmp_log(LOG_ERR, "netlink hw address length %d is too long\n",
                     entry->arp_physaddress_len);
            return -1;
        }
        memcpy(entry->arp_physaddress, RTA_DATA(tb[NDA_LLADDR]),
               entry->arp_physaddress_len);
    }

    switch (rtmp->ndm_state) {
    case NUD_INCOMPLETE:
        entry->arp_state = INETNETTOMEDIASTATE_INCOMPLETE;
        break;
    case NUD_REACHABLE:
    case NUD_PERMANENT:
        entry->arp_state = INETNETTOMEDIASTATE_REACHABLE;
        break;
    case NUD_STALE:
        entry->arp_state = INETNETTOMEDIASTATE_STALE;
        break;
    case NUD_DELAY:
        entry->arp_state = INETNETTOMEDIASTATE_DELAY;
        break;
    case NUD_PROBE:
        entry->arp_state = INETNETTOMEDIASTATE_PROBE;
        break;
    case NUD_FAILED:
        entry->arp_state = INETNETTOMEDIASTATE_INVALID;
        break;
    case NUD_NONE:
        entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN;
        break;
    default:
        snmp_log(LOG_ERR, "Unrecognized ARP entry state %d", rtmp->ndm_state);
        break;
    }

    switch (rtmp->ndm_state) {
    case NUD_INCOMPLETE:
    case NUD_FAILED:
    case NUD_NONE:
        entry->arp_type = INETNETTOMEDIATYPE_INVALID;
        break;
    case NUD_REACHABLE:
    case NUD_STALE:
    case NUD_DELAY:
    case NUD_PROBE:
        entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC;
        break;
    case NUD_PERMANENT:
        entry->arp_type = INETNETTOMEDIATYPE_STATIC;
        break;
    default:
        entry->arp_type = INETNETTOMEDIATYPE_LOCAL;
        break;
    }

    return 1;
}
示例#18
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;
}
示例#19
0
/* family = AF_UNSPEC finds ARP table entries.
   family = AF_LOCAL finds MAC addresses. */
int iface_enumerate(int family, void *parm, int (*callback)())
{
  struct sockaddr_nl addr;
  struct nlmsghdr *h;
  ssize_t len;
  static unsigned int seq = 0;
  int callback_ok = 1, newaddr = 0;

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

  addr.nl_family = AF_NETLINK;
  addr.nl_pad = 0;
  addr.nl_groups = 0;
  addr.nl_pid = 0; /* address to kernel */
 
 again: 
  if (family == AF_UNSPEC)
    req.nlh.nlmsg_type = RTM_GETNEIGH;
  else if (family == AF_LOCAL)
    req.nlh.nlmsg_type = RTM_GETLINK;
  else
    req.nlh.nlmsg_type = RTM_GETADDR;

  req.nlh.nlmsg_len = sizeof(req);
  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; 
  req.nlh.nlmsg_pid = 0;
  req.nlh.nlmsg_seq = ++seq;
  req.g.rtgen_family = family; 

  /* Don't block in recvfrom if send fails */
  while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, 
		      (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
  
  if (len == -1)
    return 0;
    
  while (1)
    {
      if ((len = netlink_recv()) == -1)
	{
	  if (errno == ENOBUFS)
	    {
	      sleep(1);
	      goto again;
	    }
	  return 0;
	}

      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
	if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
	  {
	    /* May be multicast arriving async */
	    if (nl_async(h) && option_bool(OPT_CLEVERBIND))
	      newaddr = 1; 
	  }
	else if (h->nlmsg_type == NLMSG_DONE)
	  {
	    /* handle async new interface address arrivals, these have to be done
	       after we complete as we're not re-entrant */
	    if (newaddr) 
	      {
		enumerate_interfaces();
		create_bound_listeners(0);
	      }
	    
	    return callback_ok;
	  }
	else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
	  {
	    struct ifaddrmsg *ifa = NLMSG_DATA(h);  
	    struct rtattr *rta = IFA_RTA(ifa);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
	    
	    if (ifa->ifa_family == family)
	      {
		if (ifa->ifa_family == AF_INET)
		  {
		    struct in_addr netmask, addr, broadcast;
		    
		    netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
		    addr.s_addr = 0;
		    broadcast.s_addr = 0;
		    
		    while (RTA_OK(rta, len1))
		      {
			if (rta->rta_type == IFA_LOCAL)
			  addr = *((struct in_addr *)(rta+1));
			else if (rta->rta_type == IFA_BROADCAST)
			  broadcast = *((struct in_addr *)(rta+1));
			
			rta = RTA_NEXT(rta, len1);
		      }
		    
		    if (addr.s_addr && callback_ok)
		      if (!((*callback)(addr, ifa->ifa_index, netmask, broadcast, parm)))
			callback_ok = 0;
		  }
#ifdef HAVE_IPV6
		else if (ifa->ifa_family == AF_INET6)
		  {
		    struct in6_addr *addrp = NULL;
		    while (RTA_OK(rta, len1))
		      {
			if (rta->rta_type == IFA_ADDRESS)
			  addrp = ((struct in6_addr *)(rta+1)); 
			
			rta = RTA_NEXT(rta, len1);
		      }
		    
		    if (addrp && callback_ok)
		      if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope), 
					(int)(ifa->ifa_index), (int)(ifa->ifa_flags & IFA_F_TENTATIVE), parm)))
			callback_ok = 0;
		  }
#endif
	      }
	  }
	else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC)
	  {
	    struct ndmsg *neigh = NLMSG_DATA(h);  
	    struct rtattr *rta = NDA_RTA(neigh);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*neigh));
	    size_t maclen = 0;
	    char *inaddr = NULL, *mac = NULL;
	    
	    while (RTA_OK(rta, len1))
	      {
		if (rta->rta_type == NDA_DST)
		  inaddr = (char *)(rta+1);
		else if (rta->rta_type == NDA_LLADDR)
		  {
		    maclen = rta->rta_len - sizeof(struct rtattr);
		    mac = (char *)(rta+1);
		  }
		
		rta = RTA_NEXT(rta, len1);
	      }

	    if (inaddr && mac && callback_ok)
	      if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
		callback_ok = 0;
	  }
#ifdef HAVE_DHCP6
	else if (h->nlmsg_type == RTM_NEWLINK && family == AF_LOCAL)
	  {
	    struct ifinfomsg *link =  NLMSG_DATA(h);
	    struct rtattr *rta = IFLA_RTA(link);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*link));
	    char *mac = NULL;
	    size_t maclen = 0;

	    while (RTA_OK(rta, len1))
	      {
		if (rta->rta_type == IFLA_ADDRESS)
		  {
		    maclen = rta->rta_len - sizeof(struct rtattr);
		    mac = (char *)(rta+1);
		  }
		
		rta = RTA_NEXT(rta, len1);
	      }

	    if (mac && callback_ok && !((link->ifi_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) && 
		!((*callback)((int)link->ifi_index, (unsigned int)link->ifi_type, mac, maclen, parm)))
	      callback_ok = 0;
	  }
#endif
    }
}
示例#20
0
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
{
    struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
    struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);

    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;
    struct ifaddrs *l_entry;

    char *l_name;
    char *l_addr;

    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);
        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;
        }
    }

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

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

    l_entry->ifa_flags = l_info->ifa_flags;
    if(l_interface)
    {
        l_entry->ifa_flags |= l_interface->ifa_flags;
    }

    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
    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 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;
                    }
                }

                /* Apparently in a point-to-point network IFA_ADDRESS contains
                 * the dest address and IFA_LOCAL contains the local address
                 */
                if(l_rta->rta_type == IFA_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;
        }
        if(l_prefix % 8)
        {
            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);
    return 0;
}
示例#21
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)
{
	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_DUMP | NLM_F_REQUEST
		},
		.udr = {
			.sdiag_family = AF_UNIX,
			.udiag_ino = inode,
			.udiag_states = -1,
			.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
		}
	};
	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);
		} else {
			string_quote(path, outstr + 1,
				     path_len, QUOTE_0_TERMINATED);
		}
		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,
			.ndiag_show = NDIAG_SHOW_MEMINFO
		}
	};
	return send_query(tcp, fd, &req, sizeof(req));
}
示例#22
0
int print_linkinfo(const struct sockaddr_nl *who,
		   struct nlmsghdr *n, void *arg)
{
	FILE *fp = (FILE*)arg;
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	struct rtattr * tb[IFLA_MAX+1];
	int len = n->nlmsg_len;
	unsigned m_flag = 0;

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

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

	if (filter.ifindex && ifi->ifi_index != filter.ifindex)
		return 0;
	if (filter.up && !(ifi->ifi_flags&IFF_UP))
		return 0;

	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL) {
		fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
	}
	if (filter.label &&
	    (!filter.family || filter.family == AF_PACKET) &&
	    fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
		return 0;

	if (tb[IFLA_GROUP]) {
		int group = *(int*)RTA_DATA(tb[IFLA_GROUP]);
		if (filter.group != -1 && group != filter.group)
			return -1;
	}

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

	fprintf(fp, "%d: %s", ifi->ifi_index,
		tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>");

	if (tb[IFLA_LINK]) {
		SPRINT_BUF(b1);
		int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
		if (iflink == 0)
			fprintf(fp, "@NONE: ");
		else {
			fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
			m_flag = ll_index_to_flags(iflink);
			m_flag = !(m_flag & IFF_UP);
		}
	} else {
		fprintf(fp, ": ");
	}
	print_link_flags(fp, ifi->ifi_flags, m_flag);

	if (tb[IFLA_MTU])
		fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
	if (tb[IFLA_QDISC])
		fprintf(fp, "qdisc %s ", rta_getattr_str(tb[IFLA_QDISC]));
	if (tb[IFLA_MASTER]) {
		SPRINT_BUF(b1);
		fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
	}

	if (tb[IFLA_OPERSTATE])
		print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));

	if (do_link && tb[IFLA_LINKMODE])
		print_linkmode(fp, tb[IFLA_LINKMODE]);

	if (tb[IFLA_GROUP]) {
		SPRINT_BUF(b1);
		int group = *(int*)RTA_DATA(tb[IFLA_GROUP]);
		fprintf(fp, "group %s ", rtnl_group_n2a(group, b1, sizeof(b1)));
	}

	if (filter.showqueue)
		print_queuelen(fp, tb);

	if (!filter.family || filter.family == AF_PACKET) {
		SPRINT_BUF(b1);
		fprintf(fp, "%s", _SL_);
		fprintf(fp, "    link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));

		if (tb[IFLA_ADDRESS]) {
			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
						      RTA_PAYLOAD(tb[IFLA_ADDRESS]),
						      ifi->ifi_type,
						      b1, sizeof(b1)));
		}
		if (tb[IFLA_BROADCAST]) {
			if (ifi->ifi_flags&IFF_POINTOPOINT)
				fprintf(fp, " peer ");
			else
				fprintf(fp, " brd ");
			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
						      RTA_PAYLOAD(tb[IFLA_BROADCAST]),
						      ifi->ifi_type,
						      b1, sizeof(b1)));
		}
	}

	if (do_link && tb[IFLA_PROMISCUITY] && show_details)
		fprintf(fp, " promiscuity %u ",
			*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));

	if (do_link && tb[IFLA_LINKINFO] && show_details)
		print_linktype(fp, tb[IFLA_LINKINFO]);

	if (do_link && tb[IFLA_IFALIAS]) {
		fprintf(fp, "%s    alias %s", _SL_,
			rta_getattr_str(tb[IFLA_IFALIAS]));
	}

	if (do_link && show_stats) {
		if (tb[IFLA_STATS64])
			print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64]));
		else if (tb[IFLA_STATS])
			print_link_stats(fp, RTA_DATA(tb[IFLA_STATS]));
	}

	if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
		struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
		int rem = RTA_PAYLOAD(vflist);
		for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
			print_vfinfo(fp, i);
	}

	fprintf(fp, "\n");
	fflush(fp);
	return 0;
}
示例#23
0
int getgateway(struct iface *ifl_data)
{
	struct nlmsghdr *nl_msg;
	struct route_info *rt_info;
	char msg[BUFSIZE];
	
	int sd, len, msg_seq = 0;
	
	/* Create Socket */
	if ((sd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
		perror("Socket Creation: ");
	}
	
	memset(msg, 0, BUFSIZE);
	
	/* point the header and the msg structure pointers into the buffer */
	nl_msg = (struct nlmsghdr *) msg;
	
	/* Fill in the nlmsg header*/
	nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));  // Length of message
	nl_msg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table
	
	nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump
	nl_msg->nlmsg_seq = msg_seq++; // Sequence of the message packet.
	nl_msg->nlmsg_pid = getpid(); // PID of process sending the request.
	
	/* Send the request */
	if (send(sd, nl_msg, nl_msg->nlmsg_len, 0) < 0) {
		printf("Write To Socket Failed...\n");
		return -1;
	}
	
	/* Read the response */
	if ((len = socket_netlink_read(sd, msg, msg_seq, getpid())) < 0) {
		printf("Read From Socket Failed...\n");
		return -1;
	}
	
	/* Parse and print the response */
	rt_info = (struct route_info *) malloc(sizeof(struct route_info));
	
	fprintf(stdout, "Destination\tGateway\tInterface\tSource\n");
	
	for ( ; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len)) {
		memset(rt_info, 0, sizeof(struct route_info));
		
		
		
		struct rtmsg *rt_msg;
		struct rtattr *rt_attr;
		int rt_len = 0;
		
		rt_msg = (struct rtmsg *) NLMSG_DATA(nl_msg);
		
		/* If the route is not for AF_INET or does not belong to main routing table then return. */
		if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) {
			return;
		}
		printf("LINE: %d\n", __LINE__);
		/* get the rtattr field */
		rt_attr = (struct rtattr *) RTM_RTA(rt_msg);
		rt_len = RTM_PAYLOAD(nl_msg);
		for (  ; RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr, rt_len)) {
			switch (rt_attr->rta_type) {
				case RTA_OIF:
					if_indextoname(*(int *) RTA_DATA(rt_attr), rt_info->if_name);
					break;
				case RTA_GATEWAY:
					rt_info->gateway.s_addr= *(u_int *) RTA_DATA(rt_attr);
					break;
				case RTA_PREFSRC:
					rt_info->src_addr.s_addr= *(u_int *) RTA_DATA(rt_attr);
					break;
				case RTA_DST:
					rt_info->dst_addr.s_addr= *(u_int *) RTA_DATA(rt_attr);
					break;
			}
		}
		printf("LINE: %d\n", __LINE__);
		printf("iface for gateway: %s\n", ifl_data->if_name);
		printf("route for gateway: %s\n", rt_info->if_name);
		
		if (strcmp(ifl_data->if_name, rt_info->if_name) == 0) {
			if (rt_info->gateway.s_addr != 0) { // && (ifl_data->if_addr_gateway) && (strcmp(ifl_data->if_addr_gateway, "*\0") == 0)) {
				ifl_data->if_addr_gateway = malloc(512); //strlen((char *) inet_ntoa(rt_info->gateway)));
				memset(ifl_data->if_addr_gateway, '\0', 512);
				strcpy(ifl_data->if_addr_gateway, (char *) inet_ntoa(rt_info->gateway));
			}/* else {
				ifl_data->if_addr_gateway = malloc(3);
				strncpy(ifl_data->if_addr_gateway, "*\0", 2);
			}
			printf("\tip: %s\n", ifl_data->if_addr_gateway);*/
		}
		printf("LINE: %d\n", __LINE__);
		//route_parse(nl_msg, rt_info);
		
		
	}
	
	free(rt_info);
	close(sd);
	
	return 0;
}
示例#24
0
文件: route.c 项目: amitks/netlinkops
int  loop (int sock, struct sockaddr_nl *addr)
{
    int     received_bytes = 0;
    struct  nlmsghdr *nlh;
    char    destination_address[32];
    char    gateway_address[32];
    struct  rtmsg *route_entry;  /* This struct represent a route entry \
                                    in the routing table */
    struct  rtattr *route_attribute; /* This struct contain route \
                                            attributes (route type) */
    int     route_attribute_len = 0;
    char    buffer[BUFFER_SIZE];

    bzero(destination_address, sizeof(destination_address));
    bzero(gateway_address, sizeof(gateway_address));
    bzero(buffer, sizeof(buffer));

    /* Receiving netlink socket data */
    while (1)
    {
        received_bytes = recv(sock, buffer, sizeof(buffer), 0);
        if (received_bytes < 0)
            ERR_RET("recv");
        /* cast the received buffer */
        nlh = (struct nlmsghdr *) buffer;
        /* If we received all data ---> break */
        if (nlh->nlmsg_type == NLMSG_DONE)
            break;
        /* We are just intrested in Routing information */
        if (addr->nl_groups == RTMGRP_IPV4_ROUTE)
            break;
    }

    /* Reading netlink socket data */
    /* Loop through all entries */
    /* For more informations on some functions :
     * http://www.kernel.org/doc/man-pages/online/pages/man3/netlink.3.html
     * http://www.kernel.org/doc/man-pages/online/pages/man7/rtnetlink.7.html
     */

    for ( ; NLMSG_OK(nlh, received_bytes); \
                    nlh = NLMSG_NEXT(nlh, received_bytes))
    {
        /* Get the route data */
        route_entry = (struct rtmsg *) NLMSG_DATA(nlh);

        /* We are just intrested in main routing table */
        if (route_entry->rtm_table != RT_TABLE_MAIN)
            continue;

        /* Get attributes of route_entry */
        route_attribute = (struct rtattr *) RTM_RTA(route_entry);

        /* Get the route atttibutes len */
        route_attribute_len = RTM_PAYLOAD(nlh);
        /* Loop through all attributes */
        for ( ; RTA_OK(route_attribute, route_attribute_len); \
            route_attribute = RTA_NEXT(route_attribute, route_attribute_len))
        {
            /* Get the destination address */
            if (route_attribute->rta_type == RTA_DST)
            {
                inet_ntop(AF_INET, RTA_DATA(route_attribute), \
                        destination_address, sizeof(destination_address));
            }
            /* Get the gateway (Next hop) */
            if (route_attribute->rta_type == RTA_GATEWAY)
            {
                inet_ntop(AF_INET, RTA_DATA(route_attribute), \
                        gateway_address, sizeof(gateway_address));
            }
        }

        /* Now we can dump the routing attributes */
        if (nlh->nlmsg_type == RTM_DELROUTE)
            fprintf(stdout, "Deleting route to destination --> %s and gateway %s\n", \
                destination_address, gateway_address);
        if (nlh->nlmsg_type == RTM_NEWROUTE)
            printf("Adding route to destination --> %s and gateway %s\n", \
                            destination_address, gateway_address);
    }

    return 0;
}
示例#25
0
/* family = AF_UNSPEC finds ARP table entries.
   family = AF_LOCAL finds MAC addresses. */
int iface_enumerate(int family, void *parm, int (*callback)())
{
  struct sockaddr_nl addr;
  struct nlmsghdr *h;
  ssize_t len;
  static unsigned int seq = 0;
  int callback_ok = 1;

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

  addr.nl_family = AF_NETLINK;
  addr.nl_pad = 0;
  addr.nl_groups = 0;
  addr.nl_pid = 0; /* address to kernel */
 
 again: 
  if (family == AF_UNSPEC)
    req.nlh.nlmsg_type = RTM_GETNEIGH;
  else if (family == AF_LOCAL)
    req.nlh.nlmsg_type = RTM_GETLINK;
  else
    req.nlh.nlmsg_type = RTM_GETADDR;

  req.nlh.nlmsg_len = sizeof(req);
  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; 
  req.nlh.nlmsg_pid = 0;
  req.nlh.nlmsg_seq = ++seq;
  req.g.rtgen_family = family; 

  /* Don't block in recvfrom if send fails */
  while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, 
			  (struct sockaddr *)&addr, sizeof(addr))));

  if (errno != 0)
    return 0;
    
  while (1)
    {
      if ((len = netlink_recv()) == -1)
	{
	  if (errno == ENOBUFS)
	    {
	      sleep(1);
	      goto again;
	    }
	  return 0;
	}

      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
	if (h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
	  {
	    /* May be multicast arriving async */
	    nl_async(h);
	  }
	else if (h->nlmsg_seq != seq)
	  {
	    /* May be part of incomplete response to previous request after
	       ENOBUFS. Drop it. */
	    continue;
	  }
	else if (h->nlmsg_type == NLMSG_DONE)
	  return callback_ok;
	else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
	  {
	    struct ifaddrmsg *ifa = NLMSG_DATA(h);  
	    struct rtattr *rta = IFA_RTA(ifa);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
	    
	    if (ifa->ifa_family == family)
	      {
		if (ifa->ifa_family == AF_INET)
		  {
		    struct in_addr netmask, addr, broadcast;
		    char *label = NULL;

		    netmask.s_addr = htonl(~(in_addr_t)0 << (32 - ifa->ifa_prefixlen));

		    addr.s_addr = 0;
		    broadcast.s_addr = 0;
		    
		    while (RTA_OK(rta, len1))
		      {
			if (rta->rta_type == IFA_LOCAL)
			  addr = *((struct in_addr *)(rta+1));
			else if (rta->rta_type == IFA_BROADCAST)
			  broadcast = *((struct in_addr *)(rta+1));
			else if (rta->rta_type == IFA_LABEL)
			  label = RTA_DATA(rta);
			
			rta = RTA_NEXT(rta, len1);
		      }
		    
		    if (addr.s_addr && callback_ok)
		      if (!((*callback)(addr, ifa->ifa_index, label,  netmask, broadcast, parm)))
			callback_ok = 0;
		  }
#ifdef HAVE_IPV6
		else if (ifa->ifa_family == AF_INET6)
		  {
		    struct in6_addr *addrp = NULL;
		    u32 valid = 0, preferred = 0;
		    int flags = 0;
		    
		    while (RTA_OK(rta, len1))
		      {
			if (rta->rta_type == IFA_ADDRESS)
			  addrp = ((struct in6_addr *)(rta+1)); 
			else if (rta->rta_type == IFA_CACHEINFO)
			  {
			    struct ifa_cacheinfo *ifc = (struct ifa_cacheinfo *)(rta+1);
			    preferred = ifc->ifa_prefered;
			    valid = ifc->ifa_valid;
			  }
			rta = RTA_NEXT(rta, len1);
		      }
		    
		    if (ifa->ifa_flags & IFA_F_TENTATIVE)
		      flags |= IFACE_TENTATIVE;
		    
		    if (ifa->ifa_flags & IFA_F_DEPRECATED)
		      flags |= IFACE_DEPRECATED;
		    
		    if (!(ifa->ifa_flags & IFA_F_TEMPORARY))
		      flags |= IFACE_PERMANENT;
    		    
		    if (addrp && callback_ok)
		      if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope), 
					(int)(ifa->ifa_index), flags, 
					(int) preferred, (int)valid, parm)))
			callback_ok = 0;
		  }
#endif
	      }
	  }
	else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC)
	  {
	    struct ndmsg *neigh = NLMSG_DATA(h);  
	    struct rtattr *rta = NDA_RTA(neigh);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*neigh));
	    size_t maclen = 0;
	    char *inaddr = NULL, *mac = NULL;
	    
	    while (RTA_OK(rta, len1))
	      {
		if (rta->rta_type == NDA_DST)
		  inaddr = (char *)(rta+1);
		else if (rta->rta_type == NDA_LLADDR)
		  {
		    maclen = rta->rta_len - sizeof(struct rtattr);
		    mac = (char *)(rta+1);
		  }
		
		rta = RTA_NEXT(rta, len1);
	      }

	    if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
		inaddr && mac && callback_ok)
	      if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
		callback_ok = 0;
	  }
#ifdef HAVE_DHCP6
	else if (h->nlmsg_type == RTM_NEWLINK && family == AF_LOCAL)
	  {
	    struct ifinfomsg *link =  NLMSG_DATA(h);
	    struct rtattr *rta = IFLA_RTA(link);
	    unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*link));
	    char *mac = NULL;
	    size_t maclen = 0;

	    while (RTA_OK(rta, len1))
	      {
		if (rta->rta_type == IFLA_ADDRESS)
		  {
		    maclen = rta->rta_len - sizeof(struct rtattr);
		    mac = (char *)(rta+1);
		  }
		
		rta = RTA_NEXT(rta, len1);
	      }

	    if (mac && callback_ok && !((link->ifi_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) && 
		!((*callback)((int)link->ifi_index, (unsigned int)link->ifi_type, mac, maclen, parm)))
	      callback_ok = 0;
	  }
#endif
    }
}
示例#26
0
int
route_get(route_t *r, struct route_entry *entry)
{
	static int seq;
	struct nlmsghdr *nmsg;
	struct rtmsg *rmsg;
	struct rtattr *rta;
	struct sockaddr_nl snl;
	struct iovec iov;
	struct msghdr msg;
	u_char buf[512];
	int i, af, alen;

	switch (entry->route_dst.addr_type) {
	case ADDR_TYPE_IP:
		af = AF_INET;
		alen = IP_ADDR_LEN;
		break;
	case ADDR_TYPE_IP6:
		af = AF_INET6;
		alen = IP6_ADDR_LEN;
		break;
	default:
		errno = EINVAL;
		return (-1);
	}
	memset(buf, 0, sizeof(buf));

	nmsg = (struct nlmsghdr *)buf;
	nmsg->nlmsg_len = NLMSG_LENGTH(sizeof(*nmsg)) + RTA_LENGTH(alen);
	nmsg->nlmsg_flags = NLM_F_REQUEST;
	nmsg->nlmsg_type = RTM_GETROUTE;
	nmsg->nlmsg_seq = ++seq;

	rmsg = (struct rtmsg *)(nmsg + 1);
	rmsg->rtm_family = af;
	rmsg->rtm_dst_len = entry->route_dst.addr_bits;
	
	rta = RTM_RTA(rmsg);
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(alen);

	/* XXX - gross hack for default route */
	if (af == AF_INET && entry->route_dst.addr_ip == IP_ADDR_ANY) {
		i = htonl(0x60060606);
		memcpy(RTA_DATA(rta), &i, alen);
	} else
		memcpy(RTA_DATA(rta), entry->route_dst.addr_data8, alen);
	
	memset(&snl, 0, sizeof(snl));
	snl.nl_family = AF_NETLINK;

	iov.iov_base = nmsg;
	iov.iov_len = nmsg->nlmsg_len;
	
	memset(&msg, 0, sizeof(msg));
	msg.msg_name = &snl;
	msg.msg_namelen = sizeof(snl);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	
	if (sendmsg(r->nlfd, &msg, 0) < 0)
		return (-1);

	iov.iov_base = buf;
	iov.iov_len = sizeof(buf);
	
	if ((i = recvmsg(r->nlfd, &msg, 0)) <= 0)
		return (-1);

	if (nmsg->nlmsg_len < (int)sizeof(*nmsg) || nmsg->nlmsg_len > i ||
	    nmsg->nlmsg_seq != seq) {
		errno = EINVAL;
		return (-1);
	}
	if (nmsg->nlmsg_type == NLMSG_ERROR)
		return (-1);
	
	i -= NLMSG_LENGTH(sizeof(*nmsg));
	
	while (RTA_OK(rta, i)) {
		if (rta->rta_type == RTA_GATEWAY) {
			entry->route_gw.addr_type = entry->route_dst.addr_type;
			memcpy(entry->route_gw.addr_data8, RTA_DATA(rta), alen);
			entry->route_gw.addr_bits = alen * 8;
			return (0);
		}
		rta = RTA_NEXT(rta, i);
	}
	errno = ESRCH;
	
	return (-1);
}
示例#27
0
static int
parse_address(struct nlmsghdr *nh)
{
    int len;
    struct kernel_address kaddr;
    struct ifaddrmsg *ifa = NULL;
    struct rtattr *rta = NULL;
    unsigned int rta_len;
    int is_v4 = 0;

    len = nh->nlmsg_len;

    ifa = (struct ifaddrmsg*)NLMSG_DATA(nh);
    len -= NLMSG_LENGTH(0);

    memset(&kaddr, 0, sizeof(kaddr));
    kaddr.sa.sa_family = ifa->ifa_family;

    if (kaddr.sa.sa_family != AF_INET && kaddr.sa.sa_family != AF_INET6) {
        log_dbg(LOG_DEBUG_KERNEL, "Unknown family: %d\n", kaddr.sa.sa_family);
        return -1;
    }
    is_v4 = kaddr.sa.sa_family == AF_INET;

    rta = IFA_RTA(ifa);
    len -= NLMSG_ALIGN(sizeof(*ifa));

#define COPY_ADDR(d, s)                                                 \
    do {                                                                \
        if(!is_v4) {                                                    \
            assert(rta_len >= 16);                                      \
            memcpy(&d.sin6.sin6_addr, s, 16);                           \
        }else {                                                         \
            assert(rta_len >= 4);                                       \
            memcpy(&d.sin.sin_addr, s, 4);                              \
        }                                                               \
    } while(0)

    for(; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
        rta_len = RTA_PAYLOAD(rta);
        switch (rta->rta_type) {
        case IFA_UNSPEC: break;
        case IFA_ADDRESS:
            COPY_ADDR(kaddr, RTA_DATA(rta));
            break;

        case IFA_LOCAL:
            COPY_ADDR(kaddr, RTA_DATA(rta));
            kaddr.flags |= ADDR_LOCAL;
            break;
        default:
            break;
        }
    }
#undef COPY_ADDR
#undef GET_PLEN

    if (nh->nlmsg_type == RTM_NEWADDR)
        addr_add(&addresses, &kaddr);
    else
        addr_del(addresses, &kaddr);

    return 0;
}
示例#28
0
void
ProcessInterfaceWatchNotify(int s)
{
	char buffer[4096];
	struct iovec iov;
	struct msghdr hdr;
	struct nlmsghdr *nlhdr;
	struct ifinfomsg *ifi;
	struct ifaddrmsg *ifa;
	int len;

	struct rtattr *rth;
	int rtl;

	unsigned int ext_if_name_index = 0;

	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;
	}

	if(ext_if_name) {
		ext_if_name_index = if_nametoindex(ext_if_name);
	}

	for (nlhdr = (struct nlmsghdr *) buffer;
	     NLMSG_OK (nlhdr, len);
	     nlhdr = NLMSG_NEXT (nlhdr, len))
	{
		if (nlhdr->nlmsg_type == NLMSG_DONE)
			break;
		switch(nlhdr->nlmsg_type) {
		case RTM_DELLINK:
			ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
			/*if (ProcessInterfaceDown(ifi) < 0)
				syslog(LOG_ERR, "ProcessInterfaceDown(ifi) failed");*/
			break;
		case RTM_NEWLINK:
			ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
			/*if (ProcessInterfaceUp(ifi) < 0)
				syslog(LOG_ERR, "ProcessInterfaceUp(ifi) failed");*/
			break;
		case RTM_NEWADDR:
			/* see /usr/include/linux/netlink.h
			 * and /usr/include/linux/rtnetlink.h */
			ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr);
			syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR");
			for(rth = IFA_RTA(ifa), rtl = IFA_PAYLOAD(nlhdr);
			    rtl && RTA_OK(rth, rtl);
			    rth = RTA_NEXT(rth, rtl)) {
				syslog(LOG_DEBUG, " - %u - %s type=%d",
				       ifa->ifa_index, inet_ntoa(*((struct in_addr *)RTA_DATA(rth))),
				       rth->rta_type);
			}
			if(ifa->ifa_index == ext_if_name_index) {
				should_send_public_address_change_notif = 1;
			}
			break;
		case RTM_DELADDR:
			ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr);
			syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR");
			if(ifa->ifa_index == ext_if_name_index) {
				should_send_public_address_change_notif = 1;
			}
			break;
		default:
			syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify type %d ignored", nlhdr->nlmsg_type);
		}
	}

}
示例#29
0
Ref<RouteInfoList> RouteInfo::queryTable()
{
    Ref<RouteInfoList> list = RouteInfoList::create();

    int fd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd == -1) FLUX_SYSTEM_DEBUG_ERROR(errno);

    struct sockaddr_nl src;
    memclr(&src, sizeof(src));
    src.nl_family = AF_NETLINK;
    src.nl_pid = ::getpid();
    if (::bind(fd, (struct sockaddr *)&src, (socklen_t)sizeof(src)) == -1)
        FLUX_SYSTEM_DEBUG_ERROR(errno);

    // send request
    {
        size_t msgLen = NLMSG_LENGTH(sizeof(struct rtmsg));
        struct nlmsghdr *msg = (struct nlmsghdr *)flux::malloc(msgLen);
        int seq = 0;

        memclr(msg, msgLen);
        msg->nlmsg_type = RTM_GETROUTE;
        msg->nlmsg_len = msgLen;
        msg->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
        msg->nlmsg_pid = src.nl_pid;
        msg->nlmsg_seq = seq++;

        struct rtmsg *data = (struct rtmsg *)NLMSG_DATA(msg);
        data->rtm_table = RT_TABLE_DEFAULT;
        data->rtm_protocol = RTPROT_UNSPEC;

        struct sockaddr_nl dst;
        memclr(&dst, sizeof(dst));
        dst.nl_family = AF_NETLINK;

        struct msghdr hdr;
        memclr(&hdr, sizeof(hdr));

        struct iovec iov = { msg, msgLen };
        hdr.msg_iov = &iov;
        hdr.msg_iovlen = 1;
        hdr.msg_name = (void *)&dst;
        hdr.msg_namelen = sizeof(dst);

        if (::sendmsg(fd, &hdr, 0/*flags*/) == -1)
            FLUX_SYSTEM_DEBUG_ERROR(errno);

        flux::free(msg);
    }

    typedef Map<int, Ref<NetworkInterface> > InterfaceByIndex;
    Ref<InterfaceByIndex> interfaceByIndex = InterfaceByIndex::create();

    // process reply
    {
        struct msghdr hdr;
        memclr(&hdr, sizeof(hdr));

        ssize_t bufSize = ::recvmsg(fd, &hdr, MSG_PEEK|MSG_TRUNC);
        if (bufSize < 0) FLUX_SYSTEM_DEBUG_ERROR(errno);

        void *buf = flux::malloc(bufSize);
        if (!buf) FLUX_SYSTEM_DEBUG_ERROR(errno);

        struct iovec iov = { buf, (size_t)bufSize };
        hdr.msg_iov = &iov;
        hdr.msg_iovlen = 1;
        ssize_t bufFill = ::recvmsg(fd, &hdr, 0/*flags*/);

        if (::close(fd) == -1)
            FLUX_SYSTEM_DEBUG_ERROR(errno);

        struct nlmsghdr *msg = (struct nlmsghdr *)buf;

        for (;NLMSG_OK(msg, unsigned(bufFill)); msg = NLMSG_NEXT(msg, bufFill))
        {
            unsigned msgType = msg->nlmsg_type;

            if (msgType == RTM_NEWROUTE) {
                struct rtmsg *data = (struct rtmsg *)NLMSG_DATA(msg);
                struct rtattr *attr = (struct rtattr *)RTM_RTA(data);
                int attrFill = NLMSG_PAYLOAD(msg, sizeof(struct rtmsg));

                Ref<RouteInfo> info = RouteInfo::create();
                list->append(info);
                info->sourceMask_ = data->rtm_src_len;
                info->destinationMask_ = data->rtm_dst_len;

                for (;RTA_OK(attr, attrFill); attr = RTA_NEXT(attr, attrFill))
                {
                    unsigned attrType = attr->rta_type;

                    if (
                        attrType == RTA_DST ||
                        attrType == RTA_SRC ||
                        attrType == RTA_GATEWAY
                    ) {
                        Ref<SocketAddress> address;
                        struct sockaddr_in addr4;
                        struct sockaddr_in6 addr6;
                        if (data->rtm_family == AF_INET) {
                            memclr(&addr4, sizeof(addr4));
                            // addr.sin_len = sizeof(addr);
                            *(uint8_t *)&addr4 = sizeof(addr4); // uggly, but safe HACK, for BSD4.4
                            addr4.sin_family = AF_INET;
                            addr4.sin_addr = *(struct in_addr *)RTA_DATA(attr);
                            address = SocketAddress::create(&addr4);
                        }
                        else if (data->rtm_family == AF_INET6) {
                            memclr(&addr6, sizeof(addr6));
                            #ifdef SIN6_LEN
                            addr.sin6_len = sizeof(addr6);
                            #endif
                            addr6.sin6_family = AF_INET6;
                            addr6.sin6_addr = *(struct in6_addr *)RTA_DATA(attr);
                            // addr6.sin6_scope_id = data->rtm_scope;
                            address = SocketAddress::create(&addr6);
                        }
                        if (attrType == RTA_DST)
                            info->destination_ = address;
                        else if (attrType == RTA_SRC)
                            info->source_ = address;
                        else if (attrType == RTA_GATEWAY)
                            info->gateway_ = address;
                    }
                    else if (
                        attrType == RTA_IIF ||
                        attrType == RTA_OIF
                    ) {
                        int index = *(int *)RTA_DATA(attr);
                        Ref<NetworkInterface> interface;
                        if (!interfaceByIndex->lookup(index, &interface)) {
                            interface = NetworkInterface::getLink(index);
                            interfaceByIndex->insert(index, interface);
                        }
                        if (attrType == RTA_IIF)
                            info->inputInterface_ = interface->name();
                        else
                            info->outputInterface_ = interface->name();
                    }
                    else if (attrType == RTA_PRIORITY) {
                        info->priority_ = *(int *)RTA_DATA(attr);
                    }
                    else if (attrType == RTA_METRICS) {
                        info->metric_ =  *(int *)RTA_DATA(attr);
                    }
                }
            }
            else if (msgType == NLMSG_DONE) { // paranoid HACK
                break;
            }
        }

        flux::free(buf);
    }

    return list;
}
/** 
 *  @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;
}