]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Handle all file IO in the Priviledged Actioneer
authorRoy Marples <roy@marples.name>
Tue, 12 May 2020 09:26:35 +0000 (10:26 +0100)
committerRoy Marples <roy@marples.name>
Tue, 12 May 2020 09:26:35 +0000 (10:26 +0100)
This allows us to move the database directory back into the
root of the filesystem.
While here, harden the files by denying any user read access to them.

As part of this change, init the DUID from any machine data and
cache the default DHCP vendor field before dropping priviledges as we
may lose access to this later.

27 files changed:
src/common.c
src/common.h
src/dhcp-common.c
src/dhcp-common.h
src/dhcp.c
src/dhcp6.c
src/dhcpcd-embedded.c.in
src/dhcpcd-embedded.h.in
src/dhcpcd.c
src/dhcpcd.h
src/duid.c
src/duid.h
src/genembedc
src/if-bsd.c
src/if-linux.c
src/if-options.c
src/if-options.h
src/if.h
src/ipv6.c
src/logerr.c
src/privsep-bpf.c
src/privsep-bsd.c
src/privsep-inet.c
src/privsep-root.c
src/privsep-root.h
src/privsep.c
src/privsep.h

index c4eecfee50d90cd0c86faccc741906548f7d3c8d..e72a882ef014bf91704cd69d52fe06941138512a 100644 (file)
  * SUCH DAMAGE.
  */
 
+#include <sys/stat.h>
 #include <sys/statvfs.h>
 
 #include <ctype.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "common.h"
 #include "dhcpcd.h"
 #include "if-options.h"
-#include "logerr.h"
 
 const char *
 hwaddr_ntoa(const void *hwaddr, size_t hwlen, char *buf, size_t buflen)
@@ -103,36 +104,58 @@ hwaddr_aton(uint8_t *buffer, const char *addr)
        return len;
 }
 
-size_t
-read_hwaddr_aton(uint8_t **data, const char *path)
+ssize_t
+readfile(const char *file, void *data, size_t len)
 {
-       FILE *fp;
-       char *buf;
-       size_t buf_len, len;
-
-       if ((fp = fopen(path, "r")) == NULL)
-               return 0;
-
-       buf = NULL;
-       buf_len = len = 0;
-       *data = NULL;
-       while (getline(&buf, &buf_len, fp) != -1) {
-               if ((len = hwaddr_aton(NULL, buf)) != 0) {
-                       if (buf_len >= len)
-                               *data = (uint8_t *)buf;
-                       else {
-                               if ((*data = malloc(len)) == NULL)
-                                       len = 0;
-                       }
-                       if (len != 0)
-                               (void)hwaddr_aton(*data, buf);
-                       if (buf_len < len)
-                               free(buf);
-                       break;
-               }
+       int fd;
+       struct stat st;
+       ssize_t bytes = -1;
+
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       if (fstat(fd, &st) != 0)
+               goto out;
+       if (!S_ISREG(st.st_mode)) {
+               errno = EINVAL;
+               goto out;
        }
-       fclose(fp);
-       return len;
+       if ((size_t)st.st_size > len) {
+               errno = E2BIG;
+               goto out;
+       }
+       bytes = read(fd, data, len);
+
+out:
+       if (fd != -1)
+               close(fd);
+       return bytes;
+}
+
+ssize_t
+writefile(const char *file, mode_t mode, const void *data, size_t len)
+{
+       int fd;
+       ssize_t bytes;
+
+       fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, mode);
+       if (fd == -1)
+               return -1;
+       bytes = write(fd, data, len);
+       close(fd);
+       return bytes;
+}
+
+int
+filemtime(const char *file, time_t *time)
+{
+       struct stat st;
+
+       if (stat(file, &st) == -1)
+               return -1;
+       *time = st.st_mtime;
+       return 0;
 }
 
 int
index b054d58197ff8a18df9132e2b0fb07793c2c8efd..b848434aff4f54bdff2480b984fff5c9038cd728 100644 (file)
 
 const char *hwaddr_ntoa(const void *, size_t, char *, size_t);
 size_t hwaddr_aton(uint8_t *, const char *);
-size_t read_hwaddr_aton(uint8_t **, const char *);
+ssize_t readfile(const char *, void *, size_t);
+ssize_t writefile(const char *, mode_t, const void *, size_t);
+int filemtime(const char *, time_t *);
 int is_root_local(void);
 #endif
index 93d42f4addf718fecee6cd34cfbbbcb42d9ea177..b3e9c1e03f2a49745ff46dc7ba3fb5a24a94d662 100644 (file)
@@ -26,7 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/stat.h>
 #include <sys/utsname.h>
 
 #include <ctype.h>
@@ -176,9 +175,10 @@ dhcp_vendor(char *str, size_t len)
                return -1;
        p += l;
        len -= (size_t)l;
-       l = if_machinearch(p, len);
+       l = if_machinearch(p + 1, len - 1);
        if (l == -1 || (size_t)(l + 1) > len)
                return -1;
+       *p = ':';
        p += l;
        return p - str;
 }
@@ -945,38 +945,85 @@ dhcp_zero_index(struct dhcp_opt *opt)
                dhcp_zero_index(o);
 }
 
-size_t
-dhcp_read_lease_fd(int fd, void **lease)
+ssize_t
+dhcp_readfile(struct dhcpcd_ctx *ctx, const char *file, void *data, size_t len)
 {
-       struct stat st;
-       size_t sz;
-       void *buf;
-       ssize_t len;
 
-       if (fstat(fd, &st) != 0)
-               goto out;
-       if (!S_ISREG(st.st_mode)) {
-               errno = EINVAL;
-               goto out;
-       }
-       if (st.st_size > UINT32_MAX) {
-               errno = E2BIG;
-               goto out;
-       }
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP &&
+           !(ctx->options & DHCPCD_PRIVSEPROOT))
+               return ps_root_readfile(ctx, file, data, len);
+#else
+       UNUSED(ctx);
+#endif
 
-       sz = (size_t)st.st_size;
-       if (sz == 0)
-               goto out;
-       if ((buf = malloc(sz)) == NULL)
-               goto out;
-       if ((len = read(fd, buf, sz)) == -1) {
-               free(buf);
-               goto out;
-       }
-       *lease = buf;
-       return (size_t)len;
+       return readfile(file, data, len);
+}
 
-out:
-       *lease = NULL;
-       return 0;
+ssize_t
+dhcp_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode,
+    const void *data, size_t len)
+{
+
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP &&
+           !(ctx->options & DHCPCD_PRIVSEPROOT))
+               return ps_root_writefile(ctx, file, mode, data, len);
+#else
+       UNUSED(ctx);
+#endif
+
+       return writefile(file, mode, data, len);
+}
+
+int
+dhcp_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
+{
+
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP &&
+           !(ctx->options & DHCPCD_PRIVSEPROOT))
+               return ps_root_filemtime(ctx, file, time);
+#else
+       UNUSED(ctx);
+#endif
+
+       return filemtime(file, time);
+}
+
+int
+dhcp_unlink(struct dhcpcd_ctx *ctx, const char *file)
+{
+
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP &&
+           !(ctx->options & DHCPCD_PRIVSEPROOT))
+               return ps_root_unlink(ctx, file);
+#else
+       UNUSED(ctx);
+#endif
+
+       return unlink(file);
+}
+
+size_t
+dhcp_read_hwaddr_aton(struct dhcpcd_ctx *ctx, uint8_t **data, const char *file)
+{
+       char buf[BUFSIZ];
+       ssize_t bytes;
+       size_t len;
+
+       bytes = dhcp_readfile(ctx, file, buf, sizeof(buf));
+       if (bytes == -1 || bytes == sizeof(buf))
+               return 0;
+
+       bytes[buf] = '\0';
+       len = hwaddr_aton(NULL, buf);
+       if (len == 0)
+               return 0;
+       *data = malloc(len);
+       if (*data == NULL)
+               return 0;
+       hwaddr_aton(*data, buf);
+       return len;
 }
index ed020b139535fa2ae396112dd3b4a88dae98ea1c..7be821f0baa81d51240e7aaf7c59b6d84324b3f0 100644 (file)
@@ -136,6 +136,11 @@ void dhcp_envoption(struct dhcpcd_ctx *,
     const uint8_t *, size_t, struct dhcp_opt **),
     const uint8_t *od, size_t ol);
 void dhcp_zero_index(struct dhcp_opt *);
-size_t dhcp_read_lease_fd(int, void **);
 
+ssize_t dhcp_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
+ssize_t dhcp_writefile(struct dhcpcd_ctx *, const char *, mode_t,
+    const void *, size_t);
+int dhcp_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
+int dhcp_unlink(struct dhcpcd_ctx *, const char *);
+size_t dhcp_read_hwaddr_aton(struct dhcpcd_ctx *, uint8_t **, const char *);
 #endif
index 23ba8761888c786b603f98228daac87bee8a5703..d9683a9313631a6b7438f138abe309aa5da10ac0 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <sys/param.h>
 #include <sys/socket.h>
-#include <sys/stat.h>
 
 #include <arpa/inet.h>
 #include <net/if.h>
@@ -1142,31 +1141,16 @@ toobig:
        return -1;
 }
 
-static ssize_t
-write_lease(const struct interface *ifp, const struct bootp *bootp, size_t len)
-{
-       int fd;
-       ssize_t bytes;
-       const struct dhcp_state *state = D_CSTATE(ifp);
-
-       logdebugx("%s: writing lease `%s'", ifp->name, state->leasefile);
-
-       fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-       if (fd == -1)
-               return -1;
-       bytes = write(fd, bootp, len);
-       close(fd);
-       return bytes;
-}
-
 static size_t
 read_lease(struct interface *ifp, struct bootp **bootp)
 {
-       int fd;
-       bool fd_opened;
+       union {
+               struct bootp bootp;
+               uint8_t buf[FRAMELEN_MAX];
+       } buf;
        struct dhcp_state *state = D_STATE(ifp);
        struct bootp *lease;
-       size_t bytes;
+       ssize_t bytes;
        uint8_t type;
 #ifdef AUTH
        const uint8_t *auth;
@@ -1177,37 +1161,26 @@ read_lease(struct interface *ifp, struct bootp **bootp)
        *bootp = NULL;
 
        if (state->leasefile[0] == '\0') {
-               fd = fileno(stdin);
-               fd_opened = false;
+               logdebugx("reading standard input");
+               bytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
        } else {
-               fd = open(state->leasefile, O_RDONLY);
-               fd_opened = true;
+               logdebugx("%s: reading lease `%s'",
+                   ifp->name, state->leasefile);
+               bytes = dhcp_readfile(ifp->ctx, state->leasefile,
+                   buf.buf, sizeof(buf.buf));
        }
-       if (fd == -1) {
+       if (bytes == -1) {
                if (errno != ENOENT)
-                       logerr("%s: open `%s'",
-                           ifp->name, state->leasefile);
+                       logerr("%s: %s", ifp->name, state->leasefile);
                return 0;
        }
-       if (state->leasefile[0] == '\0')
-               logdebugx("reading standard input");
-       else
-               logdebugx("%s: reading lease `%s'",
-                   ifp->name, state->leasefile);
-
-       bytes = dhcp_read_lease_fd(fd, (void **)&lease);
-       if (fd_opened)
-               close(fd);
-       if (bytes == 0)
-               return 0;
 
        /* Ensure the packet is at lease BOOTP sized
         * with a vendor area of 4 octets
         * (it should be more, and our read packet enforces this so this
         * code should not be needed, but of course people could
         * scribble whatever in the stored lease file. */
-       if (bytes < DHCP_MIN_LEN) {
-               free(lease);
+       if ((size_t)bytes < DHCP_MIN_LEN) {
                logerrx("%s: %s: truncated lease", ifp->name, __func__);
                return 0;
        }
@@ -1216,20 +1189,19 @@ read_lease(struct interface *ifp, struct bootp **bootp)
                goto out;
 
        /* We may have found a BOOTP server */
-       if (get_option_uint8(ifp->ctx, &type, (struct bootp *)lease, bytes,
+       if (get_option_uint8(ifp->ctx, &type, &buf.bootp, bytes,
            DHO_MESSAGETYPE) == -1)
                type = 0;
 
 #ifdef AUTH
        /* Authenticate the message */
-       auth = get_option(ifp->ctx, (struct bootp *)lease, bytes,
+       auth = get_option(ifp->ctx, &buf.bootp, bytes,
            DHO_AUTHENTICATION, &auth_len);
        if (auth) {
                if (dhcp_auth_validate(&state->auth, &ifp->options->auth,
                    lease, bytes, 4, type, auth, auth_len) == NULL)
                {
                        logerr("%s: authentication failed", ifp->name);
-                       free(lease);
                        return 0;
                }
                if (state->auth.token)
@@ -1241,14 +1213,18 @@ read_lease(struct interface *ifp, struct bootp **bootp)
            DHCPCD_AUTH_SENDREQUIRE)
        {
                logerrx("%s: authentication now required", ifp->name);
-               free(lease);
                return 0;
        }
 #endif
 
 out:
-       *bootp = (struct bootp *)lease;
-       return bytes;
+       *bootp = malloc(bytes);
+       if (*bootp == NULL) {
+               logerr(__func__);
+               return 0;
+       }
+       memcpy(*bootp, buf.buf, bytes);
+       return (size_t)bytes;
 }
 
 static const struct dhcp_opt *
@@ -1929,7 +1905,7 @@ dhcp_expire1(struct interface *ifp)
 
        eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
        dhcp_drop(ifp, "EXPIRE");
-       unlink(state->leasefile);
+       dhcp_unlink(ifp->ctx, state->leasefile);
        state->interval = 0;
        if (!(ifp->options->options & DHCPCD_LINK) || ifp->carrier > LINK_DOWN)
                dhcp_discover(ifp);
@@ -2072,7 +2048,7 @@ dhcp_addr_duplicated(struct interface *ifp, struct in_addr *ia)
 
        /* RFC 2131 3.1.5, Client-server interaction */
        logerrx("%s: DAD detected %s", ifp->name, inet_ntoa(*ia));
-       unlink(state->leasefile);
+       dhcp_unlink(ifp->ctx, state->leasefile);
        if (!(opts & DHCPCD_STATIC) && !state->lease.frominfo)
                dhcp_decline(ifp);
 #ifdef IN_IFF_DUPLICATED
@@ -2299,9 +2275,13 @@ dhcp_bind(struct interface *ifp)
        }
        state->state = DHS_BOUND;
        if (!state->lease.frominfo &&
-           !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
-               if (write_lease(ifp, state->new, state->new_len) == -1)
-                       logerr("write_lease: %s", state->leasefile);
+           !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) {
+               logdebugx("%s: writing lease `%s'",
+                   ifp->name, state->leasefile);
+               if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
+                   state->new, state->new_len) == -1)
+                       logerr("dhcp_writefile: %s", state->leasefile);
+       }
 
        /* Close the BPF filter as we can now receive DHCP messages
         * on a UDP socket. */
@@ -2749,7 +2729,7 @@ dhcp_drop(struct interface *ifp, const char *reason)
                        return;
                state->state = DHS_RELEASE;
 
-               unlink(state->leasefile);
+               dhcp_unlink(ifp->ctx, state->leasefile);
                if (ifp->carrier > LINK_DOWN &&
                    state->new != NULL &&
                    state->lease.server.s_addr != INADDR_ANY)
@@ -3114,7 +3094,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
                        return;
                if (!(ifp->ctx->options & DHCPCD_TEST)) {
                        dhcp_drop(ifp, "NAK");
-                       unlink(state->leasefile);
+                       dhcp_unlink(ifp->ctx, state->leasefile);
                }
 
                /* If we constantly get NAKS then we should slowly back off */
@@ -3788,7 +3768,7 @@ dhcp_init(struct interface *ifp)
        /* We need to drop the leasefile so that dhcp_start
         * doesn't load it. */
        if (ifo->options & DHCPCD_REQUEST)
-               unlink(state->leasefile);
+               dhcp_unlink(ifp->ctx, state->leasefile);
 
        free(state->clientid);
        state->clientid = NULL;
@@ -3862,7 +3842,6 @@ dhcp_start1(void *arg)
        struct dhcpcd_ctx *ctx = ifp->ctx;
        struct if_options *ifo = ifp->options;
        struct dhcp_state *state;
-       struct stat st;
        uint32_t l;
        int nolease;
 
@@ -3947,6 +3926,7 @@ dhcp_start1(void *arg)
        }
        if (state->offer) {
                struct ipv4_addr *ia;
+               time_t mtime;
 
                get_lease(ifp, &state->lease, state->offer, state->offer_len);
                state->lease.frominfo = 1;
@@ -3974,14 +3954,14 @@ dhcp_start1(void *arg)
                        state->offer_len = 0;
                } else if (!(ifo->options & DHCPCD_LASTLEASE_EXTEND) &&
                    state->lease.leasetime != DHCP_INFINITE_LIFETIME &&
-                   stat(state->leasefile, &st) == 0)
+                   dhcp_filemtime(ifp->ctx, state->leasefile, &mtime) == 0)
                {
                        time_t now;
 
                        /* Offset lease times and check expiry */
                        now = time(NULL);
                        if (now == -1 ||
-                           (time_t)state->lease.leasetime < now - st.st_mtime)
+                           (time_t)state->lease.leasetime < now - mtime)
                        {
                                logdebugx("%s: discarding expired lease",
                                    ifp->name);
@@ -4006,7 +3986,7 @@ dhcp_start1(void *arg)
                                        dhcp_drop(ifp, "EXPIRE");
 #endif
                        } else {
-                               l = (uint32_t)(now - st.st_mtime);
+                               l = (uint32_t)(now - mtime);
                                state->lease.leasetime -= l;
                                state->lease.renewaltime -= l;
                                state->lease.rebindtime -= l;
index 2019cdb98f50db77955d57a507de879a0aa9859f..f46ba42491e6468c2cdfa8ac2fe42982722fbd21 100644 (file)
@@ -26,7 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/stat.h>
 #include <sys/utsname.h>
 
 #include <netinet/in.h>
@@ -258,9 +257,8 @@ static size_t
 dhcp6_makevendor(void *data, const struct interface *ifp)
 {
        const struct if_options *ifo;
-       size_t len, i;
+       size_t len, vlen, i;
        uint8_t *p;
-       ssize_t vlen;
        const struct vivco *vivco;
        char vendor[VENDORCLASSID_MAX_LEN];
        struct dhcp6_option o;
@@ -274,11 +272,8 @@ dhcp6_makevendor(void *data, const struct interface *ifp)
                        len += sizeof(uint16_t) + vivco->len;
                vlen = 0; /* silence bogus gcc warning */
        } else {
-               vlen = dhcp_vendor(vendor, sizeof(vendor));
-               if (vlen == -1)
-                       vlen = 0;
-               else
-                       len += sizeof(uint16_t) + (size_t)vlen;
+               vlen = strlcpy(vendor, ifp->ctx->vendor, sizeof(vendor));
+               len += sizeof(uint16_t) + vlen;
        }
 
        if (len > UINT16_MAX) {
@@ -1748,7 +1743,7 @@ dhcp6_fail(struct interface *ifp)
                state->new_len = 0;
                if (state->old != NULL)
                        script_runreason(ifp, "EXPIRE6");
-               unlink(state->leasefile);
+               dhcp_unlink(ifp->ctx, state->leasefile);
        }
 
        if (!dhcp6_startdiscoinform(ifp)) {
@@ -2590,106 +2585,77 @@ dhcp6_validatelease(struct interface *ifp,
 }
 
 static ssize_t
-dhcp6_writelease(const struct interface *ifp)
-{
-       const struct dhcp6_state *state;
-       int fd;
-       ssize_t bytes;
-
-       state = D6_CSTATE(ifp);
-       logdebugx("%s: writing lease `%s'", ifp->name, state->leasefile);
-
-       fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-       if (fd == -1)
-               return -1;
-       bytes = write(fd, state->new, state->new_len);
-       close(fd);
-       return bytes;
-}
-
-static int
 dhcp6_readlease(struct interface *ifp, int validate)
 {
+       union {
+               struct dhcp6_message dhcp6;
+               uint8_t buf[UDPLEN_MAX];
+       } buf;
        struct dhcp6_state *state;
-       struct stat st;
+       ssize_t bytes;
        int fd;
-       time_t now;
-       int retval;
-       bool read_stdin, fd_opened;
+       time_t mtime, now;
 #ifdef AUTH
        uint8_t *o;
        uint16_t ol;
 #endif
 
        state = D6_STATE(ifp);
-       read_stdin = state->leasefile[0] == '\0';
-       if (read_stdin) {
+       if (state->leasefile[0] == '\0') {
                logdebugx("reading standard input");
-               fd = fileno(stdin);
-               fd_opened = false;
+               bytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
        } else {
-               logdebugx("%s: reading lease `%s'", ifp->name,state->leasefile);
-               fd = open(state->leasefile, O_RDONLY);
-               if (fd != -1 && fstat(fd, &st) == -1) {
-                       close(fd);
-                       fd = -1;
-               }
-               fd_opened = true;
+               logdebugx("%s: reading lease `%s'",
+                   ifp->name, state->leasefile);
+               bytes = dhcp_readfile(ifp->ctx, state->leasefile,
+                   buf.buf, sizeof(buf.buf));
        }
-       if (fd == -1)
-               return -1;
-       retval = -1;
-       free(state->new);
-       state->new_len = dhcp_read_lease_fd(fd, (void **)&state->new);
-       if (fd_opened)
-               close(fd);
+       if (bytes == -1)
+               goto ex;
 
-       if (ifp->ctx->options & DHCPCD_DUMPLEASE || read_stdin)
-               return 0;
+       if (ifp->ctx->options & DHCPCD_DUMPLEASE || state->leasefile[0] == '\0')
+               goto out;
 
-       if (state->new_len == 0) {
-               retval = 0;
+       if (bytes == 0)
                goto ex;
-       }
 
        /* If not validating IA's and if they have expired,
         * skip to the auth check. */
-       if (!validate) {
-               fd = 0;
+       if (!validate)
                goto auth;
-       }
 
+       if (dhcp_filemtime(ifp->ctx, state->leasefile, &mtime) == -1)
+               goto ex;
        clock_gettime(CLOCK_MONOTONIC, &state->acquired);
        if ((now = time(NULL)) == -1)
                goto ex;
-       state->acquired.tv_sec -= now - st.st_mtime;
+       state->acquired.tv_sec -= now - mtime;
 
        /* Check to see if the lease is still valid */
-       fd = dhcp6_validatelease(ifp, state->new, state->new_len, NULL,
+       fd = dhcp6_validatelease(ifp, &buf.dhcp6, bytes, NULL,
            &state->acquired);
        if (fd == -1)
                goto ex;
 
        if (state->expire != ND6_INFINITE_LIFETIME &&
-           (time_t)state->expire < now - st.st_mtime &&
+           (time_t)state->expire < now - mtime &&
            !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND))
        {
                logdebugx("%s: discarding expired lease", ifp->name);
-               retval = 0;
+               bytes = 0;
                goto ex;
        }
 
 auth:
-       retval = 0;
 #ifdef AUTH
        /* Authenticate the message */
-       o = dhcp6_findmoption(state->new, state->new_len, D6_OPTION_AUTH, &ol);
+       o = dhcp6_findmoption(&buf.dhcp6, bytes, D6_OPTION_AUTH, &ol);
        if (o) {
                if (dhcp_auth_validate(&state->auth, &ifp->options->auth,
-                   (uint8_t *)state->new, state->new_len, 6, state->new->type,
-                   o, ol) == NULL)
+                   buf.buf, bytes, 6, buf.dhcp6.type, o, ol) == NULL)
                {
                        logerr("%s: authentication failed", ifp->name);
+                       bytes = 0;
                        goto ex;
                }
                if (state->auth.token)
@@ -2705,22 +2671,32 @@ auth:
        }
 #endif
 
-       return fd;
+out:
+       free(state->new);
+       state->new = malloc(bytes);
+       if (state->new == NULL) {
+               logerr(__func__);
+               goto ex;
+       }
+
+       memcpy(state->new, buf.buf, bytes);
+       state->new_len = bytes;
+       return bytes;
 
 ex:
        dhcp6_freedrop_addrs(ifp, 0, NULL);
-       unlink(state->leasefile);
+       dhcp_unlink(ifp->ctx, state->leasefile);
        free(state->new);
        state->new = NULL;
        state->new_len = 0;
-       return retval;
+       return bytes == 0 ? 0 : -1;
 }
 
 static void
 dhcp6_startinit(struct interface *ifp)
 {
        struct dhcp6_state *state;
-       int r;
+       ssize_t r;
        uint8_t has_ta, has_non_ta;
        size_t i;
 
@@ -3259,9 +3235,13 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
                        logmessage(loglevel, "%s: expire in %"PRIu32" seconds",
                            ifp->name, state->expire);
                rt_build(ifp->ctx, AF_INET6);
-               if (!confirmed && !timedout)
-                       if (dhcp6_writelease(ifp) == -1)
-                               logerr("dhcp6_writelease: %s",state->leasefile);
+               if (!confirmed && !timedout) {
+                       logdebugx("%s: writing lease `%s'",
+                           ifp->name, state->leasefile);
+                       if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
+                           state->new, state->new_len) == -1)
+                               logerr("dhcp_writefile: %s",state->leasefile);
+               }
 #ifndef SMALL
                dhcp6_delegate_prefix(ifp);
 #endif
@@ -3688,7 +3668,7 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia)
         * replay it in my code.
         */
        static int replyn = 0;
-       char fname[PATH_MAX], tbuf[64 * 1024];
+       char fname[PATH_MAX], tbuf[UDPLEN_MAX];
        int fd;
        ssize_t tlen;
        uint8_t *si1, *si2;
@@ -3725,7 +3705,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
        struct sockaddr_in6 from;
        union {
                struct dhcp6_message dhcp6;
-               uint8_t buf[64 * 1024]; /* Maximum UDP message size */
+               uint8_t buf[UDPLEN_MAX]; /* Maximum UDP message size */
        } iovbuf;
        struct iovec iov = {
                .iov_base = iovbuf.buf, .iov_len = sizeof(iovbuf.buf),
@@ -4044,7 +4024,7 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
                                dhcp6_startrelease(ifp);
                                return;
                        }
-                       unlink(state->leasefile);
+                       dhcp_unlink(ifp->ctx, state->leasefile);
                }
                dhcp6_freedrop_addrs(ifp, drop, NULL);
                free(state->old);
index 4570946f47383300397c81705f0cc0fa52042b17..9b1b787d9ab4105338f3668f85ed931500e83ce8 100644 (file)
@@ -33,4 +33,4 @@
 
 #include <unistd.h>
 
-const char * const dhcpcd_embedded_conf[] = {
+const char dhcpcd_embedded_conf[] =
index 5443fad11a3542455bb23b09991f8274cec854fa..c1d773adedb884b10af9503cebafac9cc4d47d73 100644 (file)
@@ -35,4 +35,4 @@
 #define INITDEFINE6S   @INITDEFINE6S@
 #endif
 
-extern const char * const dhcpcd_embedded_conf[];
+extern const char dhcpcd_embedded_conf[];
index e17bebc01c21409b4ebc2baaf4c106ad0136381c..7eb8109ad3089ab77c7bbb3bb91a5bd43cdb8047 100644 (file)
@@ -357,8 +357,17 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
        eloop_event_delete(ctx->eloop, ctx->fork_fd);
        close(ctx->fork_fd);
        ctx->fork_fd = -1;
-       (void)freopen(_PATH_DEVNULL, "w", stdout);
-       (void)freopen(_PATH_DEVNULL, "w", stderr);
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP) {
+               /* Aside from Linux, we don't have access to /dev/null */
+               fclose(stdout);
+               fclose(stderr);
+       } else
+#endif
+       {
+               (void)freopen(_PATH_DEVNULL, "w", stdout);
+               (void)freopen(_PATH_DEVNULL, "w", stderr);
+       }
 #endif
 }
 
@@ -825,12 +834,27 @@ warn_iaid_conflict(struct interface *ifp, uint16_t ia_type, uint8_t *iaid)
                    ifp->name, ifn->name);
 }
 
+static void
+dhcpcd_initduid(struct dhcpcd_ctx *ctx, struct interface *ifp)
+{
+       char buf[DUID_LEN * 3];
+
+       if (ctx->duid != NULL)
+               return;
+
+       duid_init(ctx, ifp);
+       if (ctx->duid == NULL)
+               return;
+
+       loginfox("DUID %s",
+           hwaddr_ntoa(ctx->duid, ctx->duid_len, buf, sizeof(buf)));
+}
+
 void
 dhcpcd_startinterface(void *arg)
 {
        struct interface *ifp = arg;
        struct if_options *ifo = ifp->options;
-       char buf[DUID_LEN * 3];
        int carrier;
 
        if (ifo->options & DHCPCD_LINK) {
@@ -863,26 +887,21 @@ dhcpcd_startinterface(void *arg)
        if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
            !(ifo->options & DHCPCD_ANONYMOUS))
        {
+               char buf[sizeof(ifo->iaid) * 3];
 #ifdef INET6
                size_t i;
                struct if_ia *ia;
 #endif
 
-               /* Report client DUID */
-               if (ifp->ctx->duid == NULL) {
-                       if (duid_init(ifp) == 0)
-                               return;
-                       loginfox("DUID %s",
-                           hwaddr_ntoa(ifp->ctx->duid,
-                           ifp->ctx->duid_len,
-                           buf, sizeof(buf)));
-               }
+               /* Try and init DUID from the interface hardware address */
+               dhcpcd_initduid(ifp->ctx, ifp);
 
                /* Report IAIDs */
                loginfox("%s: IAID %s", ifp->name,
                    hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
                    buf, sizeof(buf)));
                warn_iaid_conflict(ifp, 0, ifo->iaid);
+
 #ifdef INET6
                for (i = 0; i < ifo->ia_len; i++) {
                        ia = &ifo->ia[i];
@@ -2251,8 +2270,16 @@ printpidfile:
        dhcpcd_setlinkrcvbuf(&ctx);
 #endif
 
+       /* Try and create DUID from the machine UUID. */
+       dhcpcd_initduid(&ctx, NULL);
+
+       /* Cache the default vendor option. */
+       if (dhcp_vendor(ctx.vendor, sizeof(ctx.vendor)) == -1)
+               logerrx("dhcp_vendor");
+
 #ifdef PRIVSEP
        if (ctx.options & DHCPCD_PRIVSEP) {
+
                /*
                 * PSF_CAP_ENTER is not set because the following functions
                 * won't work in it:
index 69d62cb5415358ad149eab8a6c060f37e10908d6..f9ad928712b047817c87168386cd30375a628a35 100644 (file)
@@ -125,6 +125,7 @@ struct passwd;
 
 struct dhcpcd_ctx {
        char pidfile[sizeof(PIDFILE) + IF_NAMESIZE + 1];
+       char vendor[256];
        int fork_fd;    /* FD for the fork init signal pipe */
        const char *cffile;
        unsigned long long options;
index d411d667253cfe95887014403bbdfba70943a9c1..012874782528076adbad8f6928aeff7dfe64d22d 100644 (file)
@@ -149,20 +149,18 @@ duid_make(void *d, const struct interface *ifp, uint16_t type)
 
 #define DUID_STRLEN DUID_LEN * 3
 static size_t
-duid_get(uint8_t **d, const struct interface *ifp)
+duid_get(struct dhcpcd_ctx *ctx, const struct interface *ifp)
 {
-       FILE *fp;
        uint8_t *data;
-       size_t len;
-       int x = 0;
+       size_t len, slen;
        char line[DUID_STRLEN];
        const struct interface *ifp2;
 
        /* If we already have a DUID then use it as it's never supposed
         * to change once we have one even if the interfaces do */
-       if ((len = read_hwaddr_aton(&data, DUID)) != 0) {
+       if ((len = dhcp_read_hwaddr_aton(ctx, &data, DUID)) != 0) {
                if (len <= DUID_LEN) {
-                       *d = data;
+                       ctx->duid = data;
                        return len;
                }
                logerrx("DUID too big (max %u): %s", DUID_LEN, DUID);
@@ -176,13 +174,18 @@ duid_get(uint8_t **d, const struct interface *ifp)
                }
        }
 
-       /* Regardless of what happens we will create a DUID to use. */
-       *d = data;
-
        /* No file? OK, lets make one based the machines UUID */
-       len = duid_make_uuid(data);
-       if (len > 0)
+       if (ifp == NULL) {
+               len = duid_make_uuid(data);
+               if (len == 0)
+                       free(data);
+               else
+                       ctx->duid = data;
                return len;
+       }
+
+       /* Regardless of what happens we will create a DUID to use. */
+       ctx->duid = data;
 
        /* No UUID? OK, lets make one based on our interface */
        if (ifp->hwlen == 0) {
@@ -202,27 +205,25 @@ duid_get(uint8_t **d, const struct interface *ifp)
                }
        }
 
-       if (!(fp = fopen(DUID, "w"))) {
-               logerr("%s", DUID);
-               return duid_make(data, ifp, DUID_LL);
-       }
        len = duid_make(data, ifp, DUID_LLT);
-       x = fprintf(fp, "%s\n", hwaddr_ntoa(data, len, line, sizeof(line)));
-       if (fclose(fp) == EOF)
-               x = -1;
-       /* Failed to write the duid? scrub it, we cannot use it */
-       if (x < 1) {
-               logerr("%s", DUID);
-               unlink(DUID);
+       hwaddr_ntoa(data, len, line, sizeof(line));
+       slen = strlen(line);
+       if (slen < sizeof(line) - 2) {
+               line[slen++] = '\n';
+               line[slen] = '\0';
+       }
+       if (dhcp_writefile(ctx, DUID, 0640, line, slen) == -1) {
+               logerr("%s: cannot write duid", __func__);
                return duid_make(data, ifp, DUID_LL);
        }
        return len;
 }
 
-size_t duid_init(const struct interface *ifp)
+size_t
+duid_init(struct dhcpcd_ctx *ctx, const struct interface *ifp)
 {
 
-       if (ifp->ctx->duid == NULL)
-               ifp->ctx->duid_len = duid_get(&ifp->ctx->duid, ifp);
-       return ifp->ctx->duid_len;
+       if (ctx->duid == NULL)
+               ctx->duid_len = duid_get(ctx, ifp);
+       return ctx->duid_len;
 }
index d9d82a61394c916a25f1e57fd517a9c17b99e505..a674bef3187ae6675341866fe445d654be9285aa 100644 (file)
@@ -35,6 +35,6 @@
 #define        DUID_UUID       4
 
 size_t duid_make(void *, const struct interface *, uint16_t);
-size_t duid_init(const struct interface *);
+size_t duid_init(struct dhcpcd_ctx *, const struct interface *);
 
 #endif
index 36b9d75db6fdd6883ffec87f9f13b25e84f60d42..81545cd86b428b59583119520743dee50644d7a3 100755 (executable)
@@ -13,7 +13,7 @@ $TOOL_SED \
        -e 's/#.*$//' \
        -e '/^$/d' \
        -e 's/^/"/g' \
-       -e 's/$/\",/g' \
+       -e 's/$/\\n\"/g' \
        -e 's/ [ ]*/ /g' \
        -e 's/  [       ]*/ /g' \
        $CONF_SMALL
@@ -22,9 +22,9 @@ $TOOL_SED \
        -e 's/#.*$//' \
        -e '/^$/d' \
        -e 's/^/"/g' \
-       -e 's/$/\",/g' \
+       -e 's/$/\\n"/g' \
        -e 's/ [ ]*/ /g' \
        -e 's/  [       ]*/ /g' \
        $CONF
 echo "#endif"
-printf "%s\n%s\n" "NULL" "};"
+printf "%s\n%s\n" '"\0";'
index 958542caad0b4931b9fc05f25b03802797359e96..5849b52edf499e656d59b28fb4f43862177f8bfc 100644 (file)
@@ -1555,7 +1555,7 @@ if_handlelink(struct dhcpcd_ctx *ctx)
 }
 
 #ifndef SYS_NMLN       /* OSX */
-#  define SYS_NMLN 256
+#  define SYS_NMLN __SYS_NAMELEN
 #endif
 #ifndef HW_MACHINE_ARCH
 #  ifdef HW_MODEL      /* OpenBSD */
@@ -1566,14 +1566,8 @@ int
 if_machinearch(char *str, size_t len)
 {
        int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
-       char march[SYS_NMLN];
-       size_t marchlen = sizeof(march);
 
-return -1;
-       if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
-           march, &marchlen, NULL, 0) != 0)
-               return -1;
-       return snprintf(str, len, ":%s", march);
+       return sysctl(mib, sizeof(mib) / sizeof(mib[0]), str, &len, NULL, 0);
 }
 
 #ifdef INET6
index cc59e5722b5e9e7692ad676548d962d026ae1ee5..c50d714ecbd056f61d4f5f073350b1639ea9ba9d 100644 (file)
@@ -211,7 +211,7 @@ if_machinearch(char *str, size_t len)
                    fscanf(fp, "%255s", buf) == 1)
                {
                        fclose(fp);
-                       return snprintf(str, len, ":%s", buf);
+                       return snprintf(str, len, "%s", buf);
                }
        }
        fclose(fp);
index 040d7bb7c6196b9e4699f559fdc051cf6bdc8a1d..4ed38a987731a3c6b4d724be45cba62020bb95b4 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <sys/param.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <arpa/inet.h>
@@ -2265,25 +2264,31 @@ finish_config(struct if_options *ifo)
  * We strip leading space and avoid comment lines, making the code that calls
  * us smaller. */
 static char *
-get_line(char ** __restrict buf, size_t * __restrict buflen,
-    FILE * __restrict fp)
+get_line(char ** __restrict buf, ssize_t * __restrict buflen)
 {
        char *p, *c;
-       ssize_t bytes;
-       int quoted;
+       bool quoted;
 
        do {
-               bytes = getline(buf, buflen, fp);
-               if (bytes == -1)
-                       return NULL;
-               for (p = *buf; *p == ' ' || *p == '\t'; p++)
+               p = *buf;
+               c = memchr(*buf, '\n', *buflen);
+               if (c == NULL) {
+                       c = memchr(*buf, '\0', *buflen);
+                       if (c == NULL)
+                               return NULL;
+                       *buflen = c - *buf;
+                       *buf = NULL;
+               } else {
+                       *c++ = '\0';
+                       *buflen -= c - *buf;
+                       *buf = c;
+               }
+               for (; *p == ' ' || *p == '\t'; p++)
                        ;
        } while (*p == '\0' || *p == '\n' || *p == '#' || *p == ';');
-       if ((*buf)[--bytes] == '\n')
-               (*buf)[bytes] = '\0';
 
        /* Strip embedded comments unless in a quoted string or escaped */
-       quoted = 0;
+       quoted = false;
        for (c = p; *c != '\0'; c++) {
                if (*c == '\\') {
                        c++; /* escaped */
@@ -2334,16 +2339,11 @@ read_config(struct dhcpcd_ctx *ctx,
     const char *ifname, const char *ssid, const char *profile)
 {
        struct if_options *ifo;
-       FILE *fp;
-       struct stat sb;
-       char *line, *buf, *option, *p;
-       size_t buflen;
+       char buf[UDPLEN_MAX], *bp; /* 64k max config file size */
+       char *line, *option, *p;
+       ssize_t buflen;
        ssize_t vlen;
        int skip, have_profile, new_block, had_block;
-#ifndef EMBEDDED_CONFIG
-       const char * const *e;
-       size_t ol;
-#endif
 #if !defined(INET) || !defined(INET6)
        size_t i;
        struct dhcp_opt *opt;
@@ -2366,12 +2366,9 @@ read_config(struct dhcpcd_ctx *ctx,
        ifo->options |= DHCPCD_DHCP6;
 #endif
 
-       vlen = dhcp_vendor((char *)ifo->vendorclassid + 1,
-                   sizeof(ifo->vendorclassid) - 1);
-       ifo->vendorclassid[0] = (uint8_t)(vlen == -1 ? 0 : vlen);
-
-       buf = NULL;
-       buflen = 0;
+       vlen = strlcpy((char *)ifo->vendorclassid + 1, ctx->vendor,
+           sizeof(ifo->vendorclassid) - 1);
+       ifo->vendorclassid[0] = (uint8_t)(vlen > 255 ? 0 : vlen);
 
        /* Reset route order */
        ctx->rt_order = 0;
@@ -2407,38 +2404,26 @@ read_config(struct dhcpcd_ctx *ctx,
 
                /* Now load our embedded config */
 #ifdef EMBEDDED_CONFIG
-               fp = fopen(EMBEDDED_CONFIG, "r");
-               if (fp == NULL)
-                       logerr("%s: fopen `%s'", __func__, EMBEDDED_CONFIG);
-
-               while (fp && (line = get_line(&buf, &buflen, fp))) {
+               buflen = dhcp_readfile(ctx, EMBEDDED_CONFIG, buf, sizeof(buf));
+               if (buflen == -1) {
+                       logerr("%s: %s", __func__, EMBEDDED_CONFIG);
+                       return ifo;
+               }
+               if (buf[buflen] != '\0') {
+                       if (buflen < sizeof(buf) - 1)
+                               bulen++;
+                       buf[buflen] = '\0';
+               }
 #else
-               buflen = 80;
-               buf = malloc(buflen);
-               if (buf == NULL) {
-                       logerr(__func__);
-                       free_options(ctx, ifo);
-                       return NULL;
+               buflen = strlcpy(buf, dhcpcd_embedded_conf, sizeof(buf));
+               if ((size_t)buflen >= sizeof(buf)) {
+                       logerrx("%s: embedded config too big", __func__);
+                       return ifo;
                }
-               ldop = edop = NULL;
-               for (e = dhcpcd_embedded_conf; *e; e++) {
-                       ol = strlen(*e) + 1;
-                       if (ol > buflen) {
-                               char *nbuf;
-
-                               buflen = ol;
-                               nbuf = realloc(buf, buflen);
-                               if (nbuf == NULL) {
-                                       logerr(__func__);
-                                       free(buf);
-                                       free_options(ctx, ifo);
-                                       return NULL;
-                               }
-                               buf = nbuf;
-                       }
-                       memcpy(buf, *e, ol);
-                       line = buf;
+               /* Our embedded config is NULL terminated */
 #endif
+               bp = buf;
+               while ((line = get_line(&bp, &buflen)) != NULL) {
                        option = strsep(&line, " \t");
                        if (line)
                                line = strskipwhite(line);
@@ -2452,13 +2437,8 @@ read_config(struct dhcpcd_ctx *ctx,
                        }
                        parse_config_line(ctx, NULL, ifo, option, line,
                            &ldop, &edop);
-
                }
 
-#ifdef EMBEDDED_CONFIG
-               if (fp)
-                       fclose(fp);
-#endif
 #ifdef INET
                ctx->dhcp_opts = ifo->dhcp_override;
                ctx->dhcp_opts_len = ifo->dhcp_override_len;
@@ -2503,26 +2483,25 @@ read_config(struct dhcpcd_ctx *ctx,
        }
 
        /* Parse our options file */
-#ifdef PRIVSEP
-       if (ctx->options & DHCPCD_PRIVSEP &&
-           ps_root_copychroot(ctx, ctx->cffile) == -1)
-               logwarn("%s: ps_root_copychroot `%s'", __func__, ctx->cffile);
-#endif
-       fp = fopen(ctx->cffile, "r");
-       if (fp == NULL) {
+       buflen = dhcp_readfile(ctx, ctx->cffile, buf, sizeof(buf));
+       if (buflen == -1) {
                /* dhcpcd can continue without it, but no DNS options
                 * would be requested ... */
-               logwarn("%s: fopen `%s'", __func__, ctx->cffile);
-               free(buf);
+               logerr("%s: %s", __func__, ctx->cffile);
                return ifo;
        }
-       if (stat(ctx->cffile, &sb) == 0)
-               ifo->mtime = sb.st_mtime;
+       if (buf[buflen] != '\0') {
+               if ((size_t)buflen < sizeof(buf) - 1)
+                       buflen++;
+               buf[buflen] = '\0';
+       }
+       dhcp_filemtime(ctx, ctx->cffile, &ifo->mtime);
 
        ldop = edop = NULL;
        skip = have_profile = new_block = 0;
        had_block = ifname == NULL ? 1 : 0;
-       while ((line = get_line(&buf, &buflen, fp))) {
+       bp = buf;
+       while ((line = get_line(&bp, &buflen)) != NULL) {
                option = strsep(&line, " \t");
                if (line)
                        line = strskipwhite(line);
@@ -2596,10 +2575,9 @@ read_config(struct dhcpcd_ctx *ctx,
                        continue;
                if (skip)
                        continue;
+
                parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);
        }
-       fclose(fp);
-       free(buf);
 
        if (profile && !have_profile) {
                free_options(ctx, ifo);
index cf93c2a0a58ce24d62bb8e9ae7ff6f98e40e39ab..6f38b43d09548fbec26e48c966cfc53a264303f2 100644 (file)
 #define DHCPCD_ONESHOT                 (1ULL << 60)
 #define DHCPCD_INACTIVE                        (1ULL << 61)
 #define        DHCPCD_SLAACTEMP                (1ULL << 62)
+#define DHCPCD_PRIVSEPROOT             (1ULL << 63)
 
 #define DHCPCD_NODROP  (DHCPCD_EXITING | DHCPCD_PERSISTENT)
 
index f58b3028fec05d8455bdaee03c93ba996a3892c3..73f8b91524775435b67ba9dccde120f591644ef5 100644 (file)
--- a/src/if.h
+++ b/src/if.h
@@ -95,6 +95,8 @@ typedef unsigned long         ioctl_request_t;
 #define        FRAMEHDRLEN_MAX                 14      /* only ethernet support */
 #define        FRAMELEN_MAX                    (FRAMEHDRLEN_MAX + 9216)
 
+#define UDPLEN_MAX                     64 * 1024
+
 /* Work out if we have a private address or not
  * 10/8
  * 172.16/12
index 18d890ef1d7f6227eb85c3092c66c0137510e059..4299425053b3ea6cb57067eac4d39e55c6613b12 100644 (file)
@@ -147,18 +147,17 @@ ipv6_init(struct dhcpcd_ctx *ctx)
 static ssize_t
 ipv6_readsecret(struct dhcpcd_ctx *ctx)
 {
-       FILE *fp;
        char line[1024];
        unsigned char *p;
        size_t len;
        uint32_t r;
-       int x;
 
-       if ((ctx->secret_len = read_hwaddr_aton(&ctx->secret, SECRET)) != 0)
+       ctx->secret_len = dhcp_read_hwaddr_aton(ctx, &ctx->secret, SECRET);
+       if (ctx->secret_len != 0)
                return (ssize_t)ctx->secret_len;
 
        if (errno != ENOENT)
-               logerr("%s: %s", __func__, SECRET);
+               logerr("%s: cannot read secret", __func__);
 
        /* Chaining arc4random should be good enough.
         * RFC7217 section 5.1 states the key SHOULD be at least 128 bits.
@@ -178,27 +177,18 @@ ipv6_readsecret(struct dhcpcd_ctx *ctx)
                p += sizeof(r);
        }
 
-       /* Ensure that only the dhcpcd user can read the secret.
-        * Write permission is also denied as changing it would remove
-        * it's stability. */
-       if ((fp = fopen(SECRET, "w")) == NULL ||
-           chmod(SECRET, S_IRUSR) == -1)
-               goto eexit;
-       x = fprintf(fp, "%s\n",
-           hwaddr_ntoa(ctx->secret, ctx->secret_len, line, sizeof(line)));
-       if (fclose(fp) == EOF)
-               x = -1;
-       fp = NULL;
-       if (x > 0)
-               return (ssize_t)ctx->secret_len;
-
-eexit:
-       logerr("%s: %s", __func__, SECRET);
-       if (fp != NULL)
-               fclose(fp);
-       unlink(SECRET);
-       ctx->secret_len = 0;
-       return -1;
+       hwaddr_ntoa(ctx->secret, ctx->secret_len, line, sizeof(line));
+       len = strlen(line);
+       if (len < sizeof(line) - 2) {
+               line[len++] = '\n';
+               line[len] = '\0';
+       }
+       if (dhcp_writefile(ctx, SECRET, S_IRUSR, line, len) == -1) {
+               logerr("%s: cannot write secret", __func__);
+               ctx->secret_len = 0;
+               return -1;
+       }
+       return (ssize_t)ctx->secret_len;
 }
 
 /* http://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xhtml
index 170b529d37b4f5a8569a4eb04b168a1b18cce733..877be37972f8b5bbbd077dd087da29ec1e7caf25 100644 (file)
@@ -104,7 +104,6 @@ logprintdate(FILE *stream)
                return -1;
 
        now = tv.tv_sec;
-       tzset();
        if (localtime_r(&now, &tmnow) == NULL)
                return -1;
        if (strftime(buf, sizeof(buf), "%b %d %T ", &tmnow) == 0)
@@ -366,6 +365,9 @@ logopen(const char *path)
 {
        struct logctx *ctx = &_logctx;
 
+       /* Cache timezone */
+       tzset();
+
        if (path == NULL) {
                int opts = 0;
 
index fd76576cc305253622562a67951f69516610d702..8326425d03ae973425e137c51f63644434844c6d 100644 (file)
@@ -91,7 +91,7 @@ ps_bpf_recvbpf(void *arg)
 
 #ifdef ARP
 static ssize_t
-ps_bpf_arp_addr(uint8_t cmd, struct ps_process *psp, struct msghdr *msg)
+ps_bpf_arp_addr(uint16_t cmd, struct ps_process *psp, struct msghdr *msg)
 {
        struct interface *ifp = &psp->psp_ifp;
        struct iovec *iov = msg->msg_iov;
@@ -197,7 +197,7 @@ ps_bpf_signal_bpfcb(int sig, void *arg)
 ssize_t
 ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
 {
-       uint8_t cmd;
+       uint16_t cmd;
        struct ps_process *psp;
        pid_t start;
        struct iovec *iov = msg->msg_iov;
@@ -205,7 +205,7 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
        struct ipv4_state *istate;
        unsigned int flags = PSF_DROPPRIVS | PSF_CAP_ENTER;
 
-       cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
+       cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
        psp = ps_findprocess(ctx, &psm->ps_id);
 
 #ifdef PRIVSEP_DEBUG
@@ -261,7 +261,7 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
                 * Pledge is currently useless for BPF ARP because we cannot
                 * change the filter:
                 * http://openbsd-archive.7691.n7.nabble.com/ \
-                *        pledge-bpf-32bit-arch-unbreak-td299901.html
+                *        pledge-bpf-32bit-arch-unbreak-td299901.html
                 */
                break;
 #endif
@@ -321,7 +321,7 @@ ps_bpf_dispatch(struct dhcpcd_ctx *ctx,
 }
 
 static ssize_t
-ps_bpf_send(const struct interface *ifp, uint8_t cmd,
+ps_bpf_send(const struct interface *ifp, uint16_t cmd,
     const void *data, size_t len)
 {
        struct dhcpcd_ctx *ctx = ifp->ctx;
index f466156ac0ddf56283f44027ba138de12f497e8b..3aa2a73d656cca031cb97b9b2fed12056bfcd725 100644 (file)
@@ -114,7 +114,7 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg)
 }
 
 static ssize_t
-ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint8_t domain, unsigned long request,
+ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint16_t domain, unsigned long request,
     void *data, size_t len)
 {
 
@@ -126,7 +126,7 @@ ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint8_t domain, unsigned long request,
 
 ssize_t
 ps_root_ioctllink(struct dhcpcd_ctx *ctx, unsigned long request,
-    void *data,size_t len)
+    void *data, size_t len)
 {
 
        return ps_root_ioctldom(ctx, PS_IOCTLLINK, request, data, len);
index cb8632ecd10069ed1e9ccff1d7c591dee345a855..70074160b1b02bea7b5aed1d237428953fa64a19 100644 (file)
@@ -498,12 +498,12 @@ ssize_t
 ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
     __unused struct msghdr *msg)
 {
-       uint8_t cmd;
+       uint16_t cmd;
        struct ps_process *psp;
        int (*start_func)(void *);
        pid_t start;
 
-       cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
+       cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
        psp = ps_findprocess(ctx, &psm->ps_id);
 
 #ifdef PRIVSEP_DEBUG
@@ -570,7 +570,7 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
 
 #ifdef INET
 static ssize_t
-ps_inet_in_docmd(struct ipv4_addr *ia, uint8_t cmd, const struct msghdr *msg)
+ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg)
 {
        assert(ia != NULL);
        struct dhcpcd_ctx *ctx = ia->iface->ctx;
@@ -614,7 +614,7 @@ ps_inet_sendbootp(struct ipv4_addr *ia, const struct msghdr *msg)
 #ifdef INET6
 #ifdef __sun
 static ssize_t
-ps_inet_ifp_docmd(struct interface *ifp, uint8_t cmd, const struct msghdr *msg)
+ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg)
 {
        struct dhcpcd_ctx *ctx = ifp->ctx;
        struct ps_msghdr psm = {
@@ -659,7 +659,7 @@ ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
 
 #ifdef DHCP6
 static ssize_t
-ps_inet_in6_docmd(struct ipv6_addr *ia, uint8_t cmd, const struct msghdr *msg)
+ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg)
 {
        struct dhcpcd_ctx *ctx = ia->iface->ctx;
        struct ps_msghdr psm = {
index 9584af8400696e3ae132ebf346902f3a4548e8ad..0bcaf5007645cdff78456506326e6eecc4d02743 100644 (file)
@@ -217,124 +217,35 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
        return status;
 }
 
-#if defined(__linux__) && !defined(st_mtimespec)
-#define        st_atimespec  st_atim
-#define        st_mtimespec  st_mtim
-#endif
-ssize_t
-ps_root_docopychroot(struct dhcpcd_ctx *ctx, const char *file)
-{
-
-       char path[PATH_MAX], buf[BUFSIZ], *slash;
-       struct stat from_sb, to_sb;
-       int from_fd, to_fd;
-       ssize_t rcount, wcount, total;
-#if defined(BSD) || defined(__linux__)
-       struct timespec ts[2];
-#else
-       struct timeval tv[2];
-#endif
-
-       if (snprintf(path, sizeof(path), "%s/%s", ctx->ps_chroot, file) == -1)
-               return -1;
-       if (stat(file, &from_sb) == -1)
-               return -1;
-       if (stat(path, &to_sb) == 0) {
-#if defined(BSD) || defined(__linux__)
-               if (from_sb.st_mtimespec.tv_sec == to_sb.st_mtimespec.tv_sec &&
-                   from_sb.st_mtimespec.tv_nsec == to_sb.st_mtimespec.tv_nsec)
-                       return 0;
-#else
-               if (from_sb.st_mtime == to_sb.st_mtime)
-                       return 0;
-#endif
-       } else {
-               /* Ensure directory exists */
-               slash = strrchr(path, '/');
-               if (slash != NULL) {
-                       *slash = '\0';
-                       ps_mkdir(path);
-                       *slash = '/';
-               }
-       }
-
-       if (unlink(path) == -1 && errno != ENOENT)
-               return -1;
-       if ((from_fd = open(file, O_RDONLY, 0)) == -1)
-               return -1;
-       if ((to_fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0555)) == -1)
-               return -1;
-
-       total = 0;
-       while ((rcount = read(from_fd, buf, sizeof(buf))) > 0) {
-               wcount = write(to_fd, buf, (size_t)rcount);
-               if (wcount != rcount) {
-                       total = -1;
-                       break;
-               }
-               total += wcount;
-       }
-
-#if defined(BSD) || defined(__linux__)
-       ts[0] = from_sb.st_atimespec;
-       ts[1] = from_sb.st_mtimespec;
-       if (futimens(to_fd, ts) == -1)
-               total = -1;
-#else
-       tv[0].tv_sec = from_sb.st_atime;
-       tv[0].tv_usec = 0;
-       tv[1].tv_sec = from_sb.st_mtime;
-       tv[1].tv_usec = 0;
-       if (futimes(to_fd, tv) == -1)
-               total = -1;
-#endif
-       close(from_fd);
-       close(to_fd);
-
-       return total;
-}
-
 static ssize_t
-ps_root_dofileop(struct dhcpcd_ctx *ctx, void *data, size_t len, uint8_t op)
+ps_root_dowritefile(mode_t mode, void *data, size_t len)
 {
-       char *path = data;
-       size_t plen;
-
-       if (len < sizeof(plen)) {
-               errno = EINVAL;
-               return -1;
-       }
+       char *file = data, *nc;
 
-       memcpy(&plen, path, sizeof(plen));
-       path += sizeof(plen);
-       if (sizeof(plen) + plen > len) {
+       nc = memchr(file, '\0', len);
+       if (nc == NULL) {
                errno = EINVAL;
                return -1;
        }
-
-       switch(op) {
-       case PS_COPY:
-               return ps_root_docopychroot(ctx, path);
-       case PS_UNLINK:
-               return (ssize_t)unlink(path);
-       default:
-               errno = ENOTSUP;
-               return -1;
-       }
+       nc++;
+       return writefile(file, mode, nc, len - (nc - file));
 }
 
 static ssize_t
 ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 {
        struct dhcpcd_ctx *ctx = arg;
-       uint8_t cmd;
+       uint16_t cmd;
        struct ps_process *psp;
        struct iovec *iov = msg->msg_iov;
        void *data = iov->iov_base;
        size_t len = iov->iov_len;
+       uint8_t buf[PS_BUFLEN];
+       time_t mtime;
        ssize_t err;
+       bool retdata = false;
 
-       cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP | PS_DELETE));
+       cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP | PS_DELETE));
        psp = ps_findprocess(ctx, &psm->ps_id);
 
 #ifdef PRIVSEP_DEBUG
@@ -388,20 +299,40 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
        switch (psm->ps_cmd) {
        case PS_IOCTL:
                err = ps_root_doioctl(psm->ps_flags, data, len);
+               retdata = true;
                break;
        case PS_SCRIPT:
                err = ps_root_run_script(ctx, data, len);
                break;
-       case PS_COPY:   /* FALLTHROUGH */
        case PS_UNLINK:
-               err = ps_root_dofileop(ctx, data, len, psm->ps_cmd);
+               err = unlink(data);
+               break;
+       case PS_READFILE:
+               errno = 0;
+               err = readfile(data, buf, sizeof(buf));
+               if (err != -1) {
+                       data = buf;
+                       len = (size_t)err;
+                       retdata = true;
+               }
+               break;
+       case PS_WRITEFILE:
+               err = ps_root_dowritefile(psm->ps_flags, data, len);
+               break;
+       case PS_FILEMTIME:
+               err = filemtime(data, &mtime);
+               if (err != -1) {
+                       data = &mtime;
+                       len = sizeof(mtime);
+                       retdata = true;
+               }
                break;
        default:
                err = ps_root_os(psm, msg);
                break;
        }
 
-       return ps_root_writeerror(ctx, err, data, len);
+       return ps_root_writeerror(ctx, err, data, retdata ? len : 0);
 }
 
 /* Receive from state engine, do an action. */
@@ -428,6 +359,7 @@ ps_root_startcb(void *arg)
                    ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
                    ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
        ctx->ps_root_pid = getpid();
+       ctx->options |= DHCPCD_PRIVSEPROOT;
        return 0;
 }
 
@@ -574,38 +506,53 @@ ps_root_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data,
        return ps_root_readerror(ctx, data, len);
 }
 
-static ssize_t
-ps_root_fileop(struct dhcpcd_ctx *ctx, const char *path, uint8_t op)
+ssize_t
+ps_root_unlink(struct dhcpcd_ctx *ctx, const char *file)
 {
-       char buf[PATH_MAX], *p = buf;
-       size_t plen = strlen(path) + 1;
-       size_t len = sizeof(plen) + plen;
-
-       if (len > sizeof(buf)) {
-               errno = ENOBUFS;
-               return -1;
-       }
-
-       memcpy(p, &plen, sizeof(plen));
-       p += sizeof(plen);
-       memcpy(p, path, plen);
 
-       if (ps_sendcmd(ctx, ctx->ps_root_fd, op, 0, buf, len) == -1)
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_UNLINK, 0,
+           file, strlen(file) + 1) == -1)
                return -1;
        return ps_root_readerror(ctx, NULL, 0);
 }
 
+ssize_t
+ps_root_readfile(struct dhcpcd_ctx *ctx, const char *file,
+    void *data, size_t len)
+{
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_READFILE, 0,
+           file, strlen(file) + 1) == -1)
+               return -1;
+       return ps_root_readerror(ctx, data, len);
+}
 
 ssize_t
-ps_root_copychroot(struct dhcpcd_ctx *ctx, const char *path)
+ps_root_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode,
+    const void *data, size_t len)
 {
+       char buf[PS_BUFLEN];
+       size_t flen;
 
-       return ps_root_fileop(ctx, path, PS_COPY);
+       flen = strlcpy(buf, file, sizeof(buf));
+       flen += 1;
+       if (flen > sizeof(buf) || flen + len > sizeof(buf)) {
+               errno = ENOBUFS;
+               return -1;
+       }
+       memcpy(buf + flen, data, len);
+
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_WRITEFILE, mode,
+           buf, flen + len) == -1)
+               return -1;
+       return ps_root_readerror(ctx, NULL, 0);
 }
 
-ssize_t
-ps_root_unlink(struct dhcpcd_ctx *ctx, const char *path)
+int
+ps_root_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
 {
 
-       return ps_root_fileop(ctx, path, PS_UNLINK);
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_FILEMTIME, 0,
+           file, strlen(file) + 1) == -1)
+               return -1;
+       return ps_root_readerror(ctx, time, sizeof(*time));
 }
index 7f8bdc6544995d54fe5e1887d3d6aac0d230e1bc..a5fdb2520b0d481d01f3ac416cb07a9c573551d7 100644 (file)
@@ -35,10 +35,12 @@ pid_t ps_root_start(struct dhcpcd_ctx *ctx);
 int ps_root_stop(struct dhcpcd_ctx *ctx);
 
 ssize_t ps_root_readerror(struct dhcpcd_ctx *, void *, size_t);
-ssize_t ps_root_docopychroot(struct dhcpcd_ctx *, const char *);
-ssize_t ps_root_copychroot(struct dhcpcd_ctx *, const char *);
 ssize_t ps_root_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
 ssize_t ps_root_unlink(struct dhcpcd_ctx *, const char *);
+int ps_root_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
+ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
+ssize_t ps_root_writefile(struct dhcpcd_ctx *, const char *, mode_t,
+    const void *, size_t);
 ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *);
 #if defined(BSD) || defined(__sun)
 ssize_t ps_root_route(struct dhcpcd_ctx *, void *, size_t);
index ac503a53e231373aadff116aefcb495a08bdc9aa..f34100c0a1e11186de0a51f827820fd6a70665ac 100644 (file)
 #include <util.h>
 #endif
 
-int
-ps_mkdir(char *path)
-{
-       char *slash;
-       bool done;
-
-       slash = path;
-       for (;;) {
-               slash += strspn(slash, "/");
-               slash += strcspn(slash, "/");
-               done = (*slash == '\0');
-               *slash = '\0';
-               if (mkdir(path, 0755) == -1 && errno != EEXIST)
-                       return -1;
-               if (done)
-                       break;
-               *slash = '/';
-       }
-       return 0;
-}
-
 int
 ps_init(struct dhcpcd_ctx *ctx)
 {
-       char path[PATH_MAX];
        struct passwd *pw;
 
        errno = 0;
@@ -120,9 +98,7 @@ ps_init(struct dhcpcd_ctx *ctx)
                ctx->ps_chroot = pw->pw_dir;
 
        /* If we pickup the _dhcp user refuse the default directory */
-       if (*ctx->ps_chroot != '/' ||
-           strcmp(ctx->ps_chroot, "/var/empty") == 0)
-       {
+       if (*ctx->ps_chroot != '/') {
                ctx->options &= ~DHCPCD_PRIVSEP;
                logerrx("refusing chroot: %s: %s",
                    PRIVSEP_USER, ctx->ps_chroot);
@@ -130,17 +106,6 @@ ps_init(struct dhcpcd_ctx *ctx)
                return -1;
        }
 
-       /* Create the database directory. */
-       if (snprintf(path, sizeof(path), "%s%s", ctx->ps_chroot, DBDIR) == -1 ||
-           ps_mkdir(path) == -1 ||
-           chown(path, pw->pw_uid, pw->pw_gid) == -1 ||
-           chmod(path, 0755) == -1)
-               logerr("%s: %s", __func__, path);
-
-       /* Ensure we have a localtime to correctly format dates. */
-       if (ps_root_docopychroot(ctx, "/etc/localtime") == -1 && errno!=ENOENT)
-               logerr("%s: %s", __func__, "/etc/localtime");
-
        ctx->options |= DHCPCD_PRIVSEP;
        return 0;
 }
@@ -152,7 +117,6 @@ ps_dropprivs(struct dhcpcd_ctx *ctx, unsigned int flags)
 
        if (!(ctx->options & DHCPCD_FORKED))
                logdebugx("chrooting to `%s'", ctx->ps_chroot);
-
        if (chroot(ctx->ps_chroot) == -1)
                logerr("%s: chroot `%s'", __func__, ctx->ps_chroot);
        if (chdir("/") == -1)
@@ -184,9 +148,8 @@ ps_dropprivs(struct dhcpcd_ctx *ctx, unsigned int flags)
                if (ctx->options & DHCPCD_UNPRIV)
                        promises = "stdio dns bpf";
                else
-                       /* SIOCGIFGROUP requries inet
-                        * lease files and foo require rpath, wpath and cpath */
-                       promises = "stdio dns inet route rpath wpath cpath";
+                       /* SIOCGIFGROUP requires inet */
+                       promises = "stdio dns inet route";
                 if (pledge(promises, NULL) == -1) {
                         logerr("%s: pledge", __func__);
                         return -1;
@@ -568,7 +531,7 @@ ps_sendpsmdata(struct dhcpcd_ctx *ctx, int fd,
 
 
 ssize_t
-ps_sendmsg(struct dhcpcd_ctx *ctx, int fd, uint8_t cmd, unsigned long flags,
+ps_sendmsg(struct dhcpcd_ctx *ctx, int fd, uint16_t cmd, unsigned long flags,
     const struct msghdr *msg)
 {
        assert(msg->msg_iovlen == 1);
@@ -610,7 +573,7 @@ ps_sendmsg(struct dhcpcd_ctx *ctx, int fd, uint8_t cmd, unsigned long flags,
 }
 
 ssize_t
-ps_sendcmd(struct dhcpcd_ctx *ctx, int fd, uint8_t cmd, unsigned long flags,
+ps_sendcmd(struct dhcpcd_ctx *ctx, int fd, uint16_t cmd, unsigned long flags,
     const void *data, size_t len)
 {
        struct ps_msghdr psm = {
@@ -628,7 +591,7 @@ ps_sendcmd(struct dhcpcd_ctx *ctx, int fd, uint8_t cmd, unsigned long flags,
 }
 
 static ssize_t
-ps_sendcmdmsg(int fd, uint8_t cmd, const struct msghdr *msg)
+ps_sendcmdmsg(int fd, uint16_t cmd, const struct msghdr *msg)
 {
        struct ps_msghdr psm = { .ps_cmd = cmd };
        uint8_t data[PS_BUFLEN], *p = data;
@@ -671,7 +634,7 @@ nobufs:
 }
 
 ssize_t
-ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, uint8_t cmd, int wfd)
+ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, uint16_t cmd, int wfd)
 {
        struct sockaddr_storage ss = { .ss_family = AF_UNSPEC };
        uint8_t controlbuf[sizeof(struct sockaddr_storage)] = { 0 };
index d64210cd43cb54b48ef6a61b5dc8160f10e50946..6fdbfdc8b03779e7c227b10210c8e74833f4ee44 100644 (file)
 #define        PSF_CAP_ENTER           0x02
 #define        PSF_PLEDGE              0x04
 
-/* Commands */
-#define        PS_BOOTP                0x01
-#define        PS_ND                   0x02
-#define        PS_DHCP6                0x03
-#define        PS_BPF_BOOTP            0x04
-#define        PS_BPF_ARP              0x05
-#define        PS_BPF_ARP_ADDR         0x06
-
-#define        PS_IOCTL                0x10
-#define        PS_ROUTE                0x11    /* Also used for NETLINK */
-#define        PS_SCRIPT               0x12
-#define        PS_UNLINK               0x13
-#define        PS_COPY                 0x14
+/* Protocols */
+#define        PS_BOOTP                0x0001
+#define        PS_ND                   0x0002
+#define        PS_DHCP6                0x0003
+#define        PS_BPF_BOOTP            0x0004
+#define        PS_BPF_ARP              0x0005
+#define        PS_BPF_ARP_ADDR         0x0006
+
+/* Generic commands */
+#define        PS_IOCTL                0x0010
+#define        PS_ROUTE                0x0011  /* Also used for NETLINK */
+#define        PS_SCRIPT               0x0012
+#define        PS_UNLINK               0x0013
+#define        PS_READFILE             0x0014
+#define        PS_WRITEFILE            0x0015
+#define        PS_FILEMTIME            0x0016
 
 /* BSD Commands */
-#define        PS_IOCTLLINK            0x15
-#define        PS_IOCTL6               0x16
-#define        PS_IOCTLINDIRECT        0x17
-#define        PS_IP6FORWARDING        0x18
+#define        PS_IOCTLLINK            0x0101
+#define        PS_IOCTL6               0x0102
+#define        PS_IOCTLINDIRECT        0x0103
+#define        PS_IP6FORWARDING        0x0104
 
 /* Linux commands */
-#define        PS_WRITEPATHUINT        0x19
+#define        PS_WRITEPATHUINT        0x0201
 
-#define        PS_DELETE               0x20
-#define        PS_START                0x40
-#define        PS_STOP                 0x80
+/* Process commands */
+#define        PS_DELETE               0x2000
+#define        PS_START                0x4000
+#define        PS_STOP                 0x8000
 
 /* Max INET message size + meta data for IPC */
 #define        PS_BUFLEN               ((64 * 1024) +                  \
@@ -96,13 +100,13 @@ struct ps_addr {
 struct ps_id {
        struct ps_addr psi_addr;
        unsigned int psi_ifindex;
-       uint8_t psi_cmd;
-       uint8_t psi_pad[3];
+       uint16_t psi_cmd;
+       uint8_t psi_pad[2];
 };
 
 struct ps_msghdr {
-       uint8_t ps_cmd;
-       uint8_t ps_pad[sizeof(unsigned long) - 1];
+       uint16_t ps_cmd;
+       uint8_t ps_pad[sizeof(unsigned long) - sizeof(uint16_t)];
        unsigned long ps_flags;
        struct ps_id ps_id;
        socklen_t ps_namelen;
@@ -141,7 +145,6 @@ TAILQ_HEAD(ps_process_head, ps_process);
 #include "privsep-bpf.h"
 #endif
 
-int ps_mkdir(char *);
 int ps_init(struct dhcpcd_ctx *);
 int ps_dropprivs(struct dhcpcd_ctx *, unsigned int);
 int ps_start(struct dhcpcd_ctx *);
@@ -152,11 +155,11 @@ ssize_t ps_sendpsmmsg(struct dhcpcd_ctx *, int,
     struct ps_msghdr *, const struct msghdr *);
 ssize_t ps_sendpsmdata(struct dhcpcd_ctx *, int,
     struct ps_msghdr *, const void *, size_t);
-ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint8_t, unsigned long,
+ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
     const struct msghdr *);
-ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint8_t, unsigned long,
+ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
     const void *data, size_t len);
-ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, uint8_t, int);
+ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, uint16_t, int);
 ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int,
     ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *), void *);