hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gthreadedresolver.c
index def85b8..c02c593 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -90,17 +88,35 @@ do_lookup_by_name (GTask         *task,
       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))
+          if (!sockaddr)
             continue;
+          if (!G_IS_INET_SOCKET_ADDRESS (sockaddr))
+            {
+              g_clear_object (&sockaddr);
+              continue;
+            }
 
           addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr));
           addresses = g_list_prepend (addresses, addr);
           g_object_unref (sockaddr);
         }
 
-      addresses = g_list_reverse (addresses);
-      g_task_return_pointer (task, addresses,
-                             (GDestroyNotify)g_resolver_free_addresses);
+      if (addresses != NULL)
+        {
+          addresses = g_list_reverse (addresses);
+          g_task_return_pointer (task, addresses,
+                                 (GDestroyNotify)g_resolver_free_addresses);
+        }
+      else
+        {
+          /* All addresses failed to be converted to GSocketAddresses. */
+          g_task_return_new_error (task,
+                                   G_RESOLVER_ERROR,
+                                   G_RESOLVER_ERROR_NOT_FOUND,
+                                   _("Error resolving '%s': %s"),
+                                   hostname,
+                                   _("No valid addresses were found"));
+        }
     }
   else
     {
@@ -246,6 +262,142 @@ lookup_by_address_finish (GResolver     *resolver,
 
 
 #if defined(G_OS_UNIX)
+
+#ifdef __BIONIC__
+/* Copy from bionic/libc/private/arpa_nameser_compat.h
+ * and bionic/libc/private/arpa_nameser.h */
+typedef struct {
+       unsigned        id :16;         /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+                       /* fields in third byte */
+       unsigned        qr: 1;          /* response flag */
+       unsigned        opcode: 4;      /* purpose of message */
+       unsigned        aa: 1;          /* authoritive answer */
+       unsigned        tc: 1;          /* truncated message */
+       unsigned        rd: 1;          /* recursion desired */
+                       /* fields in fourth byte */
+       unsigned        ra: 1;          /* recursion available */
+       unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        ad: 1;          /* authentic data from named */
+       unsigned        cd: 1;          /* checking disabled by resolver */
+       unsigned        rcode :4;       /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+                       /* fields in third byte */
+       unsigned        rd :1;          /* recursion desired */
+       unsigned        tc :1;          /* truncated message */
+       unsigned        aa :1;          /* authoritive answer */
+       unsigned        opcode :4;      /* purpose of message */
+       unsigned        qr :1;          /* response flag */
+                       /* fields in fourth byte */
+       unsigned        rcode :4;       /* response code */
+       unsigned        cd: 1;          /* checking disabled by resolver */
+       unsigned        ad: 1;          /* authentic data from named */
+       unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
+       unsigned        ra :1;          /* recursion available */
+#endif
+                       /* remaining bytes */
+       unsigned        qdcount :16;    /* number of question entries */
+       unsigned        ancount :16;    /* number of answer entries */
+       unsigned        nscount :16;    /* number of authority entries */
+       unsigned        arcount :16;    /* number of resource entries */
+} HEADER;
+
+#define NS_INT32SZ     4       /* #/bytes of data in a uint32_t */
+#define NS_INT16SZ     2       /* #/bytes of data in a uint16_t */
+
+#define NS_GET16(s, cp) do { \
+       const u_char *t_cp = (const u_char *)(cp); \
+       (s) = ((uint16_t)t_cp[0] << 8) \
+           | ((uint16_t)t_cp[1]) \
+           ; \
+       (cp) += NS_INT16SZ; \
+} while (/*CONSTCOND*/0)
+
+#define NS_GET32(l, cp) do { \
+       const u_char *t_cp = (const u_char *)(cp); \
+       (l) = ((uint32_t)t_cp[0] << 24) \
+           | ((uint32_t)t_cp[1] << 16) \
+           | ((uint32_t)t_cp[2] << 8) \
+           | ((uint32_t)t_cp[3]) \
+           ; \
+       (cp) += NS_INT32SZ; \
+} while (/*CONSTCOND*/0)
+
+#define        GETSHORT                NS_GET16
+#define        GETLONG                 NS_GET32
+
+#define C_IN 1
+
+/* From bionic/libc/private/resolv_private.h */
+int dn_expand(const u_char *, const u_char *, const u_char *, char *, int);
+#define dn_skipname __dn_skipname
+int dn_skipname(const u_char *, const u_char *);
+
+/* From bionic/libc/private/arpa_nameser_compat.h */
+#define T_MX           ns_t_mx
+#define T_TXT          ns_t_txt
+#define T_SOA          ns_t_soa
+#define T_NS           ns_t_ns
+
+/* From bionic/libc/private/arpa_nameser.h */
+typedef enum __ns_type {
+       ns_t_invalid = 0,       /* Cookie. */
+       ns_t_a = 1,             /* Host address. */
+       ns_t_ns = 2,            /* Authoritative server. */
+       ns_t_md = 3,            /* Mail destination. */
+       ns_t_mf = 4,            /* Mail forwarder. */
+       ns_t_cname = 5,         /* Canonical name. */
+       ns_t_soa = 6,           /* Start of authority zone. */
+       ns_t_mb = 7,            /* Mailbox domain name. */
+       ns_t_mg = 8,            /* Mail group member. */
+       ns_t_mr = 9,            /* Mail rename name. */
+       ns_t_null = 10,         /* Null resource record. */
+       ns_t_wks = 11,          /* Well known service. */
+       ns_t_ptr = 12,          /* Domain name pointer. */
+       ns_t_hinfo = 13,        /* Host information. */
+       ns_t_minfo = 14,        /* Mailbox information. */
+       ns_t_mx = 15,           /* Mail routing information. */
+       ns_t_txt = 16,          /* Text strings. */
+       ns_t_rp = 17,           /* Responsible person. */
+       ns_t_afsdb = 18,        /* AFS cell database. */
+       ns_t_x25 = 19,          /* X_25 calling address. */
+       ns_t_isdn = 20,         /* ISDN calling address. */
+       ns_t_rt = 21,           /* Router. */
+       ns_t_nsap = 22,         /* NSAP address. */
+       ns_t_nsap_ptr = 23,     /* Reverse NSAP lookup (deprecated). */
+       ns_t_sig = 24,          /* Security signature. */
+       ns_t_key = 25,          /* Security key. */
+       ns_t_px = 26,           /* X.400 mail mapping. */
+       ns_t_gpos = 27,         /* Geographical position (withdrawn). */
+       ns_t_aaaa = 28,         /* Ip6 Address. */
+       ns_t_loc = 29,          /* Location Information. */
+       ns_t_nxt = 30,          /* Next domain (security). */
+       ns_t_eid = 31,          /* Endpoint identifier. */
+       ns_t_nimloc = 32,       /* Nimrod Locator. */
+       ns_t_srv = 33,          /* Server Selection. */
+       ns_t_atma = 34,         /* ATM Address */
+       ns_t_naptr = 35,        /* Naming Authority PoinTeR */
+       ns_t_kx = 36,           /* Key Exchange */
+       ns_t_cert = 37,         /* Certification record */
+       ns_t_a6 = 38,           /* IPv6 address (deprecates AAAA) */
+       ns_t_dname = 39,        /* Non-terminal DNAME (for IPv6) */
+       ns_t_sink = 40,         /* Kitchen sink (experimentatl) */
+       ns_t_opt = 41,          /* EDNS0 option (meta-RR) */
+       ns_t_apl = 42,          /* Address prefix list (RFC 3123) */
+       ns_t_tkey = 249,        /* Transaction key */
+       ns_t_tsig = 250,        /* Transaction signature. */
+       ns_t_ixfr = 251,        /* Incremental zone transfer. */
+       ns_t_axfr = 252,        /* Transfer zone of authority. */
+       ns_t_mailb = 253,       /* Transfer mailbox records. */
+       ns_t_maila = 254,       /* Transfer mail agent records. */
+       ns_t_any = 255,         /* Wildcard match. */
+       ns_t_zxfr = 256,        /* BIND-specific, nonstandard. */
+       ns_t_max = 65536
+} ns_type;
+
+#endif /* __BIONIC__ */
+
 static GVariant *
 parse_res_srv (guchar  *answer,
                guchar  *end,
@@ -388,26 +540,22 @@ g_resolver_records_from_res_query (const gchar      *rrname,
 
   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'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+                       _("No DNS record of the requested type for '%s'"), rrname);
         }
       else if (herr == TRY_AGAIN)
         {
-          errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
-          format = _("Temporarily unable to resolve '%s'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
+                       _("Temporarily unable to resolve '%s'"), rrname);
         }
       else
         {
-          errnum = G_RESOLVER_ERROR_INTERNAL;
-          format = _("Error resolving '%s'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_INTERNAL,
+                       _("Error resolving '%s'"), rrname);
         }
 
-      g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
       return NULL;
     }
 
@@ -472,6 +620,14 @@ g_resolver_records_from_res_query (const gchar      *rrname,
         records = g_list_prepend (records, record);
     }
 
+  if (records == NULL)
+    {
+      g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+                   _("No DNS record of the requested type for '%s'"), rrname);
+
+      return NULL;
+    }
+  else
     return records;
 }
 
@@ -562,26 +718,22 @@ g_resolver_records_from_DnsQuery (const gchar  *rrname,
 
   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'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+                       _("No DNS record of the requested type for '%s'"), rrname);
         }
       else if (status == DNS_ERROR_RCODE_SERVER_FAILURE)
         {
-          errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
-          format = _("Temporarily unable to resolve '%s'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
+                       _("Temporarily unable to resolve '%s'"), rrname);
         }
       else
         {
-          errnum = G_RESOLVER_ERROR_INTERNAL;
-          format = _("Error resolving '%s'");
+          g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_INTERNAL,
+                       _("Error resolving '%s'"), rrname);
         }
 
-      g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
       return NULL;
     }
 
@@ -616,7 +768,15 @@ g_resolver_records_from_DnsQuery (const gchar  *rrname,
         records = g_list_prepend (records, g_variant_ref_sink (record));
     }
 
-  return records;
+  if (records == NULL)
+    {
+      g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+                   _("No DNS record of the requested type for '%s'"), rrname);
+
+      return NULL;
+    }
+  else
+    return records;
 }
 
 #endif
@@ -639,6 +799,13 @@ free_records (GList *records)
   g_list_free_full (records, (GDestroyNotify) g_variant_unref);
 }
 
+#if defined(G_OS_UNIX)
+#ifdef __BIONIC__
+#define C_IN 1
+int res_query(const char *, int, int, u_char *, int);
+#endif
+#endif
+
 static void
 do_lookup_records (GTask         *task,
                    gpointer       source_object,
@@ -771,7 +938,7 @@ g_threaded_resolver_class_init (GThreadedResolverClass *threaded_class)
   resolver_class->lookup_records_async     = lookup_records_async;
   resolver_class->lookup_records_finish    = lookup_records_finish;
 
-  /* Initialize _g_resolver_addrinfo_hints */
+  /* Initialize addrinfo_hints */
 #ifdef AI_ADDRCONFIG
   addrinfo_hints.ai_flags |= AI_ADDRCONFIG;
 #endif