@@ -283,6 +283,7 @@ struct nd_opt_hdr { /* Neighbor discovery option header */
283
283
#define ND_OPT_ROUTE_INFO 24 /* RFC4191 */
284
284
#define ND_OPT_RDNSS 25
285
285
#define ND_OPT_DNSSL 31
286
+ #define ND_OPT_PREF64_INFORMATION 38 /* RFC8781 */
286
287
287
288
struct nd_opt_prefix_info { /* prefix information */
288
289
nd_uint8_t nd_opt_pi_type ;
@@ -354,6 +355,13 @@ struct nd_opt_route_info { /* route info */
354
355
/* prefix follows */
355
356
};
356
357
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
+
357
365
/*
358
366
* icmp6 namelookup
359
367
*/
@@ -495,6 +503,7 @@ struct rr_result { /* router renumbering result message */
495
503
496
504
static const char * get_rtpref (u_int );
497
505
static const char * get_lifetime (uint32_t );
506
+ static const char * get_pref64_len_repr (uint16_t );
498
507
static void print_lladdr (netdissect_options * ndo , const u_char * , size_t );
499
508
static int icmp6_opt_print (netdissect_options * ndo , const u_char * , int );
500
509
static void mld6_print (netdissect_options * ndo , const u_char * );
@@ -734,6 +743,7 @@ static const struct tok icmp6_opt_values[] = {
734
743
{ ND_OPT_HOMEAGENT_INFO , "homeagent information" },
735
744
{ ND_OPT_NONCE , "nonce" },
736
745
{ ND_OPT_ROUTE_INFO , "route info" },
746
+ { ND_OPT_PREF64_INFORMATION , "pref64 info" },
737
747
{ 0 , NULL }
738
748
};
739
749
@@ -774,6 +784,21 @@ get_lifetime(uint32_t v)
774
784
}
775
785
}
776
786
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
+
777
802
static void
778
803
print_lladdr (netdissect_options * ndo , const uint8_t * p , size_t l )
779
804
{
@@ -1416,10 +1441,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1416
1441
const struct nd_opt_advinterval * opa ;
1417
1442
const struct nd_opt_homeagent_info * oph ;
1418
1443
const struct nd_opt_route_info * opri ;
1444
+ const struct nd_opt_pref64 * op64 ;
1419
1445
const u_char * cp , * ep , * domp ;
1420
1446
nd_ipv6 in6 ;
1421
1447
size_t l ;
1422
1448
u_int i ;
1449
+ uint16_t w ;
1423
1450
1424
1451
cp = bp ;
1425
1452
/* 'ep' points to the end of available data. */
@@ -1533,6 +1560,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1533
1560
ND_PRINT (", lifetime=%s" ,
1534
1561
get_lifetime (GET_BE_U_4 (opri -> nd_opt_rti_lifetime )));
1535
1562
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 ;
1536
1577
default :
1537
1578
if (ndo -> ndo_vflag <= 1 ) {
1538
1579
print_unknown_data (ndo ,cp + 2 ,"\n\t " , (opt_len << 3 ) - 2 ); /* skip option header */
0 commit comments