@@ -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" },
737
747
{ 0 , NULL }
738
748
};
739
749
@@ -774,6 +784,20 @@ 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
+ static const char * prefixlen_str [] = {
791
+ "96" , "64" , "56" , "48" , "40" , "32"
792
+ };
793
+
794
+ v = v & 0x0007 ;
795
+ if (v < 6 )
796
+ return prefixlen_str [v ];
797
+ else
798
+ return "??" ;
799
+ }
800
+
777
801
static void
778
802
print_lladdr (netdissect_options * ndo , const uint8_t * p , size_t l )
779
803
{
@@ -1416,10 +1440,12 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1416
1440
const struct nd_opt_advinterval * opa ;
1417
1441
const struct nd_opt_homeagent_info * oph ;
1418
1442
const struct nd_opt_route_info * opri ;
1443
+ const struct nd_opt_pref64 * op64 ;
1419
1444
const u_char * cp , * ep , * domp ;
1420
1445
nd_ipv6 in6 ;
1421
1446
size_t l ;
1422
1447
u_int i ;
1448
+ uint16_t w ;
1423
1449
1424
1450
cp = bp ;
1425
1451
/* 'ep' points to the end of available data. */
@@ -1533,6 +1559,20 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
1533
1559
ND_PRINT (", lifetime=%s" ,
1534
1560
get_lifetime (GET_BE_U_4 (opri -> nd_opt_rti_lifetime )));
1535
1561
break ;
1562
+ case ND_OPT_PREF64_INFORMATION :
1563
+ op64 = (const struct nd_opt_pref64 * )op ;
1564
+ if (opt_len != 2 )
1565
+ ND_PRINT ("%s" , "bad option length! " );
1566
+ w = GET_BE_U_2 (op64 -> nd_opt_pref64_slplc );
1567
+ memset (& in6 , 0 , sizeof (in6 ));
1568
+ GET_CPY_BYTES (& in6 , op64 -> nd_opt_pref64_words ,
1569
+ sizeof (op64 -> nd_opt_pref64_words ));
1570
+ ND_PRINT ("%s/%s (plc %u), lifetime %us" ,
1571
+ ip6addr_string (ndo , (const u_char * )& in6 ),
1572
+ get_pref64_len_repr (w ),
1573
+ w & 0x0007 ,
1574
+ w & 0xfff8 );
1575
+ break ;
1536
1576
default :
1537
1577
if (ndo -> ndo_vflag <= 1 ) {
1538
1578
print_unknown_data (ndo ,cp + 2 ,"\n\t " , (opt_len << 3 ) - 2 ); /* skip option header */
0 commit comments