Import dhcpcd-7.0.0-rc1 with the following changes:
* Default to use VLANID>0 for IAID instead of MAC address * Stop sharing the DHCPv6 port in master mode with other processes * Fix some prefix delegation issues when the carrier drops or addresses become stale * Fix a crash when starting dhcpcd with -n * Fix test for preferring a fake lease over a real one * Show to real address lifetimes being added when adding IPv6 addresses * Restore the -G, --nogateway option
This commit is contained in:
parent
a0f00732f7
commit
d0f9585b51
|
@ -28,7 +28,7 @@
|
|||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "7.0.0-beta3"
|
||||
#define VERSION "7.0.0-rc1"
|
||||
|
||||
#ifndef CONFIG
|
||||
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
|
||||
|
|
|
@ -1353,7 +1353,11 @@ dhcp6_dadcallback(void *arg)
|
|||
{
|
||||
struct ipv6_addr *ap2;
|
||||
|
||||
#ifdef SMALL
|
||||
valid = true;
|
||||
#else
|
||||
valid = (ap->delegating_prefix == NULL);
|
||||
#endif
|
||||
TAILQ_FOREACH(ap2, &state->addrs, next) {
|
||||
if (ap2->flags & IPV6_AF_ADDED &&
|
||||
!(ap2->flags & IPV6_AF_DADCOMPLETED))
|
||||
|
@ -1366,8 +1370,10 @@ dhcp6_dadcallback(void *arg)
|
|||
logdebugx("%s: DHCPv6 DAD completed",
|
||||
ifp->name);
|
||||
script_runreason(ifp,
|
||||
ap->delegating_prefix ?
|
||||
"DELEGATED6" : state->reason);
|
||||
#ifndef SMALL
|
||||
ap->delegating_prefix ? "DELEGATED6" :
|
||||
#endif
|
||||
state->reason);
|
||||
if (valid)
|
||||
dhcpcd_daemonise(ifp->ctx);
|
||||
}
|
||||
|
@ -2039,7 +2045,7 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
|
|||
uint16_t nl;
|
||||
uint8_t iaid[4];
|
||||
char buf[sizeof(iaid) * 3];
|
||||
struct ipv6_addr *ap, *nap;
|
||||
struct ipv6_addr *ap;
|
||||
|
||||
if (l < sizeof(*m)) {
|
||||
/* Should be impossible with guards at packet in
|
||||
|
@ -2162,22 +2168,62 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
|
|||
i++;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) {
|
||||
if (ap->flags & IPV6_AF_STALE) {
|
||||
eloop_q_timeout_delete(ifp->ctx->eloop, 0, NULL, ap);
|
||||
if (ap->flags & IPV6_AF_REQUEST) {
|
||||
ap->prefix_vltime = ap->prefix_pltime = 0;
|
||||
} else {
|
||||
TAILQ_REMOVE(&state->addrs, ap, next);
|
||||
free(ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == 0 && e)
|
||||
return -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
|
||||
{
|
||||
struct ipv6_addr *ia, *ian;
|
||||
|
||||
TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
|
||||
if (ia->flags & IPV6_AF_STALE) {
|
||||
if (ia->prefix_vltime != 0)
|
||||
logdebugx("%s: %s: became stale",
|
||||
ia->iface->name, ia->saddr);
|
||||
ia->prefix_pltime = 0;
|
||||
} else if (ia->prefix_vltime == 0)
|
||||
loginfox("%s: %s: no valid lifetime",
|
||||
ia->iface->name, ia->saddr);
|
||||
else
|
||||
continue;
|
||||
|
||||
#ifndef SMALL
|
||||
/* If we delegated from this prefix, deprecate or remove
|
||||
* the delegations. */
|
||||
if (ia->flags & IPV6_AF_DELEGATEDPFX) {
|
||||
struct ipv6_addr *da;
|
||||
bool touched = false;
|
||||
|
||||
TAILQ_FOREACH(da, &ia->pd_pfxs, pd_next) {
|
||||
if (ia->prefix_vltime == 0) {
|
||||
if (da->prefix_vltime != 0) {
|
||||
da->prefix_vltime = 0;
|
||||
touched = true;
|
||||
}
|
||||
} else if (da->prefix_pltime != 0) {
|
||||
da->prefix_pltime = 0;
|
||||
touched = true;
|
||||
}
|
||||
}
|
||||
if (touched)
|
||||
ipv6_addaddrs(&ia->pd_pfxs);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ia->flags & IPV6_AF_REQUEST) {
|
||||
ia->prefix_vltime = ia->prefix_pltime = 0;
|
||||
eloop_q_timeout_delete(ia->iface->ctx->eloop,
|
||||
0, NULL, ia);
|
||||
continue;
|
||||
}
|
||||
TAILQ_REMOVE(addrs, ia, next);
|
||||
ipv6_freeaddr(ia);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dhcp6_validatelease(struct interface *ifp,
|
||||
struct dhcp6_message *m, size_t len,
|
||||
|
@ -2416,7 +2462,7 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
|
|||
if (strcmp(ifp->name, prefix->iface->name) == 0) {
|
||||
if (prefix->prefix_exclude_len == 0) {
|
||||
/* Don't spam the log automatically */
|
||||
if (sla)
|
||||
if (sla != NULL)
|
||||
logwarnx("%s: DHCPv6 server does not support "
|
||||
"OPTION_PD_EXCLUDE",
|
||||
ifp->name);
|
||||
|
@ -2428,14 +2474,14 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
|
|||
sla, if_ia)) == -1)
|
||||
return NULL;
|
||||
|
||||
if (fls64(sla->suffix) > 128 - pfxlen) {
|
||||
if (sla != NULL && fls64(sla->suffix) > 128 - pfxlen) {
|
||||
logerrx("%s: suffix %" PRIu64 " + prefix_len %d > 128",
|
||||
ifp->name, sla->suffix, pfxlen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add our suffix */
|
||||
if (sla->suffix) {
|
||||
if (sla != NULL && sla->suffix != 0) {
|
||||
daddr = addr;
|
||||
vl = be64dec(addr.s6_addr + 8);
|
||||
vl |= sla->suffix;
|
||||
|
@ -2510,9 +2556,12 @@ dhcp6_script_try_run(struct interface *ifp, int delegated)
|
|||
ipv6_iffindaddr(ap->iface, &ap->addr,
|
||||
IN6_IFF_TENTATIVE))
|
||||
ap->flags |= IPV6_AF_DADCOMPLETED;
|
||||
if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0 &&
|
||||
((delegated && ap->delegating_prefix) ||
|
||||
(!delegated && !ap->delegating_prefix)))
|
||||
if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0
|
||||
#ifndef SMALL
|
||||
&& ((delegated && ap->delegating_prefix) ||
|
||||
(!delegated && !ap->delegating_prefix))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
completed = 0;
|
||||
break;
|
||||
|
@ -3166,6 +3215,7 @@ dhcp6_handledata(void *arg)
|
|||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
(time_t)state->expire, dhcp6_startexpire, ifp);
|
||||
|
||||
dhcp6_deprecateaddrs(&state->addrs);
|
||||
ipv6_addaddrs(&state->addrs);
|
||||
|
||||
if (state->state == DH6S_INFORMED)
|
||||
|
@ -3213,11 +3263,6 @@ dhcp6_open(struct dhcpcd_ctx *ctx)
|
|||
ctx->dhcp6_fd = xsocket(PF_INET6, SOCK_DGRAM | SOCK_FLAGS, IPPROTO_UDP);
|
||||
#undef SOCK_FLAGS
|
||||
if (ctx->dhcp6_fd == -1)
|
||||
return -1;
|
||||
|
||||
n = 1;
|
||||
if (setsockopt(ctx->dhcp6_fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&n, sizeof(n)) == -1)
|
||||
goto errexit;
|
||||
|
||||
n = 1;
|
||||
|
@ -3225,13 +3270,6 @@ dhcp6_open(struct dhcpcd_ctx *ctx)
|
|||
&n, sizeof(n)) == -1)
|
||||
goto errexit;
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
n = 1;
|
||||
if (setsockopt(ctx->dhcp6_fd, SOL_SOCKET, SO_REUSEPORT,
|
||||
&n, sizeof(n)) == -1)
|
||||
logerr("SO_REUSEPORT");
|
||||
#endif
|
||||
|
||||
if (!(ctx->options & DHCPCD_MASTER)) {
|
||||
/* Bind to the link-local address to allow more than one
|
||||
* DHCPv6 client to work. */
|
||||
|
@ -3260,8 +3298,11 @@ dhcp6_open(struct dhcpcd_ctx *ctx)
|
|||
return 0;
|
||||
|
||||
errexit:
|
||||
close(ctx->dhcp6_fd);
|
||||
ctx->dhcp6_fd = -1;
|
||||
logerr(__func__);
|
||||
if (ctx->dhcp6_fd != -1) {
|
||||
close(ctx->dhcp6_fd);
|
||||
ctx->dhcp6_fd = -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -3428,40 +3469,20 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
|
|||
struct dhcp6_state *state;
|
||||
struct dhcpcd_ctx *ctx;
|
||||
unsigned long long options;
|
||||
#ifndef SMALL
|
||||
int dropdele;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* As the interface is going away from dhcpcd we need to
|
||||
* remove the delegated addresses, otherwise we lose track
|
||||
* of which interface is delegating as we remeber it by pointer.
|
||||
* So if we need to change this behaviour, we need to change
|
||||
* how we remember which interface delegated.
|
||||
*
|
||||
* XXX The below is no longer true due to the change of the
|
||||
* default IAID, but do PPP links have stable ethernet
|
||||
* addresses?
|
||||
*
|
||||
* To make it more interesting, on some OS's with PPP links
|
||||
* there is no guarantee the delegating interface will have
|
||||
* the same name or index so think very hard before changing
|
||||
* this.
|
||||
*/
|
||||
if (ifp->options)
|
||||
options = ifp->options->options;
|
||||
else
|
||||
options = ifp->ctx->options;
|
||||
#ifndef SMALL
|
||||
dropdele = (options & (DHCPCD_STOPPING | DHCPCD_RELEASE) &&
|
||||
(options & DHCPCD_NODROP) != DHCPCD_NODROP);
|
||||
#endif
|
||||
|
||||
if (ifp->ctx->eloop)
|
||||
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
||||
|
||||
#ifndef SMALL
|
||||
if (dropdele)
|
||||
/* If we're dropping the lease, drop delegated addresses.
|
||||
* If, for whatever reason, we don't drop them in the future
|
||||
* then they should at least be marked as deprecated (pltime 0). */
|
||||
if (drop && (options & DHCPCD_NODROP) != DHCPCD_NODROP)
|
||||
dhcp6_delete_delegates(ifp);
|
||||
#endif
|
||||
|
||||
|
@ -3573,9 +3594,11 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
|
|||
char *pfx;
|
||||
uint32_t en;
|
||||
const struct dhcpcd_ctx *ctx;
|
||||
#ifndef SMALL
|
||||
const struct dhcp6_state *state;
|
||||
const struct ipv6_addr *ap;
|
||||
char *v, *val;
|
||||
#endif
|
||||
|
||||
n = 0;
|
||||
if (m == NULL)
|
||||
|
@ -3676,6 +3699,7 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
|
|||
free(pfx);
|
||||
|
||||
delegated:
|
||||
#ifndef SMALL
|
||||
/* Needed for Delegated Prefixes */
|
||||
state = D6_CSTATE(ifp);
|
||||
i = 0;
|
||||
|
@ -3707,6 +3731,7 @@ delegated:
|
|||
}
|
||||
if (i)
|
||||
n++;
|
||||
#endif
|
||||
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 11, 2017
|
||||
.Dd May 9, 2017
|
||||
.Dt DHCPCD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -610,6 +610,8 @@ So to stop
|
|||
.Nm
|
||||
from touching your DNS settings you would do:-
|
||||
.D1 dhcpcd -C resolv.conf eth0
|
||||
.It Fl G , Fl Fl nogateway
|
||||
Don't set any default routes.
|
||||
.It Fl H , Fl Fl xidhwaddr
|
||||
Use the last four bytes of the hardware address as the DHCP xid instead
|
||||
of a randomly generated number.
|
||||
|
|
|
@ -477,6 +477,10 @@ configure_interface1(struct interface *ifp)
|
|||
* between reboots without persitent storage,
|
||||
* generating the IAID from the MAC address is the only
|
||||
* logical default.
|
||||
* Saying that, if a VLANID has been specified then we
|
||||
* can use that. It's possible that different interfaces
|
||||
* can have the same VLANID, but this is no worse than
|
||||
* generating the IAID from the duplicate MAC address.
|
||||
*
|
||||
* dhclient uses the last 4 bytes of the MAC address.
|
||||
* dibbler uses an increamenting counter.
|
||||
|
@ -487,11 +491,18 @@ configure_interface1(struct interface *ifp)
|
|||
* dhcpcd-6.1.0 and earlier used the interface name,
|
||||
* falling back to interface index if name > 4.
|
||||
*/
|
||||
if (ifp->hwlen >= sizeof(ifo->iaid))
|
||||
if (ifp->vlanid != 0) {
|
||||
uint32_t vlanid;
|
||||
|
||||
/* Maximal VLANID is 4095, so prefix with 0xff
|
||||
* so we don't conflict with an interface index. */
|
||||
vlanid = htonl(ifp->vlanid | 0xff000000);
|
||||
memcpy(ifo->iaid, &vlanid, sizeof(vlanid));
|
||||
} else if (ifp->hwlen >= sizeof(ifo->iaid)) {
|
||||
memcpy(ifo->iaid,
|
||||
ifp->hwaddr + ifp->hwlen - sizeof(ifo->iaid),
|
||||
sizeof(ifo->iaid));
|
||||
else {
|
||||
} else {
|
||||
uint32_t len;
|
||||
|
||||
len = (uint32_t)strlen(ifp->name);
|
||||
|
@ -503,7 +514,7 @@ configure_interface1(struct interface *ifp)
|
|||
} else {
|
||||
/* IAID is the same size as a uint32_t */
|
||||
len = htonl(ifp->index);
|
||||
memcpy(ifo->iaid, &len, sizeof(len));
|
||||
memcpy(ifo->iaid, &len, sizeof(ifo->iaid));
|
||||
}
|
||||
}
|
||||
ifo->options |= DHCPCD_IAID;
|
||||
|
@ -775,7 +786,7 @@ warn_iaid_conflict(struct interface *ifp, uint8_t *iaid)
|
|||
|
||||
/* This is only a problem if the interfaces are on the same network. */
|
||||
if (ifn)
|
||||
logerr("%s: IAID conflicts with one assigned to %s",
|
||||
logerrx("%s: IAID conflicts with one assigned to %s",
|
||||
ifp->name, ifn->name);
|
||||
}
|
||||
|
||||
|
@ -1510,6 +1521,7 @@ main(int argc, char **argv)
|
|||
#endif
|
||||
case 'P':
|
||||
ctx.options |= DHCPCD_PRINT_PIDFILE;
|
||||
logopts &= ~(LOGERR_LOG | LOGERR_ERR);
|
||||
break;
|
||||
case 'T':
|
||||
i = 1;
|
||||
|
@ -1603,10 +1615,12 @@ printpidfile:
|
|||
* instance for that interface. */
|
||||
if (optind == argc - 1 && !(ctx.options & DHCPCD_MASTER)) {
|
||||
const char *per;
|
||||
const char *ifname;
|
||||
|
||||
if (strlen(argv[optind]) > IF_NAMESIZE) {
|
||||
logerrx("%s: interface name too long",
|
||||
argv[optind]);
|
||||
ifname = *ctx.ifv;
|
||||
if (ifname == NULL || strlen(ifname) > IF_NAMESIZE) {
|
||||
errno = ifname == NULL ? EINVAL : E2BIG;
|
||||
logerr("%s: ", ifname);
|
||||
goto exit_failure;
|
||||
}
|
||||
/* Allow a dhcpcd interface per address family */
|
||||
|
@ -1621,7 +1635,7 @@ printpidfile:
|
|||
per = "";
|
||||
}
|
||||
snprintf(ctx.pidfile, sizeof(ctx.pidfile),
|
||||
PIDFILE, "-", argv[optind], per);
|
||||
PIDFILE, "-", ifname, per);
|
||||
} else {
|
||||
snprintf(ctx.pidfile, sizeof(ctx.pidfile),
|
||||
PIDFILE, "", "", "");
|
||||
|
@ -1643,20 +1657,13 @@ printpidfile:
|
|||
goto exit_failure;
|
||||
}
|
||||
|
||||
/* Open our persistent sockets.
|
||||
* This is needed early for dumping leases on valid interfaces. */
|
||||
#ifdef USE_SIGNALS
|
||||
if (sig == 0) {
|
||||
#endif
|
||||
if (ctx.options & DHCPCD_DUMPLEASE) {
|
||||
/* Open sockets so we can dump something about
|
||||
* valid interfaces. */
|
||||
if (if_opensockets(&ctx) == -1) {
|
||||
logerr("%s: if_opensockets", __func__);
|
||||
goto exit_failure;
|
||||
}
|
||||
#ifdef USE_SIGNALS
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx.options & DHCPCD_DUMPLEASE) {
|
||||
if (optind != argc) {
|
||||
/* We need to try and find the interface so we can load
|
||||
* the hardware address to compare automated IAID */
|
||||
|
@ -1803,6 +1810,12 @@ printpidfile:
|
|||
|
||||
logdebugx(PACKAGE "-" VERSION " starting");
|
||||
ctx.options |= DHCPCD_STARTED;
|
||||
|
||||
if (if_opensockets(&ctx) == -1) {
|
||||
logerr("%s: if_opensockets", __func__);
|
||||
goto exit_failure;
|
||||
}
|
||||
|
||||
#ifdef USE_SIGNALS
|
||||
if (eloop_signal_set_cb(ctx.eloop,
|
||||
dhcpcd_signals, dhcpcd_signals_len,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 11, 2017
|
||||
.Dd May 9, 2017
|
||||
.Dt DHCPCD.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -199,7 +199,8 @@ Set the Interface Association Identifier to
|
|||
This option must be used in an
|
||||
.Ic interface
|
||||
block.
|
||||
This defaults to the last 4 bytes of the hardware address assigned to the
|
||||
This defaults to the VLANID (prefixed with 0xff) for the interface if set,
|
||||
otherwise the last 4 bytes of the hardware address assigned to the
|
||||
interface.
|
||||
Each instance of this should be unique within the scope of the client and
|
||||
.Nm dhcpcd
|
||||
|
@ -457,6 +458,10 @@ This is only useful when allowing IPv4LL.
|
|||
.It Ic nodhcp6
|
||||
Don't start DHCPv6 or listen to DHCPv6 messages.
|
||||
Normally DHCPv6 is started by a RA instruction or configuration.
|
||||
.It Ic nogateway
|
||||
Don't install any default routes.
|
||||
.It Ic gateway
|
||||
Install a default route if available (default).
|
||||
.It Ic nohook Ar script
|
||||
Don't run this hook script.
|
||||
Matches full name, or prefixed with 2 numbers optionally ending with
|
||||
|
|
|
@ -81,6 +81,7 @@ struct interface {
|
|||
sa_family_t family;
|
||||
unsigned char hwaddr[HWADDR_LEN];
|
||||
uint8_t hwlen;
|
||||
unsigned short vlanid;
|
||||
unsigned int metric;
|
||||
int carrier;
|
||||
int wireless;
|
||||
|
|
|
@ -48,6 +48,11 @@
|
|||
#include <netinet/in_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#ifdef __NetBSD__
|
||||
#include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */
|
||||
#else
|
||||
#include <net/if_vlan_var.h>
|
||||
#endif
|
||||
#ifdef __DragonFly__
|
||||
# include <netproto/802_11/ieee80211_ioctl.h>
|
||||
#elif __APPLE__
|
||||
|
@ -153,6 +158,8 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
|||
#define SOCK_FLAGS (SOCK_CLOEXEC | SOCK_NONBLOCK)
|
||||
ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW | SOCK_FLAGS, AF_UNSPEC);
|
||||
#undef SOCK_FLAGS
|
||||
if (ctx->link_fd == -1)
|
||||
return -1;
|
||||
|
||||
#if defined(RO_MSGFILTER)
|
||||
if (setsockopt(ctx->link_fd, PF_ROUTE, RO_MSGFILTER,
|
||||
|
@ -168,7 +175,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
|
|||
logerr(__func__);
|
||||
#endif
|
||||
|
||||
return ctx->link_fd == -1 ? -1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -194,12 +201,31 @@ if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(SIOCG80211NWID) || defined(SIOCGETVLAN)
|
||||
static int if_direct_ioctl(int s, const char *ifname,
|
||||
unsigned long cmd, void *data)
|
||||
{
|
||||
|
||||
strlcpy(data, ifname, IFNAMSIZ);
|
||||
return ioctl(s, cmd, data);
|
||||
}
|
||||
|
||||
static int if_indirect_ioctl(int s, const char *ifname,
|
||||
unsigned long cmd, void *data)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_data = data;
|
||||
return if_direct_ioctl(s, ifname, cmd, &ifr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
if_getssid1(int s, const char *ifname, void *ssid)
|
||||
{
|
||||
int retval = -1;
|
||||
#if defined(SIOCG80211NWID)
|
||||
struct ifreq ifr;
|
||||
struct ieee80211_nwid nwid;
|
||||
#elif defined(IEEE80211_IOC_SSID)
|
||||
struct ieee80211req ireq;
|
||||
|
@ -207,11 +233,8 @@ if_getssid1(int s, const char *ifname, void *ssid)
|
|||
#endif
|
||||
|
||||
#if defined(SIOCG80211NWID) /* NetBSD */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
memset(&nwid, 0, sizeof(nwid));
|
||||
ifr.ifr_data = (void *)&nwid;
|
||||
if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
|
||||
if (if_indirect_ioctl(s, ifname, SIOCG80211NWID, &nwid) == 0) {
|
||||
if (ssid == NULL)
|
||||
retval = nwid.i_len;
|
||||
else if (nwid.i_len > IF_SSIDLEN)
|
||||
|
@ -286,6 +309,31 @@ if_vimaster(const struct dhcpcd_ctx *ctx, const char *ifname)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
if_vlanid(const struct interface *ifp)
|
||||
{
|
||||
#ifdef SIOCGETVLAN
|
||||
struct vlanreq vlr;
|
||||
|
||||
memset(&vlr, 0, sizeof(vlr));
|
||||
if (if_indirect_ioctl(ifp->ctx->pf_inet_fd,
|
||||
ifp->name, SIOCGETVLAN, &vlr) != 0)
|
||||
return 0; /* 0 means no VLANID */
|
||||
return vlr.vlr_tag;
|
||||
#elif defined(SIOCGVNETID)
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGVNETID, &ifr) != 0)
|
||||
return 0; /* 0 means no VLANID */
|
||||
return ifr.ifr_vnetid;
|
||||
#else
|
||||
UNUSED(ifp);
|
||||
return 0; /* 0 means no VLANID */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
get_addrs(int type, const void *data, const struct sockaddr **sa)
|
||||
{
|
||||
|
@ -413,6 +461,9 @@ if_route(unsigned char cmd, const struct rt *rt)
|
|||
char *bp = rtmsg.buffer;
|
||||
struct sockaddr_dl sdl;
|
||||
bool gateway_unspec;
|
||||
#ifdef RTA_LABEL
|
||||
struct sockaddr_rtlabel label;
|
||||
#endif
|
||||
|
||||
assert(rt != NULL);
|
||||
ctx = rt->rt_ifp->ctx;
|
||||
|
@ -448,6 +499,9 @@ if_route(unsigned char cmd, const struct rt *rt)
|
|||
|
||||
rtm->rtm_flags |= RTF_UP;
|
||||
rtm->rtm_addrs |= RTA_GATEWAY;
|
||||
#ifdef RTA_LABEL
|
||||
rtm->rtm_addrs |= RTA_LABEL;
|
||||
#endif
|
||||
if (!(rtm->rtm_flags & RTF_REJECT) &&
|
||||
!sa_is_loopback(&rt->rt_gateway))
|
||||
{
|
||||
|
@ -532,6 +586,23 @@ if_route(unsigned char cmd, const struct rt *rt)
|
|||
if (rtm->rtm_addrs & RTA_IFA)
|
||||
ADDSA(&rt->rt_ifa);
|
||||
|
||||
#ifdef RTA_LABEL
|
||||
if (rtm->rtm_addrs & RTA_LABEL) {
|
||||
int len;
|
||||
|
||||
memset(&label, 0, sizeof(label));
|
||||
label.sr_family = AF_UNSPEC;
|
||||
label.sr_len = sizeof(label);
|
||||
len = snprintf(label.sr_label, sizeof(label.sr_label),
|
||||
PACKAGE " %d", getpid());
|
||||
/* Don't add the label if we failed to create it. */
|
||||
if (len == -1 || (size_t)len > sizeof(label.sr_label))
|
||||
rtm->rtm_addrs &= ~RTA_LABEL;
|
||||
else
|
||||
ADDSA((struct sockaddr *)&label);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef ADDSA
|
||||
|
||||
rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
|
||||
|
@ -785,7 +856,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
*/
|
||||
|
||||
#if !((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003600) || \
|
||||
(defined(__OpenBSD__)))
|
||||
(defined(__OpenBSD__) && OpenBSD >= 201605))
|
||||
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;
|
||||
|
@ -793,8 +864,8 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
/* BUT OpenBSD does not reset the address lifetime
|
||||
#if defined(__OpenBSD__) && OpenBSD <= 201705
|
||||
/* BUT OpenBSD older than 6.2 does not reset the address lifetime
|
||||
* for subsequent calls...
|
||||
* Luckily dhcpcd will remove the lease when it expires so
|
||||
* just set an infinite lifetime, unless a temporary address. */
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
#define O_IPV6 O_BASE + 33
|
||||
#define O_CONTROLGRP O_BASE + 34
|
||||
#define O_SLAAC O_BASE + 35
|
||||
// unused O_BASE + 36
|
||||
#define O_GATEWAY O_BASE + 36
|
||||
#define O_NOUP O_BASE + 37
|
||||
#define O_IPV6RA_AUTOCONF O_BASE + 38
|
||||
#define O_IPV6RA_NOAUTOCONF O_BASE + 39
|
||||
|
@ -196,6 +196,7 @@ const struct option cf_options[] = {
|
|||
{"nodhcp6", no_argument, NULL, O_NODHCP6},
|
||||
{"controlgroup", required_argument, NULL, O_CONTROLGRP},
|
||||
{"slaac", required_argument, NULL, O_SLAAC},
|
||||
{"gateway", no_argument, NULL, O_GATEWAY},
|
||||
{"reject", required_argument, NULL, O_REJECT},
|
||||
{"bootp", no_argument, NULL, O_BOOTP},
|
||||
{"nodelay", no_argument, NULL, O_NODELAY},
|
||||
|
@ -978,6 +979,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
ifo->options &= ~DHCPCD_GATEWAY;
|
||||
break;
|
||||
case 'H':
|
||||
ifo->options |= DHCPCD_XID_HWADDR;
|
||||
break;
|
||||
|
@ -1062,8 +1066,14 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
strncmp(arg, "ms_classless_static_routes=",
|
||||
strlen("ms_classless_static_routes=")) == 0)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct in_addr addr3;
|
||||
|
||||
ifp = if_find(ctx->ifaces, ifname);
|
||||
if (ifp == NULL) {
|
||||
logerrx("static routes require an interface");
|
||||
return -1;
|
||||
}
|
||||
fp = np = strwhite(p);
|
||||
if (np == NULL) {
|
||||
logerrx("all routes need a gateway");
|
||||
|
@ -1077,7 +1087,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
*fp = ' ';
|
||||
return -1;
|
||||
}
|
||||
if ((rt = rt_new(if_find(ctx->ifaces, ifname))) == NULL) {
|
||||
if ((rt = rt_new(ifp)) == NULL) {
|
||||
*fp = ' ';
|
||||
return -1;
|
||||
}
|
||||
|
@ -1087,9 +1097,16 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
|
||||
*fp = ' ';
|
||||
} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = if_find(ctx->ifaces, ifname);
|
||||
if (ifp == NULL) {
|
||||
logerrx("static routes require an interface");
|
||||
return -1;
|
||||
}
|
||||
if (parse_addr(&addr, NULL, p) == -1)
|
||||
return -1;
|
||||
if ((rt = rt_new(if_find(ctx->ifaces, ifname))) == NULL)
|
||||
if ((rt = rt_new(ifp)) == NULL)
|
||||
return -1;
|
||||
addr2.s_addr = INADDR_ANY;
|
||||
sa_in_init(&rt->rt_dest, &addr2);
|
||||
|
@ -2078,6 +2095,9 @@ err_sla:
|
|||
ctx->control_group = grp->gr_gid;
|
||||
#endif
|
||||
break;
|
||||
case O_GATEWAY:
|
||||
ifo->options |= DHCPCD_GATEWAY;
|
||||
break;
|
||||
case O_NOUP:
|
||||
ifo->options &= ~DHCPCD_IF_UP;
|
||||
break;
|
||||
|
@ -2257,7 +2277,7 @@ read_config(struct dhcpcd_ctx *ctx,
|
|||
/* Seed our default options */
|
||||
if ((ifo = default_config(ctx)) == NULL)
|
||||
return NULL;
|
||||
ifo->options |= DHCPCD_DAEMONISE;
|
||||
ifo->options |= DHCPCD_DAEMONISE | DHCPCD_GATEWAY;
|
||||
#ifdef PLUGIN_DEV
|
||||
ifo->options |= DHCPCD_DEV;
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
/* Don't set any optional arguments here so we retain POSIX
|
||||
* compatibility with getopt */
|
||||
#define IF_OPTS "146bc:de:f:gh:i:j:kl:m:no:pqr:s:t:u:v:wxy:z:" \
|
||||
"ABC:DEF:HI:JKLMNO:PQ:S:TUVW:X:Z:"
|
||||
"ABC:DEF:GHI:JKLMNO:PQ:S:TUVW:X:Z:"
|
||||
#define NOERR_IF_OPTS ":" IF_OPTS
|
||||
|
||||
#define DEFAULT_TIMEOUT 30
|
||||
|
@ -61,7 +61,7 @@
|
|||
#define DHCPCD_ARP (1ULL << 0)
|
||||
#define DHCPCD_RELEASE (1ULL << 1)
|
||||
// unused (1ULL << 2)
|
||||
// unused (1ULL << 3)
|
||||
#define DHCPCD_GATEWAY (1ULL << 3)
|
||||
#define DHCPCD_STATIC (1ULL << 4)
|
||||
#define DHCPCD_DEBUG (1ULL << 5)
|
||||
#define DHCPCD_LASTLEASE (1ULL << 7)
|
||||
|
|
|
@ -516,6 +516,8 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
|
|||
}
|
||||
}
|
||||
|
||||
ifp->vlanid = if_vlanid(ifp);
|
||||
|
||||
#ifdef SIOCGIFPRIORITY
|
||||
/* Respect the interface priority */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
|
|
@ -141,6 +141,7 @@ int if_conf(struct interface *);
|
|||
int if_init(struct interface *);
|
||||
int if_getssid(struct interface *);
|
||||
int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
|
||||
unsigned short if_vlanid(const struct interface *);
|
||||
int if_opensockets(struct dhcpcd_ctx *);
|
||||
int if_opensockets_os(struct dhcpcd_ctx *);
|
||||
void if_closesockets(struct dhcpcd_ctx *);
|
||||
|
|
|
@ -229,9 +229,9 @@ ipv4_ifcmp(const struct interface *si, const struct interface *ti)
|
|||
if (!sis->new && tis->new)
|
||||
return 1;
|
||||
/* Always prefer proper leases */
|
||||
if (!(sis->added & STATE_FAKE) && (sis->added & STATE_FAKE))
|
||||
if (!(sis->added & STATE_FAKE) && (tis->added & STATE_FAKE))
|
||||
return -1;
|
||||
if ((sis->added & STATE_FAKE) && !(sis->added & STATE_FAKE))
|
||||
if ((sis->added & STATE_FAKE) && !(tis->added & STATE_FAKE))
|
||||
return 1;
|
||||
/* If we are either, they neither have a lease, or they both have.
|
||||
* We need to check for IPv4LL and make it non-preferred. */
|
||||
|
|
|
@ -578,6 +578,22 @@ ipv6_checkaddrflags(void *arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ipv6_deletedaddr(struct ipv6_addr *ia)
|
||||
{
|
||||
|
||||
#ifdef SMALL
|
||||
UNUSED(ia);
|
||||
#else
|
||||
/* NOREJECT is set if we delegated exactly the prefix to another
|
||||
* address.
|
||||
* This can only be one address, so just clear the flag.
|
||||
* This should ensure the reject route will be restored. */
|
||||
if (ia->delegating_prefix != NULL)
|
||||
ia->delegating_prefix->flags &= ~IPV6_AF_NOREJECT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6_deleteaddr(struct ipv6_addr *ia)
|
||||
{
|
||||
|
@ -590,12 +606,7 @@ ipv6_deleteaddr(struct ipv6_addr *ia)
|
|||
errno != ENXIO && errno != ENODEV)
|
||||
logerr(__func__);
|
||||
|
||||
/* NOREJECT is set if we delegated exactly the prefix to another
|
||||
* address.
|
||||
* This can only be one address, so just clear the flag.
|
||||
* This should ensure the reject route will be restored. */
|
||||
if (ia->delegating_prefix != NULL)
|
||||
ia->delegating_prefix->flags &= ~IPV6_AF_NOREJECT;
|
||||
ipv6_deletedaddr(ia);
|
||||
|
||||
state = IPV6_STATE(ia->iface);
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
|
@ -635,6 +646,38 @@ ipv6_addaddr1(struct ipv6_addr *ap, const struct timespec *now)
|
|||
ipv6_iffindaddr(ap->iface, &ap->addr, IN6_IFF_NOTUSEABLE))
|
||||
ap->flags |= IPV6_AF_DADCOMPLETED;
|
||||
|
||||
/* Adjust plftime and vltime based on acquired time */
|
||||
pltime = ap->prefix_pltime;
|
||||
vltime = ap->prefix_vltime;
|
||||
if (timespecisset(&ap->acquired) &&
|
||||
(ap->prefix_pltime != ND6_INFINITE_LIFETIME ||
|
||||
ap->prefix_vltime != ND6_INFINITE_LIFETIME))
|
||||
{
|
||||
struct timespec n;
|
||||
|
||||
if (now == NULL) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &n);
|
||||
now = &n;
|
||||
}
|
||||
timespecsub(now, &ap->acquired, &n);
|
||||
if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) {
|
||||
ap->prefix_pltime -= (uint32_t)n.tv_sec;
|
||||
/* This can happen when confirming a
|
||||
* deprecated but still valid lease. */
|
||||
if (ap->prefix_pltime > pltime)
|
||||
ap->prefix_pltime = 0;
|
||||
}
|
||||
if (ap->prefix_vltime != ND6_INFINITE_LIFETIME) {
|
||||
ap->prefix_vltime -= (uint32_t)n.tv_sec;
|
||||
/* This should never happen. */
|
||||
if (ap->prefix_vltime > vltime) {
|
||||
logerrx("%s: %s: lifetime overflow",
|
||||
ifp->name, ap->saddr);
|
||||
ap->prefix_vltime = ap->prefix_pltime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logfunc = ap->flags & IPV6_AF_NEW ? loginfox : logdebugx;
|
||||
logfunc("%s: adding %saddress %s", ap->iface->name,
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
|
@ -658,41 +701,6 @@ ipv6_addaddr1(struct ipv6_addr *ap, const struct timespec *now)
|
|||
" seconds",
|
||||
ap->iface->name, ap->prefix_pltime, ap->prefix_vltime);
|
||||
|
||||
/* Adjust plftime and vltime based on acquired time */
|
||||
pltime = ap->prefix_pltime;
|
||||
vltime = ap->prefix_vltime;
|
||||
if (timespecisset(&ap->acquired) &&
|
||||
(ap->prefix_pltime != ND6_INFINITE_LIFETIME ||
|
||||
ap->prefix_vltime != ND6_INFINITE_LIFETIME))
|
||||
{
|
||||
struct timespec n;
|
||||
|
||||
if (now == NULL) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &n);
|
||||
now = &n;
|
||||
}
|
||||
timespecsub(now, &ap->acquired, &n);
|
||||
if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) {
|
||||
ap->prefix_pltime -= (uint32_t)n.tv_sec;
|
||||
/* This can happen when confirming a
|
||||
* deprecated but still valid lease. */
|
||||
if (ap->prefix_pltime > pltime)
|
||||
ap->prefix_pltime = 0;
|
||||
}
|
||||
if (ap->prefix_vltime != ND6_INFINITE_LIFETIME)
|
||||
ap->prefix_vltime -= (uint32_t)n.tv_sec;
|
||||
|
||||
#if 0
|
||||
logdebugx("%s: acquired %lld.%.9ld, now %lld.%.9ld, diff %lld.%.9ld",
|
||||
ap->iface->name,
|
||||
(long long)ap->acquired.tv_sec, ap->acquired.tv_nsec,
|
||||
(long long)now->tv_sec, now->tv_nsec,
|
||||
(long long)n.tv_sec, n.tv_nsec);
|
||||
logdebugx("%s: adj pltime %"PRIu32" seconds, "
|
||||
"vltime %"PRIu32" seconds",
|
||||
ap->iface->name, ap->prefix_pltime, ap->prefix_vltime);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (if_address6(RTM_NEWADDR, ap) == -1) {
|
||||
logerr(__func__);
|
||||
|
@ -719,8 +727,10 @@ ipv6_addaddr1(struct ipv6_addr *ap, const struct timespec *now)
|
|||
|
||||
ap->flags &= ~IPV6_AF_NEW;
|
||||
ap->flags |= IPV6_AF_ADDED;
|
||||
#ifndef SMALL
|
||||
if (ap->delegating_prefix != NULL)
|
||||
ap->flags |= IPV6_AF_DELEGATED;
|
||||
#endif
|
||||
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
eloop_timeout_delete(ap->iface->ctx->eloop,
|
||||
|
@ -944,6 +954,7 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
|
|||
void
|
||||
ipv6_freeaddr(struct ipv6_addr *ap)
|
||||
{
|
||||
#ifndef SMALL
|
||||
struct ipv6_addr *ia;
|
||||
|
||||
/* Forget the reference */
|
||||
|
@ -954,6 +965,7 @@ ipv6_freeaddr(struct ipv6_addr *ap)
|
|||
} else if (ap->delegating_prefix != NULL) {
|
||||
TAILQ_REMOVE(&ap->delegating_prefix->pd_pfxs, ap, pd_next);
|
||||
}
|
||||
#endif
|
||||
|
||||
eloop_q_timeout_delete(ap->iface->ctx->eloop, 0, NULL, ap);
|
||||
free(ap);
|
||||
|
@ -966,12 +978,17 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
|
|||
struct ipv6_addr *ap, *apn, *apf;
|
||||
struct timespec now;
|
||||
|
||||
#ifdef SMALL
|
||||
UNUSED(ifd);
|
||||
#endif
|
||||
timespecclear(&now);
|
||||
TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
|
||||
#ifndef SMALL
|
||||
if (ifd != NULL &&
|
||||
(ap->delegating_prefix == NULL ||
|
||||
ap->delegating_prefix->iface != ifd))
|
||||
continue;
|
||||
#endif
|
||||
if (drop != 2)
|
||||
TAILQ_REMOVE(addrs, ap, next);
|
||||
if (drop && ap->flags & IPV6_AF_ADDED &&
|
||||
|
@ -1676,6 +1693,11 @@ ipv6_handleifa_addrs(int cmd,
|
|||
ia->iface->name, ia->saddr);
|
||||
ia->flags &= ~IPV6_AF_ADDED;
|
||||
}
|
||||
if (ia->flags & IPV6_AF_DELEGATED) {
|
||||
TAILQ_REMOVE(addrs, ia, next);
|
||||
ipv6_deletedaddr(ia);
|
||||
ipv6_freeaddr(ia);
|
||||
}
|
||||
break;
|
||||
case RTM_NEWADDR:
|
||||
/* Safety - ignore tentative announcements */
|
||||
|
|
|
@ -166,12 +166,14 @@ struct ipv6_addr {
|
|||
uint8_t iaid[4];
|
||||
uint16_t ia_type;
|
||||
|
||||
#ifndef SMALL
|
||||
struct ipv6_addr *delegating_prefix;
|
||||
struct ipv6_addrhead pd_pfxs;
|
||||
TAILQ_ENTRY(ipv6_addr) pd_next;
|
||||
|
||||
uint8_t prefix_exclude_len;
|
||||
struct in6_addr prefix_exclude;
|
||||
#endif
|
||||
|
||||
void (*dadcallback)(void *);
|
||||
int dadcounter;
|
||||
|
|
|
@ -281,6 +281,21 @@ rt_add(struct rt *nrt, struct rt *ort)
|
|||
assert(nrt != NULL);
|
||||
ctx = nrt->rt_ifp->ctx;
|
||||
|
||||
/*
|
||||
* Don't install a gateway if not asked to.
|
||||
* This option is mainly for VPN users who want their VPN to be the
|
||||
* default route.
|
||||
* Because VPN's generally don't care about route management
|
||||
* beyond their own, a longer term solution would be to remove this
|
||||
* and get the VPN to inject the default route into dhcpcd somehow.
|
||||
*/
|
||||
if (((nrt->rt_ifp->active &&
|
||||
!(nrt->rt_ifp->options->options & DHCPCD_GATEWAY)) ||
|
||||
(!nrt->rt_ifp->active && !(ctx->options & DHCPCD_GATEWAY))) &&
|
||||
sa_is_unspecified(&nrt->rt_dest) &&
|
||||
sa_is_unspecified(&nrt->rt_netmask))
|
||||
return false;
|
||||
|
||||
rt_desc(ort == NULL ? "adding" : "changing", nrt);
|
||||
|
||||
change = false;
|
||||
|
|
Loading…
Reference in New Issue