#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
#include "netifd.h"
#include "device.h"
}
}
+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)
{
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
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);
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)
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;
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;
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)
" -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);
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);
case 'h':
hotplug_cmd_path = optarg;
break;
+ case 'r':
+ resolv_conf = optarg;
+ break;
default:
return usage(argv[0]);
}
#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;