xref: /dragonfly/contrib/tcpdump/print-fr.c (revision ed775ee7)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
341c99275SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos  * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos  * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos  * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos  * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos  * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos  * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos  * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos  * or promote products derived from this software without specific prior
1641c99275SPeter Avalos  * written permission.
1741c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos  */
2141c99275SPeter Avalos 
22411677aeSAaron LI /* \summary: Frame Relay printer */
2341c99275SPeter Avalos 
2441c99275SPeter Avalos #ifdef HAVE_CONFIG_H
25*ed775ee7SAntonio Huete Jimenez #include <config.h>
2641c99275SPeter Avalos #endif
2741c99275SPeter Avalos 
28*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2941c99275SPeter Avalos 
3041c99275SPeter Avalos #include <stdio.h>
3141c99275SPeter Avalos #include <string.h>
3241c99275SPeter Avalos 
33411677aeSAaron LI #include "netdissect.h"
3441c99275SPeter Avalos #include "addrtoname.h"
3541c99275SPeter Avalos #include "ethertype.h"
36411677aeSAaron LI #include "llc.h"
3741c99275SPeter Avalos #include "nlpid.h"
3841c99275SPeter Avalos #include "extract.h"
3941c99275SPeter Avalos 
40411677aeSAaron LI static void frf15_print(netdissect_options *ndo, const u_char *, u_int);
4141c99275SPeter Avalos 
4241c99275SPeter Avalos /*
4341c99275SPeter Avalos  * the frame relay header has a variable length
4441c99275SPeter Avalos  *
4541c99275SPeter Avalos  * the EA bit determines if there is another byte
4641c99275SPeter Avalos  * in the header
4741c99275SPeter Avalos  *
4841c99275SPeter Avalos  * minimum header length is 2 bytes
4941c99275SPeter Avalos  * maximum header length is 4 bytes
5041c99275SPeter Avalos  *
5141c99275SPeter Avalos  *      7    6    5    4    3    2    1    0
5241c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
5341c99275SPeter Avalos  *    |        DLCI (6 bits)        | CR | EA |
5441c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
5541c99275SPeter Avalos  *    |   DLCI (4 bits)   |FECN|BECN| DE | EA |
5641c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
5741c99275SPeter Avalos  *    |           DLCI (7 bits)          | EA |
5841c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
5941c99275SPeter Avalos  *    |        DLCI (6 bits)        |SDLC| EA |
6041c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
6141c99275SPeter Avalos  */
6241c99275SPeter Avalos 
6341c99275SPeter Avalos #define FR_EA_BIT	0x01
6441c99275SPeter Avalos 
6541c99275SPeter Avalos #define FR_CR_BIT       0x02000000
6641c99275SPeter Avalos #define FR_DE_BIT	0x00020000
6741c99275SPeter Avalos #define FR_BECN_BIT	0x00040000
6841c99275SPeter Avalos #define FR_FECN_BIT	0x00080000
6941c99275SPeter Avalos #define FR_SDLC_BIT	0x00000002
7041c99275SPeter Avalos 
7141c99275SPeter Avalos 
72411677aeSAaron LI static const struct tok fr_header_flag_values[] = {
7341c99275SPeter Avalos     { FR_CR_BIT, "C!" },
7441c99275SPeter Avalos     { FR_DE_BIT, "DE" },
7541c99275SPeter Avalos     { FR_BECN_BIT, "BECN" },
7641c99275SPeter Avalos     { FR_FECN_BIT, "FECN" },
7741c99275SPeter Avalos     { FR_SDLC_BIT, "sdlcore" },
7841c99275SPeter Avalos     { 0, NULL }
7941c99275SPeter Avalos };
8041c99275SPeter Avalos 
8141c99275SPeter Avalos /* FRF.15 / FRF.16 */
8241c99275SPeter Avalos #define MFR_B_BIT 0x80
8341c99275SPeter Avalos #define MFR_E_BIT 0x40
8441c99275SPeter Avalos #define MFR_C_BIT 0x20
8541c99275SPeter Avalos #define MFR_BEC_MASK    (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
8641c99275SPeter Avalos #define MFR_CTRL_FRAME  (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
8741c99275SPeter Avalos #define MFR_FRAG_FRAME  (MFR_B_BIT | MFR_E_BIT )
8841c99275SPeter Avalos 
89411677aeSAaron LI static const struct tok frf_flag_values[] = {
9041c99275SPeter Avalos     { MFR_B_BIT, "Begin" },
9141c99275SPeter Avalos     { MFR_E_BIT, "End" },
9241c99275SPeter Avalos     { MFR_C_BIT, "Control" },
9341c99275SPeter Avalos     { 0, NULL }
9441c99275SPeter Avalos };
9541c99275SPeter Avalos 
96411677aeSAaron LI /* Finds out Q.922 address length, DLCI and flags. Returns 1 on success,
97411677aeSAaron LI  * 0 on invalid address, -1 on truncated packet
9841c99275SPeter Avalos  * save the flags dep. on address length
9941c99275SPeter Avalos  */
parse_q922_header(netdissect_options * ndo,const u_char * p,u_int * dlci,u_int * addr_len,uint32_t * flags,u_int length)100*ed775ee7SAntonio Huete Jimenez static int parse_q922_header(netdissect_options *ndo,
101411677aeSAaron LI                            const u_char *p, u_int *dlci,
102*ed775ee7SAntonio Huete Jimenez                            u_int *addr_len, uint32_t *flags, u_int length)
10341c99275SPeter Avalos {
104*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_1(p) || length < 1)
10541c99275SPeter Avalos 		return -1;
106*ed775ee7SAntonio Huete Jimenez 	if ((GET_U_1(p) & FR_EA_BIT))
107411677aeSAaron LI 		return 0;
10841c99275SPeter Avalos 
109*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_1(p + 1) || length < 2)
110411677aeSAaron LI 		return -1;
11141c99275SPeter Avalos 	*addr_len = 2;
112*ed775ee7SAntonio Huete Jimenez 	*dlci = ((GET_U_1(p) & 0xFC) << 2) | ((GET_U_1(p + 1) & 0xF0) >> 4);
11341c99275SPeter Avalos 
114*ed775ee7SAntonio Huete Jimenez 	*flags = ((GET_U_1(p) & 0x02) << 24) |	/* CR flag */
115*ed775ee7SAntonio Huete Jimenez 		 ((GET_U_1(p + 1) & 0x0e) << 16);	/* FECN,BECN,DE flags */
11641c99275SPeter Avalos 
117*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(p + 1) & FR_EA_BIT)
118411677aeSAaron LI 		return 1;	/* 2-byte Q.922 address */
11941c99275SPeter Avalos 
12041c99275SPeter Avalos 	p += 2;
121411677aeSAaron LI 	length -= 2;
122*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_1(p) || length < 1)
123411677aeSAaron LI 		return -1;
12441c99275SPeter Avalos 	(*addr_len)++;		/* 3- or 4-byte Q.922 address */
125*ed775ee7SAntonio Huete Jimenez 	if ((GET_U_1(p) & FR_EA_BIT) == 0) {
126*ed775ee7SAntonio Huete Jimenez 		*dlci = (*dlci << 7) | (GET_U_1(p) >> 1);
12741c99275SPeter Avalos 		(*addr_len)++;	/* 4-byte Q.922 address */
12841c99275SPeter Avalos 		p++;
129411677aeSAaron LI 		length--;
13041c99275SPeter Avalos 	}
13141c99275SPeter Avalos 
132*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_1(p) || length < 1)
133411677aeSAaron LI 		return -1;
134*ed775ee7SAntonio Huete Jimenez 	if ((GET_U_1(p) & FR_EA_BIT) == 0)
135411677aeSAaron LI 		return 0; /* more than 4 bytes of Q.922 address? */
13641c99275SPeter Avalos 
137*ed775ee7SAntonio Huete Jimenez 	*flags = *flags | (GET_U_1(p) & 0x02);	/* SDLC flag */
13841c99275SPeter Avalos 
139*ed775ee7SAntonio Huete Jimenez         *dlci = (*dlci << 6) | (GET_U_1(p) >> 2);
14041c99275SPeter Avalos 
141411677aeSAaron LI 	return 1;
14241c99275SPeter Avalos }
14341c99275SPeter Avalos 
144*ed775ee7SAntonio Huete Jimenez const char *
q922_string(netdissect_options * ndo,const u_char * p,u_int length)145411677aeSAaron LI q922_string(netdissect_options *ndo, const u_char *p, u_int length)
146411677aeSAaron LI {
147ea7b4bf5SPeter Avalos 
148ea7b4bf5SPeter Avalos     static u_int dlci, addr_len;
149*ed775ee7SAntonio Huete Jimenez     static uint32_t flags;
150*ed775ee7SAntonio Huete Jimenez     static char buffer[sizeof("parse_q922_header() returned XXXXXXXXXXX")];
151*ed775ee7SAntonio Huete Jimenez     int ret;
152ea7b4bf5SPeter Avalos     memset(buffer, 0, sizeof(buffer));
153ea7b4bf5SPeter Avalos 
154*ed775ee7SAntonio Huete Jimenez     ret = parse_q922_header(ndo, p, &dlci, &addr_len, &flags, length);
155*ed775ee7SAntonio Huete Jimenez     if (ret == 1) {
156ea7b4bf5SPeter Avalos         snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);
157ea7b4bf5SPeter Avalos         return buffer;
158*ed775ee7SAntonio Huete Jimenez     } else if (ret == 0) {
159*ed775ee7SAntonio Huete Jimenez         return "<Invalid DLCI>";
160*ed775ee7SAntonio Huete Jimenez     } else if (ret == -1) {
161*ed775ee7SAntonio Huete Jimenez         return "<Truncated>";
162*ed775ee7SAntonio Huete Jimenez     } else {
163*ed775ee7SAntonio Huete Jimenez         snprintf(buffer, sizeof(buffer), "parse_q922_header() returned %d", ret);
164*ed775ee7SAntonio Huete Jimenez         return buffer;
165*ed775ee7SAntonio Huete Jimenez     }
166ea7b4bf5SPeter Avalos }
167ea7b4bf5SPeter Avalos 
168ea7b4bf5SPeter Avalos 
16941c99275SPeter Avalos /* Frame Relay packet structure, with flags and CRC removed
17041c99275SPeter Avalos 
17141c99275SPeter Avalos                   +---------------------------+
17241c99275SPeter Avalos                   |       Q.922 Address*      |
17341c99275SPeter Avalos                   +--                       --+
17441c99275SPeter Avalos                   |                           |
17541c99275SPeter Avalos                   +---------------------------+
17641c99275SPeter Avalos                   | Control (UI = 0x03)       |
17741c99275SPeter Avalos                   +---------------------------+
17841c99275SPeter Avalos                   | Optional Pad      (0x00)  |
17941c99275SPeter Avalos                   +---------------------------+
18041c99275SPeter Avalos                   | NLPID                     |
18141c99275SPeter Avalos                   +---------------------------+
18241c99275SPeter Avalos                   |             .             |
18341c99275SPeter Avalos                   |             .             |
18441c99275SPeter Avalos                   |             .             |
18541c99275SPeter Avalos                   |           Data            |
18641c99275SPeter Avalos                   |             .             |
18741c99275SPeter Avalos                   |             .             |
18841c99275SPeter Avalos                   +---------------------------+
18941c99275SPeter Avalos 
19041c99275SPeter Avalos            * Q.922 addresses, as presently defined, are two octets and
19141c99275SPeter Avalos              contain a 10-bit DLCI.  In some networks Q.922 addresses
19241c99275SPeter Avalos              may optionally be increased to three or four octets.
19341c99275SPeter Avalos */
19441c99275SPeter Avalos 
19541c99275SPeter Avalos static void
fr_hdr_print(netdissect_options * ndo,int length,u_int addr_len,u_int dlci,uint32_t flags,uint16_t nlpid)196*ed775ee7SAntonio Huete Jimenez fr_hdr_print(netdissect_options *ndo, int length, u_int addr_len,
197*ed775ee7SAntonio Huete Jimenez 	     u_int dlci, uint32_t flags, uint16_t nlpid)
19841c99275SPeter Avalos {
199411677aeSAaron LI     if (ndo->ndo_qflag) {
200*ed775ee7SAntonio Huete Jimenez         ND_PRINT("Q.922, DLCI %u, length %u: ",
20141c99275SPeter Avalos                      dlci,
202*ed775ee7SAntonio Huete Jimenez                      length);
20341c99275SPeter Avalos     } else {
20441c99275SPeter Avalos         if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */
205*ed775ee7SAntonio Huete Jimenez             ND_PRINT("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ",
20641c99275SPeter Avalos                          addr_len,
20741c99275SPeter Avalos                          dlci,
208*ed775ee7SAntonio Huete Jimenez                          bittok2str(fr_header_flag_values, "none", flags),
20941c99275SPeter Avalos                          tok2str(nlpid_values,"unknown", nlpid),
21041c99275SPeter Avalos                          nlpid,
211*ed775ee7SAntonio Huete Jimenez                          length);
21241c99275SPeter Avalos         else /* must be an ethertype */
213*ed775ee7SAntonio Huete Jimenez             ND_PRINT("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ",
21441c99275SPeter Avalos                          addr_len,
21541c99275SPeter Avalos                          dlci,
216*ed775ee7SAntonio Huete Jimenez                          bittok2str(fr_header_flag_values, "none", flags),
21741c99275SPeter Avalos                          tok2str(ethertype_values, "unknown", nlpid),
21841c99275SPeter Avalos                          nlpid,
219*ed775ee7SAntonio Huete Jimenez                          length);
22041c99275SPeter Avalos     }
22141c99275SPeter Avalos }
22241c99275SPeter Avalos 
223*ed775ee7SAntonio Huete Jimenez /* Frame Relay */
224*ed775ee7SAntonio Huete Jimenez void
fr_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)225411677aeSAaron LI fr_if_print(netdissect_options *ndo,
226*ed775ee7SAntonio Huete Jimenez             const struct pcap_pkthdr *h, const u_char *p)
22741c99275SPeter Avalos {
228*ed775ee7SAntonio Huete Jimenez 	u_int length = h->len;
229*ed775ee7SAntonio Huete Jimenez 	u_int caplen = h->caplen;
23041c99275SPeter Avalos 
231*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "fr";
232*ed775ee7SAntonio Huete Jimenez 	if (caplen < 4) {	/* minimum frame header length */
233*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
234*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += caplen;
235*ed775ee7SAntonio Huete Jimenez 		return;
236*ed775ee7SAntonio Huete Jimenez 	}
23741c99275SPeter Avalos 
238*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += fr_print(ndo, p, length);
23941c99275SPeter Avalos }
24041c99275SPeter Avalos 
24141c99275SPeter Avalos u_int
fr_print(netdissect_options * ndo,const u_char * p,u_int length)242411677aeSAaron LI fr_print(netdissect_options *ndo,
243*ed775ee7SAntonio Huete Jimenez          const u_char *p, u_int length)
24441c99275SPeter Avalos {
245411677aeSAaron LI 	int ret;
246411677aeSAaron LI 	uint16_t extracted_ethertype;
24741c99275SPeter Avalos 	u_int dlci;
24841c99275SPeter Avalos 	u_int addr_len;
249411677aeSAaron LI 	uint16_t nlpid;
25041c99275SPeter Avalos 	u_int hdr_len;
251*ed775ee7SAntonio Huete Jimenez 	uint32_t flags;
25241c99275SPeter Avalos 
253*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "fr";
254*ed775ee7SAntonio Huete Jimenez 	ret = parse_q922_header(ndo, p, &dlci, &addr_len, &flags, length);
255411677aeSAaron LI 	if (ret == -1)
256411677aeSAaron LI 		goto trunc;
257411677aeSAaron LI 	if (ret == 0) {
258*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Q.922, invalid address");
25941c99275SPeter Avalos 		return 0;
26041c99275SPeter Avalos 	}
26141c99275SPeter Avalos 
262*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_1(p + addr_len);
263411677aeSAaron LI 	if (length < addr_len + 1)
264411677aeSAaron LI 		goto trunc;
26541c99275SPeter Avalos 
266*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(p + addr_len) != LLC_UI && dlci != 0) {
267411677aeSAaron LI                 /*
268411677aeSAaron LI                  * Let's figure out if we have Cisco-style encapsulation,
269411677aeSAaron LI                  * with an Ethernet type (Cisco HDLC type?) following the
270411677aeSAaron LI                  * address.
271411677aeSAaron LI                  */
272*ed775ee7SAntonio Huete Jimenez 		if (!ND_TTEST_2(p + addr_len) || length < addr_len + 2) {
273411677aeSAaron LI                         /* no Ethertype */
274*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("UI %02x! ", GET_U_1(p + addr_len));
275411677aeSAaron LI                 } else {
276*ed775ee7SAntonio Huete Jimenez                         extracted_ethertype = GET_BE_U_2(p + addr_len);
27741c99275SPeter Avalos 
278411677aeSAaron LI                         if (ndo->ndo_eflag)
279411677aeSAaron LI                                 fr_hdr_print(ndo, length, addr_len, dlci,
280411677aeSAaron LI                                     flags, extracted_ethertype);
28141c99275SPeter Avalos 
282411677aeSAaron LI                         if (ethertype_print(ndo, extracted_ethertype,
28341c99275SPeter Avalos                                             p+addr_len+ETHERTYPE_LEN,
28441c99275SPeter Avalos                                             length-addr_len-ETHERTYPE_LEN,
285*ed775ee7SAntonio Huete Jimenez                                             ND_BYTES_AVAILABLE_AFTER(p)-addr_len-ETHERTYPE_LEN,
286411677aeSAaron LI                                             NULL, NULL) == 0)
28741c99275SPeter Avalos                                 /* ether_type not known, probably it wasn't one */
288*ed775ee7SAntonio Huete Jimenez                                 ND_PRINT("UI %02x! ", GET_U_1(p + addr_len));
28941c99275SPeter Avalos                         else
290411677aeSAaron LI                                 return addr_len + 2;
291411677aeSAaron LI                 }
29241c99275SPeter Avalos         }
29341c99275SPeter Avalos 
294*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_1(p + addr_len + 1);
295411677aeSAaron LI 	if (length < addr_len + 2)
296411677aeSAaron LI 		goto trunc;
29741c99275SPeter Avalos 
298*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(p + addr_len + 1) == 0) {
299411677aeSAaron LI 		/*
300411677aeSAaron LI 		 * Assume a pad byte after the control (UI) byte.
301411677aeSAaron LI 		 * A pad byte should only be used with 3-byte Q.922.
302411677aeSAaron LI 		 */
303411677aeSAaron LI 		if (addr_len != 3)
304*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Pad! ");
305411677aeSAaron LI 		hdr_len = addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */;
306411677aeSAaron LI 	} else {
307411677aeSAaron LI 		/*
308411677aeSAaron LI 		 * Not a pad byte.
309411677aeSAaron LI 		 * A pad byte should be used with 3-byte Q.922.
310411677aeSAaron LI 		 */
311411677aeSAaron LI 		if (addr_len == 3)
312*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("No pad! ");
313411677aeSAaron LI 		hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */;
314411677aeSAaron LI 	}
315411677aeSAaron LI 
316*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_1(p + hdr_len - 1);
317411677aeSAaron LI 	if (length < hdr_len)
318411677aeSAaron LI 		goto trunc;
319*ed775ee7SAntonio Huete Jimenez 	nlpid = GET_U_1(p + hdr_len - 1);
32041c99275SPeter Avalos 
321411677aeSAaron LI 	if (ndo->ndo_eflag)
322411677aeSAaron LI 		fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid);
32341c99275SPeter Avalos 	p += hdr_len;
32441c99275SPeter Avalos 	length -= hdr_len;
32541c99275SPeter Avalos 
32641c99275SPeter Avalos 	switch (nlpid) {
32741c99275SPeter Avalos 	case NLPID_IP:
328411677aeSAaron LI 	        ip_print(ndo, p, length);
32941c99275SPeter Avalos 		break;
33041c99275SPeter Avalos 
33141c99275SPeter Avalos 	case NLPID_IP6:
332411677aeSAaron LI 		ip6_print(ndo, p, length);
33341c99275SPeter Avalos 		break;
334411677aeSAaron LI 
33541c99275SPeter Avalos 	case NLPID_CLNP:
33641c99275SPeter Avalos 	case NLPID_ESIS:
33741c99275SPeter Avalos 	case NLPID_ISIS:
338411677aeSAaron LI 		isoclns_print(ndo, p - 1, length + 1); /* OSI printers need the NLPID field */
33941c99275SPeter Avalos 		break;
34041c99275SPeter Avalos 
34141c99275SPeter Avalos 	case NLPID_SNAP:
342*ed775ee7SAntonio Huete Jimenez 		if (snap_print(ndo, p, length, ND_BYTES_AVAILABLE_AFTER(p), NULL, NULL, 0) == 0) {
34341c99275SPeter Avalos 			/* ether_type not known, print raw packet */
344411677aeSAaron LI                         if (!ndo->ndo_eflag)
345411677aeSAaron LI                             fr_hdr_print(ndo, length + hdr_len, hdr_len,
34641c99275SPeter Avalos                                          dlci, flags, nlpid);
347411677aeSAaron LI 			if (!ndo->ndo_suppress_default_print)
348411677aeSAaron LI 				ND_DEFAULTPRINT(p - hdr_len, length + hdr_len);
34941c99275SPeter Avalos 		}
35041c99275SPeter Avalos 		break;
35141c99275SPeter Avalos 
35241c99275SPeter Avalos         case NLPID_Q933:
353411677aeSAaron LI 		q933_print(ndo, p, length);
35441c99275SPeter Avalos 		break;
35541c99275SPeter Avalos 
35641c99275SPeter Avalos         case NLPID_MFR:
357411677aeSAaron LI                 frf15_print(ndo, p, length);
35841c99275SPeter Avalos                 break;
35941c99275SPeter Avalos 
36041c99275SPeter Avalos         case NLPID_PPP:
361411677aeSAaron LI                 ppp_print(ndo, p, length);
36241c99275SPeter Avalos                 break;
36341c99275SPeter Avalos 
36441c99275SPeter Avalos 	default:
365411677aeSAaron LI 		if (!ndo->ndo_eflag)
366411677aeSAaron LI                     fr_hdr_print(ndo, length + hdr_len, addr_len,
36741c99275SPeter Avalos 				     dlci, flags, nlpid);
368411677aeSAaron LI 		if (!ndo->ndo_xflag)
369411677aeSAaron LI 			ND_DEFAULTPRINT(p, length);
37041c99275SPeter Avalos 	}
37141c99275SPeter Avalos 
37241c99275SPeter Avalos 	return hdr_len;
37341c99275SPeter Avalos 
37441c99275SPeter Avalos trunc:
375*ed775ee7SAntonio Huete Jimenez         nd_print_trunc(ndo);
37641c99275SPeter Avalos         return 0;
37741c99275SPeter Avalos 
37841c99275SPeter Avalos }
37941c99275SPeter Avalos 
380*ed775ee7SAntonio Huete Jimenez /* Multi Link Frame Relay (FRF.16) */
381*ed775ee7SAntonio Huete Jimenez void
mfr_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)382411677aeSAaron LI mfr_if_print(netdissect_options *ndo,
383*ed775ee7SAntonio Huete Jimenez              const struct pcap_pkthdr *h, const u_char *p)
38441c99275SPeter Avalos {
385*ed775ee7SAntonio Huete Jimenez 	u_int length = h->len;
386*ed775ee7SAntonio Huete Jimenez 	u_int caplen = h->caplen;
38741c99275SPeter Avalos 
388*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "mfr";
389*ed775ee7SAntonio Huete Jimenez 	if (caplen < 2) {	/* minimum frame header length */
390*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
391*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += caplen;
392*ed775ee7SAntonio Huete Jimenez 		return;
393*ed775ee7SAntonio Huete Jimenez 	}
39441c99275SPeter Avalos 
395*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += mfr_print(ndo, p, length);
39641c99275SPeter Avalos }
39741c99275SPeter Avalos 
39841c99275SPeter Avalos 
39941c99275SPeter Avalos #define MFR_CTRL_MSG_ADD_LINK        1
40041c99275SPeter Avalos #define MFR_CTRL_MSG_ADD_LINK_ACK    2
40141c99275SPeter Avalos #define MFR_CTRL_MSG_ADD_LINK_REJ    3
40241c99275SPeter Avalos #define MFR_CTRL_MSG_HELLO           4
40341c99275SPeter Avalos #define MFR_CTRL_MSG_HELLO_ACK       5
40441c99275SPeter Avalos #define MFR_CTRL_MSG_REMOVE_LINK     6
40541c99275SPeter Avalos #define MFR_CTRL_MSG_REMOVE_LINK_ACK 7
40641c99275SPeter Avalos 
407411677aeSAaron LI static const struct tok mfr_ctrl_msg_values[] = {
40841c99275SPeter Avalos     { MFR_CTRL_MSG_ADD_LINK, "Add Link" },
40941c99275SPeter Avalos     { MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" },
41041c99275SPeter Avalos     { MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" },
41141c99275SPeter Avalos     { MFR_CTRL_MSG_HELLO, "Hello" },
41241c99275SPeter Avalos     { MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" },
41341c99275SPeter Avalos     { MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" },
41441c99275SPeter Avalos     { MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" },
41541c99275SPeter Avalos     { 0, NULL }
41641c99275SPeter Avalos };
41741c99275SPeter Avalos 
41841c99275SPeter Avalos #define MFR_CTRL_IE_BUNDLE_ID  1
41941c99275SPeter Avalos #define MFR_CTRL_IE_LINK_ID    2
42041c99275SPeter Avalos #define MFR_CTRL_IE_MAGIC_NUM  3
42141c99275SPeter Avalos #define MFR_CTRL_IE_TIMESTAMP  5
42241c99275SPeter Avalos #define MFR_CTRL_IE_VENDOR_EXT 6
42341c99275SPeter Avalos #define MFR_CTRL_IE_CAUSE      7
42441c99275SPeter Avalos 
425411677aeSAaron LI static const struct tok mfr_ctrl_ie_values[] = {
42641c99275SPeter Avalos     { MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"},
42741c99275SPeter Avalos     { MFR_CTRL_IE_LINK_ID, "Link ID"},
42841c99275SPeter Avalos     { MFR_CTRL_IE_MAGIC_NUM, "Magic Number"},
42941c99275SPeter Avalos     { MFR_CTRL_IE_TIMESTAMP, "Timestamp"},
43041c99275SPeter Avalos     { MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"},
43141c99275SPeter Avalos     { MFR_CTRL_IE_CAUSE, "Cause"},
43241c99275SPeter Avalos     { 0, NULL }
43341c99275SPeter Avalos };
43441c99275SPeter Avalos 
43541c99275SPeter Avalos #define MFR_ID_STRING_MAXLEN 50
43641c99275SPeter Avalos 
43741c99275SPeter Avalos struct ie_tlv_header_t {
438411677aeSAaron LI     uint8_t ie_type;
439411677aeSAaron LI     uint8_t ie_len;
44041c99275SPeter Avalos };
44141c99275SPeter Avalos 
44241c99275SPeter Avalos u_int
mfr_print(netdissect_options * ndo,const u_char * p,u_int length)443411677aeSAaron LI mfr_print(netdissect_options *ndo,
444*ed775ee7SAntonio Huete Jimenez           const u_char *p, u_int length)
44541c99275SPeter Avalos {
44641c99275SPeter Avalos     u_int tlen,idx,hdr_len = 0;
447411677aeSAaron LI     uint16_t sequence_num;
448411677aeSAaron LI     uint8_t ie_type,ie_len;
449411677aeSAaron LI     const uint8_t *tptr;
45041c99275SPeter Avalos 
45141c99275SPeter Avalos 
45241c99275SPeter Avalos /*
45341c99275SPeter Avalos  * FRF.16 Link Integrity Control Frame
45441c99275SPeter Avalos  *
45541c99275SPeter Avalos  *      7    6    5    4    3    2    1    0
45641c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
45741c99275SPeter Avalos  *    | B  | E  | C=1| 0    0    0    0  | EA |
45841c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
45941c99275SPeter Avalos  *    | 0    0    0    0    0    0    0    0  |
46041c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
46141c99275SPeter Avalos  *    |              message type             |
46241c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
46341c99275SPeter Avalos  */
46441c99275SPeter Avalos 
465*ed775ee7SAntonio Huete Jimenez     ndo->ndo_protocol = "mfr";
466*ed775ee7SAntonio Huete Jimenez 
467*ed775ee7SAntonio Huete Jimenez     if (length < 4) {	/* minimum frame header length */
468*ed775ee7SAntonio Huete Jimenez         ND_PRINT("[length %u < 4]", length);
469*ed775ee7SAntonio Huete Jimenez         nd_print_invalid(ndo);
470411677aeSAaron LI         return length;
471411677aeSAaron LI     }
472*ed775ee7SAntonio Huete Jimenez     ND_TCHECK_4(p);
47341c99275SPeter Avalos 
474*ed775ee7SAntonio Huete Jimenez     if ((GET_U_1(p) & MFR_BEC_MASK) == MFR_CTRL_FRAME && GET_U_1(p + 1) == 0) {
475*ed775ee7SAntonio Huete Jimenez         ND_PRINT("FRF.16 Control, Flags [%s], %s, length %u",
476*ed775ee7SAntonio Huete Jimenez                bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)),
477*ed775ee7SAntonio Huete Jimenez                tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",GET_U_1(p + 2)),
478*ed775ee7SAntonio Huete Jimenez                length);
47941c99275SPeter Avalos         tptr = p + 3;
48041c99275SPeter Avalos         tlen = length -3;
48141c99275SPeter Avalos         hdr_len = 3;
48241c99275SPeter Avalos 
483411677aeSAaron LI         if (!ndo->ndo_vflag)
48441c99275SPeter Avalos             return hdr_len;
48541c99275SPeter Avalos 
48641c99275SPeter Avalos         while (tlen>sizeof(struct ie_tlv_header_t)) {
487*ed775ee7SAntonio Huete Jimenez             ND_TCHECK_LEN(tptr, sizeof(struct ie_tlv_header_t));
488*ed775ee7SAntonio Huete Jimenez             ie_type=GET_U_1(tptr);
489*ed775ee7SAntonio Huete Jimenez             ie_len=GET_U_1(tptr + 1);
49041c99275SPeter Avalos 
491*ed775ee7SAntonio Huete Jimenez             ND_PRINT("\n\tIE %s (%u), length %u: ",
49241c99275SPeter Avalos                    tok2str(mfr_ctrl_ie_values,"Unknown",ie_type),
49341c99275SPeter Avalos                    ie_type,
494*ed775ee7SAntonio Huete Jimenez                    ie_len);
49541c99275SPeter Avalos 
49641c99275SPeter Avalos             /* infinite loop check */
49741c99275SPeter Avalos             if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t))
49841c99275SPeter Avalos                 return hdr_len;
49941c99275SPeter Avalos 
500*ed775ee7SAntonio Huete Jimenez             ND_TCHECK_LEN(tptr, ie_len);
50141c99275SPeter Avalos             tptr+=sizeof(struct ie_tlv_header_t);
50241c99275SPeter Avalos             /* tlv len includes header */
50341c99275SPeter Avalos             ie_len-=sizeof(struct ie_tlv_header_t);
50441c99275SPeter Avalos             tlen-=sizeof(struct ie_tlv_header_t);
50541c99275SPeter Avalos 
50641c99275SPeter Avalos             switch (ie_type) {
50741c99275SPeter Avalos 
50841c99275SPeter Avalos             case MFR_CTRL_IE_MAGIC_NUM:
509411677aeSAaron LI                 /* FRF.16.1 Section 3.4.3 Magic Number Information Element */
510411677aeSAaron LI                 if (ie_len != 4) {
511*ed775ee7SAntonio Huete Jimenez                     ND_PRINT("[IE data length %d != 4]", ie_len);
512*ed775ee7SAntonio Huete Jimenez                     nd_print_invalid(ndo);
513411677aeSAaron LI                     break;
514411677aeSAaron LI                 }
515*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("0x%08x", GET_BE_U_4(tptr));
51641c99275SPeter Avalos                 break;
51741c99275SPeter Avalos 
51841c99275SPeter Avalos             case MFR_CTRL_IE_BUNDLE_ID: /* same message format */
51941c99275SPeter Avalos             case MFR_CTRL_IE_LINK_ID:
52041c99275SPeter Avalos                 for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) {
521*ed775ee7SAntonio Huete Jimenez                     if (GET_U_1(tptr + idx) != 0) /* don't print null termination */
522*ed775ee7SAntonio Huete Jimenez                         fn_print_char(ndo, GET_U_1(tptr + idx));
52341c99275SPeter Avalos                     else
52441c99275SPeter Avalos                         break;
52541c99275SPeter Avalos                 }
52641c99275SPeter Avalos                 break;
52741c99275SPeter Avalos 
52841c99275SPeter Avalos             case MFR_CTRL_IE_TIMESTAMP:
52941c99275SPeter Avalos                 if (ie_len == sizeof(struct timeval)) {
530411677aeSAaron LI                     ts_print(ndo, (const struct timeval *)tptr);
53141c99275SPeter Avalos                     break;
53241c99275SPeter Avalos                 }
53341c99275SPeter Avalos                 /* fall through and hexdump if no unix timestamp */
534*ed775ee7SAntonio Huete Jimenez                 ND_FALL_THROUGH;
53541c99275SPeter Avalos 
53641c99275SPeter Avalos                 /*
53741c99275SPeter Avalos                  * FIXME those are the defined IEs that lack a decoder
53841c99275SPeter Avalos                  * you are welcome to contribute code ;-)
53941c99275SPeter Avalos                  */
54041c99275SPeter Avalos 
54141c99275SPeter Avalos             case MFR_CTRL_IE_VENDOR_EXT:
54241c99275SPeter Avalos             case MFR_CTRL_IE_CAUSE:
54341c99275SPeter Avalos 
54441c99275SPeter Avalos             default:
545411677aeSAaron LI                 if (ndo->ndo_vflag <= 1)
546411677aeSAaron LI                     print_unknown_data(ndo, tptr, "\n\t  ", ie_len);
54741c99275SPeter Avalos                 break;
54841c99275SPeter Avalos             }
54941c99275SPeter Avalos 
55041c99275SPeter Avalos             /* do we want to see a hexdump of the IE ? */
551411677aeSAaron LI             if (ndo->ndo_vflag > 1 )
552411677aeSAaron LI                 print_unknown_data(ndo, tptr, "\n\t  ", ie_len);
55341c99275SPeter Avalos 
55441c99275SPeter Avalos             tlen-=ie_len;
55541c99275SPeter Avalos             tptr+=ie_len;
55641c99275SPeter Avalos         }
55741c99275SPeter Avalos         return hdr_len;
55841c99275SPeter Avalos     }
55941c99275SPeter Avalos /*
56041c99275SPeter Avalos  * FRF.16 Fragmentation Frame
56141c99275SPeter Avalos  *
56241c99275SPeter Avalos  *      7    6    5    4    3    2    1    0
56341c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
56441c99275SPeter Avalos  *    | B  | E  | C=0|seq. (high 4 bits) | EA |
56541c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
56641c99275SPeter Avalos  *    |        sequence  (low 8 bits)         |
56741c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
56841c99275SPeter Avalos  *    |        DLCI (6 bits)        | CR | EA |
56941c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
57041c99275SPeter Avalos  *    |   DLCI (4 bits)   |FECN|BECN| DE | EA |
57141c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
57241c99275SPeter Avalos  */
57341c99275SPeter Avalos 
574*ed775ee7SAntonio Huete Jimenez     sequence_num = (GET_U_1(p)&0x1e)<<7 | GET_U_1(p + 1);
57541c99275SPeter Avalos     /* whole packet or first fragment ? */
576*ed775ee7SAntonio Huete Jimenez     if ((GET_U_1(p) & MFR_BEC_MASK) == MFR_FRAG_FRAME ||
577*ed775ee7SAntonio Huete Jimenez         (GET_U_1(p) & MFR_BEC_MASK) == MFR_B_BIT) {
578*ed775ee7SAntonio Huete Jimenez         ND_PRINT("FRF.16 Frag, seq %u, Flags [%s], ",
57941c99275SPeter Avalos                sequence_num,
580*ed775ee7SAntonio Huete Jimenez                bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)));
58141c99275SPeter Avalos         hdr_len = 2;
582411677aeSAaron LI         fr_print(ndo, p+hdr_len,length-hdr_len);
58341c99275SPeter Avalos         return hdr_len;
58441c99275SPeter Avalos     }
58541c99275SPeter Avalos 
58641c99275SPeter Avalos     /* must be a middle or the last fragment */
587*ed775ee7SAntonio Huete Jimenez     ND_PRINT("FRF.16 Frag, seq %u, Flags [%s]",
58841c99275SPeter Avalos            sequence_num,
589*ed775ee7SAntonio Huete Jimenez            bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)));
590411677aeSAaron LI     print_unknown_data(ndo, p, "\n\t", length);
59141c99275SPeter Avalos 
59241c99275SPeter Avalos     return hdr_len;
59341c99275SPeter Avalos 
59441c99275SPeter Avalos trunc:
595*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
59641c99275SPeter Avalos     return length;
59741c99275SPeter Avalos }
59841c99275SPeter Avalos 
59941c99275SPeter Avalos /* an NLPID of 0xb1 indicates a 2-byte
60041c99275SPeter Avalos  * FRF.15 header
60141c99275SPeter Avalos  *
60241c99275SPeter Avalos  *      7    6    5    4    3    2    1    0
60341c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
60441c99275SPeter Avalos  *    ~              Q.922 header             ~
60541c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
60641c99275SPeter Avalos  *    |             NLPID (8 bits)            | NLPID=0xb1
60741c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
60841c99275SPeter Avalos  *    | B  | E  | C  |seq. (high 4 bits) | R  |
60941c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
61041c99275SPeter Avalos  *    |        sequence  (low 8 bits)         |
61141c99275SPeter Avalos  *    +----+----+----+----+----+----+----+----+
61241c99275SPeter Avalos  */
61341c99275SPeter Avalos 
61441c99275SPeter Avalos #define FR_FRF15_FRAGTYPE 0x01
61541c99275SPeter Avalos 
61641c99275SPeter Avalos static void
frf15_print(netdissect_options * ndo,const u_char * p,u_int length)617411677aeSAaron LI frf15_print(netdissect_options *ndo,
618411677aeSAaron LI             const u_char *p, u_int length)
619411677aeSAaron LI {
620411677aeSAaron LI     uint16_t sequence_num, flags;
62141c99275SPeter Avalos 
622411677aeSAaron LI     if (length < 2)
623411677aeSAaron LI         goto trunc;
62441c99275SPeter Avalos 
625*ed775ee7SAntonio Huete Jimenez     flags = GET_U_1(p)&MFR_BEC_MASK;
626*ed775ee7SAntonio Huete Jimenez     sequence_num = (GET_U_1(p)&0x1e)<<7 | GET_U_1(p + 1);
62741c99275SPeter Avalos 
628*ed775ee7SAntonio Huete Jimenez     ND_PRINT("FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u",
62941c99275SPeter Avalos            sequence_num,
63041c99275SPeter Avalos            bittok2str(frf_flag_values,"none",flags),
631*ed775ee7SAntonio Huete Jimenez            GET_U_1(p)&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End",
632*ed775ee7SAntonio Huete Jimenez            length);
63341c99275SPeter Avalos 
63441c99275SPeter Avalos /* TODO:
63541c99275SPeter Avalos  * depending on all permutations of the B, E and C bit
63641c99275SPeter Avalos  * dig as deep as we can - e.g. on the first (B) fragment
63741c99275SPeter Avalos  * there is enough payload to print the IP header
63841c99275SPeter Avalos  * on non (B) fragments it depends if the fragmentation
639*ed775ee7SAntonio Huete Jimenez  * model is end-to-end or interface based whether we want to print
64041c99275SPeter Avalos  * another Q.922 header
64141c99275SPeter Avalos  */
642411677aeSAaron LI     return;
64341c99275SPeter Avalos 
644411677aeSAaron LI trunc:
645*ed775ee7SAntonio Huete Jimenez     nd_print_trunc(ndo);
64641c99275SPeter Avalos }
64741c99275SPeter Avalos 
64841c99275SPeter Avalos /*
64941c99275SPeter Avalos  * Q.933 decoding portion for framerelay specific.
65041c99275SPeter Avalos  */
65141c99275SPeter Avalos 
65241c99275SPeter Avalos /* Q.933 packet format
65341c99275SPeter Avalos                       Format of Other Protocols
65441c99275SPeter Avalos                           using Q.933 NLPID
65541c99275SPeter Avalos                   +-------------------------------+
65641c99275SPeter Avalos                   |        Q.922 Address          |
65741c99275SPeter Avalos                   +---------------+---------------+
65841c99275SPeter Avalos                   |Control  0x03  | NLPID   0x08  |
65941c99275SPeter Avalos                   +---------------+---------------+
66041c99275SPeter Avalos                   |          L2 Protocol ID       |
66141c99275SPeter Avalos                   | octet 1       |  octet 2      |
66241c99275SPeter Avalos                   +-------------------------------+
66341c99275SPeter Avalos                   |          L3 Protocol ID       |
66441c99275SPeter Avalos                   | octet 2       |  octet 2      |
66541c99275SPeter Avalos                   +-------------------------------+
66641c99275SPeter Avalos                   |         Protocol Data         |
66741c99275SPeter Avalos                   +-------------------------------+
66841c99275SPeter Avalos                   | FCS                           |
66941c99275SPeter Avalos                   +-------------------------------+
67041c99275SPeter Avalos  */
67141c99275SPeter Avalos 
67241c99275SPeter Avalos /* L2 (Octet 1)- Call Reference Usually is 0x0 */
67341c99275SPeter Avalos 
67441c99275SPeter Avalos /*
67541c99275SPeter Avalos  * L2 (Octet 2)- Message Types definition 1 byte long.
67641c99275SPeter Avalos  */
67741c99275SPeter Avalos /* Call Establish */
67841c99275SPeter Avalos #define MSG_TYPE_ESC_TO_NATIONAL  0x00
67941c99275SPeter Avalos #define MSG_TYPE_ALERT            0x01
68041c99275SPeter Avalos #define MSG_TYPE_CALL_PROCEEDING  0x02
68141c99275SPeter Avalos #define MSG_TYPE_CONNECT          0x07
68241c99275SPeter Avalos #define MSG_TYPE_CONNECT_ACK      0x0F
68341c99275SPeter Avalos #define MSG_TYPE_PROGRESS         0x03
68441c99275SPeter Avalos #define MSG_TYPE_SETUP            0x05
68541c99275SPeter Avalos /* Call Clear */
68641c99275SPeter Avalos #define MSG_TYPE_DISCONNECT       0x45
68741c99275SPeter Avalos #define MSG_TYPE_RELEASE          0x4D
68841c99275SPeter Avalos #define MSG_TYPE_RELEASE_COMPLETE 0x5A
68941c99275SPeter Avalos #define MSG_TYPE_RESTART          0x46
69041c99275SPeter Avalos #define MSG_TYPE_RESTART_ACK      0x4E
69141c99275SPeter Avalos /* Status */
69241c99275SPeter Avalos #define MSG_TYPE_STATUS           0x7D
69341c99275SPeter Avalos #define MSG_TYPE_STATUS_ENQ       0x75
69441c99275SPeter Avalos 
695411677aeSAaron LI static const struct tok fr_q933_msg_values[] = {
69641c99275SPeter Avalos     { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" },
69741c99275SPeter Avalos     { MSG_TYPE_ALERT, "Alert" },
69841c99275SPeter Avalos     { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" },
69941c99275SPeter Avalos     { MSG_TYPE_CONNECT, "Connect" },
70041c99275SPeter Avalos     { MSG_TYPE_CONNECT_ACK, "Connect ACK" },
70141c99275SPeter Avalos     { MSG_TYPE_PROGRESS, "Progress" },
70241c99275SPeter Avalos     { MSG_TYPE_SETUP, "Setup" },
70341c99275SPeter Avalos     { MSG_TYPE_DISCONNECT, "Disconnect" },
70441c99275SPeter Avalos     { MSG_TYPE_RELEASE, "Release" },
70541c99275SPeter Avalos     { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" },
70641c99275SPeter Avalos     { MSG_TYPE_RESTART, "Restart" },
70741c99275SPeter Avalos     { MSG_TYPE_RESTART_ACK, "Restart ACK" },
70841c99275SPeter Avalos     { MSG_TYPE_STATUS, "Status Reply" },
70941c99275SPeter Avalos     { MSG_TYPE_STATUS_ENQ, "Status Enquiry" },
71041c99275SPeter Avalos     { 0, NULL }
71141c99275SPeter Avalos };
71241c99275SPeter Avalos 
713411677aeSAaron LI #define IE_IS_SINGLE_OCTET(iecode)	((iecode) & 0x80)
714411677aeSAaron LI #define IE_IS_SHIFT(iecode)		(((iecode) & 0xF0) == 0x90)
715411677aeSAaron LI #define IE_SHIFT_IS_NON_LOCKING(iecode)	((iecode) & 0x08)
716411677aeSAaron LI #define IE_SHIFT_IS_LOCKING(iecode)	(!(IE_SHIFT_IS_NON_LOCKING(iecode)))
717411677aeSAaron LI #define IE_SHIFT_CODESET(iecode)	((iecode) & 0x07)
71841c99275SPeter Avalos 
71941c99275SPeter Avalos #define FR_LMI_ANSI_REPORT_TYPE_IE	0x01
72041c99275SPeter Avalos #define FR_LMI_ANSI_LINK_VERIFY_IE_91	0x19 /* details? */
72141c99275SPeter Avalos #define FR_LMI_ANSI_LINK_VERIFY_IE	0x03
72241c99275SPeter Avalos #define FR_LMI_ANSI_PVC_STATUS_IE	0x07
72341c99275SPeter Avalos 
72441c99275SPeter Avalos #define FR_LMI_CCITT_REPORT_TYPE_IE	0x51
72541c99275SPeter Avalos #define FR_LMI_CCITT_LINK_VERIFY_IE	0x53
72641c99275SPeter Avalos #define FR_LMI_CCITT_PVC_STATUS_IE	0x57
72741c99275SPeter Avalos 
728411677aeSAaron LI static const struct tok fr_q933_ie_values_codeset_0_5[] = {
72941c99275SPeter Avalos     { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" },
73041c99275SPeter Avalos     { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" },
73141c99275SPeter Avalos     { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" },
73241c99275SPeter Avalos     { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" },
73341c99275SPeter Avalos     { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" },
73441c99275SPeter Avalos     { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" },
73541c99275SPeter Avalos     { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" },
73641c99275SPeter Avalos     { 0, NULL }
73741c99275SPeter Avalos };
73841c99275SPeter Avalos 
73941c99275SPeter Avalos #define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0
74041c99275SPeter Avalos #define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1
74141c99275SPeter Avalos #define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC   2
74241c99275SPeter Avalos 
743411677aeSAaron LI static const struct tok fr_lmi_report_type_ie_values[] = {
74441c99275SPeter Avalos     { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" },
74541c99275SPeter Avalos     { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" },
74641c99275SPeter Avalos     { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" },
74741c99275SPeter Avalos     { 0, NULL }
74841c99275SPeter Avalos };
74941c99275SPeter Avalos 
750411677aeSAaron LI /* array of 16 codesets - currently we only support codepage 0 and 5 */
751411677aeSAaron LI static const struct tok *fr_q933_ie_codesets[] = {
752411677aeSAaron LI     fr_q933_ie_values_codeset_0_5,
75341c99275SPeter Avalos     NULL,
75441c99275SPeter Avalos     NULL,
75541c99275SPeter Avalos     NULL,
756411677aeSAaron LI     NULL,
757411677aeSAaron LI     fr_q933_ie_values_codeset_0_5,
75841c99275SPeter Avalos     NULL,
75941c99275SPeter Avalos     NULL,
76041c99275SPeter Avalos     NULL,
76141c99275SPeter Avalos     NULL,
76241c99275SPeter Avalos     NULL,
76341c99275SPeter Avalos     NULL,
76441c99275SPeter Avalos     NULL,
76541c99275SPeter Avalos     NULL,
76641c99275SPeter Avalos     NULL,
76741c99275SPeter Avalos     NULL
76841c99275SPeter Avalos };
76941c99275SPeter Avalos 
770411677aeSAaron LI static int fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode,
771411677aeSAaron LI     u_int ielength, const u_char *p);
77241c99275SPeter Avalos 
773411677aeSAaron LI typedef int (*codeset_pr_func_t)(netdissect_options *, u_int iecode,
774411677aeSAaron LI     u_int ielength, const u_char *p);
77541c99275SPeter Avalos 
776411677aeSAaron LI /* array of 16 codesets - currently we only support codepage 0 and 5 */
777411677aeSAaron LI static const codeset_pr_func_t fr_q933_print_ie_codeset[] = {
778411677aeSAaron LI     fr_q933_print_ie_codeset_0_5,
77941c99275SPeter Avalos     NULL,
78041c99275SPeter Avalos     NULL,
78141c99275SPeter Avalos     NULL,
782411677aeSAaron LI     NULL,
783411677aeSAaron LI     fr_q933_print_ie_codeset_0_5,
78441c99275SPeter Avalos     NULL,
78541c99275SPeter Avalos     NULL,
78641c99275SPeter Avalos     NULL,
78741c99275SPeter Avalos     NULL,
78841c99275SPeter Avalos     NULL,
78941c99275SPeter Avalos     NULL,
79041c99275SPeter Avalos     NULL,
79141c99275SPeter Avalos     NULL,
79241c99275SPeter Avalos     NULL,
79341c99275SPeter Avalos     NULL
79441c99275SPeter Avalos };
79541c99275SPeter Avalos 
796411677aeSAaron LI /*
797411677aeSAaron LI  * ITU-T Q.933.
798411677aeSAaron LI  *
799411677aeSAaron LI  * p points to octet 2, the octet containing the length of the
800411677aeSAaron LI  * call reference value, so p[n] is octet n+2 ("octet X" is as
801411677aeSAaron LI  * used in Q.931/Q.933).
802411677aeSAaron LI  *
803411677aeSAaron LI  * XXX - actually used both for Q.931 and Q.933.
804411677aeSAaron LI  */
80541c99275SPeter Avalos void
q933_print(netdissect_options * ndo,const u_char * p,u_int length)806411677aeSAaron LI q933_print(netdissect_options *ndo,
807411677aeSAaron LI            const u_char *p, u_int length)
80841c99275SPeter Avalos {
809411677aeSAaron LI 	u_int olen;
810411677aeSAaron LI 	u_int call_ref_length, i;
811411677aeSAaron LI 	uint8_t call_ref[15];	/* maximum length - length field is 4 bits */
812411677aeSAaron LI 	u_int msgtype;
813411677aeSAaron LI 	u_int iecode;
814411677aeSAaron LI 	u_int ielength;
815411677aeSAaron LI 	u_int codeset = 0;
816411677aeSAaron LI 	u_int is_ansi = 0;
817411677aeSAaron LI 	u_int ie_is_known;
818411677aeSAaron LI 	u_int non_locking_shift;
819411677aeSAaron LI 	u_int unshift_codeset;
82041c99275SPeter Avalos 
821*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "q.933";
822*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s", ndo->ndo_eflag ? "" : "Q.933");
823411677aeSAaron LI 
824*ed775ee7SAntonio Huete Jimenez 	if (length == 0 || !ND_TTEST_1(p)) {
825411677aeSAaron LI 		if (!ndo->ndo_eflag)
826*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", ");
827*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("length %u", length);
828411677aeSAaron LI 		goto trunc;
82941c99275SPeter Avalos 	}
83041c99275SPeter Avalos 
831411677aeSAaron LI 	/*
832411677aeSAaron LI 	 * Get the length of the call reference value.
833411677aeSAaron LI 	 */
834411677aeSAaron LI 	olen = length; /* preserve the original length for display */
835*ed775ee7SAntonio Huete Jimenez 	call_ref_length = GET_U_1(p) & 0x0f;
836411677aeSAaron LI 	p++;
837411677aeSAaron LI 	length--;
83841c99275SPeter Avalos 
839411677aeSAaron LI 	/*
840411677aeSAaron LI 	 * Get the call reference value.
841411677aeSAaron LI 	 */
842411677aeSAaron LI 	for (i = 0; i < call_ref_length; i++) {
843*ed775ee7SAntonio Huete Jimenez 		if (length == 0 || !ND_TTEST_1(p)) {
844411677aeSAaron LI 			if (!ndo->ndo_eflag)
845*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
846*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("length %u", olen);
847411677aeSAaron LI 			goto trunc;
848411677aeSAaron LI 		}
849*ed775ee7SAntonio Huete Jimenez 		call_ref[i] = GET_U_1(p);
850411677aeSAaron LI 		p++;
851411677aeSAaron LI 		length--;
852411677aeSAaron LI 	}
853411677aeSAaron LI 
854411677aeSAaron LI 	/*
855411677aeSAaron LI 	 * Get the message type.
856411677aeSAaron LI 	 */
857*ed775ee7SAntonio Huete Jimenez 	if (length == 0 || !ND_TTEST_1(p)) {
858411677aeSAaron LI 		if (!ndo->ndo_eflag)
859*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", ");
860*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("length %u", olen);
861411677aeSAaron LI 		goto trunc;
862411677aeSAaron LI 	}
863*ed775ee7SAntonio Huete Jimenez 	msgtype = GET_U_1(p);
864411677aeSAaron LI 	p++;
865411677aeSAaron LI 	length--;
866411677aeSAaron LI 
867411677aeSAaron LI 	/*
868411677aeSAaron LI 	 * Peek ahead to see if we start with a shift.
869411677aeSAaron LI 	 */
870411677aeSAaron LI 	non_locking_shift = 0;
871411677aeSAaron LI 	unshift_codeset = codeset;
872411677aeSAaron LI 	if (length != 0) {
873*ed775ee7SAntonio Huete Jimenez 		if (!ND_TTEST_1(p)) {
874411677aeSAaron LI 			if (!ndo->ndo_eflag)
875*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
876*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("length %u", olen);
877411677aeSAaron LI 			goto trunc;
878411677aeSAaron LI 		}
879*ed775ee7SAntonio Huete Jimenez 		iecode = GET_U_1(p);
880411677aeSAaron LI 		if (IE_IS_SHIFT(iecode)) {
881411677aeSAaron LI 			/*
882411677aeSAaron LI 			 * It's a shift.  Skip over it.
883411677aeSAaron LI 			 */
884411677aeSAaron LI 			p++;
885411677aeSAaron LI 			length--;
886411677aeSAaron LI 
887411677aeSAaron LI 			/*
888411677aeSAaron LI 			 * Get the codeset.
889411677aeSAaron LI 			 */
890411677aeSAaron LI 			codeset = IE_SHIFT_CODESET(iecode);
891411677aeSAaron LI 
892411677aeSAaron LI 			/*
893411677aeSAaron LI 			 * If it's a locking shift to codeset 5,
894411677aeSAaron LI 			 * mark this as ANSI.  (XXX - 5 is actually
895411677aeSAaron LI 			 * for national variants in general, not
896411677aeSAaron LI 			 * the US variant in particular, but maybe
897411677aeSAaron LI 			 * this is more American exceptionalism. :-))
898411677aeSAaron LI 			 */
899411677aeSAaron LI 			if (IE_SHIFT_IS_LOCKING(iecode)) {
900411677aeSAaron LI 				/*
901411677aeSAaron LI 				 * It's a locking shift.
902411677aeSAaron LI 				 */
903411677aeSAaron LI 				if (codeset == 5) {
904411677aeSAaron LI 					/*
905411677aeSAaron LI 					 * It's a locking shift to
906411677aeSAaron LI 					 * codeset 5, so this is
907411677aeSAaron LI 					 * T1.617 Annex D.
908411677aeSAaron LI 					 */
90941c99275SPeter Avalos 					is_ansi = 1;
910ea7b4bf5SPeter Avalos 				}
911411677aeSAaron LI 			} else {
912411677aeSAaron LI 				/*
913411677aeSAaron LI 				 * It's a non-locking shift.
914411677aeSAaron LI 				 * Remember the current codeset, so we
915411677aeSAaron LI 				 * can revert to it after the next IE.
916411677aeSAaron LI 				 */
917411677aeSAaron LI 				non_locking_shift = 1;
918411677aeSAaron LI 				unshift_codeset = 0;
919411677aeSAaron LI 			}
920411677aeSAaron LI 		}
921411677aeSAaron LI 	}
92241c99275SPeter Avalos 
92341c99275SPeter Avalos 	/* printing out header part */
924411677aeSAaron LI 	if (!ndo->ndo_eflag)
925*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", ");
926*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset);
92741c99275SPeter Avalos 
928411677aeSAaron LI 	if (call_ref_length != 0) {
929*ed775ee7SAntonio Huete Jimenez 		if (call_ref_length > 1 || GET_U_1(p) != 0) {
930411677aeSAaron LI 			/*
931411677aeSAaron LI 			 * Not a dummy call reference.
932411677aeSAaron LI 			 */
933*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", Call Ref: 0x");
934411677aeSAaron LI 			for (i = 0; i < call_ref_length; i++)
935*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%02x", call_ref[i]);
936ea7b4bf5SPeter Avalos 		}
937411677aeSAaron LI 	}
938411677aeSAaron LI 	if (ndo->ndo_vflag) {
939*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", %s (0x%02x), length %u",
940ea7b4bf5SPeter Avalos 		   tok2str(fr_q933_msg_values,
941411677aeSAaron LI 			"unknown message", msgtype),
942411677aeSAaron LI 		   msgtype,
943*ed775ee7SAntonio Huete Jimenez 		   olen);
944ea7b4bf5SPeter Avalos 	} else {
945*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", %s",
946ea7b4bf5SPeter Avalos 		       tok2str(fr_q933_msg_values,
947*ed775ee7SAntonio Huete Jimenez 			       "unknown message 0x%02x", msgtype));
948ea7b4bf5SPeter Avalos 	}
94941c99275SPeter Avalos 
950411677aeSAaron LI 	/* Loop through the rest of the IEs */
951411677aeSAaron LI 	while (length != 0) {
952411677aeSAaron LI 		/*
953411677aeSAaron LI 		 * What's the state of any non-locking shifts?
954411677aeSAaron LI 		 */
955411677aeSAaron LI 		if (non_locking_shift == 1) {
956411677aeSAaron LI 			/*
957411677aeSAaron LI 			 * There's a non-locking shift in effect for
958411677aeSAaron LI 			 * this IE.  Count it, so we reset the codeset
959411677aeSAaron LI 			 * before the next IE.
960411677aeSAaron LI 			 */
961411677aeSAaron LI 			non_locking_shift = 2;
962411677aeSAaron LI 		} else if (non_locking_shift == 2) {
963411677aeSAaron LI 			/*
964411677aeSAaron LI 			 * Unshift.
965411677aeSAaron LI 			 */
966411677aeSAaron LI 			codeset = unshift_codeset;
967411677aeSAaron LI 			non_locking_shift = 0;
96841c99275SPeter Avalos 		}
96941c99275SPeter Avalos 
970411677aeSAaron LI 		/*
971411677aeSAaron LI 		 * Get the first octet of the IE.
972411677aeSAaron LI 		 */
973*ed775ee7SAntonio Huete Jimenez 		if (!ND_TTEST_1(p)) {
974411677aeSAaron LI 			if (!ndo->ndo_vflag) {
975*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", length %u", olen);
976411677aeSAaron LI 			}
977411677aeSAaron LI 			goto trunc;
978411677aeSAaron LI 		}
979*ed775ee7SAntonio Huete Jimenez 		iecode = GET_U_1(p);
980411677aeSAaron LI 		p++;
981411677aeSAaron LI 		length--;
982411677aeSAaron LI 
983411677aeSAaron LI 		/* Single-octet IE? */
984411677aeSAaron LI 		if (IE_IS_SINGLE_OCTET(iecode)) {
985411677aeSAaron LI 			/*
986411677aeSAaron LI 			 * Yes.  Is it a shift?
987411677aeSAaron LI 			 */
988411677aeSAaron LI 			if (IE_IS_SHIFT(iecode)) {
989411677aeSAaron LI 				/*
990411677aeSAaron LI 				 * Yes.  Is it locking?
991411677aeSAaron LI 				 */
992411677aeSAaron LI 				if (IE_SHIFT_IS_LOCKING(iecode)) {
993411677aeSAaron LI 					/*
994411677aeSAaron LI 					 * Yes.
995411677aeSAaron LI 					 */
996411677aeSAaron LI 					non_locking_shift = 0;
997ea7b4bf5SPeter Avalos 				} else {
998411677aeSAaron LI 					/*
999411677aeSAaron LI 					 * No.  Remember the current
1000411677aeSAaron LI 					 * codeset, so we can revert
1001411677aeSAaron LI 					 * to it after the next IE.
1002411677aeSAaron LI 					 */
1003411677aeSAaron LI 					non_locking_shift = 1;
1004411677aeSAaron LI 					unshift_codeset = codeset;
1005ea7b4bf5SPeter Avalos 				}
1006411677aeSAaron LI 
1007411677aeSAaron LI 				/*
1008411677aeSAaron LI 				 * Get the codeset.
1009411677aeSAaron LI 				 */
1010411677aeSAaron LI 				codeset = IE_SHIFT_CODESET(iecode);
101141c99275SPeter Avalos 			}
1012411677aeSAaron LI 		} else {
1013411677aeSAaron LI 			/*
1014411677aeSAaron LI 			 * No.  Get the IE length.
1015411677aeSAaron LI 			 */
1016*ed775ee7SAntonio Huete Jimenez 			if (length == 0 || !ND_TTEST_1(p)) {
1017411677aeSAaron LI 				if (!ndo->ndo_vflag) {
1018*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", length %u", olen);
1019411677aeSAaron LI 				}
1020411677aeSAaron LI 				goto trunc;
1021411677aeSAaron LI 			}
1022*ed775ee7SAntonio Huete Jimenez 			ielength = GET_U_1(p);
1023411677aeSAaron LI 			p++;
1024411677aeSAaron LI 			length--;
102541c99275SPeter Avalos 
102641c99275SPeter Avalos 			/* lets do the full IE parsing only in verbose mode
102741c99275SPeter Avalos 			 * however some IEs (DLCI Status, Link Verify)
1028411677aeSAaron LI 			 * are also interesting in non-verbose mode */
1029411677aeSAaron LI 			if (ndo->ndo_vflag) {
1030*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t%s IE (0x%02x), length %u: ",
1031ea7b4bf5SPeter Avalos 				    tok2str(fr_q933_ie_codesets[codeset],
1032411677aeSAaron LI 					"unknown", iecode),
1033411677aeSAaron LI 				    iecode,
1034*ed775ee7SAntonio Huete Jimenez 				    ielength);
1035ea7b4bf5SPeter Avalos 			}
103641c99275SPeter Avalos 
1037411677aeSAaron LI 			/* sanity checks */
1038411677aeSAaron LI 			if (iecode == 0 || ielength == 0) {
103941c99275SPeter Avalos 				return;
1040ea7b4bf5SPeter Avalos 			}
1041*ed775ee7SAntonio Huete Jimenez 			if (length < ielength || !ND_TTEST_LEN(p, ielength)) {
1042411677aeSAaron LI 				if (!ndo->ndo_vflag) {
1043*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", length %u", olen);
1044411677aeSAaron LI 				}
1045411677aeSAaron LI 				goto trunc;
1046411677aeSAaron LI 			}
104741c99275SPeter Avalos 
1048411677aeSAaron LI 			ie_is_known = 0;
1049ea7b4bf5SPeter Avalos 			if (fr_q933_print_ie_codeset[codeset] != NULL) {
1050411677aeSAaron LI 				ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, iecode, ielength, p);
1051ea7b4bf5SPeter Avalos 			}
105241c99275SPeter Avalos 
1053411677aeSAaron LI 			if (ie_is_known) {
1054411677aeSAaron LI 				/*
1055411677aeSAaron LI 				 * Known IE; do we want to see a hexdump
1056411677aeSAaron LI 				 * of it?
1057411677aeSAaron LI 				 */
1058411677aeSAaron LI 				if (ndo->ndo_vflag > 1) {
1059411677aeSAaron LI 					/* Yes. */
1060411677aeSAaron LI 					print_unknown_data(ndo, p, "\n\t  ", ielength);
1061411677aeSAaron LI 				}
1062411677aeSAaron LI 			} else {
1063411677aeSAaron LI 				/*
1064411677aeSAaron LI 				 * Unknown IE; if we're printing verbosely,
1065411677aeSAaron LI 				 * print its content in hex.
1066411677aeSAaron LI 				 */
1067411677aeSAaron LI 				if (ndo->ndo_vflag >= 1) {
1068411677aeSAaron LI 					print_unknown_data(ndo, p, "\n\t", ielength);
1069411677aeSAaron LI 				}
1070ea7b4bf5SPeter Avalos 			}
107141c99275SPeter Avalos 
1072411677aeSAaron LI 			length -= ielength;
1073411677aeSAaron LI 			p += ielength;
1074ea7b4bf5SPeter Avalos 		}
1075411677aeSAaron LI 	}
1076411677aeSAaron LI 	if (!ndo->ndo_vflag) {
1077*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(", length %u", olen);
1078411677aeSAaron LI 	}
1079411677aeSAaron LI 	return;
108041c99275SPeter Avalos 
1081411677aeSAaron LI trunc:
1082*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
1083ea7b4bf5SPeter Avalos }
108441c99275SPeter Avalos 
108541c99275SPeter Avalos static int
fr_q933_print_ie_codeset_0_5(netdissect_options * ndo,u_int iecode,u_int ielength,const u_char * p)1086411677aeSAaron LI fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode,
1087411677aeSAaron LI                           u_int ielength, const u_char *p)
108841c99275SPeter Avalos {
108941c99275SPeter Avalos         u_int dlci;
109041c99275SPeter Avalos 
1091411677aeSAaron LI         switch (iecode) {
109241c99275SPeter Avalos 
109341c99275SPeter Avalos         case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */
109441c99275SPeter Avalos         case FR_LMI_CCITT_REPORT_TYPE_IE:
1095411677aeSAaron LI             if (ielength < 1) {
1096411677aeSAaron LI                 if (!ndo->ndo_vflag) {
1097*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", ");
1098411677aeSAaron LI 	        }
1099*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("Invalid REPORT TYPE IE");
1100411677aeSAaron LI                 return 1;
1101411677aeSAaron LI             }
1102411677aeSAaron LI             if (ndo->ndo_vflag) {
1103*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("%s (%u)",
1104*ed775ee7SAntonio Huete Jimenez                        tok2str(fr_lmi_report_type_ie_values,"unknown",GET_U_1(p)),
1105*ed775ee7SAntonio Huete Jimenez                        GET_U_1(p));
1106ea7b4bf5SPeter Avalos 	    }
110741c99275SPeter Avalos             return 1;
110841c99275SPeter Avalos 
110941c99275SPeter Avalos         case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */
111041c99275SPeter Avalos         case FR_LMI_CCITT_LINK_VERIFY_IE:
111141c99275SPeter Avalos         case FR_LMI_ANSI_LINK_VERIFY_IE_91:
1112411677aeSAaron LI             if (!ndo->ndo_vflag) {
1113*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", ");
1114ea7b4bf5SPeter Avalos 	    }
1115411677aeSAaron LI             if (ielength < 2) {
1116*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("Invalid LINK VERIFY IE");
1117411677aeSAaron LI                 return 1;
1118411677aeSAaron LI             }
1119*ed775ee7SAntonio Huete Jimenez             ND_PRINT("TX Seq: %3d, RX Seq: %3d", GET_U_1(p), GET_U_1(p + 1));
112041c99275SPeter Avalos             return 1;
112141c99275SPeter Avalos 
112241c99275SPeter Avalos         case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */
112341c99275SPeter Avalos         case FR_LMI_CCITT_PVC_STATUS_IE:
1124411677aeSAaron LI             if (!ndo->ndo_vflag) {
1125*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", ");
1126ea7b4bf5SPeter Avalos 	    }
112741c99275SPeter Avalos             /* now parse the DLCI information element. */
1128411677aeSAaron LI             if ((ielength < 3) ||
1129*ed775ee7SAntonio Huete Jimenez                 (GET_U_1(p) & 0x80) ||
1130*ed775ee7SAntonio Huete Jimenez                 ((ielength == 3) && !(GET_U_1(p + 1) & 0x80)) ||
1131*ed775ee7SAntonio Huete Jimenez                 ((ielength == 4) &&
1132*ed775ee7SAntonio Huete Jimenez                   ((GET_U_1(p + 1) & 0x80) || !(GET_U_1(p + 2) & 0x80))) ||
1133*ed775ee7SAntonio Huete Jimenez                 ((ielength == 5) &&
1134*ed775ee7SAntonio Huete Jimenez                   ((GET_U_1(p + 1) & 0x80) || (GET_U_1(p + 2) & 0x80) ||
1135*ed775ee7SAntonio Huete Jimenez                    !(GET_U_1(p + 3) & 0x80))) ||
1136411677aeSAaron LI                 (ielength > 5) ||
1137*ed775ee7SAntonio Huete Jimenez                 !(GET_U_1(p + ielength - 1) & 0x80)) {
1138*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("Invalid DLCI in PVC STATUS IE");
1139411677aeSAaron LI                 return 1;
1140ea7b4bf5SPeter Avalos 	    }
114141c99275SPeter Avalos 
1142*ed775ee7SAntonio Huete Jimenez             dlci = ((GET_U_1(p) & 0x3F) << 4) | ((GET_U_1(p + 1) & 0x78) >> 3);
1143411677aeSAaron LI             if (ielength == 4) {
1144*ed775ee7SAntonio Huete Jimenez                 dlci = (dlci << 6) | ((GET_U_1(p + 2) & 0x7E) >> 1);
1145ea7b4bf5SPeter Avalos 	    }
1146411677aeSAaron LI             else if (ielength == 5) {
1147*ed775ee7SAntonio Huete Jimenez                 dlci = (dlci << 13) | (GET_U_1(p + 2) & 0x7F) | ((GET_U_1(p + 3) & 0x7E) >> 1);
1148ea7b4bf5SPeter Avalos 	    }
114941c99275SPeter Avalos 
1150*ed775ee7SAntonio Huete Jimenez             ND_PRINT("DLCI %u: status %s%s", dlci,
1151*ed775ee7SAntonio Huete Jimenez                     GET_U_1(p + ielength - 1) & 0x8 ? "New, " : "",
1152*ed775ee7SAntonio Huete Jimenez                     GET_U_1(p + ielength - 1) & 0x2 ? "Active" : "Inactive");
115341c99275SPeter Avalos             return 1;
115441c99275SPeter Avalos 	}
115541c99275SPeter Avalos 
115641c99275SPeter Avalos         return 0;
115741c99275SPeter Avalos }
1158