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