]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-fr.c
bhyvectl(8): Normalize the man page date
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-fr.c
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
41 static 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
73 static 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
90 static 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  */
101 static 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
147 char *
148 q922_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
190 static void
191 fr_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
218 u_int
219 fr_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
236 u_int
237 fr_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
374 u_int
375 mfr_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
401 static 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
419 static 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
431 struct ie_tlv_header_t {
432     uint8_t ie_type;
433     uint8_t ie_len;
434 };
435
436 u_int
437 mfr_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
605 static void
606 frf15_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
634 trunc:
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
685 static 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
718 static 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
733 static 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 */
741 static 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
760 static int fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode,
761     u_int ielength, const u_char *p);
762
763 typedef 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 */
767 static 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  */
795 void
796 q933_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
1071 trunc:
1072         ND_PRINT((ndo, "[|q.933]"));
1073 }
1074
1075 static int
1076 fr_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  */