summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/print-fr.c
diff options
context:
space:
mode:
authorpkelsey <pkelsey@FreeBSD.org>2015-07-08 16:19:32 +0000
committerpkelsey <pkelsey@FreeBSD.org>2015-07-08 16:19:32 +0000
commit7e965066ede451d7a551dd68d6c59acf32e4846e (patch)
treef0c2243cc0a2a59f3eb1354ba3987d4cbcb788bc /contrib/tcpdump/print-fr.c
parent732211dc794db586649eabfc1d517b8a477440f5 (diff)
parentc2704d8ede887d9fe69a9a11fe0755b09ec6895d (diff)
downloadFreeBSD-src-7e965066ede451d7a551dd68d6c59acf32e4846e.zip
FreeBSD-src-7e965066ede451d7a551dd68d6c59acf32e4846e.tar.gz
MFV r285191: tcpdump 4.7.4.
Also, the changes made in r272451 and r272653 that were lost in the merge of 4.6.2 (r276788) have been restored. PR: 199568 Differential Revision: https://reviews.freebsd.org/D3007 Reviewed by: brooks, hiren Approved by: jmallett (mentor) MFC after: 1 month
Diffstat (limited to 'contrib/tcpdump/print-fr.c')
-rw-r--r--contrib/tcpdump/print-fr.c127
1 files changed, 82 insertions, 45 deletions
diff --git a/contrib/tcpdump/print-fr.c b/contrib/tcpdump/print-fr.c
index ba6d92b..b7bec4b 100644
--- a/contrib/tcpdump/print-fr.c
+++ b/contrib/tcpdump/print-fr.c
@@ -34,6 +34,7 @@
#include "interface.h"
#include "addrtoname.h"
#include "ethertype.h"
+#include "llc.h"
#include "nlpid.h"
#include "extract.h"
#include "oui.h"
@@ -94,15 +95,21 @@ static const struct tok frf_flag_values[] = {
{ 0, NULL }
};
-/* Finds out Q.922 address length, DLCI and flags. Returns 0 on success
+/* Finds out Q.922 address length, DLCI and flags. Returns 1 on success,
+ * 0 on invalid address, -1 on truncated packet
* save the flags dep. on address length
*/
-static int parse_q922_addr(const u_char *p, u_int *dlci,
- u_int *addr_len, uint8_t *flags)
+static int parse_q922_addr(netdissect_options *ndo,
+ const u_char *p, u_int *dlci,
+ u_int *addr_len, uint8_t *flags, u_int length)
{
- if ((p[0] & FR_EA_BIT))
+ if (!ND_TTEST(p[0]) || length < 1)
return -1;
+ if ((p[0] & FR_EA_BIT))
+ return 0;
+ if (!ND_TTEST(p[1]) || length < 2)
+ return -1;
*addr_len = 2;
*dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4);
@@ -112,34 +119,42 @@ static int parse_q922_addr(const u_char *p, u_int *dlci,
flags[3] = 0;
if (p[1] & FR_EA_BIT)
- return 0; /* 2-byte Q.922 address */
+ return 1; /* 2-byte Q.922 address */
p += 2;
+ length -= 2;
+ if (!ND_TTEST(p[0]) || length < 1)
+ return -1;
(*addr_len)++; /* 3- or 4-byte Q.922 address */
if ((p[0] & FR_EA_BIT) == 0) {
*dlci = (*dlci << 7) | (p[0] >> 1);
(*addr_len)++; /* 4-byte Q.922 address */
p++;
+ length--;
}
+ if (!ND_TTEST(p[0]) || length < 1)
+ return -1;
if ((p[0] & FR_EA_BIT) == 0)
- return -1; /* more than 4 bytes of Q.922 address? */
+ return 0; /* more than 4 bytes of Q.922 address? */
flags[3] = p[0] & 0x02;
*dlci = (*dlci << 6) | (p[0] >> 2);
- return 0;
+ return 1;
}
-char *q922_string(const u_char *p) {
+char *
+q922_string(netdissect_options *ndo, const u_char *p, u_int length)
+{
static u_int dlci, addr_len;
static uint8_t flags[4];
static char buffer[sizeof("DLCI xxxxxxxxxx")];
memset(buffer, 0, sizeof(buffer));
- if (parse_q922_addr(p, &dlci, &addr_len, flags) == 0){
+ if (parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length) == 1){
snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);
}
@@ -173,15 +188,6 @@ char *q922_string(const u_char *p) {
may optionally be increased to three or four octets.
*/
-static u_int
-fr_hdrlen(const u_char *p, u_int addr_len)
-{
- if (!p[addr_len + 1] /* pad exist */)
- return addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */;
- else
- return addr_len + 1 /* UI */ + 1 /* NLPID */;
-}
-
static void
fr_hdr_print(netdissect_options *ndo,
int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid)
@@ -232,6 +238,7 @@ u_int
fr_print(netdissect_options *ndo,
register const u_char *p, u_int length)
{
+ int ret;
uint16_t extracted_ethertype;
u_int dlci;
u_int addr_len;
@@ -239,39 +246,70 @@ fr_print(netdissect_options *ndo,
u_int hdr_len;
uint8_t flags[4];
- if (parse_q922_addr(p, &dlci, &addr_len, flags)) {
+ ret = parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length);
+ if (ret == -1)
+ goto trunc;
+ if (ret == 0) {
ND_PRINT((ndo, "Q.922, invalid address"));
return 0;
}
- ND_TCHECK2(*p, addr_len+1+1);
- hdr_len = fr_hdrlen(p, addr_len);
- ND_TCHECK2(*p, hdr_len);
-
- if (p[addr_len] != 0x03 && dlci != 0) {
+ ND_TCHECK(p[addr_len]);
+ if (length < addr_len + 1)
+ goto trunc;
- /* lets figure out if we have cisco style encapsulation: */
- extracted_ethertype = EXTRACT_16BITS(p+addr_len);
-
- if (ndo->ndo_eflag)
- fr_hdr_print(ndo, length, addr_len, dlci, flags, extracted_ethertype);
-
- if (ethertype_print(ndo, extracted_ethertype,
- p+addr_len+ETHERTYPE_LEN,
- length-addr_len-ETHERTYPE_LEN,
- length-addr_len-ETHERTYPE_LEN) == 0)
- /* ether_type not known, probably it wasn't one */
- ND_PRINT((ndo, "UI %02x! ", p[addr_len]));
- else
- return hdr_len;
+ if (p[addr_len] != LLC_UI && dlci != 0) {
+ /*
+ * Let's figure out if we have Cisco-style encapsulation,
+ * with an Ethernet type (Cisco HDLC type?) following the
+ * address.
+ */
+ if (!ND_TTEST2(p[addr_len], 2) || length < addr_len + 2) {
+ /* no Ethertype */
+ ND_PRINT((ndo, "UI %02x! ", p[addr_len]));
+ } else {
+ extracted_ethertype = EXTRACT_16BITS(p+addr_len);
+
+ if (ndo->ndo_eflag)
+ fr_hdr_print(ndo, length, addr_len, dlci,
+ flags, extracted_ethertype);
+
+ if (ethertype_print(ndo, extracted_ethertype,
+ p+addr_len+ETHERTYPE_LEN,
+ length-addr_len-ETHERTYPE_LEN,
+ length-addr_len-ETHERTYPE_LEN) == 0)
+ /* ether_type not known, probably it wasn't one */
+ ND_PRINT((ndo, "UI %02x! ", p[addr_len]));
+ else
+ return addr_len + 2;
+ }
}
- if (!p[addr_len + 1]) { /* pad byte should be used with 3-byte Q.922 */
+ ND_TCHECK(p[addr_len+1]);
+ if (length < addr_len + 2)
+ goto trunc;
+
+ if (p[addr_len + 1] == 0) {
+ /*
+ * Assume a pad byte after the control (UI) byte.
+ * A pad byte should only be used with 3-byte Q.922.
+ */
if (addr_len != 3)
ND_PRINT((ndo, "Pad! "));
- } else if (addr_len == 3)
- ND_PRINT((ndo, "No pad! "));
+ hdr_len = addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */;
+ } else {
+ /*
+ * Not a pad byte.
+ * A pad byte should be used with 3-byte Q.922.
+ */
+ if (addr_len == 3)
+ ND_PRINT((ndo, "No pad! "));
+ hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */;
+ }
+ ND_TCHECK(p[hdr_len - 1]);
+ if (length < hdr_len)
+ goto trunc;
nlpid = p[hdr_len - 1];
if (ndo->ndo_eflag)
@@ -284,11 +322,10 @@ fr_print(netdissect_options *ndo,
ip_print(ndo, p, length);
break;
-#ifdef INET6
case NLPID_IP6:
ip6_print(ndo, p, length);
break;
-#endif
+
case NLPID_CLNP:
case NLPID_ESIS:
case NLPID_ISIS:
@@ -558,8 +595,8 @@ mfr_print(netdissect_options *ndo,
static void
frf15_print(netdissect_options *ndo,
- const u_char *p, u_int length) {
-
+ const u_char *p, u_int length)
+{
uint16_t sequence_num, flags;
flags = p[0]&MFR_BEC_MASK;
OpenPOWER on IntegriCloud