Import dhcpcd-7.0.3 with the following changes:

*  dhcp6: fix a null termination overflow on status messages
  *  options: static routes can be setup in global context again
  *  routes: dhcpcd added host routes are now reported correctly
This commit is contained in:
roy 2018-04-06 10:46:37 +00:00
parent 6909e9fcde
commit 71c9531719
9 changed files with 71 additions and 50 deletions

View File

@ -28,7 +28,7 @@
#define CONFIG_H
#define PACKAGE "dhcpcd"
#define VERSION "7.0.2"
#define VERSION "7.0.3"
#ifndef CONFIG
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"

View File

@ -1847,6 +1847,7 @@ dhcp6_checkstatusok(const struct interface *ifp,
{
uint8_t *opt;
uint16_t opt_len, code;
size_t mlen;
void * (*f)(void *, size_t, uint16_t, uint16_t *), *farg;
char buf[32], *sbuf;
const char *status;
@ -1872,8 +1873,8 @@ dhcp6_checkstatusok(const struct interface *ifp,
/* Anything after the code is a message. */
opt += sizeof(code);
opt_len = (uint16_t)(opt_len - sizeof(code));
if (opt_len == 0) {
mlen = opt_len - sizeof(code);
if (mlen == 0) {
sbuf = NULL;
if (code < sizeof(dhcp6_statuses) / sizeof(char *))
status = dhcp6_statuses[code];
@ -1882,12 +1883,12 @@ dhcp6_checkstatusok(const struct interface *ifp,
status = buf;
}
} else {
if ((sbuf = malloc((size_t)opt_len + 1)) == NULL) {
if ((sbuf = malloc(mlen + 1)) == NULL) {
logerr(__func__);
return -1;
}
memcpy(sbuf, opt, opt_len);
sbuf[len] = '\0';
memcpy(sbuf, opt, mlen);
sbuf[mlen] = '\0';
status = sbuf;
}

View File

@ -577,7 +577,7 @@ dhcpcd_selectprofile(struct interface *ifp, const char *profile)
} else
*ifp->profile = '\0';
free_options(ifp->options);
free_options(ifp->ctx, ifp->options);
ifp->options = ifo;
if (profile) {
add_options(ifp->ctx, ifp->name, ifp->options,
@ -995,6 +995,7 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
}
/* Check if we already have the interface */
iff = if_find(ctx->ifaces, ifp->name);
if (iff != NULL) {
if (iff->active)
logdebugx("%s: interface updated", iff->name);
@ -1013,9 +1014,12 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
}
iff = ifp;
}
if_learnaddrs(ctx, ifs, &ifaddrs);
if (action > 0 && iff->active)
dhcpcd_prestartinterface(iff);
if (action > 0) {
if_learnaddrs(ctx, ifs, &ifaddrs);
if (iff->active)
dhcpcd_prestartinterface(iff);
}
/* Free our discovered list */
while ((ifp = TAILQ_FIRST(ifs))) {
@ -1161,7 +1165,7 @@ reload_config(struct dhcpcd_ctx *ctx)
if (ctx->options & DHCPCD_DAEMONISED)
ifo->options |= DHCPCD_DAEMONISED;
ctx->options = ifo->options;
free_options(ifo);
free_options(ctx, ifo);
}
static void
@ -1519,6 +1523,8 @@ main(int argc, char **argv)
#ifdef INET
ctx.udp_fd = -1;
#endif
rt_init(&ctx);
logopts = LOGERR_ERR|LOGERR_LOG|LOGERR_LOG_DATE|LOGERR_LOG_PID;
i = 0;
while ((opt = getopt_long(argc, argv,
@ -1613,7 +1619,7 @@ main(int argc, char **argv)
if (i == 2) {
printf("Interface options:\n");
if (optind == argc - 1) {
free_options(ifo);
free_options(&ctx, ifo);
ifo = read_config(&ctx, argv[optind], NULL, NULL);
if (ifo == NULL)
goto exit_failure;
@ -1929,8 +1935,6 @@ printpidfile:
}
}
rt_init(&ctx);
TAILQ_FOREACH(ifp, ctx.ifaces, next) {
if (ifp->active)
dhcpcd_initstate1(ifp, argc, argv, 0);
@ -1981,7 +1985,7 @@ printpidfile:
handle_exit_timeout, &ctx);
}
}
free_options(ifo);
free_options(&ctx, ifo);
ifo = NULL;
if_sortinterfaces(&ctx);
@ -2018,6 +2022,7 @@ exit1:
}
free(ctx.ifaces);
}
free_options(&ctx, ifo);
rt_dispose(&ctx);
free(ctx.duid);
if (ctx.link_fd != -1) {
@ -2025,7 +2030,6 @@ exit1:
close(ctx.link_fd);
}
if_closesockets(&ctx);
free_options(ifo);
free_globals(&ctx);
ipv6_ctxfree(&ctx);
dev_stop(&ctx);

View File

@ -1086,14 +1086,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
strncmp(arg, "ms_classless_static_routes=",
strlen("ms_classless_static_routes=")) == 0)
{
struct interface *ifp;
struct in_addr addr3;
ifp = if_find(ctx->ifaces, ifname);
if (ifp == NULL) {
logerrx("static routes require an interface");
return -1;
}
fp = np = strwhite(p);
if (np == NULL) {
logerrx("all routes need a gateway");
@ -1107,7 +1101,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
*fp = ' ';
return -1;
}
if ((rt = rt_new(ifp)) == NULL) {
if ((rt = rt_new0(ctx)) == NULL) {
*fp = ' ';
return -1;
}
@ -1117,16 +1111,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
*fp = ' ';
} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
struct interface *ifp;
ifp = if_find(ctx->ifaces, ifname);
if (ifp == NULL) {
logerrx("static routes require an interface");
return -1;
}
if (parse_addr(&addr, NULL, p) == -1)
return -1;
if ((rt = rt_new(ifp)) == NULL)
if ((rt = rt_new0(ctx)) == NULL)
return -1;
addr2.s_addr = INADDR_ANY;
sa_in_init(&rt->rt_dest, &addr2);
@ -2367,7 +2354,7 @@ read_config(struct dhcpcd_ctx *ctx,
buf = malloc(buflen);
if (buf == NULL) {
logerr(__func__);
free_options(ifo);
free_options(ctx, ifo);
return NULL;
}
ldop = edop = NULL;
@ -2381,7 +2368,7 @@ read_config(struct dhcpcd_ctx *ctx,
if (nbuf == NULL) {
logerr(__func__);
free(buf);
free_options(ifo);
free_options(ctx, ifo);
return NULL;
}
buf = nbuf;
@ -2545,7 +2532,7 @@ read_config(struct dhcpcd_ctx *ctx,
free(buf);
if (profile && !have_profile) {
free_options(ifo);
free_options(ctx, ifo);
errno = ENOENT;
return NULL;
}
@ -2590,7 +2577,7 @@ add_options(struct dhcpcd_ctx *ctx, const char *ifname,
}
void
free_options(struct if_options *ifo)
free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo)
{
size_t i;
struct dhcp_opt *opt;
@ -2612,7 +2599,7 @@ free_options(struct if_options *ifo)
free(ifo->config[i++]);
free(ifo->config);
}
rt_headclear(&ifo->routes, AF_UNSPEC);
rt_headclear0(ctx, &ifo->routes, AF_UNSPEC);
free(ifo->script);
free(ifo->arping);
free(ifo->blacklist);

View File

@ -230,6 +230,6 @@ struct if_options *read_config(struct dhcpcd_ctx *,
int add_options(struct dhcpcd_ctx *, const char *,
struct if_options *, int, char **);
void free_dhcp_opt_embenc(struct dhcp_opt *);
void free_options(struct if_options *);
void free_options(struct dhcpcd_ctx *, struct if_options *);
#endif

View File

@ -85,7 +85,7 @@ if_free(struct interface *ifp)
ipv6nd_free(ifp);
ipv6_free(ifp);
rt_freeif(ifp);
free_options(ifp->options);
free_options(ifp->ctx, ifp->options);
free(ifp);
}

View File

@ -289,10 +289,11 @@ inet_dhcproutes(struct rt_head *routes, struct interface *ifp)
TAILQ_FOREACH(r, &ifp->options->routes, rt_next) {
if (sa_is_unspecified(&r->rt_gateway))
break;
if ((rt = rt_new(ifp)) == NULL)
if ((rt = rt_new0(ifp->ctx)) == NULL)
return -1;
rt->rt_dflags = RTDF_STATIC;
memcpy(rt, r, sizeof(*rt));
rt_setif(rt, ifp);
rt->rt_dflags = RTDF_STATIC;
TAILQ_INSERT_TAIL(&nroutes, rt, rt_next);
}
} else {
@ -407,6 +408,7 @@ inet_routerhostroute(struct rt_head *routes, struct interface *ifp)
}
if ((rth = rt_new(ifp)) == NULL)
return -1;
rth->rt_flags |= RTF_HOST;
sa_in_init(&rth->rt_dest, &gateway->sin_addr);
in.s_addr = INADDR_BROADCAST;
sa_in_init(&rth->rt_netmask, &in);

View File

@ -101,17 +101,13 @@ rt_desc(const char *cmd, const struct rt *rt)
}
void
rt_headclear(struct rt_head *rts, int af)
rt_headclear0(struct dhcpcd_ctx *ctx, struct rt_head *rts, int af)
{
struct rt *rt, *rtn;
struct dhcpcd_ctx *ctx;
if (rts == NULL)
return;
if ((rt = TAILQ_FIRST(rts)) == NULL)
return;
ctx = rt->rt_ifp->ctx;
assert(ctx != NULL);
assert(&ctx->froutes != rts);
TAILQ_FOREACH_SAFE(rt, rts, rt_next, rtn) {
@ -124,6 +120,16 @@ rt_headclear(struct rt_head *rts, int af)
}
}
void
rt_headclear(struct rt_head *rts, int af)
{
struct rt *rt;
if (rts == NULL || (rt = TAILQ_FIRST(rts)) == NULL)
return;
rt_headclear0(rt->rt_ifp->ctx, rts, af);
}
static void
rt_headfree(struct rt_head *rts)
{
@ -146,13 +152,11 @@ rt_dispose(struct dhcpcd_ctx *ctx)
}
struct rt *
rt_new(struct interface *ifp)
rt_new0(struct dhcpcd_ctx *ctx)
{
struct rt *rt;
struct dhcpcd_ctx *ctx;
assert(ifp != NULL);
ctx = ifp->ctx;
assert(ctx != NULL);
if ((rt = TAILQ_FIRST(&ctx->froutes)) != NULL)
TAILQ_REMOVE(&ctx->froutes, rt, rt_next);
else if ((rt = malloc(sizeof(*rt))) == NULL) {
@ -160,10 +164,30 @@ rt_new(struct interface *ifp)
return NULL;
}
memset(rt, 0, sizeof(*rt));
return rt;
}
void
rt_setif(struct rt *rt, struct interface *ifp)
{
assert(rt != NULL);
assert(ifp != NULL);
rt->rt_ifp = ifp;
#ifdef HAVE_ROUTE_METRIC
rt->rt_metric = ifp->metric;
#endif
}
struct rt *
rt_new(struct interface *ifp)
{
struct rt *rt;
assert(ifp != NULL);
if ((rt = rt_new0(ifp->ctx)) == NULL)
return NULL;
rt_setif(rt, ifp);
return rt;
}

View File

@ -86,8 +86,11 @@ void rt_dispose(struct dhcpcd_ctx *);
struct rt * rt_find(struct rt_head *, const struct rt *);
void rt_free(struct rt *);
void rt_freeif(struct interface *);
void rt_headclear0(struct dhcpcd_ctx *, struct rt_head *, int);
void rt_headclear(struct rt_head *, int);
void rt_headfreeif(struct rt_head *);
struct rt * rt_new0(struct dhcpcd_ctx *);
void rt_setif(struct rt *, struct interface *);
struct rt * rt_new(struct interface *);
void rt_recvrt(int, const struct rt *);
void rt_build(struct dhcpcd_ctx *, int);