⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ifaddrs.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
  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;}/* ---------------------------------------------------------------------- */voidfreeifaddrs (struct ifaddrs *ifa){  free (ifa);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -