diff --git a/print-icmp6.c b/print-icmp6.c index d1c2a5195..09540604a 100644 --- a/print-icmp6.c +++ b/print-icmp6.c @@ -286,6 +286,7 @@ struct nd_opt_hdr { /* Neighbor discovery option header */ #define ND_OPT_ROUTE_INFO 24 /* RFC4191 */ #define ND_OPT_RDNSS 25 #define ND_OPT_DNSSL 31 +#define ND_OPT_PREF64_INFORMATION 38 /* RFC8781 */ struct nd_opt_prefix_info { /* prefix information */ nd_uint8_t nd_opt_pi_type; @@ -357,6 +358,13 @@ struct nd_opt_route_info { /* route info */ /* prefix follows */ }; +struct nd_opt_pref64 { /* PREF64 option */ + nd_uint8_t nd_opt_pref64_type; + nd_uint8_t nd_opt_pref64_len; + nd_uint16_t nd_opt_pref64_slplc; /* 13bit lft + 3bit PLC */ + nd_uint32_t nd_opt_pref64_words[3]; /* highest 96 bits of prefix */ +}; + /* * icmp6 namelookup */ @@ -475,6 +483,8 @@ struct rr_result { /* router renumbering result message */ static const char *get_rtpref(u_int); static const char *get_lifetime(uint32_t); +static const char *get_pref64_lifetime(uint16_t); +static const char *get_pref64_len_repr(uint16_t); static void print_lladdr(netdissect_options *ndo, const u_char *, size_t); static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int); static void mld6_print(netdissect_options *ndo, const u_char *); @@ -713,6 +723,7 @@ static const struct tok icmp6_opt_values[] = { { ND_OPT_ADVINTERVAL, "advertisement interval"}, { ND_OPT_HOMEAGENT_INFO, "homeagent information"}, { ND_OPT_ROUTE_INFO, "route info"}, + { ND_OPT_PREF64_INFORMATION, "pref64 info"}, { 0, NULL } }; @@ -753,6 +764,30 @@ get_lifetime(uint32_t v) } } +static const char * +get_pref64_lifetime(uint16_t v) +{ + static char buf[12]; + + snprintf(buf, sizeof(buf), "%us", v & 0xfff8); + return buf; +} + +static const char * +get_pref64_len_repr(uint16_t v) +{ + const char *prefixlen_strunk = "??"; + static const char *prefixlen_str[] = { + "96", "64", "56", "48", "40", "32" + }; + + v = v & 0x0007; + if (v < 6) + return prefixlen_str[v]; + else + return prefixlen_strunk; +} + static void print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l) { @@ -1383,10 +1418,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) const struct nd_opt_advinterval *opa; const struct nd_opt_homeagent_info *oph; const struct nd_opt_route_info *opri; + const struct nd_opt_pref64 *op64; const u_char *cp, *ep, *domp; nd_ipv6 in6; size_t l; u_int i; + uint16_t w; cp = bp; /* 'ep' points to the end of available data. */ @@ -1496,6 +1533,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) ND_PRINT(", lifetime=%s", get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime))); break; + case ND_OPT_PREF64_INFORMATION: + op64 = (const struct nd_opt_pref64 *)op; + if (opt_len != 2) + ND_PRINT("%s", "bad option length! "); + w = GET_BE_U_2(op64->nd_opt_pref64_slplc); + memset(&in6, 0, sizeof(in6)); + GET_CPY_BYTES(&in6, op64->nd_opt_pref64_words, + sizeof(op64->nd_opt_pref64_words)); + ND_PRINT("%s/%s (plc %u)", + ip6addr_string(ndo, (const u_char *)&in6), + get_pref64_len_repr(w), + w & 7); + ND_PRINT(", lifetime %s", get_pref64_lifetime(w)); + break; default: if (ndo->ndo_vflag <= 1) { print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */ diff --git a/tests/TESTLIST b/tests/TESTLIST index a9e4be1c3..be8f00e42 100644 --- a/tests/TESTLIST +++ b/tests/TESTLIST @@ -224,6 +224,8 @@ icmpv6-rfc7112 icmpv6-rfc7112.pcap icmpv6-rfc7112.out icmpv6-RFC2894-RR icmpv6-RFC2894-RR.pcap icmpv6-RFC2894-RR.out icmpv6-RFC2894-RR-v icmpv6-RFC2894-RR.pcap icmpv6-RFC2894-RR-v.out -v icmpv6-ni-flags icmpv6-ni-flags.pcap icmpv6-ni-flags.out +icmpv6-ra-pref64-v1 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v1.out -v +icmpv6-ra-pref64-v2 icmpv6-ra-pref64.pcap icmpv6-ra-pref64-v2.out -vv # SPB tests spb spb.pcap spb.out diff --git a/tests/icmpv6-ra-pref64-v1.out b/tests/icmpv6-ra-pref64-v1.out new file mode 100644 index 000000000..0d44fc8aa --- /dev/null +++ b/tests/icmpv6-ra-pref64-v1.out @@ -0,0 +1,20 @@ + 1 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + pref64 info option (38), length 16 (2): 2001:db8:1:64:ff9b::/96 (plc 0), lifetime 0s + 2 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/?? (plc 6), lifetime 1800s + 3 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + prefix info option (3), length 32 (4): 2a00:f480:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 1800s + 4 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 65528s diff --git a/tests/icmpv6-ra-pref64-v2.out b/tests/icmpv6-ra-pref64-v2.out new file mode 100644 index 000000000..4a8c9f66b --- /dev/null +++ b/tests/icmpv6-ra-pref64-v2.out @@ -0,0 +1,36 @@ + 1 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + 0x0000: e215 81b4 b945 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + 0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001 + 0x0010: 0db8 00cc 00dd 0000 0000 0000 0000 + pref64 info option (38), length 16 (2): 2001:db8:1:64:ff9b::/96 (plc 0), lifetime 0s + 0x0000: 0000 2001 0db8 0001 0064 ff9b 0000 + 2 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + 0x0000: e215 81b4 b945 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + 0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001 + 0x0010: 0db8 00cc 00dd 0000 0000 0000 0000 + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/?? (plc 6), lifetime 1800s + 0x0000: 070e 2001 0db8 0000 0064 ff9b 0000 + 3 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + 0x0000: e215 81b4 b945 + prefix info option (3), length 32 (4): 2a00:f480:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + 0x0000: 4080 0000 0e10 0000 0708 0000 0000 2a00 + 0x0010: f480 00cc 00dd 0000 0000 0000 0000 + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 1800s + 0x0000: 0708 2001 0db8 0000 0064 ff9b 0000 + 4 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 + hop limit 80, Flags [other stateful], pref medium, router lifetime 500s, reachable time 0ms, retrans timer 0ms + source link-address option (1), length 8 (1): e2:15:81:b4:b9:45 + 0x0000: e215 81b4 b945 + prefix info option (3), length 32 (4): 2001:db8:cc:dd::/64, Flags [onlink], valid time 3600s, pref. time 1800s + 0x0000: 4080 0000 0e10 0000 0708 0000 0000 2001 + 0x0010: 0db8 00cc 00dd 0000 0000 0000 0000 + pref64 info option (38), length 16 (2): 2001:db8:0:64:ff9b::/96 (plc 0), lifetime 65528s + 0x0000: fff8 2001 0db8 0000 0064 ff9b 0000 diff --git a/tests/icmpv6-ra-pref64.pcap b/tests/icmpv6-ra-pref64.pcap new file mode 100644 index 000000000..4a405978d Binary files /dev/null and b/tests/icmpv6-ra-pref64.pcap differ