freebsd-skq/contrib/tcpdump/print-forces.c

1044 lines
24 KiB
C
Raw Normal View History

Update tcpdump to 4.1.1. Changes: Thu. April 1, 2010. guy@alum.mit.edu. Summary for 4.1.1 tcpdump release Fix build on systems with PF, such as FreeBSD and OpenBSD. Don't blow up if a zero-length link-layer address is passed to linkaddr_string(). Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu. Summary for 4.1.0 tcpdump release Fix printing of MAC addresses for VLAN frames with a length field Add some additional bounds checks and use the EXTRACT_ macros more Add a -b flag to print the AS number in BGP packets in ASDOT notation rather than ASPLAIN notation Add ICMPv6 RFC 5006 support Decode the access flags in NFS access requests Handle the new DLT_ for memory-mapped USB captures on Linux Make the default snapshot (-s) the maximum Print name of device (when -L is used) Support for OpenSolaris (and SXCE build 125 and later) Print new TCP flags Add support for RPL DIO Add support for TCP User Timeout (UTO) Add support for non-standard Ethertypes used by 3com PPPoE gear Add support for 802.11n and 802.11s Add support for Transparent Ethernet Bridge ethertype in GRE Add 4 byte AS support for BGP printer Add support for the MDT SAFI 66 BG printer Add basic IPv6 support to print-olsr Add USB printer Add printer for ForCES Handle frames with an FCS Handle 802.11n Control Wrapper, Block Acq Req and Block Ack frames Fix TCP sequence number printing Report 802.2 packets as 802.2 instead of 802.3 Don't include -L/usr/lib in LDFLAGS On x86_64 Linux, look in lib64 directory too Lots of code clean ups Autoconf clean ups Update testcases to make output changes Fix compiling with/out smi (--with{,out}-smi) Fix compiling without IPv6 support (--disable-ipv6)
2010-10-28 16:23:25 +00:00
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
* distributions retain the above copyright notice and this paragraph
* in its entirety, and (2) distributions including binary code include
* the above copyright notice and this paragraph in its entirety in
* the documentation or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* Copyright (c) 2009 Mojatatu Networks, Inc
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <tcpdump-stdinc.h>
#include <stdio.h>
#include <stdlib.h>
#include "interface.h"
#include "extract.h"
#include "forces.h"
#define RESLEN 4
int
prestlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
register const u_char *tdp = (u_char *) TLV_DATA(tlv);
struct res_val *r = (struct res_val *)tdp;
u_int dlen;
/*
* pdatacnt_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != RESLEN) {
printf("illegal RESULT-TLV: %d bytes!\n", dlen);
return -1;
}
TCHECK(*r);
if (r->result >= 0x18 && r->result <= 0xFE) {
printf("illegal reserved result code: 0x%x!\n", r->result);
return -1;
}
if (vflag >= 3) {
char *ib = indent_pr(indent, 0);
printf("%s Result: %s (code 0x%x)\n", ib,
tok2str(ForCES_errs, NULL, r->result), r->result);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
fdatatlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
u_int rlen;
register const u_char *tdp = (u_char *) TLV_DATA(tlv);
u_int16_t type;
/*
* pdatacnt_print() or pkeyitlv_print() has ensured that len
* (the TLV length) >= TLV_HDRL.
*/
rlen = len - TLV_HDRL;
TCHECK(*tlv);
type = EXTRACT_16BITS(&tlv->type);
if (type != F_TLV_FULD) {
printf("Error: expecting FULLDATA!\n");
return -1;
}
if (vflag >= 3) {
char *ib = indent_pr(indent + 2, 1);
printf("%s[", &ib[1]);
hex_print_with_offset(ib, tdp, rlen, 0);
printf("\n%s]\n", &ib[1]);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
sdatailv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
u_int rlen;
const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
int invilv;
if (len < ILV_HDRL) {
printf("Error: BAD SPARSEDATA-TLV!\n");
return -1;
}
rlen = len - ILV_HDRL;
indent += 1;
while (rlen != 0) {
TCHECK(*ilv);
invilv = ilv_valid(ilv, rlen);
if (invilv) {
printf("Error: BAD ILV!\n");
return -1;
}
if (vflag >= 3) {
register const u_char *tdp = (u_char *) ILV_DATA(ilv);
char *ib = indent_pr(indent, 1);
printf("\n%s SPARSEDATA: type %x length %d\n", &ib[1],
EXTRACT_32BITS(&ilv->type),
EXTRACT_32BITS(&ilv->length));
printf("%s[", &ib[1]);
hex_print_with_offset(ib, tdp, rlen, 0);
printf("\n%s]\n", &ib[1]);
}
ilv = GO_NXT_ILV(ilv, rlen);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
sdatatlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
u_int rlen;
register const u_char *tdp = (u_char *) TLV_DATA(tlv);
u_int16_t type;
/*
* pdatacnt_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
rlen = len - TLV_HDRL;
TCHECK(*tlv);
type = EXTRACT_16BITS(&tlv->type);
if (type != F_TLV_SPAD) {
printf("Error: expecting SPARSEDATA!\n");
return -1;
}
return sdatailv_print(tdp, rlen, op_msk, indent);
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
pkeyitlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
register const u_char *tdp = (u_char *) TLV_DATA(tlv);
register const u_char *dp = tdp + 4;
const struct forces_tlv *kdtlv = (struct forces_tlv *)dp;
u_int32_t id;
char *ib = indent_pr(indent, 0);
u_int16_t type, tll;
int invtlv;
TCHECK(*tdp);
id = EXTRACT_32BITS(tdp);
printf("%sKeyinfo: Key 0x%x\n", ib, id);
TCHECK(*kdtlv);
type = EXTRACT_16BITS(&kdtlv->type);
invtlv = tlv_valid(kdtlv, len);
if (invtlv) {
printf("%s TLV type 0x%x len %d\n",
tok2str(ForCES_TLV_err, NULL, invtlv), type,
EXTRACT_16BITS(&kdtlv->length));
return -1;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
tll = EXTRACT_16BITS(&kdtlv->length);
dp = (u_char *) TLV_DATA(kdtlv);
return fdatatlv_print(dp, tll, op_msk, indent);
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
pdatacnt_print(register const u_char * pptr, register u_int len,
u_int32_t IDcnt, u_int16_t op_msk, int indent)
{
u_int i;
int rc;
u_int32_t id;
char *ib = indent_pr(indent, 0);
for (i = 0; i < IDcnt; i++) {
TCHECK2(*pptr, 4);
if (len < 4)
goto trunc;
id = EXTRACT_32BITS(pptr);
if (vflag >= 3)
printf("%s ID#%02u: %d\n", ib, i + 1, id);
len -= 4;
pptr += 4;
}
if (len) {
const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
u_int16_t type;
u_int16_t tll;
int pad = 0;
u_int aln;
int invtlv;
TCHECK(*pdtlv);
type = EXTRACT_16BITS(&pdtlv->type);
invtlv = tlv_valid(pdtlv, len);
if (invtlv) {
printf
("%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n",
tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
EXTRACT_16BITS(&pdtlv->length));
goto pd_err;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length));
if (aln > EXTRACT_16BITS(&pdtlv->length)) {
if (aln > len) {
printf
("Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n",
type, EXTRACT_16BITS(&pdtlv->length), aln - len);
} else {
pad = aln - EXTRACT_16BITS(&pdtlv->length);
}
}
if (pd_valid(type)) {
const struct pdata_ops *ops = get_forces_pd(type);
if (vflag >= 3 && ops->v != F_TLV_PDAT) {
if (pad)
printf
("%s %s (Length %d DataLen %d pad %d Bytes)\n",
ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
tll, pad);
else
printf
("%s %s (Length %d DataLen %d Bytes)\n",
ib, ops->s, EXTRACT_16BITS(&pdtlv->length),
tll);
}
chk_op_type(type, op_msk, ops->op_msk);
rc = ops->print((const u_char *)pdtlv,
tll + pad + TLV_HDRL, op_msk,
indent + 2);
} else {
printf("Invalid path data content type 0x%x len %d\n",
type, EXTRACT_16BITS(&pdtlv->length));
pd_err:
if (EXTRACT_16BITS(&pdtlv->length)) {
hex_print_with_offset("Bad Data val\n\t [",
pptr, len, 0);
printf("]\n");
return -1;
}
}
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
pdata_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct pathdata_h *pdh = (struct pathdata_h *)pptr;
char *ib = indent_pr(indent, 0);
u_int minsize = 0;
TCHECK(*pdh);
if (len < sizeof(struct pathdata_h))
goto trunc;
if (vflag >= 3) {
printf("\n%sPathdata: Flags 0x%x ID count %d\n",
ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt));
}
if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) {
op_msk |= B_KEYIN;
}
pptr += sizeof(struct pathdata_h);
len -= sizeof(struct pathdata_h);
minsize = EXTRACT_16BITS(&pdh->pIDcnt) * 4;
if (len < minsize) {
printf("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
len);
hex_print_with_offset("\t\t\tID Data[", pptr, len, 0);
printf("]\n");
return -1;
}
return pdatacnt_print(pptr, len, EXTRACT_16BITS(&pdh->pIDcnt), op_msk, indent);
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
genoptlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
u_int16_t type;
int tll;
int invtlv;
char *ib = indent_pr(indent, 0);
TCHECK(*pdtlv);
type = EXTRACT_16BITS(&pdtlv->type);
tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
invtlv = tlv_valid(pdtlv, len);
printf("genoptlvprint - %s TLV type 0x%x len %d\n",
tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length));
if (!invtlv) {
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
register const u_char *dp = (u_char *) TLV_DATA(pdtlv);
if (!ttlv_valid(type)) {
printf("%s TLV type 0x%x len %d\n",
tok2str(ForCES_TLV_err, NULL, invtlv), type,
EXTRACT_16BITS(&pdtlv->length));
return -1;
}
if (vflag >= 3)
printf("%s%s, length %d (data length %d Bytes)",
ib, tok2str(ForCES_TLV, NULL, type),
EXTRACT_16BITS(&pdtlv->length), tll);
return pdata_print(dp, tll, op_msk, indent + 1);
} else {
printf("\t\t\tInvalid ForCES TLV type=%x", type);
return -1;
}
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
recpdoptlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr;
int tll;
int rc = 0;
int invtlv;
u_int16_t type;
register const u_char *dp;
char *ib;
while (len != 0) {
TCHECK(*pdtlv);
invtlv = tlv_valid(pdtlv, len);
if (invtlv) {
break;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
ib = indent_pr(indent, 0);
type = EXTRACT_16BITS(&pdtlv->type);
dp = (u_char *) TLV_DATA(pdtlv);
tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL;
if (vflag >= 3)
printf
("%s%s, length %d (data encapsulated %d Bytes)",
ib, tok2str(ForCES_TLV, NULL, type),
EXTRACT_16BITS(&pdtlv->length),
EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL);
rc = pdata_print(dp, tll, op_msk, indent + 1);
pdtlv = GO_NXT_TLV(pdtlv, len);
}
if (len) {
printf
("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length));
return -1;
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
invoptlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
char *ib = indent_pr(indent, 1);
if (vflag >= 3) {
printf("%sData[", &ib[1]);
hex_print_with_offset(ib, pptr, len, 0);
printf("%s]\n", ib);
}
return -1;
}
int otlv_print(const struct forces_tlv *otlv, u_int16_t op_msk _U_, int indent)
{
int rc = 0;
register const u_char *dp = (u_char *) TLV_DATA(otlv);
u_int16_t type;
int tll;
char *ib = indent_pr(indent, 0);
const struct optlv_h *ops;
/*
* lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length)
* >= TLV_HDRL.
*/
TCHECK(*otlv);
type = EXTRACT_16BITS(&otlv->type);
tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL;
ops = get_forces_optlv_h(type);
if (vflag >= 3) {
printf("%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type,
EXTRACT_16BITS(&otlv->length));
}
/* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */
if (!ops->flags & ZERO_TTLV) {
if (tll != 0) /* instead of "if (tll)" - for readability .. */
printf("%s: Illegal - MUST be empty\n", ops->s);
return rc;
}
/* rest of ops must at least have 12B {pathinfo} */
if (tll < OP_MIN_SIZ) {
printf("\t\tOper TLV %s(0x%x) length %d\n", ops->s, type,
EXTRACT_16BITS(&otlv->length));
printf("\t\tTruncated data size %d minimum required %d\n", tll,
OP_MIN_SIZ);
return invoptlv_print(dp, tll, ops->op_msk, indent);
}
rc = ops->print(dp, tll, ops->op_msk, indent + 1);
return rc;
trunc:
fputs("[|forces]", stdout);
return -1;
}
#define ASTDLN 4
#define ASTMCD 255
int
asttlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
u_int32_t rescode;
u_int dlen;
char *ib = indent_pr(indent, 0);
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != ASTDLN) {
printf("illegal ASTresult-TLV: %d bytes!\n", dlen);
return -1;
}
TCHECK2(*pptr, 4);
rescode = EXTRACT_32BITS(pptr);
if (rescode > ASTMCD) {
printf("illegal ASTresult result code: %d!\n", rescode);
return -1;
}
if (vflag >= 3) {
printf("Teardown reason:\n%s", ib);
switch (rescode) {
case 0:
printf("Normal Teardown");
break;
case 1:
printf("Loss of Heartbeats");
break;
case 2:
printf("Out of bandwidth");
break;
case 3:
printf("Out of Memory");
break;
case 4:
printf("Application Crash");
break;
default:
printf("Unknown Teardown reason");
break;
}
printf("(%x)\n%s", rescode, ib);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
#define ASRDLN 4
#define ASRMCD 3
int
asrtlv_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
u_int32_t rescode;
u_int dlen;
char *ib = indent_pr(indent, 0);
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != ASRDLN) { /* id, instance, oper tlv */
printf("illegal ASRresult-TLV: %d bytes!\n", dlen);
return -1;
}
TCHECK2(*pptr, 4);
rescode = EXTRACT_32BITS(pptr);
if (rescode > ASRMCD) {
printf("illegal ASRresult result code: %d!\n", rescode);
return -1;
}
if (vflag >= 3) {
printf("\n%s", ib);
switch (rescode) {
case 0:
printf("Success ");
break;
case 1:
printf("FE ID invalid ");
break;
case 2:
printf("permission denied ");
break;
default:
printf("Unknown ");
break;
}
printf("(%x)\n%s", rescode, ib);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
/*
* XXX - not used.
*/
int
gentltlv_print(register const u_char * pptr _U_, register u_int len,
u_int16_t op_msk _U_, int indent _U_)
{
u_int dlen = len - TLV_HDRL;
if (dlen < 4) { /* at least 32 bits must exist */
printf("truncated TLV: %d bytes missing! ", 4 - dlen);
return -1;
}
return 0;
}
#define RD_MIN 8
int
print_metailv(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
u_int dlen;
u_int rlen;
char *ib = indent_pr(indent, 0);
/* XXX: check header length */
const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
/*
* print_metatlv() has ensured that len (what remains in the
* ILV) >= ILV_HDRL.
*/
dlen = len - ILV_HDRL;
rlen = dlen;
TCHECK(*ilv);
printf("\n%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type),
EXTRACT_32BITS(&ilv->length));
hex_print_with_offset("\n\t\t\t\t[", ILV_DATA(ilv), rlen, 0);
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
print_metatlv(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
u_int dlen;
char *ib = indent_pr(indent, 0);
u_int rlen;
const struct forces_ilv *ilv = (struct forces_ilv *)pptr;
int invilv;
/*
* redirect_print() has ensured that len (what remains in the
* TLV) >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
rlen = dlen;
printf("\n%s METADATA\n", ib);
while (rlen != 0) {
TCHECK(*ilv);
invilv = ilv_valid(ilv, rlen);
if (invilv)
break;
/*
* At this point, ilv_valid() has ensured that the ILV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
print_metailv((u_char *) ilv, rlen, 0, indent + 1);
ilv = GO_NXT_ILV(ilv, rlen);
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
/*
*/
int
print_reddata(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent _U_)
{
u_int dlen;
u_int rlen;
int invtlv;
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
/*
* redirect_print() has ensured that len (what remains in the
* TLV) >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
printf("\n\t\t Redirect DATA\n");
if (dlen <= RD_MIN) {
printf("\n\t\ttruncated Redirect data: %d bytes missing! ",
RD_MIN - dlen);
return -1;
}
rlen = dlen;
TCHECK(*tlv);
invtlv = tlv_valid(tlv, rlen);
if (invtlv) {
printf("Redir data type 0x%x len %d\n", EXTRACT_16BITS(&tlv->type),
EXTRACT_16BITS(&tlv->length));
return -1;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
rlen -= TLV_HDRL;
hex_print_with_offset("\n\t\t\t[", TLV_DATA(tlv), rlen, 0);
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
redirect_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (struct forces_tlv *)pptr;
u_int dlen;
u_int rlen;
int invtlv;
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen <= RD_MIN) {
printf("\n\t\ttruncated Redirect TLV: %d bytes missing! ",
RD_MIN - dlen);
return -1;
}
rlen = dlen;
indent += 1;
while (rlen != 0) {
TCHECK(*tlv);
invtlv = tlv_valid(tlv, rlen);
if (invtlv)
break;
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
if (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) {
print_metatlv((u_char *) TLV_DATA(tlv), rlen, 0, indent);
} else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) {
print_reddata((u_char *) TLV_DATA(tlv), rlen, 0, indent);
} else {
printf("Unknown REDIRECT TLV 0x%x len %d\n",
EXTRACT_16BITS(&tlv->type), EXTRACT_16BITS(&tlv->length));
}
tlv = GO_NXT_TLV(tlv, rlen);
}
if (rlen) {
printf
("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
EXTRACT_16BITS(&tlv->type), rlen - EXTRACT_16BITS(&tlv->length));
return -1;
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
#define OP_OFF 8
#define OP_MIN 12
int
lfbselect_print(register const u_char * pptr, register u_int len,
u_int16_t op_msk, int indent)
{
const struct forces_lfbsh *lfbs;
const struct forces_tlv *otlv;
char *ib = indent_pr(indent, 0);
u_int dlen;
u_int rlen;
int invtlv;
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */
printf("\n\t\ttruncated lfb selector: %d bytes missing! ",
OP_MIN - dlen);
return -1;
}
/*
* At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so
* we also know that it's > OP_OFF.
*/
rlen = dlen - OP_OFF;
lfbs = (const struct forces_lfbsh *)pptr;
TCHECK(*lfbs);
if (vflag >= 3) {
printf("\n%s%s(Classid %x) instance %x\n",
ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)),
EXTRACT_32BITS(&lfbs->class),
EXTRACT_32BITS(&lfbs->instance));
}
otlv = (struct forces_tlv *)(lfbs + 1);
indent += 1;
while (rlen != 0) {
TCHECK(*otlv);
invtlv = tlv_valid(otlv, rlen);
if (invtlv)
break;
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
if (op_valid(EXTRACT_16BITS(&otlv->type), op_msk)) {
otlv_print(otlv, 0, indent);
} else {
if (vflag < 3)
printf("\n");
printf
("\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n",
EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length));
invoptlv_print((u_char *)otlv, rlen, 0, indent);
}
otlv = GO_NXT_TLV(otlv, rlen);
}
if (rlen) {
printf
("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ",
EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length));
return -1;
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
int
forces_type_print(register const u_char * pptr, const struct forcesh *fhdr _U_,
register u_int mlen, const struct tom_h *tops)
{
const struct forces_tlv *tltlv;
u_int rlen;
int invtlv;
int rc = 0;
int ttlv = 0;
/*
* forces_print() has already checked that mlen >= ForCES_HDRL
* by calling ForCES_HLN_VALID().
*/
rlen = mlen - ForCES_HDRL;
if (rlen > TLV_HLN) {
if (tops->flags & ZERO_TTLV) {
printf("<0x%x>Illegal Top level TLV!\n", tops->flags);
return -1;
}
} else {
if (tops->flags & ZERO_MORE_TTLV)
return 0;
if (tops->flags & ONE_MORE_TTLV) {
printf("\tTop level TLV Data missing!\n");
return -1;
}
}
if (tops->flags & ZERO_TTLV) {
return 0;
}
ttlv = tops->flags >> 4;
tltlv = GET_TOP_TLV(pptr);
/*XXX: 15 top level tlvs will probably be fine
You are nuts if you send more ;-> */
while (rlen != 0) {
TCHECK(*tltlv);
invtlv = tlv_valid(tltlv, rlen);
if (invtlv)
break;
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the packet).
*/
if (!ttlv_valid(EXTRACT_16BITS(&tltlv->type))) {
printf("\n\tInvalid ForCES Top TLV type=0x%x",
EXTRACT_16BITS(&tltlv->type));
return -1;
}
if (vflag >= 3)
printf("\t%s, length %d (data length %d Bytes)",
tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)),
EXTRACT_16BITS(&tltlv->length),
EXTRACT_16BITS(&tltlv->length) - TLV_HDRL);
rc = tops->print((u_char *) TLV_DATA(tltlv),
EXTRACT_16BITS(&tltlv->length), tops->op_msk, 9);
if (rc < 0) {
return -1;
}
tltlv = GO_NXT_TLV(tltlv, rlen);
ttlv--;
if (ttlv <= 0)
break;
}
/*
* XXX - if ttlv != 0, does that mean that the packet was too
* short, and didn't have *enough* TLVs in it?
*/
if (rlen) {
printf("\tMess TopTLV header: min %u, total %d advertised %d ",
TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length));
return -1;
}
return 0;
trunc:
fputs("[|forces]", stdout);
return -1;
}
void forces_print(register const u_char * pptr, register u_int len)
{
const struct forcesh *fhdr;
u_int mlen;
u_int32_t flg_raw;
const struct tom_h *tops;
int rc = 0;
fhdr = (const struct forcesh *)pptr;
TCHECK(*fhdr);
if (!tom_valid(fhdr->fm_tom)) {
printf("Invalid ForCES message type %d\n", fhdr->fm_tom);
goto error;
}
mlen = ForCES_BLN(fhdr);
tops = get_forces_tom(fhdr->fm_tom);
if (tops->v == TOM_RSVD) {
printf("\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom);
goto error;
}
printf("\n\tForCES %s ", tops->s);
if (!ForCES_HLN_VALID(mlen, len)) {
printf
("Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ",
ForCES_HDRL, len, ForCES_BLN(fhdr));
goto error;
}
TCHECK2(*(pptr + 20), 4);
flg_raw = EXTRACT_32BITS(pptr + 20);
if (vflag >= 1) {
printf("\n\tForCES Version %d len %uB flags 0x%08x ",
ForCES_V(fhdr), mlen, flg_raw);
printf("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIu64,
ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
EXTRACT_64BITS(fhdr->fm_cor));
}
if (vflag >= 2) {
printf
("\n\tForCES flags:\n\t %s(0x%x), prio=%d, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n",
ForCES_ACKp(ForCES_ACK(fhdr)), ForCES_ACK(fhdr),
ForCES_PRI(fhdr),
ForCES_EMp(ForCES_EM(fhdr)), ForCES_EM(fhdr),
ForCES_ATp(ForCES_AT(fhdr)), ForCES_AT(fhdr),
ForCES_TPp(ForCES_TP(fhdr)), ForCES_TP(fhdr));
printf
("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
ForCES_RS1(fhdr), ForCES_RS2(fhdr));
}
rc = forces_type_print(pptr, fhdr, mlen, tops);
if (rc < 0) {
error:
hex_print_with_offset("\n\t[", pptr, len, 0);
printf("\n\t]");
return;
}
if (vflag >= 4) {
printf("\n\t Raw ForCES message\n\t [");
hex_print_with_offset("\n\t ", pptr, len, 0);
printf("\n\t ]");
}
printf("\n");
return;
trunc:
fputs("[|forces]", stdout);
}