Skip to content

Commit 6883ca6

Browse files
Hannes Gredlerfxlb
authored andcommitted
OSPF: add support for segment routing extensions and hostname extensions
Support for segment routing extensions as per rfc8665 and rfc7684. Support for hostname extensions as per rfc5642. Add two test files, one for extended prefix LSA.
1 parent 87c9001 commit 6883ca6

File tree

7 files changed

+401
-1
lines changed

7 files changed

+401
-1
lines changed

ospf.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#define LS_OPAQUE_TYPE_TE 1 /* rfc3630 */
7373
#define LS_OPAQUE_TYPE_GRACE 3 /* rfc3623 */
7474
#define LS_OPAQUE_TYPE_RI 4 /* draft-ietf-ospf-cap-03 */
75+
#define LS_OPAQUE_TYPE_EP 7 /* rfc7684 */
7576

7677
#define LS_OPAQUE_TE_TLV_ROUTER 1 /* rfc3630 */
7778
#define LS_OPAQUE_TE_TLV_LINK 2 /* rfc3630 */
@@ -94,6 +95,12 @@
9495
#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP 1 /* rfc3630 */
9596
#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA 2 /* rfc3630 */
9697

98+
#define LS_OPAQUE_RI_SUBTLV_SID_LABEL 1 /* rfc8665 */
99+
100+
#define LS_OPAQUE_EP_EXTD_PREFIX_TLV 1 /* rfc7684 */
101+
#define LS_OPAQUE_EP_EXTD_PREFIX_RANGE_TLV 2 /* rfc8665 */
102+
#define LS_OPAQUE_EP_SUBTLV_PREFIX_SID 2 /* rfc8665 */
103+
97104
#define LS_OPAQUE_GRACE_TLV_PERIOD 1 /* rfc3623 */
98105
#define LS_OPAQUE_GRACE_TLV_REASON 2 /* rfc3623 */
99106
#define LS_OPAQUE_GRACE_TLV_INT_ADDRESS 3 /* rfc3623 */
@@ -104,7 +111,8 @@
104111
#define LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH 3 /* rfc3623 */
105112

106113
#define LS_OPAQUE_RI_TLV_CAP 1 /* draft-ietf-ospf-cap-03 */
107-
114+
#define LS_OPAQUE_RI_TLV_HOSTNAME 7 /* rfc5642 */
115+
#define LS_OPAQUE_RI_TLV_SID_LABEL_RANGE 9 /* rfc8665 */
108116

109117
/* rla_link.link_type */
110118
#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
@@ -247,6 +255,13 @@ struct lsa {
247255
nd_byte data[1]; /* may repeat */
248256
} un_ri_tlv[1]; /* may repeat */
249257

258+
/* Extended Prefix LSA */
259+
struct {
260+
nd_uint16_t type;
261+
nd_uint16_t length;
262+
nd_byte data[1]; /* may repeat */
263+
} un_ep_tlv[1]; /* may repeat */
264+
250265
/* Unknown LSA */
251266
struct unknown {
252267
nd_byte data[1]; /* may repeat */

print-ospf.c

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,56 @@ static const struct tok lsa_opaque_values[] = {
101101
{ LS_OPAQUE_TYPE_TE, "Traffic Engineering" },
102102
{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
103103
{ LS_OPAQUE_TYPE_RI, "Router Information" },
104+
{ LS_OPAQUE_TYPE_EP, "Extended Prefix" },
104105
{ 0, NULL }
105106
};
106107

108+
static const struct tok lsa_opaque_ri_sid_subtlv_values[] = {
109+
{ LS_OPAQUE_RI_SUBTLV_SID_LABEL, "SID/Label" },
110+
{ 0, NULL }
111+
};
112+
107113
static const struct tok lsa_opaque_te_tlv_values[] = {
108114
{ LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
109115
{ LS_OPAQUE_TE_TLV_LINK, "Link" },
110116
{ 0, NULL }
111117
};
112118

119+
static const struct tok lsa_opaque_ep_extd_prefix_subtlv_values[] = {
120+
{ LS_OPAQUE_EP_SUBTLV_PREFIX_SID, "Prefix-SID" },
121+
{ 0, NULL }
122+
};
123+
124+
static const struct tok ep_range_tlv_prefix_sid_subtlv_flag_values[] = {
125+
{ 0x40, "No-PHP"},
126+
{ 0x20, "Mapping-Server"},
127+
{ 0x10, "Explicit-NULL"},
128+
{ 0x08, "Value"},
129+
{ 0x04, "Local"},
130+
{ 0, NULL}
131+
};
132+
133+
134+
static const struct tok lsa_opaque_ep_route_type_values[] = {
135+
{ 0, "Unspecified" },
136+
{ 1, "Intra-Area" },
137+
{ 3, "Inter-Area" },
138+
{ 5, "AS External" },
139+
{ 7, "NSSA External" },
140+
{ 0, NULL }
141+
};
142+
143+
static const struct tok lsa_opaque_ep_tlv_values[] = {
144+
{ LS_OPAQUE_EP_EXTD_PREFIX_TLV, "Extended Prefix" },
145+
{ LS_OPAQUE_EP_EXTD_PREFIX_RANGE_TLV, "Extended Prefix Range" },
146+
{ 0, NULL }
147+
};
148+
149+
static const struct tok ep_tlv_flag_values[] = {
150+
{ 0x80, "Inter-Area"},
151+
{ 0, NULL}
152+
};
153+
113154
static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
114155
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" },
115156
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" },
@@ -151,6 +192,8 @@ static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
151192

152193
static const struct tok lsa_opaque_ri_tlv_values[] = {
153194
{ LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
195+
{ LS_OPAQUE_RI_TLV_HOSTNAME, "Hostname" },
196+
{ LS_OPAQUE_RI_TLV_SID_LABEL_RANGE, "SID/Label Range" },
154197
{ 0, NULL }
155198
};
156199

@@ -211,6 +254,7 @@ ospf_grace_lsa_print(netdissect_options *ndo,
211254

212255
/* Infinite loop protection. */
213256
if (tlv_type == 0 || tlv_length ==0) {
257+
nd_print_invalid(ndo);
214258
return -1;
215259
}
216260

@@ -298,6 +342,7 @@ ospf_te_lsa_print(netdissect_options *ndo,
298342

299343
/* Infinite loop protection. */
300344
if (tlv_type == 0 || tlv_length ==0) {
345+
nd_print_invalid(ndo);
301346
return -1;
302347
}
303348

@@ -611,6 +656,218 @@ ospf_print_tos_metrics(netdissect_options *ndo,
611656
}
612657
}
613658

659+
static int
660+
ospf_print_ri_lsa_sid_label_range_tlv(netdissect_options *ndo, const uint8_t *tptr,
661+
u_int tlv_length)
662+
{
663+
u_int subtlv_type, subtlv_length;
664+
665+
while (tlv_length >= 4) {
666+
667+
subtlv_type = GET_BE_U_2(tptr);
668+
subtlv_length = GET_BE_U_2(tptr+2);
669+
tptr+=4;
670+
tlv_length-=4;
671+
672+
/* Infinite loop protection. */
673+
if (subtlv_type == 0 || subtlv_length == 0) {
674+
nd_print_invalid(ndo);
675+
return -1;
676+
}
677+
678+
ND_PRINT("\n\t %s subTLV (%u), length: %u, value: ",
679+
tok2str(lsa_opaque_ri_sid_subtlv_values,"unknown",subtlv_type),
680+
subtlv_type,
681+
subtlv_length);
682+
683+
switch (subtlv_type) {
684+
case LS_OPAQUE_RI_SUBTLV_SID_LABEL:
685+
if (subtlv_length == 3) {
686+
ND_PRINT("\n\t\tLabel: %u", GET_BE_U_3(tptr));
687+
} else if (subtlv_length == 4) {
688+
ND_PRINT("\n\t\tSID: %u", GET_BE_U_4(tptr));
689+
} else {
690+
ND_PRINT("\n\t\tBogus subTLV length %u", subtlv_length);
691+
}
692+
break;
693+
694+
default:
695+
if (ndo->ndo_vflag <= 1) {
696+
if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
697+
return -1;
698+
}
699+
}
700+
701+
/* in OSPF everything has to be 32-bit aligned, including subTLVs */
702+
if (subtlv_length % 4) {
703+
subtlv_length += (4 - (subtlv_length % 4));
704+
}
705+
tptr+=subtlv_length;
706+
tlv_length-=subtlv_length;
707+
}
708+
return 0;
709+
}
710+
711+
static int
712+
ospf_print_ep_lsa_extd_prefix_tlv(netdissect_options *ndo, const uint8_t *tptr,
713+
u_int tlv_length)
714+
{
715+
u_int subtlv_type, subtlv_length;
716+
uint8_t flags, mt_id, algo;
717+
718+
while (tlv_length >= 4) {
719+
subtlv_type = GET_BE_U_2(tptr);
720+
subtlv_length = GET_BE_U_2(tptr+2);
721+
tptr+=4;
722+
tlv_length-=4;
723+
724+
/* Infinite loop protection. */
725+
if (subtlv_type == 0 || subtlv_length == 0) {
726+
nd_print_invalid(ndo);
727+
return -1;
728+
}
729+
730+
ND_PRINT("\n\t\t%s subTLV (%u), length: %u, value: ",
731+
tok2str(lsa_opaque_ep_extd_prefix_subtlv_values,"unknown",subtlv_type),
732+
subtlv_type,
733+
subtlv_length);
734+
735+
switch (subtlv_type) {
736+
case LS_OPAQUE_EP_SUBTLV_PREFIX_SID:
737+
flags = GET_U_1(tptr);
738+
mt_id = GET_U_1(tptr+2);
739+
algo = GET_U_1(tptr+3);
740+
741+
if (subtlv_length == 7) {
742+
ND_PRINT("\n\t\t Label: %u, MT-ID: %u, Algorithm: %u",
743+
GET_BE_U_3(tptr+4), mt_id, algo);
744+
} else if (subtlv_length == 8) {
745+
ND_PRINT("\n\t\t Index: %u, MT-ID: %u, Algorithm: %u, Flags [%s]",
746+
GET_BE_U_4(tptr+4), mt_id, algo,
747+
bittok2str(ep_range_tlv_prefix_sid_subtlv_flag_values, "none", flags));
748+
} else {
749+
ND_PRINT("\n\t\tBogus subTLV length %u", subtlv_length);
750+
}
751+
break;
752+
753+
default:
754+
if (ndo->ndo_vflag <= 1) {
755+
if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
756+
return -1;
757+
}
758+
}
759+
760+
/* in OSPF everything has to be 32-bit aligned, including subTLVs */
761+
if (subtlv_length % 4) {
762+
subtlv_length += (4 - (subtlv_length % 4));
763+
}
764+
tptr+=subtlv_length;
765+
tlv_length-=subtlv_length;
766+
}
767+
return 0;
768+
}
769+
770+
static int
771+
ospf_ep_lsa_print(netdissect_options *ndo, const uint8_t *tptr, u_int lsa_length)
772+
{
773+
u_int tlv_type, tlv_length;
774+
uint16_t range_size;
775+
uint8_t af, prefix_length, route_type, flags;
776+
777+
while (lsa_length >= 4) {
778+
779+
tlv_type = GET_BE_U_2(tptr);
780+
tlv_length = GET_BE_U_2(tptr+2);
781+
tptr+=4;
782+
lsa_length-=4;
783+
784+
/* Infinite loop protection. */
785+
if (tlv_type == 0 || tlv_length == 0) {
786+
nd_print_invalid(ndo);
787+
return -1;
788+
}
789+
790+
ND_PRINT("\n\t %s TLV (%u), length: %u, value: ",
791+
tok2str(lsa_opaque_ep_tlv_values,"unknown",tlv_type),
792+
tlv_type,
793+
tlv_length);
794+
795+
switch (tlv_type) {
796+
case LS_OPAQUE_EP_EXTD_PREFIX_TLV:
797+
prefix_length = GET_U_1(tptr+1);
798+
af = GET_U_1(tptr+2);
799+
route_type = GET_U_1(tptr);
800+
flags = GET_U_1(tptr+3);
801+
802+
if (af != 0) {
803+
ND_PRINT("\n\t Bogus AF %u", af);
804+
return -1;
805+
}
806+
807+
if (prefix_length > 32) {
808+
ND_PRINT("\n\t IPv4 prefix: bad bit length %u", prefix_length);
809+
return -1;
810+
}
811+
812+
ND_PRINT("\n\t IPv4 prefix: %15s/%u, Route Type: %s, Flags [%s]",
813+
GET_IPADDR_STRING(tptr+4), prefix_length,
814+
tok2str(lsa_opaque_ep_route_type_values, "Unknown", route_type),
815+
bittok2str(ep_tlv_flag_values, "none", flags));
816+
817+
/* subTLVs present ? */
818+
if (tlv_length > 12) {
819+
if (ospf_print_ep_lsa_extd_prefix_tlv(ndo, tptr+8, tlv_length-8) == -1) {
820+
return -1;
821+
}
822+
}
823+
break;
824+
825+
case LS_OPAQUE_EP_EXTD_PREFIX_RANGE_TLV:
826+
prefix_length = GET_U_1(tptr);
827+
af = GET_U_1(tptr+1);
828+
range_size = GET_BE_U_2(tptr+2);
829+
flags = GET_U_1(tptr+4);
830+
831+
if (af != 0) {
832+
ND_PRINT("\n\t Bogus AF %u", af);
833+
return -1;
834+
}
835+
836+
if (prefix_length > 32) {
837+
ND_PRINT("\n\t IPv4 prefix: bad bit length %u", prefix_length);
838+
return -1;
839+
}
840+
841+
ND_PRINT("\n\t IPv4 prefix: %15s/%u, Range size: %u, Flags [%s]",
842+
GET_IPADDR_STRING(tptr+8), prefix_length,
843+
range_size,
844+
bittok2str(ep_tlv_flag_values, "none", flags));
845+
846+
/* subTLVs present ? */
847+
if (tlv_length > 12) {
848+
if (ospf_print_ep_lsa_extd_prefix_tlv(ndo, tptr+12, tlv_length-12) == -1) {
849+
return -1;
850+
}
851+
}
852+
break;
853+
854+
default:
855+
if (ndo->ndo_vflag <= 1) {
856+
if (!print_unknown_data(ndo, tptr, "\n\t\t", tlv_length))
857+
return -1;
858+
}
859+
}
860+
861+
/* in OSPF everything has to be 32-bit aligned, including TLVs */
862+
if (tlv_length % 4) {
863+
tlv_length += (4 - (tlv_length % 4));
864+
}
865+
tptr+=tlv_length;
866+
lsa_length-=tlv_length;
867+
}
868+
return 0;
869+
}
870+
614871
/*
615872
* Print a single link state advertisement. If truncated or if LSA length
616873
* field is less than the length of the LSA header, return NULl, else
@@ -836,6 +1093,20 @@ ospf_print_lsa(netdissect_options *ndo,
8361093
ND_PRINT("Capabilities: %s",
8371094
bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr)));
8381095
break;
1096+
1097+
case LS_OPAQUE_RI_TLV_HOSTNAME:
1098+
ND_PRINT("\n\t Hostname: ");
1099+
nd_printjnp(ndo, tptr, tlv_length);
1100+
break;
1101+
1102+
case LS_OPAQUE_RI_TLV_SID_LABEL_RANGE:
1103+
ND_TCHECK_4(tptr);
1104+
ND_PRINT("\n\t Range size: %u", GET_BE_U_3(tptr));
1105+
if (ospf_print_ri_lsa_sid_label_range_tlv(ndo, tptr+4, tlv_length-4) == -1) {
1106+
return(ls_end);
1107+
}
1108+
break;
1109+
8391110
default:
8401111
if (ndo->ndo_vflag <= 1) {
8411112
if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
@@ -844,6 +1115,11 @@ ospf_print_lsa(netdissect_options *ndo,
8441115
break;
8451116

8461117
}
1118+
1119+
/* in OSPF everything has to be 32-bit aligned, including TLVs */
1120+
if (tlv_length % 4) {
1121+
tlv_length += (4 - (tlv_length % 4));
1122+
}
8471123
tptr+=tlv_length;
8481124
ls_length_remaining-=tlv_length;
8491125
}
@@ -863,6 +1139,13 @@ ospf_print_lsa(netdissect_options *ndo,
8631139
}
8641140
break;
8651141

1142+
case LS_OPAQUE_TYPE_EP:
1143+
if (ospf_ep_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_ep_tlv),
1144+
ls_length) == -1) {
1145+
return(ls_end);
1146+
}
1147+
break;
1148+
8661149
default:
8671150
if (ndo->ndo_vflag <= 1) {
8681151
if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,

0 commit comments

Comments
 (0)