Import dhcpcd-8.0.3 With the following changes:
* DHCP: Work with IP headers with options * script: Assert that env string are correctly terminated * script: Terminate env strings with no value * script: Don't attempt to use an invalid env string * route: Fix NULL deference error when using static routes * ARP: Respect IFF_NOARP * DHCP: Allow full DHCP support for PtP interfaces, but not by default * control: sends correct buffer to listeners dhcpcd-ui now correctly reports SSD association and all the addresses obtained (regression from dhcpcd-7)
This commit is contained in:
parent
b6a3a94eb1
commit
4dfdf2681a
|
@ -558,6 +558,15 @@ bpf_arp(struct interface *ifp, int fd)
|
|||
#define BPF_M_UDP 3
|
||||
#define BPF_M_UDPLEN 4
|
||||
|
||||
#ifdef ARPHRD_NONE
|
||||
static const struct bpf_insn bpf_bootp_none[] = {
|
||||
/* Set the frame header length to zero. */
|
||||
BPF_STMT(BPF_LD + BPF_IMM, 0),
|
||||
BPF_STMT(BPF_ST, BPF_M_FHLEN),
|
||||
};
|
||||
#define BPF_BOOTP_NONE_LEN __arraycount(bpf_bootp_none)
|
||||
#endif
|
||||
|
||||
static const struct bpf_insn bpf_bootp_ether[] = {
|
||||
/* Make sure this is an IP packet. */
|
||||
BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
|
||||
|
@ -665,6 +674,12 @@ bpf_bootp(struct interface *ifp, int fd)
|
|||
bp = bpf;
|
||||
/* Check frame header. */
|
||||
switch(ifp->family) {
|
||||
#ifdef ARPHRD_NONE
|
||||
case ARPHRD_NONE:
|
||||
memcpy(bp, bpf_bootp_none, sizeof(bpf_bootp_none));
|
||||
bp += BPF_BOOTP_NONE_LEN;
|
||||
break;
|
||||
#endif
|
||||
case ARPHRD_ETHER:
|
||||
memcpy(bp, bpf_bootp_ether, sizeof(bpf_bootp_ether));
|
||||
bp += BPF_BOOTP_ETHER_LEN;
|
||||
|
|
|
@ -52,27 +52,6 @@
|
|||
(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
|
||||
#endif
|
||||
|
||||
static void
|
||||
control_queue_purge(struct dhcpcd_ctx *ctx, char *data)
|
||||
{
|
||||
int found;
|
||||
struct fd_list *fp;
|
||||
struct fd_data *fpd;
|
||||
|
||||
/* If no other fd queue has the same data, free it */
|
||||
found = 0;
|
||||
TAILQ_FOREACH(fp, &ctx->control_fds, next) {
|
||||
TAILQ_FOREACH(fpd, &fp->queue, next) {
|
||||
if (fpd->data == data) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
control_queue_free(struct fd_list *fd)
|
||||
{
|
||||
|
@ -80,14 +59,20 @@ control_queue_free(struct fd_list *fd)
|
|||
|
||||
while ((fdp = TAILQ_FIRST(&fd->queue))) {
|
||||
TAILQ_REMOVE(&fd->queue, fdp, next);
|
||||
if (fdp->freeit)
|
||||
control_queue_purge(fd->ctx, fdp->data);
|
||||
if (fdp->data_size != 0)
|
||||
free(fdp->data);
|
||||
free(fdp);
|
||||
}
|
||||
fd->queue_len = 0;
|
||||
|
||||
#ifdef CTL_FREE_LIST
|
||||
while ((fdp = TAILQ_FIRST(&fd->free_queue))) {
|
||||
TAILQ_REMOVE(&fd->free_queue, fdp, next);
|
||||
if (fdp->data_size != 0)
|
||||
free(fdp->data);
|
||||
free(fdp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -161,29 +146,33 @@ control_handle1(struct dhcpcd_ctx *ctx, int lfd, unsigned int fd_flags)
|
|||
|
||||
len = sizeof(run);
|
||||
if ((fd = accept(lfd, (struct sockaddr *)&run, &len)) == -1)
|
||||
return;
|
||||
goto error;
|
||||
if ((flags = fcntl(fd, F_GETFD, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
{
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
goto error;
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
goto error;
|
||||
|
||||
l = malloc(sizeof(*l));
|
||||
if (l) {
|
||||
l->ctx = ctx;
|
||||
l->fd = fd;
|
||||
l->flags = fd_flags;
|
||||
TAILQ_INIT(&l->queue);
|
||||
TAILQ_INIT(&l->free_queue);
|
||||
TAILQ_INSERT_TAIL(&ctx->control_fds, l, next);
|
||||
eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
|
||||
} else
|
||||
if (l == NULL)
|
||||
goto error;
|
||||
|
||||
l->ctx = ctx;
|
||||
l->fd = fd;
|
||||
l->flags = fd_flags;
|
||||
TAILQ_INIT(&l->queue);
|
||||
l->queue_len = 0;
|
||||
#ifdef CTL_FREE_LIST
|
||||
TAILQ_INIT(&l->free_queue);
|
||||
#endif
|
||||
TAILQ_INSERT_TAIL(&ctx->control_fds, l, next);
|
||||
eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
|
||||
return;
|
||||
|
||||
error:
|
||||
logerr(__func__);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
@ -374,40 +363,85 @@ control_writeone(void *arg)
|
|||
}
|
||||
|
||||
TAILQ_REMOVE(&fd->queue, data, next);
|
||||
if (data->freeit)
|
||||
control_queue_purge(fd->ctx, data->data);
|
||||
data->data = NULL; /* safety */
|
||||
data->data_len = 0;
|
||||
fd->queue_len--;
|
||||
#ifdef CTL_FREE_LIST
|
||||
TAILQ_INSERT_TAIL(&fd->free_queue, data, next);
|
||||
#else
|
||||
if (data->data_size != 0)
|
||||
free(data->data);
|
||||
free(data);
|
||||
#endif
|
||||
|
||||
if (TAILQ_FIRST(&fd->queue) == NULL)
|
||||
eloop_event_remove_writecb(fd->ctx->eloop, fd->fd);
|
||||
}
|
||||
|
||||
int
|
||||
control_queue(struct fd_list *fd, char *data, size_t data_len, uint8_t fit)
|
||||
control_queue(struct fd_list *fd, void *data, size_t data_len, bool fit)
|
||||
{
|
||||
struct fd_data *d;
|
||||
size_t n;
|
||||
|
||||
d = TAILQ_FIRST(&fd->free_queue);
|
||||
if (d) {
|
||||
TAILQ_REMOVE(&fd->free_queue, d, next);
|
||||
} else {
|
||||
n = 0;
|
||||
TAILQ_FOREACH(d, &fd->queue, next) {
|
||||
if (++n == CONTROL_QUEUE_MAX) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
#ifdef CTL_FREE_LIST
|
||||
struct fd_data *df;
|
||||
|
||||
d = NULL;
|
||||
TAILQ_FOREACH(df, &fd->free_queue, next) {
|
||||
if (!fit) {
|
||||
if (df->data_size == 0) {
|
||||
d = df;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
d = malloc(sizeof(*d));
|
||||
if (d == NULL || d->data_size < df->data_size) {
|
||||
d = df;
|
||||
if (d->data_size <= data_len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d != NULL)
|
||||
TAILQ_REMOVE(&fd->free_queue, d, next);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (fd->queue_len == CONTROL_QUEUE_MAX) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
fd->queue_len++;
|
||||
d = calloc(1, sizeof(*d));
|
||||
if (d == NULL)
|
||||
return -1;
|
||||
}
|
||||
d->data = data;
|
||||
|
||||
if (!fit) {
|
||||
#ifdef CTL_FREE_LIST
|
||||
if (d->data_size != 0) {
|
||||
free(d->data);
|
||||
d->data_size = 0;
|
||||
}
|
||||
#endif
|
||||
d->data = data;
|
||||
d->data_len = data_len;
|
||||
goto queue;
|
||||
}
|
||||
|
||||
if (d->data_size == 0)
|
||||
d->data = NULL;
|
||||
if (d->data_size < data_len) {
|
||||
void *nbuf = realloc(d->data, data_len);
|
||||
if (nbuf == NULL) {
|
||||
free(d->data);
|
||||
free(d);
|
||||
return -1;
|
||||
}
|
||||
d->data = nbuf;
|
||||
d->data_size = data_len;
|
||||
}
|
||||
memcpy(d->data, data, data_len);
|
||||
d->data_len = data_len;
|
||||
d->freeit = fit;
|
||||
|
||||
queue:
|
||||
TAILQ_INSERT_TAIL(&fd->queue, d, next);
|
||||
eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd);
|
||||
return 0;
|
||||
|
|
|
@ -31,14 +31,20 @@
|
|||
|
||||
#include "dhcpcd.h"
|
||||
|
||||
#if !defined(CTL_FREE_LIST)
|
||||
#define CTL_FREE_LIST 1
|
||||
#elif CTL_FREE_LIST == 0
|
||||
#undef CTL_FREE_LIST
|
||||
#endif
|
||||
|
||||
/* Limit queue size per fd */
|
||||
#define CONTROL_QUEUE_MAX 100
|
||||
|
||||
struct fd_data {
|
||||
TAILQ_ENTRY(fd_data) next;
|
||||
char *data;
|
||||
void *data;
|
||||
size_t data_size;
|
||||
size_t data_len;
|
||||
uint8_t freeit;
|
||||
};
|
||||
TAILQ_HEAD(fd_data_head, fd_data);
|
||||
|
||||
|
@ -48,7 +54,10 @@ struct fd_list {
|
|||
int fd;
|
||||
unsigned int flags;
|
||||
struct fd_data_head queue;
|
||||
size_t queue_len;
|
||||
#ifdef CTL_FREE_LIST
|
||||
struct fd_data_head free_queue;
|
||||
#endif
|
||||
};
|
||||
TAILQ_HEAD(fd_list_head, fd_list);
|
||||
|
||||
|
@ -59,7 +68,7 @@ int control_start(struct dhcpcd_ctx *, const char *);
|
|||
int control_stop(struct dhcpcd_ctx *);
|
||||
int control_open(const char *);
|
||||
ssize_t control_send(struct dhcpcd_ctx *, int, char * const *);
|
||||
int control_queue(struct fd_list *fd, char *data, size_t data_len, uint8_t fit);
|
||||
int control_queue(struct fd_list *, void *, size_t, bool);
|
||||
void control_close(struct dhcpcd_ctx *ctx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "8.0.2"
|
||||
#define VERSION "8.0.3"
|
||||
|
||||
#ifndef CONFIG
|
||||
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
|
||||
|
|
|
@ -622,6 +622,7 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
|
|||
int vname,
|
||||
const uint8_t *data, size_t dl, const char *ifname)
|
||||
{
|
||||
fpos_t fp_pos;
|
||||
const uint8_t *e, *t;
|
||||
uint16_t u16;
|
||||
int16_t s16;
|
||||
|
@ -636,25 +637,32 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
|
|||
if ((ssize_t)dl == -1)
|
||||
return 0;
|
||||
|
||||
if (fprintf(fp, "%s", prefix) == -1)
|
||||
if (fgetpos(fp, &fp_pos) == -1)
|
||||
return -1;
|
||||
if (fprintf(fp, "%s", prefix) == -1)
|
||||
goto err;
|
||||
|
||||
/* We printed something, so always goto err from now-on
|
||||
* to terminate the string. */
|
||||
if (vname) {
|
||||
if (fprintf(fp, "_%s", opt->var) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
if (fputc('=', fp) == EOF)
|
||||
return -1;
|
||||
goto err;
|
||||
if (dl == 0)
|
||||
return 1;
|
||||
goto done;
|
||||
|
||||
if (opt->type & OT_RFC1035) {
|
||||
char domain[NS_MAXDNAME];
|
||||
|
||||
sl = decode_rfc1035(domain, sizeof(domain), data, dl);
|
||||
if (sl == 0 || sl == -1)
|
||||
return sl;
|
||||
if (sl == -1)
|
||||
goto err;
|
||||
if (sl == 0)
|
||||
goto done;
|
||||
if (valid_domainname(domain, opt->type) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
return efprintf(fp, "%s", domain);
|
||||
}
|
||||
|
||||
|
@ -670,7 +678,7 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
|
|||
char buf[1024];
|
||||
|
||||
if (print_string(buf, sizeof(buf), opt->type, data, dl) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
return efprintf(fp, "%s", buf);
|
||||
}
|
||||
|
||||
|
@ -690,12 +698,10 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
|
|||
*data & (1 << sl))
|
||||
{
|
||||
if (fputc(opt->bitflags[l], fp) == EOF)
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (fputc('\0', fp) == EOF)
|
||||
return -1;
|
||||
return 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
t = data;
|
||||
|
@ -703,66 +709,71 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt,
|
|||
while (data < e) {
|
||||
if (data != t) {
|
||||
if (fputc(' ', fp) == EOF)
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
if (opt->type & OT_UINT8) {
|
||||
if (fprintf(fp, "%u", *data) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data++;
|
||||
} else if (opt->type & OT_INT8) {
|
||||
if (fprintf(fp, "%d", *data) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data++;
|
||||
} else if (opt->type & OT_UINT16) {
|
||||
memcpy(&u16, data, sizeof(u16));
|
||||
u16 = ntohs(u16);
|
||||
if (fprintf(fp, "%u", u16) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data += sizeof(u16);
|
||||
} else if (opt->type & OT_INT16) {
|
||||
memcpy(&u16, data, sizeof(u16));
|
||||
s16 = (int16_t)ntohs(u16);
|
||||
if (fprintf(fp, "%d", s16) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data += sizeof(u16);
|
||||
} else if (opt->type & OT_UINT32) {
|
||||
memcpy(&u32, data, sizeof(u32));
|
||||
u32 = ntohl(u32);
|
||||
if (fprintf(fp, "%u", u32) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data += sizeof(u32);
|
||||
} else if (opt->type & OT_INT32) {
|
||||
memcpy(&u32, data, sizeof(u32));
|
||||
s32 = (int32_t)ntohl(u32);
|
||||
if (fprintf(fp, "%d", s32) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data += sizeof(u32);
|
||||
} else if (opt->type & OT_ADDRIPV4) {
|
||||
memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
|
||||
if (fprintf(fp, "%s", inet_ntoa(addr)) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
data += sizeof(addr.s_addr);
|
||||
} else if (opt->type & OT_ADDRIPV6) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (inet_ntop(AF_INET6, data, buf, sizeof(buf)) == NULL)
|
||||
return -1;
|
||||
goto err;
|
||||
if (fprintf(fp, "%s", buf) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
if (data[0] == 0xfe && (data[1] & 0xc0) == 0x80) {
|
||||
if (fprintf(fp,"%%%s", ifname) == -1)
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
data += 16;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (fputc('\0', fp) == EOF)
|
||||
return -1;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
(void)fsetpos(fp, &fp_pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1584,24 +1584,24 @@ eexit:
|
|||
}
|
||||
|
||||
static uint16_t
|
||||
checksum(const void *data, size_t len)
|
||||
in_cksum(void *data, size_t len, uint32_t *isum)
|
||||
{
|
||||
const uint8_t *addr = data;
|
||||
uint32_t sum = 0;
|
||||
const uint16_t *word = data;
|
||||
uint32_t sum = isum != NULL ? *isum : 0;
|
||||
|
||||
while (len > 1) {
|
||||
sum += (uint32_t)(addr[0] * 256 + addr[1]);
|
||||
addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
for (; len > 1; len -= sizeof(*word))
|
||||
sum += *word++;
|
||||
|
||||
if (len == 1)
|
||||
sum += (uint32_t)(*addr * 256);
|
||||
sum += *(const uint8_t *)word;
|
||||
|
||||
if (isum != NULL)
|
||||
*isum = sum;
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
|
||||
return (uint16_t)~htons((uint16_t)sum);
|
||||
return (uint16_t)~sum;
|
||||
}
|
||||
|
||||
static struct bootp_pkt *
|
||||
|
@ -1639,14 +1639,16 @@ dhcp_makeudppacket(size_t *sz, const uint8_t *data, size_t length,
|
|||
udp->uh_dport = htons(BOOTPS);
|
||||
udp->uh_ulen = htons((uint16_t)(sizeof(*udp) + length));
|
||||
ip->ip_len = udp->uh_ulen;
|
||||
udp->uh_sum = checksum(udpp, sizeof(*ip) + sizeof(*udp) + length);
|
||||
udp->uh_sum = in_cksum(udpp, sizeof(*ip) + sizeof(*udp) + length, NULL);
|
||||
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(*ip) >> 2;
|
||||
ip->ip_id = (uint16_t)arc4random_uniform(UINT16_MAX);
|
||||
ip->ip_ttl = IPDEFTTL;
|
||||
ip->ip_len = htons((uint16_t)(sizeof(*ip) + sizeof(*udp) + length));
|
||||
ip->ip_sum = checksum(ip, sizeof(*ip));
|
||||
ip->ip_sum = in_cksum(ip, sizeof(*ip), NULL);
|
||||
if (ip->ip_sum == 0)
|
||||
ip->ip_sum = 0xffff; /* RFC 768 */
|
||||
|
||||
*sz = sizeof(*ip) + sizeof(*udp) + length;
|
||||
return udpp;
|
||||
|
@ -2363,7 +2365,10 @@ dhcp_arp_address(struct interface *ifp)
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
if (ifp->options->options & DHCPCD_ARP && ia == NULL) {
|
||||
if (!(ifp->flags & IFF_NOARP) &&
|
||||
ifp->options->options & DHCPCD_ARP &&
|
||||
ia == NULL)
|
||||
{
|
||||
struct arp_state *astate;
|
||||
struct dhcp_lease l;
|
||||
|
||||
|
@ -3236,10 +3241,15 @@ valid_udp_packet(void *packet, size_t plen, struct in_addr *from,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct ip *ip = packet;
|
||||
char ip_hlv = *(char *)ip;
|
||||
struct ip pseudo_ip = {
|
||||
.ip_p = IPPROTO_UDP,
|
||||
.ip_src = ip->ip_src,
|
||||
.ip_dst = ip->ip_dst
|
||||
};
|
||||
size_t ip_hlen;
|
||||
uint16_t ip_len, uh_sum;
|
||||
struct udphdr *udp;
|
||||
uint32_t csum;
|
||||
|
||||
if (plen < sizeof(*ip)) {
|
||||
if (from != NULL)
|
||||
|
@ -3252,13 +3262,13 @@ valid_udp_packet(void *packet, size_t plen, struct in_addr *from,
|
|||
from->s_addr = ip->ip_src.s_addr;
|
||||
|
||||
ip_hlen = (size_t)ip->ip_hl * 4;
|
||||
if (checksum(ip, ip_hlen) != 0) {
|
||||
if (in_cksum(ip, ip_hlen, NULL) != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip_len = ntohs(ip->ip_len);
|
||||
/* Check we have a payload */
|
||||
ip_len = ntohs(ip->ip_len);
|
||||
if (ip_len <= ip_hlen + sizeof(*udp)) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
|
@ -3272,28 +3282,21 @@ valid_udp_packet(void *packet, size_t plen, struct in_addr *from,
|
|||
if (flags & BPF_PARTIALCSUM)
|
||||
return 0;
|
||||
|
||||
udp = (struct udphdr *)((char *)ip + ip_hlen);
|
||||
/* UDP checksum is based on a pseudo IP header alongside
|
||||
* the UDP header and payload. */
|
||||
udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
|
||||
if (udp->uh_sum == 0)
|
||||
return 0;
|
||||
uh_sum = udp->uh_sum;
|
||||
|
||||
/* This does scribble on the packet, but at this point
|
||||
* we don't care to keep it. */
|
||||
uh_sum = udp->uh_sum;
|
||||
udp->uh_sum = 0;
|
||||
ip->ip_hl = 0;
|
||||
ip->ip_v = 0;
|
||||
ip->ip_tos = 0;
|
||||
ip->ip_len = udp->uh_ulen;
|
||||
ip->ip_id = 0;
|
||||
ip->ip_off = 0;
|
||||
ip->ip_ttl = 0;
|
||||
ip->ip_sum = 0;
|
||||
if (checksum(packet, ip_len) != uh_sum) {
|
||||
pseudo_ip.ip_len = udp->uh_ulen;
|
||||
csum = 0;
|
||||
in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum);
|
||||
if (in_cksum(udp, ntohs(udp->uh_ulen), &csum) != uh_sum) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*(char *)ip = ip_hlv;
|
||||
ip->ip_len = htons(ip_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3339,12 +3342,6 @@ dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len)
|
|||
ifp->name, inet_ntoa(from));
|
||||
return;
|
||||
}
|
||||
if (ifp->flags & IFF_POINTOPOINT &&
|
||||
(state->addr == NULL || state->addr->brd.s_addr != from.s_addr))
|
||||
{
|
||||
logwarnx("%s: server %s is not destination",
|
||||
ifp->name, inet_ntoa(from));
|
||||
}
|
||||
|
||||
/*
|
||||
* DHCP has a variable option area rather than a fixed vendor area.
|
||||
|
@ -3721,12 +3718,6 @@ dhcp_start1(void *arg)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ifp->hwlen == 0 && ifo->clientid[0] == '\0') {
|
||||
logwarnx("%s: needs a clientid to configure", ifp->name);
|
||||
dhcp_drop(ifp, "FAIL");
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
||||
return;
|
||||
}
|
||||
/* We don't want to read the old lease if we NAK an old test */
|
||||
nolease = state->offer && ifp->ctx->options & DHCPCD_TEST;
|
||||
if (!nolease && ifo->options & DHCPCD_DHCP) {
|
||||
|
|
|
@ -458,11 +458,10 @@ configure_interface1(struct interface *ifp)
|
|||
ifo->options &= ~DHCPCD_ARP;
|
||||
if (!(ifp->flags & IFF_MULTICAST))
|
||||
ifo->options &= ~DHCPCD_IPV6RS;
|
||||
if (!(ifo->options & DHCPCD_INFORM))
|
||||
if (!(ifo->options & (DHCPCD_INFORM | DHCPCD_WANTDHCP)))
|
||||
ifo->options |= DHCPCD_STATIC;
|
||||
}
|
||||
if (ifp->flags & IFF_NOARP ||
|
||||
!(ifo->options & DHCPCD_ARP) ||
|
||||
if (!(ifo->options & DHCPCD_ARP) ||
|
||||
ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
|
||||
ifo->options &= ~DHCPCD_IPV4LL;
|
||||
|
||||
|
@ -1440,10 +1439,10 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
|
|||
* write callback on the fd */
|
||||
if (strcmp(*argv, "--version") == 0) {
|
||||
return control_queue(fd, UNCONST(VERSION),
|
||||
strlen(VERSION) + 1, 0);
|
||||
strlen(VERSION) + 1, false);
|
||||
} else if (strcmp(*argv, "--getconfigfile") == 0) {
|
||||
return control_queue(fd, UNCONST(fd->ctx->cffile),
|
||||
strlen(fd->ctx->cffile) + 1, 0);
|
||||
strlen(fd->ctx->cffile) + 1, false);
|
||||
} else if (strcmp(*argv, "--getinterfaces") == 0) {
|
||||
eloop_event_add_w(fd->ctx->eloop, fd->fd,
|
||||
dhcpcd_getinterfaces, fd);
|
||||
|
|
|
@ -52,10 +52,6 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef ARPHRD_NETROM
|
||||
# define ARPHRD_NETROM 0
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "duid.h"
|
||||
|
@ -189,10 +185,10 @@ duid_get(uint8_t **d, const struct interface *ifp)
|
|||
return len;
|
||||
|
||||
/* No UUID? OK, lets make one based on our interface */
|
||||
if (ifp->family == ARPHRD_NETROM) {
|
||||
logwarnx("%s: is a NET/ROM pseudo interface", ifp->name);
|
||||
if (ifp->hwlen == 0) {
|
||||
logwarnx("%s: does not have hardware address", ifp->name);
|
||||
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
|
||||
if (ifp2->family != ARPHRD_NETROM)
|
||||
if (ifp2->hwlen != 0)
|
||||
break;
|
||||
}
|
||||
if (ifp2) {
|
||||
|
|
|
@ -191,6 +191,8 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
|||
if (setsockopt(ctx->link_fd, PF_ROUTE, ROUTE_MSGFILTER,
|
||||
&msgfilter_mask, sizeof(msgfilter_mask)) == -1)
|
||||
logerr(__func__);
|
||||
#else
|
||||
#warning kernel does not support route message filtering
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -660,11 +662,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* We have already checked that at least one address must be
|
||||
* present after the rtm structure. */
|
||||
/* coverity[ptr_arith] */
|
||||
if (get_addrs(rtm->rtm_addrs, rtm + 1,
|
||||
rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
|
||||
if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
|
||||
rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
|
||||
return -1;
|
||||
memset(rt, 0, sizeof(*rt));
|
||||
|
||||
|
@ -1115,10 +1114,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
|
||||
return 0;
|
||||
|
||||
/* We have already checked that at least one address must be
|
||||
* present after the ifam structure. */
|
||||
/* coverity[ptr_arith] */
|
||||
if (get_addrs(ifam->ifam_addrs, ifam + 1,
|
||||
if (get_addrs(ifam->ifam_addrs, (const char *)ifam + sizeof(*ifam),
|
||||
ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -1314,32 +1310,41 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
|
|||
#ifdef RTM_DESYNC
|
||||
case RTM_DESYNC:
|
||||
dhcpcd_linkoverflow(ctx);
|
||||
#elif !defined(SO_RERROR)
|
||||
#warning cannot detect route socket overflow within kernel
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0);
|
||||
int
|
||||
if_handlelink(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
struct rtm rtm;
|
||||
struct iovec iov = { .iov_base = &rtm, .iov_len = sizeof(rtm) };
|
||||
struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(ctx->link_fd, &msg, 0);
|
||||
len = read(ctx->link_fd, &rtm, sizeof(rtm));
|
||||
if (len == -1)
|
||||
return -1;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
if (len < rtm.hdr.rtm_msglen) {
|
||||
if ((size_t)len < sizeof(rtm.hdr.rtm_msglen) ||
|
||||
len != rtm.hdr.rtm_msglen)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
/* We generally treat rtm.hdr has an array so we can easily
|
||||
* access the following data. */
|
||||
/* coverity[callee_ptr_arith] */
|
||||
/*
|
||||
* Coverity thinks that the data could be tainted from here.
|
||||
* I have no idea how because the length of the data we read
|
||||
* is guarded by len and checked to match rtm_msglen.
|
||||
* The issue seems to be related to extracting the addresses
|
||||
* at the end of the header, but seems to have no issues with the
|
||||
* equivalent call in if_initrt.
|
||||
*/
|
||||
/* coverity[tainted_data] */
|
||||
return if_dispatch(ctx, &rtm.hdr);
|
||||
}
|
||||
|
||||
|
|
|
@ -2062,7 +2062,7 @@ err_sla:
|
|||
ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
|
||||
break;
|
||||
case O_DHCP:
|
||||
ifo->options |= DHCPCD_DHCP | DHCPCD_IPV4;
|
||||
ifo->options |= DHCPCD_DHCP | DHCPCD_WANTDHCP | DHCPCD_IPV4;
|
||||
break;
|
||||
case O_NODHCP:
|
||||
ifo->options &= ~DHCPCD_DHCP;
|
||||
|
@ -2281,7 +2281,7 @@ default_config(struct dhcpcd_ctx *ctx)
|
|||
ifo->script = UNCONST(default_script);
|
||||
ifo->metric = -1;
|
||||
ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
|
||||
rb_tree_init(&ifo->routes, &rt_compare_proto_ops);
|
||||
rb_tree_init(&ifo->routes, &rt_compare_list_ops);
|
||||
#ifdef AUTH
|
||||
TAILQ_INIT(&ifo->auth.tokens);
|
||||
#endif
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
#define DHCPCD_DHCP6 (1ULL << 50)
|
||||
#define DHCPCD_IF_UP (1ULL << 51)
|
||||
#define DHCPCD_INFORM6 (1ULL << 52)
|
||||
// unused (1ULL << 53)
|
||||
#define DHCPCD_WANTDHCP (1ULL << 53)
|
||||
#define DHCPCD_IPV6RA_AUTOCONF (1ULL << 54)
|
||||
#define DHCPCD_ROUTER_HOST_ROUTE_WARNED (1ULL << 55)
|
||||
#define DHCPCD_LASTLEASE_EXTEND (1ULL << 56)
|
||||
|
|
|
@ -307,17 +307,16 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
struct if_spec spec;
|
||||
#ifdef AF_LINK
|
||||
const struct sockaddr_dl *sdl;
|
||||
#ifdef SIOCGIFPRIORITY
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
#ifdef IFLR_ACTIVE
|
||||
struct if_laddrreq iflr = { .flags = IFLR_PREFIX };
|
||||
int link_fd;
|
||||
#endif
|
||||
|
||||
#elif AF_PACKET
|
||||
const struct sockaddr_ll *sll;
|
||||
#endif
|
||||
#if defined(SIOCGIFPRIORITY) || defined(SIOCGIFHWADDR)
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
if ((ifs = malloc(sizeof(*ifs))) == NULL) {
|
||||
logerr(__func__);
|
||||
|
@ -512,10 +511,21 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
|
||||
#endif
|
||||
}
|
||||
#ifdef __linux__
|
||||
/* PPP addresses on Linux don't have hardware addresses */
|
||||
else
|
||||
ifp->index = if_nametoindex(ifp->name);
|
||||
#ifdef SIOCGIFHWADDR
|
||||
else {
|
||||
/* This is a huge bug in getifaddrs(3) as there
|
||||
* is no reason why this can't be returned in
|
||||
* ifa_addr. */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifa->ifa_name,
|
||||
sizeof(ifr.ifr_name));
|
||||
if (ioctl(ctx->pf_inet_fd, SIOCGIFHWADDR, &ifr) == -1)
|
||||
logerr("%s: SIOCGIFHWADDR", ifa->ifa_name);
|
||||
ifp->family = ifr.ifr_hwaddr.sa_family;
|
||||
if (ioctl(ctx->pf_inet_fd, SIOCGIFINDEX, &ifr) == -1)
|
||||
logerr("%s: SIOCGIFINDEX", ifa->ifa_name);
|
||||
ifp->index = (unsigned int)ifr.ifr_ifindex;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure hardware address is valid. */
|
||||
|
@ -535,6 +545,9 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
#endif
|
||||
#ifdef ARPHRD_PPP
|
||||
case ARPHRD_PPP:
|
||||
#endif
|
||||
#ifdef ARPHRD_NONE
|
||||
case ARPHRD_NONE:
|
||||
#endif
|
||||
/* We don't warn for supported families */
|
||||
break;
|
||||
|
|
|
@ -268,13 +268,12 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp, bool *have_default)
|
|||
rb_tree_init(&nroutes, &rt_compare_proto_ops);
|
||||
|
||||
/* First, add a subnet route. */
|
||||
if (!(ifp->flags & IFF_POINTOPOINT) &&
|
||||
if (state->addr->mask.s_addr != INADDR_ANY
|
||||
#ifndef BSD
|
||||
/* BSD adds a route in this instance */
|
||||
state->addr->mask.s_addr != INADDR_BROADCAST &&
|
||||
&& state->addr->mask.s_addr != INADDR_BROADCAST
|
||||
#endif
|
||||
state->addr->mask.s_addr != INADDR_ANY)
|
||||
{
|
||||
) {
|
||||
if ((rt = rt_new(ifp)) == NULL)
|
||||
return -1;
|
||||
rt->rt_dflags |= RTDF_IFA_ROUTE;
|
||||
|
@ -680,8 +679,10 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
|
|||
logdebugx("%s: aliased %s", ia->alias, ia->saddr);
|
||||
#endif
|
||||
|
||||
logdebugx("%s: adding IP address %s broadcast %s",
|
||||
ifp->name, ia->saddr, inet_ntoa(*bcast));
|
||||
logdebugx("%s: adding IP address %s %s %s",
|
||||
ifp->name, ia->saddr,
|
||||
ifp->flags & IFF_POINTOPOINT ? "destination" : "broadcast",
|
||||
inet_ntoa(*bcast));
|
||||
if (if_address(RTM_NEWADDR, ia) == -1) {
|
||||
if (errno != EEXIST)
|
||||
logerr("%s: if_addaddress",
|
||||
|
@ -742,7 +743,8 @@ ipv4_applyaddr(void *arg)
|
|||
#ifdef ARP
|
||||
/* Announce the preferred address to
|
||||
* kick ARP caches. */
|
||||
arp_announceaddr(ifp->ctx, &lease->addr);
|
||||
if (!(ifp->flags & IFF_NOARP))
|
||||
arp_announceaddr(ifp->ctx,&lease->addr);
|
||||
#endif
|
||||
}
|
||||
script_runreason(ifp, state->reason);
|
||||
|
@ -804,7 +806,8 @@ ipv4_applyaddr(void *arg)
|
|||
rt_build(ifp->ctx, AF_INET);
|
||||
|
||||
#ifdef ARP
|
||||
arp_announceaddr(ifp->ctx, &state->addr->addr);
|
||||
if (!(ifp->flags & IFF_NOARP))
|
||||
arp_announceaddr(ifp->ctx, &state->addr->addr);
|
||||
#endif
|
||||
|
||||
if (state->state == DHS_BOUND) {
|
||||
|
|
|
@ -100,7 +100,8 @@
|
|||
#endif
|
||||
|
||||
/* This was fixed in NetBSD */
|
||||
#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000
|
||||
#if (defined(__DragonFly_version) && __DragonFly_version >= 500704) || \
|
||||
(defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000)
|
||||
# undef IPV6_POLLADDRFLAG
|
||||
#endif
|
||||
|
||||
|
@ -153,9 +154,12 @@
|
|||
* ND6 Advertising is only used for IP address sharing to prefer
|
||||
* the address on a specific interface.
|
||||
* This just fails to work on OpenBSD and causes erroneous duplicate
|
||||
* address messages on BSD's other then NetBSD.
|
||||
* address messages on BSD's other then DragonFly and NetBSD.
|
||||
*/
|
||||
#if !defined(SMALL) && (defined(__NetBSD__) || defined(__linux__))
|
||||
#if !defined(SMALL) && \
|
||||
((defined(__DragonFly_version) && __DragonFly_version >= 500703) || \
|
||||
(defined(__NetBSD_Version__) && __NetBSD_Version__ >= 899002800) || \
|
||||
defined(__linux__))
|
||||
# define ND6_ADVERTISE
|
||||
#endif
|
||||
|
||||
|
|
|
@ -139,7 +139,19 @@ rt_compare_os(__unused void *context, const void *node1, const void *node2)
|
|||
}
|
||||
|
||||
static int
|
||||
rt_compare_proto(__unused void *context, const void *node1, const void *node2)
|
||||
rt_compare_list(__unused void *context, const void *node1, const void *node2)
|
||||
{
|
||||
const struct rt *rt1 = node1, *rt2 = node2;
|
||||
|
||||
if (rt1->rt_order > rt2->rt_order)
|
||||
return 1;
|
||||
if (rt1->rt_order < rt2->rt_order)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rt_compare_proto(void *context, const void *node1, const void *node2)
|
||||
{
|
||||
const struct rt *rt1 = node1, *rt2 = node2;
|
||||
int c;
|
||||
|
@ -161,11 +173,7 @@ rt_compare_proto(__unused void *context, const void *node1, const void *node2)
|
|||
return c;
|
||||
|
||||
/* Finally the order in which the route was given to us. */
|
||||
if (rt1->rt_order > rt2->rt_order)
|
||||
return 1;
|
||||
if (rt1->rt_order < rt2->rt_order)
|
||||
return -1;
|
||||
return 0;
|
||||
return rt_compare_list(context, rt1, rt2);
|
||||
}
|
||||
|
||||
static const rb_tree_ops_t rt_compare_os_ops = {
|
||||
|
@ -175,6 +183,13 @@ static const rb_tree_ops_t rt_compare_os_ops = {
|
|||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
const rb_tree_ops_t rt_compare_list_ops = {
|
||||
.rbto_compare_nodes = rt_compare_list,
|
||||
.rbto_compare_key = rt_compare_list,
|
||||
.rbto_node_offset = offsetof(struct rt, rt_tree),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
const rb_tree_ops_t rt_compare_proto_ops = {
|
||||
.rbto_compare_nodes = rt_compare_proto,
|
||||
.rbto_compare_key = rt_compare_proto,
|
||||
|
|
|
@ -96,6 +96,7 @@ struct rt {
|
|||
rb_node_t rt_tree;
|
||||
};
|
||||
|
||||
extern const rb_tree_ops_t rt_compare_list_ops;
|
||||
extern const rb_tree_ops_t rt_compare_proto_ops;
|
||||
|
||||
void rt_init(struct dhcpcd_ctx *);
|
||||
|
|
|
@ -288,11 +288,9 @@ sa_toprefix(const struct sockaddr *sa)
|
|||
#ifndef NDEBUG
|
||||
/* Ensure the calculation is correct */
|
||||
if (!sa_inprefix) {
|
||||
union sa_ss ss;
|
||||
union sa_ss ss = { .sa.sa_family = sa->sa_family };
|
||||
|
||||
sa_inprefix = true;
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.sa.sa_family = sa->sa_family;
|
||||
sa_fromprefix(&ss.sa, prefix);
|
||||
assert(sa_cmp(sa, &ss.sa) == 0);
|
||||
sa_inprefix = false;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
@ -172,12 +173,12 @@ efprintf(FILE *fp, const char *fmt, ...)
|
|||
return r;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
static long
|
||||
make_env(const struct interface *ifp, const char *reason)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
FILE *fp;
|
||||
char **env, **envp, *buf, *bufp, *endp, *path;
|
||||
char **env, **envp, *bufp, *endp, *path;
|
||||
size_t nenv;
|
||||
long buf_pos, i;
|
||||
int protocol = PROTO_LINK;
|
||||
|
@ -458,31 +459,38 @@ dumplease:
|
|||
logerr(__func__);
|
||||
goto eexit;
|
||||
}
|
||||
#ifdef HAVE_OPEN_MEMSTREAM
|
||||
buf = ctx->script_buf;
|
||||
#else
|
||||
|
||||
#ifndef HAVE_OPEN_MEMSTREAM
|
||||
size_t buf_len = (size_t)buf_pos;
|
||||
if (ctx->script_buflen < buf_len) {
|
||||
buf = realloc(ctx->script_buf, buf_len);
|
||||
char *buf = realloc(ctx->script_buf, buf_len);
|
||||
if (buf == NULL)
|
||||
goto eexit;
|
||||
ctx->script_buf = buf;
|
||||
ctx->script_buflen = buf_len;
|
||||
}
|
||||
buf = ctx->script_buf;
|
||||
rewind(fp);
|
||||
if (fread(buf, sizeof(char), buf_len, fp) != buf_len)
|
||||
if (fread(ctx->script_buf, sizeof(char), buf_len, fp) != buf_len)
|
||||
goto eexit;
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
#endif
|
||||
|
||||
/* Count the terminated env strings.
|
||||
* Assert that the terminations are correct. */
|
||||
nenv = 0;
|
||||
endp = buf + buf_pos;
|
||||
for (bufp = buf; bufp < endp; bufp++) {
|
||||
if (*bufp == '\0')
|
||||
endp = ctx->script_buf + buf_pos;
|
||||
for (bufp = ctx->script_buf; bufp < endp; bufp++) {
|
||||
if (*bufp == '\0') {
|
||||
#ifndef NDEBUG
|
||||
if (bufp + 1 < endp)
|
||||
assert(*(bufp + 1) != '\0');
|
||||
#endif
|
||||
nenv++;
|
||||
}
|
||||
}
|
||||
assert(*(bufp - 1) == '\0');
|
||||
|
||||
if (ctx->script_envlen < nenv) {
|
||||
env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
|
||||
if (env == NULL)
|
||||
|
@ -490,7 +498,8 @@ dumplease:
|
|||
ctx->script_env = env;
|
||||
ctx->script_envlen = nenv;
|
||||
}
|
||||
bufp = buf;
|
||||
|
||||
bufp = ctx->script_buf;
|
||||
envp = ctx->script_env;
|
||||
*envp++ = bufp++;
|
||||
endp--; /* Avoid setting the last \0 to an invalid pointer */
|
||||
|
@ -500,7 +509,7 @@ dumplease:
|
|||
}
|
||||
*envp = NULL;
|
||||
|
||||
return (ssize_t)nenv;
|
||||
return buf_pos - 1;
|
||||
|
||||
eexit:
|
||||
logerr(__func__);
|
||||
|
@ -516,10 +525,12 @@ send_interface1(struct fd_list *fd, const struct interface *ifp,
|
|||
const char *reason)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
long len;
|
||||
|
||||
if (make_env(ifp, reason) == -1)
|
||||
len = make_env(ifp, reason);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
return control_queue(fd, ctx->script_buf, ctx->script_buflen, 1);
|
||||
return control_queue(fd, ctx->script_buf, (size_t)len, 1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -636,8 +647,8 @@ send_listeners:
|
|||
TAILQ_FOREACH(fd, &ctx->control_fds, next) {
|
||||
if (!(fd->flags & FD_LISTEN))
|
||||
continue;
|
||||
if (control_queue(fd, ctx->script_buf, ctx->script_buflen, 1)
|
||||
== -1)
|
||||
if (control_queue(fd, ctx->script_buf, ctx->script_buflen,
|
||||
true) == -1)
|
||||
logerr("%s: control_queue", __func__);
|
||||
else
|
||||
status = 1;
|
||||
|
|
Loading…
Reference in New Issue