X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgresolver.c;h=e73ef0e9f8ef0b0b9d448cbb73bb01e5e2eb91ef;hb=7a1aaaa1fa02679ecf335a19fffe3f55505921b5;hp=4ca4e009206a6ade05533f9cde766af8b4ba9edd;hpb=62570a52b179fc521209444926d7945fc31210a4;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gresolver.c b/gio/gresolver.c index 4ca4e00..e73ef0e 100644 --- a/gio/gresolver.c +++ b/gio/gresolver.c @@ -15,9 +15,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . */ #include "config.h" @@ -28,8 +26,8 @@ #include "gnetworkingprivate.h" #include "gasyncresult.h" #include "ginetaddress.h" -#include "ginetsocketaddress.h" #include "gsimpleasyncresult.h" +#include "gtask.h" #include "gsrvtarget.h" #include "gthreadedresolver.h" @@ -76,7 +74,9 @@ struct _GResolverPrivate { * The object that handles DNS resolution. Use g_resolver_get_default() * to get the default resolver. */ -G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT) +G_DEFINE_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT, + G_ADD_PRIVATE (GResolver) + g_networking_init ();) static GList * srv_records_to_targets (GList *records) @@ -151,22 +151,6 @@ g_resolver_class_init (GResolverClass *resolver_class) resolver_class->lookup_service_async = g_resolver_real_lookup_service_async; resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish; - g_type_class_add_private (resolver_class, sizeof (GResolverPrivate)); - - /* Make sure _g_networking_init() has been called */ - g_type_ensure (G_TYPE_INET_ADDRESS); - - /* Initialize _g_resolver_addrinfo_hints */ -#ifdef AI_ADDRCONFIG - _g_resolver_addrinfo_hints.ai_flags |= AI_ADDRCONFIG; -#endif - /* These two don't actually matter, they just get copied into the - * returned addrinfo structures (and then we ignore them). But if - * we leave them unset, we'll get back duplicate answers. - */ - _g_resolver_addrinfo_hints.ai_socktype = SOCK_STREAM; - _g_resolver_addrinfo_hints.ai_protocol = IPPROTO_TCP; - /** * GResolver::reload: * @resolver: a #GResolver @@ -191,7 +175,7 @@ g_resolver_init (GResolver *resolver) struct stat st; #endif - resolver->priv = G_TYPE_INSTANCE_GET_PRIVATE (resolver, G_TYPE_RESOLVER, GResolverPrivate); + resolver->priv = g_resolver_get_instance_private (resolver); #ifdef G_OS_UNIX if (stat (_PATH_RESCONF, &st) == 0) @@ -208,7 +192,7 @@ static GResolver *default_resolver; * with it. #GResolver may use its reference count as a hint about how * many threads it should allocate for concurrent DNS resolutions. * - * Return value: (transfer full): the default #GResolver. + * Returns: (transfer full): the default #GResolver. * * Since: 2.22 */ @@ -245,6 +229,10 @@ g_resolver_set_default (GResolver *resolver) default_resolver = g_object_ref (resolver); } +/* Bionic has res_init() but it's not in any header */ +#ifdef __BIONIC__ +int res_init (void); +#endif static void g_resolver_maybe_reload (GResolver *resolver) @@ -257,7 +245,9 @@ g_resolver_maybe_reload (GResolver *resolver) if (st.st_mtime != resolver->priv->resolv_conf_timestamp) { resolver->priv->resolv_conf_timestamp = st.st_mtime; +#ifdef HAVE_RES_INIT res_init (); +#endif g_signal_emit (resolver, signals[RELOAD], 0); } } @@ -293,6 +283,48 @@ remove_duplicates (GList *addrs) } } +/* Note that this does not follow the "FALSE means @error is set" + * convention. The return value tells the caller whether it should + * return @addrs and @error to the caller right away, or if it should + * continue and trying to resolve the name as a hostname. + */ +static gboolean +handle_ip_address (const char *hostname, + GList **addrs, + GError **error) +{ + GInetAddress *addr; +#ifndef G_OS_WIN32 + struct in_addr ip4addr; +#endif + + addr = g_inet_address_new_from_string (hostname); + if (addr) + { + *addrs = g_list_append (NULL, addr); + return TRUE; + } + + *addrs = NULL; + + /* Reject non-standard IPv4 numbers-and-dots addresses. + * g_inet_address_new_from_string() will have accepted any "real" IP + * address, so if inet_aton() succeeds, then it's an address we want + * to reject. This check is not necessary for Windows, as getaddrinfo() + * already rejects such IPv4 addresses on Windows. + */ +#ifndef G_OS_WIN32 + if (inet_aton (hostname, &ip4addr)) + { + g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, + _("Error resolving '%s': %s"), + hostname, gai_strerror (EAI_NONAME)); + return TRUE; + } +#endif + + return FALSE; +} /** * g_resolver_lookup_by_name: @@ -306,7 +338,7 @@ remove_duplicates (GList *addrs) * the textual form of an IP address (in which case this just becomes * a wrapper around g_inet_address_new_from_string()). * - * On success, g_resolver_lookup_by_name() will return a #GList of + * On success, g_resolver_lookup_by_name() will return a non-empty #GList of * #GInetAddress, sorted in order of preference and guaranteed to not * contain duplicates. That is, if using the result to connect to * @hostname, you should attempt to connect to the first address @@ -315,7 +347,7 @@ remove_duplicates (GList *addrs) * result using e.g. g_socket_listener_add_address(). * * If the DNS resolution fails, @error (if non-%NULL) will be set to a - * value from #GResolverError. + * value from #GResolverError and %NULL will be returned. * * If @cancellable is non-%NULL, it can be used to cancel the * operation, in which case @error (if non-%NULL) will be set to @@ -325,7 +357,7 @@ remove_duplicates (GList *addrs) * address, it may be easier to create a #GNetworkAddress and use its * #GSocketConnectable interface. * - * Return value: (element-type GInetAddress) (transfer full): a #GList + * Returns: (element-type GInetAddress) (transfer full): a non-empty #GList * of #GInetAddress, or %NULL on error. You * must unref each of the addresses and free the list when you are * done with it. (You can use g_resolver_free_addresses() to do this.) @@ -338,7 +370,6 @@ g_resolver_lookup_by_name (GResolver *resolver, GCancellable *cancellable, GError **error) { - GInetAddress *addr; GList *addrs; gchar *ascii_hostname = NULL; @@ -346,9 +377,8 @@ g_resolver_lookup_by_name (GResolver *resolver, g_return_val_if_fail (hostname != NULL, NULL); /* Check if @hostname is just an IP address */ - addr = g_inet_address_new_from_string (hostname); - if (addr) - return g_list_append (NULL, addr); + if (handle_ip_address (hostname, &addrs, error)) + return addrs; if (g_hostname_is_non_ascii (hostname)) hostname = ascii_hostname = g_hostname_to_ascii (hostname); @@ -385,25 +415,25 @@ g_resolver_lookup_by_name_async (GResolver *resolver, GAsyncReadyCallback callback, gpointer user_data) { - GInetAddress *addr; gchar *ascii_hostname = NULL; + GList *addrs; + GError *error = NULL; g_return_if_fail (G_IS_RESOLVER (resolver)); g_return_if_fail (hostname != NULL); /* Check if @hostname is just an IP address */ - addr = g_inet_address_new_from_string (hostname); - if (addr) + if (handle_ip_address (hostname, &addrs, &error)) { - GSimpleAsyncResult *simple; + GTask *task; - simple = g_simple_async_result_new (G_OBJECT (resolver), - callback, user_data, - g_resolver_lookup_by_name_async); - - g_simple_async_result_set_op_res_gpointer (simple, addr, g_object_unref); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + task = g_task_new (resolver, cancellable, callback, user_data); + g_task_set_source_tag (task, g_resolver_lookup_by_name_async); + if (addrs) + g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses); + else + g_task_return_error (task, error); + g_object_unref (task); return; } @@ -430,7 +460,7 @@ g_resolver_lookup_by_name_async (GResolver *resolver, * a value from #GResolverError. If the operation was cancelled, * @error will be set to %G_IO_ERROR_CANCELLED. * - * Return value: (element-type GInetAddress) (transfer full): a #GList + * Returns: (element-type GInetAddress) (transfer full): a #GList * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name() * for more details. * @@ -449,12 +479,8 @@ g_resolver_lookup_by_name_finish (GResolver *resolver, return NULL; else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async)) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - GInetAddress *addr; - /* Handle the stringified-IP-addr case */ - addr = g_simple_async_result_get_op_res_gpointer (simple); - return g_list_append (NULL, g_object_ref (addr)); + return g_task_propagate_pointer (G_TASK (result), error); } addrs = G_RESOLVER_GET_CLASS (resolver)-> @@ -503,7 +529,7 @@ g_resolver_free_addresses (GList *addresses) * operation, in which case @error (if non-%NULL) will be set to * %G_IO_ERROR_CANCELLED. * - * Return value: a hostname (either ASCII-only, or in ASCII-encoded + * Returns: a hostname (either ASCII-only, or in ASCII-encoded * form), or %NULL on error. * * Since: 2.22 @@ -564,7 +590,7 @@ g_resolver_lookup_by_address_async (GResolver *resolver, * a value from #GResolverError. If the operation was cancelled, * @error will be set to %G_IO_ERROR_CANCELLED. * - * Return value: a hostname (either ASCII-only, or in ASCII-encoded + * Returns: a hostname (either ASCII-only, or in ASCII-encoded * form), or %NULL on error. * * Since: 2.22 @@ -611,17 +637,16 @@ g_resolver_get_service_rrname (const char *service, * Synchronously performs a DNS SRV lookup for the given @service and * @protocol in the given @domain and returns an array of #GSrvTarget. * @domain may be an ASCII-only or UTF-8 hostname. Note also that the - * @service and @protocol arguments do not - * include the leading underscore that appears in the actual DNS - * entry. + * @service and @protocol arguments do not include the leading underscore + * that appears in the actual DNS entry. * - * On success, g_resolver_lookup_service() will return a #GList of + * On success, g_resolver_lookup_service() will return a non-empty #GList of * #GSrvTarget, sorted in order of preference. (That is, you should * attempt to connect to the first target first, then the second if * the first fails, etc.) * * If the DNS resolution fails, @error (if non-%NULL) will be set to - * a value from #GResolverError. + * a value from #GResolverError and %NULL will be returned. * * If @cancellable is non-%NULL, it can be used to cancel the * operation, in which case @error (if non-%NULL) will be set to @@ -631,9 +656,10 @@ g_resolver_get_service_rrname (const char *service, * to create a #GNetworkService and use its #GSocketConnectable * interface. * - * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget, - * or %NULL on error. You must free each of the targets and the list when you are - * done with it. (You can use g_resolver_free_targets() to do this.) + * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of + * #GSrvTarget, or %NULL on error. You must free each of the targets and the + * list when you are done with it. (You can use g_resolver_free_targets() to do + * this.) * * Since: 2.22 */ @@ -719,8 +745,9 @@ g_resolver_lookup_service_async (GResolver *resolver, * a value from #GResolverError. If the operation was cancelled, * @error will be set to %G_IO_ERROR_CANCELLED. * - * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget, - * or %NULL on error. See g_resolver_lookup_service() for more details. + * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of + * #GSrvTarget, or %NULL on error. See g_resolver_lookup_service() for more + * details. * * Since: 2.22 */ @@ -772,15 +799,16 @@ g_resolver_free_targets (GList *targets) * information on what the records contain for each @record_type. * * If the DNS resolution fails, @error (if non-%NULL) will be set to - * a value from #GResolverError. + * a value from #GResolverError and %NULL will be returned. * * If @cancellable is non-%NULL, it can be used to cancel the * operation, in which case @error (if non-%NULL) will be set to * %G_IO_ERROR_CANCELLED. * - * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant, - * or %NULL on error. You must free each of the records and the list when you are - * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.) + * Returns: (element-type GVariant) (transfer full): a non-empty #GList of + * #GVariant, or %NULL on error. You must free each of the records and the list + * when you are done with it. (You can use g_list_free_full() with + * g_variant_unref() to do this.) * * Since: 2.34 */ @@ -842,16 +870,18 @@ g_resolver_lookup_records_async (GResolver *resolver, * @error: return location for a #GError, or %NULL * * Retrieves the result of a previous call to - * g_resolver_lookup_records_async(). Returns a list of records as #GVariant - * tuples. See #GResolverRecordType for information on what the records contain. + * g_resolver_lookup_records_async(). Returns a non-empty list of records as + * #GVariant tuples. See #GResolverRecordType for information on what the + * records contain. * * If the DNS resolution failed, @error (if non-%NULL) will be set to * a value from #GResolverError. If the operation was cancelled, * @error will be set to %G_IO_ERROR_CANCELLED. * - * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant, - * or %NULL on error. You must free each of the records and the list when you are - * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.) + * Returns: (element-type GVariant) (transfer full): a non-empty #GList of + * #GVariant, or %NULL on error. You must free each of the records and the list + * when you are done with it. (You can use g_list_free_full() with + * g_variant_unref() to do this.) * * Since: 2.34 */ @@ -865,556 +895,27 @@ g_resolver_lookup_records_finish (GResolver *resolver, lookup_records_finish (resolver, result, error); } +guint64 +g_resolver_get_serial (GResolver *resolver) +{ + g_return_val_if_fail (G_IS_RESOLVER (resolver), 0); + + g_resolver_maybe_reload (resolver); + +#ifdef G_OS_UNIX + return (guint64) resolver->priv->resolv_conf_timestamp; +#else + return 1; +#endif +} + /** * g_resolver_error_quark: * * Gets the #GResolver Error Quark. * - * Return value: a #GQuark. + * Returns: a #GQuark. * * Since: 2.22 */ G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error) - -static GResolverError -g_resolver_error_from_addrinfo_error (gint err) -{ - switch (err) - { - case EAI_FAIL: -#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) - case EAI_NODATA: -#endif - case EAI_NONAME: - return G_RESOLVER_ERROR_NOT_FOUND; - - case EAI_AGAIN: - return G_RESOLVER_ERROR_TEMPORARY_FAILURE; - - default: - return G_RESOLVER_ERROR_INTERNAL; - } -} - -struct addrinfo _g_resolver_addrinfo_hints; - -/* Private method to process a getaddrinfo() response. */ -GList * -_g_resolver_addresses_from_addrinfo (const char *hostname, - struct addrinfo *res, - gint gai_retval, - GError **error) -{ - struct addrinfo *ai; - GSocketAddress *sockaddr; - GInetAddress *addr; - GList *addrs; - - if (gai_retval != 0) - { - g_set_error (error, G_RESOLVER_ERROR, - g_resolver_error_from_addrinfo_error (gai_retval), - _("Error resolving '%s': %s"), - hostname, gai_strerror (gai_retval)); - return NULL; - } - - g_return_val_if_fail (res != NULL, NULL); - - addrs = NULL; - for (ai = res; ai; ai = ai->ai_next) - { - sockaddr = g_socket_address_new_from_native (ai->ai_addr, ai->ai_addrlen); - if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr)) - continue; - - addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr)); - addrs = g_list_prepend (addrs, addr); - g_object_unref (sockaddr); - } - - return g_list_reverse (addrs); -} - -/* Private method to set up a getnameinfo() request */ -void -_g_resolver_address_to_sockaddr (GInetAddress *address, - struct sockaddr_storage *sa, - gsize *len) -{ - GSocketAddress *sockaddr; - - sockaddr = g_inet_socket_address_new (address, 0); - g_socket_address_to_native (sockaddr, (struct sockaddr *)sa, sizeof (*sa), NULL); - *len = g_socket_address_get_native_size (sockaddr); - g_object_unref (sockaddr); -} - -/* Private method to process a getnameinfo() response. */ -char * -_g_resolver_name_from_nameinfo (GInetAddress *address, - const gchar *name, - gint gni_retval, - GError **error) -{ - if (gni_retval != 0) - { - gchar *phys; - - phys = g_inet_address_to_string (address); - g_set_error (error, G_RESOLVER_ERROR, - g_resolver_error_from_addrinfo_error (gni_retval), - _("Error reverse-resolving '%s': %s"), - phys ? phys : "(unknown)", gai_strerror (gni_retval)); - g_free (phys); - return NULL; - } - - return g_strdup (name); -} - -#if defined(G_OS_UNIX) - -static gboolean -parse_short (guchar **p, - guchar *end, - guint16 *value) -{ - if (*p + 2 > end) - return FALSE; - GETSHORT (*value, *p); - return TRUE; -} - -static gboolean -parse_long (guchar **p, - guchar *end, - guint32 *value) -{ - if (*p + 4 > end) - return FALSE; - GETLONG (*value, *p); - return TRUE; -} - -static GVariant * -parse_res_srv (guchar *answer, - guchar *end, - guchar *p) -{ - gchar namebuf[1024]; - guint16 priority, weight, port; - gint n; - - if (!parse_short (&p, end, &priority) || - !parse_short (&p, end, &weight) || - !parse_short (&p, end, &port)) - return NULL; - - n = dn_expand (answer, end, p, namebuf, sizeof (namebuf)); - if (n < 0) - return NULL; - *p += n; - - return g_variant_new ("(qqqs)", - priority, - weight, - port, - namebuf); -} - -static GVariant * -parse_res_soa (guchar *answer, - guchar *end, - guchar *p) -{ - gchar mnamebuf[1024]; - gchar rnamebuf[1024]; - guint32 serial, refresh, retry, expire, ttl; - gint n; - - n = dn_expand (answer, end, p, mnamebuf, sizeof (mnamebuf)); - if (n < 0) - return NULL; - p += n; - - n = dn_expand (answer, end, p, rnamebuf, sizeof (rnamebuf)); - if (n < 0) - return NULL; - p += n; - - if (!parse_long (&p, end, &serial) || - !parse_long (&p, end, &refresh) || - !parse_long (&p, end, &retry) || - !parse_long (&p, end, &expire) || - !parse_long (&p, end, &ttl)) - return NULL; - - return g_variant_new ("(ssuuuuu)", - mnamebuf, - rnamebuf, - serial, - refresh, - retry, - expire, - ttl); -} - -static GVariant * -parse_res_ns (guchar *answer, - guchar *end, - guchar *p) -{ - gchar namebuf[1024]; - gint n; - - n = dn_expand (answer, end, p, namebuf, sizeof (namebuf)); - if (n < 0) - return NULL; - - return g_variant_new ("(s)", namebuf); -} - -static GVariant * -parse_res_mx (guchar *answer, - guchar *end, - guchar *p) -{ - gchar namebuf[1024]; - guint16 preference; - gint n; - - if (!parse_short (&p, end, &preference)) - return NULL; - - n = dn_expand (answer, end, p, namebuf, sizeof (namebuf)); - if (n < 0) - return NULL; - p += n; - - return g_variant_new ("(qs)", - preference, - namebuf); -} - -static GVariant * -parse_res_txt (guchar *answer, - guchar *end, - guchar *p) -{ - GVariant *record; - GPtrArray *array; - gsize len; - - array = g_ptr_array_new_with_free_func (g_free); - while (p < end) - { - len = *(p++); - if (len > p - end) - break; - g_ptr_array_add (array, g_strndup ((gchar *)p, len)); - p += len; - } - - record = g_variant_new ("(@as)", - g_variant_new_strv ((const gchar **)array->pdata, array->len)); - g_ptr_array_free (array, TRUE); - return record; -} - -gint -_g_resolver_record_type_to_rrtype (GResolverRecordType type) -{ - switch (type) - { - case G_RESOLVER_RECORD_SRV: - return T_SRV; - case G_RESOLVER_RECORD_TXT: - return T_TXT; - case G_RESOLVER_RECORD_SOA: - return T_SOA; - case G_RESOLVER_RECORD_NS: - return T_NS; - case G_RESOLVER_RECORD_MX: - return T_MX; - } - g_return_val_if_reached (-1); -} - -/* Private method to process a res_query response into GSrvTargets */ -GList * -_g_resolver_records_from_res_query (const gchar *rrname, - gint rrtype, - guchar *answer, - gint len, - gint herr, - GError **error) -{ - gint count; - guchar *end, *p; - guint16 type, qclass, rdlength; - guint32 ttl; - HEADER *header; - GList *records; - GVariant *record; - gint n, i; - - if (len <= 0) - { - GResolverError errnum; - const gchar *format; - - if (len == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA) - { - errnum = G_RESOLVER_ERROR_NOT_FOUND; - format = _("No DNS record of the requested type for '%s'"); - } - else if (herr == TRY_AGAIN) - { - errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE; - format = _("Temporarily unable to resolve '%s'"); - } - else - { - errnum = G_RESOLVER_ERROR_INTERNAL; - format = _("Error resolving '%s'"); - } - - g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname); - return NULL; - } - - records = NULL; - - header = (HEADER *)answer; - p = answer + sizeof (HEADER); - end = answer + len; - - /* Skip query */ - count = ntohs (header->qdcount); - for (i = 0; i < count && p < end; i++) - { - n = dn_skipname (p, end); - if (n < 0) - break; - p += n; - p += 4; - } - - /* Incomplete response */ - if (i < count) - { - g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE, - _("Incomplete data received for '%s'"), rrname); - return NULL; - } - - /* Read answers */ - count = ntohs (header->ancount); - for (i = 0; i < count && p < end; i++) - { - n = dn_skipname (p, end); - if (n < 0) - break; - p += n; - - if (!parse_short (&p, end, &type) || - !parse_short (&p, end, &qclass) || - !parse_long (&p, end, &ttl) || - !parse_short (&p, end, &rdlength)) - break; - - ttl = ttl; /* To avoid -Wunused-but-set-variable */ - - if (p + rdlength > end) - break; - - if (type == rrtype && qclass == C_IN) - { - switch (rrtype) - { - case T_SRV: - record = parse_res_srv (answer, end, p); - break; - case T_MX: - record = parse_res_mx (answer, end, p); - break; - case T_SOA: - record = parse_res_soa (answer, end, p); - break; - case T_NS: - record = parse_res_ns (answer, end, p); - break; - case T_TXT: - record = parse_res_txt (answer, p + rdlength, p); - break; - default: - g_warn_if_reached (); - record = NULL; - break; - } - - if (record != NULL) - records = g_list_prepend (records, record); - } - - p += rdlength; - } - - /* Somehow got a truncated response */ - if (i < count) - { - g_list_free_full (records, (GDestroyNotify)g_variant_unref); - g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE, - _("Incomplete data received for '%s'"), rrname); - return NULL; - } - - return records; -} - -#elif defined(G_OS_WIN32) -static GVariant * -parse_dns_srv (DNS_RECORD *rec) -{ - return g_variant_new ("(qqqs)", - (guint16)rec->Data.SRV.wPriority, - (guint16)rec->Data.SRV.wWeight, - (guint16)rec->Data.SRV.wPort, - rec->Data.SRV.pNameTarget); -} - -static GVariant * -parse_dns_soa (DNS_RECORD *rec) -{ - return g_variant_new ("(ssuuuuu)", - rec->Data.SOA.pNamePrimaryServer, - rec->Data.SOA.pNameAdministrator, - (guint32)rec->Data.SOA.dwSerialNo, - (guint32)rec->Data.SOA.dwRefresh, - (guint32)rec->Data.SOA.dwRetry, - (guint32)rec->Data.SOA.dwExpire, - (guint32)rec->Data.SOA.dwDefaultTtl); -} - -static GVariant * -parse_dns_ns (DNS_RECORD *rec) -{ - return g_variant_new ("(s)", rec->Data.NS.pNameHost); -} - -static GVariant * -parse_dns_mx (DNS_RECORD *rec) -{ - return g_variant_new ("(qs)", - (guint16)rec->Data.MX.wPreference, - rec->Data.MX.pNameExchange); -} - -static GVariant * -parse_dns_txt (DNS_RECORD *rec) -{ - GVariant *record; - GPtrArray *array; - DWORD i; - - array = g_ptr_array_new (); - for (i = 0; i < rec->Data.TXT.dwStringCount; i++) - g_ptr_array_add (array, rec->Data.TXT.pStringArray[i]); - record = g_variant_new ("(@as)", - g_variant_new_strv ((const gchar **)array->pdata, array->len)); - g_ptr_array_free (array, TRUE); - return record; -} - -WORD -_g_resolver_record_type_to_dnstype (GResolverRecordType type) -{ - switch (type) - { - case G_RESOLVER_RECORD_SRV: - return DNS_TYPE_SRV; - case G_RESOLVER_RECORD_TXT: - return DNS_TYPE_TEXT; - case G_RESOLVER_RECORD_SOA: - return DNS_TYPE_SOA; - case G_RESOLVER_RECORD_NS: - return DNS_TYPE_NS; - case G_RESOLVER_RECORD_MX: - return DNS_TYPE_MX; - } - g_return_val_if_reached (-1); -} - -/* Private method to process a DnsQuery response into GVariants */ -GList * -_g_resolver_records_from_DnsQuery (const gchar *rrname, - WORD dnstype, - DNS_STATUS status, - DNS_RECORD *results, - GError **error) -{ - DNS_RECORD *rec; - gpointer record; - GList *records; - - if (status != ERROR_SUCCESS) - { - GResolverError errnum; - const gchar *format; - - if (status == DNS_ERROR_RCODE_NAME_ERROR) - { - errnum = G_RESOLVER_ERROR_NOT_FOUND; - format = _("No DNS record of the requested type for '%s'"); - } - else if (status == DNS_ERROR_RCODE_SERVER_FAILURE) - { - errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE; - format = _("Temporarily unable to resolve '%s'"); - } - else - { - errnum = G_RESOLVER_ERROR_INTERNAL; - format = _("Error resolving '%s'"); - } - - g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname); - return NULL; - } - - records = NULL; - for (rec = results; rec; rec = rec->pNext) - { - if (rec->wType != dnstype) - continue; - switch (dnstype) - { - case DNS_TYPE_SRV: - record = parse_dns_srv (rec); - break; - case DNS_TYPE_SOA: - record = parse_dns_soa (rec); - break; - case DNS_TYPE_NS: - record = parse_dns_ns (rec); - break; - case DNS_TYPE_MX: - record = parse_dns_mx (rec); - break; - case DNS_TYPE_TEXT: - record = parse_dns_txt (rec); - break; - default: - g_warn_if_reached (); - record = NULL; - break; - } - if (record != NULL) - records = g_list_prepend (records, g_variant_ref_sink (record)); - } - - return records; -} - -#endif