summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-10-10 22:17:03 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-10-11 15:23:44 +0200
commit41842d3f91733786cb4d2bcdc6ca0c3a1a1c594b (patch)
treeac120ef2e43cc60b18a81ea9fbf5f6f1e60c8f54
parent34a1a4bad31ba6f138cd6a98249c774ff66285d1 (diff)
downloadnetifd-41842d3f91733786cb4d2bcdc6ca0c3a1a1c594b.tar.gz
add some code for keeping track of dns servers and search domains and for writing resolv.conf
-rw-r--r--interface-ip.c79
-rw-r--r--interface-ip.h13
-rw-r--r--interface.c4
-rw-r--r--interface.h3
-rw-r--r--main.c7
-rw-r--r--netifd.h3
6 files changed, 108 insertions, 1 deletions
diff --git a/interface-ip.c b/interface-ip.c
index 2d7a2d0..d2e1461 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -1,6 +1,9 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
#include "netifd.h"
#include "device.h"
@@ -76,6 +79,82 @@ interface_update_proto_route(struct vlist_tree *tree,
}
}
+static void
+interface_clear_dns_servers(struct interface *iface)
+{
+ struct dns_server *s, *tmp;
+
+ list_for_each_entry_safe(s, tmp, &iface->proto_dns_servers, list) {
+ list_del(&s->list);
+ free(s);
+ }
+}
+
+static void
+interface_clear_dns_search(struct interface *iface)
+{
+ struct dns_search_domain *s, *tmp;
+
+ list_for_each_entry_safe(s, tmp, &iface->proto_dns_search, list) {
+ list_del(&s->list);
+ free(s);
+ }
+}
+
+void
+interface_clear_dns(struct interface *iface)
+{
+ interface_clear_dns_servers(iface);
+ interface_clear_dns_search(iface);
+}
+
+void
+interface_write_resolv_conf(void)
+{
+ struct interface *iface;
+ struct dns_server *s;
+ struct dns_search_domain *d;
+ char *path = alloca(strlen(resolv_conf) + 5);
+ const char *str;
+ char buf[32];
+ FILE *f;
+
+ sprintf(path, "%s.tmp", resolv_conf);
+ unlink(path);
+ f = fopen(path, "w");
+ if (!f) {
+ D(INTERFACE, "Failed to open %s for writing\n", path);
+ return;
+ }
+
+ vlist_for_each_element(&interfaces, iface, node) {
+ if (iface->state != IFS_UP)
+ continue;
+
+ if (list_empty(&iface->proto_dns_search) &&
+ list_empty(&iface->proto_dns_servers))
+ continue;
+
+ fprintf(f, "# Interface %s\n", iface->name);
+ list_for_each_entry(s, &iface->proto_dns_servers, list) {
+ str = inet_ntop(s->af, &s->addr, buf, sizeof(buf));
+ if (!str)
+ continue;
+
+ fprintf(f, "nameserver %s\n", str);
+ }
+
+ list_for_each_entry(d, &iface->proto_dns_search, list) {
+ fprintf(f, "search %s\n", d->name);
+ }
+ }
+ fclose(f);
+ if (rename(path, resolv_conf) < 0) {
+ D(INTERFACE, "Failed to replace %s\n", resolv_conf);
+ unlink(path);
+ }
+}
+
void
interface_ip_init(struct interface *iface)
{
diff --git a/interface-ip.h b/interface-ip.h
index 057f0d0..23782ad 100644
--- a/interface-ip.h
+++ b/interface-ip.h
@@ -43,6 +43,19 @@ struct device_route {
union if_addr addr;
};
+struct dns_server {
+ struct list_head list;
+ int af;
+ union if_addr addr;
+};
+
+struct dns_search_domain {
+ struct list_head list;
+ char name[];
+};
+
void interface_ip_init(struct interface *iface);
+void interface_clear_dns(struct interface *iface);
+void interface_write_resolv_conf(void);
#endif
diff --git a/interface.c b/interface.c
index 17cb754..37b20cc 100644
--- a/interface.c
+++ b/interface.c
@@ -185,6 +185,7 @@ interface_claim_device(struct interface *iface)
static void
interface_cleanup(struct interface *iface)
{
+ interface_clear_dns(iface);
interface_clear_errors(iface);
if (iface->main_dev.dev)
device_remove_user(&iface->main_dev);
@@ -241,6 +242,7 @@ interface_proto_cb(struct interface_proto_state *state, enum interface_proto_eve
iface->state = IFS_UP;
iface->start_time = system_get_rtime();
interface_event(iface, IFEV_UP);
+ interface_write_resolv_conf();
break;
case IFPEV_DOWN:
if (iface->state == IFS_DOWN)
@@ -285,6 +287,8 @@ interface_init(struct interface *iface, const char *name,
strncpy(iface->name, name, sizeof(iface->name) - 1);
INIT_LIST_HEAD(&iface->errors);
INIT_LIST_HEAD(&iface->hotplug_list);
+ INIT_LIST_HEAD(&iface->proto_dns_search);
+ INIT_LIST_HEAD(&iface->proto_dns_servers);
iface->main_dev.cb = interface_cb;
iface->l3_dev = &iface->main_dev;
diff --git a/interface.h b/interface.h
index 0e81304..6620796 100644
--- a/interface.h
+++ b/interface.h
@@ -67,6 +67,9 @@ struct interface {
struct vlist_tree proto_addr;
struct vlist_tree proto_route;
+ struct list_head proto_dns_servers;
+ struct list_head proto_dns_search;
+
/* errors/warnings while trying to bring up the interface */
struct list_head errors;
diff --git a/main.c b/main.c
index 02dd1e5..5770782 100644
--- a/main.c
+++ b/main.c
@@ -12,6 +12,7 @@
unsigned int debug_mask = 0;
const char *main_path = DEFAULT_MAIN_PATH;
+const char *resolv_conf = DEFAULT_RESOLV_CONF;
static char **global_argv;
static void netifd_do_restart(struct uloop_timeout *timeout)
@@ -47,6 +48,7 @@ static int usage(const char *progname)
" -s <path>: Path to the ubus socket\n"
" -p <path>: Path to netifd addons (default: %s)\n"
" -h <path>: Path to the hotplug script\n"
+ " -r <path>: Path to resolv.conf\n"
" (default: "DEFAULT_HOTPLUG_PATH")\n"
"\n", progname, main_path);
@@ -60,7 +62,7 @@ int main(int argc, char **argv)
global_argv = argv;
- while ((ch = getopt(argc, argv, "d:s:")) != -1) {
+ while ((ch = getopt(argc, argv, "d:s:p:h:r:")) != -1) {
switch(ch) {
case 'd':
debug_mask = strtoul(optarg, NULL, 0);
@@ -74,6 +76,9 @@ int main(int argc, char **argv)
case 'h':
hotplug_cmd_path = optarg;
break;
+ case 'r':
+ resolv_conf = optarg;
+ break;
default:
return usage(argv[0]);
}
diff --git a/netifd.h b/netifd.h
index aa04c51..d034e7a 100644
--- a/netifd.h
+++ b/netifd.h
@@ -16,11 +16,14 @@
#ifdef DUMMY_MODE
#define DEFAULT_MAIN_PATH "./dummy"
#define DEFAULT_HOTPLUG_PATH "./scripts/hotplug-cmd"
+#define DEFAULT_RESOLV_CONF "./tmp/resolv.conf"
#else
#define DEFAULT_MAIN_PATH "/lib/netifd"
#define DEFAULT_HOTPLUG_PATH "/sbin/hotplug-cmd"
+#define DEFAULT_RESOLV_CONF "/tmp/resolv.conf.auto"
#endif
+extern const char *resolv_conf;
extern char *hotplug_cmd_path;
extern unsigned int debug_mask;