print-fr.c (127675) | print-fr.c (146778) |
---|---|
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 --- 4 unchanged lines hidden (view full) --- 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 * | 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 --- 4 unchanged lines hidden (view full) --- 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 * $FreeBSD: head/contrib/tcpdump/print-fr.c 127675 2004-03-31 14:57:24Z bms $ | 21 * $FreeBSD: head/contrib/tcpdump/print-fr.c 146778 2005-05-29 19:09:28Z sam $ |
22 */ 23 24#ifndef lint | 22 */ 23 24#ifndef lint |
25static char rcsid[] = 26 "@(#)$Header: /home/ncvs/src/contrib/tcpdump/print-fr.c,v 1.1 1997/12/31 21:50:31 pst Exp $ (LBL)"; | 25static const char rcsid[] _U_ = 26 "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.32 2005/04/06 21:32:39 mcr Exp $ (LBL)"; |
27#endif 28 | 27#endif 28 |
29#ifdef PPP 30#include <sys/param.h> 31#include <sys/time.h> 32#include <sys/socket.h> 33#include <sys/file.h> 34#include <sys/ioctl.h> 35 36#if __STDC__ 37struct mbuf; 38struct rtentry; | 29#ifdef HAVE_CONFIG_H 30#include "config.h" |
39#endif | 31#endif |
40#include <net/if.h> 41#include <net/if_var.h> | |
42 | 32 |
43#include <netinet/in.h> 44#include <netinet/in_systm.h> 45#include <netinet/ip.h> | 33#include <tcpdump-stdinc.h> |
46 | 34 |
47#include <ctype.h> 48#include <netdb.h> 49#include <pcap.h> 50#include <signal.h> | |
51#include <stdio.h> | 35#include <stdio.h> |
36#include <string.h> 37#include <pcap.h> |
|
52 | 38 |
53#include <netinet/if_ether.h> | 39#include "addrtoname.h" 40#include "interface.h" |
54#include "ethertype.h" | 41#include "ethertype.h" |
42#include "nlpid.h" 43#include "extract.h" 44#include "oui.h" |
|
55 | 45 |
56#include <net/ppp_defs.h> 57#include "interface.h" 58#include "addrtoname.h" | 46static void frf15_print(const u_char *, u_int); |
59 | 47 |
48/* 49 * the frame relay header has a variable length 50 * 51 * the EA bit determines if there is another byte 52 * in the header 53 * 54 * minimum header length is 2 bytes 55 * maximum header length is 4 bytes 56 * 57 * 7 6 5 4 3 2 1 0 58 * +----+----+----+----+----+----+----+----+ 59 * | DLCI (6 bits) | CR | EA | 60 * +----+----+----+----+----+----+----+----+ 61 * | DLCI (4 bits) |FECN|BECN| DE | EA | 62 * +----+----+----+----+----+----+----+----+ 63 * | DLCI (7 bits) | EA | 64 * +----+----+----+----+----+----+----+----+ 65 * | DLCI (6 bits) |SDLC| EA | 66 * +----+----+----+----+----+----+----+----+ 67 */ |
|
60 | 68 |
61void q933_print(); | 69#define FR_EA_BIT 0x01 |
62 | 70 |
63#define FR_EA_BIT(p) ((p)&0x1) 64#define FR_DLCI(b0,b1) ((((b0)&0xFC)<<2)+(((b1)&0xF0)>>4)) | 71#define FR_CR_BIT 0x02000000 72#define FR_DE_BIT 0x00020000 73#define FR_BECN_BIT 0x00040000 74#define FR_FECN_BIT 0x00080000 75#define FR_SDLC_BIT 0x00000002 |
65 | 76 |
66struct fr_nlpids { 67 u_short id; 68 char *name; | 77 78struct tok fr_header_flag_values[] = { 79 { FR_CR_BIT, "C!" }, 80 { FR_DE_BIT, "DE" }, 81 { FR_BECN_BIT, "BECN" }, 82 { FR_FECN_BIT, "FECN" }, 83 { FR_SDLC_BIT, "sdlcore" }, 84 { 0, NULL } |
69}; 70 | 85}; 86 |
71/* find out how many bytes are there in a frame */ 72int 73fr_addr_len(const u_char *p) | 87 88/* Finds out Q.922 address length, DLCI and flags. Returns 0 on success 89 * save the flags dep. on address length 90 */ 91static int parse_q922_addr(const u_char *p, u_int *dlci, u_int *sdlcore, 92 u_int *addr_len, u_int8_t *flags) |
74{ | 93{ |
75 int i=0; 76 77 while (!FR_EA_BIT(p[i]) && i++ && !FR_EA_BIT(p[i+1])) i++; 78 return (i+1); 79} | 94 if ((p[0] & FR_EA_BIT)) 95 return -1; |
80 | 96 |
81/* the following is for framerelay */ 82#define NLPID_LEN 1 /* NLPID is one byte long */ 83#define NLPID_Q933 0x08 84#define NLPID_CLNP 0x81 85#define NLPID_ESIS 0x82 86#define NLPID_ISIS 0x83 87#define NLPID_CONS 0x84 88#define NLPID_IDRP 0x85 89#define NLPID_X25_ESIS 0x8a 90#define NLPID_IP 0xcc | 97 *addr_len = 2; 98 *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); |
91 | 99 |
100 flags[0] = p[0] & 0x02; /* populate the first flag fields */ 101 flags[1] = p[1] & 0x0c; |
|
92 | 102 |
93static struct fr_nlpids fr_nlpids[256]; 94static fr_nlpid_flag =0; | 103 if (p[1] & FR_EA_BIT) 104 return 0; /* 2-byte Q.922 address */ |
95 | 105 |
96void init_fr_nlpids() 97{ 98 int i; 99 100 if (!fr_nlpid_flag) { 101 for (i=0; i < 256; i++) { 102 fr_nlpids[i].id = 0; 103 fr_nlpids[i].name = "Not Specified"; 104 } 105 fr_nlpids[NLPID_Q933].name = "Q.933"; 106 fr_nlpids[NLPID_CLNP].name = "CLNP"; 107 fr_nlpids[NLPID_ESIS].name = "ESIS"; 108 fr_nlpids[NLPID_ISIS].name = "ISIS"; 109 fr_nlpids[NLPID_CONS].name = "CONS"; 110 fr_nlpids[NLPID_IDRP].name = "IDRP"; 111 fr_nlpids[NLPID_X25_ESIS].name = "X25_ESIS"; 112 fr_nlpids[NLPID_IP].name = "IP"; | 106 p += 2; 107 (*addr_len)++; /* 3- or 4-byte Q.922 address */ 108 if ((p[0] & FR_EA_BIT) == 0) { 109 *dlci = (*dlci << 7) | (p[0] >> 1); 110 (*addr_len)++; /* 4-byte Q.922 address */ 111 p++; |
113 } | 112 } |
114 fr_nlpid_flag = 1; | 113 114 if ((p[0] & FR_EA_BIT) == 0) 115 return -1; /* more than 4 bytes of Q.922 address? */ 116 117 flags[3] = p[0] & 0x02; 118 119 if (p[0] & 0x02) 120 *sdlcore = p[0] >> 2; 121 else 122 *dlci = (*dlci << 6) | (p[0] >> 2); 123 124 return 0; |
115} 116 | 125} 126 |
117/* Framerelay packet structure */ | 127/* Frame Relay packet structure, with flags and CRC removed |
118 | 128 |
119/* | |
120 +---------------------------+ | 129 +---------------------------+ |
121 | flag (7E hexadecimal) | 122 +---------------------------+ | |
123 | Q.922 Address* | 124 +-- --+ 125 | | 126 +---------------------------+ 127 | Control (UI = 0x03) | 128 +---------------------------+ 129 | Optional Pad (0x00) | 130 +---------------------------+ 131 | NLPID | 132 +---------------------------+ 133 | . | 134 | . | 135 | . | 136 | Data | 137 | . | 138 | . | 139 +---------------------------+ | 130 | Q.922 Address* | 131 +-- --+ 132 | | 133 +---------------------------+ 134 | Control (UI = 0x03) | 135 +---------------------------+ 136 | Optional Pad (0x00) | 137 +---------------------------+ 138 | NLPID | 139 +---------------------------+ 140 | . | 141 | . | 142 | . | 143 | Data | 144 | . | 145 | . | 146 +---------------------------+ |
140 | Frame Check Sequence | 141 +-- . --+ 142 | (two octets) | 143 +---------------------------+ 144 | flag (7E hexadecimal) | 145 +---------------------------+ | |
146 147 * Q.922 addresses, as presently defined, are two octets and 148 contain a 10-bit DLCI. In some networks Q.922 addresses 149 may optionally be increased to three or four octets. | 147 148 * Q.922 addresses, as presently defined, are two octets and 149 contain a 10-bit DLCI. In some networks Q.922 addresses 150 may optionally be increased to three or four octets. |
150 | |
151*/ 152 | 151*/ 152 |
153#define FR_PROTOCOL(p) fr_protocol((p)) 154 155int 156fr_hdrlen(const u_char *p) | 153static u_int 154fr_hdrlen(const u_char *p, u_int addr_len, u_int caplen) |
157{ | 155{ |
158 int hlen; 159 hlen = fr_addr_len(p)+1; /* addr_len + 0x03 + padding */ 160 if( p[hlen] ) 161 return hlen; 162 else 163 return hlen+1; 164} 165 166#define LAYER2_LEN(p) (fr_hdrlen((p))+NLPID_LEN) 167 168int 169fr_protocol(const u_char *p) 170{ 171 int hlen; 172 173 hlen = fr_addr_len(p) + 1; 174 if (p[hlen]) /* check for padding */ 175 return p[hlen]; | 156 if ((caplen > addr_len + 1 /* UI */ + 1 /* pad */) && 157 !p[addr_len + 1] /* pad exist */) 158 return addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */; |
176 else | 159 else |
177 return p[hlen+1]; | 160 return addr_len + 1 /* UI */ + 1 /* NLPID */; |
178} 179 | 161} 162 |
180void 181fr_hdlc_print(const u_char *p, int length) | 163static void 164fr_hdr_print(int length, u_int addr_len, u_int dlci, u_int8_t *flags, u_int16_t nlpid) |
182{ | 165{ |
183 int proto; 184 int i; 185 int hlen; 186 187 proto = FR_PROTOCOL(p); 188 189 init_fr_nlpids(); 190 /* this is kinda kludge since it assumed that DLCI is two bytes. */ 191 printf("%4d %02x%02x=DLCI(%d) ", length, p[0], p[1], FR_DLCI(p[0],p[1])); 192 printf("%02x %6s: ", proto, fr_nlpids[proto].name); | 166 if (qflag) { 167 (void)printf("Q.922, DLCI %u, length %u: ", 168 dlci, 169 length); 170 } else { 171 if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */ 172 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ", 173 addr_len, 174 dlci, 175 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 176 tok2str(nlpid_values,"unknown", nlpid), 177 nlpid, 178 length); 179 else /* must be an ethertype */ 180 (void)printf("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ", 181 addr_len, 182 dlci, 183 bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), 184 tok2str(ethertype_values, "unknown", nlpid), 185 nlpid, 186 length); 187 } |
193} 194 | 188} 189 |
195 196 197void 198fr_if_print(u_char *user, const struct pcap_pkthdr *h, 199 register const u_char *p) | 190u_int 191fr_if_print(const struct pcap_pkthdr *h, register const u_char *p) |
200{ 201 register u_int length = h->len; 202 register u_int caplen = h->caplen; | 192{ 193 register u_int length = h->len; 194 register u_int caplen = h->caplen; |
203 int frame_relay = 0, 204 proto = FR_PROTOCOL(p); | 195 u_int16_t extracted_ethertype; 196 u_int32_t orgcode; 197 register u_short et; 198 u_int dlci; 199 u_int sdlcore; 200 u_int addr_len; 201 u_int16_t nlpid; 202 u_int hdr_len; 203 u_int8_t flags[4]; |
205 | 204 |
205 if (caplen < 4) { /* minimum frame header length */ 206 printf("[|fr]"); 207 return caplen; 208 } |
|
206 | 209 |
207 ts_print(&h->ts); | 210 if (parse_q922_addr(p, &dlci, &sdlcore, &addr_len, flags)) { 211 printf("Q.922, invalid address"); 212 return caplen; 213 } |
208 | 214 |
209 if (caplen < fr_hdrlen(p)) { | 215 hdr_len = fr_hdrlen(p, addr_len, caplen); 216 217 if (caplen < hdr_len) { |
210 printf("[|fr]"); | 218 printf("[|fr]"); |
211 goto out; | 219 return caplen; |
212 } 213 | 220 } 221 |
214 /* 215 * Some printers want to get back at the link level addresses, 216 * and/or check that they're not walking off the end of the packet. 217 * Rather than pass them all the way down, we set these globals. 218 */ 219 packetp = p; 220 snapend = p + caplen; | 222 if (p[addr_len] != 0x03 && dlci != 0) { |
221 | 223 |
222 if (eflag) 223 fr_hdlc_print(p, length); | 224 /* lets figure out if we have cisco style encapsulation: */ 225 extracted_ethertype = EXTRACT_16BITS(p+addr_len); |
224 | 226 |
225 length = length - (fr_hdrlen(p) + NLPID_LEN); | 227 if (eflag) 228 fr_hdr_print(length, addr_len, dlci, flags, extracted_ethertype); |
226 | 229 |
230 if (ether_encap_print(extracted_ethertype, 231 p+addr_len+ETHERTYPE_LEN, 232 length-addr_len-ETHERTYPE_LEN, 233 caplen-addr_len-ETHERTYPE_LEN, 234 &extracted_ethertype) == 0) 235 /* ether_type not known, probably it wasn't one */ 236 printf("UI %02x! ", p[addr_len]); 237 else 238 return hdr_len; 239 } |
|
227 | 240 |
228 switch(FR_PROTOCOL(p)) { | 241 if (!p[addr_len + 1]) { /* pad byte should be used with 3-byte Q.922 */ 242 if (addr_len != 3) 243 printf("Pad! "); 244 } else if (addr_len == 3) 245 printf("No pad! "); 246 247 nlpid = p[hdr_len - 1]; 248 249 if (eflag) 250 fr_hdr_print(length, addr_len, dlci, flags, nlpid); 251 252 p += hdr_len; 253 length -= hdr_len; 254 caplen -= hdr_len; 255 256 switch (nlpid) { |
229 case NLPID_IP: | 257 case NLPID_IP: |
230 case ETHERTYPE_IP: 231 ip_print((const u_char *)(p + LAYER2_LEN(p)), length); | 258 ip_print(gndo, p, length); |
232 break; | 259 break; |
260 261#ifdef INET6 262 case NLPID_IP6: 263 ip6_print(p, length); 264 break; 265#endif |
|
233 case NLPID_CLNP: 234 case NLPID_ESIS: 235 case NLPID_ISIS: | 266 case NLPID_CLNP: 267 case NLPID_ESIS: 268 case NLPID_ISIS: |
236 isoclns_print((const u_char *)(p + LAYER2_LEN(p)), length, 237 caplen, "000000", "000000"); | 269 isoclns_print(p-1, length+1, caplen+1); /* OSI printers need the NLPID field */ |
238 break; | 270 break; |
239 case NLPID_Q933: 240 q933_print((const u_char *)(p + LAYER2_LEN(p)), length); | 271 272 case NLPID_SNAP: 273 orgcode = EXTRACT_24BITS(p); 274 et = EXTRACT_16BITS(p + 3); 275 276 if (eflag) 277 (void)printf("SNAP, oui %s (0x%06x), ethertype %s (0x%04x): ", 278 tok2str(oui_values,"Unknown",orgcode), 279 orgcode, 280 tok2str(ethertype_values,"Unknown", et), 281 et); 282 283 if (snap_print((const u_char *)(p + 5), length - 5, 284 caplen - 5, &extracted_ethertype, orgcode, et, 285 0) == 0) { 286 /* ether_type not known, print raw packet */ 287 if (!eflag) 288 fr_hdr_print(length + hdr_len, hdr_len, 289 dlci, flags, nlpid); 290 if (!xflag && !qflag) 291 default_print(p - hdr_len, caplen + hdr_len); 292 } |
241 break; | 293 break; |
294 295 case NLPID_Q933: 296 q933_print(p, length); 297 break; 298 299 case NLPID_MFR: 300 frf15_print(p, length); 301 break; 302 |
|
242 default: | 303 default: |
243 if(!eflag) 244 fr_hdlc_print(p, length); 245 if(!xflag) 246 default_print((const u_char *)(p + LAYER2_LEN(p)), 247 caplen - LAYER2_LEN(p)); | 304 if (!eflag) 305 fr_hdr_print(length + hdr_len, addr_len, 306 dlci, flags, nlpid); 307 if (!xflag) 308 default_print(p, caplen); |
248 } 249 | 309 } 310 |
250 if (xflag) 251 default_print((const u_char *)(p + LAYER2_LEN(p)), 252 caplen - LAYER2_LEN(p)); 253out: 254 putchar('\n'); | 311 return hdr_len; |
255} | 312} |
256#else 257#include <sys/types.h> 258#include <sys/time.h> | |
259 | 313 |
260#include <stdio.h> | 314/* an NLPID of 0xb1 indicates a 2-byte 315 * FRF.15 header 316 * 317 * 7 6 5 4 3 2 1 0 318 * +----+----+----+----+----+----+----+----+ 319 * ~ Q.922 header ~ 320 * +----+----+----+----+----+----+----+----+ 321 * | NLPID (8 bits) | NLPID=0xb1 322 * +----+----+----+----+----+----+----+----+ 323 * | B | E | C |seq. (high 4 bits) | R | 324 * +----+----+----+----+----+----+----+----+ 325 * | sequence (low 8 bits) | 326 * +----+----+----+----+----+----+----+----+ 327 */ |
261 | 328 |
262#include "interface.h" 263u_int 264fr_if_print(const struct pcap_pkthdr *h, const u_char *p) 265{ 266 error("not configured for ppp"); 267 /* NOTREACHED */ | 329struct tok frf15_flag_values[] = { 330 { 0x80, "Begin" }, 331 { 0x40, "End" }, 332 { 0x20, "Control" }, 333 { 0, NULL } 334}; 335 336#define FR_FRF15_FRAGTYPE 0x01 337 338static void 339frf15_print (const u_char *p, u_int length) { 340 341 u_int16_t sequence_num, flags; 342 343 flags = p[0]&0xe0; 344 sequence_num = (p[0]&0x1e)<<7 | p[1]; 345 346 printf("FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", 347 sequence_num, 348 bittok2str(frf15_flag_values,"none",flags), 349 flags&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End", 350 length); 351 352/* TODO: 353 * depending on all permutations of the B, E and C bit 354 * dig as deep as we can - e.g. on the first (B) fragment 355 * there is enough payload to print the IP header 356 * on non (B) fragments it depends if the fragmentation 357 * model is end-to-end or interface based wether we want to print 358 * another Q.922 header 359 */ 360 |
268} | 361} |
269#endif | |
270 271/* 272 * Q.933 decoding portion for framerelay specific. 273 */ 274 275/* Q.933 packet format 276 Format of Other Protocols 277 using Q.933 NLPID --- 32 unchanged lines hidden (view full) --- 310#define MSG_TYPE_RELEASE 0x4D 311#define MSG_TYPE_RELEASE_COMPLETE 0x5A 312#define MSG_TYPE_RESTART 0x46 313#define MSG_TYPE_RESTART_ACK 0x4E 314/* Status */ 315#define MSG_TYPE_STATUS 0x7D 316#define MSG_TYPE_STATUS_ENQ 0x75 317 | 362 363/* 364 * Q.933 decoding portion for framerelay specific. 365 */ 366 367/* Q.933 packet format 368 Format of Other Protocols 369 using Q.933 NLPID --- 32 unchanged lines hidden (view full) --- 402#define MSG_TYPE_RELEASE 0x4D 403#define MSG_TYPE_RELEASE_COMPLETE 0x5A 404#define MSG_TYPE_RESTART 0x46 405#define MSG_TYPE_RESTART_ACK 0x4E 406/* Status */ 407#define MSG_TYPE_STATUS 0x7D 408#define MSG_TYPE_STATUS_ENQ 0x75 409 |
318#define ONE_BYTE_IE_MASK 0xF0 | 410struct tok fr_q933_msg_values[] = { 411 { MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" }, 412 { MSG_TYPE_ALERT, "Alert" }, 413 { MSG_TYPE_CALL_PROCEEDING, "Call proceeding" }, 414 { MSG_TYPE_CONNECT, "Connect" }, 415 { MSG_TYPE_CONNECT_ACK, "Connect ACK" }, 416 { MSG_TYPE_PROGRESS, "Progress" }, 417 { MSG_TYPE_SETUP, "Setup" }, 418 { MSG_TYPE_DISCONNECT, "Disconnect" }, 419 { MSG_TYPE_RELEASE, "Release" }, 420 { MSG_TYPE_RELEASE_COMPLETE, "Release Complete" }, 421 { MSG_TYPE_RESTART, "Restart" }, 422 { MSG_TYPE_RESTART_ACK, "Restart ACK" }, 423 { MSG_TYPE_STATUS, "Status Reply" }, 424 { MSG_TYPE_STATUS_ENQ, "Status Enquiry" }, 425 { 0, NULL } 426}; |
319 | 427 |
320/* See L2 protocol ID picture above */ 321struct q933_header { 322 u_char call_ref; /* usually is 0 for framerelay PVC */ 323 u_char msg_type; | 428#define MSG_ANSI_LOCKING_SHIFT 0x95 429 430#define FR_LMI_ANSI_REPORT_TYPE_IE 0x01 431#define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */ 432#define FR_LMI_ANSI_LINK_VERIFY_IE 0x03 433#define FR_LMI_ANSI_PVC_STATUS_IE 0x07 434 435#define FR_LMI_CCITT_REPORT_TYPE_IE 0x51 436#define FR_LMI_CCITT_LINK_VERIFY_IE 0x53 437#define FR_LMI_CCITT_PVC_STATUS_IE 0x57 438 439struct tok fr_q933_ie_values_codeset5[] = { 440 { FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" }, 441 { FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" }, 442 { FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" }, 443 { FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" }, 444 { FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" }, 445 { FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" }, 446 { FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" }, 447 { 0, NULL } |
324}; 325 | 448}; 449 |
326#define REPORT_TYPE_IE 0x01 327#define LINK_VERIFY_IE_91 0x19 328#define LINK_VERIFY_IE_94 0x03 329#define PVC_STATUS_IE 0x07 | 450#define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0 451#define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1 452#define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2 |
330 | 453 |
331#define MAX_IE_SIZE | 454struct tok fr_lmi_report_type_ie_values[] = { 455 { FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" }, 456 { FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" }, 457 { FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" }, 458 { 0, NULL } 459}; |
332 | 460 |
333struct common_ie_header { 334 u_char ie_id; 335 u_char ie_len; | 461/* array of 16 codepages - currently we only support codepage 5 */ 462static struct tok *fr_q933_ie_codesets[] = { 463 NULL, 464 NULL, 465 NULL, 466 NULL, 467 NULL, 468 fr_q933_ie_values_codeset5, 469 NULL, 470 NULL, 471 NULL, 472 NULL, 473 NULL, 474 NULL, 475 NULL, 476 NULL, 477 NULL, 478 NULL |
336}; 337 | 479}; 480 |
338#define FULL_STATUS 0 339#define LINK_VERIFY 1 340#define ASYNC_PVC 2 | |
341 | 481 |
482struct common_ie_header { 483 u_int8_t ie_id; 484 u_int8_t ie_len; 485}; |
|
342 343void | 486 487void |
344q933_print(const u_char *p, int length) | 488q933_print(const u_char *p, u_int length) |
345{ | 489{ |
346 struct q933_header *header = (struct q933_header *)(p+1); | |
347 const u_char *ptemp = p; | 490 const u_char *ptemp = p; |
348 int ie_type, ie_len; 349 char *decode_str, temp_str[255]; | |
350 struct common_ie_header *ie_p; | 491 struct common_ie_header *ie_p; |
492 int olen; 493 int is_ansi = 0; 494 u_int dlci,codeset; 495 496 if (length < 9) { /* shortest: Q.933a LINK VERIFY */ 497 printf("[|q.933]"); 498 return; 499 } 500 501 codeset = p[2]&0x0f; /* extract the codeset */ 502 503 if (p[2] == MSG_ANSI_LOCKING_SHIFT) 504 is_ansi = 1; |
|
351 | 505 |
506 printf("%s", eflag ? "" : "Q.933, "); |
|
352 353 /* printing out header part */ | 507 508 /* printing out header part */ |
354 printf("Call Ref: %02x, MSG Type: %02x", 355 header->call_ref, header->msg_type); 356 switch(header->msg_type) { 357 case MSG_TYPE_STATUS: 358 decode_str = "STATUS REPLY"; 359 break; 360 case MSG_TYPE_STATUS_ENQ: 361 decode_str = "STATUS ENQUIRY"; 362 break; 363 default: 364 decode_str = "UNKNOWN MSG Type"; 365 } 366 printf(" %s\n", decode_str); | 509 printf(is_ansi ? "ANSI" : "CCITT "); |
367 | 510 |
368 length = length - 3; 369 ptemp = ptemp + 3; | 511 if (p[0]) 512 printf(", Call Ref: 0x%02x", p[0]); 513 514 if (vflag) 515 printf(", %s (0x%02x), length %u", 516 tok2str(fr_q933_msg_values,"unknown message",p[1]), 517 p[1], 518 length); 519 else 520 printf(", %s", 521 tok2str(fr_q933_msg_values,"unknown message 0x%02x",p[1])); 522 523 olen = length; /* preserve the original length for non verbose mode */ 524 525 if (length < (u_int)(2 - is_ansi)) { 526 printf("[|q.933]"); 527 return; 528 } 529 length -= 2 - is_ansi; 530 ptemp += 2 + is_ansi; |
370 371 /* Loop through the rest of IE */ | 531 532 /* Loop through the rest of IE */ |
372 while( length > 0 ) { 373 if( ptemp[0] & ONE_BYTE_IE_MASK ) { 374 ie_len = 1; 375 printf("\t\tOne byte IE: %02x, Content %02x\n", 376 (*ptemp & 0x70)>>4, (*ptemp & 0x0F)); 377 length--; 378 ptemp++; 379 } 380 else { /* Multi-byte IE */ | 533 while (length > sizeof(struct common_ie_header)) { |
381 ie_p = (struct common_ie_header *)ptemp; | 534 ie_p = (struct common_ie_header *)ptemp; |
382 switch (ie_p->ie_id) { 383 case REPORT_TYPE_IE: 384 switch(ptemp[2]) { 385 case FULL_STATUS: 386 decode_str = "FULL STATUS"; 387 break; 388 case LINK_VERIFY: 389 decode_str = "LINK VERIFY"; 390 break; 391 case ASYNC_PVC: 392 decode_str = "Async PVC Status"; 393 break; 394 default: 395 decode_str = "Reserved Value"; 396 } 397 break; 398 case LINK_VERIFY_IE_91: 399 case LINK_VERIFY_IE_94: 400 snprintf(temp_str, sizeof(temp_str), "TX Seq: %3d, RX Seq: %3d", 401 ptemp[2], ptemp[3]); 402 decode_str = temp_str; 403 break; 404 case PVC_STATUS_IE: 405 snprintf(temp_str,sizeof(temp_str), "DLCI %d: status %s %s", 406 ((ptemp[2]&0x3f)<<4)+ ((ptemp[3]&0x78)>>3), 407 ptemp[4] & 0x8 ?"new,":" ", 408 ptemp[4] & 0x2 ?"Active":"Inactive"); 409 break; 410 default: 411 decode_str = "Non-decoded Value"; | 535 if (length < sizeof(struct common_ie_header) || 536 length < sizeof(struct common_ie_header) + ie_p->ie_len) { 537 if (vflag) /* not bark if there is just a trailer */ 538 printf("\n[|q.933]"); 539 else 540 printf(", length %u",olen); 541 return; |
412 } | 542 } |
413 printf("\t\tIE: %02X Len: %d, %s\n", 414 ie_p->ie_id, ie_p->ie_len, decode_str); 415 length = length - ie_p->ie_len - 2; 416 ptemp = ptemp + ie_p->ie_len + 2; 417 } 418 } 419 420} | |
421 | 543 |
544 /* lets do the full IE parsing only in verbose mode 545 * however some IEs (DLCI Status, Link Verify) 546 * are also intereststing in non-verbose mode */ 547 if (vflag) 548 printf("\n\t%s IE (%u), length %u: ", 549 tok2str(fr_q933_ie_codesets[codeset],"unknown",ie_p->ie_id), 550 ie_p->ie_id, 551 ie_p->ie_len); 552 553 switch (ie_p->ie_id) { |
|
422 | 554 |
555 case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ 556 case FR_LMI_CCITT_REPORT_TYPE_IE: 557 if (vflag) 558 printf("%s (%u)", 559 tok2str(fr_lmi_report_type_ie_values,"unknown",ptemp[2]), 560 ptemp[2]); 561 break; |
|
423 | 562 |
563 case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */ 564 case FR_LMI_CCITT_LINK_VERIFY_IE: 565 case FR_LMI_ANSI_LINK_VERIFY_IE_91: 566 if (!vflag) 567 printf(", "); 568 printf("TX Seq: %3d, RX Seq: %3d", ptemp[2], ptemp[3]); 569 break; 570 case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ 571 case FR_LMI_CCITT_PVC_STATUS_IE: 572 if (!vflag) 573 printf(", "); 574 /* now parse the DLCI information element. */ 575 if ((ie_p->ie_len < 3) || 576 (ptemp[2] & 0x80) || 577 ((ie_p->ie_len == 3) && !(ptemp[3] & 0x80)) || 578 ((ie_p->ie_len == 4) && ((ptemp[3] & 0x80) || !(ptemp[4] & 0x80))) || 579 ((ie_p->ie_len == 5) && ((ptemp[3] & 0x80) || (ptemp[4] & 0x80) || 580 !(ptemp[5] & 0x80))) || 581 (ie_p->ie_len > 5) || 582 !(ptemp[ie_p->ie_len + 1] & 0x80)) 583 printf("Invalid DLCI IE"); 584 585 dlci = ((ptemp[2] & 0x3F) << 4) | ((ptemp[3] & 0x78) >> 3); 586 if (ie_p->ie_len == 4) 587 dlci = (dlci << 6) | ((ptemp[4] & 0x7E) >> 1); 588 else if (ie_p->ie_len == 5) 589 dlci = (dlci << 13) | (ptemp[4] & 0x7F) | ((ptemp[5] & 0x7E) >> 1); |
|
424 | 590 |
591 printf("DLCI %u: status %s%s", dlci, 592 ptemp[ie_p->ie_len + 1] & 0x8 ? "New, " : "", 593 ptemp[ie_p->ie_len + 1] & 0x2 ? "Active" : "Inactive"); 594 break; 595 596 default: 597 if (vflag <= 1) 598 print_unknown_data(ptemp+2,"\n\t",ie_p->ie_len); 599 break; 600 } |
|
425 | 601 |
602 /* do we want to see a hexdump of the IE ? */ 603 if (vflag> 1) 604 print_unknown_data(ptemp+2,"\n\t ",ie_p->ie_len); |
|
426 | 605 |
606 length = length - ie_p->ie_len - 2; 607 ptemp = ptemp + ie_p->ie_len + 2; 608 } 609 if (!vflag) 610 printf(", length %u",olen); 611} |
|