MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-lapsat.c
blob51d236d76edfb73ab8d3fc3b3452c973eac4f0c2
1 /* packet-lapsat.c
3 * Routines for GMR-1 LAPSat dissection in wireshark.
5 * Link Access Procedures (LAP) for the Satellite Channel (LAPSat).
6 * LAPSat is the protocol for signalling transfer between an Access
7 * Terminal (MES) and a Gateway Station (GS) in the GeoMobile (GMR-1) network.
9 * Copyright (c) 2011 Sylvain Munaut <tnt@246tNt.com>
10 * Inspired on LAPDm code by Duncan Salerno <duncan.salerno@googlemail.com>
12 * References:
13 * [1] ETSI TS 101 376-4-6 V1.2.1 - GMR-1 04.006
15 * $Id$
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "config.h"
38 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/reassemble.h>
41 #include <epan/wmem/wmem.h>
44 static int proto_lapsat = -1;
46 static reassembly_table lapsat_reassembly_table;
48 static dissector_table_t lapsat_sapi_dissector_table;
50 static dissector_handle_t data_handle;
52 static gint ett_lapsat = -1;
53 static gint ett_lapsat_address = -1;
54 static gint ett_lapsat_control = -1;
55 static gint ett_lapsat_fragment = -1;
56 static gint ett_lapsat_fragments = -1;
58 static int hf_lapsat_addr = -1;
59 static int hf_lapsat_addr_sst = -1;
60 static int hf_lapsat_addr_cr = -1;
61 static int hf_lapsat_addr_sapi = -1;
62 static int hf_lapsat_addr_si = -1;
63 static int hf_lapsat_addr_lpd = -1;
64 static int hf_lapsat_addr_lfi = -1;
66 static int hf_lapsat_ctl = -1;
67 static int hf_lapsat_ctl_ftype_i = -1;
68 static int hf_lapsat_ctl_ftype_s_u = -1;
69 static int hf_lapsat_ctl_s_ftype = -1;
70 static int hf_lapsat_ctl_u_modifier_cmd = -1;
71 static int hf_lapsat_ctl_u_modifier_resp = -1;
72 static int hf_lapsat_ctl_n_r = -1;
73 static int hf_lapsat_ctl_n_s = -1;
74 static int hf_lapsat_ctl_p = -1;
75 static int hf_lapsat_ctl_f = -1;
76 static int hf_lapsat_ctl_mii = -1;
78 static int hf_lapsat_payload_last_nibble = -1;
80 static int hf_lapsat_len = -1;
82 static int hf_lapsat_fragments = -1;
83 static int hf_lapsat_fragment = -1;
84 static int hf_lapsat_fragment_overlap = -1;
85 static int hf_lapsat_fragment_overlap_conflicts = -1;
86 static int hf_lapsat_fragment_multiple_tails = -1;
87 static int hf_lapsat_fragment_too_long_fragment = -1;
88 static int hf_lapsat_fragment_error = -1;
89 static int hf_lapsat_fragment_count = -1;
90 static int hf_lapsat_reassembled_in = -1;
91 static int hf_lapsat_reassembled_length = -1;
94 #define LAPSAT_HEADER_LEN 3
96 #define LAPSAT_SAPI_RR_CC_MM 0
97 #define LAPSAT_SAPI_SMS 3
101 * Address field bits
104 #define LAPSAT_SST 0x01 /* SACCH status bit */
105 #define LAPSAT_CR 0x02 /* Command/Response bit */
106 #define LAPSAT_SAPI_MSK 0x0c /* Service Access Point Identifier */
107 #define LAPSAT_SAPI_SHIFT 2
108 #define LAPSAT_SI 0x10 /* Segment Indicator */
109 #define LAPSAT_LPD_MSK 0x60 /* DL for LAPSat or SMS-CB */
110 #define LAPSAT_LPD_SHIFT 6
111 #define LAPSAT_LFI 0x80 /* Length Field Indicator */
113 static const value_string lapsat_addr_sst_vals[] = {
114 { 0, "FACCH and all other messages" },
115 { 1, "SACCH message" },
116 { 0 , NULL }
119 static const value_string lapsat_addr_sapi_vals[] = {
120 { LAPSAT_SAPI_RR_CC_MM, "RR/MM/CC" },
121 { LAPSAT_SAPI_SMS, "SMS/SS" },
122 { 0, NULL }
125 static const value_string lapsat_addr_lpd_vals[] = {
126 { 0, "Normal GMR-1" },
127 { 1, "Cell broadcast service" },
128 { 0, NULL }
131 static const value_string lapsat_addr_si_vals[] = {
132 { 0, "Complete/Last Segment of L3 message" },
133 { 1, "Segment only" },
134 { 0, NULL }
137 static const value_string lapsat_addr_lfi_vals[] = {
138 { 0, "Length Field not present (all data valid)" },
139 { 1, "Length Field present" },
140 { 0, NULL }
145 * Frame types
148 #define LAPSAT_CTL_TYPE_S 0x001
149 #define LAPSAT_CTL_TYPE_U 0x003
150 #define LAPSAT_CTL_TYPE_S_U_MSK 0x003
152 #define LAPSAT_CTL_TYPE_I 0x000
153 #define LAPSAT_CTL_TYPE_I_MSK 0x001
155 static const value_string lapsat_ctl_ftype_vals[] = {
156 { LAPSAT_CTL_TYPE_I, "Information frame" },
157 { LAPSAT_CTL_TYPE_S, "Supervisory frame" },
158 { LAPSAT_CTL_TYPE_U, "Unnumbered frame" },
159 { 0, NULL }
164 * S-format frame types
167 #define LAPSAT_CTL_S_FTYPE_MSK 0x00c
169 #define LAPSAT_RR 0x000
170 #define LAPSAT_GREJ 0x008
172 static const value_string lapsat_ctl_s_ftype_vals[] = {
173 { LAPSAT_RR >> 2, "Receiver ready" },
174 { LAPSAT_GREJ >> 2, "Group reject" },
175 { 0, NULL}
180 * U-format modifiers
183 #define LAPSAT_CTL_U_MODIFIER_MSK 0x18c
185 #define LAPSAT_SABM 0x08c
186 #define LAPSAT_DM 0x00c
187 #define LAPSAT_DISC 0x100
188 #define LAPSAT_UA 0x180
189 #define LAPSAT_UI 0x000
191 static const value_string lapsat_ctl_u_modifier_vals_cmd[] = {
192 { LAPSAT_SABM >> 2, "Set Asynchronous Balanced Mode" },
193 { LAPSAT_DISC >> 2, "Disconnect" },
194 { LAPSAT_UI >> 2, "Unnumbered Information" },
195 { 0, NULL}
198 static const value_string lapsat_ctl_u_modifier_vals_resp[] = {
199 { LAPSAT_DM >> 2, "Disconnected mode" },
200 { LAPSAT_UA >> 2, "Unnumbered Acknowledge" },
201 { 0, NULL}
206 * Control fields
209 #define LAPSAT_CTL_P_F 0x040
210 #define LAPSAT_CTL_MII 0x200
211 #define LAPSAT_CTL_N_R_MSK 0xf80
212 #define LAPSAT_CTL_N_R_SHIFT 7
213 #define LAPSAT_CTL_N_S_MSK 0x03e
214 #define LAPSAT_CTL_N_S_SHIFT 1
218 * Fragment stuff
221 static const value_string true_false_vals[] = {
222 { 0, "False" },
223 { 1, "True" },
224 { 0, NULL },
228 static const fragment_items lapsat_frag_items = {
229 /* Fragment subtrees */
230 &ett_lapsat_fragment,
231 &ett_lapsat_fragments,
232 /* Fragment fields */
233 &hf_lapsat_fragments,
234 &hf_lapsat_fragment,
235 &hf_lapsat_fragment_overlap,
236 &hf_lapsat_fragment_overlap_conflicts,
237 &hf_lapsat_fragment_multiple_tails,
238 &hf_lapsat_fragment_too_long_fragment,
239 &hf_lapsat_fragment_error,
240 &hf_lapsat_fragment_count,
241 /* Reassembled in field */
242 &hf_lapsat_reassembled_in,
243 /* Reassembled length field */
244 &hf_lapsat_reassembled_length,
245 /* Reassembled data field */
246 NULL,
247 /* Tag */
248 "fragments"
251 static void
252 lapsat_defragment_init(void)
254 reassembly_table_init(&lapsat_reassembly_table,
255 &addresses_reassembly_table_functions);
260 * Main dissection functions
263 static guint16
264 dissect_control(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int is_response)
266 proto_tree *ctl_tree;
267 proto_item *ctl_ti;
268 guint16 ctl, poll_final;
269 const char *frame_type;
270 char *info;
272 info = (char *)wmem_alloc(wmem_packet_scope(), 80);
274 /* Grab complete control field */
275 ctl = tvb_get_ntohs(tvb, 1) >> 4;
277 poll_final = ctl & LAPSAT_CTL_P_F;
279 /* Generate small 'descriptive' text */
280 switch (ctl & LAPSAT_CTL_TYPE_S_U_MSK) {
281 case LAPSAT_CTL_TYPE_S:
283 * Supervisory frame.
285 switch (ctl & LAPSAT_CTL_S_FTYPE_MSK) {
286 case LAPSAT_RR:
287 frame_type = "RR";
288 break;
289 case LAPSAT_GREJ:
290 frame_type = "GREJ";
291 break;
292 default:
293 frame_type = "Unknown";
294 break;
297 g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
298 poll_final ? (is_response ? " F" : " P") : "",
299 frame_type,
300 (ctl & LAPSAT_CTL_N_R_MSK) >> LAPSAT_CTL_N_R_SHIFT);
302 break;
304 case LAPSAT_CTL_TYPE_U:
306 * Unnumbered frame
308 switch (ctl & LAPSAT_CTL_U_MODIFIER_MSK) {
309 case LAPSAT_SABM:
310 frame_type = (ctl & LAPSAT_CTL_MII) ?
311 "SABM, MII=1" : "SABM, MII=0";
312 break;
313 case LAPSAT_DM:
314 frame_type = "DM";
315 break;
316 case LAPSAT_DISC:
317 frame_type = "DISC";
318 break;
319 case LAPSAT_UA:
320 frame_type = "UA";
321 break;
322 case LAPSAT_UI:
323 frame_type = "UI";
324 break;
325 default:
326 frame_type = "Unknown";
327 break;
330 g_snprintf(info, 80, "U%s, func=%s",
331 poll_final ? (is_response ? " F" : " P") : "",
332 frame_type);
334 break;
336 default:
338 * Information frame
340 g_snprintf(info, 80, "I%s, N(R)=%u, N(S)=%u",
341 poll_final ? " P" : "",
342 (ctl & LAPSAT_CTL_N_R_MSK) >> LAPSAT_CTL_N_R_SHIFT,
343 (ctl & LAPSAT_CTL_N_S_MSK) >> LAPSAT_CTL_N_S_SHIFT);
345 break;
348 /* Add info */
349 col_add_str(pinfo->cinfo, COL_INFO, info);
351 /* Create item & subtree */
352 ctl_ti = proto_tree_add_uint_format_value(
353 tree, hf_lapsat_ctl,
354 tvb, 1, 2, (guint32)ctl,
355 "%s (0x%03x)", info, ctl
358 ctl_tree = proto_item_add_subtree(ctl_ti, ett_lapsat_control);
360 /* Add all fields */
361 switch (ctl & LAPSAT_CTL_TYPE_S_U_MSK) {
362 case LAPSAT_CTL_TYPE_S:
364 * Supervisory frame.
367 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_ftype_s_u,
368 tvb, 1, 2, ENC_BIG_ENDIAN);
370 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_s_ftype,
371 tvb, 1, 2, ENC_BIG_ENDIAN);
373 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_n_r,
374 tvb, 1, 2, ENC_BIG_ENDIAN);
376 if (poll_final)
377 proto_tree_add_item(ctl_tree,
378 is_response ? hf_lapsat_ctl_f : hf_lapsat_ctl_p,
379 tvb, 1, 2, ENC_BIG_ENDIAN);
381 break;
383 case LAPSAT_CTL_TYPE_U:
385 * Unnumbered frame
388 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_ftype_s_u,
389 tvb, 1, 2, ENC_BIG_ENDIAN);
391 proto_tree_add_item(ctl_tree,
392 is_response ? hf_lapsat_ctl_u_modifier_resp :
393 hf_lapsat_ctl_u_modifier_cmd,
394 tvb, 1, 2, ENC_BIG_ENDIAN);
396 if (poll_final)
397 proto_tree_add_item(ctl_tree,
398 is_response ? hf_lapsat_ctl_f : hf_lapsat_ctl_p,
399 tvb, 1, 2, ENC_BIG_ENDIAN);
401 if (((ctl & LAPSAT_CTL_U_MODIFIER_MSK) == LAPSAT_SABM) &&
402 (ctl & LAPSAT_CTL_MII))
403 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_mii,
404 tvb, 1, 2, ENC_BIG_ENDIAN);
406 break;
408 default:
410 * Information frame
413 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_ftype_i,
414 tvb, 1, 2, ENC_BIG_ENDIAN);
416 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_n_r,
417 tvb, 1, 2, ENC_BIG_ENDIAN);
419 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_n_s,
420 tvb, 1, 2, ENC_BIG_ENDIAN);
422 if (poll_final)
423 proto_tree_add_item(ctl_tree, hf_lapsat_ctl_p,
424 tvb, 1, 2, ENC_BIG_ENDIAN);
426 break;
429 return ctl;
432 static void
433 dissect_lapsat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
435 proto_tree *lapsat_tree, *addr_tree;
436 proto_item *lapsat_ti, *addr_ti;
437 tvbuff_t *payload;
438 guint8 addr, sapi, cr;
439 guint16 control;
440 unsigned int hlen, is_response = 0, plen;
442 /* Check that there's enough data */
443 if (tvb_length(tvb) < LAPSAT_HEADER_LEN)
444 return;
446 /* Set protocol column */
447 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPSat");
449 /* Grab a couple of fields */
450 addr = tvb_get_guint8(tvb, 0);
452 sapi = (addr & LAPSAT_SAPI_MSK) >> LAPSAT_SAPI_SHIFT;
454 cr = addr & LAPSAT_CR;
455 if (pinfo->p2p_dir == P2P_DIR_RECV) {
456 is_response = cr ? FALSE : TRUE;
458 else if (pinfo->p2p_dir == P2P_DIR_SENT) {
459 is_response = cr ? TRUE : FALSE;
462 hlen = LAPSAT_HEADER_LEN;
464 if (addr & LAPSAT_LFI)
465 hlen++;
467 /* FIXME if "S func=GREJ", extend */
469 /* Create LAPSat tree */
470 lapsat_ti = proto_tree_add_item(tree, proto_lapsat, tvb, 0, hlen, ENC_BIG_ENDIAN);
471 lapsat_tree = proto_item_add_subtree(lapsat_ti, ett_lapsat);
473 /* Dissect address field */
474 addr_ti = proto_tree_add_item(lapsat_tree, hf_lapsat_addr, tvb, 0, 1, ENC_BIG_ENDIAN);
475 addr_tree = proto_item_add_subtree(addr_ti, ett_lapsat_address);
477 proto_tree_add_item(addr_tree, hf_lapsat_addr_sst, tvb, 0, 1, ENC_BIG_ENDIAN);
478 proto_tree_add_item(addr_tree, hf_lapsat_addr_cr, tvb, 0, 1, ENC_BIG_ENDIAN);
479 proto_tree_add_item(addr_tree, hf_lapsat_addr_sapi, tvb, 0, 1, ENC_BIG_ENDIAN);
480 proto_tree_add_item(addr_tree, hf_lapsat_addr_si, tvb, 0, 1, ENC_BIG_ENDIAN);
481 proto_tree_add_item(addr_tree, hf_lapsat_addr_lpd, tvb, 0, 1, ENC_BIG_ENDIAN);
482 proto_tree_add_item(addr_tree, hf_lapsat_addr_lfi, tvb, 0, 1, ENC_BIG_ENDIAN);
484 /* Dissect control field */
485 control = dissect_control(tvb, pinfo, lapsat_tree, is_response);
487 /* Last payload nibble */
488 proto_tree_add_item(lapsat_tree, hf_lapsat_payload_last_nibble, tvb, 2, 1, ENC_BIG_ENDIAN);
490 /* Optional length field */
491 if (addr & LAPSAT_LFI)
492 proto_tree_add_item(lapsat_tree, hf_lapsat_len, tvb, 3, 1, ENC_BIG_ENDIAN);
494 /* If frame is "S func=GREJ", then add Na(R) & Nb(R) */
495 /* FIXME */
497 /* Get the payload */
498 plen = (addr & LAPSAT_LFI) ?
499 tvb_get_guint8(tvb, 3) : tvb_length(tvb) - hlen;
501 if (!plen)
502 return; /* No point in doing more if there is no payload */
504 DISSECTOR_ASSERT((plen + hlen) <= tvb_length(tvb));
506 if ((plen + hlen) == tvb_length(tvb)) {
507 /* Need to integrate the last nibble */
508 guint8 *data = (guint8 *)tvb_memdup(NULL, tvb, hlen, plen);
509 data[plen-1] |= tvb_get_guint8(tvb, 2) << 4;
510 payload = tvb_new_child_real_data(tvb, data, plen, plen);
511 tvb_set_free_cb(payload, g_free);
512 } else {
513 /* Last nibble doesn't need merging */
514 payload = tvb_new_subset(tvb, hlen, plen, -1);
517 add_new_data_source(pinfo, payload, "LAPSat Payload");
519 /* Handle fragments */
520 if ((control & LAPSAT_CTL_TYPE_I_MSK) == LAPSAT_CTL_TYPE_I) {
522 * Potentially fragmented I frames
524 fragment_head *fd_m = NULL;
525 tvbuff_t *reassembled = NULL;
526 guint32 fragment_id;
527 gboolean save_fragmented = pinfo->fragmented;
529 /* Is this a fragment ? */
530 pinfo->fragmented = !!(addr & LAPSAT_SI);
532 /* Rely on caller to provide a way to group fragments */
533 fragment_id = (pinfo->circuit_id << 3) | (sapi << 1) | pinfo->p2p_dir;
535 /* Fragment reconstruction helpers */
536 fd_m = fragment_add_seq_next(
537 &lapsat_reassembly_table,
538 payload, 0,
539 pinfo,
540 fragment_id, /* To group fragments */
541 NULL,
542 plen,
543 !!(addr & LAPSAT_SI) /* More fragment ? */
546 reassembled = process_reassembled_data(
547 payload, 0, pinfo,
548 "Reassembled LAPSat", fd_m, &lapsat_frag_items,
549 NULL, lapsat_tree
552 /* Reassembled into this packet ? */
553 if (fd_m && pinfo->fd->num == fd_m->reassembled_in) {
554 /* Yes, so handoff to upper layers */
555 if (!dissector_try_uint(lapsat_sapi_dissector_table, sapi,
556 reassembled, pinfo, tree))
557 call_dissector(data_handle, reassembled, pinfo, tree);
558 } else {
559 /* No, just add infos */
560 col_append_str(pinfo->cinfo, COL_INFO, " (Fragment)");
561 proto_tree_add_text(lapsat_tree, payload, 0, -1, "Fragment Data");
564 /* Now reset fragmentation information in pinfo */
565 pinfo->fragmented = save_fragmented;
566 } else {
568 * Whole frame
570 if (!dissector_try_uint(lapsat_sapi_dissector_table, sapi, payload, pinfo, tree))
571 call_dissector(data_handle, payload, pinfo, tree);
575 void
576 proto_register_lapsat(void)
578 static hf_register_info hf[] = {
579 /* Address field */
580 { &hf_lapsat_addr,
581 { "Address Field", "lapsat.address",
582 FT_UINT8, BASE_HEX, NULL, 0x00,
583 NULL, HFILL },
585 { &hf_lapsat_addr_sst,
586 { "SST", "lapsat.address.sst",
587 FT_UINT8, BASE_DEC, VALS(lapsat_addr_sst_vals), LAPSAT_SST,
588 "SACCH status bit", HFILL },
590 { &hf_lapsat_addr_cr,
591 { "C/R", "lapsat.address.cr",
592 FT_UINT8, BASE_DEC, NULL, LAPSAT_CR,
593 "Command/response bit", HFILL },
595 { &hf_lapsat_addr_sapi,
596 { "SAPI", "lapsat.address.sapi",
597 FT_UINT8, BASE_DEC, VALS(lapsat_addr_sapi_vals), LAPSAT_SAPI_MSK,
598 "Service access point identifier", HFILL },
600 { &hf_lapsat_addr_si,
601 { "SI", "lapsat.address.si",
602 FT_UINT8, BASE_DEC, VALS(lapsat_addr_si_vals), LAPSAT_SI,
603 "Segment Indicator", HFILL },
605 { &hf_lapsat_addr_lpd,
606 { "LPD", "lapsat.address.lpd",
607 FT_UINT8, BASE_DEC, VALS(lapsat_addr_lpd_vals), LAPSAT_LPD_MSK,
608 "Link Protocol Discriminator", HFILL },
610 { &hf_lapsat_addr_lfi,
611 { "LFI", "lapsat.address.lfi",
612 FT_UINT8, BASE_DEC, VALS(lapsat_addr_lfi_vals), LAPSAT_LFI,
613 "Length Field Indicator", HFILL },
616 /* Control field */
617 { &hf_lapsat_ctl,
618 { "Control Field", "lapsat.control_field",
619 FT_UINT16, BASE_HEX, NULL, 0x00,
620 NULL, HFILL }
622 { &hf_lapsat_ctl_ftype_i,
623 { "Frame type", "lapsat.control.ftype",
624 FT_UINT16, BASE_DEC, VALS(lapsat_ctl_ftype_vals), LAPSAT_CTL_TYPE_I_MSK << 4,
625 NULL, HFILL }
627 { &hf_lapsat_ctl_ftype_s_u,
628 { "Frame type", "lapsat.control.ftype",
629 FT_UINT16, BASE_DEC, VALS(lapsat_ctl_ftype_vals), LAPSAT_CTL_TYPE_S_U_MSK << 4,
630 NULL, HFILL }
632 { &hf_lapsat_ctl_s_ftype,
633 { "Supervisory frame type", "lapsat.control.s_ftype",
634 FT_UINT16, BASE_DEC, VALS(lapsat_ctl_s_ftype_vals), LAPSAT_CTL_S_FTYPE_MSK << 4,
635 NULL, HFILL }
637 { &hf_lapsat_ctl_u_modifier_cmd,
638 { "Command", "lapsat.control.u_modifier_cmd",
639 FT_UINT16, BASE_HEX, VALS(lapsat_ctl_u_modifier_vals_cmd),
640 LAPSAT_CTL_U_MODIFIER_MSK << 4,
641 NULL, HFILL }
643 { &hf_lapsat_ctl_u_modifier_resp,
644 { "Response", "lapsat.control.u_modifier_resp",
645 FT_UINT16, BASE_HEX, VALS(lapsat_ctl_u_modifier_vals_resp),
646 LAPSAT_CTL_U_MODIFIER_MSK << 4,
647 NULL, HFILL }
649 { &hf_lapsat_ctl_n_r,
650 { "N(R)", "lapsat.control.n_r",
651 FT_UINT16, BASE_DEC, NULL, LAPSAT_CTL_N_R_MSK << 4,
652 NULL, HFILL }
654 { &hf_lapsat_ctl_n_s,
655 { "N(S)", "lapsat.control.n_s",
656 FT_UINT16, BASE_DEC, NULL, LAPSAT_CTL_N_S_MSK << 4,
657 NULL, HFILL }
659 { &hf_lapsat_ctl_p,
660 { "Poll", "lapsat.control.p",
661 FT_UINT16, BASE_DEC, VALS(true_false_vals), LAPSAT_CTL_P_F << 4,
662 NULL, HFILL }
664 { &hf_lapsat_ctl_f,
665 { "Final", "lapsat.control.f",
666 FT_UINT16, BASE_DEC, VALS(true_false_vals), LAPSAT_CTL_P_F << 4,
667 NULL, HFILL }
669 { &hf_lapsat_ctl_mii,
670 { "MII", "lapsat.control.mii",
671 FT_UINT16, BASE_DEC, VALS(true_false_vals), LAPSAT_CTL_MII << 4,
672 "Mobile Identity Indicator", HFILL }
675 /* Payload last nibble */
676 { &hf_lapsat_payload_last_nibble,
677 { "Payload last nibble", "lapsat.payload.last_nibble",
678 FT_UINT8, BASE_HEX, NULL, 0x0f,
679 NULL, HFILL }
682 /* Length field */
683 { &hf_lapsat_len,
684 { "Length Field", "lapsat.length",
685 FT_UINT8, BASE_DEC, NULL, 0x00,
686 NULL, HFILL },
689 /* Fragment reassembly */
690 { &hf_lapsat_fragments,
691 { "Message fragments", "lapsat.fragments",
692 FT_NONE, BASE_NONE, NULL, 0x00,
693 "LAPSat Message fragments", HFILL }
695 { &hf_lapsat_fragment,
696 { "Message fragment", "lapsat.fragment",
697 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
698 "LAPSat Message fragment", HFILL }
700 { &hf_lapsat_fragment_overlap,
701 { "Message fragment overlap", "lapsat.fragment.overlap",
702 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
703 "LAPSat Message fragment overlaps with other fragment(s)", HFILL }
705 { &hf_lapsat_fragment_overlap_conflicts,
706 { "Message fragment overlapping with conflicting data",
707 "lapsat.fragment.overlap.conflicts",
708 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
709 "LAPSat Message fragment overlaps with conflicting data", HFILL }
711 { &hf_lapsat_fragment_multiple_tails,
712 { "Message has multiple tail fragments", "lapsat.fragment.multiple_tails",
713 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
714 "LAPSat Message fragment has multiple tail fragments", HFILL }
716 { &hf_lapsat_fragment_too_long_fragment,
717 { "Message fragment too long", "lapsat.fragment.too_long_fragment",
718 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
719 "LAPSat Message fragment data goes beyond the packet end", HFILL }
721 { &hf_lapsat_fragment_error,
722 { "Message defragmentation error", "lapsat.fragment.error",
723 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
724 "LAPSat Message defragmentation error due to illegal fragments", HFILL }
726 { &hf_lapsat_fragment_count,
727 { "Message fragment count", "lapsat.fragment.count",
728 FT_UINT32, BASE_DEC, NULL, 0x00,
729 NULL, HFILL }
731 { &hf_lapsat_reassembled_in,
732 { "Reassembled in", "lapsat.reassembled.in",
733 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
734 "LAPSat Message has been reassembled in this packet.", HFILL }
736 { &hf_lapsat_reassembled_length,
737 { "Reassembled LAPSat length", "lapsat.reassembled.length",
738 FT_UINT32, BASE_DEC, NULL, 0x00,
739 "The total length of the reassembled payload", HFILL }
743 static gint *ett[] = {
744 &ett_lapsat,
745 &ett_lapsat_address,
746 &ett_lapsat_control,
747 &ett_lapsat_fragment,
748 &ett_lapsat_fragments,
751 proto_lapsat = proto_register_protocol("Link Access Procedure, Satellite channel (LAPSat)", "LAPSat", "lapsat");
753 proto_register_field_array (proto_lapsat, hf, array_length(hf));
754 proto_register_subtree_array(ett, array_length(ett));
756 register_dissector("lapsat", dissect_lapsat, proto_lapsat);
758 lapsat_sapi_dissector_table = register_dissector_table("lapsat.sapi", "LAPSat SAPI", FT_UINT8, BASE_DEC);
760 register_init_routine (lapsat_defragment_init);
763 void
764 proto_reg_handoff_lapsat(void)
766 data_handle = find_dissector("data");