mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-27 03:54:56 +08:00
Merge branch 'master' into manager_only
This commit is contained in:
commit
66811c7b9b
@ -78,7 +78,14 @@ static int _dhcpcd_rand_fd = -1; /* /dev/urandom fd */
|
||||
|
||||
static int _dhcpcd_getentropy(void *, size_t);
|
||||
static inline int _rs_allocate(struct _rs **, struct _rsx **);
|
||||
|
||||
/* dhcpcd needs to hold onto the fd at fork due to privsep */
|
||||
#if 0
|
||||
static inline void _rs_forkdetect(void);
|
||||
#else
|
||||
#define _rs_forkdetect()
|
||||
#define _rs_forkhandler()
|
||||
#endif
|
||||
|
||||
/* Inline "arc4random.h" */
|
||||
#include <sys/types.h>
|
||||
@ -89,7 +96,6 @@ static inline void _rs_rekey(u_char *dat, size_t datlen);
|
||||
/* dhcpcd isn't multithreaded */
|
||||
#define _ARC4_LOCK()
|
||||
#define _ARC4_UNLOCK()
|
||||
#define _ARC4_ATFORK(f)
|
||||
|
||||
static int
|
||||
_dhcpcd_getentropy(void *buf, size_t length)
|
||||
@ -126,6 +132,7 @@ _getentropy_fail(void)
|
||||
raise(SIGKILL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static volatile sig_atomic_t _rs_forked;
|
||||
|
||||
static inline void
|
||||
@ -148,6 +155,7 @@ _rs_forkdetect(void)
|
||||
memset(rs, 0, sizeof(*rs));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
|
||||
@ -163,7 +171,7 @@ _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
_ARC4_ATFORK(_rs_forkhandler);
|
||||
_rs_forkhandler();
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
77
compat/closefrom.c
Normal file
77
compat/closefrom.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2018
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __linux__
|
||||
# include <sys/syscall.h>
|
||||
# if defined(__NR_close_range) && !defined(SYS_close_range)
|
||||
# define SYS_close_range __NR_close_range
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__linux__) && defined(SYS_close_range)
|
||||
static inline int
|
||||
sys_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags)
|
||||
{
|
||||
|
||||
return (int)syscall(SYS_close_range, fd, max_fd, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Close all file descriptors greater than or equal to lowfd.
|
||||
* This is the expensive (fallback) method.
|
||||
*/
|
||||
static int
|
||||
closefrom_fallback(int lowfd)
|
||||
{
|
||||
int fd, maxfd;
|
||||
|
||||
#ifdef _SC_OPEN_MAX
|
||||
maxfd = (int)sysconf(_SC_OPEN_MAX);
|
||||
#else
|
||||
maxfd = getdtablesize();
|
||||
#endif
|
||||
if (maxfd == -1)
|
||||
return -1;
|
||||
|
||||
for (fd = lowfd; fd < maxfd; fd++)
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* * Close all file descriptors greater than or equal to lowfd.
|
||||
* * We try the fast way first, falling back on the slow method.
|
||||
* */
|
||||
void
|
||||
closefrom(int lowfd)
|
||||
{
|
||||
|
||||
#if defined(__linux__) && defined(SYS_close_range)
|
||||
if (sys_close_range((unsigned int)lowfd, UINT_MAX, 0) == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
closefrom_fallback(lowfd);
|
||||
}
|
24
compat/closefrom.h
Normal file
24
compat/closefrom.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2018
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef CLOSEFROM_H
|
||||
#define CLOSEFROM_H
|
||||
|
||||
void closefrom(int);
|
||||
|
||||
#endif
|
29
configure
vendored
29
configure
vendored
@ -33,6 +33,7 @@ STATIC=
|
||||
DEVS=
|
||||
EMBEDDED=
|
||||
AUTH=
|
||||
NTP=
|
||||
POLL=
|
||||
SMALL=
|
||||
SANITIZE=no
|
||||
@ -74,6 +75,8 @@ for x do
|
||||
--enable-privsep) PRIVSEP=yes;;
|
||||
--disable-seccomp) SECCOMP=no;;
|
||||
--enable-seccomp) SECCOMP=yes;;
|
||||
--disable-ntp) NTP=no;;
|
||||
--enable-ntp) NTP=yes;;
|
||||
--privsepuser) PRIVSEP_USER=$var;;
|
||||
--prefix) PREFIX=$var;prefix=$var;; # prefix is set for autotools compat
|
||||
--sysconfdir) SYSCONFDIR=$var;;
|
||||
@ -811,6 +814,28 @@ fi
|
||||
rm -f _clock_gettime.c _clock_gettime
|
||||
$abort && exit 1
|
||||
|
||||
if [ -z "$CLOSEFROM" ]; then
|
||||
printf "Testing for closefrom ... "
|
||||
cat <<EOF >_closefrom.c
|
||||
#include <unistd.h>
|
||||
int main(void) {
|
||||
closefrom(3);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if $XCC _closefrom.c -o _closefrom 2>&3; then
|
||||
CLOSEFROM=yes
|
||||
else
|
||||
CLOSEFROM=no
|
||||
fi
|
||||
echo "$CLOSEFROM"
|
||||
fi
|
||||
rm -f _closefrom.c _closefrom
|
||||
if [ "$CLOSEFROM" = no ]; then
|
||||
echo "COMPAT_SRCS+= compat/closefrom.c" >>$CONFIG_MK
|
||||
echo "#include \"compat/closefrom.h\"" >>$CONFIG_H
|
||||
fi
|
||||
|
||||
printf "Testing ioctl request type ... "
|
||||
cat <<EOF >_ioctl.c
|
||||
#include <sys/ioctl.h>
|
||||
@ -1921,6 +1946,10 @@ if ! $HOOKSET; then
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ "$NTP" = yes ]; then
|
||||
# --enable-ntp
|
||||
echo "UNCOMMENT_NTP= yes" >>$CONFIG_MK
|
||||
fi
|
||||
|
||||
echo >>$CONFIG_H
|
||||
echo "#endif /*CONFIG_H*/">>$CONFIG_H
|
||||
|
@ -106,8 +106,8 @@ if [ "$ifwireless" = "1" ] && \
|
||||
command -v wpa_cli >/dev/null 2>&1
|
||||
then
|
||||
case "$reason" in
|
||||
PREINIT) wpa_supplicant_start;;
|
||||
RECONFIGURE) wpa_supplicant_reconfigure;;
|
||||
DEPARTED) wpa_supplicant_stop;;
|
||||
PREINIT) wpa_supplicant_start;;
|
||||
RECONFIGURE) wpa_supplicant_reconfigure;;
|
||||
DEPARTED|STOPPED) wpa_supplicant_stop;;
|
||||
esac
|
||||
fi
|
||||
|
@ -118,7 +118,7 @@ set_hostname()
|
||||
*) hshort=true;;
|
||||
esac
|
||||
|
||||
need_hostname || return
|
||||
need_hostname || return 0
|
||||
|
||||
if [ -n "$new_fqdn" ]; then
|
||||
if ${hfqdn} || ! ${hshort}; then
|
||||
|
10
src/Makefile
10
src/Makefile
@ -96,8 +96,14 @@ _maninstall: ${MAN5} ${MAN8}
|
||||
_confinstall:
|
||||
${INSTALL} -d ${DESTDIR}${SYSCONFDIR}
|
||||
# Install a new default config if not present
|
||||
test -e ${DESTDIR}${SYSCONFDIR}/dhcpcd.conf || \
|
||||
${INSTALL} -m ${CONFMODE} dhcpcd.conf ${DESTDIR}${SYSCONFDIR}
|
||||
if ! [ -e ${DESTDIR}${SYSCONFDIR}/dhcpcd.conf ]; then \
|
||||
${INSTALL} -m ${CONFMODE} dhcpcd.conf ${DESTDIR}${SYSCONFDIR}; \
|
||||
if [ "${UNCOMMENT_NTP}" = yes ]; then \
|
||||
${SED} -i \
|
||||
-e 's/#option ntp_servers/option ntp_servers/' \
|
||||
${DESTDIR}/${SYSCONFDIR}/dhcpcd.conf; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
eginstall:
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#define DEFS_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "10.0.6"
|
||||
#define VERSION "10.0.8"
|
||||
|
||||
#ifndef PRIVSEP_USER
|
||||
# define PRIVSEP_USER "_" PACKAGE
|
||||
|
39
src/dhcp.c
39
src/dhcp.c
@ -1867,13 +1867,13 @@ dhcp_discover(void *arg)
|
||||
dhcp_new_xid(ifp);
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
||||
if (!(state->added & STATE_EXPIRED)) {
|
||||
if (ifo->fallback)
|
||||
if (ifo->fallback && ifo->fallback_time)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
ifo->reboot, dhcp_fallback, ifp);
|
||||
ifo->fallback_time, dhcp_fallback, ifp);
|
||||
#ifdef IPV4LL
|
||||
else if (ifo->options & DHCPCD_IPV4LL)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
ifo->reboot, ipv4ll_start, ifp);
|
||||
ifo->ipv4ll_time, ipv4ll_start, ifp);
|
||||
#endif
|
||||
}
|
||||
if (ifo->options & DHCPCD_REQUEST)
|
||||
@ -1904,11 +1904,13 @@ dhcp_request(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct dhcp_state *state = D_STATE(ifp);
|
||||
struct if_options *ifo = ifp->options;
|
||||
|
||||
state->state = DHS_REQUEST;
|
||||
// Handle the server being silent to our request.
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, ifp->options->reboot,
|
||||
dhcp_requestfailed, ifp);
|
||||
if (ifo->request_time != 0)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, ifo->request_time,
|
||||
dhcp_requestfailed, ifp);
|
||||
send_request(ifp);
|
||||
}
|
||||
|
||||
@ -1934,7 +1936,11 @@ dhcp_expire(void *arg)
|
||||
static void
|
||||
dhcp_decline(struct interface *ifp)
|
||||
{
|
||||
struct dhcp_state *state = D_STATE(ifp);
|
||||
|
||||
// Set the expired state so we send over BPF as this could be
|
||||
// an address defence failure.
|
||||
state->added |= STATE_EXPIRED;
|
||||
send_message(ifp, DHCP_DECLINE, NULL);
|
||||
}
|
||||
#endif
|
||||
@ -2085,8 +2091,12 @@ static void
|
||||
dhcp_arp_defend_failed(struct arp_state *astate)
|
||||
{
|
||||
struct interface *ifp = astate->iface;
|
||||
struct dhcp_state *state = D_STATE(ifp);
|
||||
|
||||
if (!(ifp->options->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
|
||||
dhcp_decline(ifp);
|
||||
dhcp_drop(ifp, "EXPIRED");
|
||||
dhcp_unlink(ifp->ctx, state->leasefile);
|
||||
dhcp_start1(ifp);
|
||||
}
|
||||
#endif
|
||||
@ -2677,7 +2687,7 @@ dhcp_reboot(struct interface *ifp)
|
||||
/* Need to add this before dhcp_expire and friends. */
|
||||
if (!ifo->fallback && ifo->options & DHCPCD_IPV4LL)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
ifo->reboot, ipv4ll_start, ifp);
|
||||
ifo->ipv4ll_time, ipv4ll_start, ifp);
|
||||
#endif
|
||||
|
||||
if (ifo->options & DHCPCD_LASTLEASE && state->lease.frominfo)
|
||||
@ -3134,8 +3144,8 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
|
||||
|
||||
if (has_option_mask(ifo->requestmask, DHO_IPV6_PREFERRED_ONLY)) {
|
||||
if (get_option_uint32(ifp->ctx, &v6only_time, bootp, bootp_len,
|
||||
DHO_IPV6_PREFERRED_ONLY) == 0 &&
|
||||
(state->state == DHS_DISCOVER || state->state == DHS_REBOOT))
|
||||
DHO_IPV6_PREFERRED_ONLY) == 0 && (state->state == DHS_DISCOVER ||
|
||||
state->state == DHS_REBOOT || state->state == DHS_NONE))
|
||||
{
|
||||
char v6msg[128];
|
||||
|
||||
@ -3443,12 +3453,6 @@ dhcp_handlebootp(struct interface *ifp, struct bootp *bootp, size_t len,
|
||||
{
|
||||
size_t v;
|
||||
|
||||
if (len < offsetof(struct bootp, vend)) {
|
||||
logerrx("%s: truncated packet (%zu) from %s",
|
||||
ifp->name, len, inet_ntoa(*from));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unlikely, but appeases sanitizers. */
|
||||
if (len > FRAMELEN_MAX) {
|
||||
logerrx("%s: packet exceeded frame length (%zu) from %s",
|
||||
@ -3581,6 +3585,13 @@ dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iov->iov_len < offsetof(struct bootp, vend)) {
|
||||
logerrx("%s: truncated packet (%zu) from %s",
|
||||
ifp->name, iov->iov_len, inet_ntoa(from->sin_addr));
|
||||
return;
|
||||
}
|
||||
|
||||
state = D_CSTATE(ifp);
|
||||
if (state == NULL) {
|
||||
/* Try re-directing it to another interface. */
|
||||
|
67
src/dhcp6.c
67
src/dhcp6.c
@ -180,6 +180,7 @@ static const char * const dhcp6_statuses[] = {
|
||||
static void dhcp6_bind(struct interface *, const char *, const char *);
|
||||
static void dhcp6_failinform(void *);
|
||||
static void dhcp6_startdecline(struct interface *);
|
||||
static void dhcp6_startrequest(struct interface *);
|
||||
|
||||
#ifdef SMALL
|
||||
#define dhcp6_hasprefixdelegation(a) (0)
|
||||
@ -1416,10 +1417,37 @@ dhcp6_sendinform(void *arg)
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_senddiscover(void *arg)
|
||||
dhcp6_senddiscover2(void *arg)
|
||||
{
|
||||
|
||||
dhcp6_sendmessage(arg, dhcp6_senddiscover);
|
||||
dhcp6_sendmessage(arg, dhcp6_senddiscover2);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_senddiscover1(void *arg)
|
||||
{
|
||||
/*
|
||||
* So the initial RT has elapsed.
|
||||
* If we have any ADVERTs we can now REQUEST them.
|
||||
* RFC 8415 15 and 18.2.1
|
||||
*/
|
||||
struct interface *ifp = arg;
|
||||
struct dhcp6_state *state = D6_STATE(ifp);
|
||||
|
||||
if (state->recv == NULL || state->recv->type != DHCP6_ADVERTISE)
|
||||
dhcp6_sendmessage(arg, dhcp6_senddiscover2);
|
||||
else
|
||||
dhcp6_startrequest(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_senddiscover(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct dhcp6_state *state = D6_STATE(ifp);
|
||||
|
||||
dhcp6_sendmessage(arg,
|
||||
state->IMD != 0 ? dhcp6_senddiscover : dhcp6_senddiscover1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1878,7 +1906,6 @@ dhcp6_startrebind(void *arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dhcp6_startrequest(struct interface *ifp)
|
||||
{
|
||||
@ -3431,6 +3458,16 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom,
|
||||
valid_op = false;
|
||||
break;
|
||||
}
|
||||
if (state->recv_len && state->recv->type == DHCP6_ADVERTISE) {
|
||||
/* We already have an advertismemnt.
|
||||
* RFC 8415 says we have to wait for the IRT to elapse.
|
||||
* To keep the same behaviour we won't do anything with
|
||||
* this. In the future we should make a lists of
|
||||
* ADVERTS and pick the "best" one. */
|
||||
logdebugx("%s: discarding ADVERTISEMENT from %s",
|
||||
ifp->name, sfrom);
|
||||
return;
|
||||
}
|
||||
/* RFC7083 */
|
||||
o = dhcp6_findmoption(r, len, D6_OPTION_SOL_MAX_RT, &ol);
|
||||
if (o && ol == sizeof(uint32_t)) {
|
||||
@ -3556,7 +3593,7 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom,
|
||||
else
|
||||
loginfox("%s: ADV %s from %s",
|
||||
ifp->name, ia->saddr, sfrom);
|
||||
dhcp6_startrequest(ifp);
|
||||
// We will request when the IRT elapses
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3739,7 +3776,7 @@ dhcp6_openraw(void)
|
||||
{
|
||||
int fd, v;
|
||||
|
||||
fd = socket(PF_INET6, SOCK_RAW | SOCK_CXNB, IPPROTO_UDP);
|
||||
fd = xsocket(PF_INET6, SOCK_RAW | SOCK_CXNB, IPPROTO_UDP);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
@ -3913,20 +3950,16 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state)
|
||||
case DH6S_INIT:
|
||||
goto gogogo;
|
||||
case DH6S_INFORM:
|
||||
/* RFC 8415 21.23
|
||||
* If D6_OPTION_INFO_REFRESH_TIME does not exist
|
||||
* then we MUST refresh by IRT_DEFAULT seconds
|
||||
* and should not be influenced by only the
|
||||
* pl/vl time of the RA changing. */
|
||||
if (state->state == DH6S_INIT ||
|
||||
state->state == DH6S_INFORMED ||
|
||||
(state->state == DH6S_DISCOVER &&
|
||||
!(ifp->options->options & DHCPCD_IA_FORCED) &&
|
||||
!ipv6nd_hasradhcp(ifp, true)))
|
||||
{
|
||||
/* We don't want log spam when the RA
|
||||
* has just adjusted it's prefix times. */
|
||||
if (state->state != DH6S_INFORMED) {
|
||||
state->new_start = true;
|
||||
state->failed = false;
|
||||
}
|
||||
dhcp6_startinform(ifp);
|
||||
}
|
||||
break;
|
||||
case DH6S_REQUEST:
|
||||
if (ifp->options->options & DHCPCD_DHCP6 &&
|
||||
@ -4178,6 +4211,7 @@ dhcp6_env(FILE *fp, const char *prefix, const struct interface *ifp,
|
||||
#ifndef SMALL
|
||||
const struct dhcp6_state *state;
|
||||
const struct ipv6_addr *ap;
|
||||
bool first;
|
||||
#endif
|
||||
|
||||
if (m == NULL)
|
||||
@ -4279,10 +4313,13 @@ delegated:
|
||||
return 1;
|
||||
if (fprintf(fp, "%s_delegated_dhcp6_prefix=", prefix) == -1)
|
||||
return -1;
|
||||
first = true;
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->delegating_prefix == NULL)
|
||||
continue;
|
||||
if (ap != TAILQ_FIRST(&state->addrs)) {
|
||||
if (first)
|
||||
first = false;
|
||||
else {
|
||||
if (fputc(' ', fp) == EOF)
|
||||
return -1;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ define 1 request ipaddress subnet_mask
|
||||
# RFC3442 states that the CSR has to come before all other routes
|
||||
# For completeness we also specify static routes then routers
|
||||
define 121 rfc3442 classless_static_routes
|
||||
define 2 uint32 time_offset
|
||||
define 2 int32 time_offset
|
||||
define 3 request array ipaddress routers
|
||||
define 4 array ipaddress time_servers
|
||||
define 5 array ipaddress ien116_name_servers
|
||||
@ -333,7 +333,16 @@ encap 255 flag global
|
||||
|
||||
# Options 222 and 223 are unused, RFC3942
|
||||
|
||||
# Options 224-254 are reserved for Private Use
|
||||
# Options 224-254 are reserved for site-specific use by RFC3942.
|
||||
# For historical reasons, some of these options have well known
|
||||
# definitions and we implement those definitions here.
|
||||
# Site-specific options are designed to be configured by the end user
|
||||
# if needed and any configuration here may change in the future.
|
||||
|
||||
# Option 245 is an IANA assigned private number used by Azure DHCP
|
||||
# servers to provide the IPv4 address of the Azure WireServer endpoint
|
||||
# to virtual machines hosted in Azure.
|
||||
define 245 ipaddress azureendpoint
|
||||
|
||||
# Option 249 is an IANA assigned private number used by Windows DHCP servers
|
||||
# to provide the exact same information as option 121, classless static routes
|
||||
@ -344,6 +353,38 @@ define 249 rfc3442 ms_classless_static_routes
|
||||
# Apparently the code was assigned by agreement of the DHC working group chair.
|
||||
define 252 uri wpad_url
|
||||
|
||||
define 224 binhex site_specific_224
|
||||
define 225 binhex site_specific_225
|
||||
define 226 binhex site_specific_226
|
||||
define 227 binhex site_specific_227
|
||||
define 228 binhex site_specific_228
|
||||
define 229 binhex site_specific_229
|
||||
define 230 binhex site_specific_230
|
||||
define 231 binhex site_specific_231
|
||||
define 232 binhex site_specific_232
|
||||
define 233 binhex site_specific_233
|
||||
define 234 binhex site_specific_234
|
||||
define 235 binhex site_specific_235
|
||||
define 236 binhex site_specific_236
|
||||
define 237 binhex site_specific_237
|
||||
define 238 binhex site_specific_238
|
||||
define 239 binhex site_specific_239
|
||||
define 240 binhex site_specific_240
|
||||
define 241 binhex site_specific_241
|
||||
define 242 binhex site_specific_242
|
||||
define 243 binhex site_specific_243
|
||||
define 244 binhex site_specific_244
|
||||
#Option 245 has a custom definition above.
|
||||
define 246 binhex site_specific_246
|
||||
define 247 binhex site_specific_247
|
||||
define 248 binhex site_specific_248
|
||||
#Option 249 has a custom definition above.
|
||||
define 250 binhex site_specific_250
|
||||
define 251 binhex site_specific_251
|
||||
#Option 252 has a custom definition above.
|
||||
define 253 binhex site_specific_253
|
||||
define 254 binhex site_specific_254
|
||||
|
||||
# Option 255 End
|
||||
|
||||
##############################################################################
|
||||
|
76
src/dhcpcd.c
76
src/dhcpcd.c
@ -390,30 +390,43 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
dhcpcd_drop(struct interface *ifp, int stop)
|
||||
dhcpcd_drop_af(struct interface *ifp, int stop, int af)
|
||||
{
|
||||
|
||||
if (af == AF_UNSPEC || af == AF_INET6) {
|
||||
#ifdef DHCP6
|
||||
dhcp6_drop(ifp, stop ? NULL : "EXPIRE6");
|
||||
dhcp6_drop(ifp, stop ? NULL : "EXPIRE6");
|
||||
#endif
|
||||
#ifdef INET6
|
||||
ipv6nd_drop(ifp);
|
||||
ipv6_drop(ifp);
|
||||
ipv6nd_drop(ifp);
|
||||
ipv6_drop(ifp);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (af == AF_UNSPEC || af == AF_INET) {
|
||||
#ifdef IPV4LL
|
||||
ipv4ll_drop(ifp);
|
||||
ipv4ll_drop(ifp);
|
||||
#endif
|
||||
#ifdef INET
|
||||
dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
|
||||
dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
|
||||
#endif
|
||||
#ifdef ARP
|
||||
arp_drop(ifp);
|
||||
arp_drop(ifp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(DHCP6) && !defined(DHCP)
|
||||
UNUSED(stop);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
dhcpcd_drop(struct interface *ifp, int stop)
|
||||
{
|
||||
|
||||
dhcpcd_drop_af(ifp, stop, AF_UNSPEC);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_interface(struct interface *ifp, const char *reason)
|
||||
{
|
||||
@ -1490,7 +1503,8 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
|
||||
int argc, char **argv)
|
||||
{
|
||||
struct interface *ifp;
|
||||
unsigned long long opts;
|
||||
struct if_options *ifo;
|
||||
unsigned long long opts, orig_opts;
|
||||
int opt, oi, oifind, do_reboot, do_renew, af = AF_UNSPEC;
|
||||
size_t len, l, nifaces;
|
||||
char *tmp, *p;
|
||||
@ -1619,20 +1633,40 @@ dumperr:
|
||||
}
|
||||
|
||||
if (opts & (DHCPCD_EXITING | DHCPCD_RELEASE)) {
|
||||
if (oifind == argc) {
|
||||
if (oifind == argc && af == AF_UNSPEC) {
|
||||
stop_all_interfaces(ctx, opts);
|
||||
eloop_exit(ctx->eloop, EXIT_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
for (oi = oifind; oi < argc; oi++) {
|
||||
if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
if (!ifp->active)
|
||||
continue;
|
||||
ifp->options->options |= opts;
|
||||
for (oi = oifind; oi < argc; oi++) {
|
||||
if (strcmp(ifp->name, argv[oi]) == 0)
|
||||
break;
|
||||
}
|
||||
if (oi == argc)
|
||||
continue;
|
||||
|
||||
ifo = ifp->options;
|
||||
orig_opts = ifo->options;
|
||||
ifo->options |= opts;
|
||||
if (opts & DHCPCD_RELEASE)
|
||||
ifp->options->options &= ~DHCPCD_PERSISTENT;
|
||||
stop_interface(ifp, NULL);
|
||||
ifo->options &= ~DHCPCD_PERSISTENT;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
ifo->options &= ~DHCPCD_IPV4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
ifo->options &= ~DHCPCD_IPV6;
|
||||
break;
|
||||
}
|
||||
if (af != AF_UNSPEC)
|
||||
dhcpcd_drop_af(ifp, 1, af);
|
||||
else
|
||||
stop_interface(ifp, NULL);
|
||||
ifo->options = orig_opts;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1925,6 +1959,7 @@ main(int argc, char **argv, char **envp)
|
||||
}
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
ifo = NULL;
|
||||
ctx.cffile = CONFIG;
|
||||
@ -1954,7 +1989,7 @@ main(int argc, char **argv, char **envp)
|
||||
ctx.dhcp6_wfd = -1;
|
||||
#endif
|
||||
#ifdef PRIVSEP
|
||||
ctx.ps_log_fd = -1;
|
||||
ctx.ps_log_fd = ctx.ps_log_root_fd = -1;
|
||||
TAILQ_INIT(&ctx.ps_processes);
|
||||
#endif
|
||||
|
||||
@ -2356,9 +2391,14 @@ printpidfile:
|
||||
goto run_loop;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FD
|
||||
loginfox("forkfd %d", ctx.fork_fd);
|
||||
#endif
|
||||
|
||||
/* We have now forked, setsid, forked once more.
|
||||
* From this point on, we are the controlling daemon. */
|
||||
logdebugx("spawned manager process on PID %d", getpid());
|
||||
|
||||
start_manager:
|
||||
ctx.options |= DHCPCD_STARTED;
|
||||
if ((pid = pidfile_lock(PIDFILE)) != 0) {
|
||||
@ -2555,10 +2595,6 @@ exit1:
|
||||
free(ctx.script_env);
|
||||
rt_dispose(&ctx);
|
||||
free(ctx.duid);
|
||||
if (ctx.link_fd != -1) {
|
||||
eloop_event_delete(ctx.eloop, ctx.link_fd);
|
||||
close(ctx.link_fd);
|
||||
}
|
||||
if_closesockets(&ctx);
|
||||
free_globals(&ctx);
|
||||
#ifdef INET6
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd December 21, 2023
|
||||
.Dd May 24, 2024
|
||||
.Dt DHCPCD.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -305,6 +305,10 @@ You can use this option to stop this from happening.
|
||||
.It Ic fallback Ar profile
|
||||
Fall back to using this profile if DHCP fails.
|
||||
This allows you to configure a static profile instead of using ZeroConf.
|
||||
.It Ic fallback_time Ar seconds
|
||||
Start fallback after
|
||||
.Ar seconds .
|
||||
The default is 5 seconds.
|
||||
.It Ic hostname Ar name
|
||||
Sends the hostname
|
||||
.Ar name
|
||||
@ -442,6 +446,11 @@ encodes the FQDN hostname as specified in
|
||||
.It Ic interface Ar interface
|
||||
Subsequent options are only parsed for this
|
||||
.Ar interface .
|
||||
.It Ic ipv4ll_time Ar seconds
|
||||
Wait for
|
||||
.Ar seconds
|
||||
before starting IPv4LL.
|
||||
The default is 5 seconds.
|
||||
.It Ic ipv6ra_autoconf
|
||||
Generate SLAAC addresses for each Prefix advertised by an IPv6
|
||||
Router Advertisement message with the Auto flag set.
|
||||
@ -649,6 +658,11 @@ Use
|
||||
.Ar script
|
||||
instead of the default
|
||||
.Pa @SCRIPT@ .
|
||||
.It Ic request_time Ar seconds
|
||||
Request the lease for
|
||||
.Ar seconds
|
||||
before going back to DISCOVER.
|
||||
The default is 180 seconds.
|
||||
.It Ic ssid Ar ssid
|
||||
Subsequent options are only parsed for this wireless
|
||||
.Ar ssid .
|
||||
|
26
src/if-bsd.c
26
src/if-bsd.c
@ -197,6 +197,18 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
||||
&n, sizeof(n)) == -1)
|
||||
logerr("%s: SO_USELOOPBACK", __func__);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ctx->options & DHCPCD_PRIVSEPROOT) {
|
||||
/* We only want to write to this socket, so set
|
||||
* a small as possible buffer size. */
|
||||
socklen_t smallbuf = 1;
|
||||
|
||||
if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_RCVBUF,
|
||||
&smallbuf, (socklen_t)sizeof(smallbuf)) == -1)
|
||||
logerr("%s: setsockopt(SO_RCVBUF)", __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RO_MSGFILTER)
|
||||
if (setsockopt(ctx->link_fd, PF_ROUTE, RO_MSGFILTER,
|
||||
&msgfilter, sizeof(msgfilter)) == -1)
|
||||
@ -220,9 +232,8 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
||||
ps_rights_limit_fd_sockopt(ctx->link_fd);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */
|
||||
priv->pf_link_fd = socket(PF_LINK, SOCK_DGRAM, 0);
|
||||
priv->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0);
|
||||
if (priv->pf_link_fd == -1)
|
||||
logerr("%s: socket(PF_LINK)", __func__);
|
||||
#endif
|
||||
@ -235,13 +246,20 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
|
||||
struct priv *priv;
|
||||
|
||||
priv = (struct priv *)ctx->priv;
|
||||
if (priv == NULL)
|
||||
return;
|
||||
|
||||
#ifdef INET6
|
||||
if (priv->pf_inet6_fd != -1)
|
||||
if (priv->pf_inet6_fd != -1) {
|
||||
close(priv->pf_inet6_fd);
|
||||
priv->pf_inet6_fd = -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */
|
||||
if (priv->pf_link_fd != -1)
|
||||
if (priv->pf_link_fd != -1) {
|
||||
close(priv->pf_link_fd);
|
||||
priv->pf_link_fd = -1;
|
||||
}
|
||||
#endif
|
||||
free(priv);
|
||||
ctx->priv = NULL;
|
||||
|
@ -69,7 +69,7 @@ if_getssid_wext(const char *ifname, uint8_t *ssid)
|
||||
int s, retval;
|
||||
struct iwreq iwr;
|
||||
|
||||
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
if ((s = xsocket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return -1;
|
||||
memset(&iwr, 0, sizeof(iwr));
|
||||
strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
|
||||
|
@ -500,15 +500,22 @@ setup_priv:
|
||||
void
|
||||
if_closesockets_os(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
struct priv *priv;
|
||||
struct priv *priv = ctx->priv;
|
||||
|
||||
if (ctx->priv != NULL) {
|
||||
priv = (struct priv *)ctx->priv;
|
||||
if (priv->route_fd != -1)
|
||||
close(priv->route_fd);
|
||||
if (priv->generic_fd != -1)
|
||||
close(priv->generic_fd);
|
||||
if (priv == NULL)
|
||||
return;
|
||||
|
||||
if (priv->route_fd != -1) {
|
||||
close(priv->route_fd);
|
||||
priv->route_fd = -1;
|
||||
}
|
||||
if (priv->generic_fd != -1) {
|
||||
close(priv->generic_fd);
|
||||
priv->generic_fd = -1;
|
||||
}
|
||||
|
||||
free(priv);
|
||||
ctx->priv = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@ -2154,17 +2161,16 @@ if_setup_inet6(const struct interface *ifp)
|
||||
int ra;
|
||||
char path[256];
|
||||
|
||||
/* The kernel cannot make stable private addresses.
|
||||
/* Modern linux kernels can make a stable private address.
|
||||
* However, a lot of distros ship newer kernel headers than
|
||||
* the kernel itself so sweep that error under the table. */
|
||||
* the kernel itself so we sweep that error under the table
|
||||
* from old kernels and just make them ourself regardless. */
|
||||
if (if_disable_autolinklocal(ctx, ifp->index) == -1 &&
|
||||
errno != ENODEV && errno != ENOTSUP && errno != EINVAL)
|
||||
logdebug("%s: if_disable_autolinklocal", ifp->name);
|
||||
|
||||
/*
|
||||
* If not doing autoconf, don't disable the kernel from doing it.
|
||||
* If we need to, we should have another option actively disable it.
|
||||
*/
|
||||
/* If not doing autoconf, don't disable the kernel from doing it.
|
||||
* If we need to, we should have another option actively disable it. */
|
||||
if (!(ifp->options->options & DHCPCD_IPV6RS))
|
||||
return;
|
||||
|
||||
|
@ -169,6 +169,9 @@ const struct option cf_options[] = {
|
||||
{"configure", no_argument, NULL, O_CONFIGURE},
|
||||
{"noconfigure", no_argument, NULL, O_NOCONFIGURE},
|
||||
{"arp_persistdefence", no_argument, NULL, O_ARP_PERSISTDEFENCE},
|
||||
{"request_time", required_argument, NULL, O_REQUEST_TIME},
|
||||
{"fallback_time", required_argument, NULL, O_FALLBACK_TIME},
|
||||
{"ipv4ll_time", required_argument, NULL, O_IPV4LL_TIME},
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
@ -2337,6 +2340,35 @@ invalid_token:
|
||||
case O_ARP_PERSISTDEFENCE:
|
||||
ifo->options |= DHCPCD_ARP_PERSISTDEFENCE;
|
||||
break;
|
||||
case O_REQUEST_TIME:
|
||||
ARG_REQUIRED;
|
||||
ifo->request_time =
|
||||
(uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
if (e) {
|
||||
logerrx("invalid request time: %s", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
#ifdef INET
|
||||
case O_FALLBACK_TIME:
|
||||
ARG_REQUIRED;
|
||||
ifo->request_time =
|
||||
(uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
if (e) {
|
||||
logerrx("invalid fallback time: %s", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case O_IPV4LL_TIME:
|
||||
ARG_REQUIRED;
|
||||
ifo->ipv4ll_time =
|
||||
(uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e);
|
||||
if (e) {
|
||||
logerrx("invalid ipv4ll time: %s", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -2420,6 +2452,11 @@ default_config(struct dhcpcd_ctx *ctx)
|
||||
ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
|
||||
ifo->timeout = DEFAULT_TIMEOUT;
|
||||
ifo->reboot = DEFAULT_REBOOT;
|
||||
ifo->request_time = DEFAULT_REQUEST;
|
||||
#ifdef INET
|
||||
ifo->fallback_time = DEFAULT_FALLBACK;
|
||||
ifo->ipv4ll_time = DEFAULT_IPV4LL;
|
||||
#endif
|
||||
ifo->metric = -1;
|
||||
ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
|
||||
rb_tree_init(&ifo->routes, &rt_compare_list_ops);
|
||||
@ -2461,7 +2498,7 @@ read_config(struct dhcpcd_ctx *ctx,
|
||||
default_options |= DHCPCD_CONFIGURE | DHCPCD_DAEMONISE |
|
||||
DHCPCD_GATEWAY;
|
||||
#ifdef INET
|
||||
skip = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
skip = xsocket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (skip != -1) {
|
||||
close(skip);
|
||||
default_options |= DHCPCD_IPV4 | DHCPCD_ARP |
|
||||
@ -2469,7 +2506,7 @@ read_config(struct dhcpcd_ctx *ctx,
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
skip = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
skip = xsocket(PF_INET6, SOCK_DGRAM, 0);
|
||||
if (skip != -1) {
|
||||
close(skip);
|
||||
default_options |= DHCPCD_IPV6 | DHCPCD_IPV6RS |
|
||||
|
@ -49,6 +49,9 @@
|
||||
|
||||
#define DEFAULT_TIMEOUT 30
|
||||
#define DEFAULT_REBOOT 5
|
||||
#define DEFAULT_REQUEST 180 /* secs to request, mirror DHCP6 */
|
||||
#define DEFAULT_FALLBACK 5 /* secs until fallback */
|
||||
#define DEFAULT_IPV4LL 5 /* secs until ipv4ll */
|
||||
|
||||
#ifndef HOSTNAME_MAX_LEN
|
||||
#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */
|
||||
@ -185,6 +188,9 @@
|
||||
#define O_NOCONFIGURE O_BASE + 51
|
||||
#define O_RANDOMISE_HWADDR O_BASE + 52
|
||||
#define O_ARP_PERSISTDEFENCE O_BASE + 53
|
||||
#define O_REQUEST_TIME O_BASE + 54
|
||||
#define O_FALLBACK_TIME O_BASE + 55
|
||||
#define O_IPV4LL_TIME O_BASE + 56
|
||||
|
||||
extern const struct option cf_options[];
|
||||
|
||||
@ -236,6 +242,9 @@ struct if_options {
|
||||
uint32_t leasetime;
|
||||
uint32_t timeout;
|
||||
uint32_t reboot;
|
||||
uint32_t request_time;
|
||||
uint32_t fallback_time;
|
||||
uint32_t ipv4ll_time;
|
||||
unsigned long long options;
|
||||
bool randomise_hwaddr;
|
||||
|
||||
|
@ -154,7 +154,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
||||
* We will fail noisily elsewhere anyway. */
|
||||
#endif
|
||||
|
||||
ctx->link_fd = socket(PF_ROUTE,
|
||||
ctx->link_fd = xsocket(PF_ROUTE,
|
||||
SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
||||
|
||||
if (ctx->link_fd == -1) {
|
||||
@ -180,12 +180,13 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
|
||||
struct priv *priv;
|
||||
|
||||
priv = (struct priv *)ctx->priv;
|
||||
if (priv->pf_inet6_fd != -1)
|
||||
if (priv && priv->pf_inet6_fd != -1)
|
||||
close(priv->pf_inet6_fd);
|
||||
#endif
|
||||
|
||||
/* each interface should have closed itself */
|
||||
free(ctx->priv);
|
||||
ctx->priv = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@ -727,7 +728,7 @@ if_route_get(struct dhcpcd_ctx *ctx, struct rt *rt)
|
||||
|
||||
if_route0(ctx, &rtm, RTM_GET, rt);
|
||||
rt = NULL;
|
||||
s = socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 0);
|
||||
s = xsocket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 0);
|
||||
if (s == -1)
|
||||
return NULL;
|
||||
if (write(s, &rtm, rtm.hdr.rtm_msglen) == -1)
|
||||
|
29
src/if.c
29
src/if.c
@ -132,17 +132,18 @@ void
|
||||
if_closesockets(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
|
||||
if (ctx->pf_inet_fd != -1)
|
||||
close(ctx->pf_inet_fd);
|
||||
#ifdef PF_LINK
|
||||
if (ctx->pf_link_fd != -1)
|
||||
close(ctx->pf_link_fd);
|
||||
#endif
|
||||
|
||||
if (ctx->priv) {
|
||||
if_closesockets_os(ctx);
|
||||
free(ctx->priv);
|
||||
if (ctx->link_fd != -1) {
|
||||
eloop_event_delete(ctx->eloop, ctx->link_fd);
|
||||
close(ctx->link_fd);
|
||||
ctx->link_fd = -1;
|
||||
}
|
||||
|
||||
if (ctx->pf_inet_fd != -1) {
|
||||
close(ctx->pf_inet_fd);
|
||||
ctx->pf_inet_fd = -1;
|
||||
}
|
||||
|
||||
if_closesockets_os(ctx);
|
||||
}
|
||||
|
||||
int
|
||||
@ -982,6 +983,10 @@ xsocket(int domain, int type, int protocol)
|
||||
|
||||
if ((s = socket(domain, type, protocol)) == -1)
|
||||
return -1;
|
||||
#ifdef DEBUG_FD
|
||||
logerrx("pid %d fd=%d domain=%d type=%d protocol=%d",
|
||||
getpid(), s, domain, type, protocol);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SOCK_CLOEXEC
|
||||
if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 ||
|
||||
@ -1023,6 +1028,10 @@ xsocketpair(int domain, int type, int protocol, int fd[2])
|
||||
if ((s = socketpair(domain, type, protocol, fd)) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG_FD
|
||||
logerrx("pid %d fd[0]=%d fd[1]=%d", getpid(), fd[0], fd[1]);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SOCK_CLOEXEC
|
||||
if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(fd[0], F_GETFD)) == -1 ||
|
||||
fcntl(fd[0], F_SETFD, xflags | FD_CLOEXEC) == -1))
|
||||
|
29
src/ipv6.c
29
src/ipv6.c
@ -2311,7 +2311,9 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
struct rt *rt;
|
||||
struct ra *rap;
|
||||
const struct routeinfo *rinfo;
|
||||
const struct ipv6_addr *addr;
|
||||
struct in6_addr netmask;
|
||||
|
||||
if (ctx->ra_routers == NULL)
|
||||
return 0;
|
||||
@ -2319,6 +2321,27 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
||||
TAILQ_FOREACH(rap, ctx->ra_routers, next) {
|
||||
if (rap->expired)
|
||||
continue;
|
||||
|
||||
/* add rfc4191 route information routes */
|
||||
TAILQ_FOREACH (rinfo, &rap->rinfos, next) {
|
||||
if(rinfo->lifetime == 0)
|
||||
continue;
|
||||
if ((rt = inet6_makeroute(rap->iface, rap)) == NULL)
|
||||
continue;
|
||||
|
||||
in6_addr_fromprefix(&netmask, rinfo->prefix_len);
|
||||
|
||||
sa_in6_init(&rt->rt_dest, &rinfo->prefix);
|
||||
sa_in6_init(&rt->rt_netmask, &netmask);
|
||||
sa_in6_init(&rt->rt_gateway, &rap->from);
|
||||
#ifdef HAVE_ROUTE_PREF
|
||||
rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
|
||||
#endif
|
||||
|
||||
rt_proto_add(routes, rt);
|
||||
}
|
||||
|
||||
/* add subnet routes */
|
||||
TAILQ_FOREACH(addr, &rap->addrs, next) {
|
||||
if (addr->prefix_vltime == 0)
|
||||
continue;
|
||||
@ -2326,11 +2349,13 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
||||
if (rt) {
|
||||
rt->rt_dflags |= RTDF_RA;
|
||||
#ifdef HAVE_ROUTE_PREF
|
||||
rt->rt_pref = ipv6nd_rtpref(rap);
|
||||
rt->rt_pref = ipv6nd_rtpref(rap->flags);
|
||||
#endif
|
||||
rt_proto_add(routes, rt);
|
||||
}
|
||||
}
|
||||
|
||||
/* add default route */
|
||||
if (rap->lifetime == 0)
|
||||
continue;
|
||||
if (ipv6_anyglobal(rap->iface) == NULL)
|
||||
@ -2340,7 +2365,7 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
||||
continue;
|
||||
rt->rt_dflags |= RTDF_RA;
|
||||
#ifdef HAVE_ROUTE_PREF
|
||||
rt->rt_pref = ipv6nd_rtpref(rap);
|
||||
rt->rt_pref = ipv6nd_rtpref(rap->flags);
|
||||
#endif
|
||||
rt_proto_add(routes, rt);
|
||||
}
|
||||
|
135
src/ipv6nd.c
135
src/ipv6nd.c
@ -71,6 +71,20 @@
|
||||
#define ND_OPT_PI_FLAG_ROUTER 0x20 /* Router flag in PI */
|
||||
#endif
|
||||
|
||||
#ifndef ND_OPT_RI
|
||||
#define ND_OPT_RI 24
|
||||
struct nd_opt_ri { /* Route Information option RFC4191 */
|
||||
uint8_t nd_opt_ri_type;
|
||||
uint8_t nd_opt_ri_len;
|
||||
uint8_t nd_opt_ri_prefixlen;
|
||||
uint8_t nd_opt_ri_flags_reserved;
|
||||
uint32_t nd_opt_ri_lifetime;
|
||||
struct in6_addr nd_opt_ri_prefix;
|
||||
};
|
||||
__CTASSERT(sizeof(struct nd_opt_ri) == 24);
|
||||
#define OPT_RI_FLAG_PREFERENCE(flags) ((flags & 0x18) >> 3)
|
||||
#endif
|
||||
|
||||
#ifndef ND_OPT_RDNSS
|
||||
#define ND_OPT_RDNSS 25
|
||||
struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
|
||||
@ -132,6 +146,8 @@ __CTASSERT(sizeof(struct nd_opt_dnssl) == 8);
|
||||
//
|
||||
|
||||
static void ipv6nd_handledata(void *, unsigned short);
|
||||
static struct routeinfo *routeinfo_findalloc(struct ra *, const struct in6_addr *, uint8_t);
|
||||
static void routeinfohead_free(struct routeinfohead *);
|
||||
|
||||
/*
|
||||
* Android ships buggy ICMP6 filter headers.
|
||||
@ -612,10 +628,10 @@ ipv6nd_startexpire(struct interface *ifp)
|
||||
}
|
||||
|
||||
int
|
||||
ipv6nd_rtpref(struct ra *rap)
|
||||
ipv6nd_rtpref(uint8_t flags)
|
||||
{
|
||||
|
||||
switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
|
||||
switch (flags & ND_RA_FLAG_RTPREF_MASK) {
|
||||
case ND_RA_FLAG_RTPREF_HIGH:
|
||||
return RTPREF_HIGH;
|
||||
case ND_RA_FLAG_RTPREF_MEDIUM:
|
||||
@ -624,7 +640,7 @@ ipv6nd_rtpref(struct ra *rap)
|
||||
case ND_RA_FLAG_RTPREF_LOW:
|
||||
return RTPREF_LOW;
|
||||
default:
|
||||
logerrx("%s: impossible RA flag %x", __func__, rap->flags);
|
||||
logerrx("%s: impossible RA flag %x", __func__, flags);
|
||||
return RTPREF_INVALID;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
@ -649,7 +665,7 @@ ipv6nd_sortrouters(struct dhcpcd_ctx *ctx)
|
||||
continue;
|
||||
if (!ra1->isreachable && ra2->reachable)
|
||||
continue;
|
||||
if (ipv6nd_rtpref(ra1) <= ipv6nd_rtpref(ra2))
|
||||
if (ipv6nd_rtpref(ra1->flags) <= ipv6nd_rtpref(ra2->flags))
|
||||
continue;
|
||||
/* All things being equal, prefer older routers. */
|
||||
/* We don't need to check time, becase newer
|
||||
@ -827,6 +843,7 @@ ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
|
||||
if (remove_ra)
|
||||
TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next);
|
||||
ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
|
||||
routeinfohead_free(&rap->rinfos);
|
||||
free(rap->data);
|
||||
free(rap);
|
||||
}
|
||||
@ -1105,6 +1122,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||
struct nd_opt_prefix_info pi;
|
||||
struct nd_opt_mtu mtu;
|
||||
struct nd_opt_rdnss rdnss;
|
||||
struct nd_opt_ri ri;
|
||||
struct routeinfo *rinfo;
|
||||
uint8_t *p;
|
||||
struct ra *rap;
|
||||
struct in6_addr pi_prefix;
|
||||
@ -1206,6 +1225,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||
rap->from = from->sin6_addr;
|
||||
strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
|
||||
TAILQ_INIT(&rap->addrs);
|
||||
TAILQ_INIT(&rap->rinfos);
|
||||
new_rap = true;
|
||||
rap->isreachable = true;
|
||||
} else
|
||||
@ -1237,9 +1257,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||
rap->flags = nd_ra->nd_ra_flags_reserved;
|
||||
old_lifetime = rap->lifetime;
|
||||
rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
|
||||
if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
|
||||
logwarnx("%s: %s: no longer a default router (lifetime = 0)",
|
||||
ifp->name, rap->sfrom);
|
||||
if (nd_ra->nd_ra_curhoplimit != 0)
|
||||
rap->hoplimit = nd_ra->nd_ra_curhoplimit;
|
||||
else
|
||||
@ -1502,6 +1519,46 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||
rdnss.nd_opt_rdnss_len > 1)
|
||||
rap->hasdns = 1;
|
||||
break;
|
||||
case ND_OPT_RI:
|
||||
if (ndo.nd_opt_len > 3) {
|
||||
logmessage(loglevel, "%s: invalid route info option",
|
||||
ifp->name);
|
||||
break;
|
||||
}
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
memcpy(&ri, p, olen); /* may be smaller than sizeof(ri), pad with zero */
|
||||
if(ri.nd_opt_ri_prefixlen > 128) {
|
||||
logmessage(loglevel, "%s: invalid route info prefix length",
|
||||
ifp->name);
|
||||
break;
|
||||
}
|
||||
|
||||
/* rfc4191 3.1 - RI for ::/0 applies to default route */
|
||||
if(ri.nd_opt_ri_prefixlen == 0) {
|
||||
rap->lifetime = ntohl(ri.nd_opt_ri_lifetime);
|
||||
|
||||
/* Update preference leaving other flags intact */
|
||||
rap->flags = ((rap->flags & (~ (unsigned int)ND_RA_FLAG_RTPREF_MASK))
|
||||
| ri.nd_opt_ri_flags_reserved) & 0xff;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update existing route info instead of rebuilding all routes so that
|
||||
previously announced but now absent routes can stay alive. To kill a
|
||||
route early, an RI with lifetime=0 needs to be received (rfc4191 3.1)*/
|
||||
rinfo = routeinfo_findalloc(rap, &ri.nd_opt_ri_prefix, ri.nd_opt_ri_prefixlen);
|
||||
if(rinfo == NULL) {
|
||||
logerr(__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update/initialize other route info params */
|
||||
rinfo->flags = ri.nd_opt_ri_flags_reserved;
|
||||
rinfo->lifetime = ntohl(ri.nd_opt_ri_lifetime);
|
||||
rinfo->acquired = rap->acquired;
|
||||
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -1537,6 +1594,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
|
||||
ia->prefix_pltime = 0;
|
||||
}
|
||||
|
||||
if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
|
||||
logwarnx("%s: %s: no longer a default router (lifetime = 0)",
|
||||
ifp->name, rap->sfrom);
|
||||
|
||||
if (new_data && !has_address && rap->lifetime && !ipv6_anyglobal(ifp))
|
||||
logwarnx("%s: no global addresses for default route",
|
||||
ifp->name);
|
||||
@ -1689,7 +1750,7 @@ ipv6nd_env(FILE *fp, const struct interface *ifp)
|
||||
return -1;
|
||||
if (efprintf(fp, "%s_hoplimit=%u", ndprefix, rap->hoplimit) == -1)
|
||||
return -1;
|
||||
pref = ipv6nd_rtpref(rap);
|
||||
pref = ipv6nd_rtpref(rap->flags);
|
||||
if (efprintf(fp, "%s_flags=%s%s%s%s%s", ndprefix,
|
||||
rap->flags & ND_RA_FLAG_MANAGED ? "M" : "",
|
||||
rap->flags & ND_RA_FLAG_OTHER ? "O" : "",
|
||||
@ -1794,6 +1855,7 @@ ipv6nd_expirera(void *arg)
|
||||
uint32_t elapsed;
|
||||
bool expired, valid;
|
||||
struct ipv6_addr *ia;
|
||||
struct routeinfo *rinfo, *rinfob;
|
||||
size_t len, olen;
|
||||
uint8_t *p;
|
||||
struct nd_opt_hdr ndo;
|
||||
@ -1813,7 +1875,8 @@ ipv6nd_expirera(void *arg)
|
||||
if (rap->iface != ifp || rap->expired)
|
||||
continue;
|
||||
valid = false;
|
||||
if (rap->lifetime) {
|
||||
/* lifetime may be set to infinite by rfc4191 route information */
|
||||
if (rap->lifetime && rap->lifetime != ND6_INFINITE_LIFETIME) {
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&rap->acquired, NULL);
|
||||
if (elapsed >= rap->lifetime || rap->doexpire) {
|
||||
@ -1869,6 +1932,20 @@ ipv6nd_expirera(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Expire route information */
|
||||
TAILQ_FOREACH_SAFE(rinfo, &rap->rinfos, next, rinfob) {
|
||||
if (rinfo->lifetime == ND6_INFINITE_LIFETIME &&
|
||||
!rap->doexpire)
|
||||
continue;
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&rinfo->acquired, NULL);
|
||||
if (elapsed >= rinfo->lifetime || rap->doexpire) {
|
||||
logwarnx("%s: expired route %s",
|
||||
rap->iface->name, rinfo->sprefix);
|
||||
TAILQ_REMOVE(&rap->rinfos, rinfo, next);
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out expiry for ND options */
|
||||
elapsed = (uint32_t)eloop_timespec_diff(&now,
|
||||
&rap->acquired, NULL);
|
||||
@ -2125,3 +2202,43 @@ ipv6nd_startrs(struct interface *ifp)
|
||||
eloop_timeout_add_msec(ifp->ctx->eloop, delay, ipv6nd_startrs1, ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct routeinfo *routeinfo_findalloc(struct ra *rap, const struct in6_addr *prefix, uint8_t prefix_len)
|
||||
{
|
||||
struct routeinfo *ri;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
const char *p;
|
||||
|
||||
TAILQ_FOREACH(ri, &rap->rinfos, next) {
|
||||
if (ri->prefix_len == prefix_len &&
|
||||
IN6_ARE_ADDR_EQUAL(&ri->prefix, prefix))
|
||||
return ri;
|
||||
}
|
||||
|
||||
ri = malloc(sizeof(struct routeinfo));
|
||||
if (ri == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy(&ri->prefix, prefix, sizeof(ri->prefix));
|
||||
ri->prefix_len = prefix_len;
|
||||
p = inet_ntop(AF_INET6, prefix, buf, sizeof(buf));
|
||||
if (p)
|
||||
snprintf(ri->sprefix,
|
||||
sizeof(ri->sprefix),
|
||||
"%s/%d",
|
||||
p, prefix_len);
|
||||
else
|
||||
ri->sprefix[0] = '\0';
|
||||
TAILQ_INSERT_TAIL(&rap->rinfos, ri, next);
|
||||
return ri;
|
||||
}
|
||||
|
||||
static void routeinfohead_free(struct routeinfohead *head)
|
||||
{
|
||||
struct routeinfo *ri;
|
||||
|
||||
while ((ri = TAILQ_FIRST(head))) {
|
||||
TAILQ_REMOVE(head, ri, next);
|
||||
free(ri);
|
||||
}
|
||||
}
|
||||
|
19
src/ipv6nd.h
19
src/ipv6nd.h
@ -37,6 +37,20 @@
|
||||
#include "dhcpcd.h"
|
||||
#include "ipv6.h"
|
||||
|
||||
/* rfc4191 */
|
||||
struct routeinfo {
|
||||
TAILQ_ENTRY(routeinfo) next;
|
||||
struct in6_addr prefix;
|
||||
uint8_t prefix_len;
|
||||
uint32_t lifetime;
|
||||
uint8_t flags;
|
||||
struct timespec acquired;
|
||||
char sprefix[INET6_ADDRSTRLEN];
|
||||
};
|
||||
|
||||
TAILQ_HEAD(routeinfohead, routeinfo);
|
||||
|
||||
|
||||
struct ra {
|
||||
TAILQ_ENTRY(ra) next;
|
||||
struct interface *iface;
|
||||
@ -45,13 +59,14 @@ struct ra {
|
||||
uint8_t *data;
|
||||
size_t data_len;
|
||||
struct timespec acquired;
|
||||
unsigned char flags;
|
||||
uint8_t flags;
|
||||
uint32_t lifetime;
|
||||
uint32_t reachable;
|
||||
uint32_t retrans;
|
||||
uint32_t mtu;
|
||||
uint8_t hoplimit;
|
||||
struct ipv6_addrhead addrs;
|
||||
struct routeinfohead rinfos;
|
||||
bool hasdns;
|
||||
bool expired;
|
||||
bool willexpire;
|
||||
@ -105,7 +120,7 @@ int ipv6nd_open(bool);
|
||||
int ipv6nd_openif(struct interface *);
|
||||
#endif
|
||||
void ipv6nd_recvmsg(struct dhcpcd_ctx *, struct msghdr *);
|
||||
int ipv6nd_rtpref(struct ra *);
|
||||
int ipv6nd_rtpref(uint8_t);
|
||||
void ipv6nd_printoptions(const struct dhcpcd_ctx *,
|
||||
const struct dhcp_opt *, size_t);
|
||||
void ipv6nd_startrs(struct interface *);
|
||||
|
@ -376,6 +376,8 @@ logsetfd(int fd)
|
||||
struct logctx *ctx = &_logctx;
|
||||
|
||||
ctx->log_fd = fd;
|
||||
if (fd != -1)
|
||||
closelog();
|
||||
#ifndef SMALL
|
||||
if (fd != -1 && ctx->log_file != NULL) {
|
||||
fclose(ctx->log_file);
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
/* We expect to have open 3 SEQPACKET and one RAW fd */
|
||||
|
||||
static void
|
||||
ps_bpf_recvbpf(void *arg, unsigned short events)
|
||||
{
|
||||
@ -160,6 +162,9 @@ ps_bpf_start_bpf(struct ps_process *psp)
|
||||
ps_freeprocesses(ctx, psp);
|
||||
|
||||
psp->psp_bpf = bpf_open(&psp->psp_ifp, psp->psp_filter, ia);
|
||||
#ifdef DEBUG_FD
|
||||
logdebugx("pid %d bpf_fd=%d", getpid(), psp->psp_bpf->bpf_fd);
|
||||
#endif
|
||||
if (psp->psp_bpf == NULL)
|
||||
logerr("%s: bpf_open",__func__);
|
||||
#ifdef PRIVSEP_RIGHTS
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
/* We expect to have open 2 SEQPACKET, 2 STREAM and 2 file STREAM fds */
|
||||
|
||||
static int
|
||||
ps_ctl_startcb(struct ps_process *psp)
|
||||
{
|
||||
@ -198,14 +200,16 @@ ps_ctl_start(struct dhcpcd_ctx *ctx)
|
||||
.psi_cmd = PS_CTL,
|
||||
};
|
||||
struct ps_process *psp;
|
||||
int data_fd[2], listen_fd[2];
|
||||
int work_fd[2], listen_fd[2];
|
||||
pid_t pid;
|
||||
|
||||
if (xsocketpair(AF_UNIX, SOCK_STREAM | SOCK_CXNB, 0, data_fd) == -1 ||
|
||||
if_closesockets(ctx);
|
||||
|
||||
if (xsocketpair(AF_UNIX, SOCK_STREAM | SOCK_CXNB, 0, work_fd) == -1 ||
|
||||
xsocketpair(AF_UNIX, SOCK_STREAM | SOCK_CXNB, 0, listen_fd) == -1)
|
||||
return -1;
|
||||
#ifdef PRIVSEP_RIGHTS
|
||||
if (ps_rights_limit_fdpair(data_fd) == -1 ||
|
||||
if (ps_rights_limit_fdpair(work_fd) == -1 ||
|
||||
ps_rights_limit_fdpair(listen_fd) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
@ -218,24 +222,25 @@ ps_ctl_start(struct dhcpcd_ctx *ctx)
|
||||
if (pid == -1)
|
||||
return -1;
|
||||
else if (pid != 0) {
|
||||
psp->psp_work_fd = data_fd[1];
|
||||
close(data_fd[0]);
|
||||
psp->psp_work_fd = work_fd[0];
|
||||
close(work_fd[1]);
|
||||
close(listen_fd[1]);
|
||||
ctx->ps_control = control_new(ctx,
|
||||
listen_fd[1], FD_SENDLEN | FD_LISTEN);
|
||||
listen_fd[0], FD_SENDLEN | FD_LISTEN);
|
||||
if (ctx->ps_control == NULL)
|
||||
return -1;
|
||||
close(listen_fd[0]);
|
||||
return pid;
|
||||
}
|
||||
|
||||
psp->psp_work_fd = data_fd[0];
|
||||
close(data_fd[1]);
|
||||
close(work_fd[0]);
|
||||
close(listen_fd[0]);
|
||||
|
||||
psp->psp_work_fd = work_fd[1];
|
||||
if (eloop_event_add(ctx->eloop, psp->psp_work_fd, ELE_READ,
|
||||
ps_ctl_recv, ctx) == -1)
|
||||
return -1;
|
||||
|
||||
ctx->ps_control = control_new(ctx, listen_fd[0], 0);
|
||||
close(listen_fd[1]);
|
||||
ctx->ps_control = control_new(ctx, listen_fd[1], 0);
|
||||
if (ctx->ps_control == NULL)
|
||||
return -1;
|
||||
if (eloop_event_add(ctx->eloop, ctx->ps_control->fd, ELE_READ,
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "logerr.h"
|
||||
#include "privsep.h"
|
||||
|
||||
/* We expect to have open 2 SEQPACKET, 1 udp, 1 udp6 and 1 raw6 fds */
|
||||
|
||||
#ifdef INET
|
||||
static void
|
||||
ps_inet_recvbootp(void *arg, unsigned short events)
|
||||
|
@ -259,7 +259,7 @@ ps_root_doioctl(unsigned long req, void *data, size_t len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
s = xsocket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
#ifdef IOCTL_REQUEST_TYPE
|
||||
{
|
||||
@ -679,17 +679,6 @@ ps_root_startcb(struct ps_process *psp)
|
||||
|
||||
if (if_opensockets(ctx) == -1)
|
||||
logerr("%s: if_opensockets", __func__);
|
||||
#ifdef BSD
|
||||
else {
|
||||
/* We only want to write to this socket, so set
|
||||
* a small as possible buffer size. */
|
||||
socklen_t smallbuf = 1;
|
||||
|
||||
if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_RCVBUF,
|
||||
&smallbuf, (socklen_t)sizeof(smallbuf)) == -1)
|
||||
logerr("%s: setsockopt(SO_RCVBUF)", __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open network sockets for sending.
|
||||
* This is a small bit wasteful for non sandboxed OS's
|
||||
@ -892,7 +881,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, datafd) == -1)
|
||||
if (xsocketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, datafd) == -1)
|
||||
return -1;
|
||||
if (ps_setbuf_fdpair(datafd) == -1)
|
||||
return -1;
|
||||
@ -930,6 +919,32 @@ ps_root_start(struct dhcpcd_ctx *ctx)
|
||||
return pid;
|
||||
}
|
||||
|
||||
void
|
||||
ps_root_close(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
|
||||
if_closesockets(ctx);
|
||||
|
||||
#ifdef INET
|
||||
if (ctx->udp_wfd != -1) {
|
||||
close(ctx->udp_wfd);
|
||||
ctx->udp_wfd = -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (ctx->nd_fd != -1) {
|
||||
close(ctx->nd_fd);
|
||||
ctx->nd_fd = -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef DHCP6
|
||||
if (ctx->dhcp6_wfd != -1) {
|
||||
close(ctx->dhcp6_wfd);
|
||||
ctx->dhcp6_wfd = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ps_root_stop(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
|
@ -36,6 +36,7 @@
|
||||
#endif
|
||||
|
||||
pid_t ps_root_start(struct dhcpcd_ctx *ctx);
|
||||
void ps_root_close(struct dhcpcd_ctx *ctx);
|
||||
int ps_root_stop(struct dhcpcd_ctx *ctx);
|
||||
void ps_root_signalcb(int, void *);
|
||||
|
||||
|
@ -45,7 +45,7 @@ ps_root_doioctl6(unsigned long req, void *data, size_t len)
|
||||
{
|
||||
int s, err;
|
||||
|
||||
s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
s = xsocket(PF_INET6, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
err = ioctl(s, req, data, len);
|
||||
else
|
||||
@ -63,7 +63,7 @@ ps_root_doroute(void *data, size_t len)
|
||||
int s;
|
||||
ssize_t err;
|
||||
|
||||
s = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
s = xsocket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s != -1)
|
||||
err = write(s, data, len);
|
||||
else
|
||||
|
@ -408,15 +408,23 @@ ps_startprocess(struct ps_process *psp,
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* If we are not the root process, close un-needed stuff. */
|
||||
if (ctx->ps_root != psp) {
|
||||
ps_root_close(ctx);
|
||||
#ifdef PLUGIN_DEV
|
||||
/* If we are not the root process, stop listening to devices. */
|
||||
if (ctx->ps_root != psp)
|
||||
dev_stop(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
ctx->options |= DHCPCD_FORKED;
|
||||
if (ctx->ps_log_fd != -1)
|
||||
logsetfd(ctx->ps_log_fd);
|
||||
|
||||
#ifdef DEBUG_FD
|
||||
logerrx("pid %d log_fd=%d data_fd=%d psp_fd=%d",
|
||||
getpid(), ctx->ps_log_fd, ctx->ps_data_fd, psp->psp_fd);
|
||||
#endif
|
||||
|
||||
eloop_clear(ctx->eloop, -1);
|
||||
eloop_forked(ctx->eloop);
|
||||
eloop_signal_set_cb(ctx->eloop,
|
||||
@ -459,18 +467,6 @@ ps_startprocess(struct ps_process *psp,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ctx->ps_inet != psp)
|
||||
ctx->ps_inet = NULL;
|
||||
if (ctx->ps_ctl != psp)
|
||||
ctx->ps_ctl = NULL;
|
||||
|
||||
#if 0
|
||||
char buf[1024];
|
||||
errno = 0;
|
||||
ssize_t xx = recv(psp->psp_fd, buf, sizeof(buf), MSG_PEEK);
|
||||
logerr("pid %d test fd %d recv peek %zd", getpid(), psp->psp_fd, xx);
|
||||
#endif
|
||||
|
||||
if (eloop_event_add(ctx->eloop, psp->psp_fd, ELE_READ,
|
||||
recv_msg, psp) == -1)
|
||||
{
|
||||
@ -1206,6 +1202,7 @@ ps_newprocess(struct dhcpcd_ctx *ctx, struct ps_id *psid)
|
||||
return NULL;
|
||||
psp->psp_ctx = ctx;
|
||||
memcpy(&psp->psp_id, psid, sizeof(psp->psp_id));
|
||||
psp->psp_fd = -1;
|
||||
psp->psp_work_fd = -1;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
psp->psp_pfd = -1;
|
||||
|
46
src/sa.c
46
src/sa.c
@ -300,11 +300,39 @@ sa_toprefix(const struct sockaddr *sa)
|
||||
return prefix;
|
||||
}
|
||||
|
||||
static void
|
||||
ipbytes_fromprefix(uint8_t *ap, int prefix, int max_prefix)
|
||||
{
|
||||
int bytes, bits, i;
|
||||
|
||||
bytes = prefix / NBBY;
|
||||
bits = prefix % NBBY;
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
*ap++ = 0xff;
|
||||
if (bits) {
|
||||
uint8_t a;
|
||||
|
||||
a = 0xff;
|
||||
a = (uint8_t)(a << (8 - bits));
|
||||
*ap++ = a;
|
||||
}
|
||||
bytes = (max_prefix - prefix) / NBBY;
|
||||
for (i = 0; i < bytes; i++)
|
||||
*ap++ = 0x00;
|
||||
}
|
||||
|
||||
void
|
||||
in6_addr_fromprefix(struct in6_addr *addr, int prefix)
|
||||
{
|
||||
ipbytes_fromprefix((uint8_t *)addr, prefix, 128);
|
||||
}
|
||||
|
||||
int
|
||||
sa_fromprefix(struct sockaddr *sa, int prefix)
|
||||
{
|
||||
uint8_t *ap;
|
||||
int max_prefix, bytes, bits, i;
|
||||
int max_prefix;
|
||||
|
||||
switch (sa->sa_family) {
|
||||
#ifdef INET
|
||||
@ -328,22 +356,8 @@ sa_fromprefix(struct sockaddr *sa, int prefix)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = prefix / NBBY;
|
||||
bits = prefix % NBBY;
|
||||
|
||||
ap = (uint8_t *)sa + sa_addroffset(sa);
|
||||
for (i = 0; i < bytes; i++)
|
||||
*ap++ = 0xff;
|
||||
if (bits) {
|
||||
uint8_t a;
|
||||
|
||||
a = 0xff;
|
||||
a = (uint8_t)(a << (8 - bits));
|
||||
*ap++ = a;
|
||||
}
|
||||
bytes = (max_prefix - prefix) / NBBY;
|
||||
for (i = 0; i < bytes; i++)
|
||||
*ap++ = 0x00;
|
||||
ipbytes_fromprefix(ap, prefix, max_prefix);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Ensure the calculation is correct */
|
||||
|
1
src/sa.h
1
src/sa.h
@ -67,6 +67,7 @@ bool sa_is_loopback(const struct sockaddr *);
|
||||
void *sa_toaddr(struct sockaddr *);
|
||||
int sa_toprefix(const struct sockaddr *);
|
||||
int sa_fromprefix(struct sockaddr *, int);
|
||||
void in6_addr_fromprefix(struct in6_addr *, int);
|
||||
const char *sa_addrtop(const struct sockaddr *, char *, socklen_t);
|
||||
int sa_cmp(const struct sockaddr *, const struct sockaddr *);
|
||||
void sa_in_init(struct sockaddr *, const struct in_addr *);
|
||||
|
Loading…
Reference in New Issue
Block a user