On Sun, Jul 19, 2015 at 07:03:59PM +0100, Stuart Henderson wrote: > [...] > I'm uncertain about whether dhclient should do this at all, it seems > to be the opposite of the direction dhclient has been going in > recently, > [...]
I've had a similar intuition at first, but it's one less thing to run versus the "monitor lease file" approach and it only calls one static external command with relatively fixed parameters instead of what the removed `script' option did. In the end, it's a matter of personal taste, I think. > [...] > but if it is added, it probably wants to be disabled for the ramdisk. > [...] I've attached an updated patch, in case this is still interesting to someone. Do I need to add anything other than `#ifdef SMALL' in the appropriate places? -- Gregor Best -- Index: clparse.c =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/clparse.c,v retrieving revision 1.92 diff -u -p -r1.92 clparse.c --- clparse.c 18 May 2015 17:51:21 -0000 1.92 +++ clparse.c 19 Jul 2015 18:44:12 -0000 @@ -75,6 +75,9 @@ read_client_conf(void) config->backoff_cutoff = 15; config->initial_interval = 3; config->bootp_policy = ACCEPT; +#ifndef SMALL + config->update_unbound = 0; +#endif config->requested_options [config->requested_option_count++] = DHO_SUBNET_MASK; config->requested_options @@ -270,6 +273,12 @@ parse_client_statement(FILE *cfile) if (parse_ip_addr(cfile, &config->next_server)) parse_semi(cfile); break; +#ifndef SMALL + case TOK_UPDATE_UNBOUND: + config->update_unbound = 1; + parse_semi(cfile); + break; +#endif default: parse_warn("expecting a statement."); if (token != ';') Index: conflex.c =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/conflex.c,v retrieving revision 1.32 diff -u -p -r1.32 conflex.c --- conflex.c 18 May 2015 17:51:21 -0000 1.32 +++ conflex.c 19 Jul 2015 18:48:00 -0000 @@ -341,7 +341,10 @@ static const struct keywords { { "send", TOK_SEND }, { "server-name", TOK_SERVER_NAME }, { "supersede", TOK_SUPERSEDE }, - { "timeout", TOK_TIMEOUT } + { "timeout", TOK_TIMEOUT }, +#ifndef SMALL + { "update-unbound", TOK_UPDATE_UNBOUND } +#endif }; int kw_cmp(const void *k, const void *e); Index: dhclient.c =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/dhclient.c,v retrieving revision 1.361 diff -u -p -r1.361 dhclient.c --- dhclient.c 18 May 2015 14:59:42 -0000 1.361 +++ dhclient.c 19 Jul 2015 18:45:28 -0000 @@ -97,6 +97,9 @@ int res_hnok(const char *dn); void fork_privchld(int, int); void get_ifname(char *); +#ifndef SMALL +void update_unbound_forwards(struct option_data *); +#endif char *resolv_conf_contents(struct option_data *, struct option_data *); void write_resolv_conf(u_int8_t *, size_t); @@ -903,8 +906,15 @@ bind_lease(void) goto newlease; } - client->new->resolv_conf = resolv_conf_contents( - &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS]); +#ifndef SMALL + if (config->update_unbound) { + update_unbound_forwards(&options[DHO_DOMAIN_NAME_SERVERS]); + } else +#endif + { + client->new->resolv_conf = resolv_conf_contents( + &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS]); + } /* Replace the old active lease with the new one. */ client->active = client->new; @@ -2043,6 +2053,91 @@ get_ifname(char *arg) } else if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ) error("Interface name too long"); } + +#ifndef SMALL +/* + * Update unbound forwarder list + */ +void +update_unbound_forwards(struct option_data *nameservers) +{ + char *ns; + int rslt; + + if (!nameservers->len) { + return; + } + + ns = pretty_print_option(DHO_DOMAIN_NAME_SERVERS, nameservers, 0); + + rslt = imsg_compose(unpriv_ibuf, IMSG_UPDATE_UNBOUND_FORWARDS, + 0, 0, -1, ns, strlen(ns) + 1); + + if (rslt == -1) { + warning("update_unbound_forwards: imsg_compose: %s", + strerror(errno)); + } + + flush_unpriv_ibuf("update_unbound_forwards"); +} + +void +priv_update_unbound_forwards(struct imsg *imsg) +{ + char *args[MAXNS + 3]; /* `unbound-control', `forward', final NULL */ + char *ns, *p, **srv; + int rslt, i = 0; + size_t sz; + pid_t child; + + if (imsg->hdr.len < IMSG_HEADER_SIZE) { + warning("short IMSG_UPDATE_UNBOUND_FORWARDS"); + return; + } + + ns = imsg->data; + sz = imsg->hdr.len - IMSG_HEADER_SIZE; + ns[sz] = '\0'; /* Make sure we're terminated properly */ + + /* Construct unbound-control arguments */ + memset(args, 0, sizeof(args)); + args[0] = "unbound-control"; + args[1] = "forward"; + srv = &args[2]; + while (i < MAXNS) { + p = strsep(&ns, " "); + if (p == NULL) + break; + if (*p == '\0') + continue; + rslt = asprintf(&srv[i++], "%s", p); + if (rslt == -1) + error("no memory for nameserver"); + } + + switch ((child = fork())) { + case -1: + error("cannot fork"); + break; + case 0: + fclose(stdout); /* Prevent noise from unbound-control */ + execvp("unbound-control", args); + error("execve failed: %s", strerror(errno)); + break; + default: + if (waitpid(child, NULL, 0) < 0) { + error("waitpid: %s", strerror(errno)); + } + break; + } + + for (i = 0; i < MAXNS; i++) { + if (!srv[i]) + break; + free(srv[i]); + } +} +#endif /* SMALL */ /* * Update resolv.conf. Index: dhclient.conf.5 =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/dhclient.conf.5,v retrieving revision 1.31 diff -u -p -r1.31 dhclient.conf.5 --- dhclient.conf.5 11 Nov 2013 15:39:20 -0000 1.31 +++ dhclient.conf.5 19 Jul 2015 17:31:34 -0000 @@ -406,6 +406,16 @@ specified name. Interfaces for which there is no interface declaration will use the parameters declared outside of any interface declaration, or the default settings. +.It Ic update-unbound ; +The +.Ic update-unbound +statement causes dhclient to update the unbound forward DNS list with received +name servers instead of updating /etc/resolv.conf. +This is essentially the same as calling +.Pp +.D1 unbound-control forward <ns1> <ns2> <ns3> +.Pp +after acquiring a lease that contains name server information. .El .Sh EXAMPLES The following configuration file is used on a laptop Index: dhcpd.h =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/dhcpd.h,v retrieving revision 1.150 diff -u -p -r1.150 dhcpd.h --- dhcpd.h 18 May 2015 14:59:42 -0000 1.150 +++ dhcpd.h 19 Jul 2015 18:45:57 -0000 @@ -146,6 +146,9 @@ struct client_config { time_t backoff_cutoff; enum { IGNORE, ACCEPT, PREFER } bootp_policy; +#ifndef SMALL + int update_unbound; +#endif TAILQ_HEAD(, reject_elem) reject_list; char *resolv_tail; char *filename; Index: dhctoken.h =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/dhctoken.h,v retrieving revision 1.9 diff -u -p -r1.9 dhctoken.h --- dhctoken.h 5 Dec 2013 22:31:35 -0000 1.9 +++ dhctoken.h 19 Jul 2015 18:43:36 -0000 @@ -78,6 +78,9 @@ #define TOK_REJECT 292 #define TOK_LINK_TIMEOUT 294 #define TOK_IGNORE 295 +#ifndef SMALL +#define TOK_UPDATE_UNBOUND 296 +#endif /* SMALL */ #define is_identifier(x) ((x) >= TOK_FIRST_TOKEN && \ (x) != TOK_STRING && \ Index: privsep.c =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/privsep.c,v retrieving revision 1.39 diff -u -p -r1.39 privsep.c --- privsep.c 7 Feb 2015 10:08:06 -0000 1.39 +++ privsep.c 19 Jul 2015 18:46:06 -0000 @@ -93,6 +93,11 @@ dispatch_imsg(struct imsgbuf *ibuf) case IMSG_WRITE_OPTION_DB: priv_write_option_db(&imsg); break; +#ifndef SMALL + case IMSG_UPDATE_UNBOUND_FORWARDS: + priv_update_unbound_forwards(&imsg); + break; +#endif default: warning("received unknown message, code %u", Index: privsep.h =================================================================== RCS file: /mnt/media/cvs/src/sbin/dhclient/privsep.h,v retrieving revision 1.28 diff -u -p -r1.28 privsep.h --- privsep.h 10 Feb 2015 04:20:26 -0000 1.28 +++ privsep.h 19 Jul 2015 18:46:55 -0000 @@ -29,7 +29,10 @@ enum imsg_code { IMSG_SET_INTERFACE_MTU, IMSG_HUP, IMSG_WRITE_RESOLV_CONF, - IMSG_WRITE_OPTION_DB + IMSG_WRITE_OPTION_DB, +#ifndef SMALL + IMSG_UPDATE_UNBOUND_FORWARDS +#endif }; struct imsg_delete_address { @@ -72,3 +75,6 @@ void priv_set_interface_mtu(struct imsg_ void priv_write_resolv_conf(struct imsg *); void priv_write_option_db(struct imsg *); void priv_write_file(char *, int, mode_t, uid_t, gid_t, u_int8_t *, size_t); +#ifndef SMALL +void priv_update_unbound_forwards(struct imsg *); +#endif