Changeset View
Changeset View
Standalone View
Standalone View
head/contrib/tcpdump/print-fr.c
Show All 28 Lines | |||||
#include <tcpdump-stdinc.h> | #include <tcpdump-stdinc.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "interface.h" | #include "interface.h" | ||||
#include "addrtoname.h" | #include "addrtoname.h" | ||||
#include "ethertype.h" | #include "ethertype.h" | ||||
#include "llc.h" | |||||
#include "nlpid.h" | #include "nlpid.h" | ||||
#include "extract.h" | #include "extract.h" | ||||
#include "oui.h" | #include "oui.h" | ||||
static void frf15_print(netdissect_options *ndo, const u_char *, u_int); | static void frf15_print(netdissect_options *ndo, const u_char *, u_int); | ||||
/* | /* | ||||
* the frame relay header has a variable length | * the frame relay header has a variable length | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
static const struct tok frf_flag_values[] = { | static const struct tok frf_flag_values[] = { | ||||
{ MFR_B_BIT, "Begin" }, | { MFR_B_BIT, "Begin" }, | ||||
{ MFR_E_BIT, "End" }, | { MFR_E_BIT, "End" }, | ||||
{ MFR_C_BIT, "Control" }, | { MFR_C_BIT, "Control" }, | ||||
{ 0, NULL } | { 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 | * save the flags dep. on address length | ||||
*/ | */ | ||||
static int parse_q922_addr(const u_char *p, u_int *dlci, | static int parse_q922_addr(netdissect_options *ndo, | ||||
u_int *addr_len, uint8_t *flags) | 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; | return -1; | ||||
if ((p[0] & FR_EA_BIT)) | |||||
return 0; | |||||
if (!ND_TTEST(p[1]) || length < 2) | |||||
return -1; | |||||
*addr_len = 2; | *addr_len = 2; | ||||
*dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); | *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); | ||||
flags[0] = p[0] & 0x02; /* populate the first flag fields */ | flags[0] = p[0] & 0x02; /* populate the first flag fields */ | ||||
flags[1] = p[1] & 0x0c; | flags[1] = p[1] & 0x0c; | ||||
flags[2] = 0; /* clear the rest of the flags */ | flags[2] = 0; /* clear the rest of the flags */ | ||||
flags[3] = 0; | flags[3] = 0; | ||||
if (p[1] & FR_EA_BIT) | if (p[1] & FR_EA_BIT) | ||||
return 0; /* 2-byte Q.922 address */ | return 1; /* 2-byte Q.922 address */ | ||||
p += 2; | p += 2; | ||||
length -= 2; | |||||
if (!ND_TTEST(p[0]) || length < 1) | |||||
return -1; | |||||
(*addr_len)++; /* 3- or 4-byte Q.922 address */ | (*addr_len)++; /* 3- or 4-byte Q.922 address */ | ||||
if ((p[0] & FR_EA_BIT) == 0) { | if ((p[0] & FR_EA_BIT) == 0) { | ||||
*dlci = (*dlci << 7) | (p[0] >> 1); | *dlci = (*dlci << 7) | (p[0] >> 1); | ||||
(*addr_len)++; /* 4-byte Q.922 address */ | (*addr_len)++; /* 4-byte Q.922 address */ | ||||
p++; | p++; | ||||
length--; | |||||
} | } | ||||
if (!ND_TTEST(p[0]) || length < 1) | |||||
return -1; | |||||
if ((p[0] & FR_EA_BIT) == 0) | 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; | flags[3] = p[0] & 0x02; | ||||
*dlci = (*dlci << 6) | (p[0] >> 2); | *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 u_int dlci, addr_len; | ||||
static uint8_t flags[4]; | static uint8_t flags[4]; | ||||
static char buffer[sizeof("DLCI xxxxxxxxxx")]; | static char buffer[sizeof("DLCI xxxxxxxxxx")]; | ||||
memset(buffer, 0, sizeof(buffer)); | 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); | snprintf(buffer, sizeof(buffer), "DLCI %u", dlci); | ||||
} | } | ||||
return buffer; | return buffer; | ||||
} | } | ||||
/* Frame Relay packet structure, with flags and CRC removed | /* Frame Relay packet structure, with flags and CRC removed | ||||
Show All 17 Lines | /* Frame Relay packet structure, with flags and CRC removed | ||||
| . | | | . | | ||||
+---------------------------+ | +---------------------------+ | ||||
* Q.922 addresses, as presently defined, are two octets and | * Q.922 addresses, as presently defined, are two octets and | ||||
contain a 10-bit DLCI. In some networks Q.922 addresses | contain a 10-bit DLCI. In some networks Q.922 addresses | ||||
may optionally be increased to three or four octets. | 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 | static void | ||||
fr_hdr_print(netdissect_options *ndo, | fr_hdr_print(netdissect_options *ndo, | ||||
int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid) | int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid) | ||||
{ | { | ||||
if (ndo->ndo_qflag) { | if (ndo->ndo_qflag) { | ||||
ND_PRINT((ndo, "Q.922, DLCI %u, length %u: ", | ND_PRINT((ndo, "Q.922, DLCI %u, length %u: ", | ||||
dlci, | dlci, | ||||
length)); | length)); | ||||
Show All 34 Lines | trunc: | ||||
ND_PRINT((ndo, "[|fr]")); | ND_PRINT((ndo, "[|fr]")); | ||||
return caplen; | return caplen; | ||||
} | } | ||||
u_int | u_int | ||||
fr_print(netdissect_options *ndo, | fr_print(netdissect_options *ndo, | ||||
register const u_char *p, u_int length) | register const u_char *p, u_int length) | ||||
{ | { | ||||
int ret; | |||||
uint16_t extracted_ethertype; | uint16_t extracted_ethertype; | ||||
u_int dlci; | u_int dlci; | ||||
u_int addr_len; | u_int addr_len; | ||||
uint16_t nlpid; | uint16_t nlpid; | ||||
u_int hdr_len; | u_int hdr_len; | ||||
uint8_t flags[4]; | 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")); | ND_PRINT((ndo, "Q.922, invalid address")); | ||||
return 0; | return 0; | ||||
} | } | ||||
ND_TCHECK2(*p, addr_len+1+1); | ND_TCHECK(p[addr_len]); | ||||
hdr_len = fr_hdrlen(p, addr_len); | if (length < addr_len + 1) | ||||
ND_TCHECK2(*p, hdr_len); | goto trunc; | ||||
if (p[addr_len] != 0x03 && dlci != 0) { | if (p[addr_len] != LLC_UI && dlci != 0) { | ||||
/* | |||||
/* lets figure out if we have cisco style encapsulation: */ | * 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); | extracted_ethertype = EXTRACT_16BITS(p+addr_len); | ||||
if (ndo->ndo_eflag) | if (ndo->ndo_eflag) | ||||
fr_hdr_print(ndo, length, addr_len, dlci, flags, extracted_ethertype); | fr_hdr_print(ndo, length, addr_len, dlci, | ||||
flags, extracted_ethertype); | |||||
if (ethertype_print(ndo, extracted_ethertype, | if (ethertype_print(ndo, extracted_ethertype, | ||||
p+addr_len+ETHERTYPE_LEN, | p+addr_len+ETHERTYPE_LEN, | ||||
length-addr_len-ETHERTYPE_LEN, | length-addr_len-ETHERTYPE_LEN, | ||||
length-addr_len-ETHERTYPE_LEN) == 0) | length-addr_len-ETHERTYPE_LEN) == 0) | ||||
/* ether_type not known, probably it wasn't one */ | /* ether_type not known, probably it wasn't one */ | ||||
ND_PRINT((ndo, "UI %02x! ", p[addr_len])); | ND_PRINT((ndo, "UI %02x! ", p[addr_len])); | ||||
else | else | ||||
return hdr_len; | 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) | if (addr_len != 3) | ||||
ND_PRINT((ndo, "Pad! ")); | ND_PRINT((ndo, "Pad! ")); | ||||
} else if (addr_len == 3) | 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! ")); | 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]; | nlpid = p[hdr_len - 1]; | ||||
if (ndo->ndo_eflag) | if (ndo->ndo_eflag) | ||||
fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid); | fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid); | ||||
p += hdr_len; | p += hdr_len; | ||||
length -= hdr_len; | length -= hdr_len; | ||||
switch (nlpid) { | switch (nlpid) { | ||||
case NLPID_IP: | case NLPID_IP: | ||||
ip_print(ndo, p, length); | ip_print(ndo, p, length); | ||||
break; | break; | ||||
#ifdef INET6 | |||||
case NLPID_IP6: | case NLPID_IP6: | ||||
ip6_print(ndo, p, length); | ip6_print(ndo, p, length); | ||||
break; | break; | ||||
#endif | |||||
case NLPID_CLNP: | case NLPID_CLNP: | ||||
case NLPID_ESIS: | case NLPID_ESIS: | ||||
case NLPID_ISIS: | case NLPID_ISIS: | ||||
isoclns_print(ndo, p - 1, length + 1, length + 1); /* OSI printers need the NLPID field */ | isoclns_print(ndo, p - 1, length + 1, length + 1); /* OSI printers need the NLPID field */ | ||||
break; | break; | ||||
case NLPID_SNAP: | case NLPID_SNAP: | ||||
if (snap_print(ndo, p, length, length, 0) == 0) { | if (snap_print(ndo, p, length, length, 0) == 0) { | ||||
▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | |||||
* | sequence (low 8 bits) | | * | sequence (low 8 bits) | | ||||
* +----+----+----+----+----+----+----+----+ | * +----+----+----+----+----+----+----+----+ | ||||
*/ | */ | ||||
#define FR_FRF15_FRAGTYPE 0x01 | #define FR_FRF15_FRAGTYPE 0x01 | ||||
static void | static void | ||||
frf15_print(netdissect_options *ndo, | frf15_print(netdissect_options *ndo, | ||||
const u_char *p, u_int length) { | const u_char *p, u_int length) | ||||
{ | |||||
uint16_t sequence_num, flags; | uint16_t sequence_num, flags; | ||||
flags = p[0]&MFR_BEC_MASK; | flags = p[0]&MFR_BEC_MASK; | ||||
sequence_num = (p[0]&0x1e)<<7 | p[1]; | sequence_num = (p[0]&0x1e)<<7 | p[1]; | ||||
ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", | ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", | ||||
sequence_num, | sequence_num, | ||||
bittok2str(frf_flag_values,"none",flags), | bittok2str(frf_flag_values,"none",flags), | ||||
▲ Show 20 Lines • Show All 324 Lines • Show Last 20 Lines |