*/
-#define NETDISSECT_REWORKED
+/* \summary: Open Shortest Path First (OSPF) printer */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
-#include "interface.h"
+#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "gmpls.h"
};
static const struct tok type2str[] = {
- { OSPF_TYPE_UMD, "UMD" },
{ OSPF_TYPE_HELLO, "Hello" },
{ OSPF_TYPE_DD, "Database Description" },
{ OSPF_TYPE_LS_REQ, "LS-Request" },
int
ospf_print_grace_lsa(netdissect_options *ndo,
- const u_int8_t *tptr, u_int ls_length) {
-
+ const uint8_t *tptr, u_int ls_length)
+{
u_int tlv_type, tlv_length;
int
ospf_print_te_lsa(netdissect_options *ndo,
- const u_int8_t *tptr, u_int ls_length) {
-
+ const uint8_t *tptr, u_int ls_length)
+{
u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
u_int priority_level, te_class, count_srlg;
union { /* int to float conversion buffer for several subTLVs */
float f;
- u_int32_t i;
+ uint32_t i;
} bw;
while (ls_length != 0) {
tptr+=4;
tlv_length-=4;
+ /* Infinite loop protection */
+ if (subtlv_type == 0 || subtlv_length == 0)
+ goto invalid;
+
ND_PRINT((ndo, "\n\t %s subTLV (%u), length: %u",
tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
subtlv_type,
ND_TCHECK2(*tptr, subtlv_length);
switch(subtlv_type) {
case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
+ if (subtlv_length != 4) {
+ ND_PRINT((ndo, " != 4"));
+ goto invalid;
+ }
ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
+ if (subtlv_length != 4 && subtlv_length != 8) {
+ ND_PRINT((ndo, " != 4 && != 8"));
+ goto invalid;
+ }
ND_PRINT((ndo, ", %s (0x%08x)",
ipaddr_string(ndo, tptr),
EXTRACT_32BITS(tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
+ if (subtlv_length != 4) {
+ ND_PRINT((ndo, " != 4"));
+ goto invalid;
+ }
ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
+ if (subtlv_length != 4) {
+ ND_PRINT((ndo, " != 4"));
+ goto invalid;
+ }
bw.i = EXTRACT_32BITS(tptr);
ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
+ if (subtlv_length != 32) {
+ ND_PRINT((ndo, " != 32"));
+ goto invalid;
+ }
for (te_class = 0; te_class < 8; te_class++) {
bw.i = EXTRACT_32BITS(tptr+te_class*4);
ND_PRINT((ndo, "\n\t\tTE-Class %u: %.3f Mbps",
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
+ if (subtlv_length < 4) {
+ ND_PRINT((ndo, " < 4"));
+ goto invalid;
+ }
+ /* BC Model Id (1 octet) + Reserved (3 octets) */
ND_PRINT((ndo, "\n\t\tBandwidth Constraints Model ID: %s (%u)",
tok2str(diffserv_te_bc_values, "unknown", *tptr),
*tptr));
+ if (subtlv_length % 4 != 0) {
+ ND_PRINT((ndo, "\n\t\tlength %u != N x 4", subtlv_length));
+ goto invalid;
+ }
+ if (subtlv_length > 36) {
+ ND_PRINT((ndo, "\n\t\tlength %u > 36", subtlv_length));
+ goto invalid;
+ }
/* 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);
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
+ if (subtlv_length != 4) {
+ ND_PRINT((ndo, " != 4"));
+ goto invalid;
+ }
ND_PRINT((ndo, ", Metric %u", EXTRACT_32BITS(tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
- ND_PRINT((ndo, ", %s, Priority %u",
- bittok2str(gmpls_link_prot_values, "none", *tptr),
- *(tptr + 1)));
+ /* Protection Cap (1 octet) + Reserved ((3 octets) */
+ if (subtlv_length != 4) {
+ ND_PRINT((ndo, " != 4"));
+ goto invalid;
+ }
+ ND_PRINT((ndo, ", %s",
+ bittok2str(gmpls_link_prot_values, "none", *tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
+ if (subtlv_length < 36) {
+ ND_PRINT((ndo, " < 36"));
+ goto invalid;
+ }
+ /* Switching Cap (1 octet) + Encoding (1) + Reserved (2) */
ND_PRINT((ndo, "\n\t\tInterface Switching Capability: %s",
tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))));
ND_PRINT((ndo, "\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
+ if (subtlv_length != 1) {
+ ND_PRINT((ndo, " != 1"));
+ goto invalid;
+ }
ND_PRINT((ndo, ", %s (%u)",
tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
*tptr));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
+ if (subtlv_length % 4 != 0) {
+ ND_PRINT((ndo, " != N x 4"));
+ goto invalid;
+ }
count_srlg = subtlv_length / 4;
if (count_srlg != 0)
ND_PRINT((ndo, "\n\t\t Shared risk group: "));
return 0;
trunc:
return -1;
+invalid:
+ ND_PRINT((ndo, "%s", istr));
+ return -1;
}
static int
/* draft-ietf-ospf-mt-09 */
static const struct tok ospf_topology_values[] = {
- { 0, "default " },
- { 1, "multicast " },
- { 2, "management " },
+ { 0, "default" },
+ { 1, "multicast" },
+ { 2, "management" },
{ 0, NULL }
};
/*
* Print all the per-topology metrics.
*/
-static void
+static int
ospf_print_tos_metrics(netdissect_options *ndo,
const union un_tos *tos)
{
/*
* All but the first metric contain a valid topology id.
*/
- while (toscount) {
- ND_PRINT((ndo, "\n\t\ttopology %s(%u), metric %u",
- tok2str(ospf_topology_values, "",
+ while (toscount > 0) {
+ ND_TCHECK(*tos);
+ ND_PRINT((ndo, "\n\t\ttopology %s (%u), metric %u",
+ tok2str(ospf_topology_values, "Unknown",
metric_count ? tos->metrics.tos_type : 0),
metric_count ? tos->metrics.tos_type : 0,
EXTRACT_16BITS(&tos->metrics.tos_metric)));
tos++;
toscount--;
}
+ return 0;
+trunc:
+ return 1;
}
/*
* field is less than the length of the LSA header, return NULl, else
* return pointer to data past end of LSA.
*/
-static const u_int8_t *
+static const uint8_t *
ospf_print_lsa(netdissect_options *ndo,
register const struct lsa *lsap)
{
- register const u_int8_t *ls_end;
+ register const uint8_t *ls_end;
register const struct rlalink *rlp;
register const struct in_addr *ap;
register const struct aslametric *almp;
register const struct mcla *mcp;
- register const u_int32_t *lp;
+ register const uint32_t *lp;
register int j, tlv_type, tlv_length, topology;
register int ls_length;
- const u_int8_t *tptr;
+ const uint8_t *tptr;
- tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
+ tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
ls_length = ospf_print_lshdr(ndo, &lsap->ls_hdr);
if (ls_length == -1)
return(NULL);
- ls_end = (u_int8_t *)lsap + ls_length;
+ ls_end = (const uint8_t *)lsap + ls_length;
ls_length -= sizeof(struct lsa_hdr);
switch (lsap->ls_hdr.ls_type) {
return (ls_end);
}
- ospf_print_tos_metrics(ndo, &rlp->un_tos);
+ if (ospf_print_tos_metrics(ndo, &rlp->un_tos))
+ goto trunc;
- rlp = (struct rlalink *)((u_char *)(rlp + 1) +
+ rlp = (const struct rlalink *)((const u_char *)(rlp + 1) +
((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
}
break;
ND_PRINT((ndo, "\n\t Mask %s\n\t Connected Routers:",
ipaddr_string(ndo, &lsap->lsa_un.un_nla.nla_mask)));
ap = lsap->lsa_un.un_nla.nla_router;
- while ((u_char *)ap < ls_end) {
+ while ((const u_char *)ap < ls_end) {
ND_TCHECK(*ap);
ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap)));
++ap;
ipaddr_string(ndo, &lsap->lsa_un.un_sla.sla_mask)));
ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
lp = lsap->lsa_un.un_sla.sla_tosmetric;
- while ((u_char *)lp < ls_end) {
- register u_int32_t ul;
+ while ((const u_char *)lp < ls_end) {
+ register uint32_t ul;
ND_TCHECK(*lp);
ul = EXTRACT_32BITS(lp);
topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
- ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d",
- tok2str(ospf_topology_values, "", topology),
+ ND_PRINT((ndo, "\n\t\ttopology %s (%u) metric %d",
+ tok2str(ospf_topology_values, "Unknown", topology),
topology,
ul & SLA_MASK_METRIC));
++lp;
case LS_TYPE_SUM_ABR:
ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
lp = lsap->lsa_un.un_sla.sla_tosmetric;
- while ((u_char *)lp < ls_end) {
- register u_int32_t ul;
+ while ((const u_char *)lp < ls_end) {
+ register uint32_t ul;
ND_TCHECK(*lp);
ul = EXTRACT_32BITS(lp);
topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
- ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d",
- tok2str(ospf_topology_values, "", topology),
+ ND_PRINT((ndo, "\n\t\ttopology %s (%u) metric %d",
+ tok2str(ospf_topology_values, "Unknown", topology),
topology,
ul & SLA_MASK_METRIC));
++lp;
ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
almp = lsap->lsa_un.un_asla.asla_metric;
- while ((u_char *)almp < ls_end) {
- register u_int32_t ul;
+ while ((const u_char *)almp < ls_end) {
+ register uint32_t ul;
ND_TCHECK(almp->asla_tosmetric);
ul = EXTRACT_32BITS(&almp->asla_tosmetric);
topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
- ND_PRINT((ndo, "\n\t\ttopology %s(%u), type %d, metric",
- tok2str(ospf_topology_values, "", topology),
+ ND_PRINT((ndo, "\n\t\ttopology %s (%u), type %d, metric",
+ tok2str(ospf_topology_values, "Unknown", topology),
topology,
(ul & ASLA_FLAG_EXTERNAL) ? 2 : 1));
if ((ul & ASLA_MASK_METRIC) == 0xffffff)
case LS_TYPE_GROUP:
/* Multicast extensions as of 23 July 1991 */
mcp = lsap->lsa_un.un_mcla;
- while ((u_char *)mcp < ls_end) {
+ while ((const u_char *)mcp < ls_end) {
ND_TCHECK(mcp->mcla_vid);
switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
case LS_OPAQUE_TYPE_RI:
- tptr = (u_int8_t *)(&lsap->lsa_un.un_ri_tlv.type);
+ tptr = (const uint8_t *)(&lsap->lsa_un.un_ri_tlv.type);
while (ls_length != 0) {
ND_TCHECK2(*tptr, 4);
break;
case LS_OPAQUE_TYPE_GRACE:
- if (ospf_print_grace_lsa(ndo, (u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type),
+ if (ospf_print_grace_lsa(ndo, (const uint8_t *)(&lsap->lsa_un.un_grace_tlv.type),
ls_length) == -1) {
return(ls_end);
}
break;
case LS_OPAQUE_TYPE_TE:
- if (ospf_print_te_lsa(ndo, (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
+ if (ospf_print_te_lsa(ndo, (const uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
ls_length) == -1) {
return(ls_end);
}
default:
if (ndo->ndo_vflag <= 1) {
- if (!print_unknown_data(ndo, (u_int8_t *)lsap->lsa_un.un_unknown,
+ if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
"\n\t ", ls_length))
return(ls_end);
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag> 1)
- if (!print_unknown_data(ndo, (u_int8_t *)lsap->lsa_un.un_unknown,
+ if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
"\n\t ", ls_length)) {
return(ls_end);
}
register const u_char *dptr;
register const u_char *dataend;
register u_int length2;
- register u_int16_t lls_type, lls_len;
- register u_int32_t lls_flags;
+ register uint16_t lls_type, lls_len;
+ register uint32_t lls_flags;
switch (op->ospf_type) {
/* dig deeper if LLS data is available; see RFC4813 */
length2 = EXTRACT_16BITS(&op->ospf_len);
- dptr = (u_char *)op + length2;
- dataend = (u_char *)op + length;
+ dptr = (const u_char *)op + length2;
+ dataend = (const u_char *)op + length;
if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
dptr = dptr + op->ospf_authdata[3];
register const struct lsr *lsrp;
register const struct lsa_hdr *lshp;
register const struct lsa *lsap;
- register u_int32_t lsa_count,lsa_count_max;
+ register uint32_t lsa_count,lsa_count_max;
switch (op->ospf_type) {
- case OSPF_TYPE_UMD:
- /*
- * Rob Coltun's special monitoring packets;
- * do nothing
- */
- break;
-
case OSPF_TYPE_HELLO:
+ ND_TCHECK(op->ospf_hello.hello_options);
ND_PRINT((ndo, "\n\tOptions [%s]",
bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)));
ipaddr_string(ndo, &op->ospf_hello.hello_bdr)));
ap = op->ospf_hello.hello_neighbor;
- if ((u_char *)ap < dataend)
+ if ((const u_char *)ap < dataend)
ND_PRINT((ndo, "\n\t Neighbor List:"));
- while ((u_char *)ap < dataend) {
+ while ((const u_char *)ap < dataend) {
ND_TCHECK(*ap);
ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap)));
++ap;
/* Print all the LS adv's */
lshp = op->ospf_db.db_lshdr;
- while (((u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
+ while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
++lshp;
}
break;
case OSPF_TYPE_LS_REQ:
lsrp = op->ospf_lsr;
- while ((u_char *)lsrp < dataend) {
+ while ((const u_char *)lsrp < dataend) {
ND_TCHECK(*lsrp);
ND_PRINT((ndo, "\n\t Advertising Router: %s, %s LSA (%u)",
register const u_char *dataend;
register const char *cp;
- op = (struct ospfhdr *)bp;
+ op = (const struct ospfhdr *)bp;
/* XXX Before we do anything else, strip off the MD5 trailer */
ND_TCHECK(op->ospf_authtype);
/* If the type is valid translate it, or just print the type */
/* value. If it's not valid, say so and return */
ND_TCHECK(op->ospf_type);
- cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
+ cp = tok2str(type2str, "unknown LS-type %u", op->ospf_type);
ND_PRINT((ndo, "OSPFv%u, %s, length %u", op->ospf_version, cp, length));
if (*cp == 'u')
return;