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