Import dhcpcd-7.2.1 with the following changes:
* auth: Use consttime_memequal to avoid latency attack * DHCP: Fix a potential 1 byte read overflow with DHO_OPTSOVERLOADED * DHCPv6: Fix a potential buffer overflow reading NA/TA addresses
This commit is contained in:
parent
583ae9ed45
commit
cdfaff8fa4
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Written by Matthias Drochner <drochner@NetBSD.org>.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#ifndef CONSTTIME_MEMEQUAL_H
|
||||
#define CONSTTIME_MEMEQUAL_H
|
||||
inline static int
|
||||
consttime_memequal(const void *b1, const void *b2, size_t len)
|
||||
{
|
||||
const unsigned char *c1 = b1, *c2 = b2;
|
||||
unsigned int res = 0;
|
||||
|
||||
while (len--)
|
||||
res |= *c1++ ^ *c2++;
|
||||
|
||||
/*
|
||||
* Map 0 to 1 and [1, 256) to 0 using only constant-time
|
||||
* arithmetic.
|
||||
*
|
||||
* This is not simply `!res' because although many CPUs support
|
||||
* branchless conditional moves and many compilers will take
|
||||
* advantage of them, certain compilers generate branches on
|
||||
* certain CPUs for `!res'.
|
||||
*/
|
||||
return (1 & ((res - 1) >> 8));
|
||||
}
|
||||
#endif /* CONSTTIME_MEMEQUAL_H */
|
|
@ -13,6 +13,7 @@ IPV4LL=
|
|||
INET6=
|
||||
ARC4RANDOM=
|
||||
CLOSEFROM=
|
||||
CONSTTIME_MEMEQUAL=
|
||||
STRLCPY=
|
||||
UDEV=
|
||||
OS=
|
||||
|
@ -846,6 +847,27 @@ if [ "$STRTOI" = no ]; then
|
|||
echo "#include \"compat/strtoi.h\"" >>$CONFIG_H
|
||||
fi
|
||||
|
||||
if [ -z "$CONSTTIME_MEMEQUAL" ]; then
|
||||
printf "Testing for consttime_memequal ... "
|
||||
cat <<EOF >_consttime_memequal.c
|
||||
#include <string.h>
|
||||
int main(void) {
|
||||
return consttime_memequal("deadbeef", "deadbeef", 8);
|
||||
}
|
||||
EOF
|
||||
if $XCC _consttime_memequal.c -o _consttime_memequal 2>&3; then
|
||||
CONSTTIME_MEMEQUAL=yes
|
||||
else
|
||||
CONSTTIME_MEMEQUAL=no
|
||||
fi
|
||||
echo "$CONSTTIME_MEMEQUAL"
|
||||
rm -f _consttime_memequal.c _consttime_memequal
|
||||
fi
|
||||
if [ "$CONSTTIME_MEMEQUAL" = no ]; then
|
||||
echo "#include \"compat/consttime_memequal.h\"" \
|
||||
>>$CONFIG_H
|
||||
fi
|
||||
|
||||
if [ -z "$DPRINTF" ]; then
|
||||
printf "Testing for dprintf ... "
|
||||
cat <<EOF >_dprintf.c
|
||||
|
|
|
@ -117,7 +117,11 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth,
|
|||
|
||||
m = vm;
|
||||
data = vdata;
|
||||
/* Ensure that d is inside m which *may* not be the case for DHPCPv4 */
|
||||
/* Ensure that d is inside m which *may* not be the case for DHCPv4.
|
||||
* This can occur if the authentication option is split using
|
||||
* DHCP long option from RFC 3399. Section 9 which does infact note that
|
||||
* implementations should take this into account.
|
||||
* Fixing this would be problematic, patches welcome. */
|
||||
if (data < m || data > m + mlen || data + dlen > m + mlen) {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
|
@ -354,7 +358,7 @@ gottoken:
|
|||
}
|
||||
|
||||
free(mm);
|
||||
if (memcmp(d, &hmac_code, dlen)) {
|
||||
if (!consttime_memequal(d, &hmac_code, dlen)) {
|
||||
errno = EPERM;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ control_open(const char *ifname)
|
|||
|
||||
if ((fd = make_sock(&sa, ifname, 0)) != -1) {
|
||||
socklen_t len;
|
||||
|
||||
|
||||
len = (socklen_t)SUN_LEN(&sa);
|
||||
if (connect(fd, (struct sockaddr *)&sa, len) == -1) {
|
||||
close(fd);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "7.2.0"
|
||||
#define VERSION "7.2.1"
|
||||
|
||||
#ifndef CONFIG
|
||||
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd September 15, 2018
|
||||
.Dd April 24, 2019
|
||||
.Dt DHCPCD.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -376,8 +376,7 @@ IPv6 address configuration for the internal network.
|
|||
noipv6rs # disable routing solicitation
|
||||
denyinterfaces eth2 # Don't touch eth2 at all
|
||||
interface eth0
|
||||
ipv6rs # enable routing solicitation get the
|
||||
# default IPv6 route
|
||||
ipv6rs # enable routing solicitation for eth0
|
||||
ia_na 1 # request an IPv6 address
|
||||
ia_pd 2 eth1/0 # request a PD and assign it to eth1
|
||||
ia_pd 3 eth2/1 eth3/2 # req a PD and assign it to eth2 and eth3
|
||||
|
|
|
@ -180,7 +180,9 @@ struct dhcpcd_ctx {
|
|||
uint8_t *secret;
|
||||
size_t secret_len;
|
||||
|
||||
#ifndef __sun
|
||||
int nd_fd;
|
||||
#endif
|
||||
struct ra_head *ra_routers;
|
||||
|
||||
int dhcp6_fd;
|
||||
|
|
|
@ -74,9 +74,9 @@ extern int getallifaddrs(sa_family_t, struct ifaddrs **, int64_t);
|
|||
#endif
|
||||
|
||||
#ifndef RT_ROUNDUP
|
||||
#define RT_ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
#define RT_ADVANCE(x, n) (x += RT_ROUNDUP(salen(n)))
|
||||
#define RT_ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(int32_t) - 1))) : sizeof(int32_t))
|
||||
#define RT_ADVANCE(x, n) ((x) += RT_ROUNDUP(salen((n))))
|
||||
#endif
|
||||
|
||||
#define COPYOUT(sin, sa) do { \
|
||||
|
@ -268,6 +268,7 @@ static boolean_t
|
|||
if_newaddr(const char *ifname, void *arg)
|
||||
{
|
||||
struct linkwalk *lw = arg;
|
||||
int error;
|
||||
struct ifaddrs *ifa;
|
||||
dlpi_handle_t dh;
|
||||
dlpi_info_t dlinfo;
|
||||
|
@ -276,7 +277,10 @@ if_newaddr(const char *ifname, void *arg)
|
|||
struct sockaddr_dl *sdl;
|
||||
|
||||
ifa = NULL;
|
||||
if (dlpi_open(ifname, &dh, 0) != DLPI_SUCCESS)
|
||||
error = dlpi_open(ifname, &dh, 0);
|
||||
if (error == DLPI_ENOLINK) /* Just vanished or in global zone */
|
||||
return B_FALSE;
|
||||
if (error != DLPI_SUCCESS)
|
||||
goto failed1;
|
||||
if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS)
|
||||
goto failed;
|
||||
|
@ -317,7 +321,7 @@ if_newaddr(const char *ifname, void *arg)
|
|||
ifa->ifa_next = lw->lw_ifa;
|
||||
lw->lw_ifa = ifa;
|
||||
dlpi_close(dh);
|
||||
return (B_FALSE);
|
||||
return B_FALSE;
|
||||
|
||||
failed:
|
||||
dlpi_close(dh);
|
||||
|
@ -328,7 +332,7 @@ failed:
|
|||
}
|
||||
failed1:
|
||||
lw->lw_error = errno;
|
||||
return (B_TRUE);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
/* Creates an empty sockaddr_dl for lo0. */
|
||||
|
@ -423,14 +427,16 @@ get_addrs(int type, const void *data, const struct sockaddr **sa)
|
|||
{
|
||||
const char *cp;
|
||||
int i;
|
||||
const struct sockaddr **sap;
|
||||
|
||||
cp = data;
|
||||
for (i = 0; i < RTAX_MAX; i++) {
|
||||
sap = &sa[i];
|
||||
if (type & (1 << i)) {
|
||||
sa[i] = (const struct sockaddr *)cp;
|
||||
RT_ADVANCE(cp, sa[i]);
|
||||
*sap = (const struct sockaddr *)cp;
|
||||
RT_ADVANCE(cp, *sap);
|
||||
} else
|
||||
sa[i] = NULL;
|
||||
*sap = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -520,6 +526,7 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg,
|
|||
struct rt_msghdr *rtm;
|
||||
char *bp = rtmsg->buffer;
|
||||
socklen_t sl;
|
||||
bool gateway_unspec;
|
||||
|
||||
/* WARNING: Solaris will not allow you to delete RTF_KERNEL routes.
|
||||
* This includes subnet/prefix routes. */
|
||||
|
@ -538,25 +545,28 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg,
|
|||
rtm->rtm_flags = rt->rt_flags;
|
||||
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
|
||||
|
||||
gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
|
||||
|
||||
if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
|
||||
bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
|
||||
|
||||
rtm->rtm_flags |= RTF_UP;
|
||||
if (!(rtm->rtm_flags & RTF_REJECT) &&
|
||||
!sa_is_loopback(&rt->rt_gateway) &&
|
||||
/* Solaris doesn't like interfaces on default routes. */
|
||||
!sa_is_unspecified(&rt->rt_dest))
|
||||
!sa_is_loopback(&rt->rt_gateway))
|
||||
{
|
||||
rtm->rtm_addrs |= RTA_IFP;
|
||||
#if 0
|
||||
/* RTA_IFA is currently ignored by the kernel.
|
||||
* RTA_SRC and RTF_SETSRC look like what we want,
|
||||
* but they don't work with RTF_GATEWAY.
|
||||
* We set RTA_IFA just in the hope that the
|
||||
* kernel will one day support this. */
|
||||
if (!sa_is_unspecified(&rt->rt_ifa))
|
||||
rtm->rtm_addrs |= RTA_IFA;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (netmask_bcast)
|
||||
rtm->rtm_flags |= RTF_HOST;
|
||||
else
|
||||
else if (!gateway_unspec)
|
||||
rtm->rtm_flags |= RTF_GATEWAY;
|
||||
|
||||
/* Emulate the kernel by marking address generated
|
||||
|
@ -575,7 +585,7 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg,
|
|||
|
||||
ADDSA(&rt->rt_dest);
|
||||
|
||||
if (sa_is_unspecified(&rt->rt_gateway))
|
||||
if (gateway_unspec)
|
||||
ADDSA(&rt->rt_ifa);
|
||||
else
|
||||
ADDSA(&rt->rt_gateway);
|
||||
|
@ -590,14 +600,13 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg,
|
|||
ADDSA((struct sockaddr *)&sdl);
|
||||
}
|
||||
|
||||
if (rtm->rtm_addrs & RTA_IFA) {
|
||||
ADDSA(&rt->rt_ifa);
|
||||
rtm->rtm_addrs |= RTA_SRC;
|
||||
}
|
||||
if (rtm->rtm_addrs & RTA_SRC)
|
||||
if (rtm->rtm_addrs & RTA_IFA)
|
||||
ADDSA(&rt->rt_ifa);
|
||||
|
||||
#undef ADDSA
|
||||
#if 0
|
||||
if (rtm->rtm_addrs & RTA_SRC)
|
||||
ADDSA(&rt->rt_ifa);
|
||||
#endif
|
||||
|
||||
rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
|
||||
}
|
||||
|
@ -747,15 +756,19 @@ if_finishrt(struct dhcpcd_ctx *ctx, struct rt *rt)
|
|||
rt->rt_mtu = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
if_addrflags0(int fd, const char *ifname)
|
||||
static uint64_t
|
||||
if_addrflags0(int fd, const char *ifname, const struct sockaddr *sa)
|
||||
{
|
||||
struct lifreq lifr;
|
||||
|
||||
memset(&lifr, 0, sizeof(lifr));
|
||||
strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
|
||||
if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
if (ioctl(fd, SIOCGLIFADDR, &lifr) == -1)
|
||||
return 0;
|
||||
if (sa_cmp(sa, (struct sockaddr *)&lifr.lifr_addr) != 0)
|
||||
return 0;
|
||||
|
||||
return lifr.lifr_flags;
|
||||
}
|
||||
|
@ -804,13 +817,56 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
if_getalias(struct interface *ifp, const struct sockaddr *sa, char *alias)
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
struct interface *ifpx;
|
||||
bool found;
|
||||
|
||||
ifaddrs = NULL;
|
||||
if (getallifaddrs(sa->sa_family, &ifaddrs, 0) == -1)
|
||||
return false;
|
||||
found = false;
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
if (sa_cmp(sa, ifa->ifa_addr) != 0)
|
||||
continue;
|
||||
/* Check it's for the right interace. */
|
||||
ifpx = if_find(ifp->ctx->ifaces, ifa->ifa_name);
|
||||
if (ifp == ifpx) {
|
||||
strlcpy(alias, ifa->ifa_name, IF_NAMESIZE);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddrs);
|
||||
return found;
|
||||
}
|
||||
|
||||
static int
|
||||
if_getbrdaddr(struct dhcpcd_ctx *ctx, const char *ifname, struct in_addr *brd)
|
||||
{
|
||||
struct lifreq lifr = { 0 };
|
||||
int r;
|
||||
|
||||
memset(&lifr, 0, sizeof(lifr));
|
||||
strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
|
||||
errno = 0;
|
||||
r = ioctl(ctx->pf_inet_fd, SIOCGLIFBRDADDR, &lifr, sizeof(lifr));
|
||||
if (r != -1)
|
||||
COPYOUT(*brd, (struct sockaddr *)&lifr.lifr_broadaddr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
||||
{
|
||||
struct interface *ifp;
|
||||
const struct sockaddr *sa, *rti_info[RTAX_MAX];
|
||||
int flags;
|
||||
const char *ifalias;
|
||||
char ifalias[IF_NAMESIZE];
|
||||
|
||||
/* XXX We have no way of knowing who generated these
|
||||
* messages wich truely sucks because we want to
|
||||
|
@ -819,6 +875,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
return;
|
||||
sa = (const void *)(ifam + 1);
|
||||
get_addrs(ifam->ifam_addrs, sa, rti_info);
|
||||
|
||||
if ((sa = rti_info[RTAX_IFA]) == NULL)
|
||||
return;
|
||||
|
||||
|
@ -835,31 +892,8 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
* ifam_alias
|
||||
* ifam_pid
|
||||
*/
|
||||
|
||||
ifalias = ifp->name;
|
||||
if (ifam->ifam_type != RTM_DELADDR && sa->sa_family != AF_LINK) {
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
|
||||
ifaddrs = NULL;
|
||||
if (getallifaddrs(sa->sa_family, &ifaddrs, 0) == -1)
|
||||
return;
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr != NULL) {
|
||||
if (sa_cmp(sa, ifa->ifa_addr) == 0) {
|
||||
/* Check it's for the right interace. */
|
||||
struct interface *ifpx;
|
||||
|
||||
ifpx = if_find(ctx->ifaces,
|
||||
ifa->ifa_name);
|
||||
if (ifp == ifpx) {
|
||||
ifalias = ifa->ifa_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddrs);
|
||||
}
|
||||
if (ifam->ifam_type != RTM_DELADDR && !if_getalias(ifp, sa, ifalias))
|
||||
return;
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_LINK:
|
||||
|
@ -882,12 +916,25 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
COPYOUT(mask, rti_info[RTAX_NETMASK]);
|
||||
COPYOUT(bcast, rti_info[RTAX_BRD]);
|
||||
|
||||
if (ifam->ifam_type != RTM_DELADDR) {
|
||||
flags = if_addrflags0(ctx->pf_inet_fd, ifalias);
|
||||
if (flags == -1)
|
||||
break;
|
||||
} else
|
||||
flags = 0;
|
||||
if (ifam->ifam_type == RTM_DELADDR) {
|
||||
struct ipv4_addr *ia;
|
||||
|
||||
ia = ipv4_iffindaddr(ifp, &addr, &mask);
|
||||
if (ia == NULL)
|
||||
return;
|
||||
strlcpy(ifalias, ia->alias, sizeof(ifalias));
|
||||
} else if (bcast.s_addr == INADDR_ANY) {
|
||||
/* Work around a bug where broadcast
|
||||
* address is not correctly reported. */
|
||||
if (if_getbrdaddr(ctx, ifalias, &bcast) == -1)
|
||||
return;
|
||||
}
|
||||
flags = if_addrflags(ifp, &addr, ifalias);
|
||||
if (ifam->ifam_type == RTM_DELADDR) {
|
||||
if (flags != -1)
|
||||
return;
|
||||
} else if (flags == -1)
|
||||
return;
|
||||
|
||||
ipv4_handleifa(ctx,
|
||||
ifam->ifam_type == RTM_CHGADDR ?
|
||||
|
@ -907,15 +954,20 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
|
|||
sin6 = (const void *)rti_info[RTAX_NETMASK];
|
||||
mask6 = sin6->sin6_addr;
|
||||
|
||||
if (ifam->ifam_type != RTM_DELADDR) {
|
||||
const struct priv *priv;
|
||||
if (ifam->ifam_type == RTM_DELADDR) {
|
||||
struct ipv6_addr *ia;
|
||||
|
||||
priv = (struct priv *)ctx->priv;
|
||||
flags = if_addrflags0(priv->pf_inet6_fd, ifalias);
|
||||
if (flags == -1)
|
||||
break;
|
||||
} else
|
||||
flags = 0;
|
||||
ia = ipv6_iffindaddr(ifp, &addr6, 0);
|
||||
if (ia == NULL)
|
||||
return;
|
||||
strlcpy(ifalias, ia->alias, sizeof(ifalias));
|
||||
}
|
||||
flags = if_addrflags6(ifp, &addr6, ifalias);
|
||||
if (ifam->ifam_type == RTM_DELADDR) {
|
||||
if (flags != -1)
|
||||
return;
|
||||
} else if (flags == -1)
|
||||
return;
|
||||
|
||||
ipv6_handleifa(ctx,
|
||||
ifam->ifam_type == RTM_CHGADDR ?
|
||||
|
@ -1003,7 +1055,8 @@ if_octetstr(char *buf, const Octet_t *o, ssize_t len)
|
|||
|
||||
static int
|
||||
if_addaddr(int fd, const char *ifname,
|
||||
struct sockaddr_storage *addr, struct sockaddr_storage *mask)
|
||||
struct sockaddr_storage *addr, struct sockaddr_storage *mask,
|
||||
struct sockaddr_storage *brd)
|
||||
{
|
||||
struct lifreq lifr;
|
||||
|
||||
|
@ -1020,6 +1073,13 @@ if_addaddr(int fd, const char *ifname,
|
|||
if (ioctl(fd, SIOCSLIFADDR, &lifr) == -1)
|
||||
return -1;
|
||||
|
||||
/* Then assign the broadcast address. */
|
||||
if (brd != NULL) {
|
||||
lifr.lifr_broadaddr = *brd;
|
||||
if (ioctl(fd, SIOCSLIFBRDADDR, &lifr) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now bring it up. */
|
||||
if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
|
||||
return -1;
|
||||
|
@ -1173,15 +1233,11 @@ out:
|
|||
static int
|
||||
if_unplumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
{
|
||||
struct sockaddr_storage addr, mask;
|
||||
struct sockaddr_storage addr = { .ss_family = af };
|
||||
int fd;
|
||||
|
||||
/* For the time being, don't unplumb the interface, just
|
||||
* set the address to zero. */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.ss_family = af;
|
||||
memset(&mask, 0, sizeof(mask));
|
||||
mask.ss_family = af;
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
|
@ -1202,7 +1258,8 @@ if_unplumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
|||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
return if_addaddr(fd, ifname, &addr, &mask);
|
||||
return if_addaddr(fd, ifname, &addr, &addr,
|
||||
af == AF_INET ? &addr : NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1306,6 +1363,7 @@ if_walkrt6(struct dhcpcd_ctx *ctx, char *data, size_t len)
|
|||
ipv6_mask(&in6, re->ipv6RoutePfxLength);
|
||||
sa_in6_init(&rt.rt_netmask, &in6);
|
||||
sa_in6_init(&rt.rt_gateway, &re->ipv6RouteNextHop);
|
||||
sa_in6_init(&rt.rt_ifa, &re->ipv6RouteInfo.re_src_addr);
|
||||
rt.rt_mtu = re->ipv6RouteInfo.re_max_frag;
|
||||
if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname));
|
||||
rt.rt_ifp = if_find(ctx->ifaces, ifname);
|
||||
|
@ -1456,8 +1514,10 @@ bpf_send(const struct interface *ifp, __unused int fd, uint16_t protocol,
|
|||
int
|
||||
if_address(unsigned char cmd, const struct ipv4_addr *ia)
|
||||
{
|
||||
struct sockaddr_storage ss_addr, ss_mask;
|
||||
struct sockaddr_in *sin_addr, *sin_mask;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
} addr, mask, brd;
|
||||
|
||||
/* Either remove the alias or ensure it exists. */
|
||||
if (if_plumb(cmd, ia->iface->ctx, AF_INET, ia->alias) == -1)
|
||||
|
@ -1474,24 +1534,24 @@ if_address(unsigned char cmd, const struct ipv4_addr *ia)
|
|||
/* We need to update the index now */
|
||||
ia->iface->index = if_nametoindex(ia->alias);
|
||||
|
||||
sin_addr = (struct sockaddr_in *)&ss_addr;
|
||||
sin_addr->sin_family = AF_INET;
|
||||
sin_addr->sin_addr = ia->addr;
|
||||
sin_mask = (struct sockaddr_in *)&ss_mask;
|
||||
sin_mask->sin_family = AF_INET;
|
||||
sin_mask->sin_addr = ia->mask;
|
||||
return if_addaddr(ia->iface->ctx->pf_inet_fd,
|
||||
ia->alias, &ss_addr, &ss_mask);
|
||||
sa_in_init(&addr.sa, &ia->addr);
|
||||
sa_in_init(&mask.sa, &ia->mask);
|
||||
sa_in_init(&brd.sa, &ia->brd);
|
||||
return if_addaddr(ia->iface->ctx->pf_inet_fd, ia->alias,
|
||||
&addr.ss, &mask.ss, &brd.ss);
|
||||
}
|
||||
|
||||
int
|
||||
if_addrflags(const struct interface *ifp, __unused const struct in_addr *addr,
|
||||
if_addrflags(const struct interface *ifp, const struct in_addr *addr,
|
||||
const char *alias)
|
||||
{
|
||||
int flags, aflags;
|
||||
union sa_ss ss;
|
||||
uint64_t aflags;
|
||||
int flags;
|
||||
|
||||
aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias);
|
||||
if (aflags == -1)
|
||||
sa_in_init(&ss.sa, addr);
|
||||
aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias, &ss.sa);
|
||||
if (aflags == 0)
|
||||
return -1;
|
||||
flags = 0;
|
||||
if (aflags & IFF_DUPLICATE)
|
||||
|
@ -1505,9 +1565,12 @@ if_addrflags(const struct interface *ifp, __unused const struct in_addr *addr,
|
|||
int
|
||||
if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
||||
{
|
||||
struct sockaddr_storage ss_addr, ss_mask;
|
||||
struct sockaddr_in6 *sin6_addr, *sin6_mask;
|
||||
struct priv *priv;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_storage ss;
|
||||
} addr, mask;
|
||||
const struct priv *priv;
|
||||
int r;
|
||||
|
||||
/* Either remove the alias or ensure it exists. */
|
||||
|
@ -1522,29 +1585,30 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
return -1;
|
||||
}
|
||||
|
||||
priv = (struct priv *)ia->iface->ctx->priv;
|
||||
sin6_addr = (struct sockaddr_in6 *)&ss_addr;
|
||||
sin6_addr->sin6_family = AF_INET6;
|
||||
sin6_addr->sin6_addr = ia->addr;
|
||||
sin6_mask = (struct sockaddr_in6 *)&ss_mask;
|
||||
sin6_mask->sin6_family = AF_INET6;
|
||||
ipv6_mask(&sin6_mask->sin6_addr, ia->prefix_len);
|
||||
r = if_addaddr(priv->pf_inet6_fd,
|
||||
ia->alias, &ss_addr, &ss_mask);
|
||||
sa_in6_init(&addr.sa, &ia->addr);
|
||||
mask.sin6.sin6_family = AF_INET6;
|
||||
ipv6_mask(&mask.sin6.sin6_addr, ia->prefix_len);
|
||||
priv = (const struct priv *)ia->iface->ctx->priv;
|
||||
r = if_addaddr(priv->pf_inet6_fd, ia->alias, &addr.ss, &mask.ss, NULL);
|
||||
if (r == -1 && errno == EEXIST)
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
if_addrflags6(const struct interface *ifp, __unused const struct in6_addr *addr,
|
||||
if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
|
||||
const char *alias)
|
||||
{
|
||||
struct priv *priv;
|
||||
int aflags, flags;
|
||||
union sa_ss ss;
|
||||
uint64_t aflags;
|
||||
int flags;
|
||||
|
||||
priv = (struct priv *)ifp->ctx->priv;
|
||||
aflags = if_addrflags0(priv->pf_inet6_fd, alias);
|
||||
sa_in6_init(&ss.sa, addr);
|
||||
aflags = if_addrflags0(priv->pf_inet6_fd, alias, &ss.sa);
|
||||
if (aflags == 0)
|
||||
return -1;
|
||||
flags = 0;
|
||||
if (aflags & IFF_DUPLICATE)
|
||||
flags |= IN6_IFF_DUPLICATED;
|
||||
|
|
|
@ -62,9 +62,8 @@
|
|||
* While it supports DaD, to seems to only expose IFF_DUPLICATE
|
||||
* so we have no way of knowing if it's tentative or not.
|
||||
* I don't even know if Solaris has any special treatment for tentative. */
|
||||
# define IN_IFF_TENTATIVE 0
|
||||
# define IN_IFF_DUPLICATED 0x02
|
||||
# define IN_IFF_DETACHED 0
|
||||
# define IN_IFF_NOTUSEABLE IN_IFF_DUPLICATED
|
||||
#endif
|
||||
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
|
|
|
@ -232,7 +232,7 @@ static void
|
|||
ipv4ll_probe(void *arg)
|
||||
{
|
||||
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
ipv4ll_probed(arg);
|
||||
#else
|
||||
arp_probe(arg);
|
||||
|
@ -404,7 +404,7 @@ ipv4ll_start(void *arg)
|
|||
if (ia == NULL)
|
||||
ia = ipv4_iffindlladdr(ifp);
|
||||
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
if (ia != NULL && ia->addr_flags & IN_IFF_DUPLICATED) {
|
||||
ipv4_deladdr(ia, 0);
|
||||
ia = NULL;
|
||||
|
@ -419,6 +419,8 @@ ipv4ll_start(void *arg)
|
|||
ifp->name, inet_ntoa(ia->addr));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
loginfox("%s: using IPv4LL address %s", ifp->name, ia->saddr);
|
||||
#endif
|
||||
ipv4ll_probed(astate);
|
||||
|
@ -429,7 +431,7 @@ ipv4ll_start(void *arg)
|
|||
if (state->pickedaddr.s_addr == INADDR_ANY)
|
||||
state->pickedaddr.s_addr = ipv4ll_pickaddr(astate);
|
||||
astate->addr = state->pickedaddr;
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
#ifdef IN_IFF_DUPLICATED
|
||||
ipv4ll_probed(astate);
|
||||
#else
|
||||
arp_probe(astate);
|
||||
|
|
|
@ -137,7 +137,9 @@ ipv6_init(struct dhcpcd_ctx *ctx)
|
|||
return -1;
|
||||
TAILQ_INIT(ctx->ra_routers);
|
||||
|
||||
#ifndef __sun
|
||||
ctx->nd_fd = -1;
|
||||
#endif
|
||||
ctx->dhcp6_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,6 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#define ALLNODES "ff02::1"
|
||||
#define ALLROUTERS "ff02::2"
|
||||
|
||||
#define EUI64_GBIT 0x01
|
||||
#define EUI64_UBIT 0x02
|
||||
#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
|
||||
|
@ -77,6 +74,17 @@
|
|||
(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
|
||||
#endif
|
||||
|
||||
#ifndef IN6ADDR_LINKLOCAL_ALLNODES_INIT
|
||||
#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
|
||||
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
|
||||
#endif
|
||||
#ifndef IN6ADDR_LINKLOCAL_ALLROUTERS_INIT
|
||||
#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
|
||||
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BSD kernels don't inform userland of DAD results.
|
||||
* See the discussion here:
|
||||
|
|
|
@ -61,6 +61,9 @@ struct rs_state {
|
|||
size_t rslen;
|
||||
int rsprobes;
|
||||
uint32_t retrans;
|
||||
#ifdef __sun
|
||||
int nd_fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND])
|
||||
|
|
Loading…
Reference in New Issue