@@ -217,6 +217,33 @@ static const struct tok lsa_opaque_ri_tlv_sr_algos[] = {
217217 { 0 , NULL }
218218};
219219
220+ static const struct tok lsa_opaque_el_tlv_values [] = {
221+ { LS_OPAQUE_EXTENDED_LINK_TLV , "Extended Link" },
222+ { 0 , NULL }
223+ };
224+
225+ static const struct tok lsa_opaque_extended_link_link_type_values [] = {
226+ { RLA_TYPE_ROUTER , "Point-to-Point Link" },
227+ { RLA_TYPE_TRANSIT , "Link to Transit Network" },
228+ { RLA_TYPE_STUB , "Link to Stub Network" },
229+ { RLA_TYPE_VIRTUAL , "Virtual Link" },
230+ { 0 , NULL }
231+ };
232+
233+ static const struct tok lsa_opaque_extended_link_subtlv_adj_sid_flag_values [] = {
234+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_B , "Backup" },
235+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_V , "Value/Index" },
236+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_L , "Local/Global" },
237+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_G , "Group" },
238+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_P , "Persistent" },
239+ { 0 , NULL }
240+ };
241+
242+ static const struct tok lsa_opaque_extended_link_subtlv_values [] = {
243+ { LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID , "Adj-SID Sub-TLV" },
244+ { 0 , NULL }
245+ };
246+
220247static const struct tok ospf_lls_tlv_values [] = {
221248 { OSPF_LLS_EO , "Extended Options" },
222249 { OSPF_LLS_MD5 , "MD5 Authentication" },
@@ -930,6 +957,113 @@ ospf_ep_lsa_print(netdissect_options *ndo, const uint8_t *tptr, u_int lsa_length
930957 return 0 ;
931958}
932959
960+ static int
961+ ospf_el_lsa_print (netdissect_options * ndo , const uint8_t * tptr , u_int lsa_length )
962+ {
963+ u_int tlv_type , tlv_length , link_type , sub_tlv_flags ;
964+ u_int sub_tlv_type , sub_tlv_length , sub_tlv_remaining ;
965+ const uint8_t * sub_tlv_tptr ;
966+ u_int vflag , lflag ;
967+
968+ while (lsa_length >= 4 ) {
969+ tlv_type = GET_BE_U_2 (tptr );
970+ tlv_length = GET_BE_U_2 (tptr + 2 );
971+ tptr += 4 ;
972+ lsa_length -= 4 ;
973+
974+ /* Infinite loop protection. */
975+ if (tlv_type == 0 || tlv_length == 0 ) {
976+ return -1 ;
977+ }
978+
979+ ND_PRINT ("\n\t %s TLV (%u), length: %u, value: " ,
980+ tok2str (lsa_opaque_el_tlv_values ,"unknown" ,tlv_type ),
981+ tlv_type ,
982+ tlv_length );
983+
984+ switch (tlv_type ) {
985+ case LS_OPAQUE_EXTENDED_LINK_TLV :
986+ link_type = GET_U_1 (tptr );
987+
988+ ND_PRINT ("\n\t Link Type: %s (%u)" ,
989+ tok2str (lsa_opaque_extended_link_link_type_values ,"unknown" ,link_type ),
990+ link_type );
991+ ND_PRINT ("\n\t Reserved: %u" , GET_BE_U_3 (tptr + 1 ));
992+ ND_PRINT ("\n\t Link ID: %s" , GET_IPADDR_STRING (tptr + 4 ));
993+ ND_PRINT ("\n\t Link Data: %s" , GET_IPADDR_STRING (tptr + 8 ));
994+
995+ sub_tlv_tptr = tptr + 12 ;
996+ sub_tlv_remaining = tlv_length - 12 ;
997+
998+ while (sub_tlv_remaining > 0 ) {
999+ sub_tlv_type = GET_BE_U_2 (sub_tlv_tptr );
1000+ sub_tlv_length = GET_BE_U_2 (sub_tlv_tptr + 2 );
1001+ sub_tlv_remaining -= 4 ;
1002+ sub_tlv_tptr += 4 ;
1003+
1004+ ND_PRINT ("\n\t %s (%u), length: %u, value: " ,
1005+ tok2str (lsa_opaque_extended_link_subtlv_values ,"unknown" ,sub_tlv_type ),
1006+ sub_tlv_type ,
1007+ sub_tlv_length );
1008+
1009+ switch (sub_tlv_type ){
1010+
1011+ case LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID :
1012+ sub_tlv_flags = GET_U_1 (sub_tlv_tptr );
1013+
1014+ ND_PRINT ("\n\t Flags: [%s]" ,
1015+ bittok2str (lsa_opaque_extended_link_subtlv_adj_sid_flag_values , "none" , sub_tlv_flags ));
1016+ ND_PRINT ("\n\t Reserved: %u" , GET_U_1 (sub_tlv_tptr + 1 ));
1017+ ND_PRINT ("\n\t MT-ID: %u" , GET_U_1 (sub_tlv_tptr + 2 ));
1018+ ND_PRINT ("\n\t Weight: %u" , GET_U_1 (sub_tlv_tptr + 3 ));
1019+
1020+ vflag = sub_tlv_flags & LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_V ;
1021+ lflag = sub_tlv_flags & LS_OPAQUE_EXTENDED_LINK_SUBTLV_ADJ_SID_FLAG_L ;
1022+ if (vflag && lflag ) {
1023+ ND_PRINT ("\n\t SID/Label: %u" ,GET_BE_U_3 (sub_tlv_tptr + 4 ));
1024+ }
1025+ else if ( !vflag && !lflag ) {
1026+ ND_PRINT ("\n\t SID/Label: %u" ,GET_BE_U_4 (sub_tlv_tptr + 4 ));
1027+ }
1028+ else {
1029+ ND_PRINT ("\n\t Invalid V-Flag and L-flag combination" );
1030+ if (!print_unknown_data (ndo , sub_tlv_tptr , "\n\t " , sub_tlv_length ))
1031+ return (-1 );
1032+ }
1033+ break ;
1034+
1035+ default :
1036+ if (ndo -> ndo_vflag <= 1 ) {
1037+ if (!print_unknown_data (ndo , sub_tlv_tptr , "\n\t " , sub_tlv_length ))
1038+ return (-1 );
1039+ }
1040+ break ;
1041+ }
1042+
1043+ if (sub_tlv_length % 4 ) {
1044+ sub_tlv_length += (4 - (sub_tlv_length % 4 ));
1045+ }
1046+ sub_tlv_tptr += sub_tlv_length ;
1047+ sub_tlv_remaining -= sub_tlv_length ;
1048+ }
1049+ break ;
1050+ default :
1051+ if (ndo -> ndo_vflag <= 1 ) {
1052+ if (!print_unknown_data (ndo , tptr , "\n\t " , tlv_length ))
1053+ return -1 ;
1054+ }
1055+ }
1056+
1057+ /* in OSPF everything has to be 32-bit aligned, including TLVs */
1058+ if (tlv_length % 4 ) {
1059+ tlv_length += (4 - (tlv_length % 4 ));
1060+ }
1061+ tptr += tlv_length ;
1062+ lsa_length -= tlv_length ;
1063+ }
1064+ return 0 ;
1065+ }
1066+
9331067/*
9341068 * Print a single link state advertisement. If truncated or if LSA length
9351069 * field is less than the length of the LSA header, return NULl, else
@@ -1231,6 +1365,13 @@ ospf_print_lsa(netdissect_options *ndo,
12311365 }
12321366 break ;
12331367
1368+ case LS_OPAQUE_TYPE_EL :
1369+ if (ospf_el_lsa_print (ndo , (const u_char * )(lsap -> lsa_un .un_el_tlv ),
1370+ ls_length ) == -1 ) {
1371+ return (ls_end );
1372+ }
1373+ break ;
1374+
12341375 default :
12351376 if (ndo -> ndo_vflag <= 1 ) {
12361377 if (!print_unknown_data (ndo , (const uint8_t * )lsap -> lsa_un .un_unknown ,
0 commit comments