From 73d0627bdae56bae8d9b2e699c0b620d51a6f1d6 Mon Sep 17 00:00:00 2001 From: Patrick Griffis Date: Wed, 2 Jul 2025 09:15:51 -0500 Subject: [PATCH] ginetaddress: Add scope-id and flowinfo properties This will be used by GResolver as DNS responses include this information along with the address. --- gio/ginetaddress.c | 133 +++++++++++++++++++++++++++++++++++++++++++++ gio/ginetaddress.h | 12 ++++ 2 files changed, 145 insertions(+) diff --git a/gio/ginetaddress.c b/gio/ginetaddress.c index c0ba2507a..0005b2e7c 100644 --- a/gio/ginetaddress.c +++ b/gio/ginetaddress.c @@ -42,6 +42,10 @@ struct _GInetAddressPrivate struct in6_addr ipv6; #endif } addr; +#ifdef HAVE_IPV6 + guint32 flowinfo; + guint32 scope_id; +#endif }; /** @@ -78,6 +82,8 @@ enum PROP_IS_MC_NODE_LOCAL, PROP_IS_MC_ORG_LOCAL, PROP_IS_MC_SITE_LOCAL, + PROP_FLOWINFO, + PROP_SCOPE_ID, }; static void @@ -107,6 +113,18 @@ g_inet_address_set_property (GObject *object, #endif break; + case PROP_SCOPE_ID: +#ifdef HAVE_IPV6 + address->priv->scope_id = g_value_get_uint (value); +#endif + break; + + case PROP_FLOWINFO: +#ifdef HAVE_IPV6 + address->priv->flowinfo = g_value_get_uint (value); +#endif + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -172,6 +190,14 @@ g_inet_address_get_property (GObject *object, g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address)); break; + case PROP_FLOWINFO: + g_value_set_uint (value, g_inet_address_get_flowinfo (address)); + break; + + case PROP_SCOPE_ID: + g_value_set_uint (value, g_inet_address_get_scope_id (address)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -353,6 +379,38 @@ g_inet_address_class_init (GInetAddressClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GInetAddress:flowinfo: + * + * The flowinfo for an IPv6 address. + * See [method@Gio.InetAddress.get_flowinfo]. + * + * Since: 2.86 + */ + g_object_class_install_property (gobject_class, PROP_FLOWINFO, + g_param_spec_uint ("flowinfo", NULL, NULL, + 0, G_MAXUINT32, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * GInetAddress:scope-id: + * + * The scope-id for an IPv6 address. + * See [method@Gio.InetAddress.get_scope_id]. + * + * Since: 2.86 + */ + g_object_class_install_property (gobject_class, PROP_SCOPE_ID, + g_param_spec_uint ("scope-id", NULL, NULL, + 0, G_MAXUINT32, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } static void @@ -490,6 +548,38 @@ g_inet_address_new_any (GSocketFamily family) #endif } +/** + * g_inet_address_new_from_bytes_with_ipv6_info: + * @bytes: (array) (element-type guint8): raw address data + * @family: the address family of @bytes + * @scope_id: the scope-id of the address + * + * Creates a new [class@Gio.InetAddress] from the given @family, @bytes + * and @scope_id. + * + * @bytes must be 4 bytes for [enum@Gio.SocketFamily.IPV4] and 16 bytes for + * [enum@Gio.SocketFamily.IPV6]. + * + * Returns: (transfer full): a new internet address corresponding to + * @family, @bytes and @scope_id + * + * Since: 2.86 + */ +GInetAddress * +g_inet_address_new_from_bytes_with_ipv6_info (const guint8 *bytes, + GSocketFamily family, + guint32 flowinfo, + guint32 scope_id) +{ + g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL); + + return g_object_new (G_TYPE_INET_ADDRESS, + "family", family, + "bytes", bytes, + "flowinfo", flowinfo, + "scope-id", scope_id, + NULL); +} /** * g_inet_address_to_string: @@ -866,6 +956,49 @@ g_inet_address_get_is_mc_site_local (GInetAddress *address) #endif } +/** + * g_inet_address_get_scope_id: + * @address: a #GInetAddress + * + * Gets the value of [property@Gio.InetAddress:scope-id]. + * + * Returns: The scope-id for the address, `0` if unset or not IPv6 address. + * Since: 2.86 + */ +guint32 +g_inet_address_get_scope_id (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET_ADDRESS (address), 0); + +#ifdef HAVE_IPV6 + if (address->priv->family == AF_INET6) + return address->priv->scope_id; +#endif + return 0; +} + +/** + * g_inet_address_get_flowinfo: + * @address: a #GInetAddress + * + * Gets the value of [property@Gio.InetAddress:flowinfo]. + * + * Returns: The flowinfo for the address, `0` if unset or not IPv6 address. + * Since: 2.86 + */ +guint32 +g_inet_address_get_flowinfo (GInetAddress *address) +{ + g_return_val_if_fail (G_IS_INET_ADDRESS (address), 0); + +#ifdef HAVE_IPV6 + if (address->priv->family == AF_INET6) + return address->priv->flowinfo; +#endif + return 0; +} + + /** * g_inet_address_equal: * @address: A #GInetAddress. diff --git a/gio/ginetaddress.h b/gio/ginetaddress.h index ea503a927..9d2f21b1e 100644 --- a/gio/ginetaddress.h +++ b/gio/ginetaddress.h @@ -71,6 +71,12 @@ GInetAddress * g_inet_address_new_from_bytes (const guint8 GIO_AVAILABLE_IN_ALL GInetAddress * g_inet_address_new_loopback (GSocketFamily family); +GIO_AVAILABLE_IN_2_86 +GInetAddress * g_inet_address_new_from_bytes_with_ipv6_info (const guint8 *bytes, + GSocketFamily family, + guint32 flowinfo, + guint32 scope_id); + GIO_AVAILABLE_IN_ALL GInetAddress * g_inet_address_new_any (GSocketFamily family); @@ -120,6 +126,12 @@ gboolean g_inet_address_get_is_mc_org_local (GInetAddress GIO_AVAILABLE_IN_ALL gboolean g_inet_address_get_is_mc_site_local (GInetAddress *address); +GIO_AVAILABLE_IN_2_86 +guint32 g_inet_address_get_scope_id (GInetAddress *address); + +GIO_AVAILABLE_IN_2_86 +guint32 g_inet_address_get_flowinfo (GInetAddress *address); + G_END_DECLS #endif /* __G_INET_ADDRESS_H__ */