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 + -
显示快捷键?