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