1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
3*b636d99dSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
4*b636d99dSDavid van Moolenbroek *
5*b636d99dSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek * modification, are permitted provided that: (1) source code distributions
7*b636d99dSDavid van Moolenbroek * retain the above copyright notice and this paragraph in its entirety, (2)
8*b636d99dSDavid van Moolenbroek * distributions including binary code include the above copyright notice and
9*b636d99dSDavid van Moolenbroek * this paragraph in its entirety in the documentation or other materials
10*b636d99dSDavid van Moolenbroek * provided with the distribution, and (3) all advertising materials mentioning
11*b636d99dSDavid van Moolenbroek * features or use of this software display the following acknowledgement:
12*b636d99dSDavid van Moolenbroek * ``This product includes software developed by the University of California,
13*b636d99dSDavid van Moolenbroek * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*b636d99dSDavid van Moolenbroek * the University nor the names of its contributors may be used to endorse
15*b636d99dSDavid van Moolenbroek * or promote products derived from this software without specific prior
16*b636d99dSDavid van Moolenbroek * written permission.
17*b636d99dSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*b636d99dSDavid van Moolenbroek * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*b636d99dSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*b636d99dSDavid van Moolenbroek */
21*b636d99dSDavid van Moolenbroek
22*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
23*b636d99dSDavid van Moolenbroek #ifndef lint
24*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-fr.c,v 1.6 2015/03/31 21:59:35 christos Exp $");
25*b636d99dSDavid van Moolenbroek #endif
26*b636d99dSDavid van Moolenbroek
27*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
28*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
29*b636d99dSDavid van Moolenbroek #include "config.h"
30*b636d99dSDavid van Moolenbroek #endif
31*b636d99dSDavid van Moolenbroek
32*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
33*b636d99dSDavid van Moolenbroek
34*b636d99dSDavid van Moolenbroek #include <stdio.h>
35*b636d99dSDavid van Moolenbroek #include <string.h>
36*b636d99dSDavid van Moolenbroek
37*b636d99dSDavid van Moolenbroek #include "interface.h"
38*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
39*b636d99dSDavid van Moolenbroek #include "ethertype.h"
40*b636d99dSDavid van Moolenbroek #include "llc.h"
41*b636d99dSDavid van Moolenbroek #include "nlpid.h"
42*b636d99dSDavid van Moolenbroek #include "extract.h"
43*b636d99dSDavid van Moolenbroek #include "oui.h"
44*b636d99dSDavid van Moolenbroek
45*b636d99dSDavid van Moolenbroek static void frf15_print(netdissect_options *ndo, const u_char *, u_int);
46*b636d99dSDavid van Moolenbroek
47*b636d99dSDavid van Moolenbroek /*
48*b636d99dSDavid van Moolenbroek * the frame relay header has a variable length
49*b636d99dSDavid van Moolenbroek *
50*b636d99dSDavid van Moolenbroek * the EA bit determines if there is another byte
51*b636d99dSDavid van Moolenbroek * in the header
52*b636d99dSDavid van Moolenbroek *
53*b636d99dSDavid van Moolenbroek * minimum header length is 2 bytes
54*b636d99dSDavid van Moolenbroek * maximum header length is 4 bytes
55*b636d99dSDavid van Moolenbroek *
56*b636d99dSDavid van Moolenbroek * 7 6 5 4 3 2 1 0
57*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
58*b636d99dSDavid van Moolenbroek * | DLCI (6 bits) | CR | EA |
59*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
60*b636d99dSDavid van Moolenbroek * | DLCI (4 bits) |FECN|BECN| DE | EA |
61*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
62*b636d99dSDavid van Moolenbroek * | DLCI (7 bits) | EA |
63*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
64*b636d99dSDavid van Moolenbroek * | DLCI (6 bits) |SDLC| EA |
65*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
66*b636d99dSDavid van Moolenbroek */
67*b636d99dSDavid van Moolenbroek
68*b636d99dSDavid van Moolenbroek #define FR_EA_BIT 0x01
69*b636d99dSDavid van Moolenbroek
70*b636d99dSDavid van Moolenbroek #define FR_CR_BIT 0x02000000
71*b636d99dSDavid van Moolenbroek #define FR_DE_BIT 0x00020000
72*b636d99dSDavid van Moolenbroek #define FR_BECN_BIT 0x00040000
73*b636d99dSDavid van Moolenbroek #define FR_FECN_BIT 0x00080000
74*b636d99dSDavid van Moolenbroek #define FR_SDLC_BIT 0x00000002
75*b636d99dSDavid van Moolenbroek
76*b636d99dSDavid van Moolenbroek
77*b636d99dSDavid van Moolenbroek static const struct tok fr_header_flag_values[] = {
78*b636d99dSDavid van Moolenbroek { FR_CR_BIT, "C!" },
79*b636d99dSDavid van Moolenbroek { FR_DE_BIT, "DE" },
80*b636d99dSDavid van Moolenbroek { FR_BECN_BIT, "BECN" },
81*b636d99dSDavid van Moolenbroek { FR_FECN_BIT, "FECN" },
82*b636d99dSDavid van Moolenbroek { FR_SDLC_BIT, "sdlcore" },
83*b636d99dSDavid van Moolenbroek { 0, NULL }
84*b636d99dSDavid van Moolenbroek };
85*b636d99dSDavid van Moolenbroek
86*b636d99dSDavid van Moolenbroek /* FRF.15 / FRF.16 */
87*b636d99dSDavid van Moolenbroek #define MFR_B_BIT 0x80
88*b636d99dSDavid van Moolenbroek #define MFR_E_BIT 0x40
89*b636d99dSDavid van Moolenbroek #define MFR_C_BIT 0x20
90*b636d99dSDavid van Moolenbroek #define MFR_BEC_MASK (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
91*b636d99dSDavid van Moolenbroek #define MFR_CTRL_FRAME (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
92*b636d99dSDavid van Moolenbroek #define MFR_FRAG_FRAME (MFR_B_BIT | MFR_E_BIT )
93*b636d99dSDavid van Moolenbroek
94*b636d99dSDavid van Moolenbroek static const struct tok frf_flag_values[] = {
95*b636d99dSDavid van Moolenbroek { MFR_B_BIT, "Begin" },
96*b636d99dSDavid van Moolenbroek { MFR_E_BIT, "End" },
97*b636d99dSDavid van Moolenbroek { MFR_C_BIT, "Control" },
98*b636d99dSDavid van Moolenbroek { 0, NULL }
99*b636d99dSDavid van Moolenbroek };
100*b636d99dSDavid van Moolenbroek
101*b636d99dSDavid van Moolenbroek /* Finds out Q.922 address length, DLCI and flags. Returns 1 on success,
102*b636d99dSDavid van Moolenbroek * 0 on invalid address, -1 on truncated packet
103*b636d99dSDavid van Moolenbroek * save the flags dep. on address length
104*b636d99dSDavid van Moolenbroek */
parse_q922_addr(netdissect_options * ndo,const u_char * p,u_int * dlci,u_int * addr_len,uint8_t * flags,u_int length)105*b636d99dSDavid van Moolenbroek static int parse_q922_addr(netdissect_options *ndo,
106*b636d99dSDavid van Moolenbroek const u_char *p, u_int *dlci,
107*b636d99dSDavid van Moolenbroek u_int *addr_len, uint8_t *flags, u_int length)
108*b636d99dSDavid van Moolenbroek {
109*b636d99dSDavid van Moolenbroek if (!ND_TTEST(p[0]) || length < 1)
110*b636d99dSDavid van Moolenbroek return -1;
111*b636d99dSDavid van Moolenbroek if ((p[0] & FR_EA_BIT))
112*b636d99dSDavid van Moolenbroek return 0;
113*b636d99dSDavid van Moolenbroek
114*b636d99dSDavid van Moolenbroek if (!ND_TTEST(p[1]) || length < 2)
115*b636d99dSDavid van Moolenbroek return -1;
116*b636d99dSDavid van Moolenbroek *addr_len = 2;
117*b636d99dSDavid van Moolenbroek *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4);
118*b636d99dSDavid van Moolenbroek
119*b636d99dSDavid van Moolenbroek flags[0] = p[0] & 0x02; /* populate the first flag fields */
120*b636d99dSDavid van Moolenbroek flags[1] = p[1] & 0x0c;
121*b636d99dSDavid van Moolenbroek flags[2] = 0; /* clear the rest of the flags */
122*b636d99dSDavid van Moolenbroek flags[3] = 0;
123*b636d99dSDavid van Moolenbroek
124*b636d99dSDavid van Moolenbroek if (p[1] & FR_EA_BIT)
125*b636d99dSDavid van Moolenbroek return 1; /* 2-byte Q.922 address */
126*b636d99dSDavid van Moolenbroek
127*b636d99dSDavid van Moolenbroek p += 2;
128*b636d99dSDavid van Moolenbroek length -= 2;
129*b636d99dSDavid van Moolenbroek if (!ND_TTEST(p[0]) || length < 1)
130*b636d99dSDavid van Moolenbroek return -1;
131*b636d99dSDavid van Moolenbroek (*addr_len)++; /* 3- or 4-byte Q.922 address */
132*b636d99dSDavid van Moolenbroek if ((p[0] & FR_EA_BIT) == 0) {
133*b636d99dSDavid van Moolenbroek *dlci = (*dlci << 7) | (p[0] >> 1);
134*b636d99dSDavid van Moolenbroek (*addr_len)++; /* 4-byte Q.922 address */
135*b636d99dSDavid van Moolenbroek p++;
136*b636d99dSDavid van Moolenbroek length--;
137*b636d99dSDavid van Moolenbroek }
138*b636d99dSDavid van Moolenbroek
139*b636d99dSDavid van Moolenbroek if (!ND_TTEST(p[0]) || length < 1)
140*b636d99dSDavid van Moolenbroek return -1;
141*b636d99dSDavid van Moolenbroek if ((p[0] & FR_EA_BIT) == 0)
142*b636d99dSDavid van Moolenbroek return 0; /* more than 4 bytes of Q.922 address? */
143*b636d99dSDavid van Moolenbroek
144*b636d99dSDavid van Moolenbroek flags[3] = p[0] & 0x02;
145*b636d99dSDavid van Moolenbroek
146*b636d99dSDavid van Moolenbroek *dlci = (*dlci << 6) | (p[0] >> 2);
147*b636d99dSDavid van Moolenbroek
148*b636d99dSDavid van Moolenbroek return 1;
149*b636d99dSDavid van Moolenbroek }
150*b636d99dSDavid van Moolenbroek
151*b636d99dSDavid van Moolenbroek char *
q922_string(netdissect_options * ndo,const u_char * p,u_int length)152*b636d99dSDavid van Moolenbroek q922_string(netdissect_options *ndo, const u_char *p, u_int length)
153*b636d99dSDavid van Moolenbroek {
154*b636d99dSDavid van Moolenbroek
155*b636d99dSDavid van Moolenbroek static u_int dlci, addr_len;
156*b636d99dSDavid van Moolenbroek static uint8_t flags[4];
157*b636d99dSDavid van Moolenbroek static char buffer[sizeof("DLCI xxxxxxxxxx")];
158*b636d99dSDavid van Moolenbroek memset(buffer, 0, sizeof(buffer));
159*b636d99dSDavid van Moolenbroek
160*b636d99dSDavid van Moolenbroek if (parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length) == 1){
161*b636d99dSDavid van Moolenbroek snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);
162*b636d99dSDavid van Moolenbroek }
163*b636d99dSDavid van Moolenbroek
164*b636d99dSDavid van Moolenbroek return buffer;
165*b636d99dSDavid van Moolenbroek }
166*b636d99dSDavid van Moolenbroek
167*b636d99dSDavid van Moolenbroek
168*b636d99dSDavid van Moolenbroek /* Frame Relay packet structure, with flags and CRC removed
169*b636d99dSDavid van Moolenbroek
170*b636d99dSDavid van Moolenbroek +---------------------------+
171*b636d99dSDavid van Moolenbroek | Q.922 Address* |
172*b636d99dSDavid van Moolenbroek +-- --+
173*b636d99dSDavid van Moolenbroek | |
174*b636d99dSDavid van Moolenbroek +---------------------------+
175*b636d99dSDavid van Moolenbroek | Control (UI = 0x03) |
176*b636d99dSDavid van Moolenbroek +---------------------------+
177*b636d99dSDavid van Moolenbroek | Optional Pad (0x00) |
178*b636d99dSDavid van Moolenbroek +---------------------------+
179*b636d99dSDavid van Moolenbroek | NLPID |
180*b636d99dSDavid van Moolenbroek +---------------------------+
181*b636d99dSDavid van Moolenbroek | . |
182*b636d99dSDavid van Moolenbroek | . |
183*b636d99dSDavid van Moolenbroek | . |
184*b636d99dSDavid van Moolenbroek | Data |
185*b636d99dSDavid van Moolenbroek | . |
186*b636d99dSDavid van Moolenbroek | . |
187*b636d99dSDavid van Moolenbroek +---------------------------+
188*b636d99dSDavid van Moolenbroek
189*b636d99dSDavid van Moolenbroek * Q.922 addresses, as presently defined, are two octets and
190*b636d99dSDavid van Moolenbroek contain a 10-bit DLCI. In some networks Q.922 addresses
191*b636d99dSDavid van Moolenbroek may optionally be increased to three or four octets.
192*b636d99dSDavid van Moolenbroek */
193*b636d99dSDavid van Moolenbroek
194*b636d99dSDavid van Moolenbroek static void
fr_hdr_print(netdissect_options * ndo,int length,u_int addr_len,u_int dlci,uint8_t * flags,uint16_t nlpid)195*b636d99dSDavid van Moolenbroek fr_hdr_print(netdissect_options *ndo,
196*b636d99dSDavid van Moolenbroek int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid)
197*b636d99dSDavid van Moolenbroek {
198*b636d99dSDavid van Moolenbroek if (ndo->ndo_qflag) {
199*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Q.922, DLCI %u, length %u: ",
200*b636d99dSDavid van Moolenbroek dlci,
201*b636d99dSDavid van Moolenbroek length));
202*b636d99dSDavid van Moolenbroek } else {
203*b636d99dSDavid van Moolenbroek if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */
204*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ",
205*b636d99dSDavid van Moolenbroek addr_len,
206*b636d99dSDavid van Moolenbroek dlci,
207*b636d99dSDavid van Moolenbroek bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)),
208*b636d99dSDavid van Moolenbroek tok2str(nlpid_values,"unknown", nlpid),
209*b636d99dSDavid van Moolenbroek nlpid,
210*b636d99dSDavid van Moolenbroek length));
211*b636d99dSDavid van Moolenbroek else /* must be an ethertype */
212*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ",
213*b636d99dSDavid van Moolenbroek addr_len,
214*b636d99dSDavid van Moolenbroek dlci,
215*b636d99dSDavid van Moolenbroek bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)),
216*b636d99dSDavid van Moolenbroek tok2str(ethertype_values, "unknown", nlpid),
217*b636d99dSDavid van Moolenbroek nlpid,
218*b636d99dSDavid van Moolenbroek length));
219*b636d99dSDavid van Moolenbroek }
220*b636d99dSDavid van Moolenbroek }
221*b636d99dSDavid van Moolenbroek
222*b636d99dSDavid van Moolenbroek u_int
fr_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,register const u_char * p)223*b636d99dSDavid van Moolenbroek fr_if_print(netdissect_options *ndo,
224*b636d99dSDavid van Moolenbroek const struct pcap_pkthdr *h, register const u_char *p)
225*b636d99dSDavid van Moolenbroek {
226*b636d99dSDavid van Moolenbroek register u_int length = h->len;
227*b636d99dSDavid van Moolenbroek register u_int caplen = h->caplen;
228*b636d99dSDavid van Moolenbroek
229*b636d99dSDavid van Moolenbroek ND_TCHECK2(*p, 4); /* minimum frame header length */
230*b636d99dSDavid van Moolenbroek
231*b636d99dSDavid van Moolenbroek if ((length = fr_print(ndo, p, length)) == 0)
232*b636d99dSDavid van Moolenbroek return (0);
233*b636d99dSDavid van Moolenbroek else
234*b636d99dSDavid van Moolenbroek return length;
235*b636d99dSDavid van Moolenbroek trunc:
236*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|fr]"));
237*b636d99dSDavid van Moolenbroek return caplen;
238*b636d99dSDavid van Moolenbroek }
239*b636d99dSDavid van Moolenbroek
240*b636d99dSDavid van Moolenbroek u_int
fr_print(netdissect_options * ndo,register const u_char * p,u_int length)241*b636d99dSDavid van Moolenbroek fr_print(netdissect_options *ndo,
242*b636d99dSDavid van Moolenbroek register const u_char *p, u_int length)
243*b636d99dSDavid van Moolenbroek {
244*b636d99dSDavid van Moolenbroek int ret;
245*b636d99dSDavid van Moolenbroek uint16_t extracted_ethertype;
246*b636d99dSDavid van Moolenbroek u_int dlci;
247*b636d99dSDavid van Moolenbroek u_int addr_len;
248*b636d99dSDavid van Moolenbroek uint16_t nlpid;
249*b636d99dSDavid van Moolenbroek u_int hdr_len;
250*b636d99dSDavid van Moolenbroek uint8_t flags[4];
251*b636d99dSDavid van Moolenbroek
252*b636d99dSDavid van Moolenbroek ret = parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length);
253*b636d99dSDavid van Moolenbroek if (ret == -1)
254*b636d99dSDavid van Moolenbroek goto trunc;
255*b636d99dSDavid van Moolenbroek if (ret == 0) {
256*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Q.922, invalid address"));
257*b636d99dSDavid van Moolenbroek return 0;
258*b636d99dSDavid van Moolenbroek }
259*b636d99dSDavid van Moolenbroek
260*b636d99dSDavid van Moolenbroek ND_TCHECK(p[addr_len]);
261*b636d99dSDavid van Moolenbroek if (length < addr_len + 1)
262*b636d99dSDavid van Moolenbroek goto trunc;
263*b636d99dSDavid van Moolenbroek
264*b636d99dSDavid van Moolenbroek if (p[addr_len] != LLC_UI && dlci != 0) {
265*b636d99dSDavid van Moolenbroek /*
266*b636d99dSDavid van Moolenbroek * Let's figure out if we have Cisco-style encapsulation,
267*b636d99dSDavid van Moolenbroek * with an Ethernet type (Cisco HDLC type?) following the
268*b636d99dSDavid van Moolenbroek * address.
269*b636d99dSDavid van Moolenbroek */
270*b636d99dSDavid van Moolenbroek if (!ND_TTEST2(p[addr_len], 2) || length < addr_len + 2) {
271*b636d99dSDavid van Moolenbroek /* no Ethertype */
272*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "UI %02x! ", p[addr_len]));
273*b636d99dSDavid van Moolenbroek } else {
274*b636d99dSDavid van Moolenbroek extracted_ethertype = EXTRACT_16BITS(p+addr_len);
275*b636d99dSDavid van Moolenbroek
276*b636d99dSDavid van Moolenbroek if (ndo->ndo_eflag)
277*b636d99dSDavid van Moolenbroek fr_hdr_print(ndo, length, addr_len, dlci,
278*b636d99dSDavid van Moolenbroek flags, extracted_ethertype);
279*b636d99dSDavid van Moolenbroek
280*b636d99dSDavid van Moolenbroek if (ethertype_print(ndo, extracted_ethertype,
281*b636d99dSDavid van Moolenbroek p+addr_len+ETHERTYPE_LEN,
282*b636d99dSDavid van Moolenbroek length-addr_len-ETHERTYPE_LEN,
283*b636d99dSDavid van Moolenbroek length-addr_len-ETHERTYPE_LEN) == 0)
284*b636d99dSDavid van Moolenbroek /* ether_type not known, probably it wasn't one */
285*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "UI %02x! ", p[addr_len]));
286*b636d99dSDavid van Moolenbroek else
287*b636d99dSDavid van Moolenbroek return addr_len + 2;
288*b636d99dSDavid van Moolenbroek }
289*b636d99dSDavid van Moolenbroek }
290*b636d99dSDavid van Moolenbroek
291*b636d99dSDavid van Moolenbroek ND_TCHECK(p[addr_len+1]);
292*b636d99dSDavid van Moolenbroek if (length < addr_len + 2)
293*b636d99dSDavid van Moolenbroek goto trunc;
294*b636d99dSDavid van Moolenbroek
295*b636d99dSDavid van Moolenbroek if (p[addr_len + 1] == 0) {
296*b636d99dSDavid van Moolenbroek /*
297*b636d99dSDavid van Moolenbroek * Assume a pad byte after the control (UI) byte.
298*b636d99dSDavid van Moolenbroek * A pad byte should only be used with 3-byte Q.922.
299*b636d99dSDavid van Moolenbroek */
300*b636d99dSDavid van Moolenbroek if (addr_len != 3)
301*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Pad! "));
302*b636d99dSDavid van Moolenbroek hdr_len = addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */;
303*b636d99dSDavid van Moolenbroek } else {
304*b636d99dSDavid van Moolenbroek /*
305*b636d99dSDavid van Moolenbroek * Not a pad byte.
306*b636d99dSDavid van Moolenbroek * A pad byte should be used with 3-byte Q.922.
307*b636d99dSDavid van Moolenbroek */
308*b636d99dSDavid van Moolenbroek if (addr_len == 3)
309*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "No pad! "));
310*b636d99dSDavid van Moolenbroek hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */;
311*b636d99dSDavid van Moolenbroek }
312*b636d99dSDavid van Moolenbroek
313*b636d99dSDavid van Moolenbroek ND_TCHECK(p[hdr_len - 1]);
314*b636d99dSDavid van Moolenbroek if (length < hdr_len)
315*b636d99dSDavid van Moolenbroek goto trunc;
316*b636d99dSDavid van Moolenbroek nlpid = p[hdr_len - 1];
317*b636d99dSDavid van Moolenbroek
318*b636d99dSDavid van Moolenbroek if (ndo->ndo_eflag)
319*b636d99dSDavid van Moolenbroek fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid);
320*b636d99dSDavid van Moolenbroek p += hdr_len;
321*b636d99dSDavid van Moolenbroek length -= hdr_len;
322*b636d99dSDavid van Moolenbroek
323*b636d99dSDavid van Moolenbroek switch (nlpid) {
324*b636d99dSDavid van Moolenbroek case NLPID_IP:
325*b636d99dSDavid van Moolenbroek ip_print(ndo, p, length);
326*b636d99dSDavid van Moolenbroek break;
327*b636d99dSDavid van Moolenbroek
328*b636d99dSDavid van Moolenbroek case NLPID_IP6:
329*b636d99dSDavid van Moolenbroek ip6_print(ndo, p, length);
330*b636d99dSDavid van Moolenbroek break;
331*b636d99dSDavid van Moolenbroek
332*b636d99dSDavid van Moolenbroek case NLPID_CLNP:
333*b636d99dSDavid van Moolenbroek case NLPID_ESIS:
334*b636d99dSDavid van Moolenbroek case NLPID_ISIS:
335*b636d99dSDavid van Moolenbroek isoclns_print(ndo, p - 1, length + 1, length + 1); /* OSI printers need the NLPID field */
336*b636d99dSDavid van Moolenbroek break;
337*b636d99dSDavid van Moolenbroek
338*b636d99dSDavid van Moolenbroek case NLPID_SNAP:
339*b636d99dSDavid van Moolenbroek if (snap_print(ndo, p, length, length, 0) == 0) {
340*b636d99dSDavid van Moolenbroek /* ether_type not known, print raw packet */
341*b636d99dSDavid van Moolenbroek if (!ndo->ndo_eflag)
342*b636d99dSDavid van Moolenbroek fr_hdr_print(ndo, length + hdr_len, hdr_len,
343*b636d99dSDavid van Moolenbroek dlci, flags, nlpid);
344*b636d99dSDavid van Moolenbroek if (!ndo->ndo_suppress_default_print)
345*b636d99dSDavid van Moolenbroek ND_DEFAULTPRINT(p - hdr_len, length + hdr_len);
346*b636d99dSDavid van Moolenbroek }
347*b636d99dSDavid van Moolenbroek break;
348*b636d99dSDavid van Moolenbroek
349*b636d99dSDavid van Moolenbroek case NLPID_Q933:
350*b636d99dSDavid van Moolenbroek q933_print(ndo, p, length);
351*b636d99dSDavid van Moolenbroek break;
352*b636d99dSDavid van Moolenbroek
353*b636d99dSDavid van Moolenbroek case NLPID_MFR:
354*b636d99dSDavid van Moolenbroek frf15_print(ndo, p, length);
355*b636d99dSDavid van Moolenbroek break;
356*b636d99dSDavid van Moolenbroek
357*b636d99dSDavid van Moolenbroek case NLPID_PPP:
358*b636d99dSDavid van Moolenbroek ppp_print(ndo, p, length);
359*b636d99dSDavid van Moolenbroek break;
360*b636d99dSDavid van Moolenbroek
361*b636d99dSDavid van Moolenbroek default:
362*b636d99dSDavid van Moolenbroek if (!ndo->ndo_eflag)
363*b636d99dSDavid van Moolenbroek fr_hdr_print(ndo, length + hdr_len, addr_len,
364*b636d99dSDavid van Moolenbroek dlci, flags, nlpid);
365*b636d99dSDavid van Moolenbroek if (!ndo->ndo_xflag)
366*b636d99dSDavid van Moolenbroek ND_DEFAULTPRINT(p, length);
367*b636d99dSDavid van Moolenbroek }
368*b636d99dSDavid van Moolenbroek
369*b636d99dSDavid van Moolenbroek return hdr_len;
370*b636d99dSDavid van Moolenbroek
371*b636d99dSDavid van Moolenbroek trunc:
372*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|fr]"));
373*b636d99dSDavid van Moolenbroek return 0;
374*b636d99dSDavid van Moolenbroek
375*b636d99dSDavid van Moolenbroek }
376*b636d99dSDavid van Moolenbroek
377*b636d99dSDavid van Moolenbroek u_int
mfr_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,register const u_char * p)378*b636d99dSDavid van Moolenbroek mfr_if_print(netdissect_options *ndo,
379*b636d99dSDavid van Moolenbroek const struct pcap_pkthdr *h, register const u_char *p)
380*b636d99dSDavid van Moolenbroek {
381*b636d99dSDavid van Moolenbroek register u_int length = h->len;
382*b636d99dSDavid van Moolenbroek register u_int caplen = h->caplen;
383*b636d99dSDavid van Moolenbroek
384*b636d99dSDavid van Moolenbroek ND_TCHECK2(*p, 2); /* minimum frame header length */
385*b636d99dSDavid van Moolenbroek
386*b636d99dSDavid van Moolenbroek if ((length = mfr_print(ndo, p, length)) == 0)
387*b636d99dSDavid van Moolenbroek return (0);
388*b636d99dSDavid van Moolenbroek else
389*b636d99dSDavid van Moolenbroek return length;
390*b636d99dSDavid van Moolenbroek trunc:
391*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|mfr]"));
392*b636d99dSDavid van Moolenbroek return caplen;
393*b636d99dSDavid van Moolenbroek }
394*b636d99dSDavid van Moolenbroek
395*b636d99dSDavid van Moolenbroek
396*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_ADD_LINK 1
397*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_ADD_LINK_ACK 2
398*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_ADD_LINK_REJ 3
399*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_HELLO 4
400*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_HELLO_ACK 5
401*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_REMOVE_LINK 6
402*b636d99dSDavid van Moolenbroek #define MFR_CTRL_MSG_REMOVE_LINK_ACK 7
403*b636d99dSDavid van Moolenbroek
404*b636d99dSDavid van Moolenbroek static const struct tok mfr_ctrl_msg_values[] = {
405*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_ADD_LINK, "Add Link" },
406*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" },
407*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" },
408*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_HELLO, "Hello" },
409*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" },
410*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" },
411*b636d99dSDavid van Moolenbroek { MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" },
412*b636d99dSDavid van Moolenbroek { 0, NULL }
413*b636d99dSDavid van Moolenbroek };
414*b636d99dSDavid van Moolenbroek
415*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_BUNDLE_ID 1
416*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_LINK_ID 2
417*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_MAGIC_NUM 3
418*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_TIMESTAMP 5
419*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_VENDOR_EXT 6
420*b636d99dSDavid van Moolenbroek #define MFR_CTRL_IE_CAUSE 7
421*b636d99dSDavid van Moolenbroek
422*b636d99dSDavid van Moolenbroek static const struct tok mfr_ctrl_ie_values[] = {
423*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"},
424*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_LINK_ID, "Link ID"},
425*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_MAGIC_NUM, "Magic Number"},
426*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_TIMESTAMP, "Timestamp"},
427*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"},
428*b636d99dSDavid van Moolenbroek { MFR_CTRL_IE_CAUSE, "Cause"},
429*b636d99dSDavid van Moolenbroek { 0, NULL }
430*b636d99dSDavid van Moolenbroek };
431*b636d99dSDavid van Moolenbroek
432*b636d99dSDavid van Moolenbroek #define MFR_ID_STRING_MAXLEN 50
433*b636d99dSDavid van Moolenbroek
434*b636d99dSDavid van Moolenbroek struct ie_tlv_header_t {
435*b636d99dSDavid van Moolenbroek uint8_t ie_type;
436*b636d99dSDavid van Moolenbroek uint8_t ie_len;
437*b636d99dSDavid van Moolenbroek };
438*b636d99dSDavid van Moolenbroek
439*b636d99dSDavid van Moolenbroek u_int
mfr_print(netdissect_options * ndo,register const u_char * p,u_int length)440*b636d99dSDavid van Moolenbroek mfr_print(netdissect_options *ndo,
441*b636d99dSDavid van Moolenbroek register const u_char *p, u_int length)
442*b636d99dSDavid van Moolenbroek {
443*b636d99dSDavid van Moolenbroek u_int tlen,idx,hdr_len = 0;
444*b636d99dSDavid van Moolenbroek uint16_t sequence_num;
445*b636d99dSDavid van Moolenbroek uint8_t ie_type,ie_len;
446*b636d99dSDavid van Moolenbroek const uint8_t *tptr;
447*b636d99dSDavid van Moolenbroek
448*b636d99dSDavid van Moolenbroek
449*b636d99dSDavid van Moolenbroek /*
450*b636d99dSDavid van Moolenbroek * FRF.16 Link Integrity Control Frame
451*b636d99dSDavid van Moolenbroek *
452*b636d99dSDavid van Moolenbroek * 7 6 5 4 3 2 1 0
453*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
454*b636d99dSDavid van Moolenbroek * | B | E | C=1| 0 0 0 0 | EA |
455*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
456*b636d99dSDavid van Moolenbroek * | 0 0 0 0 0 0 0 0 |
457*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
458*b636d99dSDavid van Moolenbroek * | message type |
459*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
460*b636d99dSDavid van Moolenbroek */
461*b636d99dSDavid van Moolenbroek
462*b636d99dSDavid van Moolenbroek ND_TCHECK2(*p, 4); /* minimum frame header length */
463*b636d99dSDavid van Moolenbroek
464*b636d99dSDavid van Moolenbroek if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) {
465*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "FRF.16 Control, Flags [%s], %s, length %u",
466*b636d99dSDavid van Moolenbroek bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)),
467*b636d99dSDavid van Moolenbroek tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",p[2]),
468*b636d99dSDavid van Moolenbroek length));
469*b636d99dSDavid van Moolenbroek tptr = p + 3;
470*b636d99dSDavid van Moolenbroek tlen = length -3;
471*b636d99dSDavid van Moolenbroek hdr_len = 3;
472*b636d99dSDavid van Moolenbroek
473*b636d99dSDavid van Moolenbroek if (!ndo->ndo_vflag)
474*b636d99dSDavid van Moolenbroek return hdr_len;
475*b636d99dSDavid van Moolenbroek
476*b636d99dSDavid van Moolenbroek while (tlen>sizeof(struct ie_tlv_header_t)) {
477*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, sizeof(struct ie_tlv_header_t));
478*b636d99dSDavid van Moolenbroek ie_type=tptr[0];
479*b636d99dSDavid van Moolenbroek ie_len=tptr[1];
480*b636d99dSDavid van Moolenbroek
481*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\tIE %s (%u), length %u: ",
482*b636d99dSDavid van Moolenbroek tok2str(mfr_ctrl_ie_values,"Unknown",ie_type),
483*b636d99dSDavid van Moolenbroek ie_type,
484*b636d99dSDavid van Moolenbroek ie_len));
485*b636d99dSDavid van Moolenbroek
486*b636d99dSDavid van Moolenbroek /* infinite loop check */
487*b636d99dSDavid van Moolenbroek if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t))
488*b636d99dSDavid van Moolenbroek return hdr_len;
489*b636d99dSDavid van Moolenbroek
490*b636d99dSDavid van Moolenbroek ND_TCHECK2(*tptr, ie_len);
491*b636d99dSDavid van Moolenbroek tptr+=sizeof(struct ie_tlv_header_t);
492*b636d99dSDavid van Moolenbroek /* tlv len includes header */
493*b636d99dSDavid van Moolenbroek ie_len-=sizeof(struct ie_tlv_header_t);
494*b636d99dSDavid van Moolenbroek tlen-=sizeof(struct ie_tlv_header_t);
495*b636d99dSDavid van Moolenbroek
496*b636d99dSDavid van Moolenbroek switch (ie_type) {
497*b636d99dSDavid van Moolenbroek
498*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_MAGIC_NUM:
499*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(tptr)));
500*b636d99dSDavid van Moolenbroek break;
501*b636d99dSDavid van Moolenbroek
502*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_BUNDLE_ID: /* same message format */
503*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_LINK_ID:
504*b636d99dSDavid van Moolenbroek for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) {
505*b636d99dSDavid van Moolenbroek if (*(tptr+idx) != 0) /* don't print null termination */
506*b636d99dSDavid van Moolenbroek safeputchar(ndo, *(tptr + idx));
507*b636d99dSDavid van Moolenbroek else
508*b636d99dSDavid van Moolenbroek break;
509*b636d99dSDavid van Moolenbroek }
510*b636d99dSDavid van Moolenbroek break;
511*b636d99dSDavid van Moolenbroek
512*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_TIMESTAMP:
513*b636d99dSDavid van Moolenbroek if (ie_len == sizeof(struct timeval)) {
514*b636d99dSDavid van Moolenbroek ts_print(ndo, (const struct timeval *)tptr);
515*b636d99dSDavid van Moolenbroek break;
516*b636d99dSDavid van Moolenbroek }
517*b636d99dSDavid van Moolenbroek /* fall through and hexdump if no unix timestamp */
518*b636d99dSDavid van Moolenbroek
519*b636d99dSDavid van Moolenbroek /*
520*b636d99dSDavid van Moolenbroek * FIXME those are the defined IEs that lack a decoder
521*b636d99dSDavid van Moolenbroek * you are welcome to contribute code ;-)
522*b636d99dSDavid van Moolenbroek */
523*b636d99dSDavid van Moolenbroek
524*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_VENDOR_EXT:
525*b636d99dSDavid van Moolenbroek case MFR_CTRL_IE_CAUSE:
526*b636d99dSDavid van Moolenbroek
527*b636d99dSDavid van Moolenbroek default:
528*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag <= 1)
529*b636d99dSDavid van Moolenbroek print_unknown_data(ndo, tptr, "\n\t ", ie_len);
530*b636d99dSDavid van Moolenbroek break;
531*b636d99dSDavid van Moolenbroek }
532*b636d99dSDavid van Moolenbroek
533*b636d99dSDavid van Moolenbroek /* do we want to see a hexdump of the IE ? */
534*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag > 1 )
535*b636d99dSDavid van Moolenbroek print_unknown_data(ndo, tptr, "\n\t ", ie_len);
536*b636d99dSDavid van Moolenbroek
537*b636d99dSDavid van Moolenbroek tlen-=ie_len;
538*b636d99dSDavid van Moolenbroek tptr+=ie_len;
539*b636d99dSDavid van Moolenbroek }
540*b636d99dSDavid van Moolenbroek return hdr_len;
541*b636d99dSDavid van Moolenbroek }
542*b636d99dSDavid van Moolenbroek /*
543*b636d99dSDavid van Moolenbroek * FRF.16 Fragmentation Frame
544*b636d99dSDavid van Moolenbroek *
545*b636d99dSDavid van Moolenbroek * 7 6 5 4 3 2 1 0
546*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
547*b636d99dSDavid van Moolenbroek * | B | E | C=0|seq. (high 4 bits) | EA |
548*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
549*b636d99dSDavid van Moolenbroek * | sequence (low 8 bits) |
550*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
551*b636d99dSDavid van Moolenbroek * | DLCI (6 bits) | CR | EA |
552*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
553*b636d99dSDavid van Moolenbroek * | DLCI (4 bits) |FECN|BECN| DE | EA |
554*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
555*b636d99dSDavid van Moolenbroek */
556*b636d99dSDavid van Moolenbroek
557*b636d99dSDavid van Moolenbroek sequence_num = (p[0]&0x1e)<<7 | p[1];
558*b636d99dSDavid van Moolenbroek /* whole packet or first fragment ? */
559*b636d99dSDavid van Moolenbroek if ((p[0] & MFR_BEC_MASK) == MFR_FRAG_FRAME ||
560*b636d99dSDavid van Moolenbroek (p[0] & MFR_BEC_MASK) == MFR_B_BIT) {
561*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s], ",
562*b636d99dSDavid van Moolenbroek sequence_num,
563*b636d99dSDavid van Moolenbroek bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK))));
564*b636d99dSDavid van Moolenbroek hdr_len = 2;
565*b636d99dSDavid van Moolenbroek fr_print(ndo, p+hdr_len,length-hdr_len);
566*b636d99dSDavid van Moolenbroek return hdr_len;
567*b636d99dSDavid van Moolenbroek }
568*b636d99dSDavid van Moolenbroek
569*b636d99dSDavid van Moolenbroek /* must be a middle or the last fragment */
570*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s]",
571*b636d99dSDavid van Moolenbroek sequence_num,
572*b636d99dSDavid van Moolenbroek bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK))));
573*b636d99dSDavid van Moolenbroek print_unknown_data(ndo, p, "\n\t", length);
574*b636d99dSDavid van Moolenbroek
575*b636d99dSDavid van Moolenbroek return hdr_len;
576*b636d99dSDavid van Moolenbroek
577*b636d99dSDavid van Moolenbroek trunc:
578*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|mfr]"));
579*b636d99dSDavid van Moolenbroek return length;
580*b636d99dSDavid van Moolenbroek }
581*b636d99dSDavid van Moolenbroek
582*b636d99dSDavid van Moolenbroek /* an NLPID of 0xb1 indicates a 2-byte
583*b636d99dSDavid van Moolenbroek * FRF.15 header
584*b636d99dSDavid van Moolenbroek *
585*b636d99dSDavid van Moolenbroek * 7 6 5 4 3 2 1 0
586*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
587*b636d99dSDavid van Moolenbroek * ~ Q.922 header ~
588*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
589*b636d99dSDavid van Moolenbroek * | NLPID (8 bits) | NLPID=0xb1
590*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
591*b636d99dSDavid van Moolenbroek * | B | E | C |seq. (high 4 bits) | R |
592*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
593*b636d99dSDavid van Moolenbroek * | sequence (low 8 bits) |
594*b636d99dSDavid van Moolenbroek * +----+----+----+----+----+----+----+----+
595*b636d99dSDavid van Moolenbroek */
596*b636d99dSDavid van Moolenbroek
597*b636d99dSDavid van Moolenbroek #define FR_FRF15_FRAGTYPE 0x01
598*b636d99dSDavid van Moolenbroek
599*b636d99dSDavid van Moolenbroek static void
frf15_print(netdissect_options * ndo,const u_char * p,u_int length)600*b636d99dSDavid van Moolenbroek frf15_print(netdissect_options *ndo,
601*b636d99dSDavid van Moolenbroek const u_char *p, u_int length)
602*b636d99dSDavid van Moolenbroek {
603*b636d99dSDavid van Moolenbroek uint16_t sequence_num, flags;
604*b636d99dSDavid van Moolenbroek
605*b636d99dSDavid van Moolenbroek flags = p[0]&MFR_BEC_MASK;
606*b636d99dSDavid van Moolenbroek sequence_num = (p[0]&0x1e)<<7 | p[1];
607*b636d99dSDavid van Moolenbroek
608*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u",
609*b636d99dSDavid van Moolenbroek sequence_num,
610*b636d99dSDavid van Moolenbroek bittok2str(frf_flag_values,"none",flags),
611*b636d99dSDavid van Moolenbroek p[0]&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End",
612*b636d99dSDavid van Moolenbroek length));
613*b636d99dSDavid van Moolenbroek
614*b636d99dSDavid van Moolenbroek /* TODO:
615*b636d99dSDavid van Moolenbroek * depending on all permutations of the B, E and C bit
616*b636d99dSDavid van Moolenbroek * dig as deep as we can - e.g. on the first (B) fragment
617*b636d99dSDavid van Moolenbroek * there is enough payload to print the IP header
618*b636d99dSDavid van Moolenbroek * on non (B) fragments it depends if the fragmentation
619*b636d99dSDavid van Moolenbroek * model is end-to-end or interface based wether we want to print
620*b636d99dSDavid van Moolenbroek * another Q.922 header
621*b636d99dSDavid van Moolenbroek */
622*b636d99dSDavid van Moolenbroek
623*b636d99dSDavid van Moolenbroek }
624*b636d99dSDavid van Moolenbroek
625*b636d99dSDavid van Moolenbroek /*
626*b636d99dSDavid van Moolenbroek * Q.933 decoding portion for framerelay specific.
627*b636d99dSDavid van Moolenbroek */
628*b636d99dSDavid van Moolenbroek
629*b636d99dSDavid van Moolenbroek /* Q.933 packet format
630*b636d99dSDavid van Moolenbroek Format of Other Protocols
631*b636d99dSDavid van Moolenbroek using Q.933 NLPID
632*b636d99dSDavid van Moolenbroek +-------------------------------+
633*b636d99dSDavid van Moolenbroek | Q.922 Address |
634*b636d99dSDavid van Moolenbroek +---------------+---------------+
635*b636d99dSDavid van Moolenbroek |Control 0x03 | NLPID 0x08 |
636*b636d99dSDavid van Moolenbroek +---------------+---------------+
637*b636d99dSDavid van Moolenbroek | L2 Protocol ID |
638*b636d99dSDavid van Moolenbroek | octet 1 | octet 2 |
639*b636d99dSDavid van Moolenbroek +-------------------------------+
640*b636d99dSDavid van Moolenbroek | L3 Protocol ID |
641*b636d99dSDavid van Moolenbroek | octet 2 | octet 2 |
642*b636d99dSDavid van Moolenbroek +-------------------------------+
643*b636d99dSDavid van Moolenbroek | Protocol Data |
644*b636d99dSDavid van Moolenbroek +-------------------------------+
645*b636d99dSDavid van Moolenbroek | FCS |
646*b636d99dSDavid van Moolenbroek +-------------------------------+
647*b636d99dSDavid van Moolenbroek */
648*b636d99dSDavid van Moolenbroek
649*b636d99dSDavid van Moolenbroek /* L2 (Octet 1)- Call Reference Usually is 0x0 */
650*b636d99dSDavid van Moolenbroek
651*b636d99dSDavid van Moolenbroek /*
652*b636d99dSDavid van Moolenbroek * L2 (Octet 2)- Message Types definition 1 byte long.
653*b636d99dSDavid van Moolenbroek */
654*b636d99dSDavid van Moolenbroek /* Call Establish */
655*b636d99dSDavid van Moolenbroek #define MSG_TYPE_ESC_TO_NATIONAL 0x00
656*b636d99dSDavid van Moolenbroek #define MSG_TYPE_ALERT 0x01
657*b636d99dSDavid van Moolenbroek #define MSG_TYPE_CALL_PROCEEDING 0x02
658*b636d99dSDavid van Moolenbroek #define MSG_TYPE_CONNECT 0x07
659*b636d99dSDavid van Moolenbroek #define MSG_TYPE_CONNECT_ACK 0x0F
660*b636d99dSDavid van Moolenbroek #define MSG_TYPE_PROGRESS 0x03
661*b636d99dSDavid van Moolenbroek #define MSG_TYPE_SETUP 0x05
662*b636d99dSDavid van Moolenbroek /* Call Clear */
663*b636d99dSDavid van Moolenbroek #define MSG_TYPE_DISCONNECT 0x45
664*b636d99dSDavid van Moolenbroek #define MSG_TYPE_RELEASE 0x4D
665*b636d99dSDavid van Moolenbroek #define MSG_TYPE_RELEASE_COMPLETE 0x5A
666*b636d99dSDavid van Moolenbroek #define MSG_TYPE_RESTART 0x46
667*b636d99dSDavid van Moolenbroek #define MSG_TYPE_RESTART_ACK 0x4E
668*b636d99dSDavid van Moolenbroek /* Status */
669*b636d99dSDavid van Moolenbroek #define MSG_TYPE_STATUS 0x7D
670*b636d99dSDavid van Moolenbroek #define MSG_TYPE_STATUS_ENQ 0x75
671*b636d99dSDavid van Moolenbroek
672*b636d99dSDavid van Moolenbroek static const struct tok fr_q933_msg_values[] = {
673*b636d99dSDavid van Moolenbroek { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" },
674*b636d99dSDavid van Moolenbroek { MSG_TYPE_ALERT, "Alert" },
675*b636d99dSDavid van Moolenbroek { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" },
676*b636d99dSDavid van Moolenbroek { MSG_TYPE_CONNECT, "Connect" },
677*b636d99dSDavid van Moolenbroek { MSG_TYPE_CONNECT_ACK, "Connect ACK" },
678*b636d99dSDavid van Moolenbroek { MSG_TYPE_PROGRESS, "Progress" },
679*b636d99dSDavid van Moolenbroek { MSG_TYPE_SETUP, "Setup" },
680*b636d99dSDavid van Moolenbroek { MSG_TYPE_DISCONNECT, "Disconnect" },
681*b636d99dSDavid van Moolenbroek { MSG_TYPE_RELEASE, "Release" },
682*b636d99dSDavid van Moolenbroek { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" },
683*b636d99dSDavid van Moolenbroek { MSG_TYPE_RESTART, "Restart" },
684*b636d99dSDavid van Moolenbroek { MSG_TYPE_RESTART_ACK, "Restart ACK" },
685*b636d99dSDavid van Moolenbroek { MSG_TYPE_STATUS, "Status Reply" },
686*b636d99dSDavid van Moolenbroek { MSG_TYPE_STATUS_ENQ, "Status Enquiry" },
687*b636d99dSDavid van Moolenbroek { 0, NULL }
688*b636d99dSDavid van Moolenbroek };
689*b636d99dSDavid van Moolenbroek
690*b636d99dSDavid van Moolenbroek #define MSG_ANSI_LOCKING_SHIFT 0x95
691*b636d99dSDavid van Moolenbroek
692*b636d99dSDavid van Moolenbroek #define FR_LMI_ANSI_REPORT_TYPE_IE 0x01
693*b636d99dSDavid van Moolenbroek #define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */
694*b636d99dSDavid van Moolenbroek #define FR_LMI_ANSI_LINK_VERIFY_IE 0x03
695*b636d99dSDavid van Moolenbroek #define FR_LMI_ANSI_PVC_STATUS_IE 0x07
696*b636d99dSDavid van Moolenbroek
697*b636d99dSDavid van Moolenbroek #define FR_LMI_CCITT_REPORT_TYPE_IE 0x51
698*b636d99dSDavid van Moolenbroek #define FR_LMI_CCITT_LINK_VERIFY_IE 0x53
699*b636d99dSDavid van Moolenbroek #define FR_LMI_CCITT_PVC_STATUS_IE 0x57
700*b636d99dSDavid van Moolenbroek
701*b636d99dSDavid van Moolenbroek static const struct tok fr_q933_ie_values_codeset5[] = {
702*b636d99dSDavid van Moolenbroek { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" },
703*b636d99dSDavid van Moolenbroek { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" },
704*b636d99dSDavid van Moolenbroek { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" },
705*b636d99dSDavid van Moolenbroek { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" },
706*b636d99dSDavid van Moolenbroek { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" },
707*b636d99dSDavid van Moolenbroek { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" },
708*b636d99dSDavid van Moolenbroek { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" },
709*b636d99dSDavid van Moolenbroek { 0, NULL }
710*b636d99dSDavid van Moolenbroek };
711*b636d99dSDavid van Moolenbroek
712*b636d99dSDavid van Moolenbroek #define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0
713*b636d99dSDavid van Moolenbroek #define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1
714*b636d99dSDavid van Moolenbroek #define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2
715*b636d99dSDavid van Moolenbroek
716*b636d99dSDavid van Moolenbroek static const struct tok fr_lmi_report_type_ie_values[] = {
717*b636d99dSDavid van Moolenbroek { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" },
718*b636d99dSDavid van Moolenbroek { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" },
719*b636d99dSDavid van Moolenbroek { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" },
720*b636d99dSDavid van Moolenbroek { 0, NULL }
721*b636d99dSDavid van Moolenbroek };
722*b636d99dSDavid van Moolenbroek
723*b636d99dSDavid van Moolenbroek /* array of 16 codepages - currently we only support codepage 1,5 */
724*b636d99dSDavid van Moolenbroek static const struct tok *fr_q933_ie_codesets[] = {
725*b636d99dSDavid van Moolenbroek NULL,
726*b636d99dSDavid van Moolenbroek fr_q933_ie_values_codeset5,
727*b636d99dSDavid van Moolenbroek NULL,
728*b636d99dSDavid van Moolenbroek NULL,
729*b636d99dSDavid van Moolenbroek NULL,
730*b636d99dSDavid van Moolenbroek fr_q933_ie_values_codeset5,
731*b636d99dSDavid van Moolenbroek NULL,
732*b636d99dSDavid van Moolenbroek NULL,
733*b636d99dSDavid van Moolenbroek NULL,
734*b636d99dSDavid van Moolenbroek NULL,
735*b636d99dSDavid van Moolenbroek NULL,
736*b636d99dSDavid van Moolenbroek NULL,
737*b636d99dSDavid van Moolenbroek NULL,
738*b636d99dSDavid van Moolenbroek NULL,
739*b636d99dSDavid van Moolenbroek NULL,
740*b636d99dSDavid van Moolenbroek NULL
741*b636d99dSDavid van Moolenbroek };
742*b636d99dSDavid van Moolenbroek
743*b636d99dSDavid van Moolenbroek static int fr_q933_print_ie_codeset5(netdissect_options *ndo,
744*b636d99dSDavid van Moolenbroek const struct ie_tlv_header_t *ie_p, const u_char *p);
745*b636d99dSDavid van Moolenbroek
746*b636d99dSDavid van Moolenbroek typedef int (*codeset_pr_func_t)(netdissect_options *,
747*b636d99dSDavid van Moolenbroek const struct ie_tlv_header_t *ie_p, const u_char *p);
748*b636d99dSDavid van Moolenbroek
749*b636d99dSDavid van Moolenbroek /* array of 16 codepages - currently we only support codepage 1,5 */
750*b636d99dSDavid van Moolenbroek static const codeset_pr_func_t fr_q933_print_ie_codeset[] = {
751*b636d99dSDavid van Moolenbroek NULL,
752*b636d99dSDavid van Moolenbroek fr_q933_print_ie_codeset5,
753*b636d99dSDavid van Moolenbroek NULL,
754*b636d99dSDavid van Moolenbroek NULL,
755*b636d99dSDavid van Moolenbroek NULL,
756*b636d99dSDavid van Moolenbroek fr_q933_print_ie_codeset5,
757*b636d99dSDavid van Moolenbroek NULL,
758*b636d99dSDavid van Moolenbroek NULL,
759*b636d99dSDavid van Moolenbroek NULL,
760*b636d99dSDavid van Moolenbroek NULL,
761*b636d99dSDavid van Moolenbroek NULL,
762*b636d99dSDavid van Moolenbroek NULL,
763*b636d99dSDavid van Moolenbroek NULL,
764*b636d99dSDavid van Moolenbroek NULL,
765*b636d99dSDavid van Moolenbroek NULL,
766*b636d99dSDavid van Moolenbroek NULL
767*b636d99dSDavid van Moolenbroek };
768*b636d99dSDavid van Moolenbroek
769*b636d99dSDavid van Moolenbroek void
q933_print(netdissect_options * ndo,const u_char * p,u_int length)770*b636d99dSDavid van Moolenbroek q933_print(netdissect_options *ndo,
771*b636d99dSDavid van Moolenbroek const u_char *p, u_int length)
772*b636d99dSDavid van Moolenbroek {
773*b636d99dSDavid van Moolenbroek const u_char *ptemp = p;
774*b636d99dSDavid van Moolenbroek struct ie_tlv_header_t *ie_p;
775*b636d99dSDavid van Moolenbroek int olen;
776*b636d99dSDavid van Moolenbroek int is_ansi = 0;
777*b636d99dSDavid van Moolenbroek u_int codeset;
778*b636d99dSDavid van Moolenbroek u_int ie_is_known = 0;
779*b636d99dSDavid van Moolenbroek
780*b636d99dSDavid van Moolenbroek if (length < 9) { /* shortest: Q.933a LINK VERIFY */
781*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|q.933]"));
782*b636d99dSDavid van Moolenbroek return;
783*b636d99dSDavid van Moolenbroek }
784*b636d99dSDavid van Moolenbroek
785*b636d99dSDavid van Moolenbroek codeset = p[2]&0x0f; /* extract the codeset */
786*b636d99dSDavid van Moolenbroek
787*b636d99dSDavid van Moolenbroek if (p[2] == MSG_ANSI_LOCKING_SHIFT) {
788*b636d99dSDavid van Moolenbroek is_ansi = 1;
789*b636d99dSDavid van Moolenbroek }
790*b636d99dSDavid van Moolenbroek
791*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s", ndo->ndo_eflag ? "" : "Q.933, "));
792*b636d99dSDavid van Moolenbroek
793*b636d99dSDavid van Moolenbroek /* printing out header part */
794*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset));
795*b636d99dSDavid van Moolenbroek
796*b636d99dSDavid van Moolenbroek if (p[0]) {
797*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Call Ref: 0x%02x", p[0]));
798*b636d99dSDavid van Moolenbroek }
799*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) {
800*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s (0x%02x), length %u",
801*b636d99dSDavid van Moolenbroek tok2str(fr_q933_msg_values,
802*b636d99dSDavid van Moolenbroek "unknown message", p[1]),
803*b636d99dSDavid van Moolenbroek p[1],
804*b636d99dSDavid van Moolenbroek length));
805*b636d99dSDavid van Moolenbroek } else {
806*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", %s",
807*b636d99dSDavid van Moolenbroek tok2str(fr_q933_msg_values,
808*b636d99dSDavid van Moolenbroek "unknown message 0x%02x", p[1])));
809*b636d99dSDavid van Moolenbroek }
810*b636d99dSDavid van Moolenbroek
811*b636d99dSDavid van Moolenbroek olen = length; /* preserve the original length for non verbose mode */
812*b636d99dSDavid van Moolenbroek
813*b636d99dSDavid van Moolenbroek if (length < (u_int)(2 - is_ansi)) {
814*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "[|q.933]"));
815*b636d99dSDavid van Moolenbroek return;
816*b636d99dSDavid van Moolenbroek }
817*b636d99dSDavid van Moolenbroek length -= 2 + is_ansi;
818*b636d99dSDavid van Moolenbroek ptemp += 2 + is_ansi;
819*b636d99dSDavid van Moolenbroek
820*b636d99dSDavid van Moolenbroek /* Loop through the rest of IE */
821*b636d99dSDavid van Moolenbroek while (length > sizeof(struct ie_tlv_header_t)) {
822*b636d99dSDavid van Moolenbroek ie_p = (struct ie_tlv_header_t *)ptemp;
823*b636d99dSDavid van Moolenbroek if (length < sizeof(struct ie_tlv_header_t) ||
824*b636d99dSDavid van Moolenbroek length < sizeof(struct ie_tlv_header_t) + ie_p->ie_len) {
825*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) { /* not bark if there is just a trailer */
826*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n[|q.933]"));
827*b636d99dSDavid van Moolenbroek } else {
828*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", length %u", olen));
829*b636d99dSDavid van Moolenbroek }
830*b636d99dSDavid van Moolenbroek return;
831*b636d99dSDavid van Moolenbroek }
832*b636d99dSDavid van Moolenbroek
833*b636d99dSDavid van Moolenbroek /* lets do the full IE parsing only in verbose mode
834*b636d99dSDavid van Moolenbroek * however some IEs (DLCI Status, Link Verify)
835*b636d99dSDavid van Moolenbroek * are also interestting in non-verbose mode */
836*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) {
837*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t%s IE (0x%02x), length %u: ",
838*b636d99dSDavid van Moolenbroek tok2str(fr_q933_ie_codesets[codeset],
839*b636d99dSDavid van Moolenbroek "unknown", ie_p->ie_type),
840*b636d99dSDavid van Moolenbroek ie_p->ie_type,
841*b636d99dSDavid van Moolenbroek ie_p->ie_len));
842*b636d99dSDavid van Moolenbroek }
843*b636d99dSDavid van Moolenbroek
844*b636d99dSDavid van Moolenbroek /* sanity check */
845*b636d99dSDavid van Moolenbroek if (ie_p->ie_type == 0 || ie_p->ie_len == 0) {
846*b636d99dSDavid van Moolenbroek return;
847*b636d99dSDavid van Moolenbroek }
848*b636d99dSDavid van Moolenbroek
849*b636d99dSDavid van Moolenbroek if (fr_q933_print_ie_codeset[codeset] != NULL) {
850*b636d99dSDavid van Moolenbroek ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, ie_p, ptemp);
851*b636d99dSDavid van Moolenbroek }
852*b636d99dSDavid van Moolenbroek
853*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag >= 1 && !ie_is_known) {
854*b636d99dSDavid van Moolenbroek print_unknown_data(ndo, ptemp+2, "\n\t", ie_p->ie_len);
855*b636d99dSDavid van Moolenbroek }
856*b636d99dSDavid van Moolenbroek
857*b636d99dSDavid van Moolenbroek /* do we want to see a hexdump of the IE ? */
858*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag> 1 && ie_is_known) {
859*b636d99dSDavid van Moolenbroek print_unknown_data(ndo, ptemp+2, "\n\t ", ie_p->ie_len);
860*b636d99dSDavid van Moolenbroek }
861*b636d99dSDavid van Moolenbroek
862*b636d99dSDavid van Moolenbroek length = length - ie_p->ie_len - 2;
863*b636d99dSDavid van Moolenbroek ptemp = ptemp + ie_p->ie_len + 2;
864*b636d99dSDavid van Moolenbroek }
865*b636d99dSDavid van Moolenbroek if (!ndo->ndo_vflag) {
866*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", length %u", olen));
867*b636d99dSDavid van Moolenbroek }
868*b636d99dSDavid van Moolenbroek }
869*b636d99dSDavid van Moolenbroek
870*b636d99dSDavid van Moolenbroek static int
fr_q933_print_ie_codeset5(netdissect_options * ndo,const struct ie_tlv_header_t * ie_p,const u_char * p)871*b636d99dSDavid van Moolenbroek fr_q933_print_ie_codeset5(netdissect_options *ndo,
872*b636d99dSDavid van Moolenbroek const struct ie_tlv_header_t *ie_p, const u_char *p)
873*b636d99dSDavid van Moolenbroek {
874*b636d99dSDavid van Moolenbroek u_int dlci;
875*b636d99dSDavid van Moolenbroek
876*b636d99dSDavid van Moolenbroek switch (ie_p->ie_type) {
877*b636d99dSDavid van Moolenbroek
878*b636d99dSDavid van Moolenbroek case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */
879*b636d99dSDavid van Moolenbroek case FR_LMI_CCITT_REPORT_TYPE_IE:
880*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag) {
881*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s (%u)",
882*b636d99dSDavid van Moolenbroek tok2str(fr_lmi_report_type_ie_values,"unknown",p[2]),
883*b636d99dSDavid van Moolenbroek p[2]));
884*b636d99dSDavid van Moolenbroek }
885*b636d99dSDavid van Moolenbroek return 1;
886*b636d99dSDavid van Moolenbroek
887*b636d99dSDavid van Moolenbroek case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */
888*b636d99dSDavid van Moolenbroek case FR_LMI_CCITT_LINK_VERIFY_IE:
889*b636d99dSDavid van Moolenbroek case FR_LMI_ANSI_LINK_VERIFY_IE_91:
890*b636d99dSDavid van Moolenbroek if (!ndo->ndo_vflag) {
891*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", "));
892*b636d99dSDavid van Moolenbroek }
893*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "TX Seq: %3d, RX Seq: %3d", p[2], p[3]));
894*b636d99dSDavid van Moolenbroek return 1;
895*b636d99dSDavid van Moolenbroek
896*b636d99dSDavid van Moolenbroek case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */
897*b636d99dSDavid van Moolenbroek case FR_LMI_CCITT_PVC_STATUS_IE:
898*b636d99dSDavid van Moolenbroek if (!ndo->ndo_vflag) {
899*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", "));
900*b636d99dSDavid van Moolenbroek }
901*b636d99dSDavid van Moolenbroek /* now parse the DLCI information element. */
902*b636d99dSDavid van Moolenbroek if ((ie_p->ie_len < 3) ||
903*b636d99dSDavid van Moolenbroek (p[2] & 0x80) ||
904*b636d99dSDavid van Moolenbroek ((ie_p->ie_len == 3) && !(p[3] & 0x80)) ||
905*b636d99dSDavid van Moolenbroek ((ie_p->ie_len == 4) && ((p[3] & 0x80) || !(p[4] & 0x80))) ||
906*b636d99dSDavid van Moolenbroek ((ie_p->ie_len == 5) && ((p[3] & 0x80) || (p[4] & 0x80) ||
907*b636d99dSDavid van Moolenbroek !(p[5] & 0x80))) ||
908*b636d99dSDavid van Moolenbroek (ie_p->ie_len > 5) ||
909*b636d99dSDavid van Moolenbroek !(p[ie_p->ie_len + 1] & 0x80)) {
910*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Invalid DLCI IE"));
911*b636d99dSDavid van Moolenbroek }
912*b636d99dSDavid van Moolenbroek
913*b636d99dSDavid van Moolenbroek dlci = ((p[2] & 0x3F) << 4) | ((p[3] & 0x78) >> 3);
914*b636d99dSDavid van Moolenbroek if (ie_p->ie_len == 4) {
915*b636d99dSDavid van Moolenbroek dlci = (dlci << 6) | ((p[4] & 0x7E) >> 1);
916*b636d99dSDavid van Moolenbroek }
917*b636d99dSDavid van Moolenbroek else if (ie_p->ie_len == 5) {
918*b636d99dSDavid van Moolenbroek dlci = (dlci << 13) | (p[4] & 0x7F) | ((p[5] & 0x7E) >> 1);
919*b636d99dSDavid van Moolenbroek }
920*b636d99dSDavid van Moolenbroek
921*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "DLCI %u: status %s%s", dlci,
922*b636d99dSDavid van Moolenbroek p[ie_p->ie_len + 1] & 0x8 ? "New, " : "",
923*b636d99dSDavid van Moolenbroek p[ie_p->ie_len + 1] & 0x2 ? "Active" : "Inactive"));
924*b636d99dSDavid van Moolenbroek return 1;
925*b636d99dSDavid van Moolenbroek }
926*b636d99dSDavid van Moolenbroek
927*b636d99dSDavid van Moolenbroek return 0;
928*b636d99dSDavid van Moolenbroek }
929*b636d99dSDavid van Moolenbroek /*
930*b636d99dSDavid van Moolenbroek * Local Variables:
931*b636d99dSDavid van Moolenbroek * c-style: whitesmith
932*b636d99dSDavid van Moolenbroek * c-basic-offset: 8
933*b636d99dSDavid van Moolenbroek * End:
934*b636d99dSDavid van Moolenbroek */
935