print-atm.c revision 172686
129881Swollman/*
229881Swollman * Copyright (c) 1994, 1995, 1996, 1997
329881Swollman *	The Regents of the University of California.  All rights reserved.
429881Swollman *
529881Swollman * Redistribution and use in source and binary forms, with or without
629881Swollman * modification, are permitted provided that: (1) source code distributions
729881Swollman * retain the above copyright notice and this paragraph in its entirety, (2)
829881Swollman * distributions including binary code include the above copyright notice and
929881Swollman * this paragraph in its entirety in the documentation or other materials
1029881Swollman * provided with the distribution, and (3) all advertising materials mentioning
1129881Swollman * features or use of this software display the following acknowledgement:
1229881Swollman * ``This product includes software developed by the University of California,
1329881Swollman * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1429881Swollman * the University nor the names of its contributors may be used to endorse
1529881Swollman * or promote products derived from this software without specific prior
1629881Swollman * written permission.
1729881Swollman * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1829881Swollman * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1929881Swollman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2029881Swollman *
2129881Swollman * $FreeBSD: head/contrib/tcpdump/print-atm.c 172686 2007-10-16 02:31:48Z mlaier $
2229881Swollman */
2329881Swollman#ifndef lint
2429881Swollmanstatic const char rcsid[] _U_ =
2529881Swollman    "@(#) $Header: /tcpdump/master/tcpdump/print-atm.c,v 1.38.2.6 2006/01/25 13:27:24 hannes Exp $ (LBL)";
2629881Swollman#endif
2729881Swollman
2829881Swollman#ifdef HAVE_CONFIG_H
2929881Swollman#include "config.h"
3029881Swollman#endif
3129881Swollman
3229881Swollman#include <tcpdump-stdinc.h>
3329881Swollman
34126229Sbde#include <stdio.h>
35126229Sbde#include <pcap.h>
36126229Sbde#include <string.h>
37126229Sbde
38126229Sbde#include "interface.h"
39126229Sbde#include "extract.h"
40126229Sbde#include "addrtoname.h"
41126229Sbde#include "ethertype.h"
42126229Sbde#include "atm.h"
4387715Smarkm#include "atmuni31.h"
4487715Smarkm#include "llc.h"
4587715Smarkm
4629881Swollman#include "ether.h"
4729881Swollman
4829881Swollmanstruct tok oam_f_values[] = {
4929881Swollman    { OAMF4SC, "OAM F4 (segment)" },
5029881Swollman    { OAMF4EC, "OAM F4 (end)" },
5129881Swollman    { 0, NULL }
5229881Swollman};
5329881Swollman
5429881Swollmanstruct tok oam_celltype_values[] = {
5529881Swollman    { 0x1, "Fault Management" },
5629881Swollman    { 0x2, "Performance Management" },
5729881Swollman    { 0x8, "activate/deactivate" },
5829881Swollman    { 0xf, "System Management" },
5929881Swollman    { 0, NULL }
6029881Swollman};
6129881Swollman
6229881Swollmanstruct tok oam_fm_functype_values[] = {
6387715Smarkm    { 0x0, "AIS" },
6429881Swollman    { 0x1, "RDI" },
6529881Swollman    { 0x4, "Continuity Check" },
6629881Swollman    { 0x8, "Loopback" },
6729881Swollman    { 0, NULL }
6829881Swollman};
6929881Swollman
7029881Swollmanstruct tok oam_pm_functype_values[] = {
7129881Swollman    { 0x0, "Forward Monitoring" },
7229881Swollman    { 0x1, "Backward Reporting" },
73158160Sbde    { 0x2, "Monitoring and Reporting" },
74158160Sbde    { 0, NULL }
75158160Sbde};
76158160Sbde
77158160Sbdestruct tok oam_ad_functype_values[] = {
78158160Sbde    { 0x0, "Performance Monitoring" },
79158160Sbde    { 0x1, "Continuity Check" },
80158160Sbde    { 0, NULL }
81158160Sbde};
82158160Sbde
83158160Sbdestatic const struct tok *oam_functype_values[16] = {
84158160Sbde    NULL,
85158160Sbde    oam_fm_functype_values, /* 1 */
86158160Sbde    oam_pm_functype_values, /* 2 */
87158160Sbde    NULL,
88158160Sbde    NULL,
89158160Sbde    NULL,
90158160Sbde    NULL,
91158160Sbde    NULL,
92158160Sbde    oam_ad_functype_values, /* 8 */
9329881Swollman    NULL,
9429881Swollman    NULL,
9529881Swollman    NULL,
9629881Swollman    NULL,
9729881Swollman    NULL,
9829881Swollman    NULL,
9929881Swollman    NULL
100158160Sbde};
10129881Swollman
10229881Swollman/*
10329881Swollman * Print an RFC 1483 LLC-encapsulated ATM frame.
10429881Swollman */
10529881Swollmanstatic void
10629881Swollmanatm_llc_print(const u_char *p, int length, int caplen)
10729881Swollman{
10829881Swollman	u_short extracted_ethertype;
10929881Swollman
11029881Swollman	if (!llc_print(p, length, caplen, NULL, NULL,
111158160Sbde	    &extracted_ethertype)) {
11229881Swollman		/* ether_type not known, print raw packet */
11329881Swollman		if (extracted_ethertype) {
11429881Swollman			printf("(LLC %s) ",
11529881Swollman		etherproto_string(htons(extracted_ethertype)));
11629881Swollman		}
11729881Swollman		if (!suppress_default_print)
11829881Swollman			default_print(p, caplen);
11929881Swollman	}
120158160Sbde}
121158160Sbde
122158160Sbde/*
123158160Sbde * Given a SAP value, generate the LLC header value for a UI packet
124158160Sbde * with that SAP as the source and destination SAP.
125158160Sbde */
126158160Sbde#define LLC_UI_HDR(sap)	((sap)<<16 | (sap<<8) | 0x03)
127158160Sbde
128158160Sbde/*
129158160Sbde * This is the top level routine of the printer.  'p' points
130158160Sbde * to the LLC/SNAP header of the packet, 'h->ts' is the timestamp,
131158160Sbde * 'h->len' is the length of the packet off the wire, and 'h->caplen'
132158160Sbde * is the number of bytes actually captured.
133158160Sbde */
134158160Sbdeu_int
135158160Sbdeatm_if_print(const struct pcap_pkthdr *h, const u_char *p)
136158160Sbde{
137158160Sbde	u_int caplen = h->caplen;
138158160Sbde	u_int length = h->len;
139158160Sbde	u_int32_t llchdr;
14029881Swollman	u_int hdrlen = 0;
14129881Swollman
14229881Swollman	if (caplen < 8) {
14329881Swollman		printf("[|atm]");
14429881Swollman		return (caplen);
14529881Swollman	}
14629881Swollman
14729881Swollman        /* Cisco Style NLPID ? */
14840060Sobrien        if (*p == LLC_UI) {
14929881Swollman            if (eflag)
15029881Swollman                printf("CNLPID ");
15129881Swollman            isoclns_print(p+1, length-1, caplen-1);
15229881Swollman            return hdrlen;
15329881Swollman        }
15429881Swollman
15529881Swollman	/*
15629881Swollman	 * Extract the presumed LLC header into a variable, for quick
15729881Swollman	 * testing.
15829881Swollman	 * Then check for a header that's neither a header for a SNAP
15929881Swollman	 * packet nor an RFC 2684 routed NLPID-formatted PDU nor
16029881Swollman	 * an 802.2-but-no-SNAP IP packet.
16129881Swollman	 */
16229881Swollman	llchdr = EXTRACT_24BITS(p);
16329881Swollman	if (llchdr != LLC_UI_HDR(LLCSAP_SNAP) &&
16429881Swollman	    llchdr != LLC_UI_HDR(LLCSAP_ISONS) &&
16529881Swollman	    llchdr != LLC_UI_HDR(LLCSAP_IP)) {
16629881Swollman		/*
16729881Swollman		 * XXX - assume 802.6 MAC header from Fore driver.
16829881Swollman		 *
16929881Swollman		 * Unfortunately, the above list doesn't check for
17029881Swollman		 * all known SAPs, doesn't check for headers where
17129881Swollman		 * the source and destination SAP aren't the same,
17229881Swollman		 * and doesn't check for non-UI frames.  It also
17329881Swollman		 * runs the risk of an 802.6 MAC header that happens
17429881Swollman		 * to begin with one of those values being
17529881Swollman		 * incorrectly treated as an 802.2 header.
17629881Swollman		 *
17729881Swollman		 * So is that Fore driver still around?  And, if so,
17829881Swollman		 * is it still putting 802.6 MAC headers on ATM
17929881Swollman		 * packets?  If so, could it be changed to use a
18029881Swollman		 * new DLT_IEEE802_6 value if we added it?
18129881Swollman		 */
18229881Swollman		if (eflag)
18329881Swollman			printf("%08x%08x %08x%08x ",
18429881Swollman			       EXTRACT_32BITS(p),
18529881Swollman			       EXTRACT_32BITS(p+4),
18629881Swollman			       EXTRACT_32BITS(p+8),
18729881Swollman			       EXTRACT_32BITS(p+12));
18829881Swollman		p += 20;
18929881Swollman		length -= 20;
19029881Swollman		caplen -= 20;
19129881Swollman		hdrlen += 20;
19229881Swollman	}
19329881Swollman	atm_llc_print(p, length, caplen);
19429881Swollman	return (hdrlen);
19529881Swollman}
19629881Swollman
19729881Swollman/*
19829881Swollman * ATM signalling.
19929881Swollman */
20029881Swollmanstatic struct tok msgtype2str[] = {
20129881Swollman	{ CALL_PROCEED,		"Call_proceeding" },
20229881Swollman	{ CONNECT,		"Connect" },
20329881Swollman	{ CONNECT_ACK,		"Connect_ack" },
20429881Swollman	{ SETUP,		"Setup" },
20529881Swollman	{ RELEASE,		"Release" },
20629881Swollman	{ RELEASE_DONE,		"Release_complete" },
20729881Swollman	{ RESTART,		"Restart" },
20829881Swollman	{ RESTART_ACK,		"Restart_ack" },
20929881Swollman	{ STATUS,		"Status" },
21029881Swollman	{ STATUS_ENQ,		"Status_enquiry" },
21129881Swollman	{ ADD_PARTY,		"Add_party" },
21229881Swollman	{ ADD_PARTY_ACK,	"Add_party_ack" },
21329881Swollman	{ ADD_PARTY_REJ,	"Add_party_reject" },
21429881Swollman	{ DROP_PARTY,		"Drop_party" },
21529881Swollman	{ DROP_PARTY_ACK,	"Drop_party_ack" },
21629881Swollman	{ 0,			NULL }
21729881Swollman};
21829881Swollman
21929881Swollmanstatic void
22029881Swollmansig_print(const u_char *p, int caplen)
22129881Swollman{
22229881Swollman	bpf_u_int32 call_ref;
22329881Swollman
22429881Swollman	if (caplen < PROTO_POS) {
22529881Swollman		printf("[|atm]");
22629881Swollman		return;
22729881Swollman	}
22829881Swollman	if (p[PROTO_POS] == Q2931) {
22929881Swollman		/*
23029881Swollman		 * protocol:Q.2931 for User to Network Interface
23129881Swollman		 * (UNI 3.1) signalling
23229881Swollman		 */
23329881Swollman		printf("Q.2931");
23429881Swollman		if (caplen < MSG_TYPE_POS) {
23529881Swollman			printf(" [|atm]");
23629881Swollman			return;
23729881Swollman		}
23829881Swollman		printf(":%s ",
23929881Swollman		    tok2str(msgtype2str, "msgtype#%d", p[MSG_TYPE_POS]));
24029881Swollman
24129881Swollman		if (caplen < CALL_REF_POS+3) {
24229881Swollman			printf("[|atm]");
243158160Sbde			return;
244158160Sbde		}
245158160Sbde		call_ref = EXTRACT_24BITS(&p[CALL_REF_POS]);
246158160Sbde		printf("CALL_REF:0x%06x", call_ref);
247158160Sbde	} else {
248158160Sbde		/* SCCOP with some unknown protocol atop it */
249158160Sbde		printf("SSCOP, proto %d ", p[PROTO_POS]);
250158160Sbde	}
251158160Sbde}
252158160Sbde
253158160Sbde/*
254158160Sbde * Print an ATM PDU (such as an AAL5 PDU).
255158160Sbde */
256158160Sbdevoid
257158160Sbdeatm_print(u_int vpi, u_int vci, u_int traftype, const u_char *p, u_int length,
258158160Sbde    u_int caplen)
259158160Sbde{
260158160Sbde	if (eflag)
261158160Sbde		printf("VPI:%u VCI:%u ", vpi, vci);
26229881Swollman
26329881Swollman	if (vpi == 0) {
26429881Swollman		switch (vci) {
26529881Swollman
26629881Swollman		case PPC:
26729881Swollman			sig_print(p, caplen);
26829881Swollman			return;
26929881Swollman
27029881Swollman		case BCC:
27129881Swollman			printf("broadcast sig: ");
27229881Swollman			return;
27329881Swollman
27429881Swollman		case OAMF4SC: /* fall through */
27529881Swollman		case OAMF4EC:
27629881Swollman                        oam_print(p, length, ATM_OAM_HEC);
27729881Swollman			return;
27829881Swollman
27929881Swollman		case METAC:
28029881Swollman			printf("meta: ");
28129881Swollman			return;
28229881Swollman
28329881Swollman		case ILMIC:
28429881Swollman			printf("ilmi: ");
28529881Swollman			snmp_print(p, length);
28629881Swollman			return;
28729881Swollman		}
28829881Swollman	}
28929881Swollman
29029881Swollman	switch (traftype) {
29129881Swollman
29229881Swollman	case ATM_LLC:
29329881Swollman	default:
29429881Swollman		/*
29529881Swollman		 * Assumes traffic is LLC if unknown.
29629881Swollman		 */
29729881Swollman		atm_llc_print(p, length, caplen);
29829881Swollman		break;
29929881Swollman
30029881Swollman	case ATM_LANE:
30129881Swollman		lane_print(p, length, caplen);
30229881Swollman		break;
30329881Swollman	}
30429881Swollman}
30529881Swollman
30629881Swollmanint
30729881Swollmanoam_print (const u_char *p, u_int length, u_int hec) {
30829881Swollman
30929881Swollman    u_int32_t cell_header;
31029881Swollman    u_int16_t cell_type, func_type,vpi,vci,payload,clp;
31129881Swollman
31229881Swollman    cell_header = EXTRACT_32BITS(p+hec);
31329881Swollman    cell_type = ((*(p+4+hec))>>4) & 0x0f;
31429881Swollman    func_type = *(p+4+hec) & 0x0f;
31529881Swollman
31629881Swollman    vpi = (cell_header>>20)&0xff;
31729881Swollman    vci = (cell_header>>4)&0xffff;
31829881Swollman    payload = (cell_header>>1)&0x7;
31929881Swollman    clp = cell_header&0x1;
32029881Swollman
32129881Swollman    printf("%s, vpi %u, vci %u, payload %u, clp %u, ",
32229881Swollman           tok2str(oam_f_values, "OAM F5", vci),
32329881Swollman           vpi, vci, payload, clp);
32429881Swollman
32529881Swollman    printf("cell-type %s (%u)",
32629881Swollman           tok2str(oam_celltype_values, "unknown", cell_type),
32729881Swollman           cell_type);
32829881Swollman
32929881Swollman    if (oam_functype_values[cell_type] == NULL)
330        printf(", func-type unknown (%u)", func_type);
331    else
332        printf(", func-type %s (%u)",
333               bittok2str(oam_functype_values[cell_type],"none",func_type),
334               func_type);
335
336    printf(", length %u",length);
337    return 1;
338}
339