Skip to content

Commit b697f37

Browse files
committed
IPv6: store the destination address
We need to match this address on BSD and Illumos as it might be the gateway address for a route to find the interface it belongs to.
1 parent 410bf77 commit b697f37

File tree

6 files changed

+88
-30
lines changed

6 files changed

+88
-30
lines changed

src/if-bsd.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa)
665665
return if_findindex(ctx->ifaces, scope);
666666
if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr)))
667667
return ia->iface;
668+
if ((ia = ipv6_finddstaddr(ctx, &sin->sin6_addr)))
669+
return ia->iface;
668670
break;
669671
}
670672
#endif
@@ -1508,12 +1510,15 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
15081510
case AF_INET6:
15091511
{
15101512
struct in6_addr addr6, mask6;
1513+
const struct in6_addr *dstaddr6;
15111514
const struct sockaddr_in6 *sin6;
15121515

15131516
sin6 = (const void *)rti_info[RTAX_IFA];
15141517
addr6 = sin6->sin6_addr;
15151518
sin6 = (const void *)rti_info[RTAX_NETMASK];
15161519
mask6 = sin6->sin6_addr;
1520+
sin6 = (const void *)rti_info[RTAX_BRD];
1521+
dstaddr6 = sin6 ? &sin6->sin6_addr : NULL;
15171522

15181523
/*
15191524
* If the address was deleted, lets check if it's
@@ -1539,7 +1544,8 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
15391544
#endif
15401545

15411546
ipv6_handleifa(ctx, ifam->ifam_type, NULL,
1542-
ifp->name, &addr6, ipv6_prefixlen(&mask6), flags, pid);
1547+
ifp->name, &addr6, ipv6_prefixlen(&mask6),
1548+
dstaddr6, flags, pid);
15431549
break;
15441550
}
15451551
#endif

src/if-linux.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ link_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm)
876876
int ret;
877877
#endif
878878
#ifdef INET6
879-
struct in6_addr *local6 = NULL, *address6 = NULL;
879+
struct in6_addr *local6 = NULL, *addr6 = NULL, *dstaddr6 = NULL;
880880
int flags;
881881
#endif
882882

@@ -957,21 +957,24 @@ link_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm)
957957
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
958958
switch (rta->rta_type) {
959959
case IFA_ADDRESS:
960-
address6 = (struct in6_addr *)RTA_DATA(rta);
960+
addr6 = (struct in6_addr *)RTA_DATA(rta);
961+
break;
962+
case IFA_BROADCAST:
963+
dstaddr6 = (struct in6_addr *)RTA_DATA(rta);
961964
break;
962965
case IFA_LOCAL:
963966
local6 = (struct in6_addr *)RTA_DATA(rta);
964967
break;
965968
}
966969
}
967970
if (local6 != NULL)
968-
address6 = local6;
969-
if (address6 == NULL)
971+
addr6 = local6;
972+
if (addr6 == NULL)
970973
break; /* should be impossible */
971974

972975
/* Validate RTM_DELADDR really means address deleted
973976
* and anything else really means address exists. */
974-
flags = if_addrflags6(ifp, address6, NULL);
977+
flags = if_addrflags6(ifp, addr6, NULL);
975978
if (nlm->nlmsg_type == RTM_DELADDR) {
976979
if (flags != -1)
977980
break;
@@ -981,8 +984,8 @@ link_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm)
981984
}
982985

983986
ipv6_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
984-
address6, ifa->ifa_prefixlen, ifa->ifa_flags,
985-
(pid_t)nlm->nlmsg_pid);
987+
addr6, ifa->ifa_prefixlen, dstaddr6,
988+
ifa->ifa_flags, (pid_t)nlm->nlmsg_pid);
986989
break;
987990
#endif
988991
}
@@ -1143,7 +1146,7 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
11431146
}
11441147

11451148
if (mtu != NULL)
1146-
ifp->mtu = *(unsigned int *)RTA_DATA(mtu);
1149+
ifp->mtu = (int)*(unsigned int *)RTA_DATA(mtu);
11471150

11481151
/* Re-read hardware address and friends */
11491152
if (!(ifi->ifi_flags & IFF_UP)) {

src/if-sun.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa)
539539
sin = (const void *)sa;
540540
if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr)))
541541
return ia->iface;
542+
if ((ia = ipv6_finddstaddr(ctx, &sin->sin6_addr)))
543+
return ia->iface;
542544
break;
543545
}
544546
#endif
@@ -1004,12 +1006,15 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
10041006
case AF_INET6:
10051007
{
10061008
struct in6_addr addr6, mask6;
1009+
const struct in6_addr *dstaddr6;
10071010
const struct sockaddr_in6 *sin6;
10081011

10091012
sin6 = (const void *)rti_info[RTAX_IFA];
10101013
addr6 = sin6->sin6_addr;
10111014
sin6 = (const void *)rti_info[RTAX_NETMASK];
10121015
mask6 = sin6->sin6_addr;
1016+
sin6 = (const void *)rti_info[RTAX_BRD];
1017+
dstaddr6 = sin6 ? &sin6->sin6_addr : NULL;
10131018

10141019
if (ifam->ifam_type == RTM_DELADDR) {
10151020
struct ipv6_addr *ia;
@@ -1029,7 +1034,8 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
10291034
ipv6_handleifa(ctx,
10301035
ifam->ifam_type == RTM_CHGADDR ?
10311036
RTM_NEWADDR : ifam->ifam_type,
1032-
NULL, ifalias, &addr6, ipv6_prefixlen(&mask6), flags, 0);
1037+
NULL, ifalias, &addr6, ipv6_prefixlen(&mask6),
1038+
dstaddr6, flags, 0);
10331039
break;
10341040
}
10351041
#endif

src/if.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
269269
const struct sockaddr_in *addr, *net, *brd;
270270
#endif
271271
#ifdef INET6
272-
struct sockaddr_in6 *sin6, *net6;
272+
struct sockaddr_in6 *addr6, *net6, *dstaddr6;
273273
#endif
274274
int addrflags;
275275

@@ -313,24 +313,25 @@ if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
313313
#endif
314314
#ifdef INET6
315315
case AF_INET6:
316-
sin6 = (void *)ifa->ifa_addr;
316+
addr6 = (void *)ifa->ifa_addr;
317+
dstaddr6 = (void *)ifa->ifa_dstaddr;
317318
net6 = (void *)ifa->ifa_netmask;
318319

319320
#ifdef __KAME__
320-
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
321+
if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr))
321322
/* Remove the scope from the address */
322-
sin6->sin6_addr.s6_addr[2] =
323-
sin6->sin6_addr.s6_addr[3] = '\0';
323+
addr6->sin6_addr.s6_addr[2] =
324+
addr6->sin6_addr.s6_addr[3] = '\0';
324325
#endif
325326
#ifndef HAVE_IFADDRS_ADDRFLAGS
326-
addrflags = if_addrflags6(ifp, &sin6->sin6_addr,
327+
addrflags = if_addrflags6(ifp, &addr6->sin6_addr,
327328
ifa->ifa_name);
328329
if (addrflags == -1) {
329330
if (errno != EEXIST && errno != EADDRNOTAVAIL) {
330331
char dbuf[INET6_ADDRSTRLEN];
331332
const char *dbp;
332333

333-
dbp = inet_ntop(AF_INET6, &sin6->sin6_addr,
334+
dbp = inet_ntop(AF_INET6, &addr6->sin6_addr,
334335
dbuf, sizeof(dbuf));
335336
logerr("%s: if_addrflags6: %s%%%s",
336337
__func__, dbp, ifp->name);
@@ -339,8 +340,10 @@ if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
339340
}
340341
#endif
341342
ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
342-
ifa->ifa_name, &sin6->sin6_addr,
343-
ipv6_prefixlen(&net6->sin6_addr), addrflags, 0);
343+
ifa->ifa_name, &addr6->sin6_addr,
344+
ipv6_prefixlen(&net6->sin6_addr),
345+
dstaddr6 ? &dstaddr6->sin6_addr : NULL,
346+
addrflags, 0);
344347
break;
345348
#endif
346349
}

src/ipv6.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ ipv6_checkaddrflags(void *arg)
597597
/* Simulate the kernel announcing the new address. */
598598
ipv6_handleifa(ia->iface->ctx, RTM_NEWADDR,
599599
ia->iface->ctx->ifaces, ia->iface->name,
600-
&ia->addr, ia->prefix_len, flags, 0);
600+
&ia->addr, ia->prefix_len, ia->dstaddr, flags, 0);
601601
} else {
602602
/* Still tentative? Check again in a bit. */
603603
eloop_timeout_add_msec(ia->iface->ctx->eloop,
@@ -1108,7 +1108,8 @@ ipv6_anyglobal(struct interface *sifp)
11081108
void
11091109
ipv6_handleifa(struct dhcpcd_ctx *ctx,
11101110
int cmd, struct if_head *ifs, const char *ifname,
1111-
const struct in6_addr *addr, uint8_t prefix_len, int addrflags, pid_t pid)
1111+
const struct in6_addr *addr, uint8_t prefix_len,
1112+
const struct in6_addr *dstaddr, int addrflags, pid_t pid)
11121113
{
11131114
struct interface *ifp;
11141115
struct ipv6_state *state;
@@ -1132,13 +1133,15 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
11321133
#endif
11331134

11341135
#if 0
1135-
char dbuf[INET6_ADDRSTRLEN];
1136-
const char *dbp;
1137-
1138-
dbp = inet_ntop(AF_INET6, &addr->s6_addr,
1139-
dbuf, INET6_ADDRSTRLEN);
1140-
loginfox("%s: cmd %d addr %s addrflags %d",
1141-
ifname, cmd, dbp, addrflags);
1136+
char abuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
1137+
const char *abp, *dbp;
1138+
1139+
abp = inet_ntop(AF_INET6, &addr->s6_addr, abuf, sizeof(abuf));
1140+
dbp = dstaddr ?
1141+
inet_ntop(AF_INET6, &dstaddr->s6_addr, dbuf, sizeof(dbuf))
1142+
: "::";
1143+
loginfox("%s: cmd %d addr %s dstaddr %s addrflags %d",
1144+
ifname, cmd, abp, dbp, addrflags);
11421145
#endif
11431146

11441147
if (ifs == NULL)
@@ -1199,6 +1202,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
11991202
ia->addr_flags = addrflags;
12001203
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
12011204
}
1205+
ia->dstaddr = dstaddr ? *dstaddr : in6addr_any;
12021206
ia->flags &= ~IPV6_AF_STALE;
12031207
#ifdef IPV6_MANAGETEMPADDR
12041208
if (ia->addr_flags & IN6_IFF_TEMPORARY)
@@ -1338,6 +1342,37 @@ ipv6_findmaskaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr)
13381342
return NULL;
13391343
}
13401344

1345+
1346+
static struct ipv6_addr *
1347+
ipv6_iffinddstaddr(const struct interface *ifp, const struct in6_addr *addr)
1348+
{
1349+
struct ipv6_state *state;
1350+
struct ipv6_addr *ap;
1351+
1352+
state = IPV6_STATE(ifp);
1353+
if (state) {
1354+
TAILQ_FOREACH(ap, &state->addrs, next) {
1355+
if (IN6_ARE_ADDR_EQUAL(&ap->dstaddr, addr))
1356+
return ap;
1357+
}
1358+
}
1359+
return NULL;
1360+
}
1361+
1362+
struct ipv6_addr *
1363+
ipv6_finddstaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr)
1364+
{
1365+
struct interface *ifp;
1366+
struct ipv6_addr *ap;
1367+
1368+
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
1369+
ap = ipv6_iffinddstaddr(ifp, addr);
1370+
if (ap != NULL)
1371+
return ap;
1372+
}
1373+
return NULL;
1374+
}
1375+
13411376
int
13421377
ipv6_addlinklocalcallback(struct interface *ifp,
13431378
void (*callback)(void *), void *arg)
@@ -2145,7 +2180,8 @@ ipv6_deletestaleaddrs(struct interface *ifp)
21452180
if (ia->flags & IPV6_AF_STALE)
21462181
ipv6_handleifa(ifp->ctx, RTM_DELADDR,
21472182
ifp->ctx->ifaces, ifp->name,
2148-
&ia->addr, ia->prefix_len, 0, getpid());
2183+
&ia->addr, ia->prefix_len,
2184+
&ia->dstaddr, 0, getpid());
21492185
}
21502186
}
21512187

src/ipv6.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ struct ipv6_addr {
170170
struct timespec created;
171171
struct timespec acquired;
172172
struct in6_addr addr;
173+
struct in6_addr dstaddr;
173174
int addr_flags;
174175
unsigned int flags;
175176
char saddr[INET6_ADDRSTRLEN];
@@ -261,7 +262,8 @@ void ipv6_deleteaddr(struct ipv6_addr *);
261262
void ipv6_freedrop_addrs(struct ipv6_addrhead *, int, unsigned int,
262263
const struct interface *);
263264
void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *,
264-
const char *, const struct in6_addr *, uint8_t, int, pid_t);
265+
const char *, const struct in6_addr *, uint8_t,
266+
const struct in6_addr *, int, pid_t);
265267
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *,
266268
pid_t);
267269
struct ipv6_addr *ipv6_iffindaddr(struct interface *,
@@ -274,6 +276,8 @@ struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,
274276
const struct in6_addr *, unsigned int);
275277
struct ipv6_addr *ipv6_findmaskaddr(struct dhcpcd_ctx *,
276278
const struct in6_addr *);
279+
struct ipv6_addr *ipv6_finddstaddr(struct dhcpcd_ctx *,
280+
const struct in6_addr *);
277281
#define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL, IN6_IFF_NOTUSEABLE)
278282
int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
279283
void ipv6_setscope(struct sockaddr_in6 *, unsigned int);

0 commit comments

Comments
 (0)