mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-24 02:47:52 +02:00
Unify address parsing for GInetAddress and GInetSocketAddress
This allows scope-ids to work for GInetAddress
This commit is contained in:
@@ -435,9 +435,6 @@ GInetAddress *
|
||||
g_inet_address_new_from_string (const gchar *string)
|
||||
{
|
||||
struct in_addr in_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
struct in6_addr in6_addr;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
@@ -447,13 +444,54 @@ g_inet_address_new_from_string (const gchar *string)
|
||||
*/
|
||||
g_networking_init ();
|
||||
|
||||
if (inet_pton (AF_INET, string, &in_addr) > 0)
|
||||
return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
|
||||
return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
|
||||
/* IPv6 address (or it's invalid). We use getaddrinfo() because
|
||||
* it will handle parsing a scope_id as well.
|
||||
*/
|
||||
if (strchr (string, ':'))
|
||||
{
|
||||
struct addrinfo *res;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET6,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_NUMERICHOST,
|
||||
};
|
||||
int status;
|
||||
GInetAddress *address = NULL;
|
||||
|
||||
status = getaddrinfo (string, NULL, &hints, &res);
|
||||
if (status == 0)
|
||||
{
|
||||
g_assert (res->ai_addrlen == sizeof (struct sockaddr_in6));
|
||||
struct sockaddr_in6 *sockaddr6 = (struct sockaddr_in6 *)res->ai_addr;
|
||||
address = g_inet_address_new_from_bytes_with_ipv6_info (((guint8 *)&sockaddr6->sin6_addr),
|
||||
G_SOCKET_FAMILY_IPV6,
|
||||
sockaddr6->sin6_flowinfo,
|
||||
sockaddr6->sin6_scope_id);
|
||||
freeaddrinfo (res);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct in6_addr in6_addr;
|
||||
g_debug ("getaddrinfo failed to resolve host string %s", string);
|
||||
|
||||
if (inet_pton (AF_INET6, string, &in6_addr) > 0)
|
||||
address = g_inet_address_new_from_bytes ((guint8 *)&in6_addr, G_SOCKET_FAMILY_IPV6);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IPv4 (or invalid). We don't want to use getaddrinfo() here,
|
||||
* because it accepts the stupid "IPv4 numbers-and-dots
|
||||
* notation" addresses that are never used for anything except
|
||||
* phishing. Since we don't have to worry about scope IDs for
|
||||
* IPv4, we can just use inet_pton().
|
||||
*/
|
||||
if (inet_pton (AF_INET, string, &in_addr) > 0)
|
||||
return g_inet_address_new_from_bytes ((guint8 *)&in_addr, G_SOCKET_FAMILY_IPV4);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -413,60 +413,16 @@ GSocketAddress *
|
||||
g_inet_socket_address_new_from_string (const char *address,
|
||||
guint port)
|
||||
{
|
||||
static struct addrinfo *hints, hints_struct;
|
||||
GSocketAddress *saddr;
|
||||
GInetAddress *iaddr;
|
||||
struct addrinfo *res;
|
||||
gint status;
|
||||
|
||||
if (strchr (address, ':'))
|
||||
{
|
||||
/* IPv6 address (or it's invalid). We use getaddrinfo() because
|
||||
* it will handle parsing a scope_id as well.
|
||||
*/
|
||||
iaddr = g_inet_address_new_from_string (address);
|
||||
if (!iaddr)
|
||||
return NULL;
|
||||
|
||||
if (G_UNLIKELY (g_once_init_enter_pointer (&hints)))
|
||||
{
|
||||
hints_struct.ai_family = AF_UNSPEC;
|
||||
hints_struct.ai_socktype = SOCK_STREAM;
|
||||
hints_struct.ai_protocol = 0;
|
||||
hints_struct.ai_flags = AI_NUMERICHOST;
|
||||
g_once_init_leave_pointer (&hints, &hints_struct);
|
||||
}
|
||||
|
||||
status = getaddrinfo (address, NULL, hints, &res);
|
||||
if (status != 0)
|
||||
return NULL;
|
||||
|
||||
if (res->ai_family == AF_INET6 &&
|
||||
res->ai_addrlen == sizeof (struct sockaddr_in6))
|
||||
{
|
||||
((struct sockaddr_in6 *)res->ai_addr)->sin6_port = g_htons (port);
|
||||
saddr = g_socket_address_new_from_native (res->ai_addr, res->ai_addrlen);
|
||||
}
|
||||
else
|
||||
saddr = NULL;
|
||||
|
||||
freeaddrinfo (res);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* IPv4 (or invalid). We don't want to use getaddrinfo() here,
|
||||
* because it accepts the stupid "IPv4 numbers-and-dots
|
||||
* notation" addresses that are never used for anything except
|
||||
* phishing. Since we don't have to worry about scope IDs for
|
||||
* IPv4, we can just use g_inet_address_new_from_string().
|
||||
*/
|
||||
iaddr = g_inet_address_new_from_string (address);
|
||||
if (!iaddr)
|
||||
return NULL;
|
||||
|
||||
g_warn_if_fail (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4);
|
||||
|
||||
saddr = g_inet_socket_address_new (iaddr, port);
|
||||
g_object_unref (iaddr);
|
||||
}
|
||||
saddr = g_inet_socket_address_new (iaddr, port);
|
||||
|
||||
g_object_unref (iaddr);
|
||||
return saddr;
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,9 @@ test_parse (void)
|
||||
addr = g_inet_address_new_from_string ("204.152.189.116");
|
||||
g_assert (addr != NULL);
|
||||
g_object_unref (addr);
|
||||
addr = g_inet_address_new_from_string ("::1%0");
|
||||
g_assert (addr != NULL);
|
||||
g_object_unref (addr);
|
||||
|
||||
addr = g_inet_address_new_from_string ("::1::2");
|
||||
g_assert (addr == NULL);
|
||||
@@ -206,12 +209,11 @@ test_socket_address (void)
|
||||
|
||||
g_object_unref (saddr);
|
||||
|
||||
addr = g_inet_address_new_from_string ("::1");
|
||||
addr = g_inet_address_new_from_string ("::1%25");
|
||||
saddr = G_INET_SOCKET_ADDRESS (g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
|
||||
"address", addr,
|
||||
"port", 308,
|
||||
"flowinfo", 10,
|
||||
"scope-id", 25,
|
||||
NULL));
|
||||
g_object_unref (addr);
|
||||
|
||||
|
Reference in New Issue
Block a user