inetaddr.c

来自「GNet是一个简单的网络库。它是目标定向的」· C语言 代码 · 共 2,578 行 · 第 1/4 页

C
2,578
字号
  addr = GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr;  addr = g_ntohl(addr);  if ((addr & 0xFF000000) == (127 << 24))    return TRUE;  return FALSE;}/** *  gnet_inetaddr_is_multicast: *  @inetaddr: Address to check * *  Check if the address is a multicast address.  Multicast address *  are in the range 224.0.0.1 - 239.255.255.255 (ie, the top four *  bits are 1110). *  *  Returns: TRUE if the address is a multicast address; FALSE *  otherwise. * **/gboolean gnet_inetaddr_is_multicast (const GInetAddr* inetaddr){  guint addr;  g_return_val_if_fail (inetaddr != NULL, FALSE);  addr = GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr;  addr = g_htonl(addr);  if ((addr & 0xF0000000) == 0xE0000000)    return TRUE;  return FALSE;}/** *  gnet_inetaddr_is_broadcast: *  @inetaddr: Address to check * *  Check if the address is a broadcast address.  The broadcast *  address is 255.255.255.255.  (Network broadcast address are *  network dependent.) *  *  Returns: TRUE if the address is a broadcast address; FALSE *  otherwise. * **/gboolean gnet_inetaddr_is_broadcast (const GInetAddr* inetaddr){  guint addr;  g_return_val_if_fail (inetaddr != NULL, FALSE);  addr = GNET_SOCKADDR_IN(inetaddr->sa).sin_addr.s_addr;  if (addr == 0xFFFFFFFF)    return TRUE;  return FALSE;}/* **************************************** *//** *  gnet_inetaddr_hash: *  @p: Pointer to an #GInetAddr. * *  Hash the address.  This is useful for glib containers. * *  Returns: hash value. * **/guint gnet_inetaddr_hash (gconstpointer p){  const GInetAddr* ia;  guint32 port;  guint32 addr;  g_assert(p != NULL);  ia = (const GInetAddr*) p;  /* We do pay attention to network byte order just in case the hash     result is saved or sent to a different host.  */  port = (guint32) g_ntohs(((struct sockaddr_in*) &ia->sa)->sin_port);  addr = g_ntohl(((struct sockaddr_in*) &ia->sa)->sin_addr.s_addr);  return (port ^ addr);}/** *  gnet_inetaddr_equal: *  @p1: Pointer to first #GInetAddr. *  @p2: Pointer to second #GInetAddr. * *  Compare two #GInetAddr's.   * *  Returns: 1 if they are the same; 0 otherwise. * **/gint gnet_inetaddr_equal(gconstpointer p1, gconstpointer p2){  const GInetAddr* ia1 = (const GInetAddr*) p1;  const GInetAddr* ia2 = (const GInetAddr*) p2;  g_assert(p1 != NULL && p2 != NULL);  /* Note network byte order doesn't matter */  return ((GNET_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==	   GNET_SOCKADDR_IN(ia2->sa).sin_addr.s_addr) &&	  (GNET_SOCKADDR_IN(ia1->sa).sin_port ==	   GNET_SOCKADDR_IN(ia2->sa).sin_port));}/** *  gnet_inetaddr_noport_equal: *  @p1: Pointer to first GInetAddr. *  @p2: Pointer to second GInetAddr. * *  Compare two #GInetAddr's, but does not compare the port numbers. * *  Returns: 1 if they are the same; 0 otherwise. * **/gint gnet_inetaddr_noport_equal(gconstpointer p1, gconstpointer p2){  const GInetAddr* ia1 = (const GInetAddr*) p1;  const GInetAddr* ia2 = (const GInetAddr*) p2;  g_assert(p1 != NULL && p2 != NULL);  /* Note network byte order doesn't matter */  return (GNET_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==	  GNET_SOCKADDR_IN(ia2->sa).sin_addr.s_addr);}/* **************************************** */#ifndef GNET_WIN32  /*********** Unix code ***********//** *  gnet_inetaddr_gethostname: *  *  Get the primary host's name. * *  Returns: the name of the host; NULL if there was an error.  The *  caller is responsible for deleting the returned string. * **/gchar*gnet_inetaddr_gethostname(void){  gchar* name = NULL;  struct utsname myname;  if (uname(&myname) < 0)    return NULL;  if (!gnet_gethostbyname(myname.nodename, NULL, &name))    return NULL;  return name;}#else	/*********** Windows code ***********//* (Windows doesn't have uname */gchar*gnet_inetaddr_gethostname(void){  gchar* name = NULL;  int error = 0;  name = g_new0(char, 256);  error = gethostname(name, 256);  if (error)    {      g_free(name);      return NULL;    }  return name;}#endif		/*********** End Windows code ***********//** *  gnet_inetaddr_gethostaddr: *  *  Get the primary host's #GInetAddr. * *  Returns: the #GInetAddr of the host; NULL if there was an error. *  The caller is responsible for deleting the returned #GInetAddr. * **/GInetAddr* gnet_inetaddr_gethostaddr(void){  gchar* name;  GInetAddr* ia = NULL;  name = gnet_inetaddr_gethostname();  if (name != NULL)    {        ia = gnet_inetaddr_new(name, 0);      g_free(name);    }  return ia;}/* **************************************** *//** *  gnet_inetaddr_new_any: * *  Create a #GInetAddr with the address INADDR_ANY and port 0.  This *  is useful for creating default addresses for binding.  The *  address's name will be "<INADDR_ANY>". * *  Returns: INADDR_ANY #GInetAddr. * **/GInetAddr* gnet_inetaddr_new_any (void){  GInetAddr* ia;  struct sockaddr_in* sa_in;  ia = g_new0 (GInetAddr, 1);  ia->ref_count = 1;  sa_in = (struct sockaddr_in*) &ia->sa;  sa_in->sin_addr.s_addr = g_htonl(INADDR_ANY);  sa_in->sin_port = 0;  ia->name = g_strdup ("<INADDR_ANY>");  return ia;}/** *  gnet_inetaddr_autodetect_internet_interface: * *  Find an Internet interface.  Usually, this interface routes *  packets to and from the Internet.  It can be used to automatically *  configure simple servers that must advertise their address.  This *  sometimes doesn't work correctly when the user is behind a NAT. * *  Returns: Address of an Internet interface; NULL if it couldn't *  find one or there was an error. * **/GInetAddr* gnet_inetaddr_autodetect_internet_interface (void){  GInetAddr* jm_addr;  GInetAddr* iface;  /* First try to get the interface with a route to     junglemonkey.net (141.213.11.1).  This uses the connected UDP     socket method described by Stevens.  It does not work on all     systems.  (see Stevens UNPv1 pp 231-3) */  jm_addr = gnet_inetaddr_new_nonblock ("141.213.11.1", 0);  g_assert (jm_addr);  iface = gnet_inetaddr_get_interface_to (jm_addr);  gnet_inetaddr_delete (jm_addr);  /* We want an internet interface */  if (iface && gnet_inetaddr_is_internet(iface))    return iface;  gnet_inetaddr_delete (iface);  /* Try getting an internet interface from the list via     SIOCGIFCONF. (see Stevens UNPv1 pp 428-) */  iface = gnet_inetaddr_get_internet_interface ();  return iface;}/** *  gnet_inetaddr_get_interface_to: *  @addr: address * *  Figure out which local interface would be used to send a packet to *  @addr.  This works on some systems, but not others.  We recommend *  using gnet_inetaddr_autodetect_internet_interface() to find an *  Internet interface since it's more likely to work. * *  Returns: Address of an interface used to route packets to @addr; *  NULL if there is no such interface or the system does not support *  this check. * **/GInetAddr* gnet_inetaddr_get_interface_to (const GInetAddr* addr){  int sockfd;  struct sockaddr_in myaddr;  socklen_t len;  GInetAddr* iface;  g_return_val_if_fail (addr, NULL);  sockfd = socket (AF_INET, SOCK_DGRAM, 0);  if (sockfd == -1)    return NULL;  if (connect (sockfd, &addr->sa, sizeof(addr->sa)) == -1)    {      GNET_CLOSE_SOCKET(sockfd);      return NULL;    }  len = sizeof (myaddr);  if (getsockname (sockfd, (struct sockaddr*) &myaddr, &len) != 0)    {      GNET_CLOSE_SOCKET(sockfd);      return NULL;    }  iface = g_new0 (GInetAddr, 1);  iface->ref_count = 1;  memcpy (&iface->sa, (char*) &myaddr, sizeof (struct sockaddr_in));  return iface;}/** *  gnet_inetaddr_get_internet_interface: * *  Find an Internet interface.  This just calls *  gnet_inetaddr_list_interfaces() and returns the first one that *  passes gnet_inetaddr_is_internet().  This works well on some *  systems, but not so well on others.  We recommend using *  gnet_inetaddr_autodetect_internet_interface() to find an Internet *  interface since it's more likely to work. * *  Returns: Address of an Internet interface; NULL if there is no *  such interface or the system does not support this check. * **/GInetAddr* gnet_inetaddr_get_internet_interface (void){  GInetAddr* iface = NULL;  GList* interfaces;  GList* i;  /* Get a list of interfaces */  interfaces = gnet_inetaddr_list_interfaces ();  if (interfaces == NULL)    return NULL;  /* Find the first interface that's an internet interface */  for (i = interfaces; i != NULL; i = i->next)    {      GInetAddr* ia;      ia = (GInetAddr*) i->data;      if (gnet_inetaddr_is_internet (ia))	{	  iface = gnet_inetaddr_clone (ia);	  break;	}    }  /* If we didn't find one, return the first interface. */  if (iface == NULL)    iface = gnet_inetaddr_clone ((GInetAddr*) interfaces->data);  /* Delete the interface list */  for (i = interfaces; i != NULL; i = i->next)    gnet_inetaddr_delete ((GInetAddr*) i->data);  g_list_free (interfaces);  return iface;}/** *  gnet_inetaddr_is_internet_domainname: *  @name: Domain name to check * *  Check if the domain name is a sensible Internet domain name.  This *  function uses heuristics and does not use DNS (or even block). *  For example, "localhost" and "10.10.23.42" are not sensible *  Internet domain names.  (10.10.23.42 is a network address, but not *  accessible to the Internet at large.) * *  Returns: TRUE if @name is a sensible Internet domain name; FALSE *  otherwise. * **/gbooleangnet_inetaddr_is_internet_domainname (const gchar* name){  GInetAddr* addr;  g_return_val_if_fail (name, FALSE);  /* The name can't be localhost or localhost.localdomain */  if (!strcmp(name, "localhost") ||       !strcmp(name, "localhost.localdomain"))    {      return FALSE;    }  /* The name must have a dot in it */  if (!strchr(name, '.'))    {      return FALSE;    }	  /* If it's dotted decimal, make sure it's valid */  addr = gnet_inetaddr_new_nonblock (name, 0);  if (addr)    {      gboolean rv;      rv = gnet_inetaddr_is_internet (addr);      gnet_inetaddr_delete (addr);      if (!rv)	return FALSE;    }  return TRUE;}/* **************************************** */#ifndef GNET_WIN32		/* Unix specific version *//** *  gnet_inetaddr_list_interfaces: * *  Get a list of #GInetAddr interfaces's on this host.  This list *  includes all "up" Internet interfaces and the loopback interface, *  if it exists. * *  Note that the Windows version supports a maximum of 10 interfaces. *  In Windows NT, Service Pack 4 (or higher) is required. * *  Returns: A list of #GInetAddr's representing available interfaces. *  The caller should delete the list and the addresses. * **/GList* gnet_inetaddr_list_interfaces (void){  GList* list = NULL;  gint len, lastlen;  gchar* buf;  gchar* ptr;  gint sockfd;  struct ifconf ifc;  struct ifreq* ifr;  /* Create a dummy socket */  sockfd = socket(AF_INET, SOCK_DGRAM, 0);  if (sockfd == -1) return NULL;  len = 8 * sizeof(struct ifreq);  lastlen = 0;  /* Get the list of interfaces.  We might have to try multiple times     if there are a lot of interfaces. */  while(1)    {      buf = g_new0(gchar, len);            ifc.ifc_len = len;      ifc.ifc_buf = buf;      if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)	{	  /* Might have failed because our buffer was too small */	  if (errno != EINVAL || lastlen != 0)	    {	      g_free(buf);	      return NULL;	    }	}      else	{	  /* Break if we got all the interfaces */	  if (ifc.ifc_len == lastlen)	    break;	  lastlen = ifc.ifc_len;	}      /* Did not allocate big enough buffer - try again */      len += 8 * sizeof(struct ifreq);      g_free(buf);    }  /* Create the list.  Stevens has a much more complex way of doing     this, but his is probably much more correct portable.  */  for (ptr = buf; ptr < (buf + ifc.ifc_len); #ifdef HAVE_SOCKADDR_SA_LEN            ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len#else      ptr += sizeof(struct ifreq)#endif)    {      struct sockaddr addr;      int rv;      GInetAddr* ia;      ifr = (struct ifreq*) ptr;      /* Ignore non-AF_INET */      if (ifr->ifr_addr.sa_family != AF_INET)	continue;      /* FIX: Skip colons in name?  Can happen if aliases, maybe. */      /* Save the address - the next call will clobber it */      memcpy(&addr, &ifr->ifr_addr, sizeof(addr));            /* Get the flags */      rv = ioctl(sockfd, SIOCGIFFLAGS, ifr);      if (rv == -1)	continue;      /* Ignore entries that aren't up or loopback.  Someday we'll	 write an interface structure and include this stuff. */      if (!(ifr->ifr_flags & IFF_UP) ||	  (ifr->ifr_flags & IFF_LOOPBACK))	continue;      /* Create an InetAddr for this one and add it to our list */      ia = g_new0 (GInetAddr, 1);      ia->ref_count = 1;      memcpy(&ia->sa, &addr, sizeof(addr));      list = g_list_prepend (list, ia);    }  g_free (buf);  list = g_list_reverse (list);  return list;}#else /* GNET_WIN32 Windows specific version */GList* gnet_inetaddr_list_interfaces (void){  GList* list;  SOCKET s;  int wsError;  DWORD bytesReturned;  SOCKADDR_IN* pAddrInet;  u_long SetFlags;  INTERFACE_INFO localAddr[10];  /* Assumes there will be no more than 10 IP interfaces */  int numLocalAddr;   int i;  struct sockaddr addr;  GInetAddr *ia;  /*SOCKADDR_IN* pAddrInet2; */	/* For testing */  list = NULL;  if((s = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET)    {      return NULL;    }  /* Enumerate all IP interfaces */  wsError = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, &localAddr,		     sizeof(localAddr), &bytesReturned, NULL, NULL);  if (wsError == SOCKET_ERROR)    {      closesocket(s);      return NULL;    }  closesocket(s);  /* Display interface information */  numLocalAddr = (bytesReturned/sizeof(INTERFACE_INFO));  for (i=0; i<numLocalAddr; i++)     {      pAddrInet = (SOCKADDR_IN*)&localAddr[i].iiAddress;      memcpy(&addr, pAddrInet, sizeof(addr));      /* pAddrInet2 = (SOCKADDR_IN*)&addr; */	/*For testing */      SetFlags = localAddr[i].iiFlags;      if ((SetFlags & IFF_UP) || (SetFlags & IFF_LOOPBACK))	{	  /* Create an InetAddr for this one and add it to our list */	  ia = gnet_private_inetaddr_sockaddr_new(addr);	  if (ia != NULL)	    list = g_list_prepend(list, ia);	}    }  return list;}#endif /* end Windows specific gnet_inetaddr_list_interfaces */

⌨️ 快捷键说明

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