Allow the mpw(4) interface to establish VPLS tunnel over an IPv6-only MPLS core.
This is the ifconfig(8) bit providing display and configuration of IPv6
neighbor on mpw(4) interface.
pe1# ifconfig mpw0
mpw0: flags=51<UP,POINTOPOINT,RUNNING> mtu 1500
index 7 priority 0 llprio 3
encapsulation-type ethernet, control-word
mpls label: local 16 remote 16
neighbor: 2001:db8:ff::e2
groups: mpw
Index: ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.324
diff -u -p -r1.324 ifconfig.8
--- ifconfig.8 16 Nov 2018 12:25:29 -0000 1.324
+++ ifconfig.8 22 Dec 2018 15:55:01 -0000
@@ -1344,7 +1344,7 @@ is another 20-bit number which will be u
Sets the destination address where this mpw should output.
The
.Ar dest-address
-is an IPv4 address that will be used to find the nexthop in the MPLS
+is an IPv4 or IPv6 address that will be used to find the nexthop in the MPLS
network.
.El
.Sh PAIR
Index: ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.387
diff -u -p -r1.387 ifconfig.c
--- ifconfig.c 29 Nov 2018 00:12:34 -0000 1.387
+++ ifconfig.c 22 Dec 2018 15:55:02 -0000
@@ -3803,7 +3803,9 @@ void
mpw_status(void)
{
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct ifmpwreq imr;
+ char hbuf[NI_MAXHOST];
bzero(&imr, sizeof(imr));
ifr.ifr_data = (caddr_t) &imr;
@@ -3842,11 +3844,22 @@ mpw_status(void)
else
printf("remote %u\n", imr.imr_rshim.shim_label);
- sin = (struct sockaddr_in *) &imr.imr_nexthop;
- if (sin->sin_addr.s_addr == 0)
- printf("\tneighbor: none\n");
- else
- printf("\tneighbor: %s\n", inet_ntoa(sin->sin_addr));
+ printf("\tneighbor: ");
+ switch (imr.imr_nexthop.ss_family) {
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) &imr.imr_nexthop;
+ if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
+ strlcpy(hbuf, "???", sizeof(hbuf));
+ printf("%s\n", hbuf);
+ break;
+ case AF_INET:
+ sin = (struct sockaddr_in *) &imr.imr_nexthop;
+ printf("%s\n", inet_ntoa(sin->sin_addr));
+ break;
+ default:
+ printf("none\n");
+ }
}
/* ARGSUSED */
@@ -3870,6 +3883,7 @@ void
process_mpw_commands(void)
{
struct sockaddr_in *sin, *sinn;
+ struct sockaddr_in6 *sin6, *sin6n;
struct ifmpwreq imr;
if (wconfig == 0)
@@ -3899,14 +3913,29 @@ process_mpw_commands(void)
imrsave.imr_rshim.shim_label = imr.imr_rshim.shim_label;
}
- sin = (struct sockaddr_in *) &imrsave.imr_nexthop;
- sinn = (struct sockaddr_in *) &imr.imr_nexthop;
- if (sin->sin_addr.s_addr == 0) {
- if (sinn->sin_addr.s_addr == 0)
+ switch (imrsave.imr_nexthop.ss_family) {
+ case AF_INET6:
+ case AF_INET:
+ /* neighbor was set earlier, nothing to do */
+ break;
+ default:
+ switch (imr.imr_nexthop.ss_family) {
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) &imrsave.imr_nexthop;
+ sin6n = (struct sockaddr_in6 *) &imr.imr_nexthop;
+ sin6->sin6_family = sin6n->sin6_family;
+ memcpy(&sin6->sin6_addr, &sin6n->sin6_addr,
+ sizeof(struct in6_addr));
+ break;
+ case AF_INET:
+ sin = (struct sockaddr_in *) &imrsave.imr_nexthop;
+ sinn = (struct sockaddr_in *) &imr.imr_nexthop;
+ sin->sin_family = sinn->sin_family;
+ sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+ break;
+ default:
errx(1, "mpw neighbor address not specified");
-
- sin->sin_family = sinn->sin_family;
- sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+ }
}
ifr.ifr_data = (caddr_t) &imrsave;
@@ -3949,14 +3978,41 @@ void
setmpwneighbor(const char *value, int d)
{
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ struct addrinfo hints, *res;
+ int rv;
wconfig = 1;
- sin = (struct sockaddr_in *) &imrsave.imr_nexthop;
- if (inet_aton(value, &sin->sin_addr) == 0)
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_PASSIVE;
+
+ rv = getaddrinfo(value, NULL, &hints, &res);
+ if (rv != 0)
+ errx(1, "neighbor %s: %s", value, gai_strerror(rv));
+
+ switch (res->ai_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *) &imrsave.imr_nexthop;
+ sin->sin_family = res->ai_family;
+ sin->sin_addr.s_addr =
+ ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) &imrsave.imr_nexthop;
+ sin6->sin6_family = res->ai_family;
+ memcpy(&sin6->sin6_addr,
+ &((struct sockaddr_in6*)res->ai_addr)->sin6_addr,
+ sizeof(struct in6_addr));
+ break;
+ default:
errx(1, "invalid neighbor addresses");
+ }
- sin->sin_family = AF_INET;
+ freeaddrinfo(res);
}
void