From a4eba545630f97c259d5cb10293008bbb2b1cafd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Jul 2010 11:37:21 -0700 Subject: [PATCH] Add functions for adding and flushing nameservers with resolver --- gresolv/gresolv.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gresolv/gresolv.h | 6 +++ 2 files changed, 115 insertions(+) diff --git a/gresolv/gresolv.c b/gresolv/gresolv.c index 2605676..d1aa8d2 100644 --- a/gresolv/gresolv.c +++ b/gresolv/gresolv.c @@ -23,17 +23,88 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include + #include "gresolv.h" +struct resolv_nameserver { + char *address; + uint16_t port; + unsigned long flags; + + GIOChannel *udp_channel; +}; + struct _GResolv { gint ref_count; int index; + GList *nameserver_list; GResolvDebugFunc debug_func; gpointer debug_data; }; +static void free_nameserver(struct resolv_nameserver *nameserver) +{ + if (nameserver == NULL) + return; + + if (nameserver->udp_channel != NULL) + g_io_channel_unref(nameserver->udp_channel); + + g_free(nameserver->address); + g_free(nameserver); +} + +static void flush_nameservers(GResolv *resolv) +{ + GList *list; + + for (list = g_list_first(resolv->nameserver_list); + list; list = g_list_next(list)) + free_nameserver(list->data); + + g_list_free(resolv->nameserver_list); + resolv->nameserver_list = NULL; +} + +static int connect_udp_channel(struct resolv_nameserver *nameserver) +{ + struct sockaddr_in sin; + int sk; + + sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sk < 0) + return -EIO; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(nameserver->port); + sin.sin_addr.s_addr = inet_addr(nameserver->address); + + if (connect(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + close(sk); + return -EIO; + } + + nameserver->udp_channel = g_io_channel_unix_new(sk); + if (nameserver->udp_channel == NULL) { + close(sk); + return -ENOMEM; + } + + g_io_channel_set_close_on_unref(nameserver->udp_channel, TRUE); + + return 0; +} + GResolv *g_resolv_new(int index) { GResolv *resolv; @@ -48,6 +119,7 @@ GResolv *g_resolv_new(int index) resolv->ref_count = 1; resolv->index = index; + resolv->nameserver_list = NULL; return resolv; } @@ -70,6 +142,8 @@ void g_resolv_unref(GResolv *resolv) if (g_atomic_int_dec_and_test(&resolv->ref_count) == FALSE) return; + flush_nameservers(resolv); + g_free(resolv); } @@ -82,3 +156,38 @@ void g_resolv_set_debug(GResolv *resolv, resolv->debug_func = func; resolv->debug_data = data; } + +int g_resolv_add_nameserver(GResolv *resolv, const char *address, + uint16_t port, unsigned long flags) +{ + struct resolv_nameserver *nameserver; + + if (resolv == NULL) + return -EINVAL; + + nameserver = g_try_new0(struct resolv_nameserver, 1); + if (nameserver == NULL) + return -ENOMEM; + + nameserver->address = g_strdup(address); + nameserver->port = port; + nameserver->flags = flags; + + if (connect_udp_channel(nameserver) < 0) { + free_nameserver(nameserver); + return -EIO; + } + + resolv->nameserver_list = g_list_append(resolv->nameserver_list, + nameserver); + + return 0; +} + +void g_resolv_flush_nameservers(GResolv *resolv) +{ + if (resolv == NULL) + return; + + flush_nameservers(resolv); +} diff --git a/gresolv/gresolv.h b/gresolv/gresolv.h index 521abd3..40b4972 100644 --- a/gresolv/gresolv.h +++ b/gresolv/gresolv.h @@ -22,6 +22,8 @@ #ifndef __G_RESOLV_H #define __G_RESOLV_H +#include + #include #ifdef __cplusplus @@ -42,6 +44,10 @@ void g_resolv_unref(GResolv *resolv); void g_resolv_set_debug(GResolv *resolv, GResolvDebugFunc func, gpointer data); +int g_resolv_add_nameserver(GResolv *resolv, const char *address, + uint16_t port, unsigned long flags); +void g_resolv_flush_nameservers(GResolv *resolv); + #ifdef __cplusplus } #endif -- 2.7.4