Update to dhcpcd-9.1.0 with the following changes:
* Leases are stored outside the chroot again * The chroot directory can now be (and should be) empty [1] * ARP is now per address rather than per interface * Filter allowed ioctls in the privileged actioneer * Filter allowed UDP ports used by sendto(2) in the privileged actioneer * Filter allowed file paths in the privileged actioneer * route socket is now drained on overflow as it cannot be re-opened by the unpriviledged user * hostname can no longer be clobbered by SLAAC * grep is no longer used by the test hook * Interface hardware address type changes are now picked up * Fixed some RA timing issues * Fixed nd_* option parsing in dhcpcd.conf * Allow SIGPIPE in scripts * Default dhcpcd.conf no longer sends the current hostname * Default dhcpcd.conf no longer sends a vendorclassid
This commit is contained in:
parent
9769066979
commit
7c187152f8
|
@ -97,8 +97,6 @@ install similar logic into their dhcpcd package.
|
|||
|
||||
dhcpcd-9 defaults the run directory to `/var/run/dhcpcd` instead of
|
||||
`/var/run` and the prefix of dhcpcd has been removed from the files.
|
||||
dhcpcd-9 may also run in a chroot, `/var/chroot/dhcpcd` so all the files
|
||||
could be relative to that.
|
||||
|
||||
## ChangeLog
|
||||
We no longer supply a ChangeLog.
|
||||
|
|
|
@ -1,9 +1,37 @@
|
|||
# Echo the interface flags, reason and message options
|
||||
|
||||
if [ "$reason" = "TEST" ]; then
|
||||
set | grep \
|
||||
"^\(interface\|pid\|reason\|protocol\|profile\|skip_hooks\)=" | sort
|
||||
set | grep "^if\(carrier\|flags\|mtu\|wireless\|ssid\)=" | sort
|
||||
set | grep "^\(new_\|old_\|nd[0-9]*_\)" | sort
|
||||
# General variables at the top
|
||||
set | while read line; do
|
||||
case "$line" in
|
||||
interface=*|pid=*|reason=*|protocol=*|profile=*|skip_hooks=*)
|
||||
echo "$line";;
|
||||
esac
|
||||
done
|
||||
# Interface flags
|
||||
set | while read line; do
|
||||
case "$line" in
|
||||
ifcarrier=*|ifflags=*|ifmetric=*|ifmtu=*|ifwireless=*|ifssid=*)
|
||||
echo "$line";;
|
||||
esac
|
||||
done
|
||||
# Old lease
|
||||
set | while read line; do
|
||||
case "$line" in
|
||||
old_*) echo "$line";;
|
||||
esac
|
||||
done
|
||||
# New lease
|
||||
set | while read line; do
|
||||
case "$line" in
|
||||
new_*) echo "$line";;
|
||||
esac
|
||||
done
|
||||
# Router Advertisements
|
||||
set | while read line; do
|
||||
case "$line" in
|
||||
nd[0-9]*_*) echo "$line";;
|
||||
esac
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 3, 2020
|
||||
.Dd May 24, 2020
|
||||
.Dt DHCPCD-RUN-HOOKS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -84,8 +84,6 @@ Here's a list of reasons why
|
|||
.Nm
|
||||
could be invoked:
|
||||
.Bl -tag -width EXPIREXXXEXPIRE6
|
||||
.It Dv CHROOT
|
||||
dhcpcd is starting up and needs to configure a chroot environment.
|
||||
.It Dv PREINIT
|
||||
dhcpcd is starting up and any pre-initialisation should be done.
|
||||
.It Dv CARRIER
|
||||
|
@ -95,7 +93,7 @@ This is generally just a notification and no action need be taken.
|
|||
dhcpcd lost the carrier.
|
||||
The cable may have been unplugged or association to the wireless point lost.
|
||||
.It Dv INFORM | Dv INFORM6
|
||||
dhcpcd informed a DHCP server about it's address and obtained other
|
||||
dhcpcd informed a DHCP server about its address and obtained other
|
||||
configuration details.
|
||||
.It Dv BOUND | Dv BOUND6
|
||||
dhcpcd obtained a new lease from a DHCP server.
|
||||
|
|
|
@ -67,16 +67,17 @@
|
|||
__CTASSERT(sizeof(struct arphdr) == 8);
|
||||
|
||||
static ssize_t
|
||||
arp_request(const struct interface *ifp,
|
||||
const struct in_addr *sip, const struct in_addr *tip)
|
||||
arp_request(const struct arp_state *astate,
|
||||
const struct in_addr *sip)
|
||||
{
|
||||
const struct interface *ifp = astate->iface;
|
||||
const struct in_addr *tip = &astate->addr;
|
||||
uint8_t arp_buffer[ARP_LEN];
|
||||
struct arphdr ar;
|
||||
size_t len;
|
||||
uint8_t *p;
|
||||
const struct iarp_state *state;
|
||||
|
||||
ar.ar_hrd = htons(ifp->family);
|
||||
ar.ar_hrd = htons(ifp->hwtype);
|
||||
ar.ar_pro = htons(ETHERTYPE_IP);
|
||||
ar.ar_hln = ifp->hwlen;
|
||||
ar.ar_pln = sizeof(tip->s_addr);
|
||||
|
@ -107,12 +108,11 @@ arp_request(const struct interface *ifp,
|
|||
|
||||
#ifdef PRIVSEP
|
||||
if (ifp->ctx->options & DHCPCD_PRIVSEP)
|
||||
return ps_bpf_sendarp(ifp, arp_buffer, len);
|
||||
return ps_bpf_sendarp(ifp, tip, arp_buffer, len);
|
||||
#endif
|
||||
state = ARP_CSTATE(ifp);
|
||||
/* Note that well formed ethernet will add extra padding
|
||||
* to ensure that the packet is at least 60 bytes (64 including FCS). */
|
||||
return bpf_send(ifp, state->bpf_fd, ETHERTYPE_ARP, arp_buffer, len);
|
||||
return bpf_send(astate->bpf, ETHERTYPE_ARP, arp_buffer, len);
|
||||
|
||||
eexit:
|
||||
errno = ENOBUFS;
|
||||
|
@ -134,12 +134,12 @@ arp_report_conflicted(const struct arp_state *astate,
|
|||
|
||||
hwaddr_ntoa(amsg->sha, astate->iface->hwlen, abuf, sizeof(abuf));
|
||||
if (bpf_frame_header_len(astate->iface) == 0) {
|
||||
logerrx("%s: %s claims %s",
|
||||
logwarnx("%s: %s claims %s",
|
||||
astate->iface->name, abuf, inet_ntoa(astate->addr));
|
||||
return;
|
||||
}
|
||||
|
||||
logerrx("%s: %s(%s) claims %s",
|
||||
logwarnx("%s: %s(%s) claims %s",
|
||||
astate->iface->name, abuf,
|
||||
hwaddr_ntoa(amsg->fsha, astate->iface->hwlen, fbuf, sizeof(fbuf)),
|
||||
inet_ntoa(astate->addr));
|
||||
|
@ -179,7 +179,7 @@ arp_found(struct arp_state *astate, const struct arp_msg *amsg)
|
|||
eloop_timespec_diff(&now, &astate->defend, NULL) < DEFEND_INTERVAL)
|
||||
logwarnx("%s: %d second defence failed for %s",
|
||||
ifp->name, DEFEND_INTERVAL, inet_ntoa(astate->addr));
|
||||
else if (arp_request(ifp, &astate->addr, &astate->addr) == -1)
|
||||
else if (arp_request(astate, &astate->addr) == -1)
|
||||
logerr(__func__);
|
||||
else {
|
||||
logdebugx("%s: defended address %s",
|
||||
|
@ -197,8 +197,8 @@ static bool
|
|||
arp_validate(const struct interface *ifp, struct arphdr *arp)
|
||||
{
|
||||
|
||||
/* Families must match */
|
||||
if (arp->ar_hrd != htons(ifp->family))
|
||||
/* Address type must match */
|
||||
if (arp->ar_hrd != htons(ifp->hwtype))
|
||||
return false;
|
||||
|
||||
/* Protocol must be IP. */
|
||||
|
@ -222,7 +222,8 @@ arp_validate(const struct interface *ifp, struct arphdr *arp)
|
|||
}
|
||||
|
||||
void
|
||||
arp_packet(struct interface *ifp, uint8_t *data, size_t len)
|
||||
arp_packet(struct interface *ifp, uint8_t *data, size_t len,
|
||||
unsigned int bpf_flags)
|
||||
{
|
||||
size_t fl = bpf_frame_header_len(ifp), falen;
|
||||
const struct interface *ifn;
|
||||
|
@ -292,108 +293,39 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len)
|
|||
if (IN_ARE_ADDR_EQUAL(&arm.sip, &astate->addr) ||
|
||||
(IN_IS_ADDR_UNSPECIFIED(&arm.sip) &&
|
||||
IN_ARE_ADDR_EQUAL(&arm.tip, &astate->addr) &&
|
||||
state->bpf_flags & BPF_BCAST))
|
||||
bpf_flags & BPF_BCAST))
|
||||
arp_found(astate, &arm);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arp_close(struct interface *ifp)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
struct iarp_state *state;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP(ctx)) {
|
||||
if (IN_PRIVSEP_SE(ctx) &&
|
||||
ps_bpf_closearp(ifp) == -1)
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((state = ARP_STATE(ifp)) == NULL)
|
||||
return;
|
||||
|
||||
if (state->bpf_fd == -1)
|
||||
return;
|
||||
eloop_event_delete(ctx->eloop, state->bpf_fd);
|
||||
bpf_close(ifp, state->bpf_fd);
|
||||
state->bpf_fd = -1;
|
||||
state->bpf_flags |= BPF_EOF;
|
||||
}
|
||||
|
||||
static void
|
||||
arp_tryfree(struct iarp_state *state)
|
||||
{
|
||||
struct interface *ifp = state->ifp;
|
||||
|
||||
/* If there are no more ARP states, close the socket. */
|
||||
if (TAILQ_FIRST(&state->arp_states) == NULL) {
|
||||
arp_close(ifp);
|
||||
if (state->bpf_flags & BPF_READING)
|
||||
state->bpf_flags |= BPF_EOF;
|
||||
else {
|
||||
free(state);
|
||||
ifp->if_data[IF_DATA_ARP] = NULL;
|
||||
}
|
||||
} else if (state->bpf_fd != -1) {
|
||||
if (bpf_arp(ifp, state->bpf_fd) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arp_read(void *arg)
|
||||
{
|
||||
struct iarp_state *state = arg;
|
||||
struct interface *ifp = state->ifp;
|
||||
struct arp_state *astate = arg;
|
||||
struct bpf *bpf = astate->bpf;
|
||||
struct interface *ifp = astate->iface;
|
||||
uint8_t buf[ARP_LEN];
|
||||
ssize_t bytes;
|
||||
struct in_addr addr = astate->addr;
|
||||
|
||||
/* Some RAW mechanisms are generic file descriptors, not sockets.
|
||||
* This means we have no kernel call to just get one packet,
|
||||
* so we have to process the entire buffer. */
|
||||
state->bpf_flags &= ~BPF_EOF;
|
||||
state->bpf_flags |= BPF_READING;
|
||||
while (!(state->bpf_flags & BPF_EOF)) {
|
||||
bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf),
|
||||
&state->bpf_flags);
|
||||
bpf->bpf_flags &= ~BPF_EOF;
|
||||
while (!(bpf->bpf_flags & BPF_EOF)) {
|
||||
bytes = bpf_read(bpf, buf, sizeof(buf));
|
||||
if (bytes == -1) {
|
||||
logerr("%s: %s", __func__, ifp->name);
|
||||
arp_close(ifp);
|
||||
break;
|
||||
arp_free(astate);
|
||||
return;
|
||||
}
|
||||
arp_packet(ifp, buf, (size_t)bytes);
|
||||
arp_packet(ifp, buf, (size_t)bytes, bpf->bpf_flags);
|
||||
/* Check we still have a state after processing. */
|
||||
if ((state = ARP_STATE(ifp)) == NULL)
|
||||
if ((astate = arp_find(ifp, &addr)) == NULL)
|
||||
break;
|
||||
if ((bpf = astate->bpf) == NULL)
|
||||
break;
|
||||
}
|
||||
if (state != NULL) {
|
||||
state->bpf_flags &= ~BPF_READING;
|
||||
/* Try and free the state if nothing left to do. */
|
||||
arp_tryfree(state);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
arp_open(struct interface *ifp)
|
||||
{
|
||||
struct iarp_state *state;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP_SE(ifp->ctx))
|
||||
return ps_bpf_openarp(ifp) == -1 ? -1 : 0;
|
||||
#endif
|
||||
|
||||
state = ARP_STATE(ifp);
|
||||
if (state->bpf_fd == -1) {
|
||||
state->bpf_fd = bpf_open(ifp, bpf_arp);
|
||||
if (state->bpf_fd == -1)
|
||||
return -1;
|
||||
eloop_event_add(ifp->ctx->eloop, state->bpf_fd, arp_read, state);
|
||||
}
|
||||
return state->bpf_fd;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -425,7 +357,7 @@ arp_probe1(void *arg)
|
|||
ifp->name, inet_ntoa(astate->addr),
|
||||
astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
|
||||
(float)delay / MSEC_PER_SEC);
|
||||
if (arp_request(ifp, NULL, &astate->addr) == -1)
|
||||
if (arp_request(astate, NULL) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
|
||||
|
@ -436,11 +368,6 @@ arp_probe(struct arp_state *astate)
|
|||
astate->probes = 0;
|
||||
logdebugx("%s: probing for %s",
|
||||
astate->iface->name, inet_ntoa(astate->addr));
|
||||
if (!(IN_PRIVSEP(astate->iface->ctx)) && arp_open(astate->iface) == -1)
|
||||
{
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
arp_probe1(astate);
|
||||
}
|
||||
#endif /* ARP */
|
||||
|
@ -501,7 +428,7 @@ arp_announce1(void *arg)
|
|||
goto skip_request;
|
||||
#endif
|
||||
|
||||
if (arp_request(ifp, &astate->addr, &astate->addr) == -1)
|
||||
if (arp_request(astate, &astate->addr) == -1)
|
||||
logerr(__func__);
|
||||
|
||||
#ifndef __linux__
|
||||
|
@ -516,7 +443,7 @@ skip_request:
|
|||
astate);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
arp_announce(struct arp_state *astate)
|
||||
{
|
||||
struct iarp_state *state;
|
||||
|
@ -524,12 +451,6 @@ arp_announce(struct arp_state *astate)
|
|||
struct arp_state *a2;
|
||||
int r;
|
||||
|
||||
if (!(IN_PRIVSEP(astate->iface->ctx)) && arp_open(astate->iface) == -1)
|
||||
{
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cancel any other ARP announcements for this address. */
|
||||
TAILQ_FOREACH(ifp, astate->iface->ctx->ifaces, next) {
|
||||
state = ARP_STATE(ifp);
|
||||
|
@ -557,25 +478,26 @@ arp_announce(struct arp_state *astate)
|
|||
arp_announce1(astate);
|
||||
}
|
||||
|
||||
void
|
||||
struct arp_state *
|
||||
arp_ifannounceaddr(struct interface *ifp, const struct in_addr *ia)
|
||||
{
|
||||
struct arp_state *astate;
|
||||
|
||||
if (ifp->flags & IFF_NOARP)
|
||||
return;
|
||||
if (ifp->flags & IFF_NOARP || !(ifp->options->options & DHCPCD_ARP))
|
||||
return NULL;
|
||||
|
||||
astate = arp_find(ifp, ia);
|
||||
if (astate == NULL) {
|
||||
astate = arp_new(ifp, ia);
|
||||
if (astate == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
astate->announced_cb = arp_free;
|
||||
}
|
||||
arp_announce(astate);
|
||||
return astate;
|
||||
}
|
||||
|
||||
void
|
||||
struct arp_state *
|
||||
arp_announceaddr(struct dhcpcd_ctx *ctx, const struct in_addr *ia)
|
||||
{
|
||||
struct interface *ifp, *iff = NULL;
|
||||
|
@ -588,7 +510,7 @@ arp_announceaddr(struct dhcpcd_ctx *ctx, const struct in_addr *ia)
|
|||
if (iap == NULL)
|
||||
continue;
|
||||
#ifdef IN_IFF_NOTUSEABLE
|
||||
if (!(iap->addr_flags & IN_IFF_NOTUSEABLE))
|
||||
if (iap->addr_flags & IN_IFF_NOTUSEABLE)
|
||||
continue;
|
||||
#endif
|
||||
if (iff != NULL && iff->metric < ifp->metric)
|
||||
|
@ -596,41 +518,9 @@ arp_announceaddr(struct dhcpcd_ctx *ctx, const struct in_addr *ia)
|
|||
iff = ifp;
|
||||
}
|
||||
if (iff == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
arp_ifannounceaddr(iff, ia);
|
||||
}
|
||||
|
||||
void
|
||||
arp_change(struct arp_state *astate, const struct in_addr *addr)
|
||||
{
|
||||
struct interface *ifp = astate->iface;
|
||||
struct iarp_state *state = ARP_STATE(ifp);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (!IN_IS_ADDR_UNSPECIFIED(&astate->addr) &&
|
||||
IN_PRIVSEP_SE(ifp->ctx))
|
||||
{
|
||||
if (ps_bpf_deladdr(ifp, &astate->addr) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addr != NULL)
|
||||
astate->addr = *addr;
|
||||
else
|
||||
astate->addr.s_addr = INADDR_ANY;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (addr != NULL && IN_PRIVSEP_SE(ifp->ctx)) {
|
||||
if (ps_bpf_addaddr(ifp, addr) == -1)
|
||||
logerr(__func__);
|
||||
} else
|
||||
#endif
|
||||
if (state->bpf_fd != -1) {
|
||||
if (bpf_arp(ifp, state->bpf_fd) == -1)
|
||||
logerr(__func__); /* try and continue */
|
||||
}
|
||||
return arp_ifannounceaddr(iff, ia);
|
||||
}
|
||||
|
||||
struct arp_state *
|
||||
|
@ -640,25 +530,15 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
|
|||
struct arp_state *astate;
|
||||
|
||||
if ((state = ARP_STATE(ifp)) == NULL) {
|
||||
#ifdef PRIVSEP
|
||||
/* We need to ensure ARP is spawned so we can add to it. */
|
||||
if (IN_PRIVSEP_SE(ifp->ctx) && arp_open(ifp) == -1) {
|
||||
logerr(__func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
|
||||
state = ARP_STATE(ifp);
|
||||
if (state == NULL) {
|
||||
logerr(__func__);
|
||||
return NULL;
|
||||
}
|
||||
state->ifp = ifp;
|
||||
state->bpf_fd = -1;
|
||||
state->bpf_flags = 0;
|
||||
TAILQ_INIT(&state->arp_states);
|
||||
} else {
|
||||
if (addr && (astate = arp_find(ifp, addr)))
|
||||
if ((astate = arp_find(ifp, addr)) != NULL)
|
||||
return astate;
|
||||
}
|
||||
|
||||
|
@ -667,9 +547,31 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
|
|||
return NULL;
|
||||
}
|
||||
astate->iface = ifp;
|
||||
astate->addr = *addr;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP(ifp->ctx)) {
|
||||
if (ps_bpf_openarp(ifp, addr) == -1) {
|
||||
logerr(__func__);
|
||||
free(astate);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
astate->bpf = bpf_open(ifp, bpf_arp, addr);
|
||||
if (astate->bpf == NULL) {
|
||||
logerr(__func__);
|
||||
free(astate);
|
||||
return NULL;
|
||||
}
|
||||
eloop_event_add(ifp->ctx->eloop, astate->bpf->bpf_fd,
|
||||
arp_read, astate);
|
||||
}
|
||||
|
||||
|
||||
state = ARP_STATE(ifp);
|
||||
TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
|
||||
arp_change(astate, addr);
|
||||
return astate;
|
||||
}
|
||||
|
||||
|
@ -684,20 +586,36 @@ void
|
|||
arp_free(struct arp_state *astate)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct dhcpcd_ctx *ctx;
|
||||
struct iarp_state *state;
|
||||
|
||||
if (astate == NULL)
|
||||
return;
|
||||
|
||||
ifp = astate->iface;
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, astate);
|
||||
arp_change(astate, NULL);
|
||||
ctx = ifp->ctx;
|
||||
eloop_timeout_delete(ctx->eloop, NULL, astate);
|
||||
|
||||
state = ARP_STATE(ifp);
|
||||
TAILQ_REMOVE(&state->arp_states, astate, next);
|
||||
if (astate->free_cb)
|
||||
astate->free_cb(astate);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP(ctx) && ps_bpf_closearp(ifp, &astate->addr) == -1)
|
||||
logerr(__func__);
|
||||
#endif
|
||||
if (astate->bpf != NULL) {
|
||||
eloop_event_delete(ctx->eloop, astate->bpf->bpf_fd);
|
||||
bpf_close(astate->bpf);
|
||||
}
|
||||
|
||||
free(astate);
|
||||
arp_tryfree(state);
|
||||
|
||||
if (TAILQ_FIRST(&state->arp_states) == NULL) {
|
||||
free(state);
|
||||
ifp->if_data[IF_DATA_ARP] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -718,6 +636,4 @@ arp_drop(struct interface *ifp)
|
|||
while ((state = ARP_STATE(ifp)) != NULL &&
|
||||
(astate = TAILQ_FIRST(&state->arp_states)) != NULL)
|
||||
arp_free(astate);
|
||||
|
||||
/* No need to close because the last free will close */
|
||||
}
|
||||
|
|
|
@ -41,12 +41,14 @@
|
|||
#define RATE_LIMIT_INTERVAL 60
|
||||
#define DEFEND_INTERVAL 10
|
||||
|
||||
#include "bpf.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "if.h"
|
||||
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
/* NetBSD gained RFC 5227 support in the kernel.
|
||||
* This means dhcpcd doesn't need ARP except for ARPing support. */
|
||||
* This means dhcpcd doesn't need ARP except for ARPing support
|
||||
* and ARP announcing an address. */
|
||||
#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003900
|
||||
#define KERNEL_RFC5227
|
||||
#endif
|
||||
|
@ -66,24 +68,22 @@ struct arp_msg {
|
|||
struct arp_state {
|
||||
TAILQ_ENTRY(arp_state) next;
|
||||
struct interface *iface;
|
||||
struct in_addr addr;
|
||||
struct bpf *bpf;
|
||||
|
||||
int probes;
|
||||
int claims;
|
||||
struct timespec defend;
|
||||
|
||||
void (*found_cb)(struct arp_state *, const struct arp_msg *);
|
||||
void (*not_found_cb)(struct arp_state *);
|
||||
void (*announced_cb)(struct arp_state *);
|
||||
void (*defend_failed_cb)(struct arp_state *);
|
||||
void (*free_cb)(struct arp_state *);
|
||||
|
||||
struct in_addr addr;
|
||||
int probes;
|
||||
int claims;
|
||||
struct timespec defend;
|
||||
};
|
||||
TAILQ_HEAD(arp_statehead, arp_state);
|
||||
|
||||
struct iarp_state {
|
||||
struct interface *ifp;
|
||||
int bpf_fd;
|
||||
unsigned int bpf_flags;
|
||||
struct arp_statehead arp_states;
|
||||
};
|
||||
|
||||
|
@ -93,13 +93,11 @@ struct iarp_state {
|
|||
((const struct iarp_state *)(ifp)->if_data[IF_DATA_ARP])
|
||||
|
||||
#ifdef ARP
|
||||
void arp_packet(struct interface *, uint8_t *, size_t);
|
||||
void arp_packet(struct interface *, uint8_t *, size_t, unsigned int);
|
||||
struct arp_state *arp_new(struct interface *, const struct in_addr *);
|
||||
void arp_change(struct arp_state *, const struct in_addr *);
|
||||
void arp_probe(struct arp_state *);
|
||||
void arp_announce(struct arp_state *);
|
||||
void arp_announceaddr(struct dhcpcd_ctx *, const struct in_addr *);
|
||||
void arp_ifannounceaddr(struct interface *, const struct in_addr *);
|
||||
struct arp_state *arp_announceaddr(struct dhcpcd_ctx *, const struct in_addr *);
|
||||
struct arp_state *arp_ifannounceaddr(struct interface *, const struct in_addr *);
|
||||
void arp_cancel(struct arp_state *);
|
||||
struct arp_state * arp_find(struct interface *, const struct in_addr *);
|
||||
void arp_free(struct arp_state *);
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
#ifndef BPF_HEADER
|
||||
#define BPF_HEADER
|
||||
|
||||
#define BPF_READING (1U << 0)
|
||||
#define BPF_EOF (1U << 1)
|
||||
#define BPF_PARTIALCSUM (1U << 2)
|
||||
#define BPF_BCAST (1U << 3)
|
||||
#define BPF_EOF 0x01U
|
||||
#define BPF_PARTIALCSUM 0x02U
|
||||
#define BPF_BCAST 0x04U
|
||||
|
||||
/*
|
||||
* Even though we program the BPF filter should we trust it?
|
||||
|
@ -55,16 +54,28 @@
|
|||
|
||||
#include "dhcpcd.h"
|
||||
|
||||
struct bpf {
|
||||
const struct interface *bpf_ifp;
|
||||
int bpf_fd;
|
||||
unsigned int bpf_flags;
|
||||
void *bpf_buffer;
|
||||
size_t bpf_size;
|
||||
size_t bpf_len;
|
||||
size_t bpf_pos;
|
||||
};
|
||||
|
||||
extern const char *bpf_name;
|
||||
size_t bpf_frame_header_len(const struct interface *);
|
||||
void *bpf_frame_header_src(const struct interface *, void *, size_t *);
|
||||
void *bpf_frame_header_dst(const struct interface *, void *, size_t *);
|
||||
int bpf_frame_bcast(const struct interface *, const char *frame);
|
||||
int bpf_open(struct interface *, int (*)(struct interface *, int));
|
||||
int bpf_close(struct interface *, int);
|
||||
int bpf_frame_bcast(const struct interface *, const void *);
|
||||
struct bpf * bpf_open(const struct interface *,
|
||||
int (*)(const struct bpf *, const struct in_addr *),
|
||||
const struct in_addr *);
|
||||
void bpf_close(struct bpf *);
|
||||
int bpf_attach(int, void *, unsigned int);
|
||||
ssize_t bpf_send(const struct interface *, int, uint16_t, const void *, size_t);
|
||||
ssize_t bpf_read(struct interface *, int, void *, size_t, unsigned int *);
|
||||
int bpf_arp(struct interface *, int);
|
||||
int bpf_bootp(struct interface *, int);
|
||||
ssize_t bpf_send(const struct bpf *, uint16_t, const void *, size_t);
|
||||
ssize_t bpf_read(struct bpf *, void *, size_t);
|
||||
int bpf_arp(const struct bpf *, const struct in_addr *);
|
||||
int bpf_bootp(const struct bpf *, const struct in_addr *);
|
||||
#endif
|
||||
|
|
|
@ -26,17 +26,19 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "if-options.h"
|
||||
#include "logerr.h"
|
||||
|
||||
const char *
|
||||
hwaddr_ntoa(const void *hwaddr, size_t hwlen, char *buf, size_t buflen)
|
||||
|
@ -44,7 +46,7 @@ hwaddr_ntoa(const void *hwaddr, size_t hwlen, char *buf, size_t buflen)
|
|||
const unsigned char *hp, *ep;
|
||||
char *p;
|
||||
|
||||
if (buf == NULL)
|
||||
if (buf == NULL || hwlen == 0)
|
||||
return NULL;
|
||||
|
||||
if (hwlen * 3 > buflen) {
|
||||
|
@ -103,38 +105,97 @@ hwaddr_aton(uint8_t *buffer, const char *addr)
|
|||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
read_hwaddr_aton(uint8_t **data, const char *path)
|
||||
ssize_t
|
||||
readfile(const char *file, void *data, size_t len)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf;
|
||||
size_t buf_len, len;
|
||||
int fd;
|
||||
ssize_t bytes;
|
||||
|
||||
if ((fp = fopen(path, "r")) == NULL)
|
||||
return 0;
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
bytes = read(fd, data, len);
|
||||
close(fd);
|
||||
if ((size_t)bytes == len) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
buf_len = len = 0;
|
||||
*data = NULL;
|
||||
while (getline(&buf, &buf_len, fp) != -1) {
|
||||
if ((len = hwaddr_aton(NULL, buf)) != 0) {
|
||||
if (buf_len >= len)
|
||||
*data = (uint8_t *)buf;
|
||||
else {
|
||||
if ((*data = malloc(len)) == NULL)
|
||||
len = 0;
|
||||
}
|
||||
if (len != 0)
|
||||
(void)hwaddr_aton(*data, buf);
|
||||
if (buf_len < len)
|
||||
free(buf);
|
||||
ssize_t
|
||||
writefile(const char *file, mode_t mode, const void *data, size_t len)
|
||||
{
|
||||
int fd;
|
||||
ssize_t bytes;
|
||||
|
||||
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
bytes = write(fd, data, len);
|
||||
close(fd);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int
|
||||
filemtime(const char *file, time_t *time)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(file, &st) == -1)
|
||||
return -1;
|
||||
*time = st.st_mtime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handy routine to read very long lines in text files.
|
||||
* This means we read the whole line and avoid any nasty buffer overflows.
|
||||
* We strip leading space and avoid comment lines, making the code that calls
|
||||
* us smaller. */
|
||||
char *
|
||||
get_line(char ** __restrict buf, ssize_t * __restrict buflen)
|
||||
{
|
||||
char *p, *c;
|
||||
bool quoted;
|
||||
|
||||
do {
|
||||
p = *buf;
|
||||
if (*buf == NULL)
|
||||
return NULL;
|
||||
c = memchr(*buf, '\n', (size_t)*buflen);
|
||||
if (c == NULL) {
|
||||
c = memchr(*buf, '\0', (size_t)*buflen);
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
*buflen = c - *buf;
|
||||
*buf = NULL;
|
||||
} else {
|
||||
*c++ = '\0';
|
||||
*buflen -= c - *buf;
|
||||
*buf = c;
|
||||
}
|
||||
for (; *p == ' ' || *p == '\t'; p++)
|
||||
;
|
||||
} while (*p == '\0' || *p == '\n' || *p == '#' || *p == ';');
|
||||
|
||||
/* Strip embedded comments unless in a quoted string or escaped */
|
||||
quoted = false;
|
||||
for (c = p; *c != '\0'; c++) {
|
||||
if (*c == '\\') {
|
||||
c++; /* escaped */
|
||||
continue;
|
||||
}
|
||||
if (*c == '"')
|
||||
quoted = !quoted;
|
||||
else if (*c == '#' && !quoted) {
|
||||
*c = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return len;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
is_root_local(void)
|
||||
{
|
||||
|
|
|
@ -147,6 +147,9 @@
|
|||
|
||||
const char *hwaddr_ntoa(const void *, size_t, char *, size_t);
|
||||
size_t hwaddr_aton(uint8_t *, const char *);
|
||||
size_t read_hwaddr_aton(uint8_t **, const char *);
|
||||
ssize_t readfile(const char *, void *, size_t);
|
||||
ssize_t writefile(const char *, mode_t, const void *, size_t);
|
||||
int filemtime(const char *, time_t *);
|
||||
char *get_line(char ** __restrict, ssize_t * __restrict);
|
||||
int is_root_local(void);
|
||||
#endif
|
||||
|
|
|
@ -193,21 +193,33 @@ control_handle_unpriv(void *arg)
|
|||
}
|
||||
|
||||
static int
|
||||
make_sock(struct sockaddr_un *sa, const char *ifname, bool unpriv)
|
||||
make_sock(struct sockaddr_un *sa, const char *ifname, sa_family_t family,
|
||||
bool unpriv)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
|
||||
if ((fd = xsocket(AF_UNIX, SOCK_STREAM | SOCK_FLAGS, 0)) == -1)
|
||||
if ((fd = xsocket(AF_UNIX, SOCK_STREAM | SOCK_CXNB, 0)) == -1)
|
||||
return -1;
|
||||
#undef SOCK_FLAGS
|
||||
memset(sa, 0, sizeof(*sa));
|
||||
sa->sun_family = AF_UNIX;
|
||||
if (unpriv)
|
||||
strlcpy(sa->sun_path, UNPRIVSOCKET, sizeof(sa->sun_path));
|
||||
else {
|
||||
const char *per;
|
||||
|
||||
switch(family) {
|
||||
case AF_INET:
|
||||
per = "-4";
|
||||
break;
|
||||
case AF_INET6:
|
||||
per = "-6";
|
||||
break;
|
||||
default:
|
||||
per = "";
|
||||
break;
|
||||
}
|
||||
snprintf(sa->sun_path, sizeof(sa->sun_path), CONTROLSOCKET,
|
||||
ifname ? ifname : "", ifname ? "." : "");
|
||||
ifname ? ifname : "", ifname ? per : "", ifname ? "." : "");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
@ -216,14 +228,17 @@ make_sock(struct sockaddr_un *sa, const char *ifname, bool unpriv)
|
|||
#define S_UNPRIV (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||
|
||||
static int
|
||||
control_start1(struct dhcpcd_ctx *ctx, const char *ifname, mode_t fmode)
|
||||
control_start1(struct dhcpcd_ctx *ctx, const char *ifname, sa_family_t family,
|
||||
mode_t fmode)
|
||||
{
|
||||
struct sockaddr_un sa;
|
||||
int fd;
|
||||
socklen_t len;
|
||||
|
||||
if ((fd = make_sock(&sa, ifname, (fmode & S_UNPRIV) == S_UNPRIV)) == -1)
|
||||
fd = make_sock(&sa, ifname, family, (fmode & S_UNPRIV) == S_UNPRIV);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
len = (socklen_t)SUN_LEN(&sa);
|
||||
unlink(sa.sun_path);
|
||||
if (bind(fd, (struct sockaddr *)&sa, len) == -1 ||
|
||||
|
@ -244,17 +259,19 @@ control_start1(struct dhcpcd_ctx *ctx, const char *ifname, mode_t fmode)
|
|||
}
|
||||
|
||||
int
|
||||
control_start(struct dhcpcd_ctx *ctx, const char *ifname)
|
||||
control_start(struct dhcpcd_ctx *ctx, const char *ifname, sa_family_t family)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = control_start1(ctx, ifname, S_PRIV)) == -1)
|
||||
if ((fd = control_start1(ctx, ifname, family, S_PRIV)) == -1)
|
||||
return -1;
|
||||
|
||||
ctx->control_fd = fd;
|
||||
eloop_event_add(ctx->eloop, fd, control_handle, ctx);
|
||||
|
||||
if (ifname == NULL && (fd = control_start1(ctx, NULL, S_UNPRIV)) != -1){
|
||||
if (ifname == NULL &&
|
||||
(fd = control_start1(ctx, NULL, AF_UNSPEC, S_UNPRIV)) != -1)
|
||||
{
|
||||
/* We must be in master mode, so create an unprivileged socket
|
||||
* to allow normal users to learn the status of dhcpcd. */
|
||||
ctx->control_unpriv_fd = fd;
|
||||
|
@ -318,12 +335,12 @@ control_stop(struct dhcpcd_ctx *ctx)
|
|||
}
|
||||
|
||||
int
|
||||
control_open(const char *ifname, bool unpriv)
|
||||
control_open(const char *ifname, sa_family_t family, bool unpriv)
|
||||
{
|
||||
struct sockaddr_un sa;
|
||||
int fd;
|
||||
|
||||
if ((fd = make_sock(&sa, ifname, unpriv)) != -1) {
|
||||
if ((fd = make_sock(&sa, ifname, family, unpriv)) != -1) {
|
||||
socklen_t len;
|
||||
|
||||
len = (socklen_t)SUN_LEN(&sa);
|
||||
|
|
|
@ -66,9 +66,9 @@ TAILQ_HEAD(fd_list_head, fd_list);
|
|||
#define FD_LISTEN (1<<0)
|
||||
#define FD_UNPRIV (1<<1)
|
||||
|
||||
int control_start(struct dhcpcd_ctx *, const char *);
|
||||
int control_start(struct dhcpcd_ctx *, const char *, sa_family_t);
|
||||
int control_stop(struct dhcpcd_ctx *);
|
||||
int control_open(const char *, bool);
|
||||
int control_open(const char *, sa_family_t, bool);
|
||||
ssize_t control_send(struct dhcpcd_ctx *, int, char * const *);
|
||||
int control_queue(struct fd_list *, void *, size_t, bool);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "9.0.2"
|
||||
#define VERSION "9.1.0"
|
||||
|
||||
#ifndef PRIVSEP_USER
|
||||
# define PRIVSEP_USER "_" PACKAGE
|
||||
|
@ -60,7 +60,7 @@
|
|||
# define PIDFILE RUNDIR "/%s%s%spid"
|
||||
#endif
|
||||
#ifndef CONTROLSOCKET
|
||||
# define CONTROLSOCKET RUNDIR "/%s%ssock"
|
||||
# define CONTROLSOCKET RUNDIR "/%s%s%ssock"
|
||||
#endif
|
||||
#ifndef UNPRIVSOCKET
|
||||
# define UNPRIVSOCKET RUNDIR "/unpriv.sock"
|
||||
|
|
|
@ -49,13 +49,8 @@ int dev_init(struct dev *, const struct dev_dhcpcd *);
|
|||
#include "dhcpcd.h"
|
||||
int dev_initialized(struct dhcpcd_ctx *, const char *);
|
||||
int dev_listening(struct dhcpcd_ctx *);
|
||||
int dev_start(struct dhcpcd_ctx *);
|
||||
int dev_start(struct dhcpcd_ctx *, int (*)(void *, int, const char *));
|
||||
void dev_stop(struct dhcpcd_ctx *);
|
||||
#else
|
||||
#define dev_initialized(a, b) (1)
|
||||
#define dev_listening(a) (0)
|
||||
#define dev_start(a) {}
|
||||
#define dev_stop(a) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -176,9 +175,10 @@ dhcp_vendor(char *str, size_t len)
|
|||
return -1;
|
||||
p += l;
|
||||
len -= (size_t)l;
|
||||
l = if_machinearch(p, len);
|
||||
l = if_machinearch(p + 1, len - 1);
|
||||
if (l == -1 || (size_t)(l + 1) > len)
|
||||
return -1;
|
||||
*p = ':';
|
||||
p += l;
|
||||
return p - str;
|
||||
}
|
||||
|
@ -202,8 +202,8 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
|
|||
continue;
|
||||
if (strncmp(token, "dhcp6_", 6) == 0)
|
||||
token += 6;
|
||||
if (strncmp(token, "nd6_", 4) == 0)
|
||||
token += 4;
|
||||
if (strncmp(token, "nd_", 3) == 0)
|
||||
token += 3;
|
||||
match = 0;
|
||||
for (i = 0, opt = odopts; i < odopts_len; i++, opt++) {
|
||||
if (opt->var == NULL || opt->option == 0)
|
||||
|
@ -945,38 +945,85 @@ dhcp_zero_index(struct dhcp_opt *opt)
|
|||
dhcp_zero_index(o);
|
||||
}
|
||||
|
||||
size_t
|
||||
dhcp_read_lease_fd(int fd, void **lease)
|
||||
ssize_t
|
||||
dhcp_readfile(struct dhcpcd_ctx *ctx, const char *file, void *data, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
size_t sz;
|
||||
void *buf;
|
||||
ssize_t len;
|
||||
|
||||
if (fstat(fd, &st) != 0)
|
||||
goto out;
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (st.st_size > UINT32_MAX) {
|
||||
errno = E2BIG;
|
||||
goto out;
|
||||
}
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP &&
|
||||
!(ctx->options & DHCPCD_PRIVSEPROOT))
|
||||
return ps_root_readfile(ctx, file, data, len);
|
||||
#else
|
||||
UNUSED(ctx);
|
||||
#endif
|
||||
|
||||
sz = (size_t)st.st_size;
|
||||
if (sz == 0)
|
||||
goto out;
|
||||
if ((buf = malloc(sz)) == NULL)
|
||||
goto out;
|
||||
if ((len = read(fd, buf, sz)) == -1) {
|
||||
free(buf);
|
||||
goto out;
|
||||
}
|
||||
*lease = buf;
|
||||
return (size_t)len;
|
||||
|
||||
out:
|
||||
*lease = NULL;
|
||||
return 0;
|
||||
return readfile(file, data, len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
dhcp_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP &&
|
||||
!(ctx->options & DHCPCD_PRIVSEPROOT))
|
||||
return ps_root_writefile(ctx, file, mode, data, len);
|
||||
#else
|
||||
UNUSED(ctx);
|
||||
#endif
|
||||
|
||||
return writefile(file, mode, data, len);
|
||||
}
|
||||
|
||||
int
|
||||
dhcp_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
|
||||
{
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP &&
|
||||
!(ctx->options & DHCPCD_PRIVSEPROOT))
|
||||
return (int)ps_root_filemtime(ctx, file, time);
|
||||
#else
|
||||
UNUSED(ctx);
|
||||
#endif
|
||||
|
||||
return filemtime(file, time);
|
||||
}
|
||||
|
||||
int
|
||||
dhcp_unlink(struct dhcpcd_ctx *ctx, const char *file)
|
||||
{
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP &&
|
||||
!(ctx->options & DHCPCD_PRIVSEPROOT))
|
||||
return (int)ps_root_unlink(ctx, file);
|
||||
#else
|
||||
UNUSED(ctx);
|
||||
#endif
|
||||
|
||||
return unlink(file);
|
||||
}
|
||||
|
||||
size_t
|
||||
dhcp_read_hwaddr_aton(struct dhcpcd_ctx *ctx, uint8_t **data, const char *file)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
ssize_t bytes;
|
||||
size_t len;
|
||||
|
||||
bytes = dhcp_readfile(ctx, file, buf, sizeof(buf));
|
||||
if (bytes == -1 || bytes == sizeof(buf))
|
||||
return 0;
|
||||
|
||||
bytes[buf] = '\0';
|
||||
len = hwaddr_aton(NULL, buf);
|
||||
if (len == 0)
|
||||
return 0;
|
||||
*data = malloc(len);
|
||||
if (*data == NULL)
|
||||
return 0;
|
||||
hwaddr_aton(*data, buf);
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -136,6 +136,11 @@ void dhcp_envoption(struct dhcpcd_ctx *,
|
|||
const uint8_t *, size_t, struct dhcp_opt **),
|
||||
const uint8_t *od, size_t ol);
|
||||
void dhcp_zero_index(struct dhcp_opt *);
|
||||
size_t dhcp_read_lease_fd(int, void **);
|
||||
|
||||
ssize_t dhcp_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
|
||||
ssize_t dhcp_writefile(struct dhcpcd_ctx *, const char *, mode_t,
|
||||
const void *, size_t);
|
||||
int dhcp_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
|
||||
int dhcp_unlink(struct dhcpcd_ctx *, const char *);
|
||||
size_t dhcp_read_hwaddr_aton(struct dhcpcd_ctx *, uint8_t **, const char *);
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "arp.h"
|
||||
#include "bpf.h"
|
||||
#include "auth.h"
|
||||
#include "dhcp-common.h"
|
||||
|
||||
|
@ -221,9 +222,8 @@ struct dhcp_state {
|
|||
uint32_t xid;
|
||||
int socket;
|
||||
|
||||
int bpf_fd;
|
||||
unsigned int bpf_flags;
|
||||
int udp_fd;
|
||||
struct bpf *bpf;
|
||||
int udp_rfd;
|
||||
struct ipv4_addr *addr;
|
||||
uint8_t added;
|
||||
|
||||
|
@ -256,7 +256,7 @@ ssize_t print_rfc3361(FILE *, const uint8_t *, size_t);
|
|||
ssize_t print_rfc3442(FILE *, const uint8_t *, size_t);
|
||||
|
||||
int dhcp_openudp(struct in_addr *);
|
||||
void dhcp_packet(struct interface *, uint8_t *, size_t);
|
||||
void dhcp_packet(struct interface *, uint8_t *, size_t, unsigned int);
|
||||
void dhcp_recvmsg(struct dhcpcd_ctx *, struct msghdr *);
|
||||
void dhcp_printoptions(const struct dhcpcd_ctx *,
|
||||
const struct dhcp_opt *, size_t);
|
||||
|
|
|
@ -168,9 +168,10 @@ enum DH6S {
|
|||
DH6S_INFORMED,
|
||||
DH6S_RENEW_REQUESTED,
|
||||
DH6S_PROBE,
|
||||
DH6S_DECLINE,
|
||||
DH6S_DELEGATED,
|
||||
DH6S_RELEASE,
|
||||
DH6S_RELEASED
|
||||
DH6S_RELEASED,
|
||||
};
|
||||
|
||||
struct dhcp6_state {
|
||||
|
@ -225,6 +226,7 @@ struct dhcp6_state {
|
|||
(D6_CSTATE((ifp)) && \
|
||||
D6_CSTATE((ifp))->reason && dhcp6_dadcompleted((ifp)))
|
||||
|
||||
int dhcp6_openraw(void);
|
||||
int dhcp6_openudp(unsigned int, struct in6_addr *);
|
||||
void dhcp6_recvmsg(struct dhcpcd_ctx *, struct msghdr *, struct ipv6_addr *);
|
||||
void dhcp6_printoptions(const struct dhcpcd_ctx *,
|
||||
|
|
|
@ -33,458 +33,458 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
const char * const dhcpcd_embedded_conf[] = {
|
||||
const char dhcpcd_embedded_conf[] =
|
||||
#ifdef SMALL
|
||||
"define 1 request ipaddress subnet_mask",
|
||||
"define 121 rfc3442 classless_static_routes",
|
||||
"define 3 request array ipaddress routers",
|
||||
"define 6 array ipaddress domain_name_servers",
|
||||
"define 12 dname host_name",
|
||||
"define 15 array dname domain_name",
|
||||
"define 26 uint16 interface_mtu",
|
||||
"define 28 request ipaddress broadcast_address",
|
||||
"define 33 request array ipaddress static_routes",
|
||||
"define 50 ipaddress dhcp_requested_address",
|
||||
"define 51 request uint32 dhcp_lease_time",
|
||||
"define 52 byte dhcp_option_overload",
|
||||
"define 53 byte dhcp_message_type",
|
||||
"define 54 ipaddress dhcp_server_identifier",
|
||||
"define 55 array byte dhcp_parameter_request_list",
|
||||
"define 56 string dhcp_message",
|
||||
"define 57 uint16 dhcp_max_message_size",
|
||||
"define 58 request uint32 dhcp_renewal_time",
|
||||
"define 59 request uint32 dhcp_rebinding_time",
|
||||
"define 60 string vendor_class_identifier",
|
||||
"define 61 binhex dhcp_client_identifier",
|
||||
"define 80 norequest flag rapid_commit",
|
||||
"define 81 embed fqdn",
|
||||
"embed bitflags=0000NEOS flags",
|
||||
"embed byte rcode1",
|
||||
"embed byte rcode2",
|
||||
"embed optional domain fqdn",
|
||||
"define 119 array domain domain_search",
|
||||
"define 249 rfc3442 ms_classless_static_routes",
|
||||
"definend 1 binhex source_address",
|
||||
"definend 2 binhex target_address",
|
||||
"definend 3 index embed prefix_information",
|
||||
"embed byte length",
|
||||
"embed bitflags=LA flags",
|
||||
"embed uint32 vltime",
|
||||
"embed uint32 pltime",
|
||||
"embed uint32 reserved",
|
||||
"embed array ip6address prefix",
|
||||
"definend 5 embed mtu",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 mtu",
|
||||
"definend 25 index embed rdnss",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 lifetime",
|
||||
"embed array ip6address servers",
|
||||
"definend 31 index embed dnssl",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 lifetime",
|
||||
"embed domain search",
|
||||
"define6 1 binhex client_id",
|
||||
"define6 2 binhex server_id",
|
||||
"define6 3 norequest index embed ia_na",
|
||||
"embed binhex:4 iaid",
|
||||
"embed uint32 t1",
|
||||
"embed uint32 t2",
|
||||
"encap 5 option",
|
||||
"encap 13 option",
|
||||
"define6 4 norequest index embed ia_ta",
|
||||
"embed uint32 iaid",
|
||||
"encap 5 option",
|
||||
"encap 13 option",
|
||||
"define6 5 norequest index embed ia_addr",
|
||||
"embed ip6address ia_addr",
|
||||
"embed uint32 pltime",
|
||||
"embed uint32 vltime",
|
||||
"encap 13 option",
|
||||
"define6 12 ip6address unicast",
|
||||
"define6 13 norequest embed status_code",
|
||||
"embed uint16 status_code",
|
||||
"embed optional string message",
|
||||
"define6 18 binhex interface_id",
|
||||
"define6 19 byte reconfigure_msg",
|
||||
"define6 20 flag reconfigure_accept",
|
||||
"define6 23 array ip6address name_servers",
|
||||
"define6 24 array domain domain_search",
|
||||
"define6 39 embed fqdn",
|
||||
"embed bitflags=00000NOS flags",
|
||||
"embed optional domain fqdn",
|
||||
"define6 82 request uint32 sol_max_rt",
|
||||
"define6 83 request uint32 inf_max_rt",
|
||||
"define 1 request ipaddress subnet_mask\n"
|
||||
"define 121 rfc3442 classless_static_routes\n"
|
||||
"define 3 request array ipaddress routers\n"
|
||||
"define 6 array ipaddress domain_name_servers\n"
|
||||
"define 12 dname host_name\n"
|
||||
"define 15 array dname domain_name\n"
|
||||
"define 26 uint16 interface_mtu\n"
|
||||
"define 28 request ipaddress broadcast_address\n"
|
||||
"define 33 request array ipaddress static_routes\n"
|
||||
"define 50 ipaddress dhcp_requested_address\n"
|
||||
"define 51 request uint32 dhcp_lease_time\n"
|
||||
"define 52 byte dhcp_option_overload\n"
|
||||
"define 53 byte dhcp_message_type\n"
|
||||
"define 54 ipaddress dhcp_server_identifier\n"
|
||||
"define 55 array byte dhcp_parameter_request_list\n"
|
||||
"define 56 string dhcp_message\n"
|
||||
"define 57 uint16 dhcp_max_message_size\n"
|
||||
"define 58 request uint32 dhcp_renewal_time\n"
|
||||
"define 59 request uint32 dhcp_rebinding_time\n"
|
||||
"define 60 string vendor_class_identifier\n"
|
||||
"define 61 binhex dhcp_client_identifier\n"
|
||||
"define 80 norequest flag rapid_commit\n"
|
||||
"define 81 embed fqdn\n"
|
||||
"embed bitflags=0000NEOS flags\n"
|
||||
"embed byte rcode1\n"
|
||||
"embed byte rcode2\n"
|
||||
"embed optional domain fqdn\n"
|
||||
"define 119 array domain domain_search\n"
|
||||
"define 249 rfc3442 ms_classless_static_routes\n"
|
||||
"definend 1 binhex source_address\n"
|
||||
"definend 2 binhex target_address\n"
|
||||
"definend 3 index embed prefix_information\n"
|
||||
"embed byte length\n"
|
||||
"embed bitflags=LA flags\n"
|
||||
"embed uint32 vltime\n"
|
||||
"embed uint32 pltime\n"
|
||||
"embed uint32 reserved\n"
|
||||
"embed array ip6address prefix\n"
|
||||
"definend 5 embed mtu\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 mtu\n"
|
||||
"definend 25 index embed rdnss\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 lifetime\n"
|
||||
"embed array ip6address servers\n"
|
||||
"definend 31 index embed dnssl\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 lifetime\n"
|
||||
"embed domain search\n"
|
||||
"define6 1 binhex client_id\n"
|
||||
"define6 2 binhex server_id\n"
|
||||
"define6 3 norequest index embed ia_na\n"
|
||||
"embed binhex:4 iaid\n"
|
||||
"embed uint32 t1\n"
|
||||
"embed uint32 t2\n"
|
||||
"encap 5 option\n"
|
||||
"encap 13 option\n"
|
||||
"define6 4 norequest index embed ia_ta\n"
|
||||
"embed uint32 iaid\n"
|
||||
"encap 5 option\n"
|
||||
"encap 13 option\n"
|
||||
"define6 5 norequest index embed ia_addr\n"
|
||||
"embed ip6address ia_addr\n"
|
||||
"embed uint32 pltime\n"
|
||||
"embed uint32 vltime\n"
|
||||
"encap 13 option\n"
|
||||
"define6 12 ip6address unicast\n"
|
||||
"define6 13 norequest embed status_code\n"
|
||||
"embed uint16 status_code\n"
|
||||
"embed optional string message\n"
|
||||
"define6 18 binhex interface_id\n"
|
||||
"define6 19 byte reconfigure_msg\n"
|
||||
"define6 20 flag reconfigure_accept\n"
|
||||
"define6 23 array ip6address name_servers\n"
|
||||
"define6 24 array domain domain_search\n"
|
||||
"define6 39 embed fqdn\n"
|
||||
"embed bitflags=00000NOS flags\n"
|
||||
"embed optional domain fqdn\n"
|
||||
"define6 82 request uint32 sol_max_rt\n"
|
||||
"define6 83 request uint32 inf_max_rt\n"
|
||||
#else
|
||||
"define 1 request ipaddress subnet_mask",
|
||||
"define 121 rfc3442 classless_static_routes",
|
||||
"define 2 uint32 time_offset",
|
||||
"define 3 request array ipaddress routers",
|
||||
"define 4 array ipaddress time_servers",
|
||||
"define 5 array ipaddress ien116_name_servers",
|
||||
"define 6 array ipaddress domain_name_servers",
|
||||
"define 7 array ipaddress log_servers",
|
||||
"define 8 array ipaddress cookie_servers",
|
||||
"define 9 array ipaddress lpr_servers",
|
||||
"define 10 array ipaddress impress_servers",
|
||||
"define 11 array ipaddress resource_location_servers",
|
||||
"define 12 dname host_name",
|
||||
"define 13 uint16 boot_size",
|
||||
"define 14 string merit_dump",
|
||||
"define 15 array dname domain_name",
|
||||
"define 16 ipaddress swap_server",
|
||||
"define 17 string root_path",
|
||||
"define 18 string extensions_path",
|
||||
"define 19 byte ip_forwarding",
|
||||
"define 20 byte non_local_source_routing",
|
||||
"define 21 array ipaddress policy_filter",
|
||||
"define 22 uint16 max_dgram_reassembly",
|
||||
"define 23 byte default_ip_ttl",
|
||||
"define 24 uint32 path_mtu_aging_timeout",
|
||||
"define 25 array uint16 path_mtu_plateau_table",
|
||||
"define 26 uint16 interface_mtu",
|
||||
"define 27 byte all_subnets_local",
|
||||
"define 28 request ipaddress broadcast_address",
|
||||
"define 29 byte perform_mask_discovery",
|
||||
"define 30 byte mask_supplier",
|
||||
"define 31 byte router_discovery",
|
||||
"define 32 ipaddress router_solicitation_address",
|
||||
"define 33 request array ipaddress static_routes",
|
||||
"define 34 byte trailer_encapsulation",
|
||||
"define 35 uint32 arp_cache_timeout",
|
||||
"define 36 uint16 ieee802_3_encapsulation",
|
||||
"define 37 byte default_tcp_ttl",
|
||||
"define 38 uint32 tcp_keepalive_interval",
|
||||
"define 39 byte tcp_keepalive_garbage",
|
||||
"define 40 string nis_domain",
|
||||
"define 41 array ipaddress nis_servers",
|
||||
"define 42 array ipaddress ntp_servers",
|
||||
"define 43 binhex vendor_encapsulated_options",
|
||||
"define 44 array ipaddress netbios_name_servers",
|
||||
"define 45 ipaddress netbios_dd_server",
|
||||
"define 46 byte netbios_node_type",
|
||||
"define 47 string netbios_scope",
|
||||
"define 48 array ipaddress font_servers",
|
||||
"define 49 array ipaddress x_display_manager",
|
||||
"define 50 ipaddress dhcp_requested_address",
|
||||
"define 51 request uint32 dhcp_lease_time",
|
||||
"define 52 byte dhcp_option_overload",
|
||||
"define 53 byte dhcp_message_type",
|
||||
"define 54 ipaddress dhcp_server_identifier",
|
||||
"define 55 array byte dhcp_parameter_request_list",
|
||||
"define 56 string dhcp_message",
|
||||
"define 57 uint16 dhcp_max_message_size",
|
||||
"define 58 request uint32 dhcp_renewal_time",
|
||||
"define 59 request uint32 dhcp_rebinding_time",
|
||||
"define 60 string vendor_class_identifier",
|
||||
"define 61 binhex dhcp_client_identifier",
|
||||
"define 64 string nisplus_domain",
|
||||
"define 65 array ipaddress nisplus_servers",
|
||||
"define 66 dname tftp_server_name",
|
||||
"define 67 string bootfile_name",
|
||||
"define 68 array ipaddress mobile_ip_home_agent",
|
||||
"define 69 array ipaddress smtp_server",
|
||||
"define 70 array ipaddress pop_server",
|
||||
"define 71 array ipaddress nntp_server",
|
||||
"define 72 array ipaddress www_server",
|
||||
"define 73 array ipaddress finger_server",
|
||||
"define 74 array ipaddress irc_server",
|
||||
"define 75 array ipaddress streettalk_server",
|
||||
"define 76 array ipaddress streettalk_directory_assistance_server",
|
||||
"define 77 binhex user_class",
|
||||
"define 78 embed slp_agent",
|
||||
"embed byte mandatory",
|
||||
"embed array ipaddress address",
|
||||
"define 79 embed slp_service",
|
||||
"embed byte mandatory",
|
||||
"embed ascii scope_list",
|
||||
"define 80 norequest flag rapid_commit",
|
||||
"define 81 embed fqdn",
|
||||
"embed bitflags=0000NEOS flags",
|
||||
"embed byte rcode1",
|
||||
"embed byte rcode2",
|
||||
"embed optional domain fqdn",
|
||||
"define 83 embed isns",
|
||||
"embed byte reserved1",
|
||||
"embed bitflags=00000SAE functions",
|
||||
"embed byte reserved2",
|
||||
"embed bitflags=00fFsSCE dd",
|
||||
"embed byte reserved3",
|
||||
"embed bitflags=0000DMHE admin",
|
||||
"embed uint16 reserved4",
|
||||
"embed byte reserved5",
|
||||
"embed bitflags=0TXPAMSE server_security",
|
||||
"embed array ipaddress servers",
|
||||
"define 85 array ipaddress nds_servers",
|
||||
"define 86 raw nds_tree_name",
|
||||
"define 87 raw nds_context",
|
||||
"define 88 array domain bcms_controller_names",
|
||||
"define 89 array ipaddress bcms_controller_address",
|
||||
"define 90 embed auth",
|
||||
"embed byte protocol",
|
||||
"embed byte algorithm",
|
||||
"embed byte rdm",
|
||||
"embed binhex:8 replay",
|
||||
"embed binhex information",
|
||||
"define 91 uint32 client_last_transaction_time",
|
||||
"define 92 array ipaddress associated_ip",
|
||||
"define 98 string uap_servers",
|
||||
"define 99 encap geoconf_civic",
|
||||
"embed byte what",
|
||||
"embed uint16 country_code",
|
||||
"define 100 string posix_timezone",
|
||||
"define 101 string tzdb_timezone",
|
||||
"define 116 byte auto_configure",
|
||||
"define 117 array uint16 name_service_search",
|
||||
"define 118 ipaddress subnet_selection",
|
||||
"define 119 array domain domain_search",
|
||||
"define 120 rfc3361 sip_server",
|
||||
"define 122 encap tsp",
|
||||
"encap 1 ipaddress dhcp_server",
|
||||
"encap 2 ipaddress dhcp_secondary_server",
|
||||
"encap 3 rfc3361 provisioning_server",
|
||||
"encap 4 embed as_req_as_rep_backoff",
|
||||
"embed uint32 nominal",
|
||||
"embed uint32 maximum",
|
||||
"embed uint32 retry",
|
||||
"encap 5 embed ap_req_ap_rep_backoff",
|
||||
"embed uint32 nominal",
|
||||
"embed uint32 maximum",
|
||||
"embed uint32 retry",
|
||||
"encap 6 domain kerberos_realm",
|
||||
"encap 7 byte ticket_granting_server_utilization",
|
||||
"encap 8 byte provisioning_timer",
|
||||
"define 123 binhex geoconf",
|
||||
"define 124 binhex vivco",
|
||||
"define 125 embed vivso",
|
||||
"embed uint32 enterprise_number",
|
||||
"define 136 array ipaddress pana_agent",
|
||||
"define 137 domain lost_server",
|
||||
"define 138 array ipaddress capwap_ac",
|
||||
"define 139 encap mos_ip",
|
||||
"encap 1 array ipaddress is",
|
||||
"encap 2 array ipaddress cs",
|
||||
"encap 3 array ipaddress es",
|
||||
"define 140 encap mos_domain",
|
||||
"encap 1 domain is",
|
||||
"encap 2 domain cs",
|
||||
"encap 3 domain es",
|
||||
"define 141 array domain sip_ua_cs_list",
|
||||
"define 142 array ipaddress andsf",
|
||||
"define 143 array ip6address andsf6",
|
||||
"define 144 binhex geoloc",
|
||||
"define 145 array byte forcerenew_nonce_capable",
|
||||
"define 146 embed rdnss_selection",
|
||||
"embed byte prf",
|
||||
"embed ipaddress primary",
|
||||
"embed ipaddress secondary",
|
||||
"embed array domain domains",
|
||||
"define 150 array ipaddress tftp_servers",
|
||||
"define 161 string mudurl",
|
||||
"define 208 binhex pxelinux_magic",
|
||||
"define 209 string config_file",
|
||||
"define 210 string path_prefix",
|
||||
"define 211 uint32 reboot_time",
|
||||
"define 212 embed sixrd",
|
||||
"embed byte mask_len",
|
||||
"embed byte prefix_len",
|
||||
"embed ip6address prefix",
|
||||
"embed array ipaddress brip_address",
|
||||
"define 213 domain access_domain",
|
||||
"define 221 encap vss",
|
||||
"encap 0 string nvt",
|
||||
"encap 1 binhex vpn_id",
|
||||
"encap 255 flag global",
|
||||
"define 249 rfc3442 ms_classless_static_routes",
|
||||
"define 252 string wpad_url",
|
||||
"definend 1 binhex source_address",
|
||||
"definend 2 binhex target_address",
|
||||
"definend 3 index embed prefix_information",
|
||||
"embed byte length",
|
||||
"embed bitflags=LA flags",
|
||||
"embed uint32 vltime",
|
||||
"embed uint32 pltime",
|
||||
"embed uint32 reserved",
|
||||
"embed array ip6address prefix",
|
||||
"definend 5 embed mtu",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 mtu",
|
||||
"definend 25 index embed rdnss",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 lifetime",
|
||||
"embed array ip6address servers",
|
||||
"definend 31 index embed dnssl",
|
||||
"embed uint16 reserved",
|
||||
"embed uint32 lifetime",
|
||||
"embed domain search",
|
||||
"define6 1 binhex client_id",
|
||||
"define6 2 binhex server_id",
|
||||
"define6 3 norequest index embed ia_na",
|
||||
"embed binhex:4 iaid",
|
||||
"embed uint32 t1",
|
||||
"embed uint32 t2",
|
||||
"encap 5 option",
|
||||
"encap 13 option",
|
||||
"define6 4 norequest index embed ia_ta",
|
||||
"embed uint32 iaid",
|
||||
"encap 5 option",
|
||||
"encap 13 option",
|
||||
"define6 5 norequest index embed ia_addr",
|
||||
"embed ip6address ia_addr",
|
||||
"embed uint32 pltime",
|
||||
"embed uint32 vltime",
|
||||
"encap 13 option",
|
||||
"define6 6 array uint16 option_request",
|
||||
"define6 7 byte preference",
|
||||
"define6 8 uint16 elased_time",
|
||||
"define6 9 binhex dhcp_relay_msg",
|
||||
"define6 11 embed auth",
|
||||
"embed byte protocol",
|
||||
"embed byte algorithm",
|
||||
"embed byte rdm",
|
||||
"embed binhex:8 replay",
|
||||
"embed binhex information",
|
||||
"define6 12 ip6address unicast",
|
||||
"define6 13 norequest embed status_code",
|
||||
"embed uint16 status_code",
|
||||
"embed optional string message",
|
||||
"define6 14 norequest flag rapid_commit",
|
||||
"define6 15 binhex user_class",
|
||||
"define6 16 binhex vivco",
|
||||
"define6 17 embed vivso",
|
||||
"embed uint32 enterprise_number",
|
||||
"define6 18 binhex interface_id",
|
||||
"define6 19 byte reconfigure_msg",
|
||||
"define6 20 flag reconfigure_accept",
|
||||
"define6 21 array domain sip_servers_names",
|
||||
"define6 22 array ip6address sip_servers_addresses",
|
||||
"define6 23 array ip6address name_servers",
|
||||
"define6 24 array domain domain_search",
|
||||
"define6 25 norequest index embed ia_pd",
|
||||
"embed binhex:4 iaid",
|
||||
"embed uint32 t1",
|
||||
"embed uint32 t2",
|
||||
"encap 26 option",
|
||||
"define6 26 index embed prefix",
|
||||
"embed uint32 pltime",
|
||||
"embed uint32 vltime",
|
||||
"embed byte length",
|
||||
"embed ip6address prefix",
|
||||
"encap 13 option",
|
||||
"encap 67 option",
|
||||
"define6 27 array ip6address nis_servers",
|
||||
"define6 28 array ip6address nisp_servers",
|
||||
"define6 29 string nis_domain_name",
|
||||
"define6 30 string nisp_domain_name",
|
||||
"define6 31 array ip6address sntp_servers",
|
||||
"define6 32 uint32 info_refresh_time",
|
||||
"define6 33 array domain bcms_server_d",
|
||||
"define6 34 array ip6address bcms_server_a",
|
||||
"define6 36 encap geoconf_civic",
|
||||
"embed byte what",
|
||||
"embed uint16 country_code",
|
||||
"define6 37 embed remote_id",
|
||||
"embed uint32 enterprise_number",
|
||||
"embed binhex remote_id",
|
||||
"define6 38 binhex subscriber_id",
|
||||
"define6 39 embed fqdn",
|
||||
"embed bitflags=00000NOS flags",
|
||||
"embed optional domain fqdn",
|
||||
"define6 40 array ip6address pana_agent",
|
||||
"define6 41 string posix_timezone",
|
||||
"define6 42 string tzdb_timezone",
|
||||
"define6 43 array uint16 ero",
|
||||
"define6 49 domain mip6_hnidf",
|
||||
"define6 50 encap mip6_vdinf",
|
||||
"encap 71 option",
|
||||
"encap 72 option",
|
||||
"encap 73 option",
|
||||
"define6 51 domain lost_server",
|
||||
"define6 52 array ip6address capwap_ac",
|
||||
"define6 53 binhex relay_id",
|
||||
"define6 54 encap mos_ip",
|
||||
"encap 1 array ip6address is",
|
||||
"encap 2 array ip6address cs",
|
||||
"encap 3 array ip6address es",
|
||||
"define6 55 encap mos_domain",
|
||||
"encap 1 domain is",
|
||||
"encap 2 domain cs",
|
||||
"encap 3 domain es",
|
||||
"define6 56 encap ntp_server",
|
||||
"encap 1 ip6address addr",
|
||||
"encap 2 ip6address mcast_addr",
|
||||
"encap 3 domain fqdn",
|
||||
"define6 57 domain access_domain",
|
||||
"define6 58 array domain sip_ua_cs_list",
|
||||
"define6 59 string bootfile_url",
|
||||
"define6 60 binhex bootfile_param",
|
||||
"define6 61 array uint16 architecture_types",
|
||||
"define6 62 embed nii",
|
||||
"embed byte type",
|
||||
"embed byte major",
|
||||
"embed byte minor",
|
||||
"define6 63 binhex geoloc",
|
||||
"define6 64 domain aftr_name",
|
||||
"define6 67 embed pd_exclude",
|
||||
"embed byte prefix_len",
|
||||
"embed binhex subnetID",
|
||||
"define6 69 encap mip6_idinf",
|
||||
"encap 71 option",
|
||||
"encap 72 option",
|
||||
"encap 73 option",
|
||||
"define6 70 encap mip6_udinf",
|
||||
"encap 71 option",
|
||||
"encap 72 option",
|
||||
"encap 73 option",
|
||||
"define6 71 embed mip6_hnp",
|
||||
"embed byte prefix_len",
|
||||
"embed ip6address prefix",
|
||||
"define6 72 ip6address mip6_haa",
|
||||
"define6 73 domain mip6_haf",
|
||||
"define6 74 embed rdnss_selection",
|
||||
"embed ip6address server",
|
||||
"embed byte prf",
|
||||
"embed array domain domains",
|
||||
"define6 75 string krb_principal_name",
|
||||
"define6 76 string krb_realm_name",
|
||||
"define6 78 embed krb_kdc",
|
||||
"embed uint16 priority",
|
||||
"embed uint16 weight",
|
||||
"embed byte transport_type",
|
||||
"embed uint16 port",
|
||||
"embed ip6address address",
|
||||
"embed string realm_name",
|
||||
"define6 80 ip6address link_address",
|
||||
"define6 82 request uint32 sol_max_rt",
|
||||
"define6 83 request uint32 inf_max_rt",
|
||||
"define6 89 embed s46_rule",
|
||||
"embed bitflags=0000000F flags",
|
||||
"embed byte ea_len",
|
||||
"embed byte prefix4_len",
|
||||
"embed ipaddress ipv4_prefix",
|
||||
"embed ip6address ipv6_prefix",
|
||||
"define6 90 ip6address s64_br",
|
||||
"define6 91 embed s46_dmr",
|
||||
"embed byte prefix_len",
|
||||
"embed binhex prefix",
|
||||
"define6 92 embed s46_v4v6bind",
|
||||
"embed ipaddress ipv4_address",
|
||||
"embed byte ipv6_prefix_len",
|
||||
"embed binhex ipv6_prefix_and_options",
|
||||
"define6 93 embed s46_portparams",
|
||||
"embed byte offset",
|
||||
"embed byte psid_len",
|
||||
"embed uint16 psid",
|
||||
"define6 94 embed s46_cont_mape",
|
||||
"encap 89 option",
|
||||
"encap 90 option",
|
||||
"define6 95 embed s46_cont_mapt",
|
||||
"encap 89 option",
|
||||
"encap 91 option",
|
||||
"define6 96 embed s46_cont_lw",
|
||||
"encap 90 option",
|
||||
"encap 92 option",
|
||||
"define6 112 string mudurl",
|
||||
"define 1 request ipaddress subnet_mask\n"
|
||||
"define 121 rfc3442 classless_static_routes\n"
|
||||
"define 2 uint32 time_offset\n"
|
||||
"define 3 request array ipaddress routers\n"
|
||||
"define 4 array ipaddress time_servers\n"
|
||||
"define 5 array ipaddress ien116_name_servers\n"
|
||||
"define 6 array ipaddress domain_name_servers\n"
|
||||
"define 7 array ipaddress log_servers\n"
|
||||
"define 8 array ipaddress cookie_servers\n"
|
||||
"define 9 array ipaddress lpr_servers\n"
|
||||
"define 10 array ipaddress impress_servers\n"
|
||||
"define 11 array ipaddress resource_location_servers\n"
|
||||
"define 12 dname host_name\n"
|
||||
"define 13 uint16 boot_size\n"
|
||||
"define 14 string merit_dump\n"
|
||||
"define 15 array dname domain_name\n"
|
||||
"define 16 ipaddress swap_server\n"
|
||||
"define 17 string root_path\n"
|
||||
"define 18 string extensions_path\n"
|
||||
"define 19 byte ip_forwarding\n"
|
||||
"define 20 byte non_local_source_routing\n"
|
||||
"define 21 array ipaddress policy_filter\n"
|
||||
"define 22 uint16 max_dgram_reassembly\n"
|
||||
"define 23 byte default_ip_ttl\n"
|
||||
"define 24 uint32 path_mtu_aging_timeout\n"
|
||||
"define 25 array uint16 path_mtu_plateau_table\n"
|
||||
"define 26 uint16 interface_mtu\n"
|
||||
"define 27 byte all_subnets_local\n"
|
||||
"define 28 request ipaddress broadcast_address\n"
|
||||
"define 29 byte perform_mask_discovery\n"
|
||||
"define 30 byte mask_supplier\n"
|
||||
"define 31 byte router_discovery\n"
|
||||
"define 32 ipaddress router_solicitation_address\n"
|
||||
"define 33 request array ipaddress static_routes\n"
|
||||
"define 34 byte trailer_encapsulation\n"
|
||||
"define 35 uint32 arp_cache_timeout\n"
|
||||
"define 36 uint16 ieee802_3_encapsulation\n"
|
||||
"define 37 byte default_tcp_ttl\n"
|
||||
"define 38 uint32 tcp_keepalive_interval\n"
|
||||
"define 39 byte tcp_keepalive_garbage\n"
|
||||
"define 40 string nis_domain\n"
|
||||
"define 41 array ipaddress nis_servers\n"
|
||||
"define 42 array ipaddress ntp_servers\n"
|
||||
"define 43 binhex vendor_encapsulated_options\n"
|
||||
"define 44 array ipaddress netbios_name_servers\n"
|
||||
"define 45 ipaddress netbios_dd_server\n"
|
||||
"define 46 byte netbios_node_type\n"
|
||||
"define 47 string netbios_scope\n"
|
||||
"define 48 array ipaddress font_servers\n"
|
||||
"define 49 array ipaddress x_display_manager\n"
|
||||
"define 50 ipaddress dhcp_requested_address\n"
|
||||
"define 51 request uint32 dhcp_lease_time\n"
|
||||
"define 52 byte dhcp_option_overload\n"
|
||||
"define 53 byte dhcp_message_type\n"
|
||||
"define 54 ipaddress dhcp_server_identifier\n"
|
||||
"define 55 array byte dhcp_parameter_request_list\n"
|
||||
"define 56 string dhcp_message\n"
|
||||
"define 57 uint16 dhcp_max_message_size\n"
|
||||
"define 58 request uint32 dhcp_renewal_time\n"
|
||||
"define 59 request uint32 dhcp_rebinding_time\n"
|
||||
"define 60 string vendor_class_identifier\n"
|
||||
"define 61 binhex dhcp_client_identifier\n"
|
||||
"define 64 string nisplus_domain\n"
|
||||
"define 65 array ipaddress nisplus_servers\n"
|
||||
"define 66 dname tftp_server_name\n"
|
||||
"define 67 string bootfile_name\n"
|
||||
"define 68 array ipaddress mobile_ip_home_agent\n"
|
||||
"define 69 array ipaddress smtp_server\n"
|
||||
"define 70 array ipaddress pop_server\n"
|
||||
"define 71 array ipaddress nntp_server\n"
|
||||
"define 72 array ipaddress www_server\n"
|
||||
"define 73 array ipaddress finger_server\n"
|
||||
"define 74 array ipaddress irc_server\n"
|
||||
"define 75 array ipaddress streettalk_server\n"
|
||||
"define 76 array ipaddress streettalk_directory_assistance_server\n"
|
||||
"define 77 binhex user_class\n"
|
||||
"define 78 embed slp_agent\n"
|
||||
"embed byte mandatory\n"
|
||||
"embed array ipaddress address\n"
|
||||
"define 79 embed slp_service\n"
|
||||
"embed byte mandatory\n"
|
||||
"embed ascii scope_list\n"
|
||||
"define 80 norequest flag rapid_commit\n"
|
||||
"define 81 embed fqdn\n"
|
||||
"embed bitflags=0000NEOS flags\n"
|
||||
"embed byte rcode1\n"
|
||||
"embed byte rcode2\n"
|
||||
"embed optional domain fqdn\n"
|
||||
"define 83 embed isns\n"
|
||||
"embed byte reserved1\n"
|
||||
"embed bitflags=00000SAE functions\n"
|
||||
"embed byte reserved2\n"
|
||||
"embed bitflags=00fFsSCE dd\n"
|
||||
"embed byte reserved3\n"
|
||||
"embed bitflags=0000DMHE admin\n"
|
||||
"embed uint16 reserved4\n"
|
||||
"embed byte reserved5\n"
|
||||
"embed bitflags=0TXPAMSE server_security\n"
|
||||
"embed array ipaddress servers\n"
|
||||
"define 85 array ipaddress nds_servers\n"
|
||||
"define 86 raw nds_tree_name\n"
|
||||
"define 87 raw nds_context\n"
|
||||
"define 88 array domain bcms_controller_names\n"
|
||||
"define 89 array ipaddress bcms_controller_address\n"
|
||||
"define 90 embed auth\n"
|
||||
"embed byte protocol\n"
|
||||
"embed byte algorithm\n"
|
||||
"embed byte rdm\n"
|
||||
"embed binhex:8 replay\n"
|
||||
"embed binhex information\n"
|
||||
"define 91 uint32 client_last_transaction_time\n"
|
||||
"define 92 array ipaddress associated_ip\n"
|
||||
"define 98 string uap_servers\n"
|
||||
"define 99 encap geoconf_civic\n"
|
||||
"embed byte what\n"
|
||||
"embed uint16 country_code\n"
|
||||
"define 100 string posix_timezone\n"
|
||||
"define 101 string tzdb_timezone\n"
|
||||
"define 116 byte auto_configure\n"
|
||||
"define 117 array uint16 name_service_search\n"
|
||||
"define 118 ipaddress subnet_selection\n"
|
||||
"define 119 array domain domain_search\n"
|
||||
"define 120 rfc3361 sip_server\n"
|
||||
"define 122 encap tsp\n"
|
||||
"encap 1 ipaddress dhcp_server\n"
|
||||
"encap 2 ipaddress dhcp_secondary_server\n"
|
||||
"encap 3 rfc3361 provisioning_server\n"
|
||||
"encap 4 embed as_req_as_rep_backoff\n"
|
||||
"embed uint32 nominal\n"
|
||||
"embed uint32 maximum\n"
|
||||
"embed uint32 retry\n"
|
||||
"encap 5 embed ap_req_ap_rep_backoff\n"
|
||||
"embed uint32 nominal\n"
|
||||
"embed uint32 maximum\n"
|
||||
"embed uint32 retry\n"
|
||||
"encap 6 domain kerberos_realm\n"
|
||||
"encap 7 byte ticket_granting_server_utilization\n"
|
||||
"encap 8 byte provisioning_timer\n"
|
||||
"define 123 binhex geoconf\n"
|
||||
"define 124 binhex vivco\n"
|
||||
"define 125 embed vivso\n"
|
||||
"embed uint32 enterprise_number\n"
|
||||
"define 136 array ipaddress pana_agent\n"
|
||||
"define 137 domain lost_server\n"
|
||||
"define 138 array ipaddress capwap_ac\n"
|
||||
"define 139 encap mos_ip\n"
|
||||
"encap 1 array ipaddress is\n"
|
||||
"encap 2 array ipaddress cs\n"
|
||||
"encap 3 array ipaddress es\n"
|
||||
"define 140 encap mos_domain\n"
|
||||
"encap 1 domain is\n"
|
||||
"encap 2 domain cs\n"
|
||||
"encap 3 domain es\n"
|
||||
"define 141 array domain sip_ua_cs_list\n"
|
||||
"define 142 array ipaddress andsf\n"
|
||||
"define 143 array ip6address andsf6\n"
|
||||
"define 144 binhex geoloc\n"
|
||||
"define 145 array byte forcerenew_nonce_capable\n"
|
||||
"define 146 embed rdnss_selection\n"
|
||||
"embed byte prf\n"
|
||||
"embed ipaddress primary\n"
|
||||
"embed ipaddress secondary\n"
|
||||
"embed array domain domains\n"
|
||||
"define 150 array ipaddress tftp_servers\n"
|
||||
"define 161 string mudurl\n"
|
||||
"define 208 binhex pxelinux_magic\n"
|
||||
"define 209 string config_file\n"
|
||||
"define 210 string path_prefix\n"
|
||||
"define 211 uint32 reboot_time\n"
|
||||
"define 212 embed sixrd\n"
|
||||
"embed byte mask_len\n"
|
||||
"embed byte prefix_len\n"
|
||||
"embed ip6address prefix\n"
|
||||
"embed array ipaddress brip_address\n"
|
||||
"define 213 domain access_domain\n"
|
||||
"define 221 encap vss\n"
|
||||
"encap 0 string nvt\n"
|
||||
"encap 1 binhex vpn_id\n"
|
||||
"encap 255 flag global\n"
|
||||
"define 249 rfc3442 ms_classless_static_routes\n"
|
||||
"define 252 string wpad_url\n"
|
||||
"definend 1 binhex source_address\n"
|
||||
"definend 2 binhex target_address\n"
|
||||
"definend 3 index embed prefix_information\n"
|
||||
"embed byte length\n"
|
||||
"embed bitflags=LA flags\n"
|
||||
"embed uint32 vltime\n"
|
||||
"embed uint32 pltime\n"
|
||||
"embed uint32 reserved\n"
|
||||
"embed array ip6address prefix\n"
|
||||
"definend 5 embed mtu\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 mtu\n"
|
||||
"definend 25 index embed rdnss\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 lifetime\n"
|
||||
"embed array ip6address servers\n"
|
||||
"definend 31 index embed dnssl\n"
|
||||
"embed uint16 reserved\n"
|
||||
"embed uint32 lifetime\n"
|
||||
"embed domain search\n"
|
||||
"define6 1 binhex client_id\n"
|
||||
"define6 2 binhex server_id\n"
|
||||
"define6 3 norequest index embed ia_na\n"
|
||||
"embed binhex:4 iaid\n"
|
||||
"embed uint32 t1\n"
|
||||
"embed uint32 t2\n"
|
||||
"encap 5 option\n"
|
||||
"encap 13 option\n"
|
||||
"define6 4 norequest index embed ia_ta\n"
|
||||
"embed uint32 iaid\n"
|
||||
"encap 5 option\n"
|
||||
"encap 13 option\n"
|
||||
"define6 5 norequest index embed ia_addr\n"
|
||||
"embed ip6address ia_addr\n"
|
||||
"embed uint32 pltime\n"
|
||||
"embed uint32 vltime\n"
|
||||
"encap 13 option\n"
|
||||
"define6 6 array uint16 option_request\n"
|
||||
"define6 7 byte preference\n"
|
||||
"define6 8 uint16 elased_time\n"
|
||||
"define6 9 binhex dhcp_relay_msg\n"
|
||||
"define6 11 embed auth\n"
|
||||
"embed byte protocol\n"
|
||||
"embed byte algorithm\n"
|
||||
"embed byte rdm\n"
|
||||
"embed binhex:8 replay\n"
|
||||
"embed binhex information\n"
|
||||
"define6 12 ip6address unicast\n"
|
||||
"define6 13 norequest embed status_code\n"
|
||||
"embed uint16 status_code\n"
|
||||
"embed optional string message\n"
|
||||
"define6 14 norequest flag rapid_commit\n"
|
||||
"define6 15 binhex user_class\n"
|
||||
"define6 16 binhex vivco\n"
|
||||
"define6 17 embed vivso\n"
|
||||
"embed uint32 enterprise_number\n"
|
||||
"define6 18 binhex interface_id\n"
|
||||
"define6 19 byte reconfigure_msg\n"
|
||||
"define6 20 flag reconfigure_accept\n"
|
||||
"define6 21 array domain sip_servers_names\n"
|
||||
"define6 22 array ip6address sip_servers_addresses\n"
|
||||
"define6 23 array ip6address name_servers\n"
|
||||
"define6 24 array domain domain_search\n"
|
||||
"define6 25 norequest index embed ia_pd\n"
|
||||
"embed binhex:4 iaid\n"
|
||||
"embed uint32 t1\n"
|
||||
"embed uint32 t2\n"
|
||||
"encap 26 option\n"
|
||||
"define6 26 index embed prefix\n"
|
||||
"embed uint32 pltime\n"
|
||||
"embed uint32 vltime\n"
|
||||
"embed byte length\n"
|
||||
"embed ip6address prefix\n"
|
||||
"encap 13 option\n"
|
||||
"encap 67 option\n"
|
||||
"define6 27 array ip6address nis_servers\n"
|
||||
"define6 28 array ip6address nisp_servers\n"
|
||||
"define6 29 string nis_domain_name\n"
|
||||
"define6 30 string nisp_domain_name\n"
|
||||
"define6 31 array ip6address sntp_servers\n"
|
||||
"define6 32 uint32 info_refresh_time\n"
|
||||
"define6 33 array domain bcms_server_d\n"
|
||||
"define6 34 array ip6address bcms_server_a\n"
|
||||
"define6 36 encap geoconf_civic\n"
|
||||
"embed byte what\n"
|
||||
"embed uint16 country_code\n"
|
||||
"define6 37 embed remote_id\n"
|
||||
"embed uint32 enterprise_number\n"
|
||||
"embed binhex remote_id\n"
|
||||
"define6 38 binhex subscriber_id\n"
|
||||
"define6 39 embed fqdn\n"
|
||||
"embed bitflags=00000NOS flags\n"
|
||||
"embed optional domain fqdn\n"
|
||||
"define6 40 array ip6address pana_agent\n"
|
||||
"define6 41 string posix_timezone\n"
|
||||
"define6 42 string tzdb_timezone\n"
|
||||
"define6 43 array uint16 ero\n"
|
||||
"define6 49 domain mip6_hnidf\n"
|
||||
"define6 50 encap mip6_vdinf\n"
|
||||
"encap 71 option\n"
|
||||
"encap 72 option\n"
|
||||
"encap 73 option\n"
|
||||
"define6 51 domain lost_server\n"
|
||||
"define6 52 array ip6address capwap_ac\n"
|
||||
"define6 53 binhex relay_id\n"
|
||||
"define6 54 encap mos_ip\n"
|
||||
"encap 1 array ip6address is\n"
|
||||
"encap 2 array ip6address cs\n"
|
||||
"encap 3 array ip6address es\n"
|
||||
"define6 55 encap mos_domain\n"
|
||||
"encap 1 domain is\n"
|
||||
"encap 2 domain cs\n"
|
||||
"encap 3 domain es\n"
|
||||
"define6 56 encap ntp_server\n"
|
||||
"encap 1 ip6address addr\n"
|
||||
"encap 2 ip6address mcast_addr\n"
|
||||
"encap 3 domain fqdn\n"
|
||||
"define6 57 domain access_domain\n"
|
||||
"define6 58 array domain sip_ua_cs_list\n"
|
||||
"define6 59 string bootfile_url\n"
|
||||
"define6 60 binhex bootfile_param\n"
|
||||
"define6 61 array uint16 architecture_types\n"
|
||||
"define6 62 embed nii\n"
|
||||
"embed byte type\n"
|
||||
"embed byte major\n"
|
||||
"embed byte minor\n"
|
||||
"define6 63 binhex geoloc\n"
|
||||
"define6 64 domain aftr_name\n"
|
||||
"define6 67 embed pd_exclude\n"
|
||||
"embed byte prefix_len\n"
|
||||
"embed binhex subnetID\n"
|
||||
"define6 69 encap mip6_idinf\n"
|
||||
"encap 71 option\n"
|
||||
"encap 72 option\n"
|
||||
"encap 73 option\n"
|
||||
"define6 70 encap mip6_udinf\n"
|
||||
"encap 71 option\n"
|
||||
"encap 72 option\n"
|
||||
"encap 73 option\n"
|
||||
"define6 71 embed mip6_hnp\n"
|
||||
"embed byte prefix_len\n"
|
||||
"embed ip6address prefix\n"
|
||||
"define6 72 ip6address mip6_haa\n"
|
||||
"define6 73 domain mip6_haf\n"
|
||||
"define6 74 embed rdnss_selection\n"
|
||||
"embed ip6address server\n"
|
||||
"embed byte prf\n"
|
||||
"embed array domain domains\n"
|
||||
"define6 75 string krb_principal_name\n"
|
||||
"define6 76 string krb_realm_name\n"
|
||||
"define6 78 embed krb_kdc\n"
|
||||
"embed uint16 priority\n"
|
||||
"embed uint16 weight\n"
|
||||
"embed byte transport_type\n"
|
||||
"embed uint16 port\n"
|
||||
"embed ip6address address\n"
|
||||
"embed string realm_name\n"
|
||||
"define6 80 ip6address link_address\n"
|
||||
"define6 82 request uint32 sol_max_rt\n"
|
||||
"define6 83 request uint32 inf_max_rt\n"
|
||||
"define6 89 embed s46_rule\n"
|
||||
"embed bitflags=0000000F flags\n"
|
||||
"embed byte ea_len\n"
|
||||
"embed byte prefix4_len\n"
|
||||
"embed ipaddress ipv4_prefix\n"
|
||||
"embed ip6address ipv6_prefix\n"
|
||||
"define6 90 ip6address s64_br\n"
|
||||
"define6 91 embed s46_dmr\n"
|
||||
"embed byte prefix_len\n"
|
||||
"embed binhex prefix\n"
|
||||
"define6 92 embed s46_v4v6bind\n"
|
||||
"embed ipaddress ipv4_address\n"
|
||||
"embed byte ipv6_prefix_len\n"
|
||||
"embed binhex ipv6_prefix_and_options\n"
|
||||
"define6 93 embed s46_portparams\n"
|
||||
"embed byte offset\n"
|
||||
"embed byte psid_len\n"
|
||||
"embed uint16 psid\n"
|
||||
"define6 94 embed s46_cont_mape\n"
|
||||
"encap 89 option\n"
|
||||
"encap 90 option\n"
|
||||
"define6 95 embed s46_cont_mapt\n"
|
||||
"encap 89 option\n"
|
||||
"encap 91 option\n"
|
||||
"define6 96 embed s46_cont_lw\n"
|
||||
"encap 90 option\n"
|
||||
"encap 92 option\n"
|
||||
"define6 112 string mudurl\n"
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
"\0";
|
||||
|
||||
|
|
|
@ -35,4 +35,4 @@
|
|||
#define INITDEFINE6S 69
|
||||
#endif
|
||||
|
||||
extern const char * const dhcpcd_embedded_conf[];
|
||||
extern const char dhcpcd_embedded_conf[];
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#controlgroup wheel
|
||||
|
||||
# Inform the DHCP server of our hostname for DDNS.
|
||||
hostname
|
||||
#hostname
|
||||
|
||||
# Use the hardware address of the interface for the Client ID.
|
||||
#clientid
|
||||
|
@ -18,20 +18,27 @@ duid
|
|||
# Persist interface configuration when dhcpcd exits.
|
||||
persistent
|
||||
|
||||
# Rapid commit support.
|
||||
# Safe to enable by default because it requires the equivalent option set
|
||||
# on the server to actually work.
|
||||
option rapid_commit
|
||||
# vendorclassid is set to blank to avoid sending the default of
|
||||
# dhcpcd-<version>:<os>:<machine>:<platform>
|
||||
vendorclassid
|
||||
|
||||
# A list of options to request from the DHCP server.
|
||||
option domain_name_servers, domain_name, domain_search, host_name
|
||||
option domain_name_servers, domain_name, domain_search
|
||||
option classless_static_routes
|
||||
# Respect the network MTU. This is applied to DHCP routes.
|
||||
option interface_mtu
|
||||
|
||||
# Request a hostname from the network
|
||||
option host_name
|
||||
|
||||
# Most distributions have NTP support.
|
||||
#option ntp_servers
|
||||
|
||||
# Rapid commit support.
|
||||
# Safe to enable by default because it requires the equivalent option set
|
||||
# on the server to actually work.
|
||||
option rapid_commit
|
||||
|
||||
# A ServerID is required by RFC2131.
|
||||
require dhcp_server_identifier
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 19, 2020
|
||||
.Dd May 12, 2020
|
||||
.Dt DHCPCD.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -792,7 +792,7 @@ with a name of
|
|||
exported to
|
||||
.Xr dhcpcd-run-hooks 8 ,
|
||||
with a prefix of
|
||||
.Va _nd .
|
||||
.Va nd_ .
|
||||
.It Ic define6 Ar code Ar type Ar variable
|
||||
Defines the DHCPv6 option
|
||||
.Ar code
|
||||
|
@ -803,7 +803,7 @@ with a name of
|
|||
exported to
|
||||
.Xr dhcpcd-run-hooks 8 ,
|
||||
with a prefix of
|
||||
.Va _dhcp6 .
|
||||
.Va dhcp6_ .
|
||||
.It Ic vendopt Ar code Ar type Ar variable
|
||||
Defines the Vendor-Identifying Vendor Options.
|
||||
The
|
||||
|
|
|
@ -82,7 +82,7 @@ struct interface {
|
|||
unsigned int index;
|
||||
unsigned int active;
|
||||
unsigned int flags;
|
||||
sa_family_t family;
|
||||
uint16_t hwtype; /* ARPHRD_ETHER for example */
|
||||
unsigned char hwaddr[HWADDR_LEN];
|
||||
uint8_t hwlen;
|
||||
unsigned short vlanid;
|
||||
|
@ -125,6 +125,7 @@ struct passwd;
|
|||
|
||||
struct dhcpcd_ctx {
|
||||
char pidfile[sizeof(PIDFILE) + IF_NAMESIZE + 1];
|
||||
char vendor[256];
|
||||
int fork_fd; /* FD for the fork init signal pipe */
|
||||
const char *cffile;
|
||||
unsigned long long options;
|
||||
|
@ -163,6 +164,7 @@ struct dhcpcd_ctx {
|
|||
#endif
|
||||
struct eloop *eloop;
|
||||
|
||||
char *script;
|
||||
#ifdef HAVE_OPEN_MEMSTREAM
|
||||
FILE *script_fp;
|
||||
#endif
|
||||
|
@ -205,7 +207,8 @@ struct dhcpcd_ctx {
|
|||
struct dhcp_opt *dhcp_opts;
|
||||
size_t dhcp_opts_len;
|
||||
|
||||
int udp_fd;
|
||||
int udp_rfd;
|
||||
int udp_wfd;
|
||||
|
||||
/* Our aggregate option buffer.
|
||||
* We ONLY use this when options are split, which for most purposes is
|
||||
|
@ -222,11 +225,11 @@ struct dhcpcd_ctx {
|
|||
#endif
|
||||
struct ra_head *ra_routers;
|
||||
|
||||
int dhcp6_fd;
|
||||
|
||||
struct dhcp_opt *nd_opts;
|
||||
size_t nd_opts_len;
|
||||
#ifdef DHCP6
|
||||
int dhcp6_rfd;
|
||||
int dhcp6_wfd;
|
||||
struct dhcp_opt *dhcp6_opts;
|
||||
size_t dhcp6_opts_len;
|
||||
#endif
|
||||
|
@ -247,8 +250,12 @@ struct dhcpcd_ctx {
|
|||
#ifdef USE_SIGNALS
|
||||
extern const int dhcpcd_signals[];
|
||||
extern const size_t dhcpcd_signals_len;
|
||||
extern const int dhcpcd_signals_ignore[];
|
||||
extern const size_t dhcpcd_signals_ignore_len;
|
||||
#endif
|
||||
|
||||
extern const char *dhcpcd_default_script;
|
||||
|
||||
int dhcpcd_ifafwaiting(const struct interface *);
|
||||
int dhcpcd_afwaiting(const struct dhcpcd_ctx *);
|
||||
void dhcpcd_daemonise(struct dhcpcd_ctx *);
|
||||
|
@ -257,8 +264,7 @@ void dhcpcd_linkoverflow(struct dhcpcd_ctx *);
|
|||
int dhcpcd_handleargs(struct dhcpcd_ctx *, struct fd_list *, int, char **);
|
||||
void dhcpcd_handlecarrier(struct dhcpcd_ctx *, int, unsigned int, const char *);
|
||||
int dhcpcd_handleinterface(void *, int, const char *);
|
||||
void dhcpcd_handlehwaddr(struct dhcpcd_ctx *, const char *,
|
||||
const void *, uint8_t);
|
||||
void dhcpcd_handlehwaddr(struct interface *, uint16_t, const void *, uint8_t);
|
||||
void dhcpcd_dropinterface(struct interface *, const char *);
|
||||
int dhcpcd_selectprofile(struct interface *, const char *);
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ duid_make(void *d, const struct interface *ifp, uint16_t type)
|
|||
u16 = htons(type);
|
||||
memcpy(p, &u16, sizeof(u16));
|
||||
p += sizeof(u16);
|
||||
u16 = htons(ifp->family);
|
||||
u16 = htons(ifp->hwtype);
|
||||
memcpy(p, &u16, sizeof(u16));
|
||||
p += sizeof(u16);
|
||||
if (type == DUID_LLT) {
|
||||
|
@ -149,20 +149,18 @@ duid_make(void *d, const struct interface *ifp, uint16_t type)
|
|||
|
||||
#define DUID_STRLEN DUID_LEN * 3
|
||||
static size_t
|
||||
duid_get(uint8_t **d, const struct interface *ifp)
|
||||
duid_get(struct dhcpcd_ctx *ctx, const struct interface *ifp)
|
||||
{
|
||||
FILE *fp;
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
int x = 0;
|
||||
size_t len, slen;
|
||||
char line[DUID_STRLEN];
|
||||
const struct interface *ifp2;
|
||||
|
||||
/* If we already have a DUID then use it as it's never supposed
|
||||
* to change once we have one even if the interfaces do */
|
||||
if ((len = read_hwaddr_aton(&data, DUID)) != 0) {
|
||||
if ((len = dhcp_read_hwaddr_aton(ctx, &data, DUID)) != 0) {
|
||||
if (len <= DUID_LEN) {
|
||||
*d = data;
|
||||
ctx->duid = data;
|
||||
return len;
|
||||
}
|
||||
logerrx("DUID too big (max %u): %s", DUID_LEN, DUID);
|
||||
|
@ -176,13 +174,18 @@ duid_get(uint8_t **d, const struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Regardless of what happens we will create a DUID to use. */
|
||||
*d = data;
|
||||
|
||||
/* No file? OK, lets make one based the machines UUID */
|
||||
len = duid_make_uuid(data);
|
||||
if (len > 0)
|
||||
if (ifp == NULL) {
|
||||
len = duid_make_uuid(data);
|
||||
if (len == 0)
|
||||
free(data);
|
||||
else
|
||||
ctx->duid = data;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Regardless of what happens we will create a DUID to use. */
|
||||
ctx->duid = data;
|
||||
|
||||
/* No UUID? OK, lets make one based on our interface */
|
||||
if (ifp->hwlen == 0) {
|
||||
|
@ -202,27 +205,25 @@ duid_get(uint8_t **d, const struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(fp = fopen(DUID, "w"))) {
|
||||
logerr("%s", DUID);
|
||||
return duid_make(data, ifp, DUID_LL);
|
||||
}
|
||||
len = duid_make(data, ifp, DUID_LLT);
|
||||
x = fprintf(fp, "%s\n", hwaddr_ntoa(data, len, line, sizeof(line)));
|
||||
if (fclose(fp) == EOF)
|
||||
x = -1;
|
||||
/* Failed to write the duid? scrub it, we cannot use it */
|
||||
if (x < 1) {
|
||||
logerr("%s", DUID);
|
||||
unlink(DUID);
|
||||
hwaddr_ntoa(data, len, line, sizeof(line));
|
||||
slen = strlen(line);
|
||||
if (slen < sizeof(line) - 2) {
|
||||
line[slen++] = '\n';
|
||||
line[slen] = '\0';
|
||||
}
|
||||
if (dhcp_writefile(ctx, DUID, 0640, line, slen) == -1) {
|
||||
logerr("%s: cannot write duid", __func__);
|
||||
return duid_make(data, ifp, DUID_LL);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t duid_init(const struct interface *ifp)
|
||||
size_t
|
||||
duid_init(struct dhcpcd_ctx *ctx, const struct interface *ifp)
|
||||
{
|
||||
|
||||
if (ifp->ctx->duid == NULL)
|
||||
ifp->ctx->duid_len = duid_get(&ifp->ctx->duid, ifp);
|
||||
return ifp->ctx->duid_len;
|
||||
if (ctx->duid == NULL)
|
||||
ctx->duid_len = duid_get(ctx, ifp);
|
||||
return ctx->duid_len;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,6 @@
|
|||
#define DUID_UUID 4
|
||||
|
||||
size_t duid_make(void *, const struct interface *, uint16_t);
|
||||
size_t duid_init(const struct interface *);
|
||||
size_t duid_init(struct dhcpcd_ctx *, const struct interface *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1023,12 +1023,13 @@ eloop_start(struct eloop *eloop, sigset_t *signals)
|
|||
continue;
|
||||
}
|
||||
|
||||
eloop_reduce_timers(eloop);
|
||||
|
||||
t = TAILQ_FIRST(&eloop->timeouts);
|
||||
if (t == NULL && eloop->events_len == 0)
|
||||
break;
|
||||
|
||||
if (t != NULL)
|
||||
eloop_reduce_timers(eloop);
|
||||
|
||||
if (t != NULL && t->seconds == 0 && t->nseconds == 0) {
|
||||
TAILQ_REMOVE(&eloop->timeouts, t, next);
|
||||
t->callback(t->arg);
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
#define DHCPCD_ONESHOT (1ULL << 60)
|
||||
#define DHCPCD_INACTIVE (1ULL << 61)
|
||||
#define DHCPCD_SLAACTEMP (1ULL << 62)
|
||||
#define DHCPCD_PRIVSEPROOT (1ULL << 63)
|
||||
|
||||
#define DHCPCD_NODROP (DHCPCD_EXITING | DHCPCD_PERSISTENT)
|
||||
|
||||
|
@ -128,6 +129,58 @@
|
|||
#define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \
|
||||
DHCPCD_ROUTER_HOST_ROUTE_WARNED)
|
||||
|
||||
/* These options only make sense in the config file, so don't use any
|
||||
valid short options for them */
|
||||
#define O_BASE MAX('z', 'Z') + 1
|
||||
#define O_ARPING O_BASE + 1
|
||||
#define O_FALLBACK O_BASE + 2
|
||||
#define O_DESTINATION O_BASE + 3
|
||||
#define O_IPV6RS O_BASE + 4
|
||||
#define O_NOIPV6RS O_BASE + 5
|
||||
#define O_IPV6RA_FORK O_BASE + 6
|
||||
#define O_LINK_RCVBUF O_BASE + 7
|
||||
#define O_ANONYMOUS O_BASE + 8
|
||||
#define O_NOALIAS O_BASE + 9
|
||||
#define O_IA_NA O_BASE + 10
|
||||
#define O_IA_TA O_BASE + 11
|
||||
#define O_IA_PD O_BASE + 12
|
||||
#define O_HOSTNAME_SHORT O_BASE + 13
|
||||
#define O_DEV O_BASE + 14
|
||||
#define O_NODEV O_BASE + 15
|
||||
#define O_NOIPV4 O_BASE + 16
|
||||
#define O_NOIPV6 O_BASE + 17
|
||||
#define O_IAID O_BASE + 18
|
||||
#define O_DEFINE O_BASE + 19
|
||||
#define O_DEFINE6 O_BASE + 20
|
||||
#define O_EMBED O_BASE + 21
|
||||
#define O_ENCAP O_BASE + 22
|
||||
#define O_VENDOPT O_BASE + 23
|
||||
#define O_VENDCLASS O_BASE + 24
|
||||
#define O_AUTHPROTOCOL O_BASE + 25
|
||||
#define O_AUTHTOKEN O_BASE + 26
|
||||
#define O_AUTHNOTREQUIRED O_BASE + 27
|
||||
#define O_NODHCP O_BASE + 28
|
||||
#define O_NODHCP6 O_BASE + 29
|
||||
#define O_DHCP O_BASE + 30
|
||||
#define O_DHCP6 O_BASE + 31
|
||||
#define O_IPV4 O_BASE + 32
|
||||
#define O_IPV6 O_BASE + 33
|
||||
#define O_CONTROLGRP O_BASE + 34
|
||||
#define O_SLAAC O_BASE + 35
|
||||
#define O_GATEWAY O_BASE + 36
|
||||
#define O_NOUP O_BASE + 37
|
||||
#define O_IPV6RA_AUTOCONF O_BASE + 38
|
||||
#define O_IPV6RA_NOAUTOCONF O_BASE + 39
|
||||
#define O_REJECT O_BASE + 40
|
||||
#define O_BOOTP O_BASE + 42
|
||||
#define O_DEFINEND O_BASE + 43
|
||||
#define O_NODELAY O_BASE + 44
|
||||
#define O_INFORM6 O_BASE + 45
|
||||
#define O_LASTLEASE_EXTEND O_BASE + 46
|
||||
#define O_INACTIVE O_BASE + 47
|
||||
#define O_MUDURL O_BASE + 48
|
||||
#define O_MSUSERCLASS O_BASE + 49
|
||||
|
||||
extern const struct option cf_options[];
|
||||
|
||||
struct if_sla {
|
||||
|
@ -190,7 +243,6 @@ struct if_options {
|
|||
char **config;
|
||||
|
||||
char **environ;
|
||||
char *script;
|
||||
|
||||
char hostname[HOSTNAME_MAX_LEN + 1]; /* We don't store the length */
|
||||
uint8_t fqdn;
|
||||
|
|
|
@ -75,12 +75,6 @@
|
|||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
#ifdef __sun
|
||||
/* It has the ioctl, but the member is missing from the struct?
|
||||
* No matter, our getifaddrs foo in if-sun.c will DTRT. */
|
||||
#undef SIOCGIFHWADDR
|
||||
#endif
|
||||
|
||||
void
|
||||
if_free(struct interface *ifp)
|
||||
{
|
||||
|
@ -387,10 +381,10 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
struct if_laddrreq iflr = { .flags = IFLR_PREFIX };
|
||||
int link_fd;
|
||||
#endif
|
||||
#elif AF_PACKET
|
||||
#elif defined(AF_PACKET)
|
||||
const struct sockaddr_ll *sll;
|
||||
#endif
|
||||
#if defined(SIOCGIFPRIORITY) || defined(SIOCGIFHWADDR)
|
||||
#if defined(SIOCGIFPRIORITY)
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
|
@ -398,12 +392,22 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
logerr(__func__);
|
||||
return NULL;
|
||||
}
|
||||
TAILQ_INIT(ifs);
|
||||
|
||||
#if defined(PRIVSEP) && defined(HAVE_CAPSICUM)
|
||||
if (ctx->options & DHCPCD_PRIVSEP) {
|
||||
if (ps_root_getifaddrs(ctx, ifaddrs) == -1) {
|
||||
logerr("ps_root_getifaddrs");
|
||||
free(ifs);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (getifaddrs(ifaddrs) == -1) {
|
||||
logerr(__func__);
|
||||
logerr("getifaddrs");
|
||||
free(ifs);
|
||||
return NULL;
|
||||
}
|
||||
TAILQ_INIT(ifs);
|
||||
|
||||
#ifdef IFLR_ACTIVE
|
||||
link_fd = xsocket(PF_LINK, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
|
@ -419,7 +423,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
#ifdef AF_LINK
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
#elif AF_PACKET
|
||||
#elif defined(AF_PACKET)
|
||||
if (ifa->ifa_addr->sa_family != AF_PACKET)
|
||||
continue;
|
||||
#endif
|
||||
|
@ -485,13 +489,9 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
if_noconf = ((argc == 0 || argc == -1) && ctx->ifac == 0 &&
|
||||
!if_hasconf(ctx, spec.devname));
|
||||
|
||||
/* Don't allow loopback or pointopoint unless explicit.
|
||||
* Don't allow some reserved interface names unless explicit. */
|
||||
if (if_noconf) {
|
||||
if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT) ||
|
||||
if_ignore(ctx, spec.devname))
|
||||
active = IF_INACTIVE;
|
||||
}
|
||||
/* Don't allow some reserved interface names unless explicit. */
|
||||
if (if_noconf && if_ignore(ctx, spec.devname))
|
||||
active = IF_INACTIVE;
|
||||
|
||||
ifp = calloc(1, sizeof(*ifp));
|
||||
if (ifp == NULL) {
|
||||
|
@ -533,6 +533,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
#ifdef IFT_TUNNEL
|
||||
case IFT_TUNNEL: /* FALLTHROUGH */
|
||||
#endif
|
||||
case IFT_LOOP: /* FALLTHROUGH */
|
||||
case IFT_PPP:
|
||||
/* Don't allow unless explicit */
|
||||
if (if_noconf) {
|
||||
|
@ -551,16 +552,16 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
case IFT_L3IPVLAN: /* FALLTHROUGH */
|
||||
#endif
|
||||
case IFT_ETHER:
|
||||
ifp->family = ARPHRD_ETHER;
|
||||
ifp->hwtype = ARPHRD_ETHER;
|
||||
break;
|
||||
#ifdef IFT_IEEE1394
|
||||
case IFT_IEEE1394:
|
||||
ifp->family = ARPHRD_IEEE1394;
|
||||
ifp->hwtype = ARPHRD_IEEE1394;
|
||||
break;
|
||||
#endif
|
||||
#ifdef IFT_INFINIBAND
|
||||
case IFT_INFINIBAND:
|
||||
ifp->family = ARPHRD_INFINIBAND;
|
||||
ifp->hwtype = ARPHRD_INFINIBAND;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -572,71 +573,43 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
" interface type 0x%.2x",
|
||||
ifp->name, sdl->sdl_type);
|
||||
/* Pretend it's ethernet */
|
||||
ifp->family = ARPHRD_ETHER;
|
||||
ifp->hwtype = ARPHRD_ETHER;
|
||||
break;
|
||||
}
|
||||
ifp->hwlen = sdl->sdl_alen;
|
||||
memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
|
||||
#elif AF_PACKET
|
||||
#elif defined(AF_PACKET)
|
||||
sll = (const void *)ifa->ifa_addr;
|
||||
ifp->index = (unsigned int)sll->sll_ifindex;
|
||||
ifp->family = sll->sll_hatype;
|
||||
ifp->hwtype = sll->sll_hatype;
|
||||
ifp->hwlen = sll->sll_halen;
|
||||
if (ifp->hwlen != 0)
|
||||
memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
|
||||
#endif
|
||||
}
|
||||
#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. */
|
||||
if (!if_valid_hwaddr(ifp->hwaddr, ifp->hwlen))
|
||||
ifp->hwlen = 0;
|
||||
|
||||
/* We only work on ethernet by default */
|
||||
if (ifp->family != ARPHRD_ETHER) {
|
||||
if ((argc == 0 || argc == -1) &&
|
||||
ctx->ifac == 0 && !if_hasconf(ctx, ifp->name))
|
||||
active = IF_INACTIVE;
|
||||
switch (ifp->family) {
|
||||
case ARPHRD_IEEE1394:
|
||||
case ARPHRD_INFINIBAND:
|
||||
#ifdef ARPHRD_LOOPBACK
|
||||
case ARPHRD_LOOPBACK:
|
||||
#endif
|
||||
#ifdef ARPHRD_PPP
|
||||
case ARPHRD_PPP:
|
||||
#endif
|
||||
#ifdef ARPHRD_NONE
|
||||
case ARPHRD_NONE:
|
||||
#endif
|
||||
/* We don't warn for supported families */
|
||||
switch(ifp->hwtype) {
|
||||
case ARPHRD_ETHER: /* FALLTHROUGH */
|
||||
case ARPHRD_IEEE1394: /* FALLTHROUGH */
|
||||
case ARPHRD_INFINIBAND: /* FALLTHROUGH */
|
||||
case ARPHRD_NONE: /* FALLTHROUGH */
|
||||
break;
|
||||
case ARPHRD_LOOPBACK:
|
||||
case ARPHRD_PPP:
|
||||
if (if_noconf) {
|
||||
logdebugx("%s: ignoring due to"
|
||||
" interface type and"
|
||||
" no config",
|
||||
ifp->name);
|
||||
active = IF_INACTIVE;
|
||||
}
|
||||
break;
|
||||
|
||||
/* IFT already checked */
|
||||
#ifndef AF_LINK
|
||||
default:
|
||||
if (active)
|
||||
logwarnx("%s: unsupported"
|
||||
" interface family 0x%.2x",
|
||||
ifp->name, ifp->family);
|
||||
" interface type 0x%.2x",
|
||||
ifp->name, ifp->hwtype);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) {
|
||||
|
@ -654,7 +627,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
|
|||
/* Respect the interface priority */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0)
|
||||
if (pioctl(ctx, SIOCGIFPRIORITY, &ifr, sizeof(ifr)) == 0)
|
||||
ifp->metric = (unsigned int)ifr.ifr_metric;
|
||||
if_getssid(ifp);
|
||||
#else
|
||||
|
@ -713,22 +686,39 @@ if_nametospec(const char *ifname, struct if_spec *spec)
|
|||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
*ep-- = '\0';
|
||||
*ep = '\0';
|
||||
#ifdef __sun
|
||||
ep--;
|
||||
#endif
|
||||
} else {
|
||||
spec->lun = -1;
|
||||
#ifdef __sun
|
||||
ep = spec->drvname + strlen(spec->drvname) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
strlcpy(spec->devname, spec->drvname, sizeof(spec->devname));
|
||||
#ifdef __sun
|
||||
/* Solaris has numbers in the driver name, such as e1000g */
|
||||
while (ep > spec->drvname && isdigit((int)*ep))
|
||||
ep--;
|
||||
if (*ep++ == ':') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/* BSD and Linux no not have numbers in the driver name */
|
||||
for (ep = spec->drvname; *ep != '\0' && !isdigit((int)*ep); ep++) {
|
||||
if (*ep == ':') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
spec->ppa = (int)strtoi(ep, &pp, 10, 0, INT_MAX, &e);
|
||||
*ep = '\0';
|
||||
|
||||
#ifndef __sun
|
||||
/*
|
||||
* . is used for VLAN style names
|
||||
* i is used on NetBSD for xvif interfaces
|
||||
|
@ -738,6 +728,7 @@ if_nametospec(const char *ifname, struct if_spec *spec)
|
|||
if (e)
|
||||
spec->vlid = -1;
|
||||
} else
|
||||
#endif
|
||||
spec->vlid = -1;
|
||||
|
||||
return 0;
|
||||
|
@ -808,7 +799,8 @@ if_domtu(const struct interface *ifp, short int mtu)
|
|||
if (mtu != 0)
|
||||
r = if_ioctl(ifp->ctx, SIOCSIFMTU, &ifr, sizeof(ifr));
|
||||
else
|
||||
r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMTU, &ifr);
|
||||
r = pioctl(ifp->ctx, SIOCGIFMTU, &ifr, sizeof(ifr));
|
||||
|
||||
if (r == -1)
|
||||
return -1;
|
||||
return ifr.ifr_mtu;
|
||||
|
@ -910,9 +902,6 @@ xsocket(int domain, int type, int protocol)
|
|||
#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
|
||||
int xflags, xtype = type;
|
||||
#endif
|
||||
#ifdef SO_RERROR
|
||||
int on;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SOCK_CLOEXEC
|
||||
if (xtype & SOCK_CLOEXEC)
|
||||
|
@ -937,13 +926,6 @@ xsocket(int domain, int type, int protocol)
|
|||
goto out;
|
||||
#endif
|
||||
|
||||
#ifdef SO_RERROR
|
||||
/* Tell recvmsg(2) to return ENOBUFS if the receiving socket overflows. */
|
||||
on = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_RERROR, &on, sizeof(on)) == -1)
|
||||
logerr("%s: SO_RERROR", __func__);
|
||||
#endif
|
||||
|
||||
return s;
|
||||
|
||||
#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
|
||||
|
|
|
@ -95,6 +95,8 @@ typedef unsigned long ioctl_request_t;
|
|||
#define FRAMEHDRLEN_MAX 14 /* only ethernet support */
|
||||
#define FRAMELEN_MAX (FRAMEHDRLEN_MAX + 9216)
|
||||
|
||||
#define UDPLEN_MAX 64 * 1024
|
||||
|
||||
/* Work out if we have a private address or not
|
||||
* 10/8
|
||||
* 172.16/12
|
||||
|
@ -117,6 +119,11 @@ typedef unsigned long ioctl_request_t;
|
|||
* but then ignores it. */
|
||||
#undef RTF_CLONING
|
||||
|
||||
/* This interface is busted on DilOS at least.
|
||||
* It used to work, but lukily Solaris can fall back to
|
||||
* IP_PKTINFO. */
|
||||
#undef IP_RECVIF
|
||||
|
||||
/* Solaris getifaddrs is very un-suitable for dhcpcd.
|
||||
* See if-sun.c for details why. */
|
||||
struct ifaddrs;
|
||||
|
@ -126,6 +133,11 @@ int if_getsubnet(struct dhcpcd_ctx *, const char *, int, void *, size_t);
|
|||
#endif
|
||||
|
||||
int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
|
||||
#ifdef HAVE_PLEDGE
|
||||
#define pioctl(ctx, req, data, len) if_ioctl((ctx), (req), (data), (len))
|
||||
#else
|
||||
#define pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len))
|
||||
#endif
|
||||
int if_getflags(struct interface *);
|
||||
int if_setflag(struct interface *, short, short);
|
||||
#define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0)
|
||||
|
@ -171,7 +183,7 @@ int if_conf(struct interface *);
|
|||
int if_init(struct interface *);
|
||||
int if_getssid(struct interface *);
|
||||
bool if_ignore(struct dhcpcd_ctx *, const char *);
|
||||
int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
|
||||
int if_vimaster(struct dhcpcd_ctx *ctx, const char *);
|
||||
unsigned short if_vlanid(const struct interface *);
|
||||
int if_opensockets(struct dhcpcd_ctx *);
|
||||
int if_opensockets_os(struct dhcpcd_ctx *);
|
||||
|
@ -203,6 +215,9 @@ int if_setmac(struct interface *ifp, void *, uint8_t);
|
|||
#else
|
||||
# define SOCK_NONBLOCK 0x20000000
|
||||
#endif
|
||||
#ifndef SOCK_CXNB
|
||||
#define SOCK_CXNB SOCK_CLOEXEC | SOCK_NONBLOCK
|
||||
#endif
|
||||
|
||||
int if_route(unsigned char, const struct rt *rt);
|
||||
int if_initrt(struct dhcpcd_ctx *, rb_tree_t *, int);
|
||||
|
@ -241,7 +256,7 @@ struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *,
|
|||
int xsocket(int, int, int);
|
||||
|
||||
#ifdef __linux__
|
||||
int if_linksocket(struct sockaddr_nl *, int);
|
||||
int if_linksocket(struct sockaddr_nl *, int, int);
|
||||
int if_getnetlink(struct dhcpcd_ctx *, struct iovec *, int, int,
|
||||
int (*)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *);
|
||||
#endif
|
||||
|
|
|
@ -565,8 +565,6 @@ ipv4_getstate(struct interface *ifp)
|
|||
return NULL;
|
||||
}
|
||||
TAILQ_INIT(&state->addrs);
|
||||
state->buffer_size = state->buffer_len = state->buffer_pos = 0;
|
||||
state->buffer = NULL;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -963,6 +961,5 @@ ipv4_free(struct interface *ifp)
|
|||
TAILQ_REMOVE(&state->addrs, ia, next);
|
||||
free(ia);
|
||||
}
|
||||
free(state->buffer);
|
||||
free(state);
|
||||
}
|
||||
|
|
|
@ -110,10 +110,6 @@ TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
|
|||
|
||||
struct ipv4_state {
|
||||
struct ipv4_addrhead addrs;
|
||||
|
||||
/* Buffer for BPF */
|
||||
size_t buffer_size, buffer_len, buffer_pos;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
#define IPV4_STATE(ifp) \
|
||||
|
|
|
@ -57,12 +57,10 @@ static const struct in_addr inaddr_llbcast = {
|
|||
.s_addr = HTONL(LINKLOCAL_BCAST)
|
||||
};
|
||||
|
||||
static void ipv4ll_start1(struct interface *, struct arp_state *);
|
||||
|
||||
static in_addr_t
|
||||
static void
|
||||
ipv4ll_pickaddr(struct interface *ifp)
|
||||
{
|
||||
struct in_addr addr;
|
||||
struct in_addr addr = { .s_addr = 0 };
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
state = IPV4LL_STATE(ifp);
|
||||
|
@ -88,7 +86,7 @@ again:
|
|||
|
||||
/* Restore the original random state */
|
||||
setstate(ifp->ctx->randomstate);
|
||||
return addr.s_addr;
|
||||
state->pickedaddr = addr;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -176,13 +174,12 @@ ipv4ll_announced_arp(struct arp_state *astate)
|
|||
struct ipv4ll_state *state = IPV4LL_STATE(astate->iface);
|
||||
|
||||
state->conflicts = 0;
|
||||
#ifdef KERNEL_RFC5227
|
||||
arp_free(astate);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef KERNEL_RFC5227
|
||||
/* This is the callback by ARP freeing */
|
||||
static void
|
||||
ipv4ll_arpfree(struct arp_state *astate)
|
||||
ipv4ll_free_arp(struct arp_state *astate)
|
||||
{
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
|
@ -191,23 +188,33 @@ ipv4ll_arpfree(struct arp_state *astate)
|
|||
state->arp = NULL;
|
||||
}
|
||||
|
||||
/* This is us freeing any ARP state */
|
||||
static void
|
||||
ipv4ll_freearp(struct interface *ifp)
|
||||
{
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
state = IPV4LL_STATE(ifp);
|
||||
if (state == NULL || state->arp == NULL)
|
||||
return;
|
||||
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp);
|
||||
arp_free(state->arp);
|
||||
state->arp = NULL;
|
||||
}
|
||||
#else
|
||||
#define ipv4ll_freearp(ifp)
|
||||
#endif
|
||||
|
||||
static void
|
||||
ipv4ll_not_found(struct interface *ifp)
|
||||
{
|
||||
struct ipv4ll_state *state;
|
||||
struct ipv4_addr *ia;
|
||||
#ifdef KERNEL_RFC5227
|
||||
struct arp_state *astate;
|
||||
bool new_addr;
|
||||
#endif
|
||||
|
||||
state = IPV4LL_STATE(ifp);
|
||||
assert(state != NULL);
|
||||
|
||||
ia = ipv4_iffindaddr(ifp, &state->pickedaddr, &inaddr_llmask);
|
||||
#ifdef KERNEL_RFC5227
|
||||
new_addr = ia == NULL;
|
||||
#endif
|
||||
#ifdef IN_IFF_NOTREADY
|
||||
if (ia == NULL || ia->addr_flags & IN_IFF_NOTREADY)
|
||||
#endif
|
||||
|
@ -227,6 +234,7 @@ ipv4ll_not_found(struct interface *ifp)
|
|||
return;
|
||||
logdebugx("%s: DAD completed for %s", ifp->name, ia->saddr);
|
||||
#endif
|
||||
|
||||
test:
|
||||
state->addr = ia;
|
||||
state->down = false;
|
||||
|
@ -236,49 +244,27 @@ test:
|
|||
return;
|
||||
}
|
||||
rt_build(ifp->ctx, AF_INET);
|
||||
#ifdef KERNEL_RFC5227
|
||||
if (!new_addr) {
|
||||
astate = arp_new(ifp, &ia->addr);
|
||||
if (ifp->ctx->options & DHCPCD_FORKED)
|
||||
return;
|
||||
if (astate != NULL) {
|
||||
astate->announced_cb = ipv4ll_announced_arp;
|
||||
astate->free_cb = ipv4ll_arpfree;
|
||||
arp_announce(astate);
|
||||
}
|
||||
}
|
||||
#else
|
||||
arp_announce(state->arp);
|
||||
#endif
|
||||
astate = arp_announceaddr(ifp->ctx, &ia->addr);
|
||||
if (astate != NULL)
|
||||
astate->announced_cb = ipv4ll_announced_arp;
|
||||
script_runreason(ifp, "IPV4LL");
|
||||
dhcpcd_daemonise(ifp->ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv4ll_startifp(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
state = IPV4LL_STATE(ifp);
|
||||
ipv4ll_start1(ifp, state->arp);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv4ll_found(struct interface *ifp)
|
||||
{
|
||||
struct ipv4ll_state *state = IPV4LL_STATE(ifp);
|
||||
|
||||
if (state->arp != NULL)
|
||||
arp_cancel(state->arp);
|
||||
ipv4ll_freearp(ifp);
|
||||
if (++state->conflicts == MAX_CONFLICTS)
|
||||
logerrx("%s: failed to acquire an IPv4LL address",
|
||||
ifp->name);
|
||||
state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp);
|
||||
ipv4ll_pickaddr(ifp);
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
state->conflicts >= MAX_CONFLICTS ?
|
||||
RATE_LIMIT_INTERVAL : PROBE_WAIT,
|
||||
ipv4ll_startifp, ifp);
|
||||
ipv4ll_start, ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -286,62 +272,49 @@ ipv4ll_defend_failed(struct interface *ifp)
|
|||
{
|
||||
struct ipv4ll_state *state = IPV4LL_STATE(ifp);
|
||||
|
||||
if (state->arp != NULL)
|
||||
arp_cancel(state->arp);
|
||||
ipv4ll_freearp(ifp);
|
||||
ipv4_deladdr(state->addr, 1);
|
||||
state->down = true;
|
||||
state->addr = NULL;
|
||||
rt_build(ifp->ctx, AF_INET);
|
||||
script_runreason(ifp, "IPV4LL");
|
||||
state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp);
|
||||
ipv4ll_start1(ifp, state->arp);
|
||||
ipv4ll_pickaddr(ifp);
|
||||
ipv4ll_start(ifp);
|
||||
}
|
||||
|
||||
#ifndef KERNEL_RFC5227
|
||||
static void
|
||||
ipv4ll_not_found_arp(struct arp_state *astate)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
assert(astate != NULL);
|
||||
assert(astate->iface != NULL);
|
||||
|
||||
ifp = astate->iface;
|
||||
state = IPV4LL_STATE(ifp);
|
||||
assert(state != NULL);
|
||||
assert(state->arp == astate);
|
||||
ipv4ll_not_found(ifp);
|
||||
ipv4ll_not_found(astate->iface);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv4ll_found_arp(struct arp_state *astate, __unused const struct arp_msg *amsg)
|
||||
{
|
||||
struct interface *ifp = astate->iface;
|
||||
struct ipv4ll_state *state = IPV4LL_STATE(ifp);
|
||||
|
||||
assert(state->arp == astate);
|
||||
ipv4ll_found(ifp);
|
||||
ipv4ll_found(astate->iface);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv4ll_defend_failed_arp(struct arp_state *astate)
|
||||
{
|
||||
struct ipv4ll_state *state = IPV4LL_STATE(astate->iface);
|
||||
|
||||
assert(state->arp == astate);
|
||||
ipv4ll_defend_failed(astate->iface);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ipv4ll_start1(struct interface *ifp, struct arp_state *astate)
|
||||
void
|
||||
ipv4ll_start(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct ipv4ll_state *state;
|
||||
struct ipv4_addr *ia;
|
||||
bool repick;
|
||||
#ifndef KERNEL_RFC5227
|
||||
struct arp_state *astate;
|
||||
#endif
|
||||
|
||||
assert(ifp != NULL);
|
||||
if ((state = IPV4LL_STATE(ifp)) == NULL) {
|
||||
ifp->if_data[IF_DATA_IPV4LL] = calloc(1, sizeof(*state));
|
||||
if ((state = IPV4LL_STATE(ifp)) == NULL) {
|
||||
|
@ -377,26 +350,6 @@ ipv4ll_start1(struct interface *ifp, struct arp_state *astate)
|
|||
state->seeded = true;
|
||||
}
|
||||
|
||||
#ifndef KERNEL_RFC5227
|
||||
if (astate == NULL) {
|
||||
if (state->arp != NULL)
|
||||
return;
|
||||
if ((astate = arp_new(ifp, NULL)) == NULL)
|
||||
return;
|
||||
astate->found_cb = ipv4ll_found_arp;
|
||||
astate->not_found_cb = ipv4ll_not_found_arp;
|
||||
astate->announced_cb = ipv4ll_announced_arp;
|
||||
astate->defend_failed_cb = ipv4ll_defend_failed_arp;
|
||||
astate->free_cb = ipv4ll_arpfree;
|
||||
state->arp = astate;
|
||||
} else
|
||||
assert(state->arp == astate);
|
||||
#else
|
||||
UNUSED(astate);
|
||||
#endif
|
||||
|
||||
state->down = true;
|
||||
|
||||
/* Find the previosuly used address. */
|
||||
if (state->pickedaddr.s_addr != INADDR_ANY)
|
||||
ia = ipv4_iffindaddr(ifp, &state->pickedaddr, NULL);
|
||||
|
@ -418,11 +371,9 @@ ipv4ll_start1(struct interface *ifp, struct arp_state *astate)
|
|||
#endif
|
||||
|
||||
state->addr = ia;
|
||||
state->down = true;
|
||||
if (ia != NULL) {
|
||||
state->pickedaddr = ia->addr;
|
||||
#ifndef KERNEL_RFC5227
|
||||
astate->addr = ia->addr;
|
||||
#endif
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
if (ia->addr_flags & (IN_IFF_TENTATIVE | IN_IFF_DETACHED)) {
|
||||
loginfox("%s: waiting for DAD to complete on %s",
|
||||
|
@ -433,41 +384,27 @@ ipv4ll_start1(struct interface *ifp, struct arp_state *astate)
|
|||
#ifdef IN_IFF_DUPLICATED
|
||||
loginfox("%s: using IPv4LL address %s", ifp->name, ia->saddr);
|
||||
#endif
|
||||
ipv4ll_not_found(ifp);
|
||||
return;
|
||||
} else {
|
||||
loginfox("%s: probing for an IPv4LL address", ifp->name);
|
||||
if (repick || state->pickedaddr.s_addr == INADDR_ANY)
|
||||
ipv4ll_pickaddr(ifp);
|
||||
}
|
||||
|
||||
loginfox("%s: probing for an IPv4LL address", ifp->name);
|
||||
if (repick || state->pickedaddr.s_addr == INADDR_ANY)
|
||||
state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp);
|
||||
#ifndef KERNEL_RFC5227
|
||||
astate->addr = state->pickedaddr;
|
||||
#endif
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
#ifdef KERNEL_RFC5227
|
||||
ipv4ll_not_found(ifp);
|
||||
#else
|
||||
arp_probe(astate);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ipv4ll_start(void *arg)
|
||||
{
|
||||
|
||||
ipv4ll_start1(arg, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv4ll_freearp(struct interface *ifp)
|
||||
{
|
||||
struct ipv4ll_state *state;
|
||||
|
||||
state = IPV4LL_STATE(ifp);
|
||||
if (state == NULL || state->arp == NULL)
|
||||
ipv4ll_freearp(ifp);
|
||||
state->arp = astate = arp_new(ifp, &state->pickedaddr);
|
||||
if (state->arp == NULL)
|
||||
return;
|
||||
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp);
|
||||
arp_free(state->arp);
|
||||
astate->found_cb = ipv4ll_found_arp;
|
||||
astate->not_found_cb = ipv4ll_not_found_arp;
|
||||
astate->announced_cb = ipv4ll_announced_arp;
|
||||
astate->defend_failed_cb = ipv4ll_defend_failed_arp;
|
||||
astate->free_cb = ipv4ll_free_arp;
|
||||
arp_probe(astate);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -516,6 +453,7 @@ ipv4ll_reset(struct interface *ifp)
|
|||
|
||||
if (state == NULL)
|
||||
return;
|
||||
ipv4ll_freearp(ifp);
|
||||
state->pickedaddr.s_addr = INADDR_ANY;
|
||||
state->seeded = false;
|
||||
}
|
||||
|
@ -587,9 +525,7 @@ ipv4ll_handleifa(int cmd, struct ipv4_addr *ia, pid_t pid)
|
|||
ipv4ll_not_found(ifp);
|
||||
else if (ia->addr_flags & IN_IFF_DUPLICATED) {
|
||||
logerrx("%s: DAD detected %s", ifp->name, ia->saddr);
|
||||
#ifdef KERNEL_RFC5227
|
||||
arp_freeaddr(ifp, &ia->addr);
|
||||
#endif
|
||||
ipv4ll_freearp(ifp);
|
||||
ipv4_deladdr(ia, 1);
|
||||
state->addr = NULL;
|
||||
rt_build(ifp->ctx, AF_INET);
|
||||
|
|
|
@ -43,11 +43,13 @@
|
|||
struct ipv4ll_state {
|
||||
struct in_addr pickedaddr;
|
||||
struct ipv4_addr *addr;
|
||||
struct arp_state *arp;
|
||||
char randomstate[128];
|
||||
bool seeded;
|
||||
bool down;
|
||||
size_t conflicts;
|
||||
#ifndef KERNEL_RFC5227
|
||||
struct arp_state *arp;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IPV4LL_STATE(ifp) \
|
||||
|
|
|
@ -98,10 +98,9 @@ struct rs_state {
|
|||
#define RETRANS_TIMER 1000 /* milliseconds */
|
||||
#define DELAY_FIRST_PROBE_TIME 5 /* seconds */
|
||||
|
||||
int ipv6nd_open(bool);
|
||||
#ifdef __sun
|
||||
int ipv6nd_open(struct interface *);
|
||||
#else
|
||||
int ipv6nd_open(struct dhcpcd_ctx *);
|
||||
int ipv6nd_openif(struct interface *);
|
||||
#endif
|
||||
void ipv6nd_recvmsg(struct dhcpcd_ctx *, struct msghdr *);
|
||||
int ipv6nd_rtpref(struct ra *);
|
||||
|
|
|
@ -54,11 +54,15 @@
|
|||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
#include <sys/capsicum.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
ps_bpf_recvbpf(void *arg)
|
||||
{
|
||||
struct ps_process *psp = arg;
|
||||
unsigned int flags;
|
||||
struct bpf *bpf = psp->psp_bpf;
|
||||
uint8_t buf[FRAMELEN_MAX];
|
||||
ssize_t len;
|
||||
struct ps_msghdr psm = {
|
||||
|
@ -66,16 +70,16 @@ ps_bpf_recvbpf(void *arg)
|
|||
.ps_cmd = psp->psp_id.psi_cmd,
|
||||
};
|
||||
|
||||
bpf->bpf_flags &= ~BPF_EOF;
|
||||
/* A BPF read can read more than one filtered packet at time.
|
||||
* This mechanism allows us to read each packet from the buffer. */
|
||||
flags = 0;
|
||||
while (!(flags & BPF_EOF)) {
|
||||
len = bpf_read(&psp->psp_ifp, psp->psp_work_fd,
|
||||
buf, sizeof(buf), &flags);
|
||||
while (!(bpf->bpf_flags & BPF_EOF)) {
|
||||
len = bpf_read(bpf, buf, sizeof(buf));
|
||||
if (len == -1)
|
||||
logerr(__func__);
|
||||
if (len == -1 || len == 0)
|
||||
break;
|
||||
psm.ps_flags = bpf->bpf_flags;
|
||||
len = ps_sendpsmdata(psp->psp_ctx, psp->psp_ctx->ps_data_fd,
|
||||
&psm, buf, (size_t)len);
|
||||
if (len == -1 && errno != ECONNRESET)
|
||||
|
@ -85,55 +89,30 @@ ps_bpf_recvbpf(void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ARP
|
||||
static ssize_t
|
||||
ps_bpf_arp_addr(uint8_t cmd, struct ps_process *psp, struct msghdr *msg)
|
||||
{
|
||||
struct interface *ifp = &psp->psp_ifp;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
struct in_addr addr;
|
||||
struct arp_state *astate;
|
||||
|
||||
if (psp == NULL) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(msg->msg_iovlen == 1);
|
||||
assert(iov->iov_len == sizeof(addr));
|
||||
memcpy(&addr, iov->iov_base, sizeof(addr));
|
||||
if (cmd & PS_START) {
|
||||
astate = arp_new(ifp, &addr);
|
||||
if (astate == NULL)
|
||||
return -1;
|
||||
} else if (cmd & PS_DELETE) {
|
||||
astate = arp_find(ifp, &addr);
|
||||
if (astate == NULL) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
arp_free(astate);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bpf_arp(ifp, psp->psp_work_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_bpf_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
struct ps_process *psp = arg;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
|
||||
#ifdef ARP
|
||||
if (psm->ps_cmd & (PS_START | PS_DELETE))
|
||||
return ps_bpf_arp_addr(psm->ps_cmd, psp, msg);
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
|
||||
#endif
|
||||
|
||||
return bpf_send(&psp->psp_ifp, psp->psp_work_fd, psp->psp_proto,
|
||||
switch(psm->ps_cmd) {
|
||||
#ifdef ARP
|
||||
case PS_BPF_ARP: /* FALLTHROUGH */
|
||||
#endif
|
||||
case PS_BPF_BOOTP:
|
||||
break;
|
||||
default:
|
||||
/* IPC failure, we should not be processing any commands
|
||||
* at this point!/ */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bpf_send(psp->psp_bpf, psp->psp_proto,
|
||||
iov->iov_base, iov->iov_len);
|
||||
}
|
||||
|
||||
|
@ -152,19 +131,40 @@ ps_bpf_start_bpf(void *arg)
|
|||
{
|
||||
struct ps_process *psp = arg;
|
||||
struct dhcpcd_ctx *ctx = psp->psp_ctx;
|
||||
char *addr;
|
||||
struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
|
||||
setproctitle("[BPF %s] %s", psp->psp_protostr, psp->psp_ifname);
|
||||
/* We need CAP_IOCTL so we can change the BPF filter when we
|
||||
* need to. */
|
||||
cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_IOCTL);
|
||||
#endif
|
||||
|
||||
if (ia->s_addr == INADDR_ANY) {
|
||||
ia = NULL;
|
||||
addr = NULL;
|
||||
} else
|
||||
addr = inet_ntoa(*ia);
|
||||
setproctitle("[BPF %s] %s%s%s", psp->psp_protostr, psp->psp_ifname,
|
||||
addr != NULL ? " " : "", addr != NULL ? addr : "");
|
||||
ps_freeprocesses(ctx, psp);
|
||||
|
||||
psp->psp_work_fd = bpf_open(&psp->psp_ifp, psp->psp_filter);
|
||||
if (psp->psp_work_fd == -1)
|
||||
psp->psp_bpf = bpf_open(&psp->psp_ifp, psp->psp_filter, ia);
|
||||
if (psp->psp_bpf == NULL)
|
||||
logerr("%s: bpf_open",__func__);
|
||||
#ifdef HAVE_CAPSICUM
|
||||
else if (cap_rights_limit(psp->psp_bpf->bpf_fd, &rights) == -1 &&
|
||||
errno != ENOSYS)
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
#endif
|
||||
else if (eloop_event_add(ctx->eloop,
|
||||
psp->psp_work_fd, ps_bpf_recvbpf, psp) == -1)
|
||||
psp->psp_bpf->bpf_fd, ps_bpf_recvbpf, psp) == -1)
|
||||
logerr("%s: eloop_event_add", __func__);
|
||||
else
|
||||
else {
|
||||
psp->psp_work_fd = psp->psp_bpf->bpf_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
eloop_exit(ctx->eloop, EXIT_FAILURE);
|
||||
return -1;
|
||||
|
@ -181,14 +181,13 @@ ps_bpf_signal_bpfcb(int sig, void *arg)
|
|||
ssize_t
|
||||
ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t cmd;
|
||||
struct ps_process *psp;
|
||||
pid_t start;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
struct interface *ifp;
|
||||
struct ipv4_state *istate;
|
||||
|
||||
cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
|
||||
cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
|
||||
psp = ps_findprocess(ctx, &psm->ps_id);
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
|
@ -227,11 +226,6 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
|
|||
ifp->options = NULL;
|
||||
memset(ifp->if_data, 0, sizeof(ifp->if_data));
|
||||
|
||||
if ((istate = ipv4_getstate(ifp)) == NULL) {
|
||||
ps_freeprocess(psp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(psp->psp_ifname, ifp->name, sizeof(psp->psp_ifname));
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -252,12 +246,21 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
|
|||
start = ps_dostart(ctx,
|
||||
&psp->psp_pid, &psp->psp_fd,
|
||||
ps_bpf_recvmsg, NULL, psp,
|
||||
ps_bpf_start_bpf, ps_bpf_signal_bpfcb, PSF_DROPPRIVS);
|
||||
ps_bpf_start_bpf, ps_bpf_signal_bpfcb,
|
||||
PSF_DROPPRIVS);
|
||||
switch (start) {
|
||||
case -1:
|
||||
ps_freeprocess(psp);
|
||||
return -1;
|
||||
case 0:
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (cap_enter() == -1 && errno != ENOSYS)
|
||||
logerr("%s: cap_enter", __func__);
|
||||
#endif
|
||||
#ifdef HAVE_PLEDGE
|
||||
if (pledge("stdio", NULL) == -1)
|
||||
logerr("%s: pledge", __func__);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
|
@ -275,17 +278,21 @@ ps_bpf_dispatch(struct dhcpcd_ctx *ctx,
|
|||
{
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
struct interface *ifp;
|
||||
uint8_t *bpf;
|
||||
size_t bpf_len;
|
||||
|
||||
ifp = if_findindex(ctx->ifaces, psm->ps_id.psi_ifindex);
|
||||
bpf = iov->iov_base;
|
||||
bpf_len = iov->iov_len;
|
||||
|
||||
switch (psm->ps_cmd) {
|
||||
#ifdef ARP
|
||||
case PS_BPF_ARP:
|
||||
arp_packet(ifp, iov->iov_base, iov->iov_len);
|
||||
arp_packet(ifp, bpf, bpf_len, (unsigned int)psm->ps_flags);
|
||||
break;
|
||||
#endif
|
||||
case PS_BPF_BOOTP:
|
||||
dhcp_packet(ifp, iov->iov_base, iov->iov_len);
|
||||
dhcp_packet(ifp, bpf, bpf_len, (unsigned int)psm->ps_flags);
|
||||
break;
|
||||
default:
|
||||
errno = ENOTSUP;
|
||||
|
@ -296,59 +303,48 @@ ps_bpf_dispatch(struct dhcpcd_ctx *ctx,
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
ps_bpf_send(const struct interface *ifp, uint8_t cmd,
|
||||
const void *data, size_t len)
|
||||
ps_bpf_send(const struct interface *ifp, const struct in_addr *ia,
|
||||
uint16_t cmd, const void *data, size_t len)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
struct ps_msghdr psm = {
|
||||
.ps_cmd = cmd,
|
||||
.ps_id = {
|
||||
.psi_ifindex = ifp->index,
|
||||
.psi_cmd = (uint8_t)(cmd &
|
||||
~(PS_START | PS_STOP | PS_DELETE)),
|
||||
.psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)),
|
||||
},
|
||||
};
|
||||
|
||||
if (psm.ps_id.psi_cmd == PS_BPF_ARP_ADDR)
|
||||
psm.ps_id.psi_cmd = PS_BPF_ARP;
|
||||
if (ia != NULL)
|
||||
psm.ps_id.psi_addr.psa_in_addr = *ia;
|
||||
|
||||
return ps_sendpsmdata(ctx, ctx->ps_root_fd, &psm, data, len);
|
||||
}
|
||||
|
||||
#ifdef ARP
|
||||
ssize_t
|
||||
ps_bpf_openarp(const struct interface *ifp)
|
||||
ps_bpf_openarp(const struct interface *ifp, const struct in_addr *ia)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_ARP | PS_START, ifp, sizeof(*ifp));
|
||||
assert(ia != NULL);
|
||||
return ps_bpf_send(ifp, ia, PS_BPF_ARP | PS_START,
|
||||
ifp, sizeof(*ifp));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_addaddr(const struct interface *ifp, const struct in_addr *addr)
|
||||
ps_bpf_closearp(const struct interface *ifp, const struct in_addr *ia)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_ARP_ADDR | PS_START, addr, sizeof(*addr));
|
||||
return ps_bpf_send(ifp, ia, PS_BPF_ARP | PS_STOP, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_deladdr(const struct interface *ifp, const struct in_addr *addr)
|
||||
ps_bpf_sendarp(const struct interface *ifp, const struct in_addr *ia,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_ARP_ADDR | PS_DELETE, addr, sizeof(*addr));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_closearp(const struct interface *ifp)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_ARP | PS_STOP, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_sendarp(const struct interface *ifp, const void *data, size_t len)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_ARP, data, len);
|
||||
assert(ia != NULL);
|
||||
return ps_bpf_send(ifp, ia, PS_BPF_ARP, data, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -356,19 +352,20 @@ ssize_t
|
|||
ps_bpf_openbootp(const struct interface *ifp)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_BOOTP | PS_START, ifp, sizeof(*ifp));
|
||||
return ps_bpf_send(ifp, NULL, PS_BPF_BOOTP | PS_START,
|
||||
ifp, sizeof(*ifp));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_closebootp(const struct interface *ifp)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_BOOTP | PS_STOP, NULL, 0);
|
||||
return ps_bpf_send(ifp, NULL, PS_BPF_BOOTP | PS_STOP, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_bpf_sendbootp(const struct interface *ifp, const void *data, size_t len)
|
||||
{
|
||||
|
||||
return ps_bpf_send(ifp, PS_BPF_BOOTP, data, len);
|
||||
return ps_bpf_send(ifp, NULL, PS_BPF_BOOTP, data, len);
|
||||
}
|
||||
|
|
|
@ -35,11 +35,10 @@ ssize_t ps_bpf_dispatch(struct dhcpcd_ctx *,
|
|||
struct ps_msghdr *, struct msghdr *);
|
||||
|
||||
#ifdef ARP
|
||||
ssize_t ps_bpf_openarp(const struct interface *);
|
||||
ssize_t ps_bpf_addaddr(const struct interface *, const struct in_addr *);
|
||||
ssize_t ps_bpf_deladdr(const struct interface *, const struct in_addr *);
|
||||
ssize_t ps_bpf_closearp(const struct interface *);
|
||||
ssize_t ps_bpf_sendarp(const struct interface *, const void *, size_t);
|
||||
ssize_t ps_bpf_openarp(const struct interface *, const struct in_addr *);
|
||||
ssize_t ps_bpf_closearp(const struct interface *, const struct in_addr *);
|
||||
ssize_t ps_bpf_sendarp(const struct interface *, const struct in_addr *,
|
||||
const void *, size_t);
|
||||
#endif
|
||||
|
||||
ssize_t ps_bpf_openbootp(const struct interface *);
|
||||
|
|
|
@ -28,7 +28,20 @@
|
|||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/* Need these for filtering the ioctls */
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#ifdef __DragonFly__
|
||||
# include <netproto/802_11/ieee80211_ioctl.h>
|
||||
#else
|
||||
# include <net80211/ieee80211.h>
|
||||
# include <net80211/ieee80211_ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dhcpcd.h"
|
||||
|
@ -40,13 +53,43 @@ ps_root_doioctldom(int domain, unsigned long req, void *data, size_t len)
|
|||
{
|
||||
int s, err;
|
||||
|
||||
/* Only allow these ioctls */
|
||||
switch(req) {
|
||||
#ifdef SIOCIFAFATTACH
|
||||
case SIOCIFAFATTACH: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCSIFXFLAGS
|
||||
case SIOCSIFXFLAGS: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCSIFINFO_FLAGS
|
||||
case SIOCSIFINFO_FLAGS: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCSRTRFLUSH_IN6
|
||||
case SIOCSRTRFLUSH_IN6: /* FALLTHROUGH */
|
||||
case SIOCSPFXFLUSH_IN6: /* FALLTHROUGH */
|
||||
#endif
|
||||
#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE)
|
||||
case SIOCALIFADDR: /* FALLTHROUGH */
|
||||
case SIOCDLIFADDR: /* FALLTHROUGH */
|
||||
#else
|
||||
case SIOCSIFLLADDR: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCSIFINFO_IN6
|
||||
case SIOCSIFINFO_IN6: /* FALLTHROUGH */
|
||||
#endif
|
||||
case SIOCAIFADDR_IN6: /* FALLTHROUGH */
|
||||
case SIOCDIFADDR_IN6: /* FALLTHROUGH */
|
||||
break;
|
||||
default:
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = socket(domain, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
err = ioctl(s, req, data, len);
|
||||
else
|
||||
err = -1;
|
||||
if (s != -1)
|
||||
close(s);
|
||||
if (s == -1)
|
||||
return -1;
|
||||
err = ioctl(s, req, data, len);
|
||||
close(s);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -66,6 +109,37 @@ ps_root_doroute(void *data, size_t len)
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PLEDGE
|
||||
static ssize_t
|
||||
ps_root_doindirectioctl(unsigned long req, void *data, size_t len)
|
||||
{
|
||||
char *p = data;
|
||||
struct ifreq ifr = { .ifr_flags = 0 };
|
||||
ssize_t err;
|
||||
|
||||
switch(req) {
|
||||
case SIOCG80211NWID: /* FALLTHROUGH */
|
||||
case SIOCGETVLAN:
|
||||
break;
|
||||
default:
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len < IFNAMSIZ) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strlcpy(ifr.ifr_name, p, IFNAMSIZ);
|
||||
ifr.ifr_data = p + IFNAMSIZ;
|
||||
err = ps_root_doioctldom(PF_INET, req, &ifr, sizeof(ifr));
|
||||
if (err != -1)
|
||||
memmove(data, ifr.ifr_data, len - IFNAMSIZ);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t
|
||||
ps_root_os(struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
|
@ -80,6 +154,10 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg)
|
|||
return ps_root_doioctldom(PF_INET6, psm->ps_flags, data, len);
|
||||
case PS_ROUTE:
|
||||
return ps_root_doroute(data, len);
|
||||
#ifdef HAVE_PLEDGE
|
||||
case PS_IOCTLINDIRECT:
|
||||
return ps_root_doindirectioctl(psm->ps_flags, data, len);
|
||||
#endif
|
||||
default:
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
|
@ -87,19 +165,19 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg)
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint8_t domain, unsigned long request,
|
||||
ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint16_t domain, unsigned long request,
|
||||
void *data, size_t len)
|
||||
{
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, domain,
|
||||
request, data, len) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx);
|
||||
return ps_root_readerror(ctx, data, len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_ioctllink(struct dhcpcd_ctx *ctx, unsigned long request,
|
||||
void *data,size_t len)
|
||||
void *data, size_t len)
|
||||
{
|
||||
|
||||
return ps_root_ioctldom(ctx, PS_IOCTLLINK, request, data, len);
|
||||
|
@ -119,5 +197,21 @@ ps_root_route(struct dhcpcd_ctx *ctx, void *data, size_t len)
|
|||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_ROUTE, 0, data, len) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx);
|
||||
return ps_root_readerror(ctx, data, len);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PLEDGE
|
||||
ssize_t
|
||||
ps_root_indirectioctl(struct dhcpcd_ctx *ctx, unsigned long request,
|
||||
const char *ifname, void *data, size_t len)
|
||||
{
|
||||
char buf[PS_BUFLEN];
|
||||
|
||||
strlcpy(buf, ifname, IFNAMSIZ);
|
||||
memcpy(buf + IFNAMSIZ, data, len);
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IOCTLINDIRECT,
|
||||
request, buf, IFNAMSIZ + len) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx, data, len);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
@ -45,13 +48,17 @@
|
|||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
#include <sys/capsicum.h>
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
static void
|
||||
ps_inet_recvbootp(void *arg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
|
||||
if (ps_recvmsg(ctx, ctx->udp_fd, PS_BOOTP, ctx->ps_inet_fd) == -1)
|
||||
if (ps_recvmsg(ctx, ctx->udp_rfd, PS_BOOTP, ctx->ps_inet_fd) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
#endif
|
||||
|
@ -82,7 +89,7 @@ ps_inet_recvdhcp6(void *arg)
|
|||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
|
||||
if (ps_recvmsg(ctx, ctx->dhcp6_fd, PS_DHCP6, ctx->ps_inet_fd) == -1)
|
||||
if (ps_recvmsg(ctx, ctx->dhcp6_rfd, PS_DHCP6, ctx->ps_inet_fd) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
#endif
|
||||
|
@ -92,8 +99,19 @@ ps_inet_startcb(void *arg)
|
|||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
int ret = 0;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
|
||||
setproctitle("[network proxy]");
|
||||
cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
|
||||
#endif
|
||||
|
||||
if (ctx->options & DHCPCD_MASTER)
|
||||
setproctitle("[network proxy]");
|
||||
else
|
||||
setproctitle("[network proxy] %s%s%s",
|
||||
ctx->ifv[0],
|
||||
ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
|
||||
ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
|
||||
|
||||
/* This end is the main engine, so it's useless for us. */
|
||||
close(ctx->ps_data_fd);
|
||||
|
@ -105,23 +123,42 @@ ps_inet_startcb(void *arg)
|
|||
if ((ctx->options & (DHCPCD_IPV4 | DHCPCD_MASTER)) ==
|
||||
(DHCPCD_IPV4 | DHCPCD_MASTER))
|
||||
{
|
||||
ctx->udp_fd = dhcp_openudp(NULL);
|
||||
if (ctx->udp_fd == -1)
|
||||
ctx->udp_rfd = dhcp_openudp(NULL);
|
||||
if (ctx->udp_rfd == -1)
|
||||
logerr("%s: dhcp_open", __func__);
|
||||
else if (eloop_event_add(ctx->eloop, ctx->udp_fd,
|
||||
#ifdef HAVE_CAPSICUM
|
||||
else if (cap_rights_limit(ctx->udp_rfd, &rights) == -1
|
||||
&& errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
close(ctx->udp_rfd);
|
||||
ctx->udp_rfd = -1;
|
||||
}
|
||||
#endif
|
||||
else if (eloop_event_add(ctx->eloop, ctx->udp_rfd,
|
||||
ps_inet_recvbootp, ctx) == -1)
|
||||
{
|
||||
logerr("%s: eloop_event_add DHCP", __func__);
|
||||
close(ctx->udp_fd);
|
||||
ctx->udp_fd = -1;
|
||||
close(ctx->udp_rfd);
|
||||
ctx->udp_rfd = -1;
|
||||
} else
|
||||
ret++;
|
||||
}
|
||||
#endif
|
||||
#if defined(INET6) && !defined(__sun)
|
||||
if (ctx->options & DHCPCD_IPV6) {
|
||||
if (ipv6nd_open(ctx) == -1)
|
||||
ctx->nd_fd = ipv6nd_open(true);
|
||||
if (ctx->nd_fd == -1)
|
||||
logerr("%s: ipv6nd_open", __func__);
|
||||
#ifdef HAVE_CAPSICUM
|
||||
else if (cap_rights_limit(ctx->nd_fd, &rights) == -1
|
||||
&& errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
close(ctx->nd_fd);
|
||||
ctx->nd_fd = -1;
|
||||
}
|
||||
#endif
|
||||
else if (eloop_event_add(ctx->eloop, ctx->nd_fd,
|
||||
ps_inet_recvra, ctx) == -1)
|
||||
{
|
||||
|
@ -136,15 +173,24 @@ ps_inet_startcb(void *arg)
|
|||
if ((ctx->options & (DHCPCD_DHCP6 | DHCPCD_MASTER)) ==
|
||||
(DHCPCD_DHCP6 | DHCPCD_MASTER))
|
||||
{
|
||||
ctx->dhcp6_fd = dhcp6_openudp(0, NULL);
|
||||
if (ctx->dhcp6_fd == -1)
|
||||
ctx->dhcp6_rfd = dhcp6_openudp(0, NULL);
|
||||
if (ctx->dhcp6_rfd == -1)
|
||||
logerr("%s: dhcp6_open", __func__);
|
||||
else if (eloop_event_add(ctx->eloop, ctx->dhcp6_fd,
|
||||
#ifdef HAVE_CAPSICUM
|
||||
else if (cap_rights_limit(ctx->dhcp6_rfd, &rights) == -1
|
||||
&& errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
close(ctx->dhcp6_rfd);
|
||||
ctx->dhcp6_rfd = -1;
|
||||
}
|
||||
#endif
|
||||
else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd,
|
||||
ps_inet_recvdhcp6, ctx) == -1)
|
||||
{
|
||||
logerr("%s: eloop_event_add DHCP6", __func__);
|
||||
close(ctx->dhcp6_fd);
|
||||
ctx->dhcp6_fd = -1;
|
||||
close(ctx->dhcp6_rfd);
|
||||
ctx->dhcp6_rfd = -1;
|
||||
} else
|
||||
ret++;
|
||||
}
|
||||
|
@ -157,34 +203,84 @@ ps_inet_startcb(void *arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ps_inet_recvmsg_cb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
static bool
|
||||
ps_inet_validudp(struct msghdr *msg, uint16_t sport, uint16_t dport)
|
||||
{
|
||||
struct udphdr udp;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
|
||||
if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(udp)) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&udp, iov->iov_base, sizeof(udp));
|
||||
if (udp.uh_sport != htons(sport) || udp.uh_dport != htons(dport)) {
|
||||
errno = EPERM;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static bool
|
||||
ps_inet_validnd(struct msghdr *msg)
|
||||
{
|
||||
struct icmp6_hdr icmp6;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
|
||||
if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(icmp6)) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&icmp6, iov->iov_base, sizeof(icmp6));
|
||||
switch(icmp6.icmp6_type) {
|
||||
case ND_ROUTER_SOLICIT:
|
||||
case ND_NEIGHBOR_ADVERT:
|
||||
break;
|
||||
default:
|
||||
errno = EPERM;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_inet_sendmsg(struct dhcpcd_ctx *ctx,
|
||||
struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
struct ps_process *psp;
|
||||
int s;
|
||||
|
||||
psp = ps_findprocess(ctx, &psm->ps_id);
|
||||
if (psp != NULL) {
|
||||
s = psp->psp_work_fd;
|
||||
logerrx("psp found fd %d", s);
|
||||
goto dosend;
|
||||
}
|
||||
|
||||
switch (psm->ps_cmd) {
|
||||
#ifdef INET
|
||||
case PS_BOOTP:
|
||||
s = ctx->udp_fd;
|
||||
if (!ps_inet_validudp(msg, BOOTPC, BOOTPS))
|
||||
return -1;
|
||||
s = ctx->udp_wfd;
|
||||
break;
|
||||
#endif
|
||||
#if defined(INET6) && !defined(__sun)
|
||||
case PS_ND:
|
||||
if (!ps_inet_validnd(msg))
|
||||
return -1;
|
||||
s = ctx->nd_fd;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DHCP6
|
||||
case PS_DHCP6:
|
||||
s = ctx->dhcp6_fd;
|
||||
if (!ps_inet_validudp(msg, DHCP6_CLIENT_PORT,DHCP6_SERVER_PORT))
|
||||
return -1;
|
||||
s = ctx->dhcp6_wfd;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -193,17 +289,16 @@ ps_inet_recvmsg_cb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
|||
}
|
||||
|
||||
dosend:
|
||||
|
||||
return sendmsg(s, msg, 0);
|
||||
}
|
||||
|
||||
/* Receive from state engine, send message on wire. */
|
||||
static void
|
||||
ps_inet_recvmsg(void *arg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
|
||||
if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, ps_inet_recvmsg_cb, ctx) == -1)
|
||||
/* Receive shutdown */
|
||||
if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, NULL, NULL) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
|
||||
|
@ -260,10 +355,23 @@ ps_inet_dodispatch(void *arg)
|
|||
pid_t
|
||||
ps_inet_start(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
return ps_dostart(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd,
|
||||
pid = ps_dostart(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd,
|
||||
ps_inet_recvmsg, ps_inet_dodispatch, ctx,
|
||||
ps_inet_startcb, ps_inet_signalcb, PSF_DROPPRIVS);
|
||||
ps_inet_startcb, ps_inet_signalcb,
|
||||
PSF_DROPPRIVS);
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (pid == 0 && cap_enter() == -1 && errno != ENOSYS)
|
||||
logerr("%s: cap_enter", __func__);
|
||||
#endif
|
||||
#ifdef HAVE_PLEDGE
|
||||
if (pid == 0 && pledge("stdio", NULL) == -1)
|
||||
logerr("%s: pledge", __func__);
|
||||
#endif
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -273,13 +381,6 @@ ps_inet_stop(struct dhcpcd_ctx *ctx)
|
|||
return ps_dostop(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_inet_sendmsg(struct dhcpcd_ctx *ctx, uint8_t cmd, const struct msghdr *msg)
|
||||
{
|
||||
|
||||
return ps_sendmsg(ctx, ctx->ps_inet_fd, cmd, 0, msg);
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
static void
|
||||
ps_inet_recvinbootp(void *arg)
|
||||
|
@ -297,6 +398,11 @@ ps_inet_listenin(void *arg)
|
|||
struct ps_process *psp = arg;
|
||||
struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
|
||||
cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
|
||||
#endif
|
||||
|
||||
inet_ntop(AF_INET, ia, buf, sizeof(buf));
|
||||
setproctitle("[network proxy] %s", buf);
|
||||
|
@ -307,6 +413,15 @@ ps_inet_listenin(void *arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (cap_rights_limit(psp->psp_work_fd, &rights) == -1 &&
|
||||
errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
|
||||
ps_inet_recvinbootp, psp) == -1)
|
||||
{
|
||||
|
@ -314,9 +429,7 @@ ps_inet_listenin(void *arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("spawned listener %s on PID %d", buf, getpid());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -336,6 +449,11 @@ static int
|
|||
ps_inet_listennd(void *arg)
|
||||
{
|
||||
struct ps_process *psp = arg;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
|
||||
cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
|
||||
#endif
|
||||
|
||||
setproctitle("[ND network proxy]");
|
||||
|
||||
|
@ -345,6 +463,15 @@ ps_inet_listennd(void *arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (cap_rights_limit(psp->psp_work_fd, &rights) == -1 &&
|
||||
errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
|
||||
ps_inet_recvin6nd, psp) == -1)
|
||||
{
|
||||
|
@ -374,6 +501,11 @@ ps_inet_listenin6(void *arg)
|
|||
struct ps_process *psp = arg;
|
||||
struct in6_addr *ia = &psp->psp_id.psi_addr.psa_in6_addr;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
|
||||
cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
|
||||
#endif
|
||||
|
||||
inet_ntop(AF_INET6, ia, buf, sizeof(buf));
|
||||
setproctitle("[network proxy] %s", buf);
|
||||
|
@ -384,6 +516,15 @@ ps_inet_listenin6(void *arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (cap_rights_limit(psp->psp_work_fd, &rights) == -1 &&
|
||||
errno != ENOSYS)
|
||||
{
|
||||
logerr("%s: cap_rights_limit", __func__);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
|
||||
ps_inet_recvin6dhcp6, psp) == -1)
|
||||
{
|
||||
|
@ -396,35 +537,28 @@ ps_inet_listenin6(void *arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_inet_recvmsgpsp_cb(void *arg, __unused struct ps_msghdr *psm,
|
||||
struct msghdr *msg)
|
||||
{
|
||||
struct ps_process *psp = arg;
|
||||
|
||||
return sendmsg(psp->psp_work_fd, msg, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ps_inet_recvmsgpsp(void *arg)
|
||||
{
|
||||
struct ps_process *psp = arg;
|
||||
|
||||
if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd,
|
||||
ps_inet_recvmsgpsp_cb, psp) == -1)
|
||||
/* Receive shutdown. */
|
||||
if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, NULL, NULL) == -1)
|
||||
logerr(__func__);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
|
||||
__unused struct msghdr *msg)
|
||||
ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint16_t cmd;
|
||||
struct ps_process *psp;
|
||||
int (*start_func)(void *);
|
||||
pid_t start;
|
||||
|
||||
cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
|
||||
cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
|
||||
if (cmd == psm->ps_cmd)
|
||||
return ps_inet_sendmsg(ctx, psm, msg);
|
||||
|
||||
psp = ps_findprocess(ctx, &psm->ps_id);
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
|
@ -475,12 +609,21 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
|
|||
start = ps_dostart(ctx,
|
||||
&psp->psp_pid, &psp->psp_fd,
|
||||
ps_inet_recvmsgpsp, NULL, psp,
|
||||
start_func, ps_inet_signalcb, PSF_DROPPRIVS);
|
||||
start_func, ps_inet_signalcb,
|
||||
PSF_DROPPRIVS);
|
||||
switch (start) {
|
||||
case -1:
|
||||
ps_freeprocess(psp);
|
||||
return -1;
|
||||
case 0:
|
||||
#ifdef HAVE_CAPSICUM
|
||||
if (cap_enter() == -1 && errno != ENOSYS)
|
||||
logerr("%s: cap_enter", __func__);
|
||||
#endif
|
||||
#ifdef HAVE_PLEDGE
|
||||
if (pledge("stdio", NULL) == -1)
|
||||
logerr("%s: pledge", __func__);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -490,7 +633,7 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
|
|||
|
||||
#ifdef INET
|
||||
static ssize_t
|
||||
ps_inet_in_docmd(struct ipv4_addr *ia, uint8_t cmd, const struct msghdr *msg)
|
||||
ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg)
|
||||
{
|
||||
assert(ia != NULL);
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
|
@ -521,20 +664,17 @@ ps_inet_closebootp(struct ipv4_addr *ia)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
ps_inet_sendbootp(struct ipv4_addr *ia, const struct msghdr *msg)
|
||||
ps_inet_sendbootp(struct interface *ifp, const struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
|
||||
if (ctx->options & DHCPCD_MASTER)
|
||||
return ps_sendmsg(ctx, ctx->ps_inet_fd, PS_BOOTP, 0, msg);
|
||||
return ps_inet_in_docmd(ia, PS_BOOTP, msg);
|
||||
return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_BOOTP, 0, msg);
|
||||
}
|
||||
#endif /* INET */
|
||||
|
||||
#ifdef INET6
|
||||
#ifdef __sun
|
||||
static ssize_t
|
||||
ps_inet_ifp_docmd(struct interface *ifp, uint8_t cmd, const struct msghdr *msg)
|
||||
ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
struct ps_msghdr psm = {
|
||||
|
@ -573,13 +713,13 @@ ssize_t
|
|||
ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg)
|
||||
{
|
||||
|
||||
return ps_inet_sendmsg(ifp->ctx, PS_ND, msg);
|
||||
return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_ND, 0, msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DHCP6
|
||||
static ssize_t
|
||||
ps_inet_in6_docmd(struct ipv6_addr *ia, uint8_t cmd, const struct msghdr *msg)
|
||||
ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
struct ps_msghdr psm = {
|
||||
|
@ -609,13 +749,10 @@ ps_inet_closedhcp6(struct ipv6_addr *ia)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
ps_inet_senddhcp6(struct ipv6_addr *ia, const struct msghdr *msg)
|
||||
ps_inet_senddhcp6(struct interface *ifp, const struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
|
||||
if (ctx->options & DHCPCD_MASTER)
|
||||
return ps_sendmsg(ctx, ctx->ps_inet_fd, PS_DHCP6, 0, msg);
|
||||
return ps_inet_in6_docmd(ia, PS_DHCP6, msg);
|
||||
return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_DHCP6, 0, msg);
|
||||
}
|
||||
#endif /* DHCP6 */
|
||||
#endif /* INET6 */
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
pid_t ps_inet_start(struct dhcpcd_ctx *);
|
||||
int ps_inet_stop(struct dhcpcd_ctx *);
|
||||
ssize_t ps_inet_sendmsg(struct dhcpcd_ctx *, uint8_t, const struct msghdr *);
|
||||
ssize_t ps_inet_cmd(struct dhcpcd_ctx *, struct ps_msghdr *, struct msghdr *);
|
||||
ssize_t ps_inet_dispatch(void *, struct ps_msghdr *, struct msghdr *);
|
||||
|
||||
|
@ -39,7 +38,7 @@ ssize_t ps_inet_dispatch(void *, struct ps_msghdr *, struct msghdr *);
|
|||
struct ipv4_addr;
|
||||
ssize_t ps_inet_openbootp(struct ipv4_addr *);
|
||||
ssize_t ps_inet_closebootp(struct ipv4_addr *);
|
||||
ssize_t ps_inet_sendbootp(struct ipv4_addr *, const struct msghdr *);
|
||||
ssize_t ps_inet_sendbootp(struct interface *, const struct msghdr *);
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
|
@ -52,7 +51,7 @@ ssize_t ps_inet_sendnd(struct interface *, const struct msghdr *);
|
|||
#ifdef DHCP6
|
||||
ssize_t ps_inet_opendhcp6(struct ipv6_addr *);
|
||||
ssize_t ps_inet_closedhcp6(struct ipv6_addr *);
|
||||
ssize_t ps_inet_senddhcp6(struct ipv6_addr *, const struct msghdr *);
|
||||
ssize_t ps_inet_senddhcp6(struct interface *, const struct msghdr *);
|
||||
#endif /* DHCP6 */
|
||||
#endif /* INET6 */
|
||||
#endif
|
||||
|
|
|
@ -38,16 +38,21 @@
|
|||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "dev.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "dhcp6.h"
|
||||
#include "eloop.h"
|
||||
#include "if.h"
|
||||
#include "ipv6nd.h"
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
#include "sa.h"
|
||||
#include "script.h"
|
||||
|
||||
__CTASSERT(sizeof(ioctl_request_t) <= sizeof(unsigned long));
|
||||
|
@ -57,11 +62,14 @@ struct psr_error
|
|||
ssize_t psr_result;
|
||||
int psr_errno;
|
||||
char psr_pad[sizeof(ssize_t) - sizeof(int)];
|
||||
size_t psr_datalen;
|
||||
};
|
||||
|
||||
struct psr_ctx {
|
||||
struct dhcpcd_ctx *psr_ctx;
|
||||
struct psr_error psr_error;
|
||||
size_t psr_datalen;
|
||||
void *psr_data;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -78,35 +86,43 @@ ps_root_readerrorcb(void *arg)
|
|||
struct psr_ctx *psr_ctx = arg;
|
||||
struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
|
||||
struct psr_error *psr_error = &psr_ctx->psr_error;
|
||||
struct iovec iov[] = {
|
||||
{ .iov_base = psr_error, .iov_len = sizeof(*psr_error) },
|
||||
{ .iov_base = psr_ctx->psr_data,
|
||||
.iov_len = psr_ctx->psr_datalen },
|
||||
};
|
||||
ssize_t len;
|
||||
int exit_code = EXIT_FAILURE;
|
||||
|
||||
len = read(ctx->ps_root_fd, psr_error, sizeof(*psr_error));
|
||||
if (len == 0 || len == -1) {
|
||||
logerr(__func__);
|
||||
psr_error->psr_result = -1;
|
||||
psr_error->psr_errno = errno;
|
||||
} else if ((size_t)len < sizeof(*psr_error)) {
|
||||
logerrx("%s: psr_error truncated", __func__);
|
||||
psr_error->psr_result = -1;
|
||||
psr_error->psr_errno = EINVAL;
|
||||
} else
|
||||
exit_code = EXIT_SUCCESS;
|
||||
#define PSR_ERROR(e) \
|
||||
do { \
|
||||
psr_error->psr_result = -1; \
|
||||
psr_error->psr_errno = (e); \
|
||||
goto out; \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
len = readv(ctx->ps_root_fd, iov, __arraycount(iov));
|
||||
if (len == -1)
|
||||
PSR_ERROR(errno);
|
||||
else if ((size_t)len < sizeof(*psr_error))
|
||||
PSR_ERROR(EINVAL);
|
||||
exit_code = EXIT_SUCCESS;
|
||||
|
||||
out:
|
||||
eloop_exit(ctx->ps_eloop, exit_code);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_readerror(struct dhcpcd_ctx *ctx)
|
||||
ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
|
||||
{
|
||||
struct psr_ctx psr_ctx = { .psr_ctx = ctx };
|
||||
struct psr_ctx psr_ctx = {
|
||||
.psr_ctx = ctx,
|
||||
.psr_data = data, .psr_datalen = len,
|
||||
};
|
||||
|
||||
if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
|
||||
ps_root_readerrorcb, &psr_ctx) == -1)
|
||||
{
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
eloop_start(ctx->ps_eloop, &ctx->sigset);
|
||||
|
||||
|
@ -114,19 +130,85 @@ ps_root_readerror(struct dhcpcd_ctx *ctx)
|
|||
return psr_ctx.psr_error.psr_result;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
static void
|
||||
ps_root_mreaderrorcb(void *arg)
|
||||
{
|
||||
struct psr_ctx *psr_ctx = arg;
|
||||
struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
|
||||
struct psr_error *psr_error = &psr_ctx->psr_error;
|
||||
struct iovec iov[] = {
|
||||
{ .iov_base = psr_error, .iov_len = sizeof(*psr_error) },
|
||||
{ .iov_base = NULL, .iov_len = 0 },
|
||||
};
|
||||
ssize_t len;
|
||||
int exit_code = EXIT_FAILURE;
|
||||
|
||||
len = recv(ctx->ps_root_fd, psr_error, sizeof(*psr_error), MSG_PEEK);
|
||||
if (len == -1)
|
||||
PSR_ERROR(errno);
|
||||
else if ((size_t)len < sizeof(*psr_error))
|
||||
PSR_ERROR(EINVAL);
|
||||
|
||||
if (psr_error->psr_datalen != 0) {
|
||||
psr_ctx->psr_data = malloc(psr_error->psr_datalen);
|
||||
if (psr_ctx->psr_data == NULL)
|
||||
PSR_ERROR(errno);
|
||||
psr_ctx->psr_datalen = psr_error->psr_datalen;
|
||||
iov[1].iov_base = psr_ctx->psr_data;
|
||||
iov[1].iov_len = psr_ctx->psr_datalen;
|
||||
}
|
||||
|
||||
len = readv(ctx->ps_root_fd, iov, __arraycount(iov));
|
||||
if (len == -1)
|
||||
PSR_ERROR(errno);
|
||||
else if ((size_t)len != sizeof(*psr_error) + psr_ctx->psr_datalen)
|
||||
PSR_ERROR(EINVAL);
|
||||
exit_code = EXIT_SUCCESS;
|
||||
|
||||
out:
|
||||
eloop_exit(ctx->ps_eloop, exit_code);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_mreaderror(struct dhcpcd_ctx *ctx, void **data, size_t *len)
|
||||
{
|
||||
struct psr_ctx psr_ctx = {
|
||||
.psr_ctx = ctx,
|
||||
};
|
||||
|
||||
if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
|
||||
ps_root_mreaderrorcb, &psr_ctx) == -1)
|
||||
return -1;
|
||||
|
||||
eloop_start(ctx->ps_eloop, &ctx->sigset);
|
||||
|
||||
errno = psr_ctx.psr_error.psr_errno;
|
||||
*data = psr_ctx.psr_data;
|
||||
*len = psr_ctx.psr_datalen;
|
||||
return psr_ctx.psr_error.psr_result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result)
|
||||
ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result,
|
||||
void *data, size_t len)
|
||||
{
|
||||
struct psr_error psr = {
|
||||
.psr_result = result,
|
||||
.psr_errno = errno,
|
||||
.psr_datalen = len,
|
||||
};
|
||||
struct iovec iov[] = {
|
||||
{ .iov_base = &psr, .iov_len = sizeof(psr) },
|
||||
{ .iov_base = data, .iov_len = len },
|
||||
};
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("%s: result %zd errno %d", __func__, result, errno);
|
||||
#endif
|
||||
|
||||
return write(ctx->ps_root_fd, &psr, sizeof(psr));
|
||||
return writev(ctx->ps_root_fd, iov, __arraycount(iov));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
@ -134,6 +216,27 @@ ps_root_doioctl(unsigned long req, void *data, size_t len)
|
|||
{
|
||||
int s, err;
|
||||
|
||||
/* Only allow these ioctls */
|
||||
switch(req) {
|
||||
#ifdef SIOCAIFADDR
|
||||
case SIOCAIFADDR: /* FALLTHROUGH */
|
||||
case SIOCDIFADDR: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCSIFHWADDR
|
||||
case SIOCSIFHWADDR: /* FALLTHROUGH */
|
||||
#endif
|
||||
#ifdef SIOCGIFPRIORITY
|
||||
case SIOCGIFPRIORITY: /* FALLTHROUGH */
|
||||
#endif
|
||||
case SIOCSIFFLAGS: /* FALLTHROUGH */
|
||||
case SIOCGIFMTU: /* FALLTHROUGH */
|
||||
case SIOCSIFMTU:
|
||||
break;
|
||||
default:
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
#ifdef IOCTL_REQUEST_TYPE
|
||||
|
@ -157,34 +260,13 @@ static ssize_t
|
|||
ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
const char *envbuf = data;
|
||||
char * const argv[] = { UNCONST(data), NULL };
|
||||
char * const argv[] = { ctx->script, NULL };
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("%s: IN %zu", __func__, len);
|
||||
#endif
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Script is the first one, find the environment buffer. */
|
||||
while (*envbuf != '\0') {
|
||||
if (len == 0)
|
||||
return EINVAL;
|
||||
envbuf++;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
envbuf++;
|
||||
len--;
|
||||
}
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("%s: run script: %s", __func__, argv[0]);
|
||||
#endif
|
||||
|
||||
if (script_buftoenv(ctx, UNCONST(envbuf), len) == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -202,147 +284,174 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
|
|||
return status;
|
||||
}
|
||||
|
||||
#if defined(__linux__) && !defined(st_mtimespec)
|
||||
#define st_atimespec st_atim
|
||||
#define st_mtimespec st_mtim
|
||||
#endif
|
||||
ssize_t
|
||||
ps_root_docopychroot(struct dhcpcd_ctx *ctx, const char *file)
|
||||
static bool
|
||||
ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path)
|
||||
{
|
||||
|
||||
char path[PATH_MAX], buf[BUFSIZ], *slash;
|
||||
struct stat from_sb, to_sb;
|
||||
int from_fd, to_fd;
|
||||
ssize_t rcount, wcount, total;
|
||||
#if defined(BSD) || defined(__linux__)
|
||||
struct timespec ts[2];
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
#endif
|
||||
/* Avoid a previous directory attack to avoid /proc/../
|
||||
* dhcpcd should never use a path with double dots. */
|
||||
if (strstr(path, "..") != NULL)
|
||||
return false;
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s/%s",
|
||||
ctx->ps_user->pw_dir, file) == -1)
|
||||
return -1;
|
||||
if (stat(file, &from_sb) == -1)
|
||||
return -1;
|
||||
if (stat(path, &to_sb) == 0) {
|
||||
#if defined(BSD) || defined(__linux__)
|
||||
if (from_sb.st_mtimespec.tv_sec == to_sb.st_mtimespec.tv_sec &&
|
||||
from_sb.st_mtimespec.tv_nsec == to_sb.st_mtimespec.tv_nsec)
|
||||
return 0;
|
||||
#else
|
||||
if (from_sb.st_mtime == to_sb.st_mtime)
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
/* Ensure directory exists */
|
||||
slash = strrchr(path, '/');
|
||||
if (slash != NULL) {
|
||||
*slash = '\0';
|
||||
ps_mkdir(path);
|
||||
*slash = '/';
|
||||
}
|
||||
if (cmd == PS_READFILE) {
|
||||
if (strcmp(ctx->cffile, path) == 0)
|
||||
return true;
|
||||
}
|
||||
if (strncmp(DBDIR, path, strlen(DBDIR)) == 0)
|
||||
return true;
|
||||
if (strncmp(RUNDIR, path, strlen(RUNDIR)) == 0)
|
||||
return true;
|
||||
|
||||
if (unlink(path) == -1 && errno != ENOENT)
|
||||
return -1;
|
||||
if ((from_fd = open(file, O_RDONLY, 0)) == -1)
|
||||
return -1;
|
||||
if ((to_fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0555)) == -1)
|
||||
return -1;
|
||||
|
||||
total = 0;
|
||||
while ((rcount = read(from_fd, buf, sizeof(buf))) > 0) {
|
||||
wcount = write(to_fd, buf, (size_t)rcount);
|
||||
if (wcount != rcount) {
|
||||
total = -1;
|
||||
break;
|
||||
}
|
||||
total += wcount;
|
||||
}
|
||||
|
||||
#if defined(BSD) || defined(__linux__)
|
||||
ts[0] = from_sb.st_atimespec;
|
||||
ts[1] = from_sb.st_mtimespec;
|
||||
if (futimens(to_fd, ts) == -1)
|
||||
total = -1;
|
||||
#else
|
||||
tv[0].tv_sec = from_sb.st_atime;
|
||||
tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = from_sb.st_mtime;
|
||||
tv[1].tv_usec = 0;
|
||||
if (futimes(to_fd, tv) == -1)
|
||||
total = -1;
|
||||
#ifdef __linux__
|
||||
if (strncmp("/proc/net/", path, strlen("/proc/net/")) == 0 ||
|
||||
strncmp("/proc/sys/net/", path, strlen("/proc/sys/net/")) == 0 ||
|
||||
strncmp("/sys/class/net/", path, strlen("/sys/class/net/")) == 0)
|
||||
return true;
|
||||
#endif
|
||||
close(from_fd);
|
||||
close(to_fd);
|
||||
|
||||
return total;
|
||||
errno = EPERM;
|
||||
return false;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ps_root_dofileop(struct dhcpcd_ctx *ctx, void *data, size_t len, uint8_t op)
|
||||
ps_root_dowritefile(const struct dhcpcd_ctx *ctx,
|
||||
mode_t mode, void *data, size_t len)
|
||||
{
|
||||
char *path = data;
|
||||
size_t plen;
|
||||
char *file = data, *nc;
|
||||
|
||||
if (len < sizeof(plen)) {
|
||||
nc = memchr(file, '\0', len);
|
||||
if (nc == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&plen, path, sizeof(plen));
|
||||
path += sizeof(plen);
|
||||
if (sizeof(plen) + plen > len) {
|
||||
errno = EINVAL;
|
||||
if (!ps_root_validpath(ctx, PS_WRITEFILE, file))
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(op) {
|
||||
case PS_COPY:
|
||||
return ps_root_docopychroot(ctx, path);
|
||||
case PS_UNLINK:
|
||||
return (ssize_t)unlink(path);
|
||||
default:
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
nc++;
|
||||
return writefile(file, mode, nc, len - (size_t)(nc - file));
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
#define IFA_NADDRS 3
|
||||
static ssize_t
|
||||
ps_root_dogetifaddrs(void **rdata, size_t *rlen)
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
size_t len;
|
||||
uint8_t *buf, *sap;
|
||||
socklen_t salen;
|
||||
void *ifdata;
|
||||
|
||||
if (getifaddrs(&ifaddrs) == -1)
|
||||
return -1;
|
||||
if (ifaddrs == NULL) {
|
||||
*rdata = NULL;
|
||||
*rlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Work out the buffer length required.
|
||||
* Ensure everything is aligned correctly, which does
|
||||
* create a larger buffer than what is needed to send,
|
||||
* but makes creating the same structure in the client
|
||||
* much easier. */
|
||||
len = 0;
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
len += ALIGN(sizeof(*ifa));
|
||||
len += ALIGN(IFNAMSIZ);
|
||||
len += ALIGN(sizeof(salen) * IFA_NADDRS);
|
||||
if (ifa->ifa_addr != NULL)
|
||||
len += ALIGN(sa_len(ifa->ifa_addr));
|
||||
if (ifa->ifa_netmask != NULL)
|
||||
len += ALIGN(sa_len(ifa->ifa_netmask));
|
||||
if (ifa->ifa_broadaddr != NULL)
|
||||
len += ALIGN(sa_len(ifa->ifa_broadaddr));
|
||||
}
|
||||
|
||||
/* Use calloc to set everything to zero.
|
||||
* This satisfies memory sanitizers because don't write
|
||||
* where we don't need to. */
|
||||
buf = calloc(1, len);
|
||||
if (buf == NULL) {
|
||||
freeifaddrs(ifaddrs);
|
||||
return -1;
|
||||
}
|
||||
*rdata = buf;
|
||||
*rlen = len;
|
||||
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
/* Don't carry ifa_data. */
|
||||
ifdata = ifa->ifa_data;
|
||||
ifa->ifa_data = NULL;
|
||||
memcpy(buf, ifa, sizeof(*ifa));
|
||||
buf += ALIGN(sizeof(*ifa));
|
||||
ifa->ifa_data = ifdata;
|
||||
|
||||
strlcpy((char *)buf, ifa->ifa_name, IFNAMSIZ);
|
||||
buf += ALIGN(IFNAMSIZ);
|
||||
sap = buf;
|
||||
buf += ALIGN(sizeof(salen) * IFA_NADDRS);
|
||||
|
||||
#define COPYINSA(addr) \
|
||||
do { \
|
||||
salen = sa_len((addr)); \
|
||||
if (salen != 0) { \
|
||||
memcpy(sap, &salen, sizeof(salen)); \
|
||||
memcpy(buf, (addr), salen); \
|
||||
buf += ALIGN(salen); \
|
||||
} \
|
||||
sap += sizeof(salen); \
|
||||
} while (0 /*CONSTCOND */)
|
||||
|
||||
if (ifa->ifa_addr != NULL)
|
||||
COPYINSA(ifa->ifa_addr);
|
||||
if (ifa->ifa_netmask != NULL)
|
||||
COPYINSA(ifa->ifa_netmask);
|
||||
if (ifa->ifa_broadaddr != NULL)
|
||||
COPYINSA(ifa->ifa_broadaddr);
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddrs);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
uint8_t cmd;
|
||||
uint16_t cmd;
|
||||
struct ps_process *psp;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
void *data = iov->iov_base;
|
||||
size_t len = iov->iov_len;
|
||||
void *data = iov->iov_base, *rdata = NULL;
|
||||
size_t len = iov->iov_len, rlen = 0;
|
||||
uint8_t buf[PS_BUFLEN];
|
||||
time_t mtime;
|
||||
ssize_t err;
|
||||
bool free_rdata = false;
|
||||
|
||||
cmd = (uint8_t)(psm->ps_cmd & ~(PS_START | PS_STOP | PS_DELETE));
|
||||
cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
|
||||
psp = ps_findprocess(ctx, &psm->ps_id);
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
|
||||
#endif
|
||||
|
||||
if ((!(psm->ps_cmd & PS_START) || cmd == PS_BPF_ARP_ADDR) &&
|
||||
psp != NULL)
|
||||
{
|
||||
if (psp != NULL) {
|
||||
if (psm->ps_cmd & PS_STOP) {
|
||||
int ret = ps_dostop(ctx, &psp->psp_pid, &psp->psp_fd);
|
||||
|
||||
ps_freeprocess(psp);
|
||||
return ret;
|
||||
}
|
||||
return ps_sendpsmmsg(ctx, psp->psp_fd, psm, msg);
|
||||
} else if (!(psm->ps_cmd & PS_START))
|
||||
return ps_sendpsmmsg(ctx, psp->psp_fd, psm, msg);
|
||||
/* Process has already started .... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (psm->ps_cmd & (PS_STOP | PS_DELETE) && psp == NULL)
|
||||
if (psm->ps_cmd & PS_STOP && psp == NULL)
|
||||
return 0;
|
||||
|
||||
/* All these should just be PS_START */
|
||||
switch (cmd) {
|
||||
#ifdef INET
|
||||
#ifdef ARP
|
||||
|
@ -366,7 +475,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
|||
break;
|
||||
}
|
||||
|
||||
assert(msg->msg_iovlen == 1);
|
||||
assert(msg->msg_iovlen == 0 || msg->msg_iovlen == 1);
|
||||
|
||||
/* Reset errno */
|
||||
errno = 0;
|
||||
|
@ -374,20 +483,71 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
|||
switch (psm->ps_cmd) {
|
||||
case PS_IOCTL:
|
||||
err = ps_root_doioctl(psm->ps_flags, data, len);
|
||||
if (err != -1) {
|
||||
rdata = data;
|
||||
rlen = len;
|
||||
}
|
||||
break;
|
||||
case PS_SCRIPT:
|
||||
err = ps_root_run_script(ctx, data, len);
|
||||
break;
|
||||
case PS_COPY: /* FALLTHROUGH */
|
||||
case PS_UNLINK:
|
||||
err = ps_root_dofileop(ctx, data, len, psm->ps_cmd);
|
||||
if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
err = unlink(data);
|
||||
break;
|
||||
case PS_READFILE:
|
||||
if (!ps_root_validpath(ctx, psm->ps_cmd, data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
err = readfile(data, buf, sizeof(buf));
|
||||
if (err != -1) {
|
||||
rdata = buf;
|
||||
rlen = (size_t)err;
|
||||
}
|
||||
break;
|
||||
case PS_WRITEFILE:
|
||||
err = ps_root_dowritefile(ctx, (mode_t)psm->ps_flags,
|
||||
data, len);
|
||||
break;
|
||||
case PS_FILEMTIME:
|
||||
err = filemtime(data, &mtime);
|
||||
if (err != -1) {
|
||||
rdata = &mtime;
|
||||
rlen = sizeof(mtime);
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
case PS_GETIFADDRS:
|
||||
err = ps_root_dogetifaddrs(&rdata, &rlen);
|
||||
free_rdata = true;
|
||||
break;
|
||||
#endif
|
||||
#if defined(INET6) && (defined(__linux__) || defined(HAVE_PLEDGE))
|
||||
case PS_IP6FORWARDING:
|
||||
err = ip6_forwarding(data);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PLUGIN_DEV
|
||||
case PS_DEV_INITTED:
|
||||
err = dev_initialized(ctx, data);
|
||||
break;
|
||||
case PS_DEV_LISTENING:
|
||||
err = dev_listening(ctx);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
err = ps_root_os(psm, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
return ps_root_writeerror(ctx, err);
|
||||
err = ps_root_writeerror(ctx, err, rlen != 0 ? rdata : 0, rlen);
|
||||
if (free_rdata)
|
||||
free(rdata);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Receive from state engine, do an action. */
|
||||
|
@ -401,13 +561,72 @@ ps_root_recvmsg(void *arg)
|
|||
logerr(__func__);
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_DEV
|
||||
static int
|
||||
ps_root_handleinterface(void *arg, int action, const char *ifname)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
unsigned long flag;
|
||||
|
||||
if (action == 1)
|
||||
flag = PS_DEV_IFADDED;
|
||||
else if (action == -1)
|
||||
flag = PS_DEV_IFREMOVED;
|
||||
else if (action == 0)
|
||||
flag = PS_DEV_IFUPDATED;
|
||||
else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)ps_sendcmd(ctx, ctx->ps_data_fd, PS_DEV_IFCMD, flag,
|
||||
ifname, strlen(ifname) + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ps_root_startcb(void *arg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
|
||||
setproctitle("[privileged actioneer]");
|
||||
if (ctx->options & DHCPCD_MASTER)
|
||||
setproctitle("[privileged actioneer]");
|
||||
else
|
||||
setproctitle("[privileged actioneer] %s%s%s",
|
||||
ctx->ifv[0],
|
||||
ctx->options & DHCPCD_IPV4 ? " [ip4]" : "",
|
||||
ctx->options & DHCPCD_IPV6 ? " [ip6]" : "");
|
||||
ctx->ps_root_pid = getpid();
|
||||
ctx->options |= DHCPCD_PRIVSEPROOT;
|
||||
|
||||
/* Open network sockets for sending.
|
||||
* This is a small bit wasteful for non sandboxed OS's
|
||||
* but makes life very easy for unicasting DHCPv6 in non master
|
||||
* mode as we no longer care about address selection. */
|
||||
#ifdef INET
|
||||
ctx->udp_wfd = xsocket(PF_INET, SOCK_RAW | SOCK_CXNB, IPPROTO_UDP);
|
||||
if (ctx->udp_wfd == -1)
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
ctx->nd_fd = ipv6nd_open(false);
|
||||
if (ctx->nd_fd == -1)
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef DHCP6
|
||||
ctx->dhcp6_wfd = dhcp6_openraw();
|
||||
if (ctx->dhcp6_wfd == -1)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#ifdef PLUGIN_DEV
|
||||
/* Start any dev listening plugin which may want to
|
||||
* change the interface name provided by the kernel */
|
||||
if ((ctx->options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
|
||||
(DHCPCD_MASTER | DHCPCD_DEV))
|
||||
dev_start(ctx, ps_root_handleinterface);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -429,17 +648,58 @@ ps_root_signalcb(int sig, void *arg)
|
|||
eloop_exit(ctx->eloop, sig == SIGTERM ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int (*handle_interface)(void *, int, const char *);
|
||||
|
||||
#ifdef PLUGIN_DEV
|
||||
static ssize_t
|
||||
ps_root_devcb(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
int action;
|
||||
struct iovec *iov = msg->msg_iov;
|
||||
|
||||
if (msg->msg_iovlen != 1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(psm->ps_flags) {
|
||||
case PS_DEV_IFADDED:
|
||||
action = 1;
|
||||
break;
|
||||
case PS_DEV_IFREMOVED:
|
||||
action = -1;
|
||||
break;
|
||||
case PS_DEV_IFUPDATED:
|
||||
action = 0;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dhcpcd_handleinterface(ctx, action, iov->iov_base);
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = arg;
|
||||
ssize_t err;
|
||||
|
||||
#ifdef INET
|
||||
err = ps_bpf_dispatch(ctx, psm, msg);
|
||||
if (err == -1 && errno == ENOTSUP)
|
||||
switch(psm->ps_cmd) {
|
||||
#ifdef PLUGIN_DEV
|
||||
case PS_DEV_IFCMD:
|
||||
err = ps_root_devcb(ctx, psm, msg);
|
||||
break;
|
||||
#endif
|
||||
err = ps_inet_dispatch(ctx, psm, msg);
|
||||
default:
|
||||
#ifdef INET
|
||||
err = ps_bpf_dispatch(ctx, psm, msg);
|
||||
if (err == -1 && errno == ENOTSUP)
|
||||
#endif
|
||||
err = ps_inet_dispatch(ctx, psm, msg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -458,7 +718,6 @@ ps_root_start(struct dhcpcd_ctx *ctx)
|
|||
int fd[2];
|
||||
pid_t pid;
|
||||
|
||||
#define SOCK_CXNB SOCK_CLOEXEC | SOCK_NONBLOCK
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CXNB, 0, fd) == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -477,20 +736,16 @@ ps_root_start(struct dhcpcd_ctx *ctx)
|
|||
close(fd[1]);
|
||||
if (eloop_event_add(ctx->eloop, ctx->ps_data_fd,
|
||||
ps_root_dispatch, ctx) == -1)
|
||||
logerr(__func__);
|
||||
|
||||
if ((ctx->ps_eloop = eloop_new()) == NULL) {
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ctx->ps_eloop = eloop_new()) == NULL)
|
||||
return -1;
|
||||
|
||||
if (eloop_signal_set_cb(ctx->ps_eloop,
|
||||
dhcpcd_signals, dhcpcd_signals_len,
|
||||
ps_root_readerrorsig, ctx) == -1)
|
||||
{
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
@ -502,39 +757,12 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_script(const struct interface *ifp, const void *data, size_t len)
|
||||
ps_root_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
char buf[PS_BUFLEN], *p = buf;
|
||||
size_t blen = PS_BUFLEN, slen = strlen(ifp->options->script) + 1;
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("%s: sending script: %zu %s len %zu",
|
||||
__func__, slen, ifp->options->script, len);
|
||||
#endif
|
||||
|
||||
if (slen > blen) {
|
||||
errno = ENOBUFS;
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_SCRIPT, 0, data, len) == -1)
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, ifp->options->script, slen);
|
||||
p += slen;
|
||||
blen -= slen;
|
||||
|
||||
if (len > blen) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, data, len);
|
||||
|
||||
#ifdef PRIVSEP_DEBUG
|
||||
logdebugx("%s: sending script data: %zu", __func__, slen + len);
|
||||
#endif
|
||||
|
||||
if (ps_sendcmd(ifp->ctx, ifp->ctx->ps_root_fd, PS_SCRIPT, 0,
|
||||
buf, slen + len) == -1)
|
||||
return -1;
|
||||
|
||||
return ps_root_readerror(ifp->ctx);
|
||||
return ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
|
@ -551,41 +779,157 @@ ps_root_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data,
|
|||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IOCTL, req, data, len) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
return ps_root_readerror(ctx);
|
||||
return ps_root_readerror(ctx, data, len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ps_root_fileop(struct dhcpcd_ctx *ctx, const char *path, uint8_t op)
|
||||
ssize_t
|
||||
ps_root_unlink(struct dhcpcd_ctx *ctx, const char *file)
|
||||
{
|
||||
char buf[PATH_MAX], *p = buf;
|
||||
size_t plen = strlen(path) + 1;
|
||||
size_t len = sizeof(plen) + plen;
|
||||
|
||||
if (len > sizeof(buf)) {
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_UNLINK, 0,
|
||||
file, strlen(file) + 1) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_readfile(struct dhcpcd_ctx *ctx, const char *file,
|
||||
void *data, size_t len)
|
||||
{
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_READFILE, 0,
|
||||
file, strlen(file) + 1) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx, data, len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_writefile(struct dhcpcd_ctx *ctx, const char *file, mode_t mode,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
char buf[PS_BUFLEN];
|
||||
size_t flen;
|
||||
|
||||
flen = strlcpy(buf, file, sizeof(buf));
|
||||
flen += 1;
|
||||
if (flen > sizeof(buf) || flen + len > sizeof(buf)) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf + flen, data, len);
|
||||
|
||||
memcpy(p, &plen, sizeof(plen));
|
||||
p += sizeof(plen);
|
||||
memcpy(p, path, plen);
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, op, 0, buf, len) == -1)
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_WRITEFILE, mode,
|
||||
buf, flen + len) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ps_root_copychroot(struct dhcpcd_ctx *ctx, const char *path)
|
||||
{
|
||||
|
||||
return ps_root_fileop(ctx, path, PS_COPY);
|
||||
return ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ps_root_unlink(struct dhcpcd_ctx *ctx, const char *path)
|
||||
ps_root_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
|
||||
{
|
||||
|
||||
return ps_root_fileop(ctx, path, PS_UNLINK);
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_FILEMTIME, 0,
|
||||
file, strlen(file) + 1) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx, time, sizeof(*time));
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAPSICUM
|
||||
int
|
||||
ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
|
||||
{
|
||||
struct ifaddrs *ifa;
|
||||
void *buf = NULL;
|
||||
char *bp, *sap;
|
||||
socklen_t salen;
|
||||
size_t len;
|
||||
ssize_t err;
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd,
|
||||
PS_GETIFADDRS, 0, NULL, 0) == -1)
|
||||
return -1;
|
||||
err = ps_root_mreaderror(ctx, &buf, &len);
|
||||
|
||||
if (err == -1)
|
||||
return -1;
|
||||
|
||||
/* Should be impossible - lo0 will always exist. */
|
||||
if (len == 0) {
|
||||
*ifahead = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp = buf;
|
||||
*ifahead = (struct ifaddrs *)(void *)bp;
|
||||
for (ifa = *ifahead; len != 0; ifa = ifa->ifa_next) {
|
||||
if (len < ALIGN(sizeof(*ifa)) +
|
||||
ALIGN(IFNAMSIZ) + ALIGN(sizeof(salen) * IFA_NADDRS))
|
||||
goto err;
|
||||
bp += ALIGN(sizeof(*ifa));
|
||||
ifa->ifa_name = bp;
|
||||
bp += ALIGN(IFNAMSIZ);
|
||||
sap = bp;
|
||||
bp += ALIGN(sizeof(salen) * IFA_NADDRS);
|
||||
len -= ALIGN(sizeof(*ifa)) +
|
||||
ALIGN(IFNAMSIZ) + ALIGN(sizeof(salen) * IFA_NADDRS);
|
||||
|
||||
#define COPYOUTSA(addr) \
|
||||
do { \
|
||||
memcpy(&salen, sap, sizeof(salen)); \
|
||||
if (len < salen) \
|
||||
goto err; \
|
||||
if (salen != 0) { \
|
||||
(addr) = (struct sockaddr *)bp; \
|
||||
bp += ALIGN(salen); \
|
||||
len -= ALIGN(salen); \
|
||||
} \
|
||||
sap += sizeof(salen); \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
COPYOUTSA(ifa->ifa_addr);
|
||||
COPYOUTSA(ifa->ifa_netmask);
|
||||
COPYOUTSA(ifa->ifa_broadaddr);
|
||||
ifa->ifa_next = (struct ifaddrs *)(void *)bp;
|
||||
}
|
||||
ifa->ifa_next = NULL;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(buf);
|
||||
*ifahead = NULL;
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(HAVE_PLEDGE)
|
||||
ssize_t
|
||||
ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
|
||||
{
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IP6FORWARDING, 0,
|
||||
ifname, ifname != NULL ? strlen(ifname) + 1 : 0) == -1)
|
||||
return -1;
|
||||
return ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PLUGIN_DEV
|
||||
int
|
||||
ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
|
||||
{
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0,
|
||||
ifname, strlen(ifname) + 1)== -1)
|
||||
return -1;
|
||||
return (int)ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
|
||||
int
|
||||
ps_root_dev_listening(struct dhcpcd_ctx * ctx)
|
||||
{
|
||||
|
||||
if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_LISTENING, 0, NULL, 0)== -1)
|
||||
return -1;
|
||||
return (int)ps_root_readerror(ctx, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,21 +34,34 @@
|
|||
pid_t ps_root_start(struct dhcpcd_ctx *ctx);
|
||||
int ps_root_stop(struct dhcpcd_ctx *ctx);
|
||||
|
||||
ssize_t ps_root_readerror(struct dhcpcd_ctx *);
|
||||
ssize_t ps_root_docopychroot(struct dhcpcd_ctx *, const char *);
|
||||
ssize_t ps_root_copychroot(struct dhcpcd_ctx *, const char *);
|
||||
ssize_t ps_root_readerror(struct dhcpcd_ctx *, void *, size_t);
|
||||
ssize_t ps_root_mreaderror(struct dhcpcd_ctx *, void **, size_t *);
|
||||
ssize_t ps_root_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
|
||||
ssize_t ps_root_ip6forwarding(struct dhcpcd_ctx *, const char *);
|
||||
ssize_t ps_root_unlink(struct dhcpcd_ctx *, const char *);
|
||||
ssize_t ps_root_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
|
||||
ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
|
||||
ssize_t ps_root_writefile(struct dhcpcd_ctx *, const char *, mode_t,
|
||||
const void *, size_t);
|
||||
ssize_t ps_root_script(struct dhcpcd_ctx *, const void *, size_t);
|
||||
int ps_root_getifaddrs(struct dhcpcd_ctx *, struct ifaddrs **);
|
||||
|
||||
ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *);
|
||||
#if defined(BSD) || defined(__sun)
|
||||
ssize_t ps_root_route(struct dhcpcd_ctx *, void *, size_t);
|
||||
ssize_t ps_root_ioctllink(struct dhcpcd_ctx *, unsigned long, void *, size_t);
|
||||
ssize_t ps_root_ioctl6(struct dhcpcd_ctx *, unsigned long, void *, size_t);
|
||||
ssize_t ps_root_indirectioctl(struct dhcpcd_ctx *, unsigned long, const char *,
|
||||
void *, size_t);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *);
|
||||
ssize_t ps_root_writepathuint(struct dhcpcd_ctx *, const char *, unsigned int);
|
||||
#endif
|
||||
ssize_t ps_root_script(const struct interface *, const void *, size_t);
|
||||
|
||||
#ifdef PLUGIN_DEV
|
||||
int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *);
|
||||
int ps_root_dev_listening(struct dhcpcd_ctx *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,30 +34,42 @@
|
|||
/* Start flags */
|
||||
#define PSF_DROPPRIVS 0x01
|
||||
|
||||
/* Commands */
|
||||
#define PS_BOOTP 0x01
|
||||
#define PS_ND 0x02
|
||||
#define PS_DHCP6 0x03
|
||||
#define PS_BPF_BOOTP 0x04
|
||||
#define PS_BPF_ARP 0x05
|
||||
#define PS_BPF_ARP_ADDR 0x06
|
||||
/* Protocols */
|
||||
#define PS_BOOTP 0x0001
|
||||
#define PS_ND 0x0002
|
||||
#define PS_DHCP6 0x0003
|
||||
#define PS_BPF_BOOTP 0x0004
|
||||
#define PS_BPF_ARP 0x0005
|
||||
|
||||
#define PS_IOCTL 0x10
|
||||
#define PS_ROUTE 0x11 /* Also used for NETLINK */
|
||||
#define PS_SCRIPT 0x12
|
||||
#define PS_UNLINK 0x13
|
||||
#define PS_COPY 0x14
|
||||
/* Generic commands */
|
||||
#define PS_IOCTL 0x0010
|
||||
#define PS_ROUTE 0x0011 /* Also used for NETLINK */
|
||||
#define PS_SCRIPT 0x0012
|
||||
#define PS_UNLINK 0x0013
|
||||
#define PS_READFILE 0x0014
|
||||
#define PS_WRITEFILE 0x0015
|
||||
#define PS_FILEMTIME 0x0016
|
||||
|
||||
/* BSD Commands */
|
||||
#define PS_IOCTLLINK 0x15
|
||||
#define PS_IOCTL6 0x16
|
||||
#define PS_IOCTLLINK 0x0101
|
||||
#define PS_IOCTL6 0x0102
|
||||
#define PS_IOCTLINDIRECT 0x0103
|
||||
#define PS_IP6FORWARDING 0x0104
|
||||
#define PS_GETIFADDRS 0x0105
|
||||
|
||||
/* Linux commands */
|
||||
#define PS_WRITEPATHUINT 0x17
|
||||
/* Dev Commands */
|
||||
#define PS_DEV_LISTENING 0x0201
|
||||
#define PS_DEV_INITTED 0x0202
|
||||
#define PS_DEV_IFCMD 0x0203
|
||||
|
||||
#define PS_DELETE 0x20
|
||||
#define PS_START 0x40
|
||||
#define PS_STOP 0x80
|
||||
/* Dev Interface Commands (via flags) */
|
||||
#define PS_DEV_IFADDED 0x0001
|
||||
#define PS_DEV_IFREMOVED 0x0002
|
||||
#define PS_DEV_IFUPDATED 0x0003
|
||||
|
||||
/* Process commands */
|
||||
#define PS_START 0x4000
|
||||
#define PS_STOP 0x8000
|
||||
|
||||
/* Max INET message size + meta data for IPC */
|
||||
#define PS_BUFLEN ((64 * 1024) + \
|
||||
|
@ -92,13 +104,13 @@ struct ps_addr {
|
|||
struct ps_id {
|
||||
struct ps_addr psi_addr;
|
||||
unsigned int psi_ifindex;
|
||||
uint8_t psi_cmd;
|
||||
uint8_t psi_pad[3];
|
||||
uint16_t psi_cmd;
|
||||
uint8_t psi_pad[2];
|
||||
};
|
||||
|
||||
struct ps_msghdr {
|
||||
uint8_t ps_cmd;
|
||||
uint8_t ps_pad[sizeof(unsigned long) - 1];
|
||||
uint16_t ps_cmd;
|
||||
uint8_t ps_pad[sizeof(unsigned long) - sizeof(uint16_t)];
|
||||
unsigned long ps_flags;
|
||||
struct ps_id ps_id;
|
||||
socklen_t ps_namelen;
|
||||
|
@ -112,6 +124,7 @@ struct ps_msg {
|
|||
uint8_t psm_data[PS_BUFLEN];
|
||||
};
|
||||
|
||||
struct bpf;
|
||||
struct ps_process {
|
||||
TAILQ_ENTRY(ps_process) next;
|
||||
struct dhcpcd_ctx *psp_ctx;
|
||||
|
@ -125,8 +138,9 @@ struct ps_process {
|
|||
const char *psp_protostr;
|
||||
|
||||
#ifdef INET
|
||||
int (*psp_filter)(struct interface *, int);
|
||||
int (*psp_filter)(const struct bpf *, const struct in_addr *);
|
||||
struct interface psp_ifp; /* Move BPF gubbins elsewhere */
|
||||
struct bpf *psp_bpf;
|
||||
#endif
|
||||
};
|
||||
TAILQ_HEAD(ps_process_head, ps_process);
|
||||
|
@ -137,7 +151,6 @@ TAILQ_HEAD(ps_process_head, ps_process);
|
|||
#include "privsep-bpf.h"
|
||||
#endif
|
||||
|
||||
int ps_mkdir(char *);
|
||||
int ps_init(struct dhcpcd_ctx *);
|
||||
int ps_dropprivs(struct dhcpcd_ctx *);
|
||||
int ps_start(struct dhcpcd_ctx *);
|
||||
|
@ -148,11 +161,11 @@ ssize_t ps_sendpsmmsg(struct dhcpcd_ctx *, int,
|
|||
struct ps_msghdr *, const struct msghdr *);
|
||||
ssize_t ps_sendpsmdata(struct dhcpcd_ctx *, int,
|
||||
struct ps_msghdr *, const void *, size_t);
|
||||
ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint8_t, unsigned long,
|
||||
ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
|
||||
const struct msghdr *);
|
||||
ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint8_t, unsigned long,
|
||||
ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
|
||||
const void *data, size_t len);
|
||||
ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, uint8_t, int);
|
||||
ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, uint16_t, int);
|
||||
ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int,
|
||||
ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *), void *);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#ifdef AF_LINK
|
||||
#include <net/if_dl.h>
|
||||
#elif AF_PACKET
|
||||
#elif defined(AF_PACKET)
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
|
||||
|
@ -288,7 +288,7 @@ sa_toprefix(const struct sockaddr *sa)
|
|||
#ifndef NDEBUG
|
||||
/* Ensure the calculation is correct */
|
||||
if (!sa_inprefix) {
|
||||
union sa_ss ss = { .sa.sa_family = sa->sa_family };
|
||||
union sa_ss ss = { .sa = { .sa_family = sa->sa_family } };
|
||||
|
||||
sa_inprefix = true;
|
||||
sa_fromprefix(&ss.sa, prefix);
|
||||
|
@ -385,7 +385,7 @@ sa_addrtop(const struct sockaddr *sa, char *buf, socklen_t len)
|
|||
}
|
||||
return hwaddr_ntoa(CLLADDR(sdl), sdl->sdl_alen, buf, len);
|
||||
}
|
||||
#elif AF_PACKET
|
||||
#elif defined(AF_PACKET)
|
||||
if (sa->sa_family == AF_PACKET) {
|
||||
const struct sockaddr_ll *sll;
|
||||
|
||||
|
|
|
@ -37,5 +37,4 @@ char ** script_buftoenv(struct dhcpcd_ctx *, char *, size_t);
|
|||
pid_t script_exec(char *const *, char *const *);
|
||||
int send_interface(struct fd_list *, const struct interface *, int);
|
||||
int script_runreason(const struct interface *, const char *);
|
||||
int script_runchroot(struct dhcpcd_ctx *, char *);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue