Skip to content

Commit 43c5b31

Browse files
committed
ICMPv6: Recognise ND option 38 (PREF64)
This option, defined in RFC 8781, allows a router administrator to pass NAT64 prefix information for the network to end hosts together with other routing and prefix information in the RA message, getting rid of the need for DNS64 service in the network. As of today the option is widely supported by software routers, including radvd, BIRD and systemd-networkd. We implement the printer and test some valid and broken option contents.
1 parent 2c5130e commit 43c5b31

File tree

5 files changed

+109
-0
lines changed

5 files changed

+109
-0
lines changed

print-icmp6.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ struct nd_opt_hdr { /* Neighbor discovery option header */
282282
#define ND_OPT_ROUTE_INFO 24 /* RFC4191 */
283283
#define ND_OPT_RDNSS 25
284284
#define ND_OPT_DNSSL 31
285+
#define ND_OPT_PREF64_INFORMATION 38 /* RFC8781 */
285286

286287
struct nd_opt_prefix_info { /* prefix information */
287288
nd_uint8_t nd_opt_pi_type;
@@ -353,6 +354,13 @@ struct nd_opt_route_info { /* route info */
353354
/* prefix follows */
354355
};
355356

357+
struct nd_opt_pref64 { /* PREF64 option */
358+
nd_uint8_t nd_opt_pref64_type;
359+
nd_uint8_t nd_opt_pref64_len;
360+
nd_uint16_t nd_opt_pref64_slplc; /* 13bit lft + 3bit PLC */
361+
nd_uint32_t nd_opt_pref64_words[3]; /* highest 96 bits of prefix */
362+
};
363+
356364
/*
357365
* icmp6 namelookup
358366
*/
@@ -494,6 +502,8 @@ struct rr_result { /* router renumbering result message */
494502

495503
static const char *get_rtpref(u_int);
496504
static const char *get_lifetime(uint32_t);
505+
static const char *get_pref64_lifetime(uint16_t);
506+
static const char *get_pref64_len_repr(uint16_t);
497507
static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
498508
static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
499509
static void mld6_print(netdissect_options *ndo, const u_char *);
@@ -732,6 +742,7 @@ static const struct tok icmp6_opt_values[] = {
732742
{ ND_OPT_ADVINTERVAL, "advertisement interval"},
733743
{ ND_OPT_HOMEAGENT_INFO, "homeagent information"},
734744
{ ND_OPT_ROUTE_INFO, "route info"},
745+
{ ND_OPT_PREF64_INFORMATION, "pref64 info"},
735746
{ 0, NULL }
736747
};
737748

@@ -772,6 +783,30 @@ get_lifetime(uint32_t v)
772783
}
773784
}
774785

786+
static const char *
787+
get_pref64_lifetime(uint16_t v)
788+
{
789+
static char buf[12];
790+
791+
snprintf(buf, sizeof(buf), "%us", v & 0xfff8);
792+
return buf;
793+
}
794+
795+
static const char *
796+
get_pref64_len_repr(uint16_t v)
797+
{
798+
const char *prefixlen_strunk = "??";
799+
static const char *prefixlen_str[] = {
800+
"96", "64", "56", "48", "40", "32"
801+
};
802+
803+
v = v & 0x0007;
804+
if (v < 6)
805+
return prefixlen_str[v];
806+
else
807+
return prefixlen_strunk;
808+
}
809+
775810
static void
776811
print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
777812
{
@@ -1414,10 +1449,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
14141449
const struct nd_opt_advinterval *opa;
14151450
const struct nd_opt_homeagent_info *oph;
14161451
const struct nd_opt_route_info *opri;
1452+
const struct nd_opt_pref64 *op64;
14171453
const u_char *cp, *ep, *domp;
14181454
nd_ipv6 in6;
14191455
size_t l;
14201456
u_int i;
1457+
uint16_t w;
14211458

14221459
cp = bp;
14231460
/* 'ep' points to the end of available data. */
@@ -1527,6 +1564,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
15271564
ND_PRINT(", lifetime=%s",
15281565
get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime)));
15291566
break;
1567+
case ND_OPT_PREF64_INFORMATION:
1568+
op64 = (const struct nd_opt_pref64 *)op;
1569+
if (opt_len != 2)
1570+
ND_PRINT("%s", "bad option length! ");
1571+
w = GET_BE_U_2(op64->nd_opt_pref64_slplc);
1572+
memset(&in6, 0, sizeof(in6));
1573+
GET_CPY_BYTES(&in6, op64->nd_opt_pref64_words,
1574+
sizeof(op64->nd_opt_pref64_words));
1575+
ND_PRINT("%s/%s (plc %u)",
1576+
ip6addr_string(ndo, (const u_char *)&in6),
1577+
get_pref64_len_repr(w),
1578+
w & 7);
1579+
ND_PRINT(", lifetime %s", get_pref64_lifetime(w));
1580+
break;
15301581
default:
15311582
if (ndo->ndo_vflag <= 1) {
15321583
print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */

tests/TESTLIST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ icmpv6_nodeinfo_queryipv4 icmpv6_nodeinfo_queryipv4.pcap icmpv6_nodeinfo_queryip
246246
icmpv6_nodeinfo_replyipv4 icmpv6_nodeinfo_replyipv4.pcap icmpv6_nodeinfo_replyipv4.out -v
247247
icmpv6_nodeinfo_queryipv6 icmpv6_nodeinfo_queryipv6.pcap icmpv6_nodeinfo_queryipv6.out -v
248248
icmpv6_nodeinfo_replyipv6 icmpv6_nodeinfo_replyipv6.pcap icmpv6_nodeinfo_replyipv6.out -v
249+
icmpv6-ra-pref64-v1 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v1.out -v
250+
icmpv6-ra-pref64-v2 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v2.out -vv
249251

250252
# SPB tests
251253
spb spb.pcap spb.out

tests/icmpv6-ra-pref64-v1.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
1 2023-12-04 20:18:21.401201 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
2+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
3+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
4+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
5+
pref64 info option (38), length 16 (2): 2001:db8:1:64:ff9b::/96 (plc 0), lifetime 0s
6+
2 2023-12-04 20:18:24.401773 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
7+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
8+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
9+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
10+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/?? (plc 6), lifetime 1800s
11+
3 2023-12-04 20:18:27.402345 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
12+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
13+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
14+
prefix info option (3), length 32 (4): 2a00:f480:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
15+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 1800s
16+
4 2023-12-04 20:18:30.402917 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
17+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
18+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
19+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
20+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 65528s

tests/icmpv6-ra-pref64-v2.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
1 2023-12-04 20:18:21.401201 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
2+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
3+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
4+
0x0000: e215 81b4 b945
5+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
6+
0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001
7+
0x0010: 0db8 00cc 00dd 0000 0000 0000 0000
8+
pref64 info option (38), length 16 (2): 2001:db8:1:64:ff9b::/96 (plc 0), lifetime 0s
9+
0x0000: 0000 2001 0db8 0001 0064 ff9b 0000
10+
2 2023-12-04 20:18:24.401773 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
11+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
12+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
13+
0x0000: e215 81b4 b945
14+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
15+
0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001
16+
0x0010: 0db8 00cc 00dd 0000 0000 0000 0000
17+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/?? (plc 6), lifetime 1800s
18+
0x0000: 070e 2001 0db8 0000 0064 ff9b 0000
19+
3 2023-12-04 20:18:27.402345 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
20+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
21+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
22+
0x0000: e215 81b4 b945
23+
prefix info option (3), length 32 (4): 2a00:f480:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
24+
0x0000: 4080 0000 0e10 0000 0708 0000 0000 2a00
25+
0x0010: f480 00cc 00dd 0000 0000 0000 0000
26+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 1800s
27+
0x0000: 0708 2001 0db8 0000 0064 ff9b 0000
28+
4 2023-12-04 20:18:30.402917 IP6 (flowlabel 0x9fc72, hlim 255, next-header ICMPv6 (58), payload length 72) fe80::e015:81ff:feb4:b945 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 72
29+
hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms
30+
source link-address option (1), length 8 (1): e2:15:81:b4:b9:45
31+
0x0000: e215 81b4 b945
32+
prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s
33+
0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001
34+
0x0010: 0db8 00cc 00dd 0000 0000 0000 0000
35+
pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 65528s
36+
0x0000: fff8 2001 0db8 0000 0064 ff9b 0000

tests/icmpv6-ra-pref64.pcap

592 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)