Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-osi-options.c
Line
Count
Source
1
/* packet-osi-options.c
2
 * Routines for the decode of ISO/OSI option part
3
 * Covers:
4
 * ISO  8473 CLNP (ConnectionLess Mode Network Service Protocol)
5
 * ISO 10589 ISIS (Intradomain Routing Information Exchange Protocol)
6
 * ISO  9542 ESIS (End System To Intermediate System Routing Exchange Protocol)
7
 *
8
 * Ralf Schneider <Ralf.Schneider@t-online.de>
9
 *
10
 * Wireshark - Network traffic analyzer
11
 * By Gerald Combs <gerald@wireshark.org>
12
 * Copyright 1998 Gerald Combs
13
 *
14
 * SPDX-License-Identifier: GPL-2.0-or-later
15
 */
16
17
#include "config.h"
18
19
#include <epan/packet.h>
20
#include <epan/expert.h>
21
#include <epan/decode_as.h>
22
#include "packet-osi.h"
23
#include "packet-osi-options.h"
24
25
extern void proto_register_osi_options(void);
26
27
6
#define OSI_OPT_SECURITY                0xc5
28
4
#define OSI_OPT_QOS_MAINTANANCE         0xc3
29
16
#define OSI_OPT_PRIORITY                0xcd
30
2
#define OSI_OPT_ADDRESS_MASK            0xe1
31
14
#define OSI_OPT_SNPA_MASK               0xe2
32
2
#define OSI_OPT_ES_CONFIG_TIMER         0xc6
33
34
16
#define OSI_OPT_MAX_PRIORITY            0x0e
35
36
6
#define OSI_OPT_PADDING                 0xcc
37
41
#define OSI_OPT_SOURCE_ROUTING          0xc8
38
52
#define OSI_OPT_RECORD_OF_ROUTE         0xcb
39
12
#define OSI_OPT_REASON_OF_DISCARD       0xc1
40
41
16
#define OSI_OPT_SEC_MASK                0xc0
42
2
#define OSI_OPT_SEC_RESERVED            0x00
43
2
#define OSI_OPT_SEC_SRC_ADR_SPEC        0x01
44
2
#define OSI_OPT_SEC_DST_ADR_SPEC        0x02
45
4
#define OSI_OPT_SEC_GLOBAL_UNIQUE       0x03
46
47
20
#define OSI_OPT_QOS_MASK                0xc0
48
#define OSI_OPT_QOS_RESERVED            0x00
49
#define OSI_OPT_QOS_SRC_ADR_SPEC        0x01
50
#define OSI_OPT_QOS_DST_ADR_SPEC        0x02
51
4
#define OSI_OPT_QOS_GLOBAL_UNIQUE       0x03
52
53
#define OSI_OPT_QOS_SUB_MASK            0x3f
54
16
#define OSI_OPT_QOS_SUB_RSVD            0x20
55
16
#define OSI_OPT_QOS_SUB_SEQ_VS_TRS      0x10
56
16
#define OSI_OPT_QOS_SUB_CONG_EXPED      0x08
57
16
#define OSI_OPT_QOS_SUB_TSD_VS_COST     0x04
58
16
#define OSI_OPT_QOS_SUB_RESERR_TRS      0x02
59
16
#define OSI_OPT_QOS_SUB_RESERR_COST     0x01
60
61
2
#define OSI_OPT_RFD_GENERAL             0x00
62
0
#define OSI_OPT_RFD_ADDRESS             0x08
63
0
#define OSI_OPT_RFD_SOURCE_ROUTING      0x09
64
1
#define OSI_OPT_RFD_LIFETIME            0x0a
65
1
#define OSI_OPT_RFD_PDU_DISCARDED       0x0b
66
4
#define OSI_OPT_RFD_REASSEMBLY          0x0c
67
68
28
#define OSI_OPT_RFD_MASK                0xf0
69
96
#define OSI_OPT_RFD_SUB_MASK            0x0f
70
71
/* Generated from convert_proto_tree_add_text.pl */
72
static int hf_osi_options_address_mask;
73
static int hf_osi_options_transit_delay_vs_cost;
74
static int hf_osi_options_rtd_general;
75
static int hf_osi_options_residual_error_prob_vs_transit_delay;
76
static int hf_osi_options_qos_sequencing_vs_transit_delay;
77
static int hf_osi_options_rtd_address;
78
static int hf_osi_options_congestion_experienced;
79
static int hf_osi_options_esct;
80
static int hf_osi_options_rtd_reassembly;
81
static int hf_osi_options_qos_maintenance;
82
static int hf_osi_options_security_type;
83
static int hf_osi_options_route_recording;
84
static int hf_osi_options_last_hop;
85
static int hf_osi_options_route;
86
static int hf_osi_options_rtd_lifetime;
87
static int hf_osi_options_rtd_source_routing;
88
static int hf_osi_options_padding;
89
static int hf_osi_options_rfd_error_class;
90
static int hf_osi_options_snpa_mask;
91
static int hf_osi_options_source_routing;
92
static int hf_osi_options_priority;
93
static int hf_osi_options_qos_reserved;
94
static int hf_osi_options_residual_error_prob_vs_cost;
95
static int hf_osi_options_rtd_pdu_discarded;
96
static int hf_osi_options_rfd_field;
97
98
static int ett_osi_options;
99
static int ett_osi_qos;
100
static int ett_osi_route;
101
static int ett_osi_redirect;
102
103
static expert_field ei_osi_options_none;
104
static expert_field ei_osi_options_rfd_error_class;
105
106
static const value_string osi_opt_sec_vals[] = {
107
  {OSI_OPT_SEC_RESERVED,      "Reserved"},
108
  {OSI_OPT_SEC_SRC_ADR_SPEC,  "Source Address Specific"},
109
  {OSI_OPT_SEC_DST_ADR_SPEC,  "Destination Address Specific"},
110
  {OSI_OPT_SEC_GLOBAL_UNIQUE, "Globally Unique"},
111
  {0,                         NULL}
112
};
113
114
static const value_string osi_opt_qos_vals[] = {
115
  {OSI_OPT_QOS_RESERVED,      "Reserved"},
116
  {OSI_OPT_QOS_SRC_ADR_SPEC,  "Source Address Specific"},
117
  {OSI_OPT_QOS_DST_ADR_SPEC,  "Destination Address Specific"},
118
  {OSI_OPT_QOS_GLOBAL_UNIQUE, "Globally Unique"},
119
  {0,                         NULL}
120
};
121
122
static const value_string osi_opt_rfd_error_class[] = {
123
  {OSI_OPT_RFD_GENERAL, "General"},
124
  {OSI_OPT_RFD_ADDRESS, "Address"},
125
  {OSI_OPT_RFD_SOURCE_ROUTING, "Source Routing"},
126
  {OSI_OPT_RFD_LIFETIME, "Lifetime"},
127
  {OSI_OPT_RFD_PDU_DISCARDED, "PDU discarded"},
128
  {OSI_OPT_RFD_REASSEMBLY, "Reassembly"},
129
  {0,    NULL}
130
};
131
132
static const value_string osi_opt_rfd_general[] = {
133
  {0x00, "Reason not specified"},
134
  {0x01, "Protocol procedure error"},
135
  {0x02, "Incorrect checksum"},
136
  {0x03, "PDU discarded due to congestion"},
137
  {0x04, "Header syntax error ( cannot be parsed )"},
138
  {0x05, "Segmentation needed but not permitted"},
139
  {0x06, "Incomplete PDU received"},
140
  {0x07, "Duplicate option"},
141
  {0,    NULL}
142
};
143
144
static const value_string osi_opt_rfd_address[] = {
145
  {0x00, "Destination Address unreachable"},
146
  {0x01, "Destination Address unknown"},
147
  {0,    NULL}
148
};
149
150
static const value_string osi_opt_rfd_src_route[] = {
151
  {0x00, "Unspecified source routing error"},
152
  {0x01, "Syntax error in source routing field"},
153
  {0x02, "Unknown address in source routing field"},
154
  {0x03, "Path not acceptable"},
155
  {0,    NULL}
156
};
157
158
static const value_string osi_opt_rfd_lifetime[] = {
159
  {0x00, "Lifetime expired while data unit in transit"},
160
  {0x01, "Lifetime expired during reassembly"},
161
  {0,    NULL}
162
};
163
164
static const value_string osi_opt_rfd_discarded[] = {
165
  {0x00, "Unsupported option not specified"},
166
  {0x01, "Unsupported protocol version"},
167
  {0x02, "Unsupported security option"},
168
  {0x03, "Unsupported source routing option"},
169
  {0x04, "Unsupported recording of route option"},
170
  {0,    NULL}
171
};
172
173
static const value_string osi_opt_rfd_reassembly[] = {
174
  {0x00, "Reassembly interference"},
175
  {0,    NULL} };
176
177
static dissector_table_t subdissector_decode_as_opt_security_table;
178
179
static void
180
dissect_option_qos(const uint8_t qos, proto_tree *tree, tvbuff_t *tvb, int offset)
181
4
{
182
4
  proto_item *ti;
183
4
  proto_tree *osi_qos_tree;
184
185
4
  ti = proto_tree_add_item(tree, hf_osi_options_qos_maintenance, tvb, offset, 1, ENC_BIG_ENDIAN);
186
4
  osi_qos_tree = proto_item_add_subtree(ti, ett_osi_qos);
187
188
4
  if ( ((qos & OSI_OPT_QOS_MASK) >> 6) == OSI_OPT_QOS_GLOBAL_UNIQUE) { /* Analyze BIT field to get all Values */
189
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_qos_reserved, tvb, offset, 1, ENC_NA);
190
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_qos_sequencing_vs_transit_delay, tvb, offset, 1, ENC_NA);
191
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_congestion_experienced, tvb, offset, 1, ENC_NA);
192
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_transit_delay_vs_cost, tvb, offset, 1, ENC_NA);
193
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_residual_error_prob_vs_transit_delay, tvb, offset, 1, ENC_NA);
194
2
    proto_tree_add_item(osi_qos_tree, hf_osi_options_residual_error_prob_vs_cost, tvb, offset, 1, ENC_NA);
195
2
  }
196
4
}
197
198
static void
199
dissect_option_route(unsigned char parm_type, int offset, unsigned char parm_len,
200
                     tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo )
201
31
{
202
31
  unsigned char      next_hop = 0;
203
31
  uint16_t    this_hop = 0;
204
31
  unsigned char      netl     = 0;
205
31
  unsigned char      last_hop = 0;
206
31
  unsigned char      cnt_hops = 0;
207
31
  unsigned char      crr      = 0;
208
31
  char*      str;
209
210
31
  proto_tree *osi_route_tree = NULL;
211
212
31
  if ( parm_type == OSI_OPT_SOURCE_ROUTING ) {
213
10
    next_hop = tvb_get_uint8(tvb, offset + 1);
214
10
    netl     = tvb_get_uint8(tvb, next_hop + 2);
215
10
    this_hop = offset + 2;  /* points to first netl */
216
217
10
    proto_tree_add_uint_format_value(tree, hf_osi_options_source_routing, tvb, offset + next_hop, netl,
218
10
                        tvb_get_uint8(tvb, offset), "%s   ( Next Hop Highlighted In Data Buffer )",
219
10
                        (tvb_get_uint8(tvb, offset) == 0) ? "Partial Source Routing" :
220
10
                                                             "Complete Source Routing");
221
10
  }
222
21
  else if ( parm_type == OSI_OPT_RECORD_OF_ROUTE ) {
223
21
    crr = tvb_get_uint8(tvb, offset);
224
21
    last_hop = tvb_get_uint8(tvb, offset + 1);
225
21
    osi_route_tree = proto_tree_add_subtree(tree, tvb, offset, parm_len, ett_osi_route, NULL,
226
21
                             (crr == 0) ? "Partial Route Recording" : "Complete Route Recording");
227
228
    /* Complete Route Recording or Partial Route Recording */
229
21
    proto_tree_add_uint_format_value(tree, hf_osi_options_route_recording, tvb, offset, 1, crr, "%s ",
230
21
                             (crr == 0) ? "Partial Route Recording" :
231
21
                                          "Complete Route Recording");
232
233
    /* "last_hop" is either :
234
     *  0x03 : special value for no NET recorded yet.
235
     *  0xFF : special value telling there is no more place
236
               in the Route Recording Allocated Length and
237
               therefore next NETs won't be recorded.
238
    *  Other value : Total length of recorded NETs so far.
239
    */
240
21
    if ( last_hop == 0x03 )
241
1
      proto_tree_add_uint_format(osi_route_tree, hf_osi_options_last_hop, tvb, offset + 1, 1, last_hop,
242
1
                          "No Network Entity Titles Recorded Yet");
243
21
    if ( last_hop == 0xFF )
244
4
      proto_tree_add_uint_format(osi_route_tree, hf_osi_options_last_hop, tvb, offset + 1, 1, last_hop,
245
4
                          "Recording Terminated : No more space !");
246
247
21
    if ( last_hop == 255 || last_hop == 0x03 )
248
5
      this_hop = parm_len + 1;   /* recording terminated,
249
                                  * or not begun, nothing to show */
250
16
    else
251
16
      this_hop = offset + 2;         /* points to first netl */
252
21
  }
253
254
90
  while ( this_hop < offset + last_hop -2 ) { /* -2 for crr and last_hop */
255
59
    netl = tvb_get_uint8(tvb, this_hop);
256
59
    str = print_nsap_net(pinfo->pool, tvb, this_hop + 1, netl);
257
59
    proto_tree_add_string_format(osi_route_tree, hf_osi_options_route, tvb, this_hop, netl + 1, str,
258
59
                        "Hop #%3u NETL: %2u, NET: %s", cnt_hops++, netl, str);
259
59
    this_hop += 1 + netl;
260
59
  }
261
31
}
262
263
264
static void
265
dissect_option_rfd(const unsigned char error, const unsigned char field, int offset,
266
                   unsigned char len _U_, tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo )
267
12
{
268
12
  proto_item *ti;
269
270
12
  ti = proto_tree_add_item(tree, hf_osi_options_rfd_error_class, tvb, offset, 1, ENC_BIG_ENDIAN);
271
272
12
  switch ((error & OSI_OPT_RFD_MASK) >> 4)
273
12
  {
274
2
  case OSI_OPT_RFD_GENERAL:
275
2
    proto_tree_add_item(tree, hf_osi_options_rtd_general, tvb, offset, 1, ENC_BIG_ENDIAN);
276
2
  break;
277
0
  case OSI_OPT_RFD_ADDRESS:
278
0
    proto_tree_add_item(tree, hf_osi_options_rtd_address, tvb, offset, 1, ENC_BIG_ENDIAN);
279
0
  break;
280
0
  case OSI_OPT_RFD_SOURCE_ROUTING:
281
0
    proto_tree_add_item(tree, hf_osi_options_rtd_source_routing, tvb, offset, 1, ENC_BIG_ENDIAN);
282
0
  break;
283
1
  case OSI_OPT_RFD_LIFETIME:
284
1
    proto_tree_add_item(tree, hf_osi_options_rtd_lifetime, tvb, offset, 1, ENC_BIG_ENDIAN);
285
1
  break;
286
1
  case OSI_OPT_RFD_PDU_DISCARDED:
287
1
    proto_tree_add_item(tree, hf_osi_options_rtd_pdu_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
288
1
  break;
289
4
  case OSI_OPT_RFD_REASSEMBLY:
290
4
    proto_tree_add_item(tree, hf_osi_options_rtd_reassembly, tvb, offset, 1, ENC_BIG_ENDIAN);
291
4
  break;
292
4
  default:
293
4
    expert_add_info(pinfo, ti, &ei_osi_options_rfd_error_class);
294
12
  }
295
296
12
  proto_tree_add_uint(tree, hf_osi_options_rfd_field, tvb, offset + field, 1, field);
297
12
}
298
299
/* ############################## Dissection Functions ###################### */
300
301
/*
302
 * Name: dissect_osi_options()
303
 *
304
 * Description:
305
 *   Main entry area for esis de-mangling.  This will build the
306
 *   main esis tree data and call the sub-protocols as needed.
307
 *
308
 * Input:
309
 *   unsigned char       : length of option section
310
 *   tvbuff_t *   : tvbuff containing packet data
311
 *   int          : offset into packet where we are (packet_data[offset]== start
312
 *                  of what we care about)
313
 *   proto_tree * : tree of display data.  May be NULL.
314
 *
315
 * Output:
316
 *   void, but we will add to the proto_tree if it is not NULL.
317
 */
318
void
319
dissect_osi_options(unsigned char opt_len, tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo)
320
262
{
321
262
  proto_item *ti;
322
262
  proto_tree *osi_option_tree = NULL;
323
262
  unsigned char      parm_len        = 0;
324
262
  unsigned char      parm_type       = 0;
325
262
  uint8_t     octet;
326
262
  uint32_t    sec_type;
327
262
  tvbuff_t   *next_tvb;
328
329
262
    osi_option_tree = proto_tree_add_subtree(tree, tvb, offset, opt_len,
330
262
                             ett_osi_options, &ti, "### Option Section ###");
331
262
    if ( 0 == opt_len ) {
332
156
       expert_add_info(pinfo, ti, &ei_osi_options_none);
333
156
       return;
334
156
    }
335
336
1.16k
    while ( 0 < opt_len ) {
337
1.15k
      parm_type = tvb_get_uint8(tvb, offset++);
338
1.15k
      parm_len = tvb_get_uint8(tvb, offset++);
339
340
1.15k
      switch ( parm_type ) {
341
4
        case OSI_OPT_QOS_MAINTANANCE:
342
4
          octet = tvb_get_uint8(tvb, offset);
343
4
          dissect_option_qos(octet, osi_option_tree, tvb, offset);
344
4
          break;
345
346
6
        case OSI_OPT_SECURITY:
347
          /*
348
           * This is unspecified by ISO 8473, and the interpretation
349
           * of the value of the security option appears to be
350
           * specified by various profiles, such as GOSIP, TUBA, and
351
           * ATN.
352
           *
353
           * Thus, we use a payload dissector, so the user can
354
           * specify which dissector to use.
355
           */
356
6
          proto_tree_add_item_ret_uint(osi_option_tree, hf_osi_options_security_type, tvb, offset, 1, ENC_BIG_ENDIAN, &sec_type);
357
          /* XXX */
358
6
          switch ( sec_type ) {
359
360
2
          case OSI_OPT_SEC_RESERVED:
361
2
          case OSI_OPT_SEC_SRC_ADR_SPEC:
362
2
          case OSI_OPT_SEC_DST_ADR_SPEC:
363
2
          default:
364
2
            break;
365
366
4
          case OSI_OPT_SEC_GLOBAL_UNIQUE:
367
4
              next_tvb = tvb_new_subset_length(tvb, offset + 1, parm_len - 1);
368
4
              (void) dissector_try_payload_with_data(subdissector_decode_as_opt_security_table,
369
4
                                     next_tvb, pinfo, osi_option_tree, true, NULL);
370
4
              break;
371
6
          }
372
6
          break;
373
374
16
        case OSI_OPT_PRIORITY:
375
16
          octet = tvb_get_uint8(tvb, offset);
376
16
          if ( OSI_OPT_MAX_PRIORITY >= octet ) {
377
6
            ti = proto_tree_add_item(osi_option_tree, hf_osi_options_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
378
10
          } else {
379
10
            ti = proto_tree_add_uint_format_value(osi_option_tree, hf_osi_options_priority, tvb, offset, 1,
380
10
                                octet, "%u ( Invalid )", octet);
381
10
          }
382
16
          proto_item_set_len(ti, parm_len);
383
16
          break;
384
385
2
        case OSI_OPT_ADDRESS_MASK:
386
2
          proto_tree_add_bytes_format_value(osi_option_tree, hf_osi_options_address_mask, tvb, offset, parm_len,
387
2
                              NULL, "%s",
388
2
                              print_area(pinfo->pool, tvb, offset, parm_len));
389
2
          break;
390
391
14
        case OSI_OPT_SNPA_MASK:
392
14
          proto_tree_add_item(osi_option_tree, hf_osi_options_snpa_mask, tvb, offset, parm_len, ENC_NA);
393
14
          break;
394
395
2
        case OSI_OPT_ES_CONFIG_TIMER:
396
2
          ti = proto_tree_add_item(osi_option_tree, hf_osi_options_esct, tvb, offset, 2, ENC_BIG_ENDIAN);
397
2
          proto_item_set_len(ti, parm_len);          break;
398
399
6
        case OSI_OPT_PADDING:
400
6
          proto_tree_add_item(osi_option_tree, hf_osi_options_padding, tvb, offset, parm_len, ENC_NA);
401
6
          break;
402
403
10
        case OSI_OPT_SOURCE_ROUTING:
404
31
        case OSI_OPT_RECORD_OF_ROUTE:
405
31
          dissect_option_route(parm_type, offset, parm_len, tvb,
406
31
                               osi_option_tree, pinfo);
407
31
          break;
408
409
12
        case OSI_OPT_REASON_OF_DISCARD:
410
12
          dissect_option_rfd(tvb_get_uint8(tvb, offset),
411
12
                             tvb_get_uint8(tvb, offset + 1), offset, parm_len,
412
12
                             tvb, osi_option_tree, pinfo);
413
12
          break;
414
1.15k
      }
415
1.05k
      opt_len -= parm_len + 2;
416
1.05k
      offset  += parm_len;
417
1.05k
    }
418
106
} /* dissect-osi-options */
419
420
421
/*
422
 * Name: proto_register_osi_options()
423
 *
424
 * Description:
425
 *      main register for esis protocol set.  We register some display
426
 *      formats and the protocol module variables.
427
 *
428
 *      NOTE: this procedure to autolinked by the makefile process that
429
 *      builds register.c
430
 *
431
 * Input:
432
 *      void
433
 *
434
 * Output:
435
 *      void
436
 */
437
438
void
439
16
proto_register_osi_options(void) {
440
441
16
  static hf_register_info hf[] =
442
16
  {
443
      /* Generated from convert_proto_tree_add_text.pl */
444
16
      { &hf_osi_options_qos_maintenance, { "Quality of service maintenance", "osi.options.qos.maintenance", FT_UINT8, BASE_DEC, VALS(osi_opt_qos_vals), OSI_OPT_QOS_MASK, NULL, HFILL }},
445
16
      { &hf_osi_options_qos_reserved, { "Reserved", "osi.options.qos.reserved", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_RSVD, NULL, HFILL }},
446
16
      { &hf_osi_options_qos_sequencing_vs_transit_delay, { "Sequencing versus transit delay", "osi.options.qos.seq_vs_trs", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_SEQ_VS_TRS, NULL, HFILL }},
447
16
      { &hf_osi_options_congestion_experienced, { "Congestion experienced", "osi.options.qos.cong_exped", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_CONG_EXPED, NULL, HFILL }},
448
16
      { &hf_osi_options_transit_delay_vs_cost, { "Transit delay versus cost", "osi.options.qos.tsd_vs_cost", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_TSD_VS_COST, NULL, HFILL }},
449
16
      { &hf_osi_options_residual_error_prob_vs_transit_delay, { "Residual error probability versus transit delay", "osi.options.qos.reserror_trs", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_RESERR_TRS, NULL, HFILL }},
450
16
      { &hf_osi_options_residual_error_prob_vs_cost, { "Residual error probability versus cost", "osi.options.qos.reserror_cost", FT_BOOLEAN, 8, NULL, OSI_OPT_QOS_SUB_RESERR_COST, NULL, HFILL }},
451
16
      { &hf_osi_options_source_routing, { "Source Routing", "osi.options.source_routing", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
452
16
      { &hf_osi_options_route_recording, { "Route Recording", "osi.options.route_recording", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
453
16
      { &hf_osi_options_last_hop, { "Last Hop", "osi.options.last_hop", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
454
16
      { &hf_osi_options_route, { "Route", "osi.options.route", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
455
16
      { &hf_osi_options_rfd_error_class, { "Error Class", "osi.options.rfd.error_class", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_error_class), OSI_OPT_RFD_MASK, NULL, HFILL }},
456
16
      { &hf_osi_options_rtd_general, { "Reason for discard {General}", "osi.options.rtd_general", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_general), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
457
16
      { &hf_osi_options_rtd_address, { "Reason for discard {Address}", "osi.options.rtd_address", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_address), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
458
16
      { &hf_osi_options_rtd_source_routing, { "Reason for discard {Source Routing}", "osi.options.rtd_source_routing", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_src_route), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
459
16
      { &hf_osi_options_rtd_lifetime, { "Reason for discard {Lifetime}", "osi.options.rtd_lifetime", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_lifetime), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
460
16
      { &hf_osi_options_rtd_pdu_discarded, { "Reason for discard {PDU discarded}", "osi.options.rtd_pdu_discarded", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_discarded), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
461
16
      { &hf_osi_options_rtd_reassembly, { "Reason for discard {Reassembly}", "osi.options.rtd_reassembly", FT_UINT8, BASE_DEC, VALS(osi_opt_rfd_reassembly), OSI_OPT_RFD_SUB_MASK, NULL, HFILL }},
462
16
      { &hf_osi_options_rfd_field, { "Field", "osi.options.rfd.field", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
463
16
      { &hf_osi_options_security_type, { "Security type", "osi.options.security_type", FT_UINT8, BASE_DEC, VALS(osi_opt_sec_vals), OSI_OPT_SEC_MASK, NULL, HFILL }},
464
16
      { &hf_osi_options_priority, { "Priority", "osi.options.priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
465
16
      { &hf_osi_options_address_mask, { "Address Mask", "osi.options.address_mask", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
466
16
      { &hf_osi_options_snpa_mask, { "SNPA Mask", "osi.options.snpa_mask", FT_SYSTEM_ID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
467
16
      { &hf_osi_options_esct, { "ESCT (seconds)", "osi.options.esct", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
468
16
      { &hf_osi_options_padding, { "Padding", "osi.options.padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
469
16
  };
470
471
16
  static int *ett[] = {
472
16
    &ett_osi_options,
473
16
    &ett_osi_qos,
474
16
    &ett_osi_route,
475
16
    &ett_osi_redirect
476
16
  };
477
478
16
  static ei_register_info ei[] = {
479
16
      { &ei_osi_options_none, { "osi.options.none", PI_PROTOCOL, PI_NOTE, "No Options for this PDU", EXPFILL }},
480
16
      { &ei_osi_options_rfd_error_class, { "osi.options.rfd.error_class.unknown", PI_PROTOCOL, PI_WARN, "UNKNOWN Error Class", EXPFILL }},
481
16
  };
482
483
16
  expert_module_t *expert_osi_options;
484
485
16
  proto_register_field_array(proto_osi, hf, array_length(hf));
486
16
  proto_register_subtree_array(ett, array_length(ett));
487
16
  expert_osi_options = expert_register_protocol(proto_osi);
488
16
  expert_register_field_array(expert_osi_options, ei, array_length(ei));
489
490
16
  subdissector_decode_as_opt_security_table = register_decode_as_next_proto(proto_osi,
491
        "osi.opt_security", "OSI Security Option", NULL);
492
16
}
493
494
/*
495
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
496
 *
497
 * Local variables:
498
 * c-basic-offset: 2
499
 * tab-width: 8
500
 * indent-tabs-mode: nil
501
 * End:
502
 *
503
 * vi: set shiftwidth=2 tabstop=8 expandtab:
504
 * :indentSize=2:tabSize=8:noTabs=true:
505
 */