*/
#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.44 2003-10-22 17:08:45 hannes Exp $ (LBL)";
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.56.2.4 2006-12-13 08:24:27 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
{ OSPF_OPTION_EA, "Advertise External" },
{ OSPF_OPTION_DC, "Demand Circuit" },
{ OSPF_OPTION_O, "Opaque" },
+ { OSPF_OPTION_DN, "Up/Down" },
{ 0, NULL }
};
static struct tok ospf_authtype_values[] = {
{ OSPF_AUTH_NONE, "none" },
- { OSPF_AUTH_NONE, "simple" },
+ { OSPF_AUTH_SIMPLE, "simple" },
{ OSPF_AUTH_MD5, "MD5" },
{ 0, NULL }
};
static struct tok lsa_opaque_values[] = {
{ LS_OPAQUE_TYPE_TE, "Traffic Engineering" },
{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
+ { LS_OPAQUE_TYPE_RI, "Router Information" },
{ 0, NULL }
};
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
{ LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
{ LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" },
+ { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" },
{ 0, NULL }
};
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP 1 /* rfc3630 */
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA 2 /* rfc3630 */
+static struct tok lsa_opaque_grace_tlv_values[] = {
+ { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" },
+ { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" },
+ { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" },
+ { 0, NULL }
+};
+
+static struct tok lsa_opaque_grace_tlv_reason_values[] = {
+ { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" },
+ { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" },
+ { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" },
+ { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" },
+ { 0, NULL }
+};
static struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
{ 0, NULL }
};
+static struct tok lsa_opaque_ri_tlv_values[] = {
+ { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
+ { 0, NULL }
+};
+
+static struct tok lsa_opaque_ri_tlv_cap_values[] = {
+ { 1, "Reserved" },
+ { 2, "Reserved" },
+ { 4, "Reserved" },
+ { 8, "Reserved" },
+ { 16, "graceful restart capable" },
+ { 32, "graceful restart helper" },
+ { 64, "Stub router support" },
+ { 128, "Traffic engineering" },
+ { 256, "p2p over LAN" },
+ { 512, "path computation server" },
+ { 0, NULL }
+};
+
static char tstr[] = " [|ospf]";
#ifdef WIN32
#endif /* WIN32 */
static int ospf_print_lshdr(const struct lsa_hdr *);
-static int ospf_print_lsa(const struct lsa *);
+static const u_char *ospf_print_lsa(const struct lsa *);
static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
static int
-ospf_print_lshdr(register const struct lsa_hdr *lshp) {
-
- TCHECK(lshp->ls_type);
- TCHECK(lshp->ls_options);
+ospf_print_lshdr(register const struct lsa_hdr *lshp)
+{
+ u_int ls_length;
+
+ TCHECK(lshp->ls_length);
+ ls_length = EXTRACT_16BITS(&lshp->ls_length);
+ if (ls_length < sizeof(struct lsa_hdr)) {
+ printf("\n\t Bogus length %u < %lu", ls_length,
+ (unsigned long)sizeof(struct lsa_hdr));
+ return(-1);
+ }
+ TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */
printf("\n\t Advertising Router: %s, seq 0x%08x, age %us, length: %u",
ipaddr_string(&lshp->ls_router),
EXTRACT_32BITS(&lshp->ls_seq),
EXTRACT_16BITS(&lshp->ls_age),
- EXTRACT_16BITS(&lshp->ls_length)-sizeof(struct lsa_hdr));
+ ls_length-(u_int)sizeof(struct lsa_hdr));
+ TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */
switch (lshp->ls_type) {
/* the LSA header for opaque LSAs was slightly changed */
case LS_TYPE_OPAQUE_LL:
break;
}
+ TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */
printf("\n\t Options: [%s]", bittok2str(ospf_option_values,"none",lshp->ls_options));
-return (0);
+ return (ls_length);
trunc:
- return (1);
+ return (-1);
}
/*
- * Print a single link state advertisement. If truncated return 1, else 0.
+ * Print a single link state advertisement. If truncated or if LSA length
+ * field is less than the length of the LSA header, return NULl, else
+ * return pointer to data past end of LSA.
*/
-static int
+static const u_int8_t *
ospf_print_lsa(register const struct lsa *lsap)
{
- register const u_char *ls_end;
+ register const u_int8_t *ls_end;
register const struct rlalink *rlp;
register const struct tos_metric *tosp;
register const struct in_addr *ap;
register const struct aslametric *almp;
register const struct mcla *mcp;
register const u_int32_t *lp;
- register int j, k,ls_length, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level;
+ register int j, k, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level, te_class;
+ register int ls_length;
const u_int8_t *tptr;
int count_srlg;
union { /* int to float conversion buffer for several subTLVs */
} bw;
tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
- ls_length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr);
-
- ospf_print_lshdr(&lsap->ls_hdr);
-
- TCHECK(lsap->ls_hdr.ls_length);
- ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
+ ls_length = ospf_print_lshdr(&lsap->ls_hdr);
+ if (ls_length == -1)
+ return(NULL);
+ ls_end = (u_int8_t *)lsap + ls_length;
+ ls_length -= sizeof(struct lsa_hdr);
switch (lsap->ls_hdr.ls_type) {
default:
printf("\n\t Unknown Router Link Type (%u)",
rlp->link_type);
- return (0);
+ return (ls_end);
}
printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric));
tosp = (struct tos_metric *)
break;
case LS_TYPE_ASE:
+ case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */
TCHECK(lsap->lsa_un.un_nla.nla_mask);
printf("\n\t Mask %s",
ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
case LS_TYPE_OPAQUE_DW:
switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
- case LS_OPAQUE_TYPE_TE:
- if (!TTEST2(*tptr, 4))
- goto trunc;
+ case LS_OPAQUE_TYPE_RI:
+ tptr = (u_int8_t *)(&lsap->lsa_un.un_ri_tlv.type);
+
+ while (ls_length != 0) {
+ TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ printf("\n\t Remaining LS length %u < 4", ls_length);
+ return(ls_end);
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
+
+ printf("\n\t %s TLV (%u), length: %u, value: ",
+ tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length);
+
+ if (tlv_length > ls_length) {
+ printf("\n\t Bogus length %u > %u", tlv_length,
+ ls_length);
+ return(ls_end);
+ }
+ ls_length-=tlv_length;
+ TCHECK2(*tptr, tlv_length);
+ switch(tlv_type) {
- tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type);
+ case LS_OPAQUE_RI_TLV_CAP:
+ if (tlv_length != 4) {
+ printf("\n\t Bogus length %u != 4", tlv_length);
+ return(ls_end);
+ }
+ printf("Capabilities: %s",
+ bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr)));
+ break;
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data(tptr,"\n\t ",tlv_length))
+ return(ls_end);
+ }
+ break;
- while (ls_length > 0) {
+ }
+ tptr+=tlv_length;
+ }
+
+ break;
+ case LS_OPAQUE_TYPE_GRACE:
+ tptr = (u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type);
+
+ while (ls_length != 0) {
+ TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ printf("\n\t Remaining LS length %u < 4", ls_length);
+ return(ls_end);
+ }
tlv_type = EXTRACT_16BITS(tptr);
tlv_length = EXTRACT_16BITS(tptr+2);
- ls_length-=(tlv_length+4);
tptr+=4;
+ ls_length-=4;
+
+ printf("\n\t %s TLV (%u), length: %u, value: ",
+ tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length);
+
+ if (tlv_length > ls_length) {
+ printf("\n\t Bogus length %u > %u", tlv_length,
+ ls_length);
+ return(ls_end);
+ }
+ ls_length-=tlv_length;
+ TCHECK2(*tptr, tlv_length);
+ switch(tlv_type) {
+
+ case LS_OPAQUE_GRACE_TLV_PERIOD:
+ if (tlv_length != 4) {
+ printf("\n\t Bogus length %u != 4", tlv_length);
+ return(ls_end);
+ }
+ printf("%us",EXTRACT_32BITS(tptr));
+ break;
+ case LS_OPAQUE_GRACE_TLV_REASON:
+ if (tlv_length != 1) {
+ printf("\n\t Bogus length %u != 1", tlv_length);
+ return(ls_end);
+ }
+ printf("%s (%u)",
+ tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr),
+ *tptr);
+ break;
+ case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
+ if (tlv_length != 4) {
+ printf("\n\t Bogus length %u != 4", tlv_length);
+ return(ls_end);
+ }
+ printf("%s", ipaddr_string(tptr));
+ break;
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data(tptr,"\n\t ",tlv_length))
+ return(ls_end);
+ }
+ break;
+
+ }
+ tptr+=tlv_length;
+ }
+
+ break;
+ case LS_OPAQUE_TYPE_TE:
+ tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type);
+
+ while (ls_length != 0) {
+ TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ printf("\n\t Remaining LS length %u < 4", ls_length);
+ return(ls_end);
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
printf("\n\t %s TLV (%u), length: %u",
tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
tlv_type,
tlv_length);
+ if (tlv_length > ls_length) {
+ printf("\n\t Bogus length %u > %u", tlv_length,
+ ls_length);
+ return(ls_end);
+ }
+ ls_length-=tlv_length;
switch(tlv_type) {
case LS_OPAQUE_TE_TLV_LINK:
- while (tlv_length > 0) {
- if (!TTEST2(*tptr, 4))
- goto trunc;
+ while (tlv_length != 0) {
+ if (tlv_length < 4) {
+ printf("\n\t Remaining TLV length %u < 4",
+ tlv_length);
+ return(ls_end);
+ }
+ TCHECK2(*tptr, 4);
subtlv_type = EXTRACT_16BITS(tptr);
subtlv_length = EXTRACT_16BITS(tptr+2);
- tlv_length-=4;
tptr+=4;
+ tlv_length-=4;
printf("\n\t %s subTLV (%u), length: %u",
tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
subtlv_type,
subtlv_length);
- if (!TTEST2(*tptr, subtlv_length))
- goto trunc;
+ TCHECK2(*tptr, subtlv_length);
switch(subtlv_type) {
case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
printf(", 0x%08x", EXTRACT_32BITS(tptr));
printf(", %.3f Mbps", bw.f*8/1000000 );
break;
case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
- for (priority_level = 0; priority_level < 8; priority_level++) {
- bw.i = EXTRACT_32BITS(tptr+priority_level*4);
- printf("\n\t\tpriority level %d: %.3f Mbps",
- priority_level,
+ for (te_class = 0; te_class < 8; te_class++) {
+ bw.i = EXTRACT_32BITS(tptr+te_class*4);
+ printf("\n\t\tTE-Class %u: %.3f Mbps",
+ te_class,
+ bw.f*8/1000000 );
+ }
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
+ printf("\n\t\tBandwidth Constraints Model ID: %s (%u)",
+ tok2str(diffserv_te_bc_values, "unknown", *tptr),
+ *tptr);
+ /* decode BCs until the subTLV ends */
+ for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
+ bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
+ printf("\n\t\t Bandwidth constraint CT%u: %.3f Mbps",
+ te_class,
bw.f*8/1000000 );
}
break;
default:
if (vflag <= 1) {
if(!print_unknown_data(tptr,"\n\t\t",subtlv_length))
- return(0);
+ return(ls_end);
}
break;
}
break;
case LS_OPAQUE_TE_TLV_ROUTER:
+ if (tlv_length < 4) {
+ printf("\n\t TLV length %u < 4", tlv_length);
+ return(ls_end);
+ }
+ TCHECK2(*tptr, 4);
printf(", %s", ipaddr_string(tptr));
break;
default:
if (vflag <= 1) {
if(!print_unknown_data(tptr,"\n\t ",tlv_length))
- return(0);
+ return(ls_end);
}
break;
}
default:
if (vflag <= 1) {
if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
- "\n\t ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr)))
- return(0);
+ "\n\t ", ls_length))
+ return(ls_end);
}
break;
}
/* do we want to see an additionally hexdump ? */
if (vflag> 1)
if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
- "\n\t ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr))) {
- return(0);
+ "\n\t ", ls_length)) {
+ return(ls_end);
}
- return (0);
+ return (ls_end);
trunc:
- return (1);
+ return (NULL);
}
static int
if (vflag) {
/* Print all the LS adv's */
lshp = op->ospf_db.db_lshdr;
- while (!ospf_print_lshdr(lshp)) {
+ while (ospf_print_lshdr(lshp) != -1) {
++lshp;
}
}
printf(", %d LSA%s",lsa_count_max, lsa_count_max > 1 ? "s" : "");
for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
printf("\n\t LSA #%u",lsa_count);
- if (ospf_print_lsa(lsap))
+ lsap = (const struct lsa *)ospf_print_lsa(lsap);
+ if (lsap == NULL)
goto trunc;
- lsap = (struct lsa *)((u_char *)lsap +
- EXTRACT_16BITS(&lsap->ls_hdr.ls_length));
}
break;
case OSPF_TYPE_LS_ACK:
lshp = op->ospf_lsa.lsa_lshdr;
- while (!ospf_print_lshdr(lshp)) {
+ while (ospf_print_lshdr(lshp) != -1) {
++lshp;
}
break;
void
ospf_print(register const u_char *bp, register u_int length,
- register const u_char *bp2)
+ const u_char *bp2 _U_)
{
register const struct ospfhdr *op;
- register const struct ip *ip;
register const u_char *dataend;
register const char *cp;
op = (struct ospfhdr *)bp;
- ip = (struct ip *)bp2;
/* XXX Before we do anything else, strip off the MD5 trailer */
TCHECK(op->ospf_authtype);
/* value. If it's not valid, say so and return */
TCHECK(op->ospf_type);
cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
- printf("OSPFv%u, %s (%u), length: %u",
+ printf("OSPFv%u, %s, length: %u",
op->ospf_version,
cp,
- op->ospf_type,
length);
if (*cp == 'u')
return;
break;
case OSPF_AUTH_SIMPLE:
- (void)fn_printn(op->ospf_authdata,
- sizeof(op->ospf_authdata), NULL);
- printf("\"");
+ printf("\n\tSimple text password: ");
+ safeputs(op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
break;
case OSPF_AUTH_MD5: