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

📄 ifaddrs.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$Id: ifaddrs.c,v 1.4 2003/04/22 18:05:33 shemminger Exp $	*//* 	from USAGI: ifaddrs.c,v 1.20.2.1 2002/12/08 08:22:23 yoshfuji Exp *//*  * Copyright (C)2000 YOSHIFUJI Hideaki *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <string.h>#include <time.h>#include <malloc.h>#include <errno.h>#include <unistd.h>#define __set_errno(x)	errno = (x)#include <sys/socket.h>#include <asm/types.h>#include <linux/netlink.h>#include <linux/rtnetlink.h>#include <sys/types.h>#include <sys/socket.h>#include <netpacket/packet.h>#include <net/ethernet.h>	/* the L2 protocols */#include <sys/uio.h>#include <net/if.h>#include <net/if_arp.h>#include <ifaddrs.h>#include <netinet/in.h>#ifdef _USAGI_LIBINET6#include "libc-compat.h"#endif/* ====================================================================== */struct nlmsg_list{  struct nlmsg_list *nlm_next;  struct nlmsghdr *nlh;  int size;  time_t seq;};struct rtmaddr_ifamap{  void *address;  void *local;#ifdef IFA_NETMASK  void *netmask;#endif  void *broadcast;#ifdef HAVE_IFADDRS_IFA_ANYCAST  void *anycast;#endif  int address_len;  int local_len;#ifdef IFA_NETMASK  int netmask_len;#endif  int broadcast_len;#ifdef HAVE_IFADDRS_IFA_ANYCAST  int anycast_len;#endif};/* ====================================================================== */static size_tifa_sa_len (sa_family_t family, int len){  size_t size;  switch (family)    {    case AF_INET:      size = sizeof (struct sockaddr_in);      break;    case AF_INET6:      size = sizeof (struct sockaddr_in6);      break;    case AF_PACKET:      size = (size_t) (((struct sockaddr_ll *) NULL)->sll_addr) + len;      if (size < sizeof (struct sockaddr_ll))	size = sizeof (struct sockaddr_ll);      break;    default:      size = (size_t) (((struct sockaddr *) NULL)->sa_data) + len;      if (size < sizeof (struct sockaddr))	size = sizeof (struct sockaddr);    }  return size;}static voidifa_make_sockaddr (sa_family_t family,		   struct sockaddr *sa,		   void *p, size_t len, uint32_t scope, uint32_t scopeid){  if (sa == NULL)    return;  switch (family)    {    case AF_INET:      memcpy (&((struct sockaddr_in *) sa)->sin_addr, (char *) p, len);      break;    case AF_INET6:      memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, (char *) p, len);      if (IN6_IS_ADDR_LINKLOCAL (p) || IN6_IS_ADDR_MC_LINKLOCAL (p))	{	  ((struct sockaddr_in6 *) sa)->sin6_scope_id = scopeid;	}      break;    case AF_PACKET:      memcpy (((struct sockaddr_ll *) sa)->sll_addr, (char *) p, len);      ((struct sockaddr_ll *) sa)->sll_halen = len;      break;    default:      memcpy (sa->sa_data, p, len);      /*XXX*/ break;    }  sa->sa_family = family;#ifdef HAVE_SOCKADDR_SA_LEN  sa->sa_len = ifa_sa_len (family, len);#endif}static struct sockaddr *ifa_make_sockaddr_mask (sa_family_t family,			struct sockaddr *sa, uint32_t prefixlen){  int i;  char *p = NULL, c;  uint32_t max_prefixlen = 0;  if (sa == NULL)    return NULL;  switch (family)    {    case AF_INET:      memset (&((struct sockaddr_in *) sa)->sin_addr, 0,	      sizeof (((struct sockaddr_in *) sa)->sin_addr));      p = (char *) &((struct sockaddr_in *) sa)->sin_addr;      max_prefixlen = 32;      break;    case AF_INET6:      memset (&((struct sockaddr_in6 *) sa)->sin6_addr, 0,	      sizeof (((struct sockaddr_in6 *) sa)->sin6_addr));      p = (char *) &((struct sockaddr_in6 *) sa)->sin6_addr;#if 0				/* XXX: fill scope-id? */      if (IN6_IS_ADDR_LINKLOCAL (p) || IN6_IS_ADDR_MC_LINKLOCAL (p))	{	  ((struct sockaddr_in6 *) sa)->sin6_scope_id = scopeid;	}#endif      max_prefixlen = 128;      break;    default:      return NULL;    }  sa->sa_family = family;#ifdef HAVE_SOCKADDR_SA_LEN  sa->sa_len = ifa_sa_len (family, len);#endif  if (p)    {      if (prefixlen > max_prefixlen)	prefixlen = max_prefixlen;      for (i = 0; i < (prefixlen / 8); i++)	*p++ = 0xff;      c = 0xff;      c <<= (8 - (prefixlen % 8));      *p = c;    }  return sa;}/* ====================================================================== */static intnl_sendreq (int sd, int request, int flags, int *seq){  char reqbuf[NLMSG_ALIGN (sizeof (struct nlmsghdr)) +	      NLMSG_ALIGN (sizeof (struct rtgenmsg))];  struct sockaddr_nl nladdr;  struct nlmsghdr *req_hdr;  struct rtgenmsg *req_msg;  time_t t = time (NULL);  if (seq)    *seq = t;  memset (&reqbuf, 0, sizeof (reqbuf));  req_hdr = (struct nlmsghdr *) reqbuf;  req_msg = (struct rtgenmsg *) NLMSG_DATA (req_hdr);  req_hdr->nlmsg_len = NLMSG_LENGTH (sizeof (*req_msg));  req_hdr->nlmsg_type = request;  req_hdr->nlmsg_flags = flags | NLM_F_REQUEST;  req_hdr->nlmsg_pid = 0;  req_hdr->nlmsg_seq = t;  req_msg->rtgen_family = AF_UNSPEC;  memset (&nladdr, 0, sizeof (nladdr));  nladdr.nl_family = AF_NETLINK;  return (sendto (sd, (void *) req_hdr, req_hdr->nlmsg_len, 0,		  (struct sockaddr *) &nladdr, sizeof (nladdr)));}static intnl_recvmsg (int sd, int request, int seq,	    void *buf, size_t buflen, int *flags){  struct msghdr msg;  struct iovec iov = { buf, buflen };  struct sockaddr_nl nladdr;  int read_len;  for (;;)    {      msg.msg_name = (void *) &nladdr;      msg.msg_namelen = sizeof (nladdr);      msg.msg_iov = &iov;      msg.msg_iovlen = 1;      msg.msg_control = NULL;      msg.msg_controllen = 0;      msg.msg_flags = 0;      read_len = recvmsg (sd, &msg, 0);      if ((read_len < 0 && errno == EINTR) || (msg.msg_flags & MSG_TRUNC))	continue;      if (flags)	*flags = msg.msg_flags;      break;    }  return read_len;}static intnl_getmsg (int sd, int request, int seq, struct nlmsghdr **nlhp, int *done){  struct nlmsghdr *nh;  size_t bufsize = 65536, lastbufsize = 0;  void *buff = NULL;  int result = 0, read_size;  int msg_flags;  pid_t pid = getpid ();  for (;;)    {      void *newbuff = realloc (buff, bufsize);      if (newbuff == NULL || bufsize < lastbufsize)	{	  result = -1;	  break;	}      buff = newbuff;      result = read_size =	nl_recvmsg (sd, request, seq, buff, bufsize, &msg_flags);      if (read_size < 0 || (msg_flags & MSG_TRUNC))	{	  lastbufsize = bufsize;	  bufsize *= 2;	  continue;	}      if (read_size == 0)	break;      nh = (struct nlmsghdr *) buff;      for (nh = (struct nlmsghdr *) buff;	   NLMSG_OK (nh, read_size);	   nh = (struct nlmsghdr *) NLMSG_NEXT (nh, read_size))	{	  if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq)	    continue;	  if (nh->nlmsg_type == NLMSG_DONE)	    {	      (*done)++;	      break;		/* ok */	    }	  if (nh->nlmsg_type == NLMSG_ERROR)	    {	      struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nh);	      result = -1;	      if (nh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))		__set_errno (EIO);	      else		__set_errno (-nlerr->error);	      break;	    }	}      break;    }  if (result < 0)    if (buff)      {	int saved_errno = errno;	free (buff);	__set_errno (saved_errno);      }  *nlhp = (struct nlmsghdr *) buff;  return result;}static intnl_getlist (int sd, int seq,	    int request,	    struct nlmsg_list **nlm_list, struct nlmsg_list **nlm_end){  struct nlmsghdr *nlh = NULL;  int status;  int done = 0;  status = nl_sendreq (sd, request, NLM_F_ROOT | NLM_F_MATCH, &seq);  if (status < 0)    return status;  if (seq == 0)    seq = (int) time (NULL);  while (!done)    {      status = nl_getmsg (sd, request, seq, &nlh, &done);      if (status < 0)	return status;      if (nlh)	{	  struct nlmsg_list *nlm_next =	    (struct nlmsg_list *) malloc (sizeof (struct nlmsg_list));	  if (nlm_next == NULL)	    {	      int saved_errno = errno;	      free (nlh);	      __set_errno (saved_errno);	      status = -1;	    }	  else	    {	      nlm_next->nlm_next = NULL;	      nlm_next->nlh = (struct nlmsghdr *) nlh;	      nlm_next->size = status;	      nlm_next->seq = seq;	      if (*nlm_list == NULL)		{		  *nlm_list = nlm_next;		  *nlm_end = nlm_next;		}	      else		{		  (*nlm_end)->nlm_next = nlm_next;		  *nlm_end = nlm_next;		}	    }	}    }  return status >= 0 ? seq : status;}/* ---------------------------------------------------------------------- */static voidfree_nlmsglist (struct nlmsg_list *nlm0){  struct nlmsg_list *nlm, *nlm_next;  int saved_errno;  if (!nlm0)    return;  saved_errno = errno;  nlm = nlm0;  while (nlm)    {      if (nlm->nlh)	free (nlm->nlh);      nlm_next = nlm->nlm_next;      free(nlm);      nlm = nlm_next;    }  __set_errno (saved_errno);}static voidfree_data (void *data, void *ifdata){  int saved_errno = errno;  if (data != NULL)    free (data);  if (ifdata != NULL)    free (ifdata);  __set_errno (saved_errno);}/* ---------------------------------------------------------------------- */static voidnl_close (int sd){  int saved_errno = errno;  if (sd >= 0)    __close (sd);  __set_errno (saved_errno);}/* ---------------------------------------------------------------------- */static intnl_open (void){  struct sockaddr_nl nladdr;  int sd;  sd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);  if (sd < 0)    return -1;  memset (&nladdr, 0, sizeof (nladdr));  nladdr.nl_family = AF_NETLINK;  if (bind (sd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)    {      nl_close (sd);      return -1;    }  return sd;}/* ====================================================================== */intgetifaddrs (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;

⌨️ 快捷键说明

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