* 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"
* to get the default resolver.
*/
G_DEFINE_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT,
+ G_ADD_PRIVATE (GResolver)
g_networking_init ();)
static GList *
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));
-
/**
* GResolver::reload:
* @resolver: a #GResolver
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)
* 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
*/
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)
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);
}
}
}
}
+/* 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:
* 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
* 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
* 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.)
GCancellable *cancellable,
GError **error)
{
- GInetAddress *addr;
GList *addrs;
gchar *ascii_hostname = NULL;
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);
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))
{
GTask *task;
task = g_task_new (resolver, cancellable, callback, user_data);
g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
- g_task_return_pointer (task, g_list_append (NULL, addr),
- (GDestroyNotify) g_resolver_free_addresses);
+ 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;
}
* 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.
*
* 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
* 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
* 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 <emphasis>do not</emphasis>
- * 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
* 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
*/
* 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
*/
* 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
*/
* @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
*/
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
*/