Sync with dhcpcd-9.3.0
This commit is contained in:
parent
32fe301ab8
commit
be38669a3c
|
@ -70,14 +70,14 @@
|
||||||
(insn)->jt = 0; \
|
(insn)->jt = 0; \
|
||||||
(insn)->jf = 0; \
|
(insn)->jf = 0; \
|
||||||
(insn)->k = (uint32_t)(v); \
|
(insn)->k = (uint32_t)(v); \
|
||||||
};
|
}
|
||||||
|
|
||||||
#define BPF_SET_JUMP(insn, c, v, t, f) { \
|
#define BPF_SET_JUMP(insn, c, v, t, f) { \
|
||||||
(insn)->code = (c); \
|
(insn)->code = (c); \
|
||||||
(insn)->jt = (t); \
|
(insn)->jt = (t); \
|
||||||
(insn)->jf = (f); \
|
(insn)->jf = (f); \
|
||||||
(insn)->k = (uint32_t)(v); \
|
(insn)->k = (uint32_t)(v); \
|
||||||
};
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
bpf_frame_header_len(const struct interface *ifp)
|
bpf_frame_header_len(const struct interface *ifp)
|
||||||
|
@ -585,9 +585,6 @@ static const struct bpf_insn bpf_bootp_ether[] = {
|
||||||
};
|
};
|
||||||
#define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether)
|
#define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether)
|
||||||
|
|
||||||
#define BOOTP_MIN_SIZE sizeof(struct ip) + sizeof(struct udphdr) + \
|
|
||||||
sizeof(struct bootp)
|
|
||||||
|
|
||||||
static const struct bpf_insn bpf_bootp_base[] = {
|
static const struct bpf_insn bpf_bootp_base[] = {
|
||||||
/* Make sure it's an IPv4 packet. */
|
/* Make sure it's an IPv4 packet. */
|
||||||
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
|
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
|
||||||
|
|
|
@ -1164,7 +1164,7 @@ read_lease(struct interface *ifp, struct bootp **bootp)
|
||||||
logdebugx("reading standard input");
|
logdebugx("reading standard input");
|
||||||
sbytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
|
sbytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
|
||||||
} else {
|
} else {
|
||||||
logdebugx("%s: reading lease `%s'",
|
logdebugx("%s: reading lease: %s",
|
||||||
ifp->name, state->leasefile);
|
ifp->name, state->leasefile);
|
||||||
sbytes = dhcp_readfile(ifp->ctx, state->leasefile,
|
sbytes = dhcp_readfile(ifp->ctx, state->leasefile,
|
||||||
buf.buf, sizeof(buf.buf));
|
buf.buf, sizeof(buf.buf));
|
||||||
|
@ -2314,7 +2314,7 @@ dhcp_bind(struct interface *ifp)
|
||||||
state->state = DHS_BOUND;
|
state->state = DHS_BOUND;
|
||||||
if (!state->lease.frominfo &&
|
if (!state->lease.frominfo &&
|
||||||
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) {
|
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) {
|
||||||
logdebugx("%s: writing lease `%s'",
|
logdebugx("%s: writing lease: %s",
|
||||||
ifp->name, state->leasefile);
|
ifp->name, state->leasefile);
|
||||||
if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
|
if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
|
||||||
state->new, state->new_len) == -1)
|
state->new, state->new_len) == -1)
|
||||||
|
@ -2865,10 +2865,10 @@ log_dhcp(int loglevel, const char *msg,
|
||||||
print_string(sname, sizeof(sname), OT_STRING | OT_DOMAIN,
|
print_string(sname, sizeof(sname), OT_STRING | OT_DOMAIN,
|
||||||
bootp->sname, sizeof(bootp->sname));
|
bootp->sname, sizeof(bootp->sname));
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
logmessage(loglevel, "%s: %s %s %s `%s'",
|
logmessage(loglevel, "%s: %s %s %s %s",
|
||||||
ifp->name, msg, tfrom, inet_ntoa(addr), sname);
|
ifp->name, msg, tfrom, inet_ntoa(addr), sname);
|
||||||
else
|
else
|
||||||
logmessage(loglevel, "%s: %s %s %s %s `%s'",
|
logmessage(loglevel, "%s: %s %s %s %s %s",
|
||||||
ifp->name, msg, a, tfrom, inet_ntoa(addr), sname);
|
ifp->name, msg, a, tfrom, inet_ntoa(addr), sname);
|
||||||
} else {
|
} else {
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
|
@ -3477,6 +3477,16 @@ dhcp_packet(struct interface *ifp, uint8_t *data, size_t len,
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
const struct dhcp_state *state = D_CSTATE(ifp);
|
const struct dhcp_state *state = D_CSTATE(ifp);
|
||||||
|
|
||||||
|
/* It's possible that an interface departs and arrives in short
|
||||||
|
* order to receive a BPF frame out of order.
|
||||||
|
* There is a similar check in ARP, but much lower down the stack.
|
||||||
|
* It's not needed for other inet protocols because we send the
|
||||||
|
* message as a whole and select the interface off that and then
|
||||||
|
* check state. BPF on the other hand is very interface
|
||||||
|
* specific and we do need this check. */
|
||||||
|
if (state == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Ignore double reads */
|
/* Ignore double reads */
|
||||||
if (IN_PRIVSEP(ifp->ctx)) {
|
if (IN_PRIVSEP(ifp->ctx)) {
|
||||||
switch (state->state) {
|
switch (state->state) {
|
||||||
|
|
|
@ -147,7 +147,7 @@ struct dhcp_compat {
|
||||||
uint16_t dhcp6_opt;
|
uint16_t dhcp6_opt;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct dhcp_compat dhcp_compats[] = {
|
static const struct dhcp_compat dhcp_compats[] = {
|
||||||
{ DHO_DNSSERVER, D6_OPTION_DNS_SERVERS },
|
{ DHO_DNSSERVER, D6_OPTION_DNS_SERVERS },
|
||||||
{ DHO_HOSTNAME, D6_OPTION_FQDN },
|
{ DHO_HOSTNAME, D6_OPTION_FQDN },
|
||||||
{ DHO_DNSDOMAIN, D6_OPTION_FQDN },
|
{ DHO_DNSDOMAIN, D6_OPTION_FQDN },
|
||||||
|
@ -2588,7 +2588,7 @@ dhcp6_readlease(struct interface *ifp, int validate)
|
||||||
logdebugx("reading standard input");
|
logdebugx("reading standard input");
|
||||||
bytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
|
bytes = read(fileno(stdin), buf.buf, sizeof(buf.buf));
|
||||||
} else {
|
} else {
|
||||||
logdebugx("%s: reading lease `%s'",
|
logdebugx("%s: reading lease: %s",
|
||||||
ifp->name, state->leasefile);
|
ifp->name, state->leasefile);
|
||||||
bytes = dhcp_readfile(ifp->ctx, state->leasefile,
|
bytes = dhcp_readfile(ifp->ctx, state->leasefile,
|
||||||
buf.buf, sizeof(buf.buf));
|
buf.buf, sizeof(buf.buf));
|
||||||
|
@ -3218,7 +3218,7 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
|
||||||
ifp->name, state->expire);
|
ifp->name, state->expire);
|
||||||
rt_build(ifp->ctx, AF_INET6);
|
rt_build(ifp->ctx, AF_INET6);
|
||||||
if (!confirmed && !timedout) {
|
if (!confirmed && !timedout) {
|
||||||
logdebugx("%s: writing lease `%s'",
|
logdebugx("%s: writing lease: %s",
|
||||||
ifp->name, state->leasefile);
|
ifp->name, state->leasefile);
|
||||||
if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
|
if (dhcp_writefile(ifp->ctx, state->leasefile, 0640,
|
||||||
state->new, state->new_len) == -1)
|
state->new, state->new_len) == -1)
|
||||||
|
@ -3657,12 +3657,12 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia)
|
||||||
"/tmp/dhcp6.reply%d.raw", replyn++);
|
"/tmp/dhcp6.reply%d.raw", replyn++);
|
||||||
fd = open(fname, O_RDONLY, 0);
|
fd = open(fname, O_RDONLY, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
logerr("%s: open `%s'", __func__, fname);
|
logerr("%s: open: %s", __func__, fname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tlen = read(fd, tbuf, sizeof(tbuf));
|
tlen = read(fd, tbuf, sizeof(tbuf));
|
||||||
if (tlen == -1)
|
if (tlen == -1)
|
||||||
logerr("%s: read `%s'", __func__, fname);
|
logerr("%s: read: %s", __func__, fname);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
/* Copy across ServerID so we can work with our own server. */
|
/* Copy across ServerID so we can work with our own server. */
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples";
|
static const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples";
|
||||||
|
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
@ -360,7 +360,7 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Don't use loginfo because this makes no sense in a log. */
|
/* Don't use loginfo because this makes no sense in a log. */
|
||||||
if (!(logopts & LOGERR_QUIET))
|
if (!(logopts & LOGERR_QUIET) && ctx->stderr_valid)
|
||||||
(void)fprintf(stderr,
|
(void)fprintf(stderr,
|
||||||
"forked to background, child pid %d\n", getpid());
|
"forked to background, child pid %d\n", getpid());
|
||||||
i = EXIT_SUCCESS;
|
i = EXIT_SUCCESS;
|
||||||
|
@ -432,8 +432,6 @@ stop_interface(struct interface *ifp)
|
||||||
/* De-activate the interface */
|
/* De-activate the interface */
|
||||||
ifp->active = IF_INACTIVE;
|
ifp->active = IF_INACTIVE;
|
||||||
ifp->options->options &= ~DHCPCD_STOPPING;
|
ifp->options->options &= ~DHCPCD_STOPPING;
|
||||||
/* Set the link state to unknown as we're no longer tracking it. */
|
|
||||||
ifp->carrier = LINK_UNKNOWN;
|
|
||||||
|
|
||||||
if (!(ctx->options & (DHCPCD_MASTER | DHCPCD_TEST)))
|
if (!(ctx->options & (DHCPCD_MASTER | DHCPCD_TEST)))
|
||||||
eloop_exit(ctx->eloop, EXIT_FAILURE);
|
eloop_exit(ctx->eloop, EXIT_FAILURE);
|
||||||
|
@ -700,43 +698,36 @@ dhcpcd_reportssid(struct interface *ifp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
loginfox("%s: connected to Access Point `%s'", ifp->name, pssid);
|
loginfox("%s: connected to Access Point: %s", ifp->name, pssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
|
dhcpcd_handlecarrier(struct interface *ifp, int carrier, unsigned int flags)
|
||||||
const char *ifname)
|
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
bool nolink = ifp->options == NULL ||
|
||||||
|
!(ifp->options->options & DHCPCD_LINK);
|
||||||
ifp = if_find(ctx->ifaces, ifname);
|
|
||||||
if (ifp == NULL ||
|
|
||||||
ifp->options == NULL || !(ifp->options->options & DHCPCD_LINK) ||
|
|
||||||
!ifp->active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
ifp->flags = flags;
|
||||||
if (carrier == LINK_UNKNOWN) {
|
if (carrier == LINK_UNKNOWN) {
|
||||||
if (ifp->wireless) {
|
if (ifp->wireless)
|
||||||
carrier = LINK_DOWN;
|
carrier = LINK_DOWN;
|
||||||
ifp->flags = flags;
|
else
|
||||||
} else
|
|
||||||
carrier = if_carrier(ifp);
|
|
||||||
} else
|
|
||||||
ifp->flags = flags;
|
|
||||||
if (carrier == LINK_UNKNOWN)
|
|
||||||
carrier = IF_UPANDRUNNING(ifp) ? LINK_UP : LINK_DOWN;
|
carrier = IF_UPANDRUNNING(ifp) ? LINK_UP : LINK_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
|
if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
|
||||||
if (ifp->carrier != LINK_DOWN) {
|
if (ifp->carrier != LINK_DOWN) {
|
||||||
if (ifp->carrier == LINK_UP)
|
|
||||||
loginfox("%s: carrier lost", ifp->name);
|
|
||||||
#ifdef NOCARRIER_PRESERVE_IP
|
#ifdef NOCARRIER_PRESERVE_IP
|
||||||
if (ifp->flags & IFF_UP &&
|
if (ifp->flags & IFF_UP &&
|
||||||
!(ifp->options->options & DHCPCD_ANONYMOUS))
|
(ifp->options == NULL ||
|
||||||
|
!(ifp->options->options & DHCPCD_ANONYMOUS)))
|
||||||
ifp->carrier = LINK_DOWN_IFFUP;
|
ifp->carrier = LINK_DOWN_IFFUP;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ifp->carrier = LINK_DOWN;
|
ifp->carrier = LINK_DOWN;
|
||||||
|
if (!ifp->active || nolink)
|
||||||
|
return;
|
||||||
|
loginfox("%s: carrier lost", ifp->name);
|
||||||
script_runreason(ifp, "NOCARRIER");
|
script_runreason(ifp, "NOCARRIER");
|
||||||
#ifdef NOCARRIER_PRESERVE_IP
|
#ifdef NOCARRIER_PRESERVE_IP
|
||||||
if (ifp->flags & IFF_UP &&
|
if (ifp->flags & IFF_UP &&
|
||||||
|
@ -767,13 +758,14 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
|
||||||
}
|
}
|
||||||
} else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
|
} else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
|
||||||
if (ifp->carrier != LINK_UP) {
|
if (ifp->carrier != LINK_UP) {
|
||||||
loginfox("%s: carrier acquired", ifp->name);
|
|
||||||
ifp->carrier = LINK_UP;
|
ifp->carrier = LINK_UP;
|
||||||
|
if (ifp->active)
|
||||||
|
loginfox("%s: carrier acquired", ifp->name);
|
||||||
#if !defined(__linux__) && !defined(__NetBSD__)
|
#if !defined(__linux__) && !defined(__NetBSD__)
|
||||||
/* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
|
/* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
|
||||||
* hardware address changes so we have to go
|
* hardware address changes so we have to go
|
||||||
* through the disovery process to work it out. */
|
* through the disovery process to work it out. */
|
||||||
dhcpcd_handleinterface(ctx, 0, ifp->name);
|
dhcpcd_handleinterface(ifp->ctx, 0, ifp->name);
|
||||||
#endif
|
#endif
|
||||||
if (ifp->wireless) {
|
if (ifp->wireless) {
|
||||||
uint8_t ossid[IF_SSIDLEN];
|
uint8_t ossid[IF_SSIDLEN];
|
||||||
|
@ -784,8 +776,9 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
|
||||||
if_getssid(ifp);
|
if_getssid(ifp);
|
||||||
|
|
||||||
/* If we changed SSID network, drop leases */
|
/* If we changed SSID network, drop leases */
|
||||||
if (ifp->ssid_len != olen ||
|
if ((ifp->ssid_len != olen ||
|
||||||
memcmp(ifp->ssid, ossid, ifp->ssid_len))
|
memcmp(ifp->ssid, ossid, ifp->ssid_len)) &&
|
||||||
|
ifp->active)
|
||||||
{
|
{
|
||||||
dhcpcd_reportssid(ifp);
|
dhcpcd_reportssid(ifp);
|
||||||
#ifdef NOCARRIER_PRESERVE_IP
|
#ifdef NOCARRIER_PRESERVE_IP
|
||||||
|
@ -796,6 +789,8 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!ifp->active || nolink)
|
||||||
|
return;
|
||||||
dhcpcd_initstate(ifp, 0);
|
dhcpcd_initstate(ifp, 0);
|
||||||
script_runreason(ifp, "CARRIER");
|
script_runreason(ifp, "CARRIER");
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
|
@ -871,20 +866,11 @@ dhcpcd_startinterface(void *arg)
|
||||||
struct interface *ifp = arg;
|
struct interface *ifp = arg;
|
||||||
struct if_options *ifo = ifp->options;
|
struct if_options *ifo = ifp->options;
|
||||||
|
|
||||||
if (ifo->options & DHCPCD_LINK) {
|
if (ifo->options & DHCPCD_LINK && (ifp->carrier == LINK_DOWN ||
|
||||||
switch (ifp->carrier) {
|
(ifp->carrier == LINK_UNKNOWN && !IF_UPANDRUNNING(ifp))))
|
||||||
case LINK_UP:
|
{
|
||||||
break;
|
|
||||||
case LINK_DOWN:
|
|
||||||
loginfox("%s: waiting for carrier", ifp->name);
|
loginfox("%s: waiting for carrier", ifp->name);
|
||||||
return;
|
return;
|
||||||
case LINK_UNKNOWN:
|
|
||||||
/* No media state available.
|
|
||||||
* Loop until both IFF_UP and IFF_RUNNING are set */
|
|
||||||
if (ifo->poll == 0)
|
|
||||||
if_pollinit(ifp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
|
if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
|
||||||
|
@ -993,9 +979,6 @@ dhcpcd_prestartinterface(void *arg)
|
||||||
logerr(__func__);
|
logerr(__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifp->options->poll != 0)
|
|
||||||
if_pollinit(ifp);
|
|
||||||
|
|
||||||
dhcpcd_startinterface(ifp);
|
dhcpcd_startinterface(ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,14 +1017,13 @@ dhcpcd_activateinterface(struct interface *ifp, unsigned long long options)
|
||||||
int
|
int
|
||||||
dhcpcd_handleinterface(void *arg, int action, const char *ifname)
|
dhcpcd_handleinterface(void *arg, int action, const char *ifname)
|
||||||
{
|
{
|
||||||
struct dhcpcd_ctx *ctx;
|
struct dhcpcd_ctx *ctx = arg;
|
||||||
struct ifaddrs *ifaddrs;
|
struct ifaddrs *ifaddrs;
|
||||||
struct if_head *ifs;
|
struct if_head *ifs;
|
||||||
struct interface *ifp, *iff;
|
struct interface *ifp, *iff;
|
||||||
const char * const argv[] = { ifname };
|
const char * const argv[] = { ifname };
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
ctx = arg;
|
|
||||||
if (action == -1) {
|
if (action == -1) {
|
||||||
ifp = if_find(ctx->ifaces, ifname);
|
ifp = if_find(ctx->ifaces, ifname);
|
||||||
if (ifp == NULL) {
|
if (ifp == NULL) {
|
||||||
|
@ -1131,14 +1113,14 @@ dhcpcd_handlelink(void *arg)
|
||||||
static void
|
static void
|
||||||
dhcpcd_checkcarrier(void *arg)
|
dhcpcd_checkcarrier(void *arg)
|
||||||
{
|
{
|
||||||
struct interface *ifp = arg;
|
struct interface *ifp0 = arg, *ifp;
|
||||||
int carrier;
|
|
||||||
|
|
||||||
/* Check carrier here rather than setting LINK_UNKNOWN.
|
ifp = if_find(ifp0->ctx->ifaces, ifp0->name);
|
||||||
* This is because we force LINK_UNKNOWN as down for wireless which
|
if (ifp == NULL || ifp->carrier == ifp0->carrier)
|
||||||
* we do not want when dealing with a route socket overflow. */
|
return;
|
||||||
carrier = if_carrier(ifp);
|
|
||||||
dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
|
dhcpcd_handlecarrier(ifp, ifp0->carrier, ifp0->flags);
|
||||||
|
if_free(ifp0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SMALL
|
#ifndef SMALL
|
||||||
|
@ -1224,10 +1206,10 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
|
||||||
ifp1 = if_find(ctx->ifaces, ifp->name);
|
ifp1 = if_find(ctx->ifaces, ifp->name);
|
||||||
if (ifp1 != NULL) {
|
if (ifp1 != NULL) {
|
||||||
/* If the interface already exists,
|
/* If the interface already exists,
|
||||||
* check carrier state. */
|
* check carrier state.
|
||||||
|
* dhcpcd_checkcarrier will free ifp. */
|
||||||
eloop_timeout_add_sec(ctx->eloop, 0,
|
eloop_timeout_add_sec(ctx->eloop, 0,
|
||||||
dhcpcd_checkcarrier, ifp1);
|
dhcpcd_checkcarrier, ifp);
|
||||||
if_free(ifp);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
|
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
|
||||||
|
@ -1417,17 +1399,9 @@ dhcpcd_signal_cb(int sig, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
|
if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
|
||||||
if (sig == SIGHUP)
|
if (sig != SIGHUP &&
|
||||||
return;
|
write(ctx->fork_fd, &sig, sizeof(sig)) == -1)
|
||||||
|
logerr("%s: write", __func__);
|
||||||
pid_t pid = pidfile_read(ctx->pidfile);
|
|
||||||
if (pid == -1) {
|
|
||||||
if (errno != ENOENT)
|
|
||||||
logerr("%s: pidfile_read",__func__);
|
|
||||||
} else if (pid == 0)
|
|
||||||
logerr("%s: pid cannot be zero", __func__);
|
|
||||||
else if (kill(pid, sig) == -1)
|
|
||||||
logerr("%s: kill", __func__);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1780,7 +1754,10 @@ dhcpcd_fork_cb(void *arg)
|
||||||
__func__, len, sizeof(exit_code));
|
__func__, len, sizeof(exit_code));
|
||||||
exit_code = EXIT_FAILURE;
|
exit_code = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (ctx->options & DHCPCD_FORKED)
|
||||||
eloop_exit(ctx->eloop, exit_code);
|
eloop_exit(ctx->eloop, exit_code);
|
||||||
|
else
|
||||||
|
dhcpcd_signal_cb(exit_code, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1893,9 +1870,16 @@ main(int argc, char **argv)
|
||||||
ctx.ps_inet_fd = ctx.ps_control_fd = -1;
|
ctx.ps_inet_fd = ctx.ps_control_fd = -1;
|
||||||
TAILQ_INIT(&ctx.ps_processes);
|
TAILQ_INIT(&ctx.ps_processes);
|
||||||
#endif
|
#endif
|
||||||
rt_init(&ctx);
|
|
||||||
|
|
||||||
logopts = LOGERR_ERR|LOGERR_LOG|LOGERR_LOG_DATE|LOGERR_LOG_PID;
|
/* Check our streams for validity */
|
||||||
|
ctx.stdin_valid = fcntl(STDIN_FILENO, F_GETFD) != -1;
|
||||||
|
ctx.stdout_valid = fcntl(STDOUT_FILENO, F_GETFD) != -1;
|
||||||
|
ctx.stderr_valid = fcntl(STDERR_FILENO, F_GETFD) != -1;
|
||||||
|
|
||||||
|
logopts = LOGERR_LOG | LOGERR_LOG_DATE | LOGERR_LOG_PID;
|
||||||
|
if (ctx.stderr_valid)
|
||||||
|
logopts |= LOGERR_ERR;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((opt = getopt_long(argc, argv,
|
while ((opt = getopt_long(argc, argv,
|
||||||
ctx.options & DHCPCD_PRINT_PIDFILE ? NOERR_IF_OPTS : IF_OPTS,
|
ctx.options & DHCPCD_PRINT_PIDFILE ? NOERR_IF_OPTS : IF_OPTS,
|
||||||
|
@ -1979,6 +1963,8 @@ main(int argc, char **argv)
|
||||||
ctx.ifc = argc - optind;
|
ctx.ifc = argc - optind;
|
||||||
ctx.ifv = argv + optind;
|
ctx.ifv = argv + optind;
|
||||||
|
|
||||||
|
rt_init(&ctx);
|
||||||
|
|
||||||
ifo = read_config(&ctx, NULL, NULL, NULL);
|
ifo = read_config(&ctx, NULL, NULL, NULL);
|
||||||
if (ifo == NULL) {
|
if (ifo == NULL) {
|
||||||
if (ctx.options & DHCPCD_PRINT_PIDFILE)
|
if (ctx.options & DHCPCD_PRINT_PIDFILE)
|
||||||
|
@ -2080,7 +2066,7 @@ printpidfile:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chdir("/") == -1)
|
if (chdir("/") == -1)
|
||||||
logerr("%s: chdir `/'", __func__);
|
logerr("%s: chdir: /", __func__);
|
||||||
|
|
||||||
/* Freeing allocated addresses from dumping leases can trigger
|
/* Freeing allocated addresses from dumping leases can trigger
|
||||||
* eloop removals as well, so init here. */
|
* eloop removals as well, so init here. */
|
||||||
|
@ -2147,7 +2133,7 @@ printpidfile:
|
||||||
{
|
{
|
||||||
ctx.options |= DHCPCD_FORKED; /* pretend child process */
|
ctx.options |= DHCPCD_FORKED; /* pretend child process */
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
|
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, NULL) == -1)
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
#endif
|
#endif
|
||||||
ifp = calloc(1, sizeof(*ifp));
|
ifp = calloc(1, sizeof(*ifp));
|
||||||
|
@ -2199,12 +2185,9 @@ printpidfile:
|
||||||
ctx.options & DHCPCD_DUMPLEASE);
|
ctx.options & DHCPCD_DUMPLEASE);
|
||||||
if (ctx.control_fd != -1) {
|
if (ctx.control_fd != -1) {
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
ctx.options &= ~DHCPCD_FORKED;
|
if (IN_PRIVSEP(&ctx) &&
|
||||||
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) {
|
ps_mastersandbox(&ctx, NULL) == -1)
|
||||||
ctx.options |= DHCPCD_FORKED;
|
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
|
||||||
ctx.options |= DHCPCD_FORKED;
|
|
||||||
#endif
|
#endif
|
||||||
if (!(ctx.options & DHCPCD_DUMPLEASE))
|
if (!(ctx.options & DHCPCD_DUMPLEASE))
|
||||||
loginfox("sending commands to dhcpcd process");
|
loginfox("sending commands to dhcpcd process");
|
||||||
|
@ -2240,9 +2223,9 @@ printpidfile:
|
||||||
if (!(ctx.options & DHCPCD_TEST)) {
|
if (!(ctx.options & DHCPCD_TEST)) {
|
||||||
/* Ensure we have the needed directories */
|
/* Ensure we have the needed directories */
|
||||||
if (mkdir(DBDIR, 0750) == -1 && errno != EEXIST)
|
if (mkdir(DBDIR, 0750) == -1 && errno != EEXIST)
|
||||||
logerr("%s: mkdir `%s'", __func__, DBDIR);
|
logerr("%s: mkdir: %s", __func__, DBDIR);
|
||||||
if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
|
if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
|
||||||
logerr("%s: mkdir `%s'", __func__, RUNDIR);
|
logerr("%s: mkdir: %s", __func__, RUNDIR);
|
||||||
if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
|
if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
logerr("%s: pidfile_lock: %s",
|
logerr("%s: pidfile_lock: %s",
|
||||||
|
@ -2256,12 +2239,13 @@ printpidfile:
|
||||||
}
|
}
|
||||||
|
|
||||||
loginfox(PACKAGE "-" VERSION " starting");
|
loginfox(PACKAGE "-" VERSION " starting");
|
||||||
if (freopen(_PATH_DEVNULL, "r", stdin) == NULL)
|
if (ctx.stdin_valid && freopen(_PATH_DEVNULL, "w", stdin) == NULL)
|
||||||
logerr("%s: freopen stdin", __func__);
|
logwarn("freopen stdin");
|
||||||
|
|
||||||
#if defined(USE_SIGNALS) && !defined(THERE_IS_NO_FORK)
|
#if defined(USE_SIGNALS) && !defined(THERE_IS_NO_FORK)
|
||||||
if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fork_fd) == -1 ||
|
if (xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fork_fd) == -1 ||
|
||||||
xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, stderr_fd) == -1)
|
(ctx.stderr_valid &&
|
||||||
|
xsocketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, stderr_fd) == -1))
|
||||||
{
|
{
|
||||||
logerr("socketpair");
|
logerr("socketpair");
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
|
@ -2279,20 +2263,25 @@ printpidfile:
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Redirect stderr to the stderr socketpair.
|
* Redirect stderr to the stderr socketpair.
|
||||||
* Redirect stdout as well.
|
* Redirect stdout as well.
|
||||||
* dhcpcd doesn't output via stdout, but something in
|
* dhcpcd doesn't output via stdout, but something in
|
||||||
* a called script might.
|
* a called script might.
|
||||||
*
|
|
||||||
* Do NOT rights limit this fd as it will affect scripts.
|
|
||||||
* For example, cmp reports insufficient caps on FreeBSD.
|
|
||||||
*/
|
*/
|
||||||
|
if (ctx.stderr_valid) {
|
||||||
if (dup2(stderr_fd[1], STDERR_FILENO) == -1 ||
|
if (dup2(stderr_fd[1], STDERR_FILENO) == -1 ||
|
||||||
dup2(stderr_fd[1], STDOUT_FILENO) == -1)
|
(ctx.stdout_valid &&
|
||||||
|
dup2(stderr_fd[1], STDOUT_FILENO) == -1))
|
||||||
logerr("dup2");
|
logerr("dup2");
|
||||||
close(stderr_fd[0]);
|
close(stderr_fd[0]);
|
||||||
close(stderr_fd[1]);
|
close(stderr_fd[1]);
|
||||||
|
} else if (ctx.stdout_valid) {
|
||||||
|
if (freopen(_PATH_DEVNULL, "w", stdout) == NULL)
|
||||||
|
logerr("freopen stdout");
|
||||||
|
}
|
||||||
if (setsid() == -1) {
|
if (setsid() == -1) {
|
||||||
logerr("%s: setsid", __func__);
|
logerr("%s: setsid", __func__);
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
|
@ -2311,11 +2300,10 @@ printpidfile:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ctx.options |= DHCPCD_FORKED; /* A lie */
|
setproctitle("[launcher]");
|
||||||
|
ctx.options |= DHCPCD_FORKED;
|
||||||
ctx.fork_fd = fork_fd[0];
|
ctx.fork_fd = fork_fd[0];
|
||||||
close(fork_fd[1]);
|
close(fork_fd[1]);
|
||||||
ctx.stderr_fd = stderr_fd[0];
|
|
||||||
close(stderr_fd[1]);
|
|
||||||
#ifdef PRIVSEP_RIGHTS
|
#ifdef PRIVSEP_RIGHTS
|
||||||
if (ps_rights_limit_fd(fork_fd[0]) == -1 ||
|
if (ps_rights_limit_fd(fork_fd[0]) == -1 ||
|
||||||
ps_rights_limit_fd(stderr_fd[0]) == 1)
|
ps_rights_limit_fd(stderr_fd[0]) == 1)
|
||||||
|
@ -2324,10 +2312,25 @@ printpidfile:
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setproctitle("[launcher]");
|
|
||||||
eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
|
eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
|
||||||
eloop_event_add(ctx.eloop, ctx.stderr_fd, dhcpcd_stderr_cb,
|
|
||||||
&ctx);
|
if (ctx.stderr_valid) {
|
||||||
|
ctx.stderr_fd = stderr_fd[0];
|
||||||
|
close(stderr_fd[1]);
|
||||||
|
#ifdef PRIVSEP_RIGHTS
|
||||||
|
if (ps_rights_limit_fd(stderr_fd[0]) == 1) {
|
||||||
|
logerr("ps_rights_limit_fdpair");
|
||||||
|
goto exit_failure;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (ctx.stderr_valid)
|
||||||
|
eloop_event_add(ctx.eloop, ctx.stderr_fd,
|
||||||
|
dhcpcd_stderr_cb, &ctx);
|
||||||
|
}
|
||||||
|
#ifdef PRIVSEP
|
||||||
|
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, NULL) == -1)
|
||||||
|
goto exit_failure;
|
||||||
|
#endif
|
||||||
goto run_loop;
|
goto run_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2336,10 +2339,16 @@ printpidfile:
|
||||||
ctx.options |= DHCPCD_STARTED;
|
ctx.options |= DHCPCD_STARTED;
|
||||||
if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
|
if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
|
||||||
logerr("%s: pidfile_lock %d", __func__, pid);
|
logerr("%s: pidfile_lock %d", __func__, pid);
|
||||||
|
#ifdef PRIVSEP
|
||||||
|
/* privsep has not started ... */
|
||||||
|
ctx.options &= ~DHCPCD_PRIVSEP;
|
||||||
|
#endif
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
os_init();
|
||||||
|
|
||||||
#if defined(BSD) && defined(INET6)
|
#if defined(BSD) && defined(INET6)
|
||||||
/* Disable the kernel RTADV sysctl as early as possible. */
|
/* Disable the kernel RTADV sysctl as early as possible. */
|
||||||
if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
|
if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
|
||||||
|
@ -2399,7 +2408,7 @@ printpidfile:
|
||||||
eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
|
eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
|
||||||
|
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
|
if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, "stdio route") == -1)
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2525,6 +2534,9 @@ exit1:
|
||||||
#endif
|
#endif
|
||||||
freeifaddrs(ifaddrs);
|
freeifaddrs(ifaddrs);
|
||||||
}
|
}
|
||||||
|
/* ps_stop will clear DHCPCD_PRIVSEP but we need to
|
||||||
|
* remember it to avoid attemping to remove the pidfile */
|
||||||
|
oi = ctx.options & DHCPCD_PRIVSEP ? 1 : 0;
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
ps_stop(&ctx);
|
ps_stop(&ctx);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2573,14 +2585,14 @@ exit1:
|
||||||
setproctitle_free();
|
setproctitle_free();
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SIGNALS
|
#ifdef USE_SIGNALS
|
||||||
if (ctx.options & DHCPCD_FORKED)
|
if (ctx.options & DHCPCD_STARTED) {
|
||||||
_exit(i); /* so atexit won't remove our pidfile */
|
|
||||||
else if (ctx.options & DHCPCD_STARTED) {
|
|
||||||
/* Try to detach from the launch process. */
|
/* Try to detach from the launch process. */
|
||||||
if (ctx.fork_fd != -1 &&
|
if (ctx.fork_fd != -1 &&
|
||||||
write(ctx.fork_fd, &i, sizeof(i)) == -1)
|
write(ctx.fork_fd, &i, sizeof(i)) == -1)
|
||||||
logerr("%s: write", __func__);
|
logerr("%s: write", __func__);
|
||||||
}
|
}
|
||||||
|
if (ctx.options & DHCPCD_FORKED || oi != 0)
|
||||||
|
_exit(i); /* so atexit won't remove our pidfile */
|
||||||
#endif
|
#endif
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,7 @@ static const char * const ifnames_ignore[] = {
|
||||||
"fwe", /* Firewire */
|
"fwe", /* Firewire */
|
||||||
"fwip", /* Firewire */
|
"fwip", /* Firewire */
|
||||||
"tap",
|
"tap",
|
||||||
|
"vether",
|
||||||
"xvif", /* XEN DOM0 -> guest interface */
|
"xvif", /* XEN DOM0 -> guest interface */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -121,6 +122,12 @@ struct rtm
|
||||||
char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
|
char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
os_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
if_init(__unused struct interface *iface)
|
if_init(__unused struct interface *iface)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +215,13 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
||||||
#warning kernel does not support route message filtering
|
#warning kernel does not support route message filtering
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PRIVSEP_RIGHTS
|
||||||
|
/* We need to getsockopt for SO_RCVBUF and
|
||||||
|
* setsockopt for RO_MISSFILTER. */
|
||||||
|
if (IN_PRIVSEP(ctx))
|
||||||
|
ps_rights_limit_fd_sockopt(ctx->link_fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,21 +367,40 @@ if_ignore(struct dhcpcd_ctx *ctx, const char *ifname)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int if_indirect_ioctl(struct dhcpcd_ctx *ctx,
|
||||||
if_carrier(struct interface *ifp)
|
const char *ifname, unsigned long cmd, void *data, size_t len)
|
||||||
{
|
{
|
||||||
struct ifmediareq ifmr = { .ifm_status = 0 };
|
struct ifreq ifr = { .ifr_flags = 0 };
|
||||||
|
|
||||||
/* Not really needed, but the other OS update flags here also */
|
#if defined(PRIVSEP) && (defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE))
|
||||||
if (if_getflags(ifp) == -1)
|
if (IN_PRIVSEP(ctx))
|
||||||
|
return (int)ps_root_indirectioctl(ctx, cmd, ifname, data, len);
|
||||||
|
#else
|
||||||
|
UNUSED(len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
ifr.ifr_data = data;
|
||||||
|
return ioctl(ctx->pf_inet_fd, cmd, &ifr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
if_carrier(__unused struct interface *ifp, const void *ifadata)
|
||||||
|
{
|
||||||
|
const struct if_data *ifi = ifadata;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Every BSD returns this and it is the sole source of truth.
|
||||||
|
* Not all BSD's support SIOCGIFDATA and not all interfaces
|
||||||
|
* support SIOCGIFMEDIA.
|
||||||
|
*/
|
||||||
|
assert(ifadata != NULL);
|
||||||
|
|
||||||
|
if (ifi->ifi_link_state >= LINK_STATE_UP)
|
||||||
|
return LINK_UP;
|
||||||
|
if (ifi->ifi_link_state == LINK_STATE_UNKNOWN)
|
||||||
return LINK_UNKNOWN;
|
return LINK_UNKNOWN;
|
||||||
|
return LINK_DOWN;
|
||||||
strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
|
|
||||||
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 ||
|
|
||||||
!(ifmr.ifm_status & IFM_AVALID))
|
|
||||||
return LINK_UNKNOWN;
|
|
||||||
|
|
||||||
return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -381,25 +414,6 @@ if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
|
||||||
sdl->sdl_index = (unsigned short)ifp->index;
|
sdl->sdl_index = (unsigned short)ifp->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SIOCG80211NWID) || defined(SIOCGETVLAN)
|
|
||||||
static int if_indirect_ioctl(struct dhcpcd_ctx *ctx,
|
|
||||||
const char *ifname, unsigned long cmd, void *data, size_t len)
|
|
||||||
{
|
|
||||||
struct ifreq ifr = { .ifr_flags = 0 };
|
|
||||||
|
|
||||||
#if defined(PRIVSEP) && defined(HAVE_PLEDGE)
|
|
||||||
if (IN_PRIVSEP(ctx))
|
|
||||||
return (int)ps_root_indirectioctl(ctx, cmd, ifname, data, len);
|
|
||||||
#else
|
|
||||||
UNUSED(len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
|
||||||
ifr.ifr_data = data;
|
|
||||||
return ioctl(ctx->pf_inet_fd, cmd, &ifr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
if_getssid1(struct dhcpcd_ctx *ctx, const char *ifname, void *ssid)
|
if_getssid1(struct dhcpcd_ctx *ctx, const char *ifname, void *ssid)
|
||||||
{
|
{
|
||||||
|
@ -1186,24 +1200,8 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
|
||||||
if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
|
if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (ifm->ifm_data.ifi_link_state) {
|
link_state = if_carrier(ifp, &ifm->ifm_data);
|
||||||
case LINK_STATE_UNKNOWN:
|
dhcpcd_handlecarrier(ifp, link_state, (unsigned int)ifm->ifm_flags);
|
||||||
link_state = LINK_UNKNOWN;
|
|
||||||
break;
|
|
||||||
#ifdef LINK_STATE_FULL_DUPLEX
|
|
||||||
case LINK_STATE_HALF_DUPLEX: /* FALLTHROUGH */
|
|
||||||
case LINK_STATE_FULL_DUPLEX: /* FALLTHROUGH */
|
|
||||||
#endif
|
|
||||||
case LINK_STATE_UP:
|
|
||||||
link_state = LINK_UP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
link_state = LINK_DOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dhcpcd_handlecarrier(ctx, link_state,
|
|
||||||
(unsigned int)ifm->ifm_flags, ifp->name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "dhcp6.h"
|
#include "dhcp6.h"
|
||||||
#include "dhcpcd-embedded.h"
|
#include "dhcpcd-embedded.h"
|
||||||
|
#include "duid.h"
|
||||||
#include "if.h"
|
#include "if.h"
|
||||||
#include "if-options.h"
|
#include "if-options.h"
|
||||||
#include "ipv4.h"
|
#include "ipv4.h"
|
||||||
|
@ -94,7 +95,7 @@ const struct option cf_options[] = {
|
||||||
{"noarp", no_argument, NULL, 'A'},
|
{"noarp", no_argument, NULL, 'A'},
|
||||||
{"nobackground", no_argument, NULL, 'B'},
|
{"nobackground", no_argument, NULL, 'B'},
|
||||||
{"nohook", required_argument, NULL, 'C'},
|
{"nohook", required_argument, NULL, 'C'},
|
||||||
{"duid", no_argument, NULL, 'D'},
|
{"duid", optional_argument, NULL, 'D'},
|
||||||
{"lastlease", no_argument, NULL, 'E'},
|
{"lastlease", no_argument, NULL, 'E'},
|
||||||
{"fqdn", optional_argument, NULL, 'F'},
|
{"fqdn", optional_argument, NULL, 'F'},
|
||||||
{"nogateway", no_argument, NULL, 'G'},
|
{"nogateway", no_argument, NULL, 'G'},
|
||||||
|
@ -164,7 +165,6 @@ const struct option cf_options[] = {
|
||||||
{"inactive", no_argument, NULL, O_INACTIVE},
|
{"inactive", no_argument, NULL, O_INACTIVE},
|
||||||
{"mudurl", required_argument, NULL, O_MUDURL},
|
{"mudurl", required_argument, NULL, O_MUDURL},
|
||||||
{"link_rcvbuf", required_argument, NULL, O_LINK_RCVBUF},
|
{"link_rcvbuf", required_argument, NULL, O_LINK_RCVBUF},
|
||||||
{"poll", optional_argument, NULL, O_POLL},
|
|
||||||
{NULL, 0, NULL, '\0'}
|
{NULL, 0, NULL, '\0'}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -460,13 +460,13 @@ parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
|
||||||
if (e != 0 ||
|
if (e != 0 ||
|
||||||
(net != NULL && inet_cidrtoaddr((int)i, net) != 0))
|
(net != NULL && inet_cidrtoaddr((int)i, net) != 0))
|
||||||
{
|
{
|
||||||
logerrx("`%s' is not a valid CIDR", p);
|
logerrx("invalid CIDR: %s", p);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr != NULL && inet_aton(arg, addr) == 0) {
|
if (addr != NULL && inet_aton(arg, addr) == 0) {
|
||||||
logerrx("`%s' is not a valid IP address", arg);
|
logerrx("invalid IP address: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
|
@ -788,7 +788,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
|
make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
|
||||||
make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
|
make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
|
||||||
{
|
{
|
||||||
logerrx("unknown option `%s'", arg);
|
logerrx("unknown option: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -800,7 +800,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
|
make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
|
||||||
make_option_mask(d, dl, od, odl, require, arg, -1) != 0)
|
make_option_mask(d, dl, od, odl, require, arg, -1) != 0)
|
||||||
{
|
{
|
||||||
logerrx("unknown option `%s'", arg);
|
logerrx("unknown option: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -985,6 +985,20 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID;
|
ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID;
|
||||||
|
if (ifname != NULL) /* duid type only a global option */
|
||||||
|
break;
|
||||||
|
if (arg == NULL)
|
||||||
|
ctx->duid_type = DUID_DEFAULT;
|
||||||
|
else if (strcmp(arg, "ll") == 0)
|
||||||
|
ctx->duid_type = DUID_LL;
|
||||||
|
else if (strcmp(arg, "llt") == 0)
|
||||||
|
ctx->duid_type = DUID_LLT;
|
||||||
|
else if (strcmp(arg, "uuid") == 0)
|
||||||
|
ctx->duid_type = DUID_UUID;
|
||||||
|
else {
|
||||||
|
logwarnx("%s: invalid duid type", arg);
|
||||||
|
ctx->duid_type = DUID_DEFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
ifo->options |= DHCPCD_LASTLEASE;
|
ifo->options |= DHCPCD_LASTLEASE;
|
||||||
|
@ -1003,7 +1017,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
else if (strcmp(arg, "disable") == 0)
|
else if (strcmp(arg, "disable") == 0)
|
||||||
ifo->fqdn = FQDN_DISABLE;
|
ifo->fqdn = FQDN_DISABLE;
|
||||||
else {
|
else {
|
||||||
logerrx("invalid value `%s' for FQDN", arg);
|
logerrx("invalid FQDN value: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1049,7 +1063,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
|
make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
|
||||||
make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
|
make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
|
||||||
{
|
{
|
||||||
logerrx("unknown option `%s'", arg);
|
logerrx("unknown option: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1062,7 +1076,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
|
make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
|
||||||
make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
|
make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
|
||||||
{
|
{
|
||||||
logerrx("unknown option `%s'", arg);
|
logerrx("unknown option: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1299,10 +1313,10 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
||||||
ifo->dstmask, arg, 2) != 0)
|
ifo->dstmask, arg, 2) != 0)
|
||||||
{
|
{
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
logerrx("option `%s' does not take"
|
logerrx("option does not take"
|
||||||
" an IPv4 address", arg);
|
" an IPv4 address: %s", arg);
|
||||||
else
|
else
|
||||||
logerrx("unknown option `%s'", arg);
|
logerrx("unknown option: %s", arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1785,7 +1799,7 @@ err_sla:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (l && !(t & (OT_STRING | OT_BINHEX))) {
|
if (l && !(t & (OT_STRING | OT_BINHEX))) {
|
||||||
logwarnx("ignoring length for type `%s'", arg);
|
logwarnx("ignoring length for type: %s", arg);
|
||||||
l = 0;
|
l = 0;
|
||||||
}
|
}
|
||||||
if (t & OT_ARRAY && t & (OT_STRING | OT_BINHEX) &&
|
if (t & OT_ARRAY && t & (OT_STRING | OT_BINHEX) &&
|
||||||
|
@ -2220,18 +2234,6 @@ invalid_token:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case O_POLL:
|
|
||||||
if (arg == NULL) {
|
|
||||||
ifo->poll = IF_POLL_UP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ifo->poll = (unsigned long)
|
|
||||||
strtou(arg, NULL, 0, 0, ULONG_MAX, &e);
|
|
||||||
if (e) {
|
|
||||||
logerrx("failed to convert poll %s", arg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||||
if (rap->willexpire)
|
if (rap->willexpire)
|
||||||
new_data = true;
|
new_data = true;
|
||||||
loglevel = new_rap || rap->willexpire || !rap->isreachable ?
|
loglevel = new_rap || rap->willexpire || !rap->isreachable ?
|
||||||
LOG_INFO : LOG_DEBUG,
|
LOG_INFO : LOG_DEBUG;
|
||||||
logmessage(loglevel, "%s: Router Advertisement from %s",
|
logmessage(loglevel, "%s: Router Advertisement from %s",
|
||||||
ifp->name, rap->sfrom);
|
ifp->name, rap->sfrom);
|
||||||
|
|
||||||
|
|
|
@ -382,7 +382,7 @@ logopen(const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SMALL
|
#ifndef SMALL
|
||||||
if ((ctx->log_file = fopen(path, "a")) == NULL)
|
if ((ctx->log_file = fopen(path, "ae")) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
setlinebuf(ctx->log_file);
|
setlinebuf(ctx->log_file);
|
||||||
return fileno(ctx->log_file);
|
return fileno(ctx->log_file);
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
#ifdef HAVE_CAPSICUM
|
#ifdef HAVE_CAPSICUM
|
||||||
#include <sys/capsicum.h>
|
#include <sys/capsicum.h>
|
||||||
#include <capsicum_helpers.h>
|
#include <capsicum_helpers.h>
|
||||||
#define ps_rights_limit_stdio caph_limit_stdio
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_UTIL_H
|
#ifdef HAVE_UTIL_H
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
@ -118,11 +117,12 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
|
||||||
struct passwd *pw = ctx->ps_user;
|
struct passwd *pw = ctx->ps_user;
|
||||||
|
|
||||||
if (!(ctx->options & DHCPCD_FORKED))
|
if (!(ctx->options & DHCPCD_FORKED))
|
||||||
logdebugx("chrooting to `%s' as %s", pw->pw_dir, pw->pw_name);
|
logdebugx("chrooting as %s to %s", pw->pw_name, pw->pw_dir);
|
||||||
if (chroot(pw->pw_dir) == -1)
|
if (chroot(pw->pw_dir) == -1 &&
|
||||||
logerr("%s: chroot `%s'", __func__, pw->pw_dir);
|
(errno != EPERM || ctx->options & DHCPCD_FORKED))
|
||||||
|
logerr("%s: chroot: %s", __func__, pw->pw_dir);
|
||||||
if (chdir("/") == -1)
|
if (chdir("/") == -1)
|
||||||
logerr("%s: chdir `/'", __func__);
|
logerr("%s: chdir: /", __func__);
|
||||||
|
|
||||||
if ((setgroups(1, &pw->pw_gid) == -1 ||
|
if ((setgroups(1, &pw->pw_gid) == -1 ||
|
||||||
setgid(pw->pw_gid) == -1 ||
|
setgid(pw->pw_gid) == -1 ||
|
||||||
|
@ -259,6 +259,18 @@ ps_rights_limit_fd(int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ps_rights_limit_fd_sockopt(int fd)
|
||||||
|
{
|
||||||
|
cap_rights_t rights;
|
||||||
|
|
||||||
|
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT,
|
||||||
|
CAP_GETSOCKOPT, CAP_SETSOCKOPT);
|
||||||
|
if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ps_rights_limit_fd_rdonly(int fd)
|
ps_rights_limit_fd_rdonly(int fd)
|
||||||
{
|
{
|
||||||
|
@ -278,6 +290,25 @@ ps_rights_limit_fdpair(int fd[])
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ps_rights_limit_stdio(struct dhcpcd_ctx *ctx)
|
||||||
|
{
|
||||||
|
const int iebadf = CAPH_IGNORE_EBADF;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (ctx->stdin_valid &&
|
||||||
|
caph_limit_stream(STDIN_FILENO, CAPH_READ | iebadf) == -1)
|
||||||
|
error = -1;
|
||||||
|
if (ctx->stdout_valid &&
|
||||||
|
caph_limit_stream(STDOUT_FILENO, CAPH_WRITE | iebadf) == -1)
|
||||||
|
error = -1;
|
||||||
|
if (ctx->stderr_valid &&
|
||||||
|
caph_limit_stream(STDERR_FILENO, CAPH_WRITE | iebadf) == -1)
|
||||||
|
error = -1;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
|
@ -346,7 +377,7 @@ ps_dostart(struct dhcpcd_ctx *ctx,
|
||||||
|
|
||||||
#ifdef PRIVSEP_RIGHTS
|
#ifdef PRIVSEP_RIGHTS
|
||||||
/* We cannot limit the root process in any way. */
|
/* We cannot limit the root process in any way. */
|
||||||
if (ps_rights_limit_stdio() == -1) {
|
if (ps_rights_limit_stdio(ctx) == -1) {
|
||||||
logerr("ps_rights_limit_stdio");
|
logerr("ps_rights_limit_stdio");
|
||||||
goto errexit;
|
goto errexit;
|
||||||
}
|
}
|
||||||
|
@ -472,10 +503,45 @@ started_net:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ps_mastersandbox(struct dhcpcd_ctx *ctx)
|
ps_entersandbox(const char *_pledge, const char **sandbox)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ps_dropprivs(ctx) == -1) {
|
#if !defined(HAVE_PLEDGE)
|
||||||
|
UNUSED(_pledge);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_CAPSICUM)
|
||||||
|
if (sandbox != NULL)
|
||||||
|
*sandbox = "capsicum";
|
||||||
|
return cap_enter();
|
||||||
|
#elif defined(HAVE_PLEDGE)
|
||||||
|
if (sandbox != NULL)
|
||||||
|
*sandbox = "pledge";
|
||||||
|
return pledge(_pledge, NULL);
|
||||||
|
#elif defined(HAVE_SECCOMP)
|
||||||
|
if (sandbox != NULL)
|
||||||
|
*sandbox = "seccomp";
|
||||||
|
return ps_seccomp_enter();
|
||||||
|
#else
|
||||||
|
if (sandbox != NULL)
|
||||||
|
*sandbox = "posix resource limited";
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ps_mastersandbox(struct dhcpcd_ctx *ctx, const char *_pledge)
|
||||||
|
{
|
||||||
|
const char *sandbox = NULL;
|
||||||
|
bool forked;
|
||||||
|
int dropped;
|
||||||
|
|
||||||
|
forked = ctx->options & DHCPCD_FORKED;
|
||||||
|
ctx->options &= ~DHCPCD_FORKED;
|
||||||
|
dropped = ps_dropprivs(ctx);
|
||||||
|
if (forked)
|
||||||
|
ctx->options |= DHCPCD_FORKED;
|
||||||
|
if (dropped == -1) {
|
||||||
logerr("%s: ps_dropprivs", __func__);
|
logerr("%s: ps_dropprivs", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -483,26 +549,25 @@ ps_mastersandbox(struct dhcpcd_ctx *ctx)
|
||||||
#ifdef PRIVSEP_RIGHTS
|
#ifdef PRIVSEP_RIGHTS
|
||||||
if ((ctx->pf_inet_fd != -1 &&
|
if ((ctx->pf_inet_fd != -1 &&
|
||||||
ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1) ||
|
ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1) ||
|
||||||
(ctx->link_fd != -1 && ps_rights_limit_fd(ctx->link_fd) == -1) ||
|
ps_rights_limit_stdio(ctx) == -1)
|
||||||
ps_rights_limit_stdio() == -1)
|
|
||||||
{
|
{
|
||||||
logerr("%s: cap_rights_limit", __func__);
|
logerr("%s: cap_rights_limit", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CAPSICUM
|
|
||||||
if (cap_enter() == -1 && errno != ENOSYS) {
|
|
||||||
logerr("%s: cap_enter", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_PLEDGE
|
|
||||||
if (pledge("stdio route", NULL) == -1) {
|
|
||||||
logerr("%s: pledge", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
if (_pledge == NULL)
|
||||||
|
_pledge = "stdio";
|
||||||
|
if (ps_entersandbox(_pledge, &sandbox) == -1) {
|
||||||
|
if (errno == ENOSYS) {
|
||||||
|
if (sandbox != NULL)
|
||||||
|
logwarnx("sandbox unavailable: %s", sandbox);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
logerr("%s: %s", __func__, sandbox);
|
||||||
|
return -1;
|
||||||
|
} else if (!forked)
|
||||||
|
logdebugx("sandbox: %s", sandbox);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -736,7 +736,7 @@ script_runreason(const struct interface *ifp, const char *reason)
|
||||||
|
|
||||||
argv[0] = ctx->script;
|
argv[0] = ctx->script;
|
||||||
argv[1] = NULL;
|
argv[1] = NULL;
|
||||||
logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason);
|
logdebugx("%s: executing: %s %s", ifp->name, argv[0], reason);
|
||||||
|
|
||||||
#ifdef PRIVSEP
|
#ifdef PRIVSEP
|
||||||
if (ctx->options & DHCPCD_PRIVSEP) {
|
if (ctx->options & DHCPCD_PRIVSEP) {
|
||||||
|
|
Loading…
Reference in New Issue