Skip to content

Commit 10e75cb

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 f40911a commit 10e75cb

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

print-icmp6.c

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

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

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

496504
static const char *get_rtpref(u_int);
497505
static const char *get_lifetime(uint32_t);
506+
static const char *get_pref64_len_repr(uint16_t);
498507
static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
499508
static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
500509
static void mld6_print(netdissect_options *ndo, const u_char *);
@@ -734,6 +743,7 @@ static const struct tok icmp6_opt_values[] = {
734743
{ ND_OPT_HOMEAGENT_INFO, "homeagent information"},
735744
{ ND_OPT_NONCE, "nonce"},
736745
{ ND_OPT_ROUTE_INFO, "route info"},
746+
{ ND_OPT_PREF64_INFORMATION, "pref64 info"},
737747
{ 0, NULL }
738748
};
739749

@@ -774,6 +784,21 @@ get_lifetime(uint32_t v)
774784
}
775785
}
776786

787+
static const char *
788+
get_pref64_len_repr(uint16_t v)
789+
{
790+
const char *prefixlen_strunk = "??";
791+
static const char *prefixlen_str[] = {
792+
"96", "64", "56", "48", "40", "32"
793+
};
794+
795+
v = v & 0x0007;
796+
if (v < 6)
797+
return prefixlen_str[v];
798+
else
799+
return prefixlen_strunk;
800+
}
801+
777802
static void
778803
print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
779804
{
@@ -1416,10 +1441,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
14161441
const struct nd_opt_advinterval *opa;
14171442
const struct nd_opt_homeagent_info *oph;
14181443
const struct nd_opt_route_info *opri;
1444+
const struct nd_opt_pref64 *op64;
14191445
const u_char *cp, *ep, *domp;
14201446
nd_ipv6 in6;
14211447
size_t l;
14221448
u_int i;
1449+
uint16_t w;
14231450

14241451
cp = bp;
14251452
/* 'ep' points to the end of available data. */
@@ -1533,6 +1560,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
15331560
ND_PRINT(", lifetime=%s",
15341561
get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime)));
15351562
break;
1563+
case ND_OPT_PREF64_INFORMATION:
1564+
op64 = (const struct nd_opt_pref64 *)op;
1565+
if (opt_len != 2)
1566+
ND_PRINT("%s", "bad option length! ");
1567+
w = GET_BE_U_2(op64->nd_opt_pref64_slplc);
1568+
memset(&in6, 0, sizeof(in6));
1569+
GET_CPY_BYTES(&in6, op64->nd_opt_pref64_words,
1570+
sizeof(op64->nd_opt_pref64_words));
1571+
ND_PRINT("%s/%s (plc %u), lifetime %us",
1572+
ip6addr_string(ndo, (const u_char *)&in6),
1573+
get_pref64_len_repr(w),
1574+
w & 7,
1575+
w & 0xfff8);
1576+
break;
15361577
default:
15371578
if (ndo->ndo_vflag <= 1) {
15381579
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
@@ -249,6 +249,8 @@ icmpv6_nodeinfo_replyipv6 icmpv6_nodeinfo_replyipv6.pcap icmpv6_nodeinfo_replyip
249249
icmpv6-ns-nonce-v0 icmpv6-ns-nonce.pcap icmpv6-ns-nonce-v0.out
250250
icmpv6-ns-nonce-v1 icmpv6-ns-nonce.pcap icmpv6-ns-nonce-v1.out -v
251251
icmpv6-ns-nonce-v2 icmpv6-ns-nonce.pcap icmpv6-ns-nonce-v2.out -vv
252+
icmpv6-ra-pref64-v1 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v1.out -v
253+
icmpv6-ra-pref64-v2 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v2.out -vv
252254

253255
# SPB tests
254256
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)