@@ -282,6 +282,7 @@ struct nd_opt_hdr { /* Neighbor discovery option header */
282
282
#define ND_OPT_ROUTE_INFO 24 /* RFC4191 */
283
283
#define ND_OPT_RDNSS 25
284
284
#define ND_OPT_DNSSL 31
285
+ #define ND_OPT_PREF64_INFORMATION 38 /* RFC8781 */
285
286
286
287
struct nd_opt_prefix_info { /* prefix information */
287
288
nd_uint8_t nd_opt_pi_type ;
@@ -353,6 +354,13 @@ struct nd_opt_route_info { /* route info */
353
354
/* prefix follows */
354
355
};
355
356
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
+
356
364
/*
357
365
* icmp6 namelookup
358
366
*/
@@ -494,6 +502,8 @@ struct rr_result { /* router renumbering result message */
494
502
495
503
static const char * get_rtpref (u_int );
496
504
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 );
497
507
static void print_lladdr (netdissect_options * ndo , const u_char * , size_t );
498
508
static int icmp6_opt_print (netdissect_options * ndo , const u_char * , int );
499
509
static void mld6_print (netdissect_options * ndo , const u_char * );
@@ -732,6 +742,7 @@ static const struct tok icmp6_opt_values[] = {
732
742
{ ND_OPT_ADVINTERVAL , "advertisement interval" },
733
743
{ ND_OPT_HOMEAGENT_INFO , "homeagent information" },
734
744
{ ND_OPT_ROUTE_INFO , "route info" },
745
+ { ND_OPT_PREF64_INFORMATION , "pref64 info" },
735
746
{ 0 , NULL }
736
747
};
737
748
@@ -772,6 +783,30 @@ get_lifetime(uint32_t v)
772
783
}
773
784
}
774
785
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
+
775
810
static void
776
811
print_lladdr (netdissect_options * ndo , const uint8_t * p , size_t l )
777
812
{
@@ -1414,10 +1449,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1414
1449
const struct nd_opt_advinterval * opa ;
1415
1450
const struct nd_opt_homeagent_info * oph ;
1416
1451
const struct nd_opt_route_info * opri ;
1452
+ const struct nd_opt_pref64 * op64 ;
1417
1453
const u_char * cp , * ep , * domp ;
1418
1454
nd_ipv6 in6 ;
1419
1455
size_t l ;
1420
1456
u_int i ;
1457
+ uint16_t w ;
1421
1458
1422
1459
cp = bp ;
1423
1460
/* 'ep' points to the end of available data. */
@@ -1527,6 +1564,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1527
1564
ND_PRINT (", lifetime=%s" ,
1528
1565
get_lifetime (GET_BE_U_4 (opri -> nd_opt_rti_lifetime )));
1529
1566
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 ;
1530
1581
default :
1531
1582
if (ndo -> ndo_vflag <= 1 ) {
1532
1583
print_unknown_data (ndo ,cp + 2 ,"\n\t " , (opt_len << 3 ) - 2 ); /* skip option header */
0 commit comments