mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-19 15:18:55 +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)
|
g_inet_address_new_from_string (const gchar *string)
|
||||||
{
|
{
|
||||||
struct in_addr in_addr;
|
struct in_addr in_addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct in6_addr in6_addr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
g_return_val_if_fail (string != NULL, NULL);
|
||||||
|
|
||||||
@@ -447,13 +444,54 @@ g_inet_address_new_from_string (const gchar *string)
|
|||||||
*/
|
*/
|
||||||
g_networking_init ();
|
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
|
#ifdef HAVE_IPV6
|
||||||
else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
|
/* IPv6 address (or it's invalid). We use getaddrinfo() because
|
||||||
return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
|
* 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
|
#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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -413,60 +413,16 @@ GSocketAddress *
|
|||||||
g_inet_socket_address_new_from_string (const char *address,
|
g_inet_socket_address_new_from_string (const char *address,
|
||||||
guint port)
|
guint port)
|
||||||
{
|
{
|
||||||
static struct addrinfo *hints, hints_struct;
|
|
||||||
GSocketAddress *saddr;
|
GSocketAddress *saddr;
|
||||||
GInetAddress *iaddr;
|
GInetAddress *iaddr;
|
||||||
struct addrinfo *res;
|
|
||||||
gint status;
|
|
||||||
|
|
||||||
if (strchr (address, ':'))
|
iaddr = g_inet_address_new_from_string (address);
|
||||||
{
|
if (!iaddr)
|
||||||
/* IPv6 address (or it's invalid). We use getaddrinfo() because
|
return NULL;
|
||||||
* it will handle parsing a scope_id as well.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (G_UNLIKELY (g_once_init_enter_pointer (&hints)))
|
saddr = g_inet_socket_address_new (iaddr, port);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
g_object_unref (iaddr);
|
||||||
return saddr;
|
return saddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,9 @@ test_parse (void)
|
|||||||
addr = g_inet_address_new_from_string ("204.152.189.116");
|
addr = g_inet_address_new_from_string ("204.152.189.116");
|
||||||
g_assert (addr != NULL);
|
g_assert (addr != NULL);
|
||||||
g_object_unref (addr);
|
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");
|
addr = g_inet_address_new_from_string ("::1::2");
|
||||||
g_assert (addr == NULL);
|
g_assert (addr == NULL);
|
||||||
@@ -206,12 +209,11 @@ test_socket_address (void)
|
|||||||
|
|
||||||
g_object_unref (saddr);
|
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,
|
saddr = G_INET_SOCKET_ADDRESS (g_object_new (G_TYPE_INET_SOCKET_ADDRESS,
|
||||||
"address", addr,
|
"address", addr,
|
||||||
"port", 308,
|
"port", 308,
|
||||||
"flowinfo", 10,
|
"flowinfo", 10,
|
||||||
"scope-id", 25,
|
|
||||||
NULL));
|
NULL));
|
||||||
g_object_unref (addr);
|
g_object_unref (addr);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user