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