summaryrefslogtreecommitdiff
path: root/sbin/dhclient/dhclient.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2013-01-27 02:45:47 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2013-01-27 02:45:47 +0000
commit7916201b604eca6f61e23485c3bb6cf41fb93e44 (patch)
treec48bed3edae12da3ddb9510f760aae7600a36f50 /sbin/dhclient/dhclient.c
parent8d6479d68203c38f0bf1bc8233b57ca97ee3be7c (diff)
Refactor code a bit. Calculate resolv.conf contents once when binding a
lease and reuse as required whenever resolv.conf is written. Use write_file() rather than a custom message/functions to write out resolv.conf.
Diffstat (limited to 'sbin/dhclient/dhclient.c')
-rw-r--r--sbin/dhclient/dhclient.c121
1 files changed, 63 insertions, 58 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index e8dd7814e13..e3779d07128 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.216 2013/01/26 18:51:42 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.217 2013/01/27 02:45:46 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -60,6 +60,7 @@
#include <poll.h>
#include <pwd.h>
+#include <resolv.h>
#define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
#define DEFAULT_LEASE_TIME 43200 /* 12 hours... */
@@ -97,7 +98,8 @@ int res_hnok(const char *dn);
char *option_as_string(unsigned int code, unsigned char *data, int len);
void fork_privchld(int, int);
void get_ifname(char *);
-void new_resolv_conf(char *, char *, char *, char *);
+char *resolv_conf_contents(struct option_data *,
+ struct option_data *);
void write_file(char *, int, mode_t, uid_t, gid_t, u_int8_t *,
size_t);
struct client_lease *apply_defaults(struct client_lease *);
@@ -781,8 +783,13 @@ bind_lease(void)
if (nameservers == NULL)
error("no memory for nameservers");
- new_resolv_conf(ifi->name, domainname, nameservers,
- config->resolv_tail);
+ client->new->resolv_conf = resolv_conf_contents(
+ &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS]);
+ if (client->new->resolv_conf)
+ write_file("/etc/resolv.conf",
+ O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_EXLOCK,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0, 0,
+ client->new->resolv_conf, strlen(client->new->resolv_conf));
/*
* Add address and default route last, so we know when the binding
@@ -1510,6 +1517,8 @@ free_client_lease(struct client_lease *lease)
free(lease->server_name);
if (lease->filename)
free(lease->filename);
+ if (lease->resolv_conf)
+ free(lease->resolv_conf);
for (i = 0; i < 256; i++) {
if (lease->options[i].len)
free(lease->options[i].data);
@@ -1899,74 +1908,70 @@ get_ifname(char *arg)
* Update resolv.conf.
*/
-void
-new_resolv_conf(char *ifname, char *domainname, char *nameservers,
- char *resolv_tail)
+char *
+resolv_conf_contents(struct option_data *domainname,
+ struct option_data *nameservers)
{
- struct imsg_resolv_conf imsg;
- char *p;
- int rslt;
+ char *dn, *ns, *nss[MAXNS], *contents, *p;
+ size_t len;
+ int i, rslt;
- memset(&imsg, 0, sizeof(imsg));
+ memset(nss, 0, sizeof(nss));
- /* Build string of contents of new resolv.conf. */
- if (domainname && strlen(domainname)) {
- strlcat(imsg.contents, "search ", MAXRESOLVCONFSIZE);
- strlcat(imsg.contents, domainname, MAXRESOLVCONFSIZE);
- strlcat(imsg.contents, "\n", MAXRESOLVCONFSIZE);
- }
+ if (domainname->len) {
+ rslt = asprintf(&dn, "search %s\n",
+ pretty_print_option(DHO_DOMAIN_NAME, domainname, 0));
+ if (rslt == -1)
+ dn = NULL;
+ } else
+ dn = strdup("");
+ if (dn == NULL)
+ error("no memory for domainname");
- for (p = strsep(&nameservers, " "); p != NULL;
- p = strsep(&nameservers, " ")) {
- if (*p == '\0')
- continue;
- strlcat(imsg.contents, "nameserver ", MAXRESOLVCONFSIZE);
- strlcat(imsg.contents, p, MAXRESOLVCONFSIZE);
- strlcat(imsg.contents, "\n", MAXRESOLVCONFSIZE);
+ if (nameservers->len) {
+ ns = pretty_print_option(DHO_DOMAIN_NAME_SERVERS, nameservers,
+ 0);
+ for (i = 0; i < MAXNS; i++) {
+ p = strsep(&ns, " ");
+ if (p == NULL)
+ break;
+ if (*p == '\0')
+ continue;
+ rslt = asprintf(&nss[i], "nameserver %s\n", p);
+ if (rslt == -1)
+ error("no memory for nameserver");
+ }
}
- /* Don't touch resolv.conf if no domainname and no nameservers. */
- if (strlen(imsg.contents) == 0)
- return;
-
- strlcat(imsg.contents, resolv_tail, MAXRESOLVCONFSIZE);
+ len = strlen(dn) + 1;
+ for (i = 0; i < MAXNS; i++)
+ if (nss[i])
+ len += strlen(nss[i]);
- rslt = imsg_compose(unpriv_ibuf, IMSG_NEW_RESOLV_CONF, 0, 0, -1, &imsg,
- sizeof(imsg));
+ if (len > 0 && config->resolv_tail)
+ len += strlen(config->resolv_tail);
- if (rslt == -1)
- warning("new_resolv_conf: imsg_compose: %s", strerror(errno));
-}
+ if (len == 0)
+ return (NULL);
-void
-priv_resolv_conf(struct imsg_resolv_conf *imsg)
-{
- ssize_t n;
- int conffd;
+ contents = calloc(1, len);
+ if (contents == NULL)
+ error("no memory for resolv.conf contents");
- if (strlen(imsg->contents) == 0)
- return;
+ strlcat(contents, dn, len);
+ free(dn);
- conffd = open("/etc/resolv.conf",
- O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_EXLOCK,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (conffd == -1) {
- note("Couldn't open resolv.conf: %s", strerror(errno));
- return;
+ for (i = 0; i < MAXNS; i++) {
+ if (nss[i]) {
+ strlcat(contents, nss[i], len);
+ free(nss[i]);
+ }
}
- n = write(conffd, imsg->contents, strlen(imsg->contents));
- if (n == -1)
- note("Couldn't write contents to resolv.conf: %s",
- strerror(errno));
- else if (n < strlen(imsg->contents))
- note("Short contents write to resolv.conf (%zd vs %zd)",
- n, strlen(imsg->contents));
-
- fchmod(conffd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- fchown(conffd, 0, 0); /* root:wheel */
+ if (config->resolv_tail)
+ strlcat(contents, config->resolv_tail, len);
- close(conffd);
+ return (contents);
}
struct client_lease *