Permalink
Browse files

Import dhcpcd-6.11.4 with the following changes:

  *  Fixed octal and hex string parsing in options.
  *  Several statically sized buffers have been removed and replaced
     with dynamically sized ones where we have no real idea of what
     the size will be.
  *  Reverse IPv4 route removal order.
  *  Added --small configure directive to reduce binary size
  *  Allow DHCPv6, IPv4lL and authentication to be compiled out
  *  Add support for ifa_addrflags in getifaddrs(3)
  *  Add support for ifam_addrflags and ifam_pid from route(4)
  *  If T1 or T2 are not set in DHCPv6 messages, use a default from the
     lowest pltime instead of the expiration time.
  *  Validate lease before moving to REQUEST when both ends use
     rapid commit.
  *  If lease validation fails, don't restart the DISCOVER phase if
     we're already in it.
  • Loading branch information...
1 parent 0872399 commit 42f3e79da2a859b886a0ae511bd2a2e81c4ace46 roy committed Oct 7, 2016
@@ -27,7 +27,11 @@
#include <sys/param.h>
#include <sys/time.h>
+#ifdef __sun
+#include <sys/sysmacros.h>
+#endif
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -53,6 +57,9 @@
# define _PATH_DEVNULL "/dev/null"
#endif
+/* Most route(4) messages are less than 256 bytes. */
+#define IOVEC_BUFSIZ 256
+
#if USE_LOGFILE
void
logger_open(struct dhcpcd_ctx *ctx)
@@ -374,3 +381,51 @@ read_hwaddr_aton(uint8_t **data, const char *path)
fclose(fp);
return len;
}
+
+ssize_t
+recvmsg_realloc(int fd, struct msghdr *msg, int flags)
+{
+ struct iovec *iov;
+ ssize_t slen;
+ size_t len;
+ void *n;
+
+ assert(msg != NULL);
+ assert(msg->msg_iov != NULL && msg->msg_iovlen > 0);
+ assert((flags & (MSG_PEEK | MSG_TRUNC)) == 0);
+
+ /* Assume we are reallocing the last iovec. */
+ iov = &msg->msg_iov[msg->msg_iovlen - 1];
+
+ for (;;) {
+ /* Passing MSG_TRUNC should return the actual size needed. */
+ slen = recvmsg(fd, msg, flags | MSG_PEEK | MSG_TRUNC);
+ if (slen == -1)
+ return -1;
+ if (!(msg->msg_flags & MSG_TRUNC))
+ break;
+
+ len = (size_t)slen;
+
+ /* Some kernels return the size of the receive buffer
+ * on truncation, not the actual size needed.
+ * So grow the buffer and try again. */
+ if (iov->iov_len == len)
+ len++;
+ else if (iov->iov_len > len)
+ break;
+ len = roundup(len, IOVEC_BUFSIZ);
+ if ((n = realloc(iov->iov_base, len)) == NULL)
+ return -1;
+ iov->iov_base = n;
+ iov->iov_len = len;
+ }
+
+ slen = recvmsg(fd, msg, flags);
+ if (slen != -1 && msg->msg_flags & MSG_TRUNC) {
+ /* This should not be possible ... */
+ errno = ENOBUFS;
+ return -1;
+ }
+ return slen;
+}
@@ -165,6 +165,10 @@ int get_monotonic(struct timespec *);
* However, this results in a ugly output on the command line
* and relies on syslogd(8) starting before dhcpcd which is not
* always the case. */
+#ifdef SMALL
+# undef USE_LOGFILE
+# define USE_LOGFILE 0
+#endif
#ifndef USE_LOGFILE
# define USE_LOGFILE 1
#endif
@@ -196,4 +200,6 @@ ssize_t addvard(struct dhcpcd_ctx *,
char *hwaddr_ntoa(const uint8_t *, size_t, char *, size_t);
size_t hwaddr_aton(uint8_t *, const char *);
size_t read_hwaddr_aton(uint8_t **, const char *);
+
+ssize_t recvmsg_realloc(int, struct msghdr *, int);
#endif
@@ -5,6 +5,9 @@
#define LIBEXECDIR "/libexec"
#define DBDIR "/var/db"
#define RUNDIR "/var/run"
+#define HAVE_IFAM_PID
+#define HAVE_IFAM_ADDRFLAGS
+#define HAVE_IFADDRS_ADDRFLAGS
#define HAVE_UTIL_H
#define HAVE_SYS_QUEUE_H
#define HAVE_SPAWN_H
@@ -726,8 +726,8 @@ static ssize_t
make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
{
struct bootp *bootp;
- uint8_t *lp, *p, *e, *auth;
- uint8_t *n_params = NULL, auth_len;
+ uint8_t *lp, *p, *e;
+ uint8_t *n_params = NULL;
uint32_t ul;
uint16_t sz;
size_t len, i;
@@ -739,6 +739,9 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
const char *hostname;
const struct vivco *vivco;
int mtu;
+#ifdef AUTH
+ uint8_t *auth, auth_len;
+#endif
if ((mtu = if_getmtu(ifp)) == -1)
logger(ifp->ctx, LOG_ERR,
@@ -971,6 +974,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
p += ifo->vendor[0] + 1;
}
+#ifdef AUTH
if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
DHCPCD_AUTH_SENDREQUIRE)
{
@@ -980,6 +984,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
*p++ = 1;
*p++ = AUTH_ALG_HMAC_MD5;
}
+#endif
if (ifo->vivco_len) {
AREA_CHECK(sizeof(ul));
@@ -1053,10 +1058,9 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
*n_params = (uint8_t)(p - n_params - 1);
}
- /* silence GCC */
+#ifdef AUTH
+ auth = NULL; /* appease GCC */
auth_len = 0;
- auth = NULL;
-
if (ifo->auth.options & DHCPCD_AUTH_SEND) {
ssize_t alen = dhcp_auth_encode(&ifo->auth,
state->auth.token,
@@ -1077,6 +1081,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
p += auth_len;
}
}
+#endif
*p++ = DHO_END;
len = (size_t)(p - (uint8_t *)bootp);
@@ -1091,9 +1096,11 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
len++;
}
+#ifdef AUTH
if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0)
dhcp_auth_encode(&ifo->auth, state->auth.token,
(uint8_t *)bootp, len, 4, type, auth, auth_len);
+#endif
return (ssize_t)len;
@@ -1129,9 +1136,11 @@ read_lease(struct interface *ifp, struct bootp **bootp)
struct dhcp_state *state = D_STATE(ifp);
uint8_t *lease;
size_t bytes;
- const uint8_t *auth;
uint8_t type;
+#ifdef AUTH
+ const uint8_t *auth;
size_t auth_len;
+#endif
/* Safety */
*bootp = NULL;
@@ -1184,6 +1193,7 @@ read_lease(struct interface *ifp, struct bootp **bootp)
DHO_MESSAGETYPE) == -1)
type = 0;
+#ifdef AUTH
/* Authenticate the message */
auth = get_option(ifp->ctx, (struct bootp *)lease, bytes,
DHO_AUTHENTICATION, &auth_len);
@@ -1211,6 +1221,7 @@ read_lease(struct interface *ifp, struct bootp **bootp)
free(lease);
return 0;
}
+#endif
out:
*bootp = (struct bootp *)lease;
@@ -1834,9 +1845,11 @@ dhcp_discover(void *arg)
if (ifo->fallback)
eloop_timeout_add_sec(ifp->ctx->eloop,
ifo->reboot, dhcp_fallback, ifp);
+#ifdef IPV4LL
else if (ifo->options & DHCPCD_IPV4LL)
eloop_timeout_add_sec(ifp->ctx->eloop,
ifo->reboot, ipv4ll_start, ifp);
+#endif
if (ifo->options & DHCPCD_REQUEST)
logger(ifp->ctx, LOG_INFO,
"%s: soliciting a DHCP lease (requesting %s)",
@@ -2499,10 +2512,12 @@ dhcp_reboot(struct interface *ifp)
state->lease.server.s_addr = 0;
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+#ifdef IPV4LL
/* Need to add this before dhcp_expire and friends. */
if (!ifo->fallback && ifo->options & DHCPCD_IPV4LL)
eloop_timeout_add_sec(ifp->ctx->eloop,
ifo->reboot, ipv4ll_start, ifp);
+#endif
if (ifo->options & DHCPCD_LASTLEASE && state->lease.frominfo)
eloop_timeout_add_sec(ifp->ctx->eloop,
@@ -2560,7 +2575,9 @@ dhcp_drop(struct interface *ifp, const char *reason)
}
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+#ifdef AUTH
dhcp_auth_reset(&state->auth);
+#endif
dhcp_close(ifp);
free(state->offer);
@@ -2681,12 +2698,14 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
struct if_options *ifo = ifp->options;
struct dhcp_lease *lease = &state->lease;
uint8_t type, tmp;
- const uint8_t *auth;
struct in_addr addr;
unsigned int i;
- size_t auth_len;
char *msg;
bool bootp_copied;
+ const uint8_t *auth;
+#ifdef AUTH
+ size_t auth_len;
+#endif
#ifdef IN_IFF_DUPLICATED
struct ipv4_addr *ia;
#endif
@@ -2726,6 +2745,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
return;
}
+#ifdef AUTH
/* Authenticate the message */
auth = get_option(ifp->ctx, bootp, bootp_len,
DHO_AUTHENTICATION, &auth_len);
@@ -2753,6 +2773,9 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
}
LOGDHCP0(LOG_WARNING, "no authentication");
}
+#else
+ auth = NULL;
+#endif
/* RFC 3203 */
if (type == DHCP_FORCERENEW) {
@@ -2888,6 +2911,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
"%s: message: %s", ifp->name, msg);
free(msg);
}
+#ifdef IPV4LL
if (state->state == DHS_DISCOVER &&
get_option_uint8(ifp->ctx, &tmp, bootp, bootp_len,
DHO_AUTOCONFIGURE) == 0)
@@ -2912,6 +2936,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
eloop_timeout_add_sec(ifp->ctx->eloop,
DHCP_MAX, dhcp_discover, ifp);
}
+#endif
return;
}
@@ -3562,11 +3587,13 @@ dhcp_start1(void *arg)
}
}
+#ifdef IPV4LL
if (!(ifo->options & DHCPCD_DHCP)) {
if (ifo->options & DHCPCD_IPV4LL)
ipv4ll_start(ifp);
return;
}
+#endif
if (state->offer == NULL || !IS_DHCP(state->offer))
dhcp_discover(ifp);
@@ -3653,9 +3680,12 @@ dhcp_handleifa(int cmd, struct ipv4_addr *ia)
return;
if (cmd == RTM_DELADDR) {
- if (IPV4_BRD_EQ(state->addr, ia)) {
+ if (state->addr == ia) {
logger(ifp->ctx, LOG_INFO,
"%s: deleted IP address %s", ifp->name, ia->saddr);
+ state->addr = NULL;
+ /* Don't clear the added state as we need
+ * to drop the lease. */
dhcp_drop(ifp, "EXPIRE");
}
return;
Oops, something went wrong.

0 comments on commit 42f3e79

Please sign in to comment.