Skip to content

Commit

Permalink
Merge branch 'NetworkConfiguration:master' into noipv6rs
Browse files Browse the repository at this point in the history
  • Loading branch information
jvfranklin authored Oct 17, 2024
2 parents b5945b7 + c4c757f commit fb896f6
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 110 deletions.
10 changes: 8 additions & 2 deletions hooks/dhcpcd-run-hooks.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 31, 2022
.Dd October 11, 2024
.Dt DHCPCD-RUN-HOOKS 8
.Os
.Sh NAME
Expand Down Expand Up @@ -114,7 +114,7 @@ dhcpcd has been configured with a static configuration which has not been
obtained from a DHCP server.
.It Dv 3RDPARTY
dhcpcd is monitoring the interface for a 3rd party to give it an IP address.
.It Dv TIMEOUT
.It Dv TIMEOUT | TIMEOUT6
dhcpcd failed to contact any DHCP servers but was able to use an old lease.
.It Dv EXPIRE | EXPIRE6
dhcpcd's lease or state expired and it failed to obtain a new one.
Expand Down Expand Up @@ -185,6 +185,12 @@ the SSID the
is connected to.
.It Ev $interface_order
A list of interfaces, in order of preference.
.It Ev $if_configured
.Dv true
if dhcpcd has configured the
.Ev interface
otherwise
.Dv false .
.It Ev $if_up
.Dv true
if the
Expand Down
1 change: 1 addition & 0 deletions src/dhcp-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols)
if (opt->type & OT_NOREQ)
printf(" norequest");
putchar('\n');
fflush(stdout);
}

struct dhcp_opt *
Expand Down
2 changes: 2 additions & 0 deletions src/dhcp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,8 @@ dhcp6_fail(struct interface *ifp, bool drop)
dhcp_unlink(ifp->ctx, state->leasefile);
dhcp6_addrequestedaddrs(ifp);
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
} else if (state->recv && ifp->options->options & DHCPCD_LASTLEASE) {
dhcp6_bind(ifp, NULL, NULL);
} else if (state->new) {
script_runreason(ifp, "TIMEOUT6");
// We need to keep the expire timeout alive
Expand Down
1 change: 1 addition & 0 deletions src/dhcpcd-definitions-small.conf
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ embed uint32 pltime
embed uint32 vltime
encap 13 option

define6 7 byte preference
define6 12 ip6address unicast

define6 13 norequest embed status_code
Expand Down
3 changes: 2 additions & 1 deletion src/dhcpcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ printf("usage: "PACKAGE"\t[-146ABbDdEGgHJKLMNPpqTV]\n"
"\t\t[-O, --nooption option] [-o, --option option]\n"
"\t\t[-Q, --require option] [-r, --request address]\n"
"\t\t[-S, --static value]\n"
"\t\t[-s, --inform address[/cidr[/broadcast_address]]]\n [--inform6]"
"\t\t[-s, --inform address[/cidr[/broadcast_address]]] [--inform6]\n"
"\t\t[-t, --timeout seconds] [-u, --userclass class]\n"
"\t\t[-v, --vendor code, value] [-W, --whitelist address[/cidr]] [-w]\n"
"\t\t[--waitip [4 | 6]] [-y, --reboot seconds]\n"
Expand Down Expand Up @@ -2719,6 +2719,7 @@ main(int argc, char **argv, char **envp)
eloop_free(ctx.eloop);
logclose();
free(ctx.logfile);
fflush(stdout);
free(ctx.ctl_buf);
#ifdef SETPROCTITLE_H
setproctitle_fini();
Expand Down
13 changes: 12 additions & 1 deletion src/dhcpcd.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd May 24, 2024
.Dd October 11, 2024
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
Expand Down Expand Up @@ -471,6 +471,17 @@ always fork on a RA.
Enables IPv6 Router Advertisement solicitation.
This is on by default, but is documented here in the case where it is disabled
globally but needs to be enabled for one interface.
.It Ic lastlease
If
.Nm dhcpcd
cannot obtain a lease, then try to use the last lease acquired for the
interface.
.It Ic lastleaseextend
Same as the above, but the lease will be retained even if it expires.
.Nm dhcpcd
will give it up if any other host tries to claim it for their own via ARP.
This violates RFC 2131, section 3.7, which states the lease should be
dropped once it has expired.
.It Ic leasetime Ar seconds
Request DHCP a lease time of
.Ar seconds .
Expand Down
34 changes: 1 addition & 33 deletions src/if-bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1658,8 +1658,7 @@ if_machinearch(char *str, size_t len)
}

#ifdef INET6
#if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \
defined(IPV6CTL_FORWARDING)
#if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV))
#define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0)
#define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1)
static int
Expand Down Expand Up @@ -1731,37 +1730,6 @@ if_applyra(const struct ra *rap)
#endif
}

#ifndef IPV6CTL_FORWARDING
#define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0)
#define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1)
static int
inet6_sysctlbyname(const char *name, int val, int action)
{
size_t size;

size = sizeof(val);
if (action) {
if (sysctlbyname(name, NULL, 0, &val, size) == -1)
return -1;
return 0;
}
if (sysctlbyname(name, &val, &size, NULL, 0) == -1)
return -1;
return val;
}
#endif

int
ip6_forwarding(__unused const char *ifname)
{

#ifdef IPV6CTL_FORWARDING
return get_inet6_sysctl(IPV6CTL_FORWARDING);
#else
return get_inet6_sysctlbyname("net.inet6.ip6.forwarding");
#endif
}

#ifdef SIOCIFAFATTACH
static int
if_af_attach(const struct interface *ifp, int af)
Expand Down
60 changes: 33 additions & 27 deletions src/if-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@
#include <linux/if_arp.h>
#endif

#ifndef IFF_DORMANT
/* Inlcude this *after* net/if.h so we get IFF_DORMANT */
#include <linux/if.h>
#endif

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
Expand Down Expand Up @@ -109,6 +104,27 @@ int if_getssid_wext(const char *ifname, uint8_t *ssid);
#define SOL_NETLINK 270
#endif

/*
* We cannot include linux/if.h due to the need to support old kernels.
* IFLA_LINKINFO is a define which was added after IFF_LOWER_UP and
* IFF_DORMANT.
* So we miss a few versions, but it's the best we can do.
*/
#ifdef IFLA_LINKINFO
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
#endif
#ifndef IFF_DORMANT
#define IFF_DORMANT 0x20000
#endif
#endif

/* Linux defines IFA_FLAGS as an enum.
* For older kernels we know it exists if IFA_F_MANAGETEMPADDR does. */
#ifdef IFA_F_MANAGETEMPADDR
#define IFA_FLAGS IFA_FLAGS
#endif

/*
* Someone should fix kernel headers for clang alignment warnings.
* But this is unlikely.
Expand Down Expand Up @@ -1208,13 +1224,15 @@ add_attr_l(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
return 0;
}

#if defined(HAVE_ROUTE_PREF) || defined(HAVE_IN6_ADDR_GEN_MODE_NONE)
static int
add_attr_8(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
uint8_t data)
{

return add_attr_l(n, maxlen, type, &data, sizeof(data));
}
#endif

static int
add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
Expand Down Expand Up @@ -1997,7 +2015,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
#endif
}
#elif IFA_F_MANAGETEMPADDR
#elif defined(IFA_F_MANAGETEMPADDR)
if (ia->flags & IPV6_AF_AUTOCONF && IA6_CANAUTOCONF(ia))
flags |= IFA_F_MANAGETEMPADDR;
#endif
Expand Down Expand Up @@ -2037,12 +2055,15 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
struct rtattr *rta;
struct ifaddrmsg *ifa;
struct in6_addr *local = NULL, *address = NULL;
uint32_t *flags = NULL;
uint32_t flags;

ifa = NLMSG_DATA(nlm);
if (ifa->ifa_index != ia->ifa_ifindex || ifa->ifa_family != AF_INET6)
return 0;

/* Old kernels set flags here, newer ones as attributed data. */
flags = ifa->ifa_flags;

rta = IFA_RTA(ifa);
len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
Expand All @@ -2053,9 +2074,11 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
case IFA_LOCAL:
local = (struct in6_addr *)RTA_DATA(rta);
break;
#ifdef IFA_F_MANAGETEMPADDR /* IFA_FLAGS is an enum, can't test that */
case IFA_FLAGS:
flags = (uint32_t *)RTA_DATA(rta);
memcpy(&flags, RTA_DATA(rta), sizeof(flags));
break;
#endif
}
}

Expand All @@ -2066,8 +2089,8 @@ _if_addrflags6(__unused struct dhcpcd_ctx *ctx,
if (IN6_ARE_ADDR_EQUAL(&ia->ifa_addr, address))
ia->ifa_found = true;
}
if (flags && ia->ifa_found)
memcpy(&ia->ifa_flags, flags, sizeof(ia->ifa_flags));
if (ia->ifa_found)
ia->ifa_flags = flags;
return 0;
}

Expand Down Expand Up @@ -2242,21 +2265,4 @@ if_applyra(const struct ra *rap)
return error;
}

int
ip6_forwarding(const char *ifname)
{
char path[256], buf[64];
int error, i;

if (ifname == NULL)
ifname = "all";
snprintf(path, sizeof(path), "%s/%s/forwarding", p_conf, ifname);
if (readfile(path, buf, sizeof(buf)) == -1)
return -1;
i = (int)strtoi(buf, NULL, 0, INT_MIN, INT_MAX, &error);
if (error != 0 && error != ENOTSUP)
return -1;
return i;
}

#endif /* INET6 */
7 changes: 0 additions & 7 deletions src/if-sun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1746,11 +1746,4 @@ if_setup_inet6(__unused const struct interface *ifp)
{

}

int
ip6_forwarding(__unused const char *ifname)
{

return 1;
}
#endif
48 changes: 27 additions & 21 deletions src/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,29 +1114,19 @@ ipv6_anyglobal(struct interface *sifp)
{
struct ipv6_addr *ia;
struct interface *ifp;
bool forwarding;

ia = ipv6_ifanyglobal(sifp);
if (ia != NULL)
return ia;

/* BSD forwarding is either on or off.
* Linux forwarding is technically the same as it's
* configured by the "all" interface.
* Per interface only affects IsRouter of NA messages. */
#ifdef PRIVSEP_SYSCTL
if (IN_PRIVSEP(sifp->ctx))
forwarding = ps_root_ip6forwarding(sifp->ctx, NULL) > 0;
else
#endif
forwarding = ip6_forwarding(NULL) > 0;

if (!forwarding)
return NULL;

/*
* IPv6 source address selection will prefer the outgoing interface,
* but will also use any other interface if it things the address is
* a better fit for the destination.
* This logic is pretty much baked into all kernels and you
* don't need to be a router either.
* We only have this logic to work around badly configured IPv6
* setups where there is a default router, but you're not handed
* a reachable address. This results in network timeouts which we
* want to actively avoid.
*/
TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) {
if (ifp == sifp)
continue;
ia = ipv6_ifanyglobal(ifp);
if (ia != NULL)
return ia;
Expand Down Expand Up @@ -2332,6 +2322,7 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
sa_in6_init(&rt->rt_dest, &rinfo->prefix);
sa_in6_init(&rt->rt_netmask, &netmask);
sa_in6_init(&rt->rt_gateway, &rap->from);
rt->rt_dflags |= RTDF_RA;
#ifdef HAVE_ROUTE_PREF
rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
#endif
Expand All @@ -2356,6 +2347,21 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
/* add default route */
if (rap->lifetime == 0)
continue;
/*
* We only want to install a default route if we have
* an address that we can use over it.
* If we don't have any global addresses then the link-local
* address would be used instead and we wouldn't reach
* our destination and even if we could, they wouldn't
* be able to reply back to us.
* This avoids timeouts on badly configured IPv6 setups
* where there is a default router but it or a DHCPv6 server
* doesn't hand out an address.
* If an address appears from anywhere, dhcpcd will spot this
* and then add the default like.
* Likewise, if all global addresses are removed then dhcpcd
* will remove the default route.
*/
if (ipv6_anyglobal(rap->iface) == NULL)
continue;
rt = inet6_makerouter(rap);
Expand Down
17 changes: 0 additions & 17 deletions src/privsep-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,11 +611,6 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
free_rdata = true;
break;
#endif
#if defined(INET6) && defined(PRIVSEP_SYSCTL)
case PS_IP6FORWARDING:
err = ip6_forwarding(data);
break;
#endif
#ifdef PLUGIN_DEV
case PS_DEV_INITTED:
err = dev_initialised(ctx, data);
Expand Down Expand Up @@ -1173,18 +1168,6 @@ ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
}
#endif

#ifdef PRIVSEP_SYSCTL
ssize_t
ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
{

if (ps_sendcmd(ctx, PS_ROOT_FD(ctx), PS_IP6FORWARDING, 0,
ifname, ifname != NULL ? strlen(ifname) + 1 : 0) == -1)
return -1;
return ps_root_readerror(ctx, NULL, 0);
}
#endif

#ifdef AUTH
int
ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm)
Expand Down
1 change: 0 additions & 1 deletion src/privsep-root.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ void ps_root_signalcb(int, void *);
ssize_t ps_root_readerror(struct dhcpcd_ctx *, void *, size_t);
ssize_t ps_root_mreaderror(struct dhcpcd_ctx *, void **, size_t *);
ssize_t ps_root_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
ssize_t ps_root_ip6forwarding(struct dhcpcd_ctx *, const char *);
ssize_t ps_root_unlink(struct dhcpcd_ctx *, const char *);
ssize_t ps_root_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
Expand Down
Loading

0 comments on commit fb896f6

Please sign in to comment.