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