print-fr.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 885 行 · 第 1/2 页

C
885
字号
/* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 *	The Regents of the University of California.  All rights reserved. * * 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, (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, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * 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. */#ifndef lintstatic const char rcsid[] _U_ =	"@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.51 2006-06-23 22:20:32 hannes Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <tcpdump-stdinc.h>#include <stdio.h>#include <string.h>#include <pcap.h>#include "addrtoname.h"#include "interface.h"#include "ethertype.h"#include "nlpid.h"#include "extract.h"#include "oui.h"static void frf15_print(const u_char *, u_int);/* * the frame relay header has a variable length * * the EA bit determines if there is another byte * in the header * * minimum header length is 2 bytes * maximum header length is 4 bytes * *      7    6    5    4    3    2    1    0 *    +----+----+----+----+----+----+----+----+ *    |        DLCI (6 bits)        | CR | EA | *    +----+----+----+----+----+----+----+----+ *    |   DLCI (4 bits)   |FECN|BECN| DE | EA | *    +----+----+----+----+----+----+----+----+ *    |           DLCI (7 bits)          | EA | *    +----+----+----+----+----+----+----+----+ *    |        DLCI (6 bits)        |SDLC| EA | *    +----+----+----+----+----+----+----+----+ */#define FR_EA_BIT	0x01#define FR_CR_BIT       0x02000000#define FR_DE_BIT	0x00020000#define FR_BECN_BIT	0x00040000#define FR_FECN_BIT	0x00080000#define FR_SDLC_BIT	0x00000002struct tok fr_header_flag_values[] = {    { FR_CR_BIT, "C!" },    { FR_DE_BIT, "DE" },    { FR_BECN_BIT, "BECN" },    { FR_FECN_BIT, "FECN" },    { FR_SDLC_BIT, "sdlcore" },    { 0, NULL }};/* FRF.15 / FRF.16 */#define MFR_B_BIT 0x80#define MFR_E_BIT 0x40#define MFR_C_BIT 0x20#define MFR_BEC_MASK    (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)#define MFR_CTRL_FRAME  (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)#define MFR_FRAG_FRAME  (MFR_B_BIT | MFR_E_BIT )struct tok frf_flag_values[] = {    { MFR_B_BIT, "Begin" },    { MFR_E_BIT, "End" },    { MFR_C_BIT, "Control" },    { 0, NULL }};/* Finds out Q.922 address length, DLCI and flags. Returns 0 on success * save the flags dep. on address length */static int parse_q922_addr(const u_char *p, u_int *dlci,                           u_int *addr_len, u_int8_t *flags){	if ((p[0] & FR_EA_BIT))		return -1;	*addr_len = 2;	*dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4);        flags[0] = p[0] & 0x02; /* populate the first flag fields */        flags[1] = p[1] & 0x0c;        flags[2] = 0;           /* clear the rest of the flags */        flags[3] = 0;	if (p[1] & FR_EA_BIT)		return 0;	/* 2-byte Q.922 address */	p += 2;	(*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++;	}	if ((p[0] & FR_EA_BIT) == 0)		return -1; /* more than 4 bytes of Q.922 address? */        flags[3] = p[0] & 0x02;        *dlci = (*dlci << 6) | (p[0] >> 2);	return 0;}char *q922_string(const u_char *p) {    static u_int dlci, addr_len;    static u_int8_t flags[4];    static char buffer[sizeof("DLCI xxxxxxxxxx")];    memset(buffer, 0, sizeof(buffer));    if (parse_q922_addr(p, &dlci, &addr_len, flags) == 0){        snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);    }    return buffer;}/* Frame Relay packet structure, with flags and CRC removed                  +---------------------------+                  |       Q.922 Address*      |                  +--                       --+                  |                           |                  +---------------------------+                  | Control (UI = 0x03)       |                  +---------------------------+                  | Optional Pad      (0x00)  |                  +---------------------------+                  | NLPID                     |                  +---------------------------+                  |             .             |                  |             .             |                  |             .             |                  |           Data            |                  |             .             |                  |             .             |                  +---------------------------+           * Q.922 addresses, as presently defined, are two octets and             contain a 10-bit DLCI.  In some networks Q.922 addresses             may optionally be increased to three or four octets.*/static u_intfr_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 voidfr_hdr_print(int length, u_int addr_len, u_int dlci, u_int8_t *flags, u_int16_t nlpid){    if (qflag) {        (void)printf("Q.922, DLCI %u, length %u: ",                     dlci,                     length);    } else {        if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */            (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ",                         addr_len,                         dlci,                         bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)),                         tok2str(nlpid_values,"unknown", nlpid),                         nlpid,                         length);        else /* must be an ethertype */            (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ",                         addr_len,                         dlci,                         bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)),                         tok2str(ethertype_values, "unknown", nlpid),                         nlpid,                         length);            }}u_intfr_if_print(const struct pcap_pkthdr *h, register const u_char *p){	register u_int length = h->len;	register u_int caplen = h->caplen;        TCHECK2(*p, 4); /* minimum frame header length */        if ((length = fr_print(p, length)) == 0)            return (0);        else            return length; trunc:        printf("[|fr]");        return caplen;}u_intfr_print(register const u_char *p, u_int length){	u_int16_t extracted_ethertype;	u_int dlci;	u_int addr_len;	u_int16_t nlpid;	u_int hdr_len;	u_int8_t flags[4];	if (parse_q922_addr(p, &dlci, &addr_len, flags)) {		printf("Q.922, invalid address");		return 0;	}        TCHECK2(*p,addr_len+1+1);	hdr_len = fr_hdrlen(p, addr_len);        TCHECK2(*p,hdr_len);	if (p[addr_len] != 0x03 && dlci != 0) {                /* lets figure out if we have cisco style encapsulation: */                extracted_ethertype = EXTRACT_16BITS(p+addr_len);                if (eflag)                    fr_hdr_print(length, addr_len, dlci, flags, extracted_ethertype);                if (ether_encap_print(extracted_ethertype,                                      p+addr_len+ETHERTYPE_LEN,                                      length-addr_len-ETHERTYPE_LEN,                                      length-addr_len-ETHERTYPE_LEN,                                      &extracted_ethertype) == 0)                    /* ether_type not known, probably it wasn't one */                    printf("UI %02x! ", p[addr_len]);                else                    return hdr_len;        }	if (!p[addr_len + 1]) {	/* pad byte should be used with 3-byte Q.922 */		if (addr_len != 3)			printf("Pad! ");	} else if (addr_len == 3)		printf("No pad! ");	nlpid = p[hdr_len - 1];	if (eflag)		fr_hdr_print(length, addr_len, dlci, flags, nlpid);	p += hdr_len;	length -= hdr_len;	switch (nlpid) {	case NLPID_IP:	        ip_print(gndo, p, length);		break;#ifdef INET6	case NLPID_IP6:		ip6_print(p, length);		break;#endif	case NLPID_CLNP:	case NLPID_ESIS:	case NLPID_ISIS:                isoclns_print(p-1, length+1, length+1); /* OSI printers need the NLPID field */		break;	case NLPID_SNAP:		if (snap_print(p, length, length, &extracted_ethertype, 0) == 0) {			/* ether_type not known, print raw packet */                        if (!eflag)                            fr_hdr_print(length + hdr_len, hdr_len,                                         dlci, flags, nlpid);			if (!suppress_default_print)                            default_print(p - hdr_len, length + hdr_len);		}		break;        case NLPID_Q933:		q933_print(p, length);		break;        case NLPID_MFR:                frf15_print(p, length);                break;        case NLPID_PPP:                ppp_print(p, length);                break;	default:		if (!eflag)                    fr_hdr_print(length + hdr_len, addr_len,				     dlci, flags, nlpid);		if (!xflag)			default_print(p, length);	}	return hdr_len; trunc:        printf("[|fr]");        return 0;}u_intmfr_if_print(const struct pcap_pkthdr *h, register const u_char *p){	register u_int length = h->len;	register u_int caplen = h->caplen;        TCHECK2(*p, 2); /* minimum frame header length */        if ((length = mfr_print(p, length)) == 0)            return (0);        else            return length; trunc:        printf("[|mfr]");        return caplen;}#define MFR_CTRL_MSG_ADD_LINK        1#define MFR_CTRL_MSG_ADD_LINK_ACK    2#define MFR_CTRL_MSG_ADD_LINK_REJ    3#define MFR_CTRL_MSG_HELLO           4#define MFR_CTRL_MSG_HELLO_ACK       5#define MFR_CTRL_MSG_REMOVE_LINK     6#define MFR_CTRL_MSG_REMOVE_LINK_ACK 7struct tok mfr_ctrl_msg_values[] = {    { MFR_CTRL_MSG_ADD_LINK, "Add Link" },    { MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" },    { MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" },    { MFR_CTRL_MSG_HELLO, "Hello" },    { MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" },    { MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" },    { MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" },    { 0, NULL }};#define MFR_CTRL_IE_BUNDLE_ID  1#define MFR_CTRL_IE_LINK_ID    2#define MFR_CTRL_IE_MAGIC_NUM  3#define MFR_CTRL_IE_TIMESTAMP  5#define MFR_CTRL_IE_VENDOR_EXT 6#define MFR_CTRL_IE_CAUSE      7struct tok mfr_ctrl_ie_values[] = {    { MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"},    { MFR_CTRL_IE_LINK_ID, "Link ID"},    { MFR_CTRL_IE_MAGIC_NUM, "Magic Number"},    { MFR_CTRL_IE_TIMESTAMP, "Timestamp"},    { MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"},    { MFR_CTRL_IE_CAUSE, "Cause"},    { 0, NULL }};#define MFR_ID_STRING_MAXLEN 50struct ie_tlv_header_t {    u_int8_t ie_type;    u_int8_t ie_len;};u_intmfr_print(register const u_char *p, u_int length){    u_int tlen,idx,hdr_len = 0;    u_int16_t sequence_num;    u_int8_t ie_type,ie_len;    const u_int8_t *tptr;/* * FRF.16 Link Integrity Control Frame *  *      7    6    5    4    3    2    1    0 *    +----+----+----+----+----+----+----+----+ *    | B  | E  | C=1| 0    0    0    0  | EA | *    +----+----+----+----+----+----+----+----+ *    | 0    0    0    0    0    0    0    0  | *    +----+----+----+----+----+----+----+----+ *    |              message type             | *    +----+----+----+----+----+----+----+----+ */    TCHECK2(*p, 4); /* minimum frame header length */    if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) {        printf("FRF.16 Control, Flags [%s], %s, length %u",               bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)),               tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",p[2]),               length);        tptr = p + 3;        tlen = length -3;        hdr_len = 3;        if (!vflag)            return hdr_len;        while (tlen>sizeof(struct ie_tlv_header_t)) {            TCHECK2(*tptr, sizeof(struct ie_tlv_header_t));            ie_type=tptr[0];            ie_len=tptr[1];            printf("\n\tIE %s (%u), length %u: ",                   tok2str(mfr_ctrl_ie_values,"Unknown",ie_type),                   ie_type,                   ie_len);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?