add some code for keeping track of dns servers and search domains and for writing...
authorFelix Fietkau <nbd@openwrt.org>
Mon, 10 Oct 2011 20:17:03 +0000 (22:17 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 11 Oct 2011 13:23:44 +0000 (15:23 +0200)
interface-ip.c
interface-ip.h
interface.c
interface.h
main.c
netifd.h

index 2d7a2d0d8d1b22a5ac9771f90f3d33ba67dc1e68..d2e1461cfa8cca291bd8a785775a3ed745496163 100644 (file)
@@ -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)
 {
index 057f0d05526b66dfce511010ccd9c23ce28e9db2..23782ad686d535ee046a8c974f4e911eff0d01ee 100644 (file)
@@ -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
index 17cb75418550c228123f999125d83320c84c95be..37b20cc9c03b13f4eb0a85bc1be494f04dc53be1 100644 (file)
@@ -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;
index 0e813043b32cae8bbb576e5485b141f6bcfff78f..6620796306363e2c5a6fb107e131d43e53c0dd17 100644 (file)
@@ -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 02dd1e51c308db7728b8bd7499044ccd5710d14d..5770782f1646498c29be6efd3d45c67be3491f63 100644 (file)
--- 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]);
                }
index aa04c512b5be6da153e7a5320f3f0a7cca6b0915..d034e7aef1e6018c6d5dd66d8a3491e44b145d59 100644 (file)
--- a/netifd.h
+++ b/netifd.h
 #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;