Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-opsi.c
Line
Count
Source
1
/* packet-opsi.c
2
 * Routines for OPSI protocol dissection
3
 * Copyright 2004, Laurent Rabret (France Telecom R&D) <laurent.rabret@i.hate.spams.org>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/prefs.h>
16
#include <epan/expert.h>
17
18
#include "packet-tcp.h"
19
20
void proto_register_opsi(void);
21
void proto_reg_handoff_opsi(void);
22
23
static dissector_handle_t opsi_handle;
24
25
/* TCP destination port dedicated to the OPSI protocol */
26
15
#define TCP_PORT_OPSI   4002 /* Not IANA registered */
27
28
/* Information position in OPSI header */
29
8
#define MAJOR_VERSION_OFFSET  0
30
8
#define MINOR_VERSION_OFFSET  1
31
16
#define CODE_OFFSET   2
32
8
#define HOOK_ID_OFFSET    3
33
8
#define PACKET_LENGTH_OFFSET  4
34
8
#define SESSION_OFFSET    6
35
36
12
#define HEADER_LENGTH   8
37
38
39
/* Valid OPSI code values */
40
#define DISCOVER_REQUEST  1
41
#define DISCOVER_RESPONSE 2
42
#define SERVICE_REQUEST   3
43
#define SERVICE_ACCEPT    4
44
#define SERVICE_REJECT    5
45
#define TERMINATE_REQUEST 6
46
47
/* Internal structure to dissect attributes */
48
typedef struct {
49
  uint16_t     attribute_type;  /* attribute code */
50
  const char  *tree_text;             /* text for fold out */
51
  int   *tree_id;               /* id for add_item */
52
  int             *hf_type_attribute; /* id for search option */
53
  void    (*dissect)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item,
54
           int* hfValue, int offset, int length);
55
} opsi_attribute_handle_t;
56
57
58
/* Attributes codes */
59
#define USER_NAME_ATTRIBUTE    1
60
#define USER_PASSWD_ATTRIBUTE    2
61
#define CHAP_PASSWD_ATTRIBUTE    3
62
#define NAS_IP_ADDRESS_ATTRIBUTE   4
63
#define NAS_PORT_ATTRIBUTE     5
64
#define SERVICE_TYPE_ATTRIBUTE     6
65
#define FRAMED_PROTOCOL_ATTRIBUTE  7
66
#define FRAMED_ADDRESS_ATTRIBUTE   8
67
#define FRAMED_NETMASK_ATTRIBUTE   9
68
#define FRAMED_ROUTING_ATTRIBUTE  10
69
#define FRAMED_FILTER_ATTRIBUTE   11
70
#define FRAMED_MTU_ATTRIBUTE    12
71
#define FRAMED_COMPRESSION_ATTRIBUTE  13
72
#define CALLED_STATION_ID_ATTRIBUTE 30
73
#define CALLING_STATION_ID_ATTRIBUTE  31
74
#define NAS_IDENTIFIER      32
75
#define ACCOUNTING_40_ATTRIBUTE   40
76
#define ACCOUNTING_41_ATTRIBUTE   41
77
#define ACCOUNTING_42_ATTRIBUTE   42
78
#define ACCOUNTING_43_ATTRIBUTE   43
79
#define ACCOUNTING_SESSION_ID_ATTRIBUTE 44
80
#define ACCOUNTING_45_ATTRIBUTE   45
81
#define ACCOUNTING_46_ATTRIBUTE   46
82
#define ACCOUNTING_47_ATTRIBUTE   47
83
#define ACCOUNTING_48_ATTRIBUTE   48
84
#define ACCOUNTING_49_ATTRIBUTE   49
85
#define ACCOUNTING_50_ATTRIBUTE   50
86
#define ACCOUNTING_51_ATTRIBUTE   51
87
#define ACCOUNTING_52_ATTRIBUTE   52
88
#define ACCOUNTING_53_ATTRIBUTE   53
89
#define ACCOUNTING_54_ATTRIBUTE   54
90
#define ACCOUNTING_55_ATTRIBUTE   55
91
#define ACCOUNTING_56_ATTRIBUTE   56
92
#define ACCOUNTING_57_ATTRIBUTE   57
93
#define ACCOUNTING_58_ATTRIBUTE   58
94
#define ACCOUNTING_59_ATTRIBUTE   59
95
#define CHAP_CHALLENGE_ATTRIBUTE  60
96
#define NAS_PORT_TYPE_ATTRIBUTE   61
97
#define DESIGNATION_NUMBER_ATTRIBUTE  77
98
#define NAS_PORT_ID_ATTRIBUTE   87
99
100
#define SMC_AAAID_ATTRIBUTE   651
101
#define SMC_VPNID_ATTRIBUTE   652
102
#define SMC_VPNNAME_ATTRIBUTE   653
103
#define SMC_RANID_ATTRIBUTE   654
104
#define SMC_RANIP_ATTRIBUTE   655
105
#define SMC_RANNAME_ATTRIBUTE   656
106
#define SMC_POPID_ATTRIBUTE   657
107
#define SMC_POPNAME_ATTRIBUTE   658
108
#define SMC_SMCID_ATTRIBUTE   659
109
#define SMC_RECEIVE_TIME_ATTRIBUTE  660
110
#define SMC_STAT_TIME_ATTRIBUTE   661
111
112
#define OPSI_FLAGS_ATTRIBUTE    674
113
#define OPSI_APPLICATION_NAME_ATTRIBUTE 675
114
115
/*
116
 * Published API functions.  NOTE, "local" API functions
117
 * only valid from the packet-opsi file.
118
 */
119
static void decode_string_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length);
120
static void decode_ipv4_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length);
121
static void decode_longint_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length);
122
static void decode_value_string_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length);
123
static void decode_time_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length);
124
/******* *******/
125
126
/* Initialize the protocol and registered fields */
127
static int proto_opsi;
128
static int hf_opsi_major_version;
129
static int hf_opsi_minor_version;
130
static int hf_opsi_opcode;
131
static int hf_opsi_hook_id;
132
static int hf_opsi_length;
133
static int hf_opsi_session_id;
134
static int hf_user_name_att;
135
static int hf_password_att;
136
static int hf_chap_password_att;
137
static int hf_nas_ip_add_att;
138
static int hf_nas_port_att;
139
static int hf_service_type_att;
140
static int hf_framed_protocol_att;
141
static int hf_framed_address_att;
142
static int hf_framed_netmask_att;
143
static int hf_framed_routing_att;
144
static int hf_framed_filter_att;
145
static int hf_framed_mtu_att;
146
static int hf_framed_compression_att;
147
static int hf_called_station_att;
148
static int hf_calling_station_att;
149
static int hf_nas_identifier_att;
150
static int hf_accounting_att;
151
static int hf_acct_session_id_att;
152
static int hf_chap_challenge_att;
153
static int hf_nas_port_type_att;
154
static int hf_designation_num_att;
155
static int hf_nas_port_id_att;
156
static int hf_smc_aaa_id_att;
157
static int hf_smc_vpn_id_att;
158
static int hf_smc_vpn_name_att;
159
static int hf_smc_ran_id_att;
160
static int hf_smc_ran_ip_att;
161
static int hf_smc_ran_name_att;
162
static int hf_smc_pop_id_att;
163
static int hf_smc_pop_name_att;
164
static int hf_smc_id_att;
165
static int hf_smc_receive_time_att;
166
static int hf_smc_stat_time_att;
167
static int hf_opsi_flags_att;
168
static int hf_opsi_application_name_att;
169
static int hf_opsi_attribute_length;
170
171
/* Initialize the subtree pointers */
172
static int ett_opsi;
173
static int ett_opsi_user_name;
174
static int ett_opsi_user_password;
175
static int ett_opsi_chap_password;
176
static int ett_opsi_nas_ip_address;
177
static int ett_opsi_nas_port;
178
static int ett_opsi_service_type;
179
static int ett_opsi_framed_protocol;
180
static int ett_opsi_framed_address;
181
static int ett_opsi_framed_netmask;
182
static int ett_opsi_framed_routing;
183
static int ett_opsi_framed_filter;
184
static int ett_opsi_framed_mtu;
185
static int ett_opsi_framed_compression;
186
static int ett_opsi_called_station_id;
187
static int ett_opsi_calling_station_id;
188
static int ett_opsi_nas_identifier;
189
static int ett_opsi_accounting;
190
static int ett_opsi_acct_session_id;
191
static int ett_opsi_chap_challenge;
192
static int ett_opsi_nas_port_type;
193
static int ett_opsi_designation_number;
194
static int ett_opsi_nas_port_id;
195
static int ett_opsi_smc_aaa_id;
196
static int ett_opsi_smc_vpn_id;
197
static int ett_opsi_smc_vpn_name;
198
static int ett_opsi_smc_ran_id;
199
static int ett_opsi_smc_ran_ip;
200
static int ett_opsi_smc_ran_name;
201
static int ett_opsi_smc_pop_id;
202
static int ett_opsi_smc_pop_name;
203
static int ett_opsi_smc_id;
204
static int ett_opsi_smc_receive_time;
205
static int ett_opsi_smc_stat_time;
206
static int ett_opsi_flags;
207
static int ett_opsi_application_name;
208
209
static expert_field ei_opsi_unknown_attribute;
210
static expert_field ei_opsi_short_attribute;
211
static expert_field ei_opsi_short_frame;
212
213
/* Code mapping */
214
static const value_string opsi_opcode[] = {
215
  { DISCOVER_REQUEST,  "Discover Request" },
216
  { DISCOVER_RESPONSE, "Discover Response" },
217
  { SERVICE_REQUEST,   "Service Request" },
218
  { SERVICE_ACCEPT,    "Service Accept" },
219
  { SERVICE_REJECT,    "Service Reject" },
220
  { TERMINATE_REQUEST, "Terminate Request" },
221
  { 0, NULL }
222
};
223
224
static const value_string opsi_service_type_code[] = {
225
  { 1, "Login" },
226
  { 2, "Framed" },
227
  { 3, "Callback Login" },
228
  { 4, "Callback Framed" },
229
  { 5, "Outbound" },
230
  { 6, "Administrative" },
231
  { 7, "NAS Prompt" },
232
  { 8, "Authenticate Only" },
233
  { 9, "Callback NAS Prompt" },
234
  { 0, NULL }
235
};
236
237
static const value_string opsi_framed_protocol_code[] = {
238
  {   1, "PPP" },
239
  {   2, "SLIP" },
240
  {   3, "AppleTalk Remote Access Protocol (ARAP)" },
241
  {   4, "Gandalf proprietary SingleLink/MultiLink protocol" },
242
  {   5, "Xylogics proprietary IPX/SLIP" },
243
  { 255, "Ascend ARA" },
244
  { 256, "MPP" },
245
  { 257, "EURAW" },
246
  { 258, "EUUI" },
247
  { 259, "X25" },
248
  { 260, "COMB" },
249
  { 261, "FR" },
250
  { 262, "MP" },
251
  { 263, "FR-CIR"},
252
  { 0, NULL }
253
};
254
255
static const value_string opsi_framed_routing_code[] = {
256
  { 0, "None" },
257
  { 1, "Broadcast" },
258
  { 2, "Listen" },
259
  { 3, "Broadcast-Listen" },
260
  { 4, "Broadcast V2" },
261
  { 5, "Listen V2" },
262
  { 6, "Broadcast-Listen V2" },
263
  { 0, NULL },
264
};
265
266
static const value_string opsi_framed_compression_code[] = {
267
  { 0, "None" },
268
  { 1, "Van Jacobsen TCP/IP" },
269
  { 2, "IPX header compression" },
270
  { 0, NULL }
271
};
272
273
static const value_string opsi_nas_port_type_code[] = {
274
  {   0, "Async" },
275
  {   1, "Sync" },
276
  {   2, "ISDN Sync" },
277
  {   3, "ISDN Async V.120" },
278
  {   4, "ISDN Async V.110" },
279
  {   5, "Virtual" },
280
  {   6, "PIAFS" },
281
  {   7, "HDLC Clear Channel" },
282
  {   8, "X.25" },
283
  {   9, "X.75" },
284
  {  10, "G.3 Fax" },
285
  {  11, "SDSL - Symmetric DSL" },
286
  {  12, "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation" },
287
  {  13, "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone" },
288
  {  14, "IDSL - ISDN Digital Subscriber Line" },
289
  {  15, "Ethernet" },
290
  {  16, "xDSL - Digital Subscriber Line of unknown type" },
291
  {  17, "Cable" },
292
  {  18, "Wireless - Other" },
293
  {  19, "Wireless - IEEE 802.11" },
294
  { 201, "Voice over IP" },
295
  { 0, NULL }
296
};
297
298
299
/* Structure used to decode OPSI frame attributes */
300
/* CAUTION : it is compulsory to sort this array  */
301
/* (first argument of the opsi_attribute_handle_t)  */
302
/* in ascending order           */
303
/*              */
304
static const opsi_attribute_handle_t opsi_attributes[] = {
305
  { USER_NAME_ATTRIBUTE,      /* 1 */
306
  "User name attribute",       &ett_opsi_user_name, &hf_user_name_att, decode_string_attribute },
307
  { USER_PASSWD_ATTRIBUTE,    /* 2 */
308
  "User password attribute" ,    &ett_opsi_user_password, &hf_password_att, decode_string_attribute },
309
  { CHAP_PASSWD_ATTRIBUTE,    /* 3 */
310
  "CHAP password attribute",     &ett_opsi_chap_password, &hf_chap_password_att, decode_string_attribute },
311
  { NAS_IP_ADDRESS_ATTRIBUTE,   /* 4 */
312
  "NAS IP address attribute",    &ett_opsi_nas_ip_address, &hf_nas_ip_add_att, decode_ipv4_attribute },
313
  {NAS_PORT_ATTRIBUTE,      /* 5 */
314
  "NAS port attribute",      &ett_opsi_nas_port, &hf_nas_port_att, decode_longint_attribute },
315
  {SERVICE_TYPE_ATTRIBUTE,    /* 6 */
316
  "Service type attribute",    &ett_opsi_service_type, &hf_service_type_att, decode_value_string_attribute },
317
  {FRAMED_PROTOCOL_ATTRIBUTE,   /* 7 */
318
  "Framed protocol attribute",     &ett_opsi_framed_protocol, &hf_framed_protocol_att, decode_value_string_attribute },
319
  {FRAMED_ADDRESS_ATTRIBUTE,    /* 8 */
320
  "Framed address attribute",    &ett_opsi_framed_address, &hf_framed_address_att, decode_ipv4_attribute },
321
  {FRAMED_NETMASK_ATTRIBUTE,    /* 9 */
322
  "Framed netmask attribute",    &ett_opsi_framed_netmask, &hf_framed_netmask_att, decode_ipv4_attribute },
323
  {FRAMED_ROUTING_ATTRIBUTE,    /* 10 */
324
  "Framed routing attribute",    &ett_opsi_framed_routing, &hf_framed_routing_att, decode_value_string_attribute },
325
  {FRAMED_FILTER_ATTRIBUTE,   /* 11 */
326
  "Framed filter attribute",     &ett_opsi_framed_filter, &hf_framed_filter_att, decode_string_attribute },
327
  {FRAMED_MTU_ATTRIBUTE,      /* 12 */
328
  "Framed MTU attribute",      &ett_opsi_framed_mtu, &hf_framed_mtu_att, decode_longint_attribute },
329
  {FRAMED_COMPRESSION_ATTRIBUTE,    /* 13 */
330
  "Framed compression attribute",    &ett_opsi_framed_compression, &hf_framed_compression_att, decode_value_string_attribute },
331
  {CALLED_STATION_ID_ATTRIBUTE,   /* 30 */
332
  "Called station ID attribute",     &ett_opsi_called_station_id, &hf_called_station_att, decode_string_attribute },
333
  {CALLING_STATION_ID_ATTRIBUTE,    /* 31 */
334
  "Calling station ID attribute",    &ett_opsi_calling_station_id, &hf_calling_station_att, decode_string_attribute },
335
  {NAS_IDENTIFIER,      /* 32 */
336
  "NAS Identifier attribute",    &ett_opsi_nas_identifier, &hf_nas_identifier_att, decode_string_attribute },
337
  {ACCOUNTING_40_ATTRIBUTE,   /* 40 */
338
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
339
  {ACCOUNTING_41_ATTRIBUTE,   /* 41 */
340
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
341
  {ACCOUNTING_42_ATTRIBUTE,   /* 42 */
342
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
343
  {ACCOUNTING_43_ATTRIBUTE,   /* 43 */
344
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
345
  {ACCOUNTING_SESSION_ID_ATTRIBUTE, /* 44 */
346
  "Accounting session ID attribute", &ett_opsi_acct_session_id, &hf_acct_session_id_att, decode_string_attribute },
347
  {ACCOUNTING_45_ATTRIBUTE,   /* 45 */
348
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
349
  {ACCOUNTING_46_ATTRIBUTE,   /* 46 */
350
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
351
  {ACCOUNTING_47_ATTRIBUTE,   /* 47 */
352
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
353
  {ACCOUNTING_48_ATTRIBUTE,   /* 48 */
354
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
355
  {ACCOUNTING_49_ATTRIBUTE,   /* 49 */
356
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
357
  {ACCOUNTING_50_ATTRIBUTE,   /* 50 */
358
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
359
  {ACCOUNTING_51_ATTRIBUTE,   /* 51 */
360
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
361
  {ACCOUNTING_52_ATTRIBUTE,   /* 52 */
362
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
363
  {ACCOUNTING_53_ATTRIBUTE,   /* 53 */
364
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
365
  {ACCOUNTING_54_ATTRIBUTE,   /* 54 */
366
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
367
  {ACCOUNTING_55_ATTRIBUTE,   /* 55 */
368
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
369
  {ACCOUNTING_56_ATTRIBUTE,   /* 56 */
370
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
371
  {ACCOUNTING_57_ATTRIBUTE,   /* 57 */
372
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
373
  {ACCOUNTING_58_ATTRIBUTE,   /* 58 */
374
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
375
  {ACCOUNTING_59_ATTRIBUTE,   /* 59 */
376
  "Accounting attribute",      &ett_opsi_accounting, &hf_accounting_att, decode_string_attribute },
377
  {CHAP_CHALLENGE_ATTRIBUTE,    /* 60 */
378
  "CHAP challenge",      &ett_opsi_chap_challenge, &hf_chap_challenge_att, decode_string_attribute },
379
  {NAS_PORT_TYPE_ATTRIBUTE,   /* 61 */
380
  "NAS port type attribute",     &ett_opsi_nas_port_type, &hf_nas_port_type_att, decode_value_string_attribute },
381
  {DESIGNATION_NUMBER_ATTRIBUTE,    /* 77 */
382
  "Designation number attribute",    &ett_opsi_designation_number, &hf_designation_num_att, decode_string_attribute },
383
  {NAS_PORT_ID_ATTRIBUTE,     /* 87 */
384
  "NAS port ID attribute",     &ett_opsi_nas_port_id, &hf_nas_port_id_att, decode_string_attribute },
385
  {SMC_AAAID_ATTRIBUTE,     /* 651 */
386
  "SMC AAA ID attribute",      &ett_opsi_smc_aaa_id, &hf_smc_aaa_id_att, decode_longint_attribute },
387
  {SMC_VPNID_ATTRIBUTE,     /* 652 */
388
  "SMC VPN ID attribute",      &ett_opsi_smc_vpn_id, &hf_smc_vpn_id_att, decode_longint_attribute },
389
  {SMC_VPNNAME_ATTRIBUTE,     /* 653 */
390
  "SMC VPN name attribute",    &ett_opsi_smc_vpn_name, &hf_smc_vpn_name_att, decode_string_attribute },
391
  {SMC_RANID_ATTRIBUTE,     /* 654 */
392
  "SMC RAN ID attribute",      &ett_opsi_smc_ran_id, &hf_smc_ran_id_att, decode_longint_attribute },
393
  {SMC_RANIP_ATTRIBUTE,     /* 655 */
394
  "SMC RAN IP attribute",      &ett_opsi_smc_ran_ip, &hf_smc_ran_ip_att, decode_ipv4_attribute },
395
  {SMC_RANNAME_ATTRIBUTE,     /* 656 */
396
  "SMC RAN name attribute",    &ett_opsi_smc_ran_name, &hf_smc_ran_name_att, decode_string_attribute },
397
  {SMC_POPID_ATTRIBUTE,     /* 657 */
398
  "SMC POP ID attribute",      &ett_opsi_smc_pop_id, &hf_smc_pop_id_att, decode_longint_attribute },
399
  {SMC_POPNAME_ATTRIBUTE,     /* 658 */
400
  "SMC POP name attribute",    &ett_opsi_smc_pop_name, &hf_smc_pop_name_att, decode_string_attribute },
401
  {SMC_SMCID_ATTRIBUTE,     /* 659 */
402
  "SMC ID attribute",      &ett_opsi_smc_id, &hf_smc_id_att, decode_longint_attribute },
403
  {SMC_RECEIVE_TIME_ATTRIBUTE,    /* 660 */
404
  "SMC receive time attribute",    &ett_opsi_smc_receive_time, &hf_smc_receive_time_att, decode_time_attribute },
405
  {SMC_STAT_TIME_ATTRIBUTE,   /* 661 */
406
  "SMC stat time attribute",     &ett_opsi_smc_stat_time, &hf_smc_stat_time_att, decode_longint_attribute },
407
  {OPSI_FLAGS_ATTRIBUTE,      /* 674 */
408
  "OPSI flags attribute",      &ett_opsi_flags, &hf_opsi_flags_att, decode_longint_attribute },
409
  {OPSI_APPLICATION_NAME_ATTRIBUTE, /* 675 */
410
  "OPSI application name attribute", &ett_opsi_application_name, &hf_opsi_application_name_att, decode_string_attribute },
411
412
};
413
414
/* Desegmentation of OPSI (over TCP) */
415
static bool opsi_desegment = true;
416
417
static void
418
decode_string_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length)
419
1
{
420
1
  if (length < 4) {
421
0
    expert_add_info(pinfo, item, &ei_opsi_short_attribute);
422
0
    return;
423
0
  }
424
425
1
  proto_tree_add_item(tree, *hfValue, tvb, offset+4, length-4, ENC_ASCII|ENC_NA);
426
1
}
427
428
429
static void
430
decode_ipv4_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length)
431
0
{
432
0
  if (length < 8) {
433
0
    expert_add_info(pinfo, item, &ei_opsi_short_attribute);
434
0
    return;
435
0
  }
436
0
  proto_tree_add_item(tree, *hfValue, tvb, offset+4, 4, ENC_BIG_ENDIAN);
437
0
}
438
439
static void
440
decode_longint_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length)
441
0
{
442
0
  if (length < 8) {
443
0
    expert_add_info(pinfo, item, &ei_opsi_short_attribute);
444
0
    return;
445
0
  }
446
0
  proto_tree_add_item(tree, *hfValue, tvb, offset+4, 4, ENC_BIG_ENDIAN);
447
0
}
448
449
static void
450
decode_value_string_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length)
451
1
{
452
1
  if (length < 8) {
453
1
    expert_add_info(pinfo, item, &ei_opsi_short_attribute);
454
1
    return;
455
1
  }
456
0
  proto_tree_add_item(tree, *hfValue, tvb, offset+4, 4, ENC_BIG_ENDIAN);
457
0
}
458
459
static void
460
decode_time_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *item, int* hfValue, int offset, int length)
461
0
{
462
0
  if (length < 8) {
463
0
    expert_add_info(pinfo, item, &ei_opsi_short_attribute);
464
0
    return;
465
0
  }
466
0
  proto_tree_add_item(tree, *hfValue, tvb, offset+4, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN);
467
0
}
468
469
/****************************************************************************/
470
/********** End of attribute decoding ***************************************/
471
/****************************************************************************/
472
473
/* To find the correct size of the PDU. Needed by the desegmentation feature*/
474
static unsigned
475
get_opsi_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
476
8
{
477
  /*
478
   * Get the length of the OPSI packet.
479
   * We are guaranteed there're enough chars in tvb in order to
480
   * extract the length value. No exception thrown !!
481
   */
482
8
  return tvb_get_ntohs(tvb, offset + 4);
483
8
}
484
485
static int
486
opsi_attribute_compar(const void *key, const void *member)
487
27
{
488
27
  return *(const int *)key - ((const opsi_attribute_handle_t *)member)->attribute_type;
489
27
}
490
491
static void
492
dissect_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *opsi_tree, int offset, int length)
493
8
{
494
8
  int attribute_type;
495
8
  int attribute_length;
496
8
  proto_item *ti;
497
8
  proto_tree *ntree = NULL;
498
499
11
  while (length >= 4) {
500
9
    const opsi_attribute_handle_t *attr;
501
9
    attribute_type    = tvb_get_ntohs(tvb, offset);
502
9
    attribute_length  = tvb_get_ntohs(tvb, offset+2);
503
9
    if (attribute_length > length) break;
504
    /* We perform a standard log(n) lookup */
505
506
6
    attr = bsearch(&attribute_type, opsi_attributes, array_length(opsi_attributes), sizeof opsi_attributes[0], opsi_attribute_compar);
507
6
    if (attr == NULL) {
508
3
      proto_tree_add_expert_format(opsi_tree, pinfo, &ei_opsi_unknown_attribute, tvb, offset, attribute_length,
509
3
                    "Unknown attribute (%d)", attribute_type);
510
3
    } else {
511
3
      ntree = proto_tree_add_subtree_format(opsi_tree, tvb, offset, attribute_length, *attr->tree_id, &ti,
512
3
                "%s (%d)", attr->tree_text, attribute_type);
513
3
      proto_tree_add_item(ntree, hf_opsi_attribute_length, tvb, offset+2, 2, ENC_BIG_ENDIAN);
514
3
      attr->dissect(tvb, pinfo, ntree, ti, attr->hf_type_attribute, offset, attribute_length);
515
3
    }
516
6
    if (attribute_length < 4) {
517
      /* Length must be at least 4, for the type and length. */
518
3
      break;
519
3
    }
520
3
    offset += attribute_length;
521
3
    length -= attribute_length;
522
3
  }
523
8
  if (length) {
524
6
    proto_tree_add_expert_remaining(opsi_tree, pinfo, &ei_opsi_short_frame, tvb, offset);
525
6
  }
526
8
}
527
528
static int
529
dissect_opsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
530
8
{
531
8
  proto_item *ti;
532
8
  proto_tree *opsi_tree;
533
534
8
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "OPSI");
535
8
  col_clear(pinfo->cinfo, COL_INFO);
536
537
8
  col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
538
8
    val_to_str(pinfo->pool, tvb_get_uint8(tvb, CODE_OFFSET), opsi_opcode,
539
8
      "<Unknown opcode %d>"));
540
8
  col_set_fence(pinfo->cinfo, COL_INFO);
541
542
8
  ti = proto_tree_add_item(tree, proto_opsi, tvb, 0, -1, ENC_NA);
543
8
  opsi_tree = proto_item_add_subtree(ti, ett_opsi);
544
545
8
  if (opsi_tree) {
546
8
    proto_tree_add_item(opsi_tree, hf_opsi_major_version, tvb, MAJOR_VERSION_OFFSET, 1, ENC_BIG_ENDIAN);
547
8
    proto_tree_add_item(opsi_tree, hf_opsi_minor_version, tvb, MINOR_VERSION_OFFSET, 1, ENC_BIG_ENDIAN);
548
8
    proto_tree_add_item(opsi_tree, hf_opsi_opcode, tvb, CODE_OFFSET, 1, ENC_BIG_ENDIAN);
549
8
    proto_tree_add_item(opsi_tree, hf_opsi_hook_id, tvb, HOOK_ID_OFFSET, 1, ENC_BIG_ENDIAN);
550
8
    proto_tree_add_item(opsi_tree, hf_opsi_length, tvb, PACKET_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN);
551
8
    proto_tree_add_item(opsi_tree, hf_opsi_session_id, tvb, SESSION_OFFSET, 2, ENC_BIG_ENDIAN);
552
8
  }
553
554
8
  dissect_attributes(tvb, pinfo, opsi_tree, HEADER_LENGTH, MIN(((int)tvb_reported_length(tvb)-HEADER_LENGTH), (tvb_get_ntohs(tvb, PACKET_LENGTH_OFFSET)-HEADER_LENGTH)));
555
8
  return tvb_reported_length(tvb);
556
8
}
557
558
559
static int
560
dissect_opsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
561
4
{
562
  /* We should minimally grab the header */
563
4
  tcp_dissect_pdus(tvb, pinfo, tree, opsi_desegment, HEADER_LENGTH, get_opsi_pdu_len,
564
4
    dissect_opsi_pdu, data);
565
4
  return tvb_reported_length(tvb);
566
4
}
567
568
569
void
570
proto_register_opsi(void)
571
15
{
572
573
/* Setup list of header fields  See Section 1.6.1 for details*/
574
15
  static hf_register_info hf[] = {
575
15
    { &hf_opsi_major_version,
576
15
      { "Major version",           "opsi.major",
577
15
      FT_UINT8, BASE_DEC, NULL, 0x0,
578
15
      NULL, HFILL }
579
15
    },
580
15
    { &hf_opsi_minor_version,
581
15
      { "Minor version",           "opsi.minor",
582
15
      FT_UINT8, BASE_DEC, NULL, 0x0,
583
15
      NULL, HFILL }
584
15
    },
585
15
    { &hf_opsi_opcode,
586
15
            { "Operation code",   "opsi.opcode",
587
15
            FT_UINT8, BASE_DEC, VALS(opsi_opcode), 0x0,
588
15
            NULL, HFILL }
589
15
    },
590
15
    { &hf_opsi_hook_id,
591
15
      { "Hook ID",      "opsi.hook",
592
15
      FT_UINT8, BASE_DEC, NULL, 0x0,
593
15
      NULL, HFILL }
594
15
    },
595
15
    { &hf_opsi_length,
596
15
      { "Message length",   "opsi.length",
597
15
      FT_UINT16, BASE_DEC, NULL, 0x0,
598
15
      NULL, HFILL }
599
15
    },
600
15
    { &hf_opsi_session_id,
601
15
      { "Session ID",     "opsi.session_id",
602
15
      FT_UINT16, BASE_DEC, NULL, 0x0,
603
15
      NULL, HFILL }
604
15
    },
605
15
    { &hf_user_name_att,
606
15
      { "User name",      "opsi.attr.user_name",
607
15
      FT_STRING, BASE_NONE, NULL, 0x00,
608
15
      NULL, HFILL }
609
15
    },
610
15
    { &hf_password_att,
611
15
      { "User password",    "opsi.attr.password",
612
15
      FT_STRING, BASE_NONE, NULL, 0x00,
613
15
      NULL, HFILL }
614
15
    },
615
15
    { &hf_chap_password_att,
616
15
      { "CHAP password attribute",  "opsi.attr.chap_password",
617
15
      FT_STRING, BASE_NONE, NULL, 0x00,
618
15
      NULL, HFILL }
619
15
    },
620
15
    { &hf_nas_ip_add_att,
621
15
      { "NAS IP address",   "opsi.attr.nas_ip_addr",
622
15
      FT_IPv4, BASE_NONE, NULL, 0x00,
623
15
      NULL, HFILL }
624
15
    },
625
15
    { &hf_nas_port_att,
626
15
      { "NAS port",     "opsi.attr.nas_port",
627
15
      FT_UINT32, BASE_HEX, NULL, 0x00,
628
15
      NULL, HFILL }
629
15
    },
630
15
    { &hf_service_type_att,
631
15
            { "Service type",   "opsi.attr.service_type",
632
15
      FT_UINT32, BASE_DEC, VALS(opsi_service_type_code), 0x0,
633
15
      NULL, HFILL }
634
15
    },
635
15
    { &hf_framed_protocol_att,
636
15
      { "Framed protocol",    "opsi.attr.framed_protocol",
637
15
      FT_UINT32, BASE_DEC, VALS(opsi_framed_protocol_code), 0x0,
638
15
      NULL, HFILL }
639
15
    },
640
15
    { &hf_framed_address_att,
641
15
      { "Framed address",   "opsi.attr.framed_address",
642
15
      FT_IPv4, BASE_NONE, NULL, 0x00,
643
15
      NULL, HFILL }
644
15
    },
645
15
    { &hf_framed_netmask_att,
646
15
      { "Framed netmask",   "opsi.attr.framed_netmask",
647
15
      FT_IPv4, BASE_NETMASK, NULL, 0x00,
648
15
      NULL, HFILL }
649
15
    },
650
15
    { &hf_framed_routing_att,
651
15
      { "Framed routing",   "opsi.attr.framed_routing",
652
15
      FT_UINT32, BASE_DEC, VALS(opsi_framed_routing_code), 0x0,
653
15
      NULL, HFILL }
654
15
    },
655
15
    { &hf_framed_filter_att,
656
15
      { "Framed filter",    "opsi.attr.framed_filter",
657
15
      FT_STRING, BASE_NONE, NULL, 0x00,
658
15
      NULL, HFILL }
659
15
    },
660
15
    { &hf_framed_mtu_att,
661
15
      { "Framed MTU",   "opsi.attr.framed_mtu",
662
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
663
15
      NULL, HFILL }
664
15
    },
665
15
    { &hf_framed_compression_att,
666
15
      { "Framed compression",   "opsi.attr.framed_compression",
667
15
      FT_UINT32, BASE_DEC, VALS(opsi_framed_compression_code), 0x0,
668
15
      NULL, HFILL }
669
15
    },
670
15
    { &hf_called_station_att,
671
15
      { "Called station ID",    "opsi.attr.called_station_id",
672
15
      FT_STRING, BASE_NONE, NULL, 0x00,
673
15
      NULL, HFILL }
674
15
    },
675
15
    { &hf_calling_station_att,
676
15
      { "Calling station ID",   "opsi.attr.calling_station_id",
677
15
      FT_STRING, BASE_NONE, NULL, 0x00,
678
15
      NULL, HFILL }
679
15
    },
680
15
    { &hf_nas_identifier_att,
681
15
      { "NAS ID",     "opsi.attr.nas_id",
682
15
      FT_STRING, BASE_NONE, NULL, 0x00,
683
15
      NULL, HFILL }
684
15
    },
685
15
    { &hf_accounting_att,
686
15
      { "Accounting",     "opsi.attr.accounting",
687
15
      FT_STRING, BASE_NONE, NULL, 0x00,
688
15
      NULL, HFILL }
689
15
    },
690
15
    { &hf_acct_session_id_att,
691
15
      { "Accounting session ID",  "opsi.attr.acct.session_id",
692
15
      FT_STRING, BASE_NONE, NULL, 0x00,
693
15
      NULL, HFILL }
694
15
    },
695
15
    { &hf_chap_challenge_att,
696
15
      { "CHAP challenge",   "opsi.attr.chap_challenge",
697
15
      FT_STRING, BASE_NONE, NULL, 0x00,
698
15
      NULL, HFILL }
699
15
    },
700
15
    { &hf_nas_port_type_att,
701
15
      { "NAS port type",    "opsi.attr.nas_port_type",
702
15
      FT_UINT32, BASE_DEC, VALS(opsi_nas_port_type_code), 0x0,
703
15
      NULL, HFILL }
704
15
    },
705
15
    { &hf_designation_num_att,
706
15
      { "Designation number",   "opsi.attr.designation_number",
707
15
      FT_STRING, BASE_NONE, NULL, 0x00,
708
15
      NULL, HFILL }
709
15
    },
710
15
    { &hf_nas_port_id_att,
711
15
      { "NAS port ID",    "opsi.attr.nas_port_id",
712
15
      FT_STRING, BASE_NONE, NULL, 0x00,
713
15
      NULL, HFILL }
714
15
    },
715
15
    { &hf_smc_aaa_id_att,
716
15
      { "SMC AAA ID",     "opsi.attr.smc_aaa_id",
717
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
718
15
      NULL, HFILL }
719
15
    },
720
15
    { &hf_smc_vpn_id_att,
721
15
      { "SMC VPN ID",     "opsi.attr.smc_vpn_id",
722
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
723
15
      NULL, HFILL }
724
15
    },
725
15
    { &hf_smc_vpn_name_att,
726
15
      { "SMC VPN name",   "opsi.attr.smc_vpn_name",
727
15
      FT_STRING, BASE_NONE, NULL, 0x00,
728
15
      NULL, HFILL }
729
15
    },
730
15
    { &hf_smc_ran_id_att,
731
15
      { "SMC RAN ID",     "opsi.attr.smc_ran_id",
732
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
733
15
      NULL, HFILL }
734
15
    },
735
15
    { &hf_smc_ran_ip_att,
736
15
      { "SMC RAN IP address",   "opsi.attr.smc_ran_ip",
737
15
      FT_IPv4, BASE_NONE, NULL, 0x00,
738
15
      NULL, HFILL }
739
15
    },
740
15
    { &hf_smc_ran_name_att,
741
15
      { "SMC RAN name",   "opsi.attr.smc_ran_name",
742
15
      FT_STRING, BASE_NONE, NULL, 0x00,
743
15
      NULL, HFILL }
744
15
    },
745
15
    { &hf_smc_pop_id_att,
746
15
      { "SMC POP id",     "opsi.attr.smc_pop_id",
747
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
748
15
      NULL, HFILL }
749
15
    },
750
15
    { &hf_smc_pop_name_att,
751
15
      { "SMC POP name",   "opsi.attr.smc_pop_name",
752
15
      FT_STRING, BASE_NONE, NULL, 0x00,
753
15
      NULL, HFILL }
754
15
    },
755
15
    { &hf_smc_id_att,
756
15
      { "SMC ID",     "opsi.attr.smc_id",
757
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
758
15
      NULL, HFILL }
759
15
    },
760
15
    { &hf_smc_receive_time_att,
761
15
      { "SMC receive time",   "opsi.attr.smc_receive_time",
762
15
      FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
763
15
      NULL, HFILL }
764
15
    },
765
15
    { &hf_smc_stat_time_att,
766
15
      { "SMC stat time",    "opsi.attr.smc_stat_time",
767
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
768
15
      NULL, HFILL }
769
15
    },
770
15
    { &hf_opsi_flags_att,
771
15
      { "OPSI flags",     "opsi.attr.flags",
772
15
      FT_UINT32, BASE_DEC, NULL, 0x00,
773
15
      NULL, HFILL }
774
15
    },
775
15
    { &hf_opsi_application_name_att,
776
15
      { "OPSI application name",  "opsi.attr.application_name",
777
15
      FT_STRING, BASE_NONE, NULL, 0x00,
778
15
      NULL, HFILL }
779
15
    },
780
15
    { &hf_opsi_attribute_length,
781
15
      { "Length", "opsi.attr_length",
782
15
      FT_UINT16, BASE_DEC, NULL, 0x00,
783
15
      NULL, HFILL }
784
15
    },
785
15
  };
786
787
/* Setup protocol subtree array */
788
15
  static int *ett[] = {
789
15
    &ett_opsi,
790
15
    &ett_opsi_user_name,
791
15
    &ett_opsi_user_password,
792
15
    &ett_opsi_chap_password,
793
15
    &ett_opsi_nas_ip_address,
794
15
    &ett_opsi_nas_port,
795
15
    &ett_opsi_service_type,
796
15
    &ett_opsi_framed_protocol,
797
15
    &ett_opsi_framed_address,
798
15
    &ett_opsi_framed_netmask,
799
15
    &ett_opsi_framed_routing,
800
15
    &ett_opsi_framed_filter,
801
15
    &ett_opsi_framed_mtu,
802
15
    &ett_opsi_framed_compression,
803
15
    &ett_opsi_called_station_id,
804
15
    &ett_opsi_calling_station_id,
805
15
    &ett_opsi_nas_identifier,
806
15
    &ett_opsi_accounting,
807
15
    &ett_opsi_acct_session_id,
808
15
    &ett_opsi_chap_challenge,
809
15
    &ett_opsi_nas_port_type,
810
15
    &ett_opsi_designation_number,
811
15
    &ett_opsi_nas_port_id,
812
15
    &ett_opsi_smc_aaa_id,
813
15
    &ett_opsi_smc_vpn_id,
814
15
    &ett_opsi_smc_vpn_name,
815
15
    &ett_opsi_smc_ran_id,
816
15
    &ett_opsi_smc_ran_ip,
817
15
    &ett_opsi_smc_ran_name,
818
15
    &ett_opsi_smc_pop_id,
819
15
    &ett_opsi_smc_pop_name,
820
15
    &ett_opsi_smc_id,
821
15
    &ett_opsi_smc_receive_time,
822
15
    &ett_opsi_smc_stat_time,
823
15
    &ett_opsi_flags,
824
15
    &ett_opsi_application_name,
825
15
  };
826
827
15
  static ei_register_info ei[] = {
828
15
    { &ei_opsi_unknown_attribute, { "opsi.attr_unknown", PI_PROTOCOL, PI_WARN, "Unknown attribute", EXPFILL }},
829
15
    { &ei_opsi_short_attribute, { "opsi.attr_too_short", PI_MALFORMED, PI_WARN, "Too short attribute!", EXPFILL }},
830
15
    { &ei_opsi_short_frame, { "opsi.short_frame", PI_MALFORMED, PI_WARN, "Short frame", EXPFILL }},
831
15
  };
832
833
/* For desegmentation / reassembly */
834
15
  module_t *opsi_module;
835
15
  expert_module_t* expert_opsi;
836
837
/* Register the protocol name and description */
838
15
  proto_opsi = proto_register_protocol("Open Policy Service Interface", "OPSI", "opsi");
839
840
/* Required function calls to register the header fields and subtrees used */
841
15
  proto_register_field_array(proto_opsi, hf, array_length(hf));
842
15
  proto_register_subtree_array(ett, array_length(ett));
843
15
  expert_opsi = expert_register_protocol(proto_opsi);
844
15
  expert_register_field_array(expert_opsi, ei, array_length(ei));
845
846
/* We activate the desegmentation / reassembly feature */
847
15
  opsi_module = prefs_register_protocol(proto_opsi, NULL);
848
15
  prefs_register_bool_preference(opsi_module, "desegment_opsi_messages",
849
15
    "Reassemble OPSI messages spanning multiple TCP segments",
850
15
    "Whether the OPSI dissector should desegment all messages spanning multiple TCP segments",
851
15
    &opsi_desegment);
852
853
/* Register the dissector */
854
15
  opsi_handle = register_dissector("opsi", dissect_opsi, proto_opsi);
855
15
}
856
857
858
void
859
proto_reg_handoff_opsi(void)
860
15
{
861
15
  dissector_add_uint_with_preference("tcp.port", TCP_PORT_OPSI, opsi_handle);
862
15
}
863
864
/*
865
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
866
 *
867
 * Local variables:
868
 * c-basic-offset: 8
869
 * tab-width: 8
870
 * indent-tabs-mode: t
871
 * End:
872
 *
873
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
874
 * :indentSize=8:tabSize=8:noTabs=false:
875
 */