Sync
This commit is contained in:
parent
9a245d3e64
commit
4982964f6e
|
@ -42,7 +42,7 @@ build_resolv_conf()
|
|||
# Build the nameserver list
|
||||
srvs=$(cd "$resolv_conf_dir"; \
|
||||
key_get_value "nameserver " ${interfaces})
|
||||
for x in $(uniqify ${srvs}); do
|
||||
for x in $(uniqify $srvs); do
|
||||
servers="${servers}nameserver $x$NL"
|
||||
done
|
||||
fi
|
||||
|
@ -152,6 +152,7 @@ add_resolv_conf()
|
|||
fi
|
||||
fi
|
||||
if [ -n "$new_domain_search" ]; then
|
||||
new_domain_search=$(uniqify $new_domain_search)
|
||||
if valid_domainname_list $new_domain_search; then
|
||||
conf="${conf}search $new_domain_search$NL"
|
||||
elif ! $warn; then
|
||||
|
@ -159,6 +160,7 @@ add_resolv_conf()
|
|||
"$new_domain_search"
|
||||
fi
|
||||
fi
|
||||
new_domain_name_servers=$(uniqify $new_domain_name_servers)
|
||||
for x in ${new_domain_name_servers}; do
|
||||
conf="${conf}nameserver $x$NL"
|
||||
done
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
# Set the hostname from DHCP data if required
|
||||
|
||||
# A hostname can either be a short hostname or a FQDN.
|
||||
# hostname_fqdn=true
|
||||
# hostname_fqdn=false
|
||||
# hostname_fqdn=server
|
||||
|
||||
# A value of server means just what the server says, don't manipulate it.
|
||||
# This could lead to an inconsistent hostname on a DHCPv4 and DHCPv6 network
|
||||
# where the DHCPv4 hostname is short and the DHCPv6 has an FQDN.
|
||||
# DHCPv6 has no hostname option.
|
||||
# RFC4702 section 3.1 says FQDN should be prefered over hostname.
|
||||
#
|
||||
# As such, the default is hostname_fqdn=true so that a consistent hostname
|
||||
# is always assigned.
|
||||
: ${hostname_fqdn:=true}
|
||||
|
||||
# If we used to set the hostname, but relinquish control of it, we should
|
||||
# reset to the default value.
|
||||
: ${hostname_default=localhost}
|
||||
|
||||
# Some systems don't have hostname(1)
|
||||
_hostname()
|
||||
{
|
||||
if [ -z "${1+x}" ]; then
|
||||
if type hostname >/dev/null 2>&1; then
|
||||
hostname
|
||||
elif [ -r /proc/sys/kernel/hostname ]; then
|
||||
read name </proc/sys/kernel/hostname && echo "$name"
|
||||
elif sysctl kern.hostname >/dev/null 2>&1; then
|
||||
sysctl -n kern.hostname
|
||||
elif sysctl kernel.hostname >/dev/null 2>&1; then
|
||||
sysctl -n kernel.hostname
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Always prefer hostname(1) if we have it
|
||||
if type hostname >/dev/null 2>&1; then
|
||||
hostname "$1"
|
||||
elif [ -w /proc/sys/kernel/hostname ]; then
|
||||
echo "$1" >/proc/sys/kernel/hostname
|
||||
elif sysctl kern.hostname >/dev/null 2>&1; then
|
||||
sysctl -w "kern.hostname=$1"
|
||||
elif sysctl kernel.hostname >/dev/null 2>&1; then
|
||||
sysctl -w "kernel.hostname=$1"
|
||||
else
|
||||
# We know this will fail, but it will now fail
|
||||
# with an error to stdout
|
||||
hostname "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
set_hostname_vars()
|
||||
{
|
||||
hfqdn=false
|
||||
hshort=false
|
||||
case "$hostname_fqdn" in
|
||||
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) hfqdn=true;;
|
||||
""|[Ss][Ee][Rr][Vv][Ee][Rr]) ;;
|
||||
*) hshort=true;;
|
||||
esac
|
||||
}
|
||||
|
||||
need_hostname()
|
||||
{
|
||||
# Always load the hostname variable for future use
|
||||
hostname="$(_hostname)"
|
||||
case "$hostname" in
|
||||
""|"(none)"|localhost|localhost.localdomain|"$hostname_default")
|
||||
return 0;;
|
||||
esac
|
||||
|
||||
case "$force_hostname" in
|
||||
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) return 0;;
|
||||
esac
|
||||
|
||||
set_hostname_vars
|
||||
|
||||
if [ -n "$old_fqdn" ]; then
|
||||
if ${hfqdn} || ! ${hshort}; then
|
||||
[ "$hostname" = "$old_fqdn" ]
|
||||
else
|
||||
[ "$hostname" = "${old_fqdn%%.*}" ]
|
||||
fi
|
||||
elif [ -n "$old_host_name" ]; then
|
||||
if ${hfqdn}; then
|
||||
if [ -n "$old_domain_name" ] &&
|
||||
[ "$old_host_name" = "${old_host_name#*.}" ]
|
||||
then
|
||||
[ "$hostname" = \
|
||||
"$old_host_name.$old_domain_name" ]
|
||||
else
|
||||
[ "$hostname" = "$old_host_name" ]
|
||||
fi
|
||||
elif ${hshort}; then
|
||||
[ "$hostname" = "${old_host_name%%.*}" ]
|
||||
else
|
||||
[ "$hostname" = "$old_host_name" ]
|
||||
fi
|
||||
else
|
||||
# No old hostname
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
try_hostname()
|
||||
{
|
||||
[ "$hostname" = "$1" ] && return 0
|
||||
if valid_domainname "$1"; then
|
||||
syslog info "Setting hostname: $1"
|
||||
_hostname "$1"
|
||||
else
|
||||
syslog err "Invalid hostname: $1"
|
||||
fi
|
||||
}
|
||||
|
||||
set_hostname()
|
||||
{
|
||||
need_hostname || return
|
||||
|
||||
set_hostname_vars
|
||||
|
||||
if [ -n "$new_fqdn" ]; then
|
||||
if ${hfqdn} || ! ${hshort}; then
|
||||
try_hostname "$new_fqdn"
|
||||
else
|
||||
try_hostname "${new_fqdn%%.*}"
|
||||
fi
|
||||
elif [ -n "$new_host_name" ]; then
|
||||
if ${hfqdn}; then
|
||||
if [ -n "$new_domain_name" ] &&
|
||||
[ "$new_host_name" = "${new_host_name#*.}" ]
|
||||
then
|
||||
try_hostname "$new_host_name.$new_domain_name"
|
||||
else
|
||||
try_hostname "$new_host_name"
|
||||
fi
|
||||
elif ${hshort}; then
|
||||
try_hostname "${new_host_name%%.*}"
|
||||
else
|
||||
try_hostname "$new_host_name"
|
||||
fi
|
||||
elif [ -n "${hostname_default+x}" ]; then
|
||||
try_hostname "$hostname_default"
|
||||
fi
|
||||
}
|
||||
|
||||
# For ease of use, map DHCP6 names onto our DHCP4 names
|
||||
case "$reason" in
|
||||
BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
|
||||
new_fqdn="$new_dhcp6_fqdn"
|
||||
old_fqdn="$old_dhcp6_fqdn"
|
||||
;;
|
||||
esac
|
||||
|
||||
if $if_up; then
|
||||
set_hostname
|
||||
fi
|
|
@ -41,7 +41,7 @@ if [ -z "$ntp_service" ]; then
|
|||
esac
|
||||
fi
|
||||
|
||||
# Debian has a seperate file for DHCP config to avoid stamping on
|
||||
# Debian has a separate file for DHCP config to avoid stamping on
|
||||
# the master.
|
||||
if [ "$ntp_service" = ntpd ] && type invoke-rc.d >/dev/null 2>&1; then
|
||||
[ -e /var/lib/ntp ] || mkdir /var/lib/ntp
|
||||
|
|
|
@ -8,7 +8,7 @@ signature_base="# Generated by dhcpcd"
|
|||
signature="$signature_base $from $ifname"
|
||||
signature_base_end="# End of dhcpcd"
|
||||
signature_end="$signature_base_end $from $ifname"
|
||||
state_dir=@RUNDIR@/dhcpcd
|
||||
state_dir=@RUNDIR@/hook-state
|
||||
_detected_init=false
|
||||
|
||||
: ${if_up:=false}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd: BPF arp and bootp filtering
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -93,6 +93,38 @@ bpf_frame_header_len(const struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
void *
|
||||
bpf_frame_header_src(const struct interface *ifp, void *fh, size_t *len)
|
||||
{
|
||||
uint8_t *f = fh;
|
||||
|
||||
switch (ifp->family) {
|
||||
case ARPHRD_ETHER:
|
||||
*len = sizeof(((struct ether_header *)0)->ether_shost);
|
||||
return f + offsetof(struct ether_header, ether_shost);
|
||||
default:
|
||||
*len = 0;
|
||||
errno = ENOTSUP;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
bpf_frame_header_dst(const struct interface *ifp, void *fh, size_t *len)
|
||||
{
|
||||
uint8_t *f = fh;
|
||||
|
||||
switch (ifp->family) {
|
||||
case ARPHRD_ETHER:
|
||||
*len = sizeof(((struct ether_header *)0)->ether_dhost);
|
||||
return f + offsetof(struct ether_header, ether_dhost);
|
||||
default:
|
||||
*len = 0;
|
||||
errno = ENOTSUP;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t etherbcastaddr[] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
|
@ -215,7 +247,6 @@ ssize_t
|
|||
bpf_read(struct interface *ifp, int fd, void *data, size_t len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
|
||||
ssize_t bytes;
|
||||
struct ipv4_state *state = IPV4_STATE(ifp);
|
||||
|
||||
|
@ -250,10 +281,10 @@ bpf_read(struct interface *ifp, int fd, void *data, size_t len,
|
|||
*flags |= BPF_BCAST;
|
||||
else
|
||||
*flags &= ~BPF_BCAST;
|
||||
payload += fl;
|
||||
bytes = (ssize_t)packet.bh_caplen - fl;
|
||||
if ((size_t)bytes > len)
|
||||
if (packet.bh_caplen > len)
|
||||
bytes = (ssize_t)len;
|
||||
else
|
||||
bytes = (ssize_t)packet.bh_caplen;
|
||||
memcpy(data, payload, (size_t)bytes);
|
||||
next:
|
||||
state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
|
||||
|
@ -464,6 +495,8 @@ bpf_arp(struct interface *ifp, int fd)
|
|||
struct bpf_insn *bp;
|
||||
struct iarp_state *state;
|
||||
uint16_t arp_len;
|
||||
struct arp_state *astate;
|
||||
size_t naddrs;
|
||||
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
@ -490,58 +523,60 @@ bpf_arp(struct interface *ifp, int fd)
|
|||
false, ifp->hwaddr, ifp->hwlen);
|
||||
|
||||
state = ARP_STATE(ifp);
|
||||
if (TAILQ_FIRST(&state->arp_states)) {
|
||||
struct arp_state *astate;
|
||||
size_t naddrs;
|
||||
/* privsep may not have an initial state yet. */
|
||||
if (state == NULL || TAILQ_FIRST(&state->arp_states) == NULL)
|
||||
goto noaddrs;
|
||||
|
||||
/* Match sender protocol address */
|
||||
BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
|
||||
sizeof(struct arphdr) + ifp->hwlen);
|
||||
bp++;
|
||||
naddrs = 0;
|
||||
TAILQ_FOREACH(astate, &state->arp_states, next) {
|
||||
if (++naddrs > ARP_ADDRS_MAX) {
|
||||
errno = ENOBUFS;
|
||||
logerr(__func__);
|
||||
break;
|
||||
}
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
|
||||
htonl(astate->addr.s_addr), 0, 1);
|
||||
bp++;
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
|
||||
bp++;
|
||||
/* Match sender protocol address */
|
||||
BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
|
||||
sizeof(struct arphdr) + ifp->hwlen);
|
||||
bp++;
|
||||
naddrs = 0;
|
||||
TAILQ_FOREACH(astate, &state->arp_states, next) {
|
||||
if (IN_IS_ADDR_UNSPECIFIED(&astate->addr))
|
||||
continue;
|
||||
if (++naddrs > ARP_ADDRS_MAX) {
|
||||
errno = ENOBUFS;
|
||||
logerr(__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't match sender, then we're only interested in
|
||||
* ARP probes to us, so check the null host sender. */
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K, INADDR_ANY, 1, 0);
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
|
||||
htonl(astate->addr.s_addr), 0, 1);
|
||||
bp++;
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
|
||||
bp++;
|
||||
|
||||
/* Match target protocol address */
|
||||
BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
|
||||
(sizeof(struct arphdr)
|
||||
+ (size_t)(ifp->hwlen * 2) + sizeof(in_addr_t)));
|
||||
bp++;
|
||||
naddrs = 0;
|
||||
TAILQ_FOREACH(astate, &state->arp_states, next) {
|
||||
if (++naddrs > ARP_ADDRS_MAX) {
|
||||
/* Already logged error above. */
|
||||
break;
|
||||
}
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
|
||||
htonl(astate->addr.s_addr), 0, 1);
|
||||
bp++;
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
|
||||
bp++;
|
||||
}
|
||||
|
||||
/* Return nothing, no protocol address match. */
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
|
||||
bp++;
|
||||
}
|
||||
|
||||
/* If we didn't match sender, then we're only interested in
|
||||
* ARP probes to us, so check the null host sender. */
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K, INADDR_ANY, 1, 0);
|
||||
bp++;
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
|
||||
bp++;
|
||||
|
||||
/* Match target protocol address */
|
||||
BPF_SET_STMT(bp, BPF_LD + BPF_W + BPF_IND,
|
||||
(sizeof(struct arphdr)
|
||||
+ (size_t)(ifp->hwlen * 2) + sizeof(in_addr_t)));
|
||||
bp++;
|
||||
naddrs = 0;
|
||||
TAILQ_FOREACH(astate, &state->arp_states, next) {
|
||||
if (++naddrs > ARP_ADDRS_MAX) {
|
||||
/* Already logged error above. */
|
||||
break;
|
||||
}
|
||||
BPF_SET_JUMP(bp, BPF_JMP + BPF_JEQ + BPF_K,
|
||||
htonl(astate->addr.s_addr), 0, 1);
|
||||
bp++;
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, arp_len);
|
||||
bp++;
|
||||
}
|
||||
|
||||
noaddrs:
|
||||
/* Return nothing, no protocol address match. */
|
||||
BPF_SET_STMT(bp, BPF_RET + BPF_K, 0);
|
||||
bp++;
|
||||
|
||||
return bpf_attach(fd, bpf, (unsigned int)(bp - bpf));
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2006-2019 Roy Marples
|
||||
.\" Copyright (c) 2006-2020 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
|
@ -24,7 +24,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd October 9, 2019
|
||||
.Dd March 27, 2020
|
||||
.Dt DHCPCD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -357,8 +357,9 @@ Some badly configured DHCP servers reject unknown vendorclassids.
|
|||
To work around it, try and impersonate Windows by using the MSFT vendorclassid.
|
||||
.It Fl j , Fl Fl logfile Ar logfile
|
||||
Writes to the specified
|
||||
.Ar logfile
|
||||
rather than
|
||||
.Ar logfile .
|
||||
.Nm
|
||||
still writes to
|
||||
.Xr syslog 3 .
|
||||
The
|
||||
.Ar logfile
|
||||
|
@ -683,10 +684,9 @@ To test INFORM the interface needs to be configured with the desired address
|
|||
before starting
|
||||
.Nm .
|
||||
.It Fl U , Fl Fl dumplease Ar interface
|
||||
Dumps the last lease for the
|
||||
Dumps the current lease for the
|
||||
.Ar interface
|
||||
to stdout.
|
||||
If omitted, standard input is used to read a DHCP wire formatted message.
|
||||
Use the
|
||||
.Fl 4
|
||||
or
|
||||
|
@ -804,20 +804,20 @@ lease and use the file's mtime as when it was issued.
|
|||
Stores the monotonic counter used in the
|
||||
.Ar replay
|
||||
field in Authentication Options.
|
||||
.It Pa @RUNDIR@/dhcpcd.pid
|
||||
.It Pa @RUNDIR@/pid
|
||||
Stores the PID of
|
||||
.Nm
|
||||
running on all interfaces.
|
||||
.It Pa @RUNDIR@/dhcpcd\- Ns Ar interface Ns .pid
|
||||
.It Pa @RUNDIR@/ Ns Ar interface Ns .pid
|
||||
Stores the PID of
|
||||
.Nm
|
||||
running on the
|
||||
.Ar interface .
|
||||
.It Pa @RUNDIR@/dhcpcd.sock
|
||||
.It Pa @RUNDIR@/sock
|
||||
Control socket to the master daemon.
|
||||
.It Pa @RUNDIR@/dhcpcd.unpriv.sock
|
||||
.It Pa @RUNDIR@/unpriv.sock
|
||||
Unprivileged socket to the master daemon, only allows state retrieval.
|
||||
.It Pa @RUNDIR@/dhcpcd\- Ns Ar interface Ns .sock
|
||||
.It Pa @RUNDIR@/ Ns Ar interface Ns .sock
|
||||
Control socket to per interface daemon.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
|
@ -833,9 +833,17 @@ RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
|
|||
RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
|
||||
RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,
|
||||
RFC\ 4941, RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6355,
|
||||
RFC\ 6603, RFC\ 6704, RFC\ 7217, RFC\ 7550.
|
||||
RFC\ 6603, RFC\ 6704, RFC\ 7217, RFC\ 7550, RFC\ 7844.
|
||||
.Sh AUTHORS
|
||||
.An Roy Marples Aq Mt roy@marples.name
|
||||
.Sh BUGS
|
||||
If
|
||||
.Nm
|
||||
is running in a
|
||||
.Xr chroot 2
|
||||
then re-opening the
|
||||
.Fl Fl logfile
|
||||
from SIGUSR2 may not work.
|
||||
.Pp
|
||||
Please report them to
|
||||
.Lk http://roy.marples.name/projects/dhcpcd
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* BSD interface driver for dhcpcd
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -58,8 +58,6 @@
|
|||
#endif
|
||||
#ifdef __DragonFly__
|
||||
# include <netproto/802_11/ieee80211_ioctl.h>
|
||||
#elif __APPLE__
|
||||
/* FIXME: Add apple includes so we can work out SSID */
|
||||
#else
|
||||
# include <net80211/ieee80211.h>
|
||||
# include <net80211/ieee80211_ioctl.h>
|
||||
|
@ -92,6 +90,7 @@
|
|||
#include "ipv6.h"
|
||||
#include "ipv6nd.h"
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
#include "route.h"
|
||||
#include "sa.h"
|
||||
|
||||
|
@ -106,6 +105,7 @@ static const char * const ifnames_ignore[] = {
|
|||
"bridge",
|
||||
"fwe", /* Firewire */
|
||||
"tap",
|
||||
"xvif", /* XEN DOM0 -> guest interface */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -214,6 +214,69 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
|
|||
priv = (struct priv *)ctx->priv;
|
||||
if (priv->pf_inet6_fd != -1)
|
||||
close(priv->pf_inet6_fd);
|
||||
free(priv);
|
||||
ctx->priv = NULL;
|
||||
}
|
||||
|
||||
#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */
|
||||
static int
|
||||
if_ioctllink(struct dhcpcd_ctx *ctx, unsigned long req, void *data, size_t len)
|
||||
{
|
||||
int s;
|
||||
int retval;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP)
|
||||
return (int)ps_root_ioctllink(ctx, req, data, len);
|
||||
#else
|
||||
UNUSED(ctx);
|
||||
#endif
|
||||
|
||||
s = socket(PF_LINK, SOCK_DGRAM, 0);
|
||||
if (s == -1)
|
||||
return -1;
|
||||
retval = ioctl(s, req, data, len);
|
||||
close(s);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
if_setmac(struct interface *ifp, void *mac, uint8_t maclen)
|
||||
{
|
||||
|
||||
if (ifp->hwlen != maclen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */
|
||||
struct if_laddrreq iflr = { .flags = IFLR_ACTIVE };
|
||||
struct sockaddr_dl *sdl = satosdl(&iflr.addr);
|
||||
int retval;
|
||||
|
||||
strlcpy(iflr.iflr_name, ifp->name, sizeof(iflr.iflr_name));
|
||||
sdl->sdl_family = AF_LINK;
|
||||
sdl->sdl_len = sizeof(*sdl);
|
||||
sdl->sdl_alen = maclen;
|
||||
memcpy(LLADDR(sdl), mac, maclen);
|
||||
retval = if_ioctllink(ifp->ctx, SIOCALIFADDR, &iflr, sizeof(iflr));
|
||||
|
||||
/* Try and remove the old address */
|
||||
memcpy(LLADDR(sdl), ifp->hwaddr, ifp->hwlen);
|
||||
if_ioctllink(ifp->ctx, SIOCDLIFADDR, &iflr, sizeof(iflr));
|
||||
|
||||
return retval;
|
||||
#else
|
||||
struct ifreq ifr = {
|
||||
.ifr_addr.sa_family = AF_LINK,
|
||||
.ifr_addr.sa_len = maclen,
|
||||
};
|
||||
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
memcpy(ifr.ifr_addr.sa_data, mac, maclen);
|
||||
return if_ioctl(ifp->ctx, SIOCSIFLLADDR, &ifr, sizeof(ifr));
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -692,11 +755,42 @@ if_route(unsigned char cmd, const struct rt *rt)
|
|||
#undef ADDSA
|
||||
|
||||
rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP) {
|
||||
if (ps_root_route(ctx, rtm, rtm->rtm_msglen) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (write(ctx->link_fd, rtm, rtm->rtm_msglen) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
if_realroute(const struct rt_msghdr *rtm)
|
||||
{
|
||||
|
||||
#ifdef RTF_CLONED
|
||||
if (rtm->rtm_flags & RTF_CLONED)
|
||||
return false;
|
||||
#endif
|
||||
#ifdef RTF_WASCLONED
|
||||
if (rtm->rtm_flags & RTF_WASCLONED)
|
||||
return false;
|
||||
#endif
|
||||
#ifdef RTF_LOCAL
|
||||
if (rtm->rtm_flags & RTF_LOCAL)
|
||||
return false;
|
||||
#endif
|
||||
#ifdef RTF_BROADCAST
|
||||
if (rtm->rtm_flags & RTF_BROADCAST)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
|
||||
{
|
||||
|
@ -710,30 +804,6 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#ifdef RTF_CLONED
|
||||
if (rtm->rtm_flags & RTF_CLONED) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef RTF_WASCLONED
|
||||
if (rtm->rtm_flags & RTF_WASCLONED) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef RTF_LOCAL
|
||||
if (rtm->rtm_flags & RTF_LOCAL) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef RTF_BROADCAST
|
||||
if (rtm->rtm_flags & RTF_BROADCAST) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
|
||||
rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
|
||||
|
@ -820,6 +890,8 @@ if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af)
|
|||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!if_realroute(rtm))
|
||||
continue;
|
||||
if (if_copyrt(ctx, &rt, rtm) != 0)
|
||||
continue;
|
||||
if ((rtn = rt_new(rt.rt_ifp)) == NULL) {
|
||||
|
@ -840,6 +912,7 @@ if_address(unsigned char cmd, const struct ipv4_addr *ia)
|
|||
{
|
||||
int r;
|
||||
struct in_aliasreq ifra;
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
|
||||
memset(&ifra, 0, sizeof(ifra));
|
||||
strlcpy(ifra.ifra_name, ia->iface->name, sizeof(ifra.ifra_name));
|
||||
|
@ -855,8 +928,8 @@ if_address(unsigned char cmd, const struct ipv4_addr *ia)
|
|||
ADDADDR(&ifra.ifra_broadaddr, &ia->brd);
|
||||
#undef ADDADDR
|
||||
|
||||
r = ioctl(ia->iface->ctx->pf_inet_fd,
|
||||
cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
|
||||
r = if_ioctl(ctx,
|
||||
cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra,sizeof(ifra));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -925,14 +998,26 @@ ifa_getscope(const struct sockaddr_in6 *sin)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
if_ioctl6(struct dhcpcd_ctx *ctx, unsigned long req, void *data, size_t len)
|
||||
{
|
||||
struct priv *priv;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP)
|
||||
return (int)ps_root_ioctl6(ctx, req, data, len);
|
||||
#endif
|
||||
|
||||
priv = ctx->priv;
|
||||
return ioctl(priv->pf_inet6_fd, req, data, len);
|
||||
}
|
||||
|
||||
int
|
||||
if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
||||
{
|
||||
struct in6_aliasreq ifa;
|
||||
struct in6_addr mask;
|
||||
struct priv *priv;
|
||||
|
||||
priv = (struct priv *)ia->iface->ctx->priv;
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
|
||||
memset(&ifa, 0, sizeof(ifa));
|
||||
strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name));
|
||||
|
@ -1004,7 +1089,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
if (cmd == RTM_NEWADDR && !(ia->flags & IPV6_AF_ADDED)) {
|
||||
ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
(void)ioctl(priv->pf_inet6_fd, SIOCAIFADDR_IN6, &ifa);
|
||||
(void)if_ioctl6(ctx, SIOCAIFADDR_IN6, &ifa, sizeof(ifa));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1025,8 +1110,9 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
|
||||
#endif
|
||||
|
||||
return ioctl(priv->pf_inet6_fd,
|
||||
cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
|
||||
return if_ioctl6(ctx,
|
||||
cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6,
|
||||
&ifa, sizeof(ifa));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1159,6 +1245,14 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
|
|||
if (rtm->rtm_errno != 0)
|
||||
return 0;
|
||||
|
||||
/* Ignore messages from ourself. */
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->ps_root_pid != 0) {
|
||||
if (rtm->rtm_pid == ctx->ps_root_pid)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (if_copyrt(ctx, &rt, rtm) == -1)
|
||||
return errno == ENOTSUP ? 0 : -1;
|
||||
|
||||
|
@ -1182,7 +1276,7 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (rtm->rtm_type != RTM_MISS)
|
||||
if (rtm->rtm_type != RTM_MISS && if_realroute(rtm))
|
||||
rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1199,6 +1293,28 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IFAM_PID
|
||||
/* Ignore address deletions from ourself.
|
||||
* We need to process address flag changes though. */
|
||||
if (ifam->ifam_type == RTM_DELADDR) {
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->ps_root_pid != 0) {
|
||||
if (ifam->ifam_pid == ctx->ps_root_pid)
|
||||
return 0;
|
||||
} else
|
||||
#endif
|
||||
/* address management is done via ioctl,
|
||||
* so SO_USELOOPBACK has no effect,
|
||||
* so we do need to check the pid. */
|
||||
if (ifam->ifam_pid == getpid())
|
||||
return 0;
|
||||
}
|
||||
pid = ifam->ifam_pid;
|
||||
#else
|
||||
pid = 0;
|
||||
#endif
|
||||
|
||||
if (~ifam->ifam_addrs & RTA_IFA)
|
||||
return 0;
|
||||
if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
|
||||
|
@ -1208,12 +1324,6 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_IFAM_PID
|
||||
pid = ifam->ifam_pid;
|
||||
#else
|
||||
pid = 0;
|
||||
#endif
|
||||
|
||||
switch (rti_info[RTAX_IFA]->sa_family) {
|
||||
case AF_LINK:
|
||||
{
|
||||
|
@ -1334,7 +1444,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
*/
|
||||
flags = if_addrflags6(ifp, &addr6, NULL);
|
||||
if (flags == -1) {
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
if (errno != ENXIO && errno != EADDRNOTAVAIL)
|
||||
logerr("%s: if_addrflags6", __func__);
|
||||
if (ifam->ifam_type != RTM_DELADDR)
|
||||
break;
|
||||
|
@ -1394,6 +1504,73 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
if_missfilter0(struct dhcpcd_ctx *ctx, struct interface *ifp,
|
||||
struct sockaddr *sa)
|
||||
{
|
||||
size_t salen = (size_t)RT_ROUNDUP(sa->sa_len);
|
||||
size_t newlen = ctx->rt_missfilterlen + salen;
|
||||
size_t diff = salen - (sa->sa_len);
|
||||
uint8_t *cp;
|
||||
|
||||
if (ctx->rt_missfiltersize < newlen) {
|
||||
void *n = realloc(ctx->rt_missfilter, newlen);
|
||||
if (n == NULL)
|
||||
return -1;
|
||||
ctx->rt_missfilter = n;
|
||||
ctx->rt_missfiltersize = newlen;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6)
|
||||
ifa_setscope(satosin6(sa), ifp->index);
|
||||
#endif
|
||||
|
||||
cp = ctx->rt_missfilter + ctx->rt_missfilterlen;
|
||||
memcpy(cp, sa, sa->sa_len);
|
||||
if (diff != 0)
|
||||
memset(cp + sa->sa_len, 0, diff);
|
||||
ctx->rt_missfilterlen += salen;
|
||||
|
||||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6)
|
||||
ifa_setscope(satosin6(sa), 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
if_missfilter(struct interface *ifp, struct sockaddr *sa)
|
||||
{
|
||||
|
||||
return if_missfilter0(ifp->ctx, ifp, sa);
|
||||
}
|
||||
|
||||
int
|
||||
if_missfilter_apply(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
#ifdef RO_MISSFILTER
|
||||
if (ctx->rt_missfilterlen == 0) {
|
||||
struct sockaddr sa = {
|
||||
.sa_family = AF_UNSPEC,
|
||||
.sa_len = sizeof(sa),
|
||||
};
|
||||
|
||||
if (if_missfilter0(ctx, NULL, &sa) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setsockopt(ctx->link_fd, PF_ROUTE, RO_MISSFILTER,
|
||||
ctx->rt_missfilter, (socklen_t)ctx->rt_missfilterlen);
|
||||
#else
|
||||
#warning kernel does not support RTM_MISS DST filtering
|
||||
UNUSED(ctx);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
__CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0);
|
||||
int
|
||||
if_handlelink(struct dhcpcd_ctx *ctx)
|
||||
|
@ -1475,19 +1652,20 @@ int
|
|||
if_applyra(const struct ra *rap)
|
||||
{
|
||||
#ifdef SIOCSIFINFO_IN6
|
||||
struct in6_ndireq ndi = { .ndi.chlim = 0 };
|
||||
struct priv *priv = rap->iface->ctx->priv;
|
||||
struct in6_ndireq nd = { .ndi.chlim = 0 };
|
||||
struct dhcpcd_ctx *ctx = rap->iface->ctx;
|
||||
struct priv *priv = ctx->priv;
|
||||
int error;
|
||||
|
||||
strlcpy(ndi.ifname, rap->iface->name, sizeof(ndi.ifname));
|
||||
if (ioctl(priv->pf_inet6_fd, SIOCGIFINFO_IN6, &ndi) == -1)
|
||||
strlcpy(nd.ifname, rap->iface->name, sizeof(nd.ifname));
|
||||
if (ioctl(priv->pf_inet6_fd, SIOCGIFINFO_IN6, &nd, sizeof(nd)) == -1)
|
||||
return -1;
|
||||
|
||||
ndi.ndi.linkmtu = rap->mtu;
|
||||
ndi.ndi.chlim = rap->hoplimit;
|
||||
ndi.ndi.retrans = rap->retrans;
|
||||
ndi.ndi.basereachable = rap->reachable;
|
||||
error = ioctl(priv->pf_inet6_fd, SIOCSIFINFO_IN6, &ndi);
|
||||
nd.ndi.linkmtu = rap->mtu;
|
||||
nd.ndi.chlim = rap->hoplimit;
|
||||
nd.ndi.retrans = rap->retrans;
|
||||
nd.ndi.basereachable = rap->reachable;
|
||||
error = if_ioctl6(ctx, SIOCSIFINFO_IN6, &nd, sizeof(nd));
|
||||
if (error == -1 && errno == EINVAL) {
|
||||
/*
|
||||
* Very likely that this is caused by a dodgy MTU
|
||||
|
@ -1496,8 +1674,8 @@ if_applyra(const struct ra *rap)
|
|||
* Doesn't really matter as we fix the MTU against the
|
||||
* routes we add as not all OS support SIOCSIFINFO_IN6.
|
||||
*/
|
||||
ndi.ndi.linkmtu = 0;
|
||||
error = ioctl(priv->pf_inet6_fd, SIOCSIFINFO_IN6, &ndi);
|
||||
nd.ndi.linkmtu = 0;
|
||||
error = if_ioctl6(ctx, SIOCSIFINFO_IN6, &nd, sizeof(nd));
|
||||
}
|
||||
return error;
|
||||
#else
|
||||
|
@ -1508,7 +1686,7 @@ if_applyra(const struct ra *rap)
|
|||
}
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
#ifndef IPV6CTL_TEMPVLTIME
|
||||
#if !defined(IPV6CTL_TEMPVLTIME) && !defined(__OpenBSD__)
|
||||
#define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0)
|
||||
#define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1)
|
||||
static int
|
||||
|
@ -1528,6 +1706,40 @@ inet6_sysctlbyname(const char *name, int val, int action)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
int
|
||||
ip6_use_tempaddr(const char *ifname)
|
||||
{
|
||||
int s, r;
|
||||
struct ifreq ifr;
|
||||
|
||||
s = socket(PF_INET6, SOCK_DGRAM, 0); /* XXX Not efficient */
|
||||
if (s == -1)
|
||||
return -1;
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
r = ioctl(s, SIOCGIFXFLAGS, &ifr);
|
||||
close(s);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
return ifr.ifr_flags & IFXF_INET6_NOPRIVACY ? 0 : 1;
|
||||
}
|
||||
|
||||
int
|
||||
ip6_temp_preferred_lifetime(__unused const char *ifname)
|
||||
{
|
||||
|
||||
return ND6_PRIV_PREFERRED_LIFETIME;
|
||||
}
|
||||
|
||||
int
|
||||
ip6_temp_valid_lifetime(__unused const char *ifname)
|
||||
{
|
||||
|
||||
return ND6_PRIV_VALID_LIFETIME;
|
||||
}
|
||||
|
||||
#else /* __OpenBSD__ */
|
||||
|
||||
int
|
||||
ip6_use_tempaddr(__unused const char *ifname)
|
||||
{
|
||||
|
@ -1566,6 +1778,7 @@ ip6_temp_valid_lifetime(__unused const char *ifname)
|
|||
#endif
|
||||
return val < 0 ? TEMP_VALID_LIFETIME : val;
|
||||
}
|
||||
#endif /* !__OpenBSD__ */
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -1583,25 +1796,26 @@ ip6_forwarding(__unused const char *ifname)
|
|||
|
||||
#ifdef SIOCIFAFATTACH
|
||||
static int
|
||||
af_attach(int s, const struct interface *ifp, int af)
|
||||
if_af_attach(const struct interface *ifp, int af)
|
||||
{
|
||||
struct if_afreq ifar;
|
||||
|
||||
strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name));
|
||||
ifar.ifar_af = af;
|
||||
return ioctl(s, SIOCIFAFATTACH, (void *)&ifar);
|
||||
return if_ioctl6(ifp->ctx, SIOCIFAFATTACH, &ifar, sizeof(ifar));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFXFLAGS
|
||||
static int
|
||||
set_ifxflags(int s, const struct interface *ifp)
|
||||
if_set_ifxflags(const struct interface *ifp)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int flags;
|
||||
struct priv *priv = ifp->ctx->priv;
|
||||
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1)
|
||||
if (ioctl(priv->pf_inet6_fd, SIOCGIFXFLAGS, &ifr) == -1)
|
||||
return -1;
|
||||
flags = ifr.ifr_flags;
|
||||
#ifdef IFXF_NOINET6
|
||||
|
@ -1628,7 +1842,7 @@ set_ifxflags(int s, const struct interface *ifp)
|
|||
if (ifr.ifr_flags == flags)
|
||||
return 0;
|
||||
ifr.ifr_flags = flags;
|
||||
return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr);
|
||||
return if_ioctl6(ifp->ctx, SIOCSIFXFLAGS, &ifr, sizeof(ifr));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1711,7 +1925,8 @@ if_setup_inet6(const struct interface *ifp)
|
|||
#ifdef ND6_NDI_FLAGS
|
||||
if (nd.ndi.flags != (uint32_t)flags) {
|
||||
nd.ndi.flags = (uint32_t)flags;
|
||||
if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1)
|
||||
if (if_ioctl6(ifp->ctx, SIOCSIFINFO_FLAGS,
|
||||
&nd, sizeof(nd)) == -1)
|
||||
logerr("%s: SIOCSIFINFO_FLAGS", ifp->name);
|
||||
}
|
||||
#endif
|
||||
|
@ -1720,12 +1935,12 @@ if_setup_inet6(const struct interface *ifp)
|
|||
* last action undertaken to ensure kernel RS and
|
||||
* LLADDR auto configuration are disabled where applicable. */
|
||||
#ifdef SIOCIFAFATTACH
|
||||
if (af_attach(s, ifp, AF_INET6) == -1)
|
||||
logerr("%s: af_attach", ifp->name);
|
||||
if (if_af_attach(ifp, AF_INET6) == -1)
|
||||
logerr("%s: if_af_attach", ifp->name);
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFXFLAGS
|
||||
if (set_ifxflags(s, ifp) == -1)
|
||||
if (if_set_ifxflags(ifp) == -1)
|
||||
logerr("%s: set_ifxflags", ifp->name);
|
||||
#endif
|
||||
|
||||
|
@ -1738,10 +1953,12 @@ if_setup_inet6(const struct interface *ifp)
|
|||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(s, SIOCSRTRFLUSH_IN6, &ifr) == -1 &&
|
||||
if (if_ioctl6(ifp->ctx, SIOCSRTRFLUSH_IN6,
|
||||
&ifr, sizeof(ifr)) == -1 &&
|
||||
errno != ENOTSUP)
|
||||
logwarn("SIOCSRTRFLUSH_IN6");
|
||||
if (ioctl(s, SIOCSPFXFLUSH_IN6, &ifr) == -1 &&
|
||||
if (if_ioctl6(ifp->ctx, SIOCSPFXFLUSH_IN6,
|
||||
&ifr, sizeof(ifr)) == -1 &&
|
||||
errno != ENOTSUP)
|
||||
logwarn("SIOCSPFXFLUSH_IN6");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -66,7 +66,7 @@
|
|||
#define O_NOIPV6RS O_BASE + 5
|
||||
#define O_IPV6RA_FORK O_BASE + 6
|
||||
#define O_LINK_RCVBUF O_BASE + 7
|
||||
// unused O_BASE + 8
|
||||
#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
|
||||
|
@ -106,6 +106,7 @@
|
|||
#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
|
||||
|
||||
const struct option cf_options[] = {
|
||||
{"background", no_argument, NULL, 'b'},
|
||||
|
@ -129,6 +130,9 @@ const struct option cf_options[] = {
|
|||
{"inform6", optional_argument, NULL, O_INFORM6},
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"userclass", required_argument, NULL, 'u'},
|
||||
#ifndef SMALL
|
||||
{"msuserclass", required_argument, NULL, O_MSUSERCLASS},
|
||||
#endif
|
||||
{"vendor", required_argument, NULL, 'v'},
|
||||
{"waitip", optional_argument, NULL, 'w'},
|
||||
{"exit", no_argument, NULL, 'x'},
|
||||
|
@ -161,6 +165,7 @@ const struct option cf_options[] = {
|
|||
{"oneshot", no_argument, NULL, '1'},
|
||||
{"ipv4only", no_argument, NULL, '4'},
|
||||
{"ipv6only", no_argument, NULL, '6'},
|
||||
{"anonymous", no_argument, NULL, O_ANONYMOUS},
|
||||
{"arping", required_argument, NULL, O_ARPING},
|
||||
{"destination", required_argument, NULL, O_DESTINATION},
|
||||
{"fallback", required_argument, NULL, O_FALLBACK},
|
||||
|
@ -286,6 +291,7 @@ add_environ(char ***array, const char *value, int uniq)
|
|||
#define PARSE_STRING_NULL 1
|
||||
#define PARSE_HWADDR 2
|
||||
#define parse_string(a, b, c) parse_str((a), (b), (c), PARSE_STRING)
|
||||
#define parse_nstring(a, b, c) parse_str((a), (b), (c), PARSE_STRING_NULL)
|
||||
#define parse_hwaddr(a, b, c) parse_str((a), (b), (c), PARSE_HWADDR)
|
||||
static ssize_t
|
||||
parse_str(char *sbuf, size_t slen, const char *str, int flags)
|
||||
|
@ -722,7 +728,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
ARG_REQUIRED;
|
||||
if (ifo->script != default_script)
|
||||
free(ifo->script);
|
||||
s = parse_str(NULL, 0, arg, PARSE_STRING_NULL);
|
||||
s = parse_nstring(NULL, 0, arg);
|
||||
if (s == 0) {
|
||||
ifo->script = NULL;
|
||||
break;
|
||||
|
@ -733,7 +739,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
s = parse_str(ifo->script, dl, arg, PARSE_STRING_NULL);
|
||||
s = parse_nstring(ifo->script, dl, arg);
|
||||
if (s == -1 ||
|
||||
ifo->script[0] == '\0' ||
|
||||
strcmp(ifo->script, "/dev/null") == 0)
|
||||
|
@ -754,7 +760,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
ifo->options |= DHCPCD_HOSTNAME;
|
||||
break;
|
||||
}
|
||||
s = parse_string(ifo->hostname, HOSTNAME_MAX_LEN, arg);
|
||||
s = parse_nstring(ifo->hostname, sizeof(ifo->hostname), arg);
|
||||
if (s == -1) {
|
||||
logerr("%s: hostname", __func__);
|
||||
return -1;
|
||||
|
@ -763,7 +769,6 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
logerrx("hostname cannot begin with .");
|
||||
return -1;
|
||||
}
|
||||
ifo->hostname[s] = '\0';
|
||||
if (ifo->hostname[0] == '\0')
|
||||
ifo->options &= ~DHCPCD_HOSTNAME;
|
||||
else
|
||||
|
@ -874,16 +879,16 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
break;
|
||||
case 't':
|
||||
ARG_REQUIRED;
|
||||
ifo->timeout = (time_t)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
|
||||
ifo->timeout = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
if (e) {
|
||||
logerrx("failed to convert timeout %s", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
s = USERCLASS_MAX_LEN - ifo->userclass[0] - 1;
|
||||
dl = sizeof(ifo->userclass) - ifo->userclass[0] - 1;
|
||||
s = parse_string((char *)ifo->userclass +
|
||||
ifo->userclass[0] + 2, (size_t)s, arg);
|
||||
ifo->userclass[0] + 2, dl, arg);
|
||||
if (s == -1) {
|
||||
logerr("userclass");
|
||||
return -1;
|
||||
|
@ -893,6 +898,19 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
ifo->userclass[0] = (uint8_t)(ifo->userclass[0] + s +1);
|
||||
}
|
||||
break;
|
||||
#ifndef SMALL
|
||||
case O_MSUSERCLASS:
|
||||
/* Some Microsoft DHCP servers expect userclass to be an
|
||||
* opaque blob. This is not RFC 3004 compliant. */
|
||||
s = parse_string((char *)ifo->userclass + 1,
|
||||
sizeof(ifo->userclass) - 1, arg);
|
||||
if (s == -1) {
|
||||
logerr("msuserclass");
|
||||
return -1;
|
||||
}
|
||||
ifo->userclass[0] = (uint8_t)s;
|
||||
break;
|
||||
#endif
|
||||
case 'v':
|
||||
ARG_REQUIRED;
|
||||
p = strchr(arg, ',');
|
||||
|
@ -967,7 +985,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
break;
|
||||
case 'y':
|
||||
ARG_REQUIRED;
|
||||
ifo->reboot = (time_t)strtoi(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
ifo->reboot = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
if (e) {
|
||||
logerr("failed to convert reboot %s", arg);
|
||||
return -1;
|
||||
|
@ -1165,7 +1183,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
np = strchr(p, '/');
|
||||
if (np)
|
||||
*np++ = '\0';
|
||||
if (inet_pton(AF_INET6, p, &ifo->req_addr6) == 1) {
|
||||
if ((i = inet_pton(AF_INET6, p, &ifo->req_addr6)) == 1) {
|
||||
if (np) {
|
||||
ifo->req_prefix_len = (uint8_t)strtou(np,
|
||||
NULL, 0, 0, 128, &e);
|
||||
|
@ -1178,6 +1196,14 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
} else
|
||||
ifo->req_prefix_len = 128;
|
||||
}
|
||||
if (np)
|
||||
*(--np) = '\0';
|
||||
if (i != 1) {
|
||||
logerrx("invalid AF_INET6: %s", p);
|
||||
memset(&ifo->req_addr6, 0,
|
||||
sizeof(ifo->req_addr6));
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
add_environ(&ifo->config, arg, 1);
|
||||
break;
|
||||
|
@ -1238,6 +1264,34 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
break;
|
||||
case O_NOIPV6:
|
||||
ifo->options &= ~DHCPCD_IPV6;
|
||||
break;
|
||||
case O_ANONYMOUS:
|
||||
ifo->options |= DHCPCD_ANONYMOUS;
|
||||
ifo->options &= ~DHCPCD_HOSTNAME;
|
||||
ifo->fqdn = FQDN_DISABLE;
|
||||
|
||||
/* Block everything */
|
||||
memset(ifo->nomask, 0xff, sizeof(ifo->nomask));
|
||||
memset(ifo->nomask6, 0xff, sizeof(ifo->nomask6));
|
||||
|
||||
/* Allow the bare minimum through */
|
||||
del_option_mask(ifo->nomask, DHO_SUBNETMASK);
|
||||
del_option_mask(ifo->nomask, DHO_CSR);
|
||||
del_option_mask(ifo->nomask, DHO_ROUTER);
|
||||
del_option_mask(ifo->nomask, DHO_DNSSERVER);
|
||||
del_option_mask(ifo->nomask, DHO_DNSDOMAIN);
|
||||
del_option_mask(ifo->nomask, DHO_BROADCAST);
|
||||
del_option_mask(ifo->nomask, DHO_STATICROUTE);
|
||||
del_option_mask(ifo->nomask, DHO_SERVERID);
|
||||
del_option_mask(ifo->nomask, DHO_RENEWALTIME);
|
||||
del_option_mask(ifo->nomask, DHO_REBINDTIME);
|
||||
del_option_mask(ifo->nomask, DHO_DNSSEARCH);
|
||||
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_DNS_SERVERS);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_DOMAIN_LIST);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_SOL_MAX_RT);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_INF_MAX_RT);
|
||||
|
||||
break;
|
||||
#ifdef INET
|
||||
case O_ARPING:
|
||||
|
@ -1398,8 +1452,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
p = strchr(arg, '/');
|
||||
if (p)
|
||||
*p++ = '\0';
|
||||
if (inet_pton(AF_INET6, arg, &ia->addr) == -1) {
|
||||
logerr("%s", arg);
|
||||
if (inet_pton(AF_INET6, arg, &ia->addr) != 1) {
|
||||
logerrx("invalid AF_INET6: %s", arg);
|
||||
memset(&ia->addr, 0, sizeof(ia->addr));
|
||||
}
|
||||
if (p && ia->ia_type == D6_OPTION_IA_PD) {
|
||||
|
@ -1972,52 +2026,42 @@ err_sla:
|
|||
return -1;
|
||||
}
|
||||
*fp++ = '\0';
|
||||
token = malloc(sizeof(*token));
|
||||
token = calloc(1, sizeof(*token));
|
||||
if (token == NULL) {
|
||||
logerr(__func__);
|
||||
free(token);
|
||||
return -1;
|
||||
}
|
||||
if (parse_uint32(&token->secretid, arg) == -1) {
|
||||
logerrx("%s: not a number", arg);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
arg = fp;
|
||||
fp = strend(arg);
|
||||
if (fp == NULL) {
|
||||
logerrx("authtoken requies an a key");
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
*fp++ = '\0';
|
||||
s = parse_string(NULL, 0, arg);
|
||||
if (s == -1) {
|
||||
logerr("realm_len");
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
if (s) {
|
||||
if (s != 0) {
|
||||
token->realm_len = (size_t)s;
|
||||
token->realm = malloc(token->realm_len);
|
||||
if (token->realm == NULL) {
|
||||
logerr(__func__);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
parse_string((char *)token->realm, token->realm_len,
|
||||
arg);
|
||||
} else {
|
||||
token->realm_len = 0;
|
||||
token->realm = NULL;
|
||||
}
|
||||
arg = fp;
|
||||
fp = strend(arg);
|
||||
if (fp == NULL) {
|
||||
logerrx("authtoken requies an expiry date");
|
||||
free(token->realm);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
*fp++ = '\0';
|
||||
if (*arg == '"') {
|
||||
|
@ -2034,15 +2078,11 @@ err_sla:
|
|||
memset(&tm, 0, sizeof(tm));
|
||||
if (strptime(arg, "%Y-%m-%d %H:%M", &tm) == NULL) {
|
||||
logerrx("%s: invalid date time", arg);
|
||||
free(token->realm);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
if ((token->expire = mktime(&tm)) == (time_t)-1) {
|
||||
logerr("%s: mktime", __func__);
|
||||
free(token->realm);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
}
|
||||
arg = fp;
|
||||
|
@ -2052,19 +2092,25 @@ err_sla:
|
|||
logerr("token_len");
|
||||
else
|
||||
logerrx("authtoken needs a key");
|
||||
free(token->realm);
|
||||
free(token);
|
||||
return -1;
|
||||
goto invalid_token;
|
||||
}
|
||||
token->key_len = (size_t)s;
|
||||
token->key = malloc(token->key_len);
|
||||
if (token->key == NULL) {
|
||||
logerr(__func__);
|
||||
goto invalid_token;
|
||||
}
|
||||
parse_string((char *)token->key, token->key_len, arg);
|
||||
TAILQ_INSERT_TAIL(&ifo->auth.tokens, token, next);
|
||||
break;
|
||||
|
||||
invalid_token:
|
||||
free(token->realm);
|
||||
free(token);
|
||||
#else
|
||||
logerrx("no authentication support");
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
return -1;
|
||||
case O_AUTHNOTREQUIRED:
|
||||
ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
|
||||
break;
|
||||
|
@ -2491,6 +2537,11 @@ read_config(struct dhcpcd_ctx *ctx,
|
|||
}
|
||||
|
||||
/* Parse our options file */
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP &&
|
||||
ps_root_copychroot(ctx, ctx->cffile) == -1)
|
||||
logwarn("%s: ps_root_copychroot `%s'", __func__, ctx->cffile);
|
||||
#endif
|
||||
fp = fopen(ctx->cffile, "r");
|
||||
if (fp == NULL) {
|
||||
/* dhcpcd can continue without it, but no DNS options
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -57,9 +57,10 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ELOOP_QUEUE 7
|
||||
#define ELOOP_QUEUE ELOOP_IPV6
|
||||
#include "common.h"
|
||||
#include "if.h"
|
||||
#include "dhcpcd.h"
|
||||
|
@ -380,25 +381,14 @@ ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp,
|
|||
static int
|
||||
ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len)
|
||||
{
|
||||
int bytes, bits;
|
||||
struct in6_addr mask;
|
||||
size_t i;
|
||||
|
||||
if (len < 0 || len > 128) {
|
||||
errno = EINVAL;
|
||||
if (ipv6_mask(&mask, len) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = len / NBBY;
|
||||
bits = len % NBBY;
|
||||
memcpy(&prefix->s6_addr, &addr->s6_addr, (size_t)bytes);
|
||||
if (bits != 0) {
|
||||
/* Coverify false positive.
|
||||
* bytelen cannot be 16 if bitlen is non zero */
|
||||
/* coverity[overrun-local] */
|
||||
prefix->s6_addr[bytes] =
|
||||
(uint8_t)(prefix->s6_addr[bytes] >> (NBBY - bits));
|
||||
}
|
||||
memset((char *)prefix->s6_addr + bytes, 0,
|
||||
sizeof(prefix->s6_addr) - (size_t)bytes);
|
||||
*prefix = *addr;
|
||||
for (i = 0; i < sizeof(prefix->s6_addr); i++)
|
||||
prefix->s6_addr[i] &= mask.s6_addr[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -568,11 +558,8 @@ ipv6_checkaddrflags(void *arg)
|
|||
&ia->addr, ia->prefix_len, flags, 0);
|
||||
} else {
|
||||
/* Still tentative? Check again in a bit. */
|
||||
struct timespec tv;
|
||||
|
||||
ms_to_ts(&tv, RETRANS_TIMER / 2);
|
||||
eloop_timeout_add_tv(ia->iface->ctx->eloop, &tv,
|
||||
ipv6_checkaddrflags, ia);
|
||||
eloop_timeout_add_msec(ia->iface->ctx->eloop,
|
||||
RETRANS_TIMER / 2, ipv6_checkaddrflags, ia);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -581,7 +568,10 @@ static void
|
|||
ipv6_deletedaddr(struct ipv6_addr *ia)
|
||||
{
|
||||
|
||||
#ifdef SMALL
|
||||
#ifdef PRIVSEP
|
||||
if (!(ia->iface->ctx->options & DHCPCD_MASTER))
|
||||
ps_inet_closedhcp6(ia);
|
||||
#elif defined(SMALL)
|
||||
UNUSED(ia);
|
||||
#else
|
||||
/* NOREJECT is set if we delegated exactly the prefix to another
|
||||
|
@ -627,7 +617,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
|
|||
{
|
||||
struct interface *ifp;
|
||||
uint32_t pltime, vltime;
|
||||
__printflike(1, 2) void (*logfunc)(const char *, ...);
|
||||
int loglevel;
|
||||
#ifdef ND6_ADVERTISE
|
||||
bool vltime_was_zero = ia->prefix_vltime == 0;
|
||||
#endif
|
||||
|
@ -663,33 +653,31 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
|
|||
(ia->prefix_pltime != ND6_INFINITE_LIFETIME ||
|
||||
ia->prefix_vltime != ND6_INFINITE_LIFETIME))
|
||||
{
|
||||
uint32_t elapsed;
|
||||
struct timespec n;
|
||||
|
||||
if (now == NULL) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &n);
|
||||
now = &n;
|
||||
}
|
||||
timespecsub(now, &ia->acquired, &n);
|
||||
elapsed = (uint32_t)eloop_timespec_diff(now, &ia->acquired,
|
||||
NULL);
|
||||
if (ia->prefix_pltime != ND6_INFINITE_LIFETIME) {
|
||||
ia->prefix_pltime -= (uint32_t)n.tv_sec;
|
||||
/* This can happen when confirming a
|
||||
* deprecated but still valid lease. */
|
||||
if (ia->prefix_pltime > pltime)
|
||||
if (elapsed > ia->prefix_pltime)
|
||||
ia->prefix_pltime = 0;
|
||||
else
|
||||
ia->prefix_pltime -= elapsed;
|
||||
}
|
||||
if (ia->prefix_vltime != ND6_INFINITE_LIFETIME) {
|
||||
ia->prefix_vltime -= (uint32_t)n.tv_sec;
|
||||
/* This should never happen. */
|
||||
if (ia->prefix_vltime > vltime) {
|
||||
logerrx("%s: %s: lifetime overflow",
|
||||
ifp->name, ia->saddr);
|
||||
ia->prefix_vltime = ia->prefix_pltime = 0;
|
||||
}
|
||||
if (elapsed > ia->prefix_vltime)
|
||||
ia->prefix_vltime = 0;
|
||||
else
|
||||
ia->prefix_vltime -= elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
logfunc = ia->flags & IPV6_AF_NEW ? loginfox : logdebugx;
|
||||
logfunc("%s: adding %saddress %s", ifp->name,
|
||||
loglevel = ia->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG;
|
||||
logmessage(loglevel, "%s: adding %saddress %s", ifp->name,
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
ia->flags & IPV6_AF_TEMPORARY ? "temporary " : "",
|
||||
#else
|
||||
|
@ -726,7 +714,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
|
|||
ia->prefix_vltime &&
|
||||
ip6_use_tempaddr(ifp->name))
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
(time_t)ia->prefix_pltime - REGEN_ADVANCE,
|
||||
ia->prefix_pltime - REGEN_ADVANCE,
|
||||
ipv6_regentempaddr, ia);
|
||||
#endif
|
||||
|
||||
|
@ -745,11 +733,8 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
|
|||
eloop_timeout_delete(ifp->ctx->eloop,
|
||||
ipv6_checkaddrflags, ia);
|
||||
if (!(ia->flags & IPV6_AF_DADCOMPLETED)) {
|
||||
struct timespec tv;
|
||||
|
||||
ms_to_ts(&tv, RETRANS_TIMER / 2);
|
||||
eloop_timeout_add_tv(ifp->ctx->eloop,
|
||||
&tv, ipv6_checkaddrflags, ia);
|
||||
eloop_timeout_add_msec(ifp->ctx->eloop,
|
||||
RETRANS_TIMER / 2, ipv6_checkaddrflags, ia);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -932,7 +917,7 @@ ipv6_doaddr(struct ipv6_addr *ia, struct timespec *now)
|
|||
if (ia->flags & IPV6_AF_ADDED)
|
||||
ipv6_deleteaddr(ia);
|
||||
eloop_q_timeout_delete(ia->iface->ctx->eloop,
|
||||
0, NULL, ia);
|
||||
ELOOP_QUEUE_ALL, NULL, ia);
|
||||
if (ia->flags & IPV6_AF_REQUEST) {
|
||||
ia->flags &= ~IPV6_AF_ADDED;
|
||||
return 0;
|
||||
|
@ -974,6 +959,7 @@ ipv6_addaddrs(struct ipv6_addrhead *iaddrs)
|
|||
void
|
||||
ipv6_freeaddr(struct ipv6_addr *ia)
|
||||
{
|
||||
struct eloop *eloop = ia->iface->ctx->eloop;
|
||||
#ifndef SMALL
|
||||
struct ipv6_addr *iad;
|
||||
|
||||
|
@ -989,10 +975,10 @@ ipv6_freeaddr(struct ipv6_addr *ia)
|
|||
|
||||
if (ia->dhcp6_fd != -1) {
|
||||
close(ia->dhcp6_fd);
|
||||
eloop_event_delete(ia->iface->ctx->eloop, ia->dhcp6_fd);
|
||||
eloop_event_delete(eloop, ia->dhcp6_fd);
|
||||
}
|
||||
|
||||
eloop_q_timeout_delete(ia->iface->ctx->eloop, 0, NULL, ia);
|
||||
eloop_q_timeout_delete(eloop, ELOOP_QUEUE_ALL, NULL, ia);
|
||||
free(ia->na);
|
||||
free(ia);
|
||||
}
|
||||
|
@ -1207,12 +1193,9 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
|
|||
if (IN6_IS_ADDR_LINKLOCAL(&ia->addr) || ia->dadcallback) {
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
if (ia->addr_flags & IN6_IFF_TENTATIVE) {
|
||||
struct timespec tv;
|
||||
|
||||
ms_to_ts(&tv, RETRANS_TIMER / 2);
|
||||
eloop_timeout_add_tv(
|
||||
eloop_timeout_add_msec(
|
||||
ia->iface->ctx->eloop,
|
||||
&tv, ipv6_checkaddrflags, ia);
|
||||
RETRANS_TIMER / 2, ipv6_checkaddrflags, ia);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1509,12 +1492,9 @@ ipv6_tryaddlinklocal(struct interface *ifp)
|
|||
if (ia != NULL) {
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
if (ia->addr_flags & IN6_IFF_TENTATIVE) {
|
||||
struct timespec tv;
|
||||
|
||||
ms_to_ts(&tv, RETRANS_TIMER / 2);
|
||||
eloop_timeout_add_tv(
|
||||
eloop_timeout_add_msec(
|
||||
ia->iface->ctx->eloop,
|
||||
&tv, ipv6_checkaddrflags, ia);
|
||||
RETRANS_TIMER / 2, ipv6_checkaddrflags, ia);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -1529,18 +1509,28 @@ struct ipv6_addr *
|
|||
ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
|
||||
uint8_t prefix_len, unsigned int flags)
|
||||
{
|
||||
struct ipv6_addr *ia;
|
||||
struct ipv6_addr *ia, *iaf;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
const char *cbp;
|
||||
bool tempaddr;
|
||||
int addr_flags;
|
||||
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
tempaddr = flags & IPV6_AF_TEMPORARY;
|
||||
#else
|
||||
tempaddr = false;
|
||||
#endif
|
||||
|
||||
/* If adding a new DHCP / RA derived address, check current flags
|
||||
* from an existing address. */
|
||||
ia = ipv6_iffindaddr(ifp, addr, 0);
|
||||
if (ia != NULL)
|
||||
addr_flags = ia->addr_flags;
|
||||
if (flags & IPV6_AF_AUTOCONF)
|
||||
iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
|
||||
else
|
||||
iaf = ipv6_iffindaddr(ifp, addr, 0);
|
||||
if (iaf != NULL) {
|
||||
addr_flags = iaf->addr_flags;
|
||||
flags |= IPV6_AF_ADDED;
|
||||
} else
|
||||
addr_flags = IN6_IFF_TENTATIVE;
|
||||
|
||||
ia = calloc(1, sizeof(*ia));
|
||||
|
@ -1559,21 +1549,19 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
|
|||
TAILQ_INIT(&ia->pd_pfxs);
|
||||
#endif
|
||||
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
tempaddr = ia->flags & IPV6_AF_TEMPORARY;
|
||||
#else
|
||||
tempaddr = false;
|
||||
#endif
|
||||
|
||||
if (prefix_len == 128)
|
||||
goto makepfx;
|
||||
else if (ia->flags & IPV6_AF_AUTOCONF && !tempaddr) {
|
||||
ia->prefix = *addr;
|
||||
ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp,
|
||||
&ia->prefix,
|
||||
ia->prefix_len);
|
||||
if (ia->dadcounter == -1)
|
||||
goto err;
|
||||
if (iaf != NULL)
|
||||
memcpy(&ia->addr, &iaf->addr, sizeof(ia->addr));
|
||||
else {
|
||||
ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp,
|
||||
&ia->prefix,
|
||||
ia->prefix_len);
|
||||
if (ia->dadcounter == -1)
|
||||
goto err;
|
||||
}
|
||||
} else if (ia->flags & IPV6_AF_RAPFX) {
|
||||
ia->prefix = *addr;
|
||||
#ifdef __sun
|
||||
|
@ -1819,9 +1807,9 @@ ipv6_handleifa_addrs(int cmd,
|
|||
ia->iface->name, pid, ia->saddr);
|
||||
ia->flags &= ~IPV6_AF_ADDED;
|
||||
}
|
||||
ipv6_deletedaddr(ia);
|
||||
if (ia->flags & IPV6_AF_DELEGATED) {
|
||||
TAILQ_REMOVE(addrs, ia, next);
|
||||
ipv6_deletedaddr(ia);
|
||||
ipv6_freeaddr(ia);
|
||||
}
|
||||
break;
|
||||
|
@ -1877,7 +1865,7 @@ static void
|
|||
ipv6_regen_desync(struct interface *ifp, int force)
|
||||
{
|
||||
struct ipv6_state *state;
|
||||
time_t max;
|
||||
unsigned int max, pref;
|
||||
|
||||
state = IPV6_STATE(ifp);
|
||||
|
||||
|
@ -1885,15 +1873,14 @@ ipv6_regen_desync(struct interface *ifp, int force)
|
|||
* greater than TEMP_VALID_LIFETIME - REGEN_ADVANCE.
|
||||
* I believe this is an error and it should be never be greateter than
|
||||
* TEMP_PREFERRED_LIFETIME - REGEN_ADVANCE. */
|
||||
max = ip6_temp_preferred_lifetime(ifp->name) - REGEN_ADVANCE;
|
||||
pref = (unsigned int)ip6_temp_preferred_lifetime(ifp->name);
|
||||
max = pref - REGEN_ADVANCE;
|
||||
if (state->desync_factor && !force && state->desync_factor < max)
|
||||
return;
|
||||
if (state->desync_factor == 0)
|
||||
state->desync_factor =
|
||||
(time_t)arc4random_uniform(MIN(MAX_DESYNC_FACTOR,
|
||||
(uint32_t)max));
|
||||
max = ip6_temp_preferred_lifetime(ifp->name) -
|
||||
state->desync_factor - REGEN_ADVANCE;
|
||||
arc4random_uniform(MIN(MAX_DESYNC_FACTOR, max));
|
||||
max = pref - state->desync_factor - REGEN_ADVANCE;
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, max, ipv6_regentempifid, ifp);
|
||||
}
|
||||
|
||||
|
@ -2048,8 +2035,8 @@ again:
|
|||
ipv6_regen_desync(ia->iface, 0);
|
||||
|
||||
/* RFC4941 Section 3.3.4 */
|
||||
i = (uint32_t)(ip6_temp_preferred_lifetime(ia0->iface->name) -
|
||||
state->desync_factor);
|
||||
i = (uint32_t)ip6_temp_preferred_lifetime(ia0->iface->name) -
|
||||
state->desync_factor;
|
||||
ia->prefix_pltime = MIN(ia0->prefix_pltime, i);
|
||||
i = (uint32_t)ip6_temp_valid_lifetime(ia0->iface->name);
|
||||
ia->prefix_vltime = MIN(ia0->prefix_vltime, i);
|
||||
|
@ -2078,7 +2065,7 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
|
|||
ap->prefix_pltime &&
|
||||
IN6_ARE_ADDR_EQUAL(&ia->prefix, &ap->prefix))
|
||||
{
|
||||
time_t max, ext;
|
||||
unsigned int max, ext;
|
||||
|
||||
if (flags == 0) {
|
||||
if (ap->prefix_pltime -
|
||||
|
@ -2107,10 +2094,11 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
|
|||
/* RFC4941 Section 3.3.2
|
||||
* Extend temporary times, but ensure that they
|
||||
* never last beyond the system limit. */
|
||||
ext = ia->acquired.tv_sec + (time_t)ia->prefix_pltime;
|
||||
max = ap->created.tv_sec +
|
||||
ext = (unsigned int)ia->acquired.tv_sec
|
||||
+ ia->prefix_pltime;
|
||||
max = (unsigned int)(ap->created.tv_sec +
|
||||
ip6_temp_preferred_lifetime(ap->iface->name) -
|
||||
state->desync_factor;
|
||||
state->desync_factor);
|
||||
if (ext < max)
|
||||
ap->prefix_pltime = ia->prefix_pltime;
|
||||
else
|
||||
|
@ -2118,9 +2106,10 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
|
|||
(uint32_t)(max - ia->acquired.tv_sec);
|
||||
|
||||
valid:
|
||||
ext = ia->acquired.tv_sec + (time_t)ia->prefix_vltime;
|
||||
max = ap->created.tv_sec +
|
||||
ip6_temp_valid_lifetime(ap->iface->name);
|
||||
ext = (unsigned int)ia->acquired.tv_sec +
|
||||
ia->prefix_vltime;
|
||||
max = (unsigned int)(ap->created.tv_sec +
|
||||
ip6_temp_valid_lifetime(ap->iface->name));
|
||||
if (ext < max)
|
||||
ap->prefix_vltime = ia->prefix_vltime;
|
||||
else
|
||||
|
@ -2342,6 +2331,9 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
|||
struct ra *rap;
|
||||
const struct ipv6_addr *addr;
|
||||
|
||||
if (ctx->ra_routers == NULL)
|
||||
return 0;
|
||||
|
||||
TAILQ_FOREACH(rap, ctx->ra_routers, next) {
|
||||
if (rap->expired)
|
||||
continue;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -69,6 +69,8 @@
|
|||
|
||||
/* Interface identifier length. Prefix + this == 128 for autoconf */
|
||||
#define ipv6_ifidlen(ifp) 64
|
||||
#define IA6_CANAUTOCONF(ia) \
|
||||
((ia)->prefix_len + ipv6_ifidlen((ia)->iface) == 128)
|
||||
|
||||
#ifndef IN6_ARE_MASKED_ADDR_EQUAL
|
||||
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
|
||||
|
@ -108,6 +110,11 @@
|
|||
# undef IPV6_POLLADDRFLAG
|
||||
#endif
|
||||
|
||||
/* Of course OpenBSD has their own special name. */
|
||||
#if !defined(IN6_IFF_TEMPORARY) && defined(IN6_IFF_PRIVACY)
|
||||
#define IN6_IFF_TEMPORARY IN6_IFF_PRIVACY
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
/* Solaris lacks these defines.
|
||||
* While it supports DaD, to seems to only expose IFF_DUPLICATE
|
||||
|
@ -237,7 +244,7 @@ struct ipv6_state {
|
|||
struct ll_callback_head ll_callbacks;
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
time_t desync_factor;
|
||||
uint32_t desync_factor;
|
||||
uint8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
|
||||
uint8_t randomseed1[8]; /* lower 64 bits */
|
||||
uint8_t randomid[8];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd - IPv6 ND handling
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,9 +41,10 @@
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ELOOP_QUEUE 3
|
||||
#define ELOOP_QUEUE ELOOP_IPV6ND
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "dhcp-common.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include "ipv6.h"
|
||||
#include "ipv6nd.h"
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
#include "route.h"
|
||||
#include "script.h"
|
||||
|
||||
|
@ -235,7 +237,7 @@ eexit:
|
|||
}
|
||||
|
||||
#ifdef __sun
|
||||
static int
|
||||
int
|
||||
ipv6nd_open(struct interface *ifp)
|
||||
{
|
||||
int fd;
|
||||
|
@ -272,7 +274,7 @@ ipv6nd_open(struct interface *ifp)
|
|||
return fd;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
int
|
||||
ipv6nd_open(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
int fd;
|
||||
|
@ -285,7 +287,8 @@ ipv6nd_open(struct dhcpcd_ctx *ctx)
|
|||
return -1;
|
||||
|
||||
ctx->nd_fd = fd;
|
||||
eloop_event_add(ctx->eloop, fd, ipv6nd_handledata, ctx);
|
||||
if (!(IN_PRIVSEP(ctx)))
|
||||
eloop_event_add(ctx->eloop, fd, ipv6nd_handledata, ctx);
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
@ -363,6 +366,13 @@ ipv6nd_sendrsprobe(void *arg)
|
|||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
logdebugx("%s: sending Router Solicitation", ifp->name);
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP(ifp->ctx)) {
|
||||
if (ps_inet_sendnd(ifp, &msg) == -1)
|
||||
logerr(__func__);
|
||||
goto sent;
|
||||
}
|
||||
#endif
|
||||
#ifdef __sun
|
||||
s = state->nd_fd;
|
||||
#else
|
||||
|
@ -376,13 +386,14 @@ ipv6nd_sendrsprobe(void *arg)
|
|||
* associate with an access point. */
|
||||
}
|
||||
|
||||
#ifdef PRIVSEP
|
||||
sent:
|
||||
#endif
|
||||
if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
|
||||
else {
|
||||
else
|
||||
logwarnx("%s: no IPv6 Routers available", ifp->name);
|
||||
ipv6nd_drop(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ND6_ADVERTISE
|
||||
|
@ -424,6 +435,14 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
cm->cmsg_len = CMSG_LEN(sizeof(pi));
|
||||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (IN_PRIVSEP(ifp->ctx)) {
|
||||
if (ps_inet_sendnd(ifp, &msg) == -1)
|
||||
logerr(__func__);
|
||||
goto sent;
|
||||
}
|
||||
#endif
|
||||
#ifdef __sun
|
||||
s = state->nd_fd;
|
||||
#else
|
||||
|
@ -432,6 +451,9 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
if (sendmsg(s, &msg, 0) == -1)
|
||||
logerr(__func__);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
sent:
|
||||
#endif
|
||||
if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
|
||||
eloop_timeout_add_sec(ctx->eloop,
|
||||
state->retrans / 1000, ipv6nd_sendadvertisement, ia);
|
||||
|
@ -531,19 +553,13 @@ ipv6nd_expire(void *arg)
|
|||
{
|
||||
struct interface *ifp = arg;
|
||||
struct ra *rap;
|
||||
struct ipv6_addr *ia;
|
||||
struct timespec now = { .tv_sec = 1 };
|
||||
|
||||
if (ifp->ctx->ra_routers == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
|
||||
if (rap->iface == ifp)
|
||||
continue;
|
||||
rap->acquired = now;
|
||||
TAILQ_FOREACH(ia, &rap->addrs, next) {
|
||||
ia->acquired = now;
|
||||
}
|
||||
if (rap->iface == ifp && rap->willexpire)
|
||||
rap->doexpire = true;
|
||||
}
|
||||
ipv6nd_expirera(ifp);
|
||||
}
|
||||
|
@ -551,9 +567,17 @@ ipv6nd_expire(void *arg)
|
|||
void
|
||||
ipv6nd_startexpire(struct interface *ifp)
|
||||
{
|
||||
struct ra *rap;
|
||||
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, RTR_CARRIER_EXPIRE,
|
||||
ipv6nd_expire, ifp);
|
||||
if (ifp->ctx->ra_routers == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
|
||||
if (rap->iface == ifp)
|
||||
rap->willexpire = true;
|
||||
}
|
||||
eloop_q_timeout_add_sec(ifp->ctx->eloop, ELOOP_IPV6RA_EXPIRE,
|
||||
RTR_CARRIER_EXPIRE, ipv6nd_expire, ifp);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -584,19 +608,22 @@ ipv6nd_sortrouters(struct dhcpcd_ctx *ctx)
|
|||
while ((ra1 = TAILQ_FIRST(ctx->ra_routers)) != NULL) {
|
||||
TAILQ_REMOVE(ctx->ra_routers, ra1, next);
|
||||
TAILQ_FOREACH(ra2, &sorted_routers, next) {
|
||||
if (ra1->iface->metric < ra2->iface->metric)
|
||||
if (ra1->iface->metric > ra2->iface->metric)
|
||||
continue;
|
||||
if (ra1->expired && !ra2->expired)
|
||||
continue;
|
||||
if (ra1->willexpire && !ra2->willexpire)
|
||||
continue;
|
||||
if (ra1->lifetime == 0 && ra2->lifetime != 0)
|
||||
continue;
|
||||
if (!ra1->isreachable && ra2->reachable)
|
||||
continue;
|
||||
if (ipv6nd_rtpref(ra1) < ipv6nd_rtpref(ra2))
|
||||
if (ipv6nd_rtpref(ra1) <= ipv6nd_rtpref(ra2))
|
||||
continue;
|
||||
/* All things being equal, prefer older routers. */
|
||||
if (timespeccmp(&ra1->acquired, &ra2->acquired, >=))
|
||||
continue;
|
||||
/* We don't need to check time, becase newer
|
||||
* routers are always added to the tail and then
|
||||
* sorted. */
|
||||
TAILQ_INSERT_BEFORE(ra2, ra1, next);
|
||||
break;
|
||||
}
|
||||
|
@ -719,6 +746,40 @@ ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct ipv6_addr *
|
||||
ipv6nd_rapfindprefix(struct ra *rap,
|
||||
const struct in6_addr *pfx, uint8_t pfxlen)
|
||||
{
|
||||
struct ipv6_addr *ia;
|
||||
|
||||
TAILQ_FOREACH(ia, &rap->addrs, next) {
|
||||
if (ia->prefix_vltime == 0)
|
||||
continue;
|
||||
if (ia->prefix_len == pfxlen &&
|
||||
IN6_ARE_ADDR_EQUAL(&ia->prefix, pfx))
|
||||
break;
|
||||
}
|
||||
return ia;
|
||||
}
|
||||
|
||||
struct ipv6_addr *
|
||||
ipv6nd_iffindprefix(struct interface *ifp,
|
||||
const struct in6_addr *pfx, uint8_t pfxlen)
|
||||
{
|
||||
struct ra *rap;
|
||||
struct ipv6_addr *ia;
|
||||
|
||||
ia = NULL;
|
||||
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
|
||||
if (rap->iface != ifp)
|
||||
continue;
|
||||
ia = ipv6nd_rapfindprefix(rap, pfx, pfxlen);
|
||||
if (ia != NULL)
|
||||
break;
|
||||
}
|
||||
return ia;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
|
||||
{
|
||||
|
@ -786,10 +847,10 @@ ipv6nd_free(struct interface *ifp)
|
|||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
ipv6nd_scriptrun(struct ra *rap)
|
||||
{
|
||||
int hasdns, hasaddress, pid;
|
||||
int hasdns, hasaddress;
|
||||
struct ipv6_addr *ap;
|
||||
|
||||
hasaddress = 0;
|
||||
|
@ -807,7 +868,7 @@ ipv6nd_scriptrun(struct ra *rap)
|
|||
logdebugx("%s: waiting for Router Advertisement"
|
||||
" DAD to complete",
|
||||
rap->iface->name);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -820,19 +881,16 @@ ipv6nd_scriptrun(struct ra *rap)
|
|||
}
|
||||
|
||||
script_runreason(rap->iface, "ROUTERADVERT");
|
||||
pid = 0;
|
||||
if (hasdns && (hasaddress ||
|
||||
!(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
|
||||
pid = dhcpcd_daemonise(rap->iface->ctx);
|
||||
dhcpcd_daemonise(rap->iface->ctx);
|
||||
#if 0
|
||||
else if (options & DHCPCD_DAEMONISE &&
|
||||
!(options & DHCPCD_DAEMONISED) && new_data)
|
||||
logwarnx("%s: did not fork due to an absent"
|
||||
" RDNSS option in the RA",
|
||||
ifp->name);
|
||||
}
|
||||
#endif
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -869,7 +927,6 @@ ipv6nd_dadcallback(void *arg)
|
|||
struct interface *ifp;
|
||||
struct ra *rap;
|
||||
int wascompleted, found;
|
||||
struct timespec tv;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
const char *p;
|
||||
int dadcounter;
|
||||
|
@ -885,7 +942,11 @@ ipv6nd_dadcallback(void *arg)
|
|||
* Because ap->dadcounter is always increamented,
|
||||
* a different address is generated. */
|
||||
/* XXX Cache DAD counter per prefix/id/ssid? */
|
||||
if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
|
||||
if (ifp->options->options & DHCPCD_SLAACPRIVATE &&
|
||||
IA6_CANAUTOCONF(ia))
|
||||
{
|
||||
unsigned int delay;
|
||||
|
||||
if (ia->dadcounter >= IDGEN_RETRIES) {
|
||||
logerrx("%s: unable to obtain a"
|
||||
" stable private address",
|
||||
|
@ -916,11 +977,8 @@ ipv6nd_dadcallback(void *arg)
|
|||
p, ia->prefix_len);
|
||||
else
|
||||
ia->saddr[0] = '\0';
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_nsec = (suseconds_t)
|
||||
arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
|
||||
timespecnorm(&tv);
|
||||
eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
|
||||
delay = arc4random_uniform(IDGEN_DELAY * MSEC_PER_SEC);
|
||||
eloop_timeout_add_msec(ifp->ctx->eloop, delay,
|
||||
ipv6nd_addaddr, ia);
|
||||
return;
|
||||
}
|
||||
|
@ -949,8 +1007,7 @@ try_script:
|
|||
logdebugx("%s: Router Advertisement DAD "
|
||||
"completed",
|
||||
rap->iface->name);
|
||||
if (ipv6nd_scriptrun(rap))
|
||||
return;
|
||||
ipv6nd_scriptrun(rap);
|
||||
}
|
||||
}
|
||||
#ifdef ND6_ADVERTISE
|
||||
|
@ -959,6 +1016,30 @@ try_script:
|
|||
}
|
||||
}
|
||||
|
||||
static struct ipv6_addr *
|
||||
ipv6nd_findmarkstale(struct ra *rap, struct ipv6_addr *ia, bool mark)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ia->iface->ctx;
|
||||
struct ra *rap2;
|
||||
struct ipv6_addr *ia2;
|
||||
|
||||
TAILQ_FOREACH(rap2, ctx->ra_routers, next) {
|
||||
if (rap2 == rap ||
|
||||
rap2->iface != rap->iface ||
|
||||
rap2->expired)
|
||||
continue;
|
||||
TAILQ_FOREACH(ia2, &rap2->addrs, next) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&ia->prefix, &ia2->prefix))
|
||||
continue;
|
||||
if (!(ia2->flags & IPV6_AF_STALE))
|
||||
return ia2;
|
||||
if (mark)
|
||||
ia2->prefix_pltime = 0;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef DHCP6
|
||||
/* If DHCPv6 is compiled out, supply a shim to provide an error message
|
||||
* if IPv6RA requests DHCPv6. */
|
||||
|
@ -989,14 +1070,14 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
uint8_t *p;
|
||||
struct ra *rap;
|
||||
struct in6_addr pi_prefix;
|
||||
struct ipv6_addr *ap;
|
||||
struct ipv6_addr *ia;
|
||||
struct dhcp_opt *dho;
|
||||
bool new_rap, new_data, has_address;
|
||||
uint32_t old_lifetime;
|
||||
int ifmtu;
|
||||
__printflike(1, 2) void (*logfunc)(const char *, ...);
|
||||
int loglevel;
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
uint8_t new_ap;
|
||||
bool new_ia;
|
||||
#endif
|
||||
|
||||
if (ifp == NULL) {
|
||||
|
@ -1093,8 +1174,11 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
* routers like to decrease the advertised valid and preferred times
|
||||
* in accordance with the own prefix times which would result in too
|
||||
* much needless log spam. */
|
||||
logfunc = new_data || !rap->isreachable ? loginfox : logdebugx,
|
||||
logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
|
||||
if (rap->willexpire)
|
||||
new_data = true;
|
||||
loglevel = new_data || !rap->isreachable ? LOG_INFO : LOG_DEBUG,
|
||||
logmessage(loglevel, "%s: Router Advertisement from %s",
|
||||
ifp->name, rap->sfrom);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
|
||||
rap->flags = nd_ra->nd_ra_flags_reserved;
|
||||
|
@ -1117,7 +1201,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
|
||||
else
|
||||
rap->retrans = RETRANS_TIMER;
|
||||
rap->expired = false;
|
||||
rap->expired = rap->willexpire = rap->doexpire = false;
|
||||
rap->hasdns = false;
|
||||
rap->isreachable = true;
|
||||
has_address = false;
|
||||
|
@ -1126,8 +1210,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
#ifdef IPV6_AF_TEMPORARY
|
||||
ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
|
||||
#endif
|
||||
TAILQ_FOREACH(ap, &rap->addrs, next) {
|
||||
ap->flags |= IPV6_AF_STALE;
|
||||
TAILQ_FOREACH(ia, &rap->addrs, next) {
|
||||
ia->flags |= IPV6_AF_STALE;
|
||||
}
|
||||
|
||||
len -= sizeof(struct nd_router_advert);
|
||||
|
@ -1177,15 +1261,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
|
||||
switch (ndo.nd_opt_type) {
|
||||
case ND_OPT_PREFIX_INFORMATION:
|
||||
logfunc = new_data ? logerrx : logdebugx;
|
||||
loglevel = new_data ? LOG_ERR : LOG_DEBUG;
|
||||
if (ndo.nd_opt_len != 4) {
|
||||
logfunc("%s: invalid option len for prefix",
|
||||
logmessage(loglevel, "%s: invalid option len for prefix",
|
||||
ifp->name);
|
||||
continue;
|
||||
}
|
||||
memcpy(&pi, p, sizeof(pi));
|
||||
if (pi.nd_opt_pi_prefix_len > 128) {
|
||||
logfunc("%s: invalid prefix len", ifp->name);
|
||||
logmessage(loglevel, "%s: invalid prefix len", ifp->name);
|
||||
continue;
|
||||
}
|
||||
/* nd_opt_pi_prefix is not aligned. */
|
||||
|
@ -1194,20 +1278,18 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
|
||||
IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
|
||||
{
|
||||
logfunc("%s: invalid prefix in RA", ifp->name);
|
||||
logmessage(loglevel, "%s: invalid prefix in RA", ifp->name);
|
||||
continue;
|
||||
}
|
||||
if (ntohl(pi.nd_opt_pi_preferred_time) >
|
||||
ntohl(pi.nd_opt_pi_valid_time))
|
||||
{
|
||||
logfunc("%s: pltime > vltime", ifp->name);
|
||||
logmessage(loglevel, "%s: pltime > vltime", ifp->name);
|
||||
continue;
|
||||
}
|
||||
TAILQ_FOREACH(ap, &rap->addrs, next)
|
||||
if (ap->prefix_len ==pi.nd_opt_pi_prefix_len &&
|
||||
IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix))
|
||||
break;
|
||||
if (ap == NULL) {
|
||||
ia = ipv6nd_rapfindprefix(rap,
|
||||
&pi_prefix, pi.nd_opt_pi_prefix_len);
|
||||
if (ia == NULL) {
|
||||
unsigned int flags;
|
||||
|
||||
flags = IPV6_AF_RAPFX;
|
||||
|
@ -1217,15 +1299,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
DHCPCD_IPV6RA_AUTOCONF)
|
||||
flags |= IPV6_AF_AUTOCONF;
|
||||
|
||||
ap = ipv6_newaddr(rap->iface,
|
||||
ia = ipv6_newaddr(rap->iface,
|
||||
&pi_prefix, pi.nd_opt_pi_prefix_len, flags);
|
||||
if (ap == NULL)
|
||||
if (ia == NULL)
|
||||
break;
|
||||
ap->prefix = pi_prefix;
|
||||
ia->prefix = pi_prefix;
|
||||
if (flags & IPV6_AF_AUTOCONF)
|
||||
ap->dadcallback = ipv6nd_dadcallback;
|
||||
ap->created = ap->acquired = rap->acquired;
|
||||
TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
|
||||
ia->dadcallback = ipv6nd_dadcallback;
|
||||
ia->created = ia->acquired = rap->acquired;
|
||||
TAILQ_INSERT_TAIL(&rap->addrs, ia, next);
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
/* New address to dhcpcd RA handling.
|
||||
|
@ -1234,44 +1316,44 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
* extend the existing one rather than
|
||||
* create a new one */
|
||||
if (flags & IPV6_AF_AUTOCONF &&
|
||||
ipv6_iffindaddr(ifp, &ap->addr,
|
||||
ipv6_iffindaddr(ifp, &ia->addr,
|
||||
IN6_IFF_NOTUSEABLE) &&
|
||||
ipv6_settemptime(ap, 0))
|
||||
new_ap = 0;
|
||||
ipv6_settemptime(ia, 0))
|
||||
new_ia = false;
|
||||
else
|
||||
new_ap = 1;
|
||||
new_ia = true;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
new_ap = 0;
|
||||
new_ia = false;
|
||||
#endif
|
||||
ap->flags &= ~IPV6_AF_STALE;
|
||||
ap->acquired = rap->acquired;
|
||||
ia->flags &= ~IPV6_AF_STALE;
|
||||
ia->acquired = rap->acquired;
|
||||
}
|
||||
if (pi.nd_opt_pi_flags_reserved &
|
||||
ND_OPT_PI_FLAG_ONLINK)
|
||||
ap->flags |= IPV6_AF_ONLINK;
|
||||
ap->prefix_vltime =
|
||||
ia->flags |= IPV6_AF_ONLINK;
|
||||
ia->prefix_vltime =
|
||||
ntohl(pi.nd_opt_pi_valid_time);
|
||||
ap->prefix_pltime =
|
||||
ia->prefix_pltime =
|
||||
ntohl(pi.nd_opt_pi_preferred_time);
|
||||
if (ap->prefix_vltime != 0 &&
|
||||
ap->flags & IPV6_AF_AUTOCONF)
|
||||
if (ia->prefix_vltime != 0 &&
|
||||
ia->flags & IPV6_AF_AUTOCONF)
|
||||
has_address = true;
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
/* RFC4941 Section 3.3.3 */
|
||||
if (ap->flags & IPV6_AF_AUTOCONF &&
|
||||
ip6_use_tempaddr(ap->iface->name) &&
|
||||
ipv6_ifidlen(ap->iface) + ap->prefix_len == 128)
|
||||
if (ia->flags & IPV6_AF_AUTOCONF &&
|
||||
ip6_use_tempaddr(ia->iface->name) &&
|
||||
IA6_CANAUTOCONF(ia))
|
||||
{
|
||||
if (!new_ap) {
|
||||
if (ipv6_settemptime(ap, 1) == NULL)
|
||||
new_ap = 1;
|
||||
if (!new_ia) {
|
||||
if (ipv6_settemptime(ia, 1) == NULL)
|
||||
new_ia = true;
|
||||
}
|
||||
if (new_ap && ap->prefix_pltime) {
|
||||
if (ipv6_createtempaddr(ap,
|
||||
&ap->acquired) == NULL)
|
||||
if (new_ia && ia->prefix_pltime) {
|
||||
if (ipv6_createtempaddr(ia,
|
||||
&ia->acquired) == NULL)
|
||||
logerr("ipv6_createtempaddr");
|
||||
}
|
||||
}
|
||||
|
@ -1280,13 +1362,13 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
|
||||
case ND_OPT_MTU:
|
||||
if (len < sizeof(mtu)) {
|
||||
logfunc("%s: short MTU option", ifp->name);
|
||||
logmessage(loglevel, "%s: short MTU option", ifp->name);
|
||||
break;
|
||||
}
|
||||
memcpy(&mtu, p, sizeof(mtu));
|
||||
mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
|
||||
if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
|
||||
logfunc("%s: invalid MTU %d",
|
||||
logmessage(loglevel, "%s: invalid MTU %d",
|
||||
ifp->name, mtu.nd_opt_mtu_mtu);
|
||||
break;
|
||||
}
|
||||
|
@ -1294,7 +1376,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
if (ifmtu == -1)
|
||||
logerr("if_getmtu");
|
||||
else if (mtu.nd_opt_mtu_mtu > (uint32_t)ifmtu) {
|
||||
logfunc("%s: advertised MTU %d"
|
||||
logmessage(loglevel, "%s: advertised MTU %d"
|
||||
" is greater than link MTU %d",
|
||||
ifp->name, mtu.nd_opt_mtu_mtu, ifmtu);
|
||||
rap->mtu = (uint32_t)ifmtu;
|
||||
|
@ -1303,7 +1385,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
break;
|
||||
case ND_OPT_RDNSS:
|
||||
if (len < sizeof(rdnss)) {
|
||||
logfunc("%s: short RDNSS option", ifp->name);
|
||||
logmessage(loglevel, "%s: short RDNSS option", ifp->name);
|
||||
break;
|
||||
}
|
||||
memcpy(&rdnss, p, sizeof(rdnss));
|
||||
|
@ -1333,6 +1415,19 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(ia, &rap->addrs, next) {
|
||||
if (!(ia->flags & IPV6_AF_STALE) || ia->prefix_pltime == 0)
|
||||
continue;
|
||||
if (ipv6nd_findmarkstale(rap, ia, false) != NULL)
|
||||
continue;
|
||||
ipv6nd_findmarkstale(rap, ia, true);
|
||||
logdebugx("%s: %s: became stale", ifp->name, ia->saddr);
|
||||
/* Technically this violates RFC 4861 6.3.4,
|
||||
* but we need a mechanism to tell the kernel to
|
||||
* try and prefer other addresses. */
|
||||
ia->prefix_pltime = 0;
|
||||
}
|
||||
|
||||
if (new_data && !has_address && rap->lifetime && !ipv6_anyglobal(ifp))
|
||||
logwarnx("%s: no global addresses for default route",
|
||||
ifp->name);
|
||||
|
@ -1353,8 +1448,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
|||
#endif
|
||||
|
||||
rt_build(ifp->ctx, AF_INET6);
|
||||
if (ipv6nd_scriptrun(rap))
|
||||
return;
|
||||
ipv6nd_scriptrun(rap);
|
||||
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
|
||||
|
@ -1397,7 +1491,8 @@ ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
|
|||
|
||||
if (ifp->ctx->ra_routers) {
|
||||
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
|
||||
if (rap->iface == ifp && !rap->expired &&
|
||||
if (rap->iface == ifp &&
|
||||
!rap->expired &&
|
||||
(!lifetime ||rap->lifetime))
|
||||
return true;
|
||||
}
|
||||
|
@ -1405,15 +1500,16 @@ ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
|
|||
}
|
||||
|
||||
bool
|
||||
ipv6nd_hasradhcp(const struct interface *ifp)
|
||||
ipv6nd_hasradhcp(const struct interface *ifp, bool managed)
|
||||
{
|
||||
const struct ra *rap;
|
||||
|
||||
if (ifp->ctx->ra_routers) {
|
||||
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
|
||||
if (rap->iface == ifp &&
|
||||
!rap->expired &&
|
||||
(rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER)))
|
||||
!rap->expired && !rap->willexpire &&
|
||||
((managed && rap->flags & ND_RA_FLAG_MANAGED) ||
|
||||
(!managed && rap->flags & ND_RA_FLAG_OTHER)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1548,7 +1644,7 @@ ipv6nd_env(FILE *fp, const struct interface *ifp)
|
|||
ia->prefix_vltime == 0)
|
||||
continue;
|
||||
if (efprintf(fp, "%s_addr%zu=%s",
|
||||
ndprefix, j++, ia->saddr) == -1)
|
||||
ndprefix, ++j, ia->saddr) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1577,7 +1673,8 @@ ipv6nd_expirera(void *arg)
|
|||
{
|
||||
struct interface *ifp;
|
||||
struct ra *rap, *ran;
|
||||
struct timespec now, lt, expire, next;
|
||||
struct timespec now;
|
||||
uint32_t elapsed;
|
||||
bool expired, valid;
|
||||
struct ipv6_addr *ia;
|
||||
size_t len, olen;
|
||||
|
@ -1588,23 +1685,21 @@ ipv6nd_expirera(void *arg)
|
|||
#endif
|
||||
struct nd_opt_dnssl dnssl;
|
||||
struct nd_opt_rdnss rdnss;
|
||||
uint32_t ltime;
|
||||
unsigned int next = 0, ltime;
|
||||
size_t nexpired = 0;
|
||||
|
||||
ifp = arg;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
expired = false;
|
||||
timespecclear(&next);
|
||||
|
||||
TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
|
||||
if (rap->iface != ifp || rap->expired)
|
||||
continue;
|
||||
valid = false;
|
||||
if (rap->lifetime) {
|
||||
lt.tv_sec = (time_t)rap->lifetime;
|
||||
lt.tv_nsec = 0;
|
||||
timespecadd(&rap->acquired, <, &expire);
|
||||
if (timespeccmp(&now, &expire, >)) {
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&rap->acquired, NULL);
|
||||
if (elapsed > rap->lifetime || rap->doexpire) {
|
||||
if (!rap->expired) {
|
||||
logwarnx("%s: %s: router expired",
|
||||
ifp->name, rap->sfrom);
|
||||
|
@ -1613,10 +1708,9 @@ ipv6nd_expirera(void *arg)
|
|||
}
|
||||
} else {
|
||||
valid = true;
|
||||
timespecsub(&expire, &now, <);
|
||||
if (!timespecisset(&next) ||
|
||||
timespeccmp(&next, <, >))
|
||||
next = lt;
|
||||
ltime = rap->lifetime - elapsed;
|
||||
if (next == 0 || ltime < next)
|
||||
next = ltime;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1626,17 +1720,21 @@ ipv6nd_expirera(void *arg)
|
|||
TAILQ_FOREACH(ia, &rap->addrs, next) {
|
||||
if (ia->prefix_vltime == 0)
|
||||
continue;
|
||||
if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
|
||||
if (ia->prefix_vltime == ND6_INFINITE_LIFETIME &&
|
||||
!rap->doexpire)
|
||||
{
|
||||
valid = true;
|
||||
continue;
|
||||
}
|
||||
lt.tv_sec = (time_t)ia->prefix_vltime;
|
||||
lt.tv_nsec = 0;
|
||||
timespecadd(&ia->acquired, <, &expire);
|
||||
if (timespeccmp(&now, &expire, >)) {
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&ia->acquired, NULL);
|
||||
if (elapsed > ia->prefix_vltime || rap->doexpire) {
|
||||
if (ia->flags & IPV6_AF_ADDED) {
|
||||
logwarnx("%s: expired address %s",
|
||||
ia->iface->name, ia->saddr);
|
||||
logwarnx("%s: expired %s %s",
|
||||
ia->iface->name,
|
||||
ia->flags & IPV6_AF_AUTOCONF ?
|
||||
"address" : "prefix",
|
||||
ia->saddr);
|
||||
if (if_address6(RTM_DELADDR, ia)== -1 &&
|
||||
errno != EADDRNOTAVAIL &&
|
||||
errno != ENXIO)
|
||||
|
@ -1647,15 +1745,16 @@ ipv6nd_expirera(void *arg)
|
|||
~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
|
||||
expired = true;
|
||||
} else {
|
||||
timespecsub(&expire, &now, <);
|
||||
if (!timespecisset(&next) ||
|
||||
timespeccmp(&next, <, >))
|
||||
next = lt;
|
||||
valid = true;
|
||||
ltime = ia->prefix_vltime - elapsed;
|
||||
if (next == 0 || ltime < next)
|
||||
next = ltime;
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out expiry for ND options */
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&rap->acquired, NULL);
|
||||
len = rap->data_len - sizeof(struct nd_router_advert);
|
||||
for (p = rap->data + sizeof(struct nd_router_advert);
|
||||
len >= sizeof(ndo);
|
||||
|
@ -1700,26 +1799,25 @@ ipv6nd_expirera(void *arg)
|
|||
|
||||
if (ltime == 0)
|
||||
continue;
|
||||
if (rap->doexpire) {
|
||||
expired = true;
|
||||
continue;
|
||||
}
|
||||
if (ltime == ND6_INFINITE_LIFETIME) {
|
||||
valid = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
lt.tv_sec = (time_t)ntohl(ltime);
|
||||
lt.tv_nsec = 0;
|
||||
timespecadd(&rap->acquired, <, &expire);
|
||||
if (timespeccmp(&now, &expire, >)) {
|
||||
ltime = ntohl(ltime);
|
||||
if (elapsed > ltime) {
|
||||
expired = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
timespecsub(&expire, &now, <);
|
||||
if (!timespecisset(&next) ||
|
||||
timespeccmp(&next, <, >))
|
||||
{
|
||||
next = lt;
|
||||
valid = true;
|
||||
}
|
||||
valid = true;
|
||||
ltime -= elapsed;
|
||||
if (next == 0 || ltime < next)
|
||||
next = ltime;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
|
@ -1731,11 +1829,12 @@ ipv6nd_expirera(void *arg)
|
|||
ipv6nd_free_ra(rap);
|
||||
}
|
||||
|
||||
if (timespecisset(&next))
|
||||
eloop_timeout_add_tv(ifp->ctx->eloop,
|
||||
&next, ipv6nd_expirera, ifp);
|
||||
if (next != 0)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
next, ipv6nd_expirera, ifp);
|
||||
if (expired) {
|
||||
logwarnx("%s: part of Router Advertisement expired", ifp->name);
|
||||
logwarnx("%s: part of a Router Advertisement expired",
|
||||
ifp->name);
|
||||
rt_build(ifp->ctx, AF_INET6);
|
||||
script_runreason(ifp, "ROUTERADVERT");
|
||||
}
|
||||
|
@ -1764,7 +1863,7 @@ ipv6nd_drop(struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
|
||||
{
|
||||
struct sockaddr_in6 *from = (struct sockaddr_in6 *)msg->msg_name;
|
||||
|
@ -1866,17 +1965,19 @@ ipv6nd_startrs1(void *arg)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (!(IN_PRIVSEP(ifp->ctx))) {
|
||||
#ifdef __sun
|
||||
if (ipv6nd_open(ifp) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
if (ipv6nd_open(ifp) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (ipv6nd_open(ifp->ctx) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
if (ipv6nd_open(ifp->ctx) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Always make a new probe as the underlying hardware
|
||||
* address could have changed. */
|
||||
|
@ -1894,7 +1995,7 @@ ipv6nd_startrs1(void *arg)
|
|||
void
|
||||
ipv6nd_startrs(struct interface *ifp)
|
||||
{
|
||||
struct timespec tv;
|
||||
unsigned int delay;
|
||||
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
||||
if (!(ifp->options->options & DHCPCD_INITIAL_DELAY)) {
|
||||
|
@ -1902,12 +2003,9 @@ ipv6nd_startrs(struct interface *ifp)
|
|||
return;
|
||||
}
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_nsec = (suseconds_t)arc4random_uniform(
|
||||
MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
|
||||
timespecnorm(&tv);
|
||||
delay = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY * MSEC_PER_SEC);
|
||||
logdebugx("%s: delaying IPv6 router solicitation for %0.1f seconds",
|
||||
ifp->name, timespec_to_double(&tv));
|
||||
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
|
||||
ifp->name, (float)delay / MSEC_PER_SEC);
|
||||
eloop_timeout_add_msec(ifp->ctx->eloop, delay, ipv6nd_startrs1, ifp);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* logerr: errx with logging
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -207,24 +207,20 @@ vlogmessage(int pri, const char *fmt, va_list args)
|
|||
if (!(ctx->log_opts & LOGERR_LOG))
|
||||
return len;
|
||||
|
||||
#ifdef SMALL
|
||||
#ifndef SMALL
|
||||
if (ctx->log_file != NULL &&
|
||||
(pri != LOG_DEBUG || (ctx->log_opts & LOGERR_DEBUG)))
|
||||
len = vlogprintf_r(ctx, ctx->log_file, fmt, args);
|
||||
#endif
|
||||
|
||||
vsyslog(pri, fmt, args);
|
||||
return len;
|
||||
#else
|
||||
if (ctx->log_file == NULL) {
|
||||
vsyslog(pri, fmt, args);
|
||||
return len;
|
||||
}
|
||||
if (pri == LOG_DEBUG && !(ctx->log_opts & LOGERR_DEBUG))
|
||||
return len;
|
||||
return vlogprintf_r(ctx, ctx->log_file, fmt, args);
|
||||
#endif
|
||||
}
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
__printflike(2, 3) static void
|
||||
__printflike(2, 3) void
|
||||
logmessage(int pri, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -244,8 +240,18 @@ vlogerrmessage(int pri, const char *fmt, va_list args)
|
|||
logmessage(pri, "%s: %s", buf, strerror(_errno));
|
||||
}
|
||||
|
||||
__printflike(2, 3) void
|
||||
logerrmessage(int pri, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vlogerrmessage(pri, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
logdebug(const char *fmt, ...)
|
||||
log_debug(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -255,7 +261,7 @@ logdebug(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
logdebugx(const char *fmt, ...)
|
||||
log_debugx(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -265,7 +271,7 @@ logdebugx(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
loginfo(const char *fmt, ...)
|
||||
log_info(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -275,7 +281,7 @@ loginfo(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
loginfox(const char *fmt, ...)
|
||||
log_infox(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -285,7 +291,7 @@ loginfox(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
logwarn(const char *fmt, ...)
|
||||
log_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -295,7 +301,7 @@ logwarn(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
logwarnx(const char *fmt, ...)
|
||||
log_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -305,7 +311,7 @@ logwarnx(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
logerr(const char *fmt, ...)
|
||||
log_err(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -315,7 +321,7 @@ logerr(const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
logerrx(const char *fmt, ...)
|
||||
log_errx(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
|
@ -324,6 +330,14 @@ logerrx(const char *fmt, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
loggetopts(void)
|
||||
{
|
||||
struct logctx *ctx = &_logctx;
|
||||
|
||||
return ctx->log_opts;
|
||||
}
|
||||
|
||||
void
|
||||
logsetopts(unsigned int opts)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
/* stSPDX-License-Identifier: BSD-2-Clause */
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
|
||||
* Copyright (c) 2006-2020 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -36,6 +36,7 @@
|
|||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -47,18 +48,15 @@
|
|||
#include "common.h"
|
||||
#include "dhcp.h"
|
||||
#include "dhcp6.h"
|
||||
#include "eloop.h"
|
||||
#include "if.h"
|
||||
#include "if-options.h"
|
||||
#include "ipv4ll.h"
|
||||
#include "ipv6nd.h"
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
#include "script.h"
|
||||
|
||||
/* Allow the OS to define another script env var name */
|
||||
#ifndef RC_SVCNAME
|
||||
#define RC_SVCNAME "RC_SVCNAME"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PATH "/usr/bin:/usr/sbin:/bin:/sbin"
|
||||
|
||||
static const char * const if_params[] = {
|
||||
|
@ -85,7 +83,7 @@ if_printoptions(void)
|
|||
printf(" - %s\n", *p);
|
||||
}
|
||||
|
||||
static int
|
||||
pid_t
|
||||
script_exec(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
|
@ -173,7 +171,7 @@ efprintf(FILE *fp, const char *fmt, ...)
|
|||
return r;
|
||||
}
|
||||
|
||||
static char **
|
||||
char **
|
||||
script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len)
|
||||
{
|
||||
char **env, **envp, *bufp, *endp;
|
||||
|
@ -216,14 +214,14 @@ script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len)
|
|||
}
|
||||
|
||||
static long
|
||||
make_env(const struct interface *ifp, const char *reason)
|
||||
make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp,
|
||||
const char *reason)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
FILE *fp;
|
||||
long buf_pos, i;
|
||||
char *path;
|
||||
int protocol = PROTO_LINK;
|
||||
const struct if_options *ifo = ifp->options;
|
||||
const struct if_options *ifo;
|
||||
const struct interface *ifp2;
|
||||
int af;
|
||||
#ifdef INET
|
||||
|
@ -262,6 +260,25 @@ make_env(const struct interface *ifp, const char *reason)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Needed for scripts */
|
||||
path = getenv("PATH");
|
||||
if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
|
||||
goto eexit;
|
||||
if (efprintf(fp, "reason=%s", reason) == -1)
|
||||
goto eexit;
|
||||
if (efprintf(fp, "pid=%d", getpid()) == -1)
|
||||
goto eexit;
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP && ctx->ps_user != NULL) {
|
||||
if (efprintf(fp, "chroot=%s", ctx->ps_user->pw_dir) == -1)
|
||||
goto eexit;
|
||||
}
|
||||
if (strcmp(reason, "CHROOT") == 0)
|
||||
goto make;
|
||||
#endif
|
||||
|
||||
ifo = ifp->options;
|
||||
#ifdef INET
|
||||
state = D_STATE(ifp);
|
||||
#ifdef IPV4LL
|
||||
|
@ -272,7 +289,10 @@ make_env(const struct interface *ifp, const char *reason)
|
|||
d6_state = D6_CSTATE(ifp);
|
||||
#endif
|
||||
if (strcmp(reason, "TEST") == 0) {
|
||||
if (1 == 2) {}
|
||||
if (1 == 2) {
|
||||
/* This space left intentionally blank
|
||||
* as all the below statements are optional. */
|
||||
}
|
||||
#ifdef INET6
|
||||
#ifdef DHCP6
|
||||
else if (d6_state && d6_state->new)
|
||||
|
@ -316,19 +336,11 @@ make_env(const struct interface *ifp, const char *reason)
|
|||
protocol = PROTO_DHCP;
|
||||
#endif
|
||||
|
||||
/* Needed for scripts */
|
||||
path = getenv("PATH");
|
||||
if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
|
||||
goto eexit;
|
||||
|
||||
if (efprintf(fp, "interface=%s", ifp->name) == -1)
|
||||
goto eexit;
|
||||
if (efprintf(fp, "reason=%s", reason) == -1)
|
||||
goto eexit;
|
||||
if (ifp->ctx->options & DHCPCD_DUMPLEASE)
|
||||
goto dumplease;
|
||||
if (efprintf(fp, "pid=%d", getpid()) == -1)
|
||||
goto eexit;
|
||||
if (efprintf(fp, "ifcarrier=%s",
|
||||
ifp->carrier == LINK_UNKNOWN ? "unknown" :
|
||||
ifp->carrier == LINK_UP ? "up" : "down") == -1)
|
||||
|
@ -492,6 +504,9 @@ dumplease:
|
|||
goto eexit;
|
||||
}
|
||||
|
||||
#ifdef PRIVSEP
|
||||
make:
|
||||
#endif
|
||||
/* Convert buffer to argv */
|
||||
fflush(fp);
|
||||
|
||||
|
@ -520,7 +535,7 @@ dumplease:
|
|||
if (script_buftoenv(ctx, ctx->script_buf, (size_t)buf_pos) == NULL)
|
||||
goto eexit;
|
||||
|
||||
return buf_pos - 1;
|
||||
return buf_pos;
|
||||
|
||||
eexit:
|
||||
logerr(__func__);
|
||||
|
@ -538,16 +553,15 @@ send_interface1(struct fd_list *fd, const struct interface *ifp,
|
|||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
long len;
|
||||
|
||||
len = make_env(ifp, reason);
|
||||
len = make_env(ifp->ctx, ifp, reason);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
return control_queue(fd, ctx->script_buf, (size_t)len, 1);
|
||||
return control_queue(fd, ctx->script_buf, (size_t)len, 1);
|
||||
}
|
||||
|
||||
int
|
||||
send_interface(struct fd_list *fd, const struct interface *ifp)
|
||||
send_interface(struct fd_list *fd, const struct interface *ifp, int af)
|
||||
{
|
||||
const char *reason;
|
||||
int retval = 0;
|
||||
#ifdef INET
|
||||
const struct dhcp_state *d;
|
||||
|
@ -556,80 +570,92 @@ send_interface(struct fd_list *fd, const struct interface *ifp)
|
|||
const struct dhcp6_state *d6;
|
||||
#endif
|
||||
|
||||
switch (ifp->carrier) {
|
||||
case LINK_UP:
|
||||
reason = "CARRIER";
|
||||
break;
|
||||
case LINK_DOWN:
|
||||
case LINK_DOWN_IFFUP:
|
||||
reason = "NOCARRIER";
|
||||
break;
|
||||
default:
|
||||
reason = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
if (send_interface1(fd, ifp, reason) == -1)
|
||||
retval = -1;
|
||||
#ifdef INET
|
||||
if (D_STATE_RUNNING(ifp)) {
|
||||
d = D_CSTATE(ifp);
|
||||
if (send_interface1(fd, ifp, d->reason) == -1)
|
||||
retval = -1;
|
||||
}
|
||||
#ifdef IPV4LL
|
||||
if (IPV4LL_STATE_RUNNING(ifp)) {
|
||||
if (send_interface1(fd, ifp, "IPV4LL") == -1)
|
||||
retval = -1;
|
||||
}
|
||||
#ifndef AF_LINK
|
||||
#define AF_LINK AF_PACKET
|
||||
#endif
|
||||
|
||||
if (af == AF_UNSPEC || af == AF_LINK) {
|
||||
const char *reason;
|
||||
|
||||
switch (ifp->carrier) {
|
||||
case LINK_UP:
|
||||
reason = "CARRIER";
|
||||
break;
|
||||
case LINK_DOWN:
|
||||
case LINK_DOWN_IFFUP:
|
||||
reason = "NOCARRIER";
|
||||
break;
|
||||
default:
|
||||
reason = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp, reason) == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
if (af == AF_UNSPEC || af == AF_INET) {
|
||||
if (D_STATE_RUNNING(ifp)) {
|
||||
d = D_CSTATE(ifp);
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp, d->reason) == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
#ifdef IPV4LL
|
||||
if (IPV4LL_STATE_RUNNING(ifp)) {
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp, "IPV4LL") == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
if (IPV6_STATE_RUNNING(ifp)) {
|
||||
if (send_interface1(fd, ifp, "STATIC6") == -1)
|
||||
retval = -1;
|
||||
}
|
||||
if (RS_STATE_RUNNING(ifp)) {
|
||||
if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
|
||||
retval = -1;
|
||||
}
|
||||
if (af == AF_UNSPEC || af == AF_INET6) {
|
||||
if (IPV6_STATE_RUNNING(ifp)) {
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp, "STATIC6") == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
if (RS_STATE_RUNNING(ifp)) {
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp,
|
||||
"ROUTERADVERT") == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
#ifdef DHCP6
|
||||
if (D6_STATE_RUNNING(ifp)) {
|
||||
d6 = D6_CSTATE(ifp);
|
||||
if (send_interface1(fd, ifp, d6->reason) == -1)
|
||||
retval = -1;
|
||||
}
|
||||
if (D6_STATE_RUNNING(ifp)) {
|
||||
d6 = D6_CSTATE(ifp);
|
||||
if (fd != NULL) {
|
||||
if (send_interface1(fd, ifp, d6->reason) == -1)
|
||||
retval = -1;
|
||||
} else
|
||||
retval++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
script_runreason(const struct interface *ifp, const char *reason)
|
||||
static int
|
||||
script_run(struct dhcpcd_ctx *ctx, char **argv)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
char *argv[2];
|
||||
pid_t pid;
|
||||
int status = 0;
|
||||
struct fd_list *fd;
|
||||
|
||||
if (ifp->options->script == NULL &&
|
||||
TAILQ_FIRST(&ifp->ctx->control_fds) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Make our env */
|
||||
if (make_env(ifp, reason) == -1) {
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ifp->options->script == NULL)
|
||||
goto send_listeners;
|
||||
|
||||
argv[0] = ifp->options->script;
|
||||
argv[1] = NULL;
|
||||
logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason);
|
||||
|
||||
pid = script_exec(ctx, argv, ctx->script_env);
|
||||
if (pid == -1)
|
||||
|
@ -652,6 +678,45 @@ script_runreason(const struct interface *ifp, const char *reason)
|
|||
__func__, argv[0], strsignal(WTERMSIG(status)));
|
||||
}
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
int
|
||||
script_runreason(const struct interface *ifp, const char *reason)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
char *argv[2];
|
||||
int status = 0;
|
||||
struct fd_list *fd;
|
||||
|
||||
if (ifp->options->script == NULL &&
|
||||
TAILQ_FIRST(&ifp->ctx->control_fds) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Make our env */
|
||||
if (make_env(ifp->ctx, ifp, reason) == -1) {
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ifp->options->script == NULL)
|
||||
goto send_listeners;
|
||||
|
||||
argv[0] = ifp->options->script;
|
||||
argv[1] = NULL;
|
||||
logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEP) {
|
||||
if (ps_root_script(ifp,
|
||||
ctx->script_buf, ctx->script_buflen) == -1)
|
||||
logerr(__func__);
|
||||
goto send_listeners;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = script_run(ctx, argv);
|
||||
|
||||
send_listeners:
|
||||
/* Send to our listeners */
|
||||
status = 0;
|
||||
|
@ -665,5 +730,25 @@ send_listeners:
|
|||
status = 1;
|
||||
}
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef PRIVSEP
|
||||
int
|
||||
script_runchroot(struct dhcpcd_ctx *ctx, char *script)
|
||||
{
|
||||
char *argv[2];
|
||||
|
||||
/* Make our env */
|
||||
if (make_env(ctx, NULL, "CHROOT") == -1) {
|
||||
logerr(__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
argv[0] = script;
|
||||
argv[1] = NULL;
|
||||
logdebugx("executing `%s' %s", argv[0], "CHROOT");
|
||||
|
||||
return script_run(ctx, argv);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue