Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-gre.c
Line
Count
Source
1
/* packet-gre.c
2
 * Routines for the Generic Routing Encapsulation (GRE) protocol
3
 * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
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/tfs.h>
16
#include <epan/capture_dissectors.h>
17
#include <epan/etypes.h>
18
#include <epan/in_cksum.h>
19
#include <epan/expert.h>
20
#include <epan/iana-info.h>
21
#include "packet-gre.h"
22
#include "packet-wccp.h"
23
#include "packet-llc.h"
24
25
26
#include <epan/decode_as.h>
27
28
14
#define GRE_IN_UDP_PORT 4754
29
30
void proto_register_gre(void);
31
void proto_reg_handoff_gre(void);
32
33
static dissector_handle_t gre_handle;
34
static capture_dissector_handle_t gre_cap_handle;
35
36
37
/*
38
 * See RFC 1701 "Generic Routing Encapsulation (GRE)", RFC 1702
39
 * "Generic Routing Encapsulation over IPv4 networks", RFC 2637
40
 * "Point-to-Point Tunneling Protocol (PPTP)", RFC 2784 "Generic
41
 * Routing Encapsulation (GRE)", RFC 2890 "Key and Sequence
42
 * Number Extensions to GRE", RFC 8086 "GRE-in-UDP Encapsulation",
43
 * and draft-ietf-mpls-in-ip-or-gre-07.txt
44
 * "Encapsulating MPLS in IP or Generic Routing Encapsulation (GRE)".
45
 */
46
47
static int proto_gre;
48
static int hf_gre_proto;
49
static int hf_gre_flags_and_version;
50
static int hf_gre_flags_checksum;
51
static int hf_gre_flags_routing;
52
static int hf_gre_flags_key;
53
static int hf_gre_flags_sequence_number;
54
static int hf_gre_flags_strict_source_route;
55
static int hf_gre_flags_recursion_control;
56
static int hf_gre_flags_ack;
57
static int hf_gre_flags_reserved_ppp;
58
static int hf_gre_flags_reserved;
59
static int hf_gre_flags_version;
60
static int hf_gre_checksum;
61
static int hf_gre_checksum_status;
62
static int hf_gre_offset;
63
static int hf_gre_key;
64
static int hf_gre_key_payload_length;
65
static int hf_gre_key_call_id;
66
static int hf_gre_sequence_number;
67
static int hf_gre_ack_number;
68
static int hf_gre_routing;
69
static int hf_gre_routing_address_family;
70
static int hf_gre_routing_sre_length;
71
static int hf_gre_routing_sre_offset;
72
static int hf_gre_routing_information;
73
74
/* Ref 3GPP2 A.S0012-C v2.0 and A.S0008-A v1.0 */
75
static int hf_gre_3gpp2_attrib;
76
static int hf_gre_3gpp2_attrib_id;
77
static int hf_gre_3gpp2_attrib_length;
78
static int hf_gre_3gpp2_sdi;
79
static int hf_gre_3gpp2_fci;
80
static int hf_gre_3gpp2_di;
81
static int hf_gre_3gpp2_flow_disc;
82
static int hf_gre_3gpp2_seg;
83
84
static int hf_gre_wccp_redirect_header;
85
static int hf_gre_wccp_dynamic_service;
86
static int hf_gre_wccp_alternative_bucket_used;
87
static int hf_gre_wccp_redirect_header_valid;
88
static int hf_gre_wccp_service_id;
89
static int hf_gre_wccp_alternative_bucket;
90
static int hf_gre_wccp_primary_bucket;
91
92
static int ett_gre;
93
static int ett_gre_flags;
94
static int ett_gre_routing;
95
static int ett_gre_wccp2_redirect_header;
96
static int ett_3gpp2_attribs;
97
static int ett_3gpp2_attr;
98
99
static expert_field ei_gre_checksum_incorrect;
100
101
static dissector_table_t gre_dissector_table;
102
103
static dissector_table_t gre_subdissector_table;
104
105
static const value_string gre_version[] = {
106
    { 0, "GRE" },                /* [RFC2784] */
107
    { 1, "Enhanced GRE" },       /* [RFC2637] */
108
    { 0, NULL}
109
};
110
const value_string gre_typevals[] = {
111
    { GRE_KEEPALIVE,       "Possible GRE keepalive packet" },
112
    { ETHERTYPE_PPP,       "PPP" },
113
    { ETHERTYPE_IP,        "IP" },
114
    { ETHERTYPE_ARP,       "ARP" },
115
    { SAP_OSINL5,          "OSI"},
116
    { GRE_WCCP,            "WCCP"},
117
    { GRE_CISCO_CDP,       "CDP (Cisco)"},
118
    { GRE_NHRP,            "NHRP"},
119
    { GRE_ERSPAN_88BE,     "ERSPAN"},
120
    { GRE_ERSPAN_22EB,     "ERSPAN III"},
121
    { GRE_MIKROTIK_EOIP,   "MIKROTIK EoIP"},
122
    { GRE_AIROHIVE,        "AIROHIVE AP AP"},
123
    { ETHERTYPE_IPX,       "IPX"},
124
    { ETHERTYPE_ETHBRIDGE, "Transparent Ethernet bridging" },
125
    { ETHERTYPE_RAW_FR,    "Frame Relay"},
126
    { ETHERTYPE_IPv6,      "IPv6" },
127
    { ETHERTYPE_MPLS,      "MPLS label switched packet" },
128
    { ETHERTYPE_NSH,       "Network Service Header" },
129
    { ETHERTYPE_CDMA2000_A10_UBS,"CDMA2000 A10 Unstructured byte stream" },
130
    { ETHERTYPE_3GPP2,     "CDMA2000 A10 3GPP2 Packet" },
131
    { ETHERTYPE_CMD,       "CiscoMetaData" },
132
    { GRE_GREBONDING,      "Huawei GRE bonding" },
133
    { GRE_ARUBA_8200,      "ARUBA WLAN" },
134
    { GRE_ARUBA_8210,      "ARUBA WLAN" },
135
    { GRE_ARUBA_8220,      "ARUBA WLAN" },
136
    { GRE_ARUBA_8230,      "ARUBA WLAN" },
137
    { GRE_ARUBA_8240,      "ARUBA WLAN" },
138
    { GRE_ARUBA_8250,      "ARUBA WLAN" },
139
    { GRE_ARUBA_8260,      "ARUBA WLAN" },
140
    { GRE_ARUBA_8270,      "ARUBA WLAN" },
141
    { GRE_ARUBA_8280,      "ARUBA WLAN" },
142
    { GRE_ARUBA_8290,      "ARUBA WLAN" },
143
    { GRE_ARUBA_82A0,      "ARUBA WLAN" },
144
    { GRE_ARUBA_82B0,      "ARUBA WLAN" },
145
    { GRE_ARUBA_82C0,      "ARUBA WLAN" },
146
    { GRE_ARUBA_82D0,      "ARUBA WLAN" },
147
    { GRE_ARUBA_82E0,      "ARUBA WLAN" },
148
    { GRE_ARUBA_82F0,      "ARUBA WLAN" },
149
    { GRE_ARUBA_8300,      "ARUBA WLAN" },
150
    { GRE_ARUBA_8310,      "ARUBA WLAN" },
151
    { GRE_ARUBA_8320,      "ARUBA WLAN" },
152
    { GRE_ARUBA_8330,      "ARUBA WLAN" },
153
    { GRE_ARUBA_8340,      "ARUBA WLAN" },
154
    { GRE_ARUBA_8350,      "ARUBA WLAN" },
155
    { GRE_ARUBA_8360,      "ARUBA WLAN" },
156
    { GRE_ARUBA_8370,      "ARUBA WLAN" },
157
    { GRE_ARUBA_9000,      "ARUBA WLAN" },
158
    { GRE_ARUBA_9100,      "ARUBA WLAN" },
159
    { GRE_ARUBA_9110,      "ARUBA WLAN" },
160
    { GRE_ARUBA_9120,      "ARUBA WLAN" },
161
    { GRE_ARUBA_9130,      "ARUBA WLAN" },
162
    { GRE_ARUBA_9140,      "ARUBA WLAN" },
163
    { GRE_ARUBA_9150,      "ARUBA WLAN" },
164
    { GRE_ARUBA_9160,      "ARUBA WLAN" },
165
    { GRE_ARUBA_9170,      "ARUBA WLAN" },
166
    { GRE_ARUBA_9180,      "ARUBA WLAN" },
167
    { GRE_ARUBA_9190,      "ARUBA WLAN" },
168
    { GRE_ARUBA_91A0,      "ARUBA WLAN" },
169
    { GRE_ARUBA_91B0,      "ARUBA WLAN" },
170
    { GRE_ARUBA_91C0,      "ARUBA WLAN" },
171
    { GRE_ARUBA_91D0,      "ARUBA WLAN" },
172
    { GRE_ARUBA_91E0,      "ARUBA WLAN" },
173
    { GRE_ARUBA_91F0,      "ARUBA WLAN" },
174
    { 0,                   NULL }
175
};
176
177
14
#define ID_3GPP2_SDI_FLAG 1
178
42
#define ID_3GPP2_FLOW_CTRL 2
179
16
#define ID_3GPP2_FLOW_DISCRIMINATOR 3
180
19
#define ID_3GPP2_SEG 4
181
182
static const value_string gre_3gpp2_seg_vals[] = {
183
    { 0x00, "Packet Started" },
184
    { 0x01, "Packet continued" },
185
    { 0x02, "Packet Ended" },
186
    { 0,    NULL }
187
};
188
/* 3GPP2 A.S0012-C v2.0
189
 * 2.6.1 GRE Attributes
190
 */
191
static const value_string gre_3gpp2_attrib_id_vals[] = {
192
    { 0x01, "1x SDB/HRPD DOS Indicator" },
193
    { 0x02, "Flow Control Indication" },
194
    /* A.S0008-A v1.0 */
195
    { 0x03, "IP Flow Discriminator" },
196
    { 0x04, "Segmentation Indication" },
197
    { 0,    NULL }
198
};
199
200
static const true_false_string gre_3gpp2_sdi_val = {
201
    "Packet suitable for 1x SDB or HRPD DOS transmission",
202
    "Reserved"
203
};
204
205
static const true_false_string gre_3gpp2_fci_val = {
206
    "XOFF",
207
    "XON"
208
};
209
210
static const true_false_string gre_3gpp2_di_val = {
211
    "INDEFINITE:",
212
    "TEMPORARY"
213
};
214
215
static const true_false_string gre_wccp_dynamic_service_val = {
216
    "Dynamic service",
217
    "Well-known service"
218
};
219
220
static const true_false_string gre_wccp_alternative_bucket_used_val = {
221
    "Alternative bucket used",
222
    "Primary bucket used",
223
};
224
225
static const true_false_string gre_wccp_redirect_header_valid_val = {
226
    "Header is present, but ignore contents",
227
    "Header contents are valid",
228
};
229
230
231
static int
232
dissect_gre_3gpp2_attribs(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *tree)
233
22
{
234
22
    bool        last_attrib  = false;
235
22
    proto_item *attr_item;
236
22
    proto_tree *attr_tree;
237
22
    uint8_t     value;
238
22
    int         start_offset = offset;
239
240
22
    proto_item *ti = proto_tree_add_item(tree, hf_gre_3gpp2_attrib, tvb, offset, 0, ENC_NA);
241
22
    proto_tree *atree = proto_item_add_subtree(ti, ett_3gpp2_attribs);
242
243
325
    while(last_attrib != true)
244
319
    {
245
319
        uint8_t attrib_id = tvb_get_uint8(tvb, offset);
246
319
        uint8_t attrib_length = tvb_get_uint8(tvb, offset + 1);
247
248
319
        attr_tree = proto_tree_add_subtree(atree, tvb, offset, attrib_length + 1 + 1, ett_3gpp2_attr, &attr_item,
249
319
                                        val_to_str(pinfo->pool, (attrib_id&0x7f), gre_3gpp2_attrib_id_vals, "%u (Unknown)"));
250
251
319
        proto_tree_add_item(attr_tree, hf_gre_3gpp2_attrib_id, tvb, offset, 1, ENC_BIG_ENDIAN);
252
319
        proto_tree_add_item(attr_tree, hf_gre_3gpp2_attrib_length, tvb, offset+1, 1, ENC_BIG_ENDIAN);
253
254
319
        offset += 2;
255
319
        last_attrib = (attrib_id & 0x80)?true:false;
256
319
        attrib_id &= 0x7F;
257
258
319
        switch(attrib_id)
259
319
        {
260
16
        case ID_3GPP2_FLOW_DISCRIMINATOR:
261
16
        {
262
16
            value = tvb_get_uint8(tvb,offset);
263
16
            proto_tree_add_item(attr_tree, hf_gre_3gpp2_flow_disc, tvb, offset, attrib_length, ENC_NA);
264
16
            proto_item_append_text(attr_item," - 0x%x",value);
265
16
        }
266
16
        break;
267
14
        case ID_3GPP2_SDI_FLAG:
268
14
        {
269
14
            value = tvb_get_uint8(tvb,offset);
270
14
            proto_tree_add_item(attr_tree, hf_gre_3gpp2_sdi, tvb, offset, attrib_length, ENC_BIG_ENDIAN);
271
14
            proto_item_append_text(attr_item," - %s",
272
14
                                   (value & 0x80) ? "Packet suitable for 1x SDB or HRPD DOS transmission" : "Reserved");
273
274
14
        }
275
14
        break;
276
19
        case ID_3GPP2_SEG:
277
19
        {
278
19
            value = tvb_get_uint8(tvb,offset) >>6;
279
19
            proto_tree_add_item(attr_tree, hf_gre_3gpp2_seg, tvb, offset, attrib_length, ENC_BIG_ENDIAN);
280
19
            proto_item_append_text(attr_item," - %s",val_to_str(pinfo->pool, value, gre_3gpp2_seg_vals, "0x%02X - Unknown"));
281
19
        }
282
19
        break;
283
42
        case ID_3GPP2_FLOW_CTRL:
284
42
        {
285
42
            value = tvb_get_uint8(tvb,offset);
286
42
            proto_tree_add_item(attr_tree, hf_gre_3gpp2_fci, tvb, offset, attrib_length, ENC_BIG_ENDIAN);
287
42
            proto_item_append_text(attr_item," - %s",
288
42
                                   (value & 0x80) ? "XON" : "XOFF");
289
42
            proto_tree_add_item(attr_tree, hf_gre_3gpp2_di, tvb, offset, attrib_length, ENC_BIG_ENDIAN);
290
42
            proto_item_append_text(attr_item,"/%s",
291
42
                                   (value & 0x40) ? "INDEFINITE" : "TEMPORARY");
292
42
        }
293
42
        break;
294
319
        }
295
296
303
        offset += attrib_length;
297
303
    }
298
6
    proto_item_set_len(ti, offset - start_offset);
299
300
6
    return offset;
301
22
}
302
303
static void
304
dissect_gre_wccp2_redirect_header(tvbuff_t *tvb, int offset, proto_tree *tree)
305
1
{
306
1
    proto_item *ti;
307
1
    proto_tree *rh_tree;
308
309
1
    ti = proto_tree_add_item(tree, hf_gre_wccp_redirect_header, tvb, offset, 4, ENC_NA);
310
1
    rh_tree = proto_item_add_subtree(ti, ett_gre_wccp2_redirect_header);
311
312
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_dynamic_service, tvb, offset, 1, ENC_BIG_ENDIAN);
313
314
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_alternative_bucket_used, tvb, offset, 1, ENC_BIG_ENDIAN);
315
316
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_redirect_header_valid, tvb, offset, 1, ENC_BIG_ENDIAN);
317
318
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_service_id, tvb, offset +1, 1, ENC_BIG_ENDIAN);
319
320
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_alternative_bucket, tvb, offset +2, 1, ENC_BIG_ENDIAN);
321
322
1
    proto_tree_add_item(rh_tree, hf_gre_wccp_primary_bucket, tvb, offset +3, 1, ENC_BIG_ENDIAN);
323
1
}
324
325
static bool
326
capture_gre(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
327
0
{
328
0
    capture_dissector_increment_count(cpinfo, proto_gre);
329
0
    return true;
330
0
}
331
332
static int
333
dissect_gre(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
334
6.19k
{
335
336
6.19k
    int             offset             = 0;
337
6.19k
    gre_hdr_info_t  gre_hdr_info;
338
6.19k
    uint16_t        type;
339
6.19k
    bool            is_ppp             = false;
340
6.19k
    bool            is_wccp2           = false;
341
6.19k
    proto_item     *ti, *it_flags;
342
6.19k
    proto_tree     *gre_tree, *fv_tree = NULL;
343
6.19k
    uint16_t        sre_af;
344
6.19k
    uint8_t         sre_length;
345
6.19k
    tvbuff_t       *next_tvb;
346
347
6.19k
    gre_hdr_info.flags_and_ver = tvb_get_ntohs(tvb, offset);
348
6.19k
    type = tvb_get_ntohs(tvb, offset + 2);
349
350
6.19k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "GRE");
351
352
6.19k
    col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated %s", val_to_str(pinfo->pool, type, gre_typevals, "0x%04X (unknown)"));
353
354
6.19k
    switch (type) {
355
356
1
    case ETHERTYPE_PPP:
357
1
        if (gre_hdr_info.flags_and_ver & GRE_VERSION)
358
0
            is_ppp = true;
359
1
        break;
360
22
    case ETHERTYPE_3GPP2:
361
4.51k
    case ETHERTYPE_CDMA2000_A10_UBS:
362
4.51k
        is_ppp = true;
363
4.51k
        break;
364
365
1
    case GRE_WCCP:
366
        /* WCCP2 puts an extra 4 octets into the header, but uses the same
367
           encapsulation type; if it looks as if the first octet of the packet
368
           isn't the beginning of an IPv4 header, assume it's WCCP2. */
369
1
        if ((tvb_get_uint8(tvb, offset + 2 + 2) & 0xF0) != 0x40) {
370
1
            is_wccp2 = true;
371
1
        }
372
1
        break;
373
6.19k
    }
374
375
    /* Per README.developer, section 1.2, we must call subdissectors regardless
376
     * of whether "tree" is NULL or not.  That is done below using
377
     * call_dissector(), but since the next_tvb must begin at the correct offset,
378
     * it's easier and more readable to always enter this block in order to
379
     * compute the correct offset to pass to tvb_new_subset_remaining().
380
     */
381
6.19k
    if (1) {
382
6.19k
        ti = proto_tree_add_protocol_format(tree, proto_gre, tvb, offset, -1, "Generic Routing Encapsulation (%s)",
383
6.19k
                                            val_to_str(pinfo->pool, type, gre_typevals, "0x%04X - unknown"));
384
6.19k
        gre_tree = proto_item_add_subtree(ti, ett_gre);
385
386
387
6.19k
        it_flags = proto_tree_add_item(gre_tree, hf_gre_flags_and_version, tvb, offset, 2, ENC_BIG_ENDIAN);
388
6.19k
        fv_tree = proto_item_add_subtree(it_flags, ett_gre_flags);
389
390
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
391
392
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_routing, tvb, offset, 2, ENC_BIG_ENDIAN);
393
394
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_key, tvb, offset, 2, ENC_BIG_ENDIAN);
395
396
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
397
398
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_strict_source_route, tvb, offset, 2, ENC_BIG_ENDIAN);
399
400
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_recursion_control, tvb, offset, 2, ENC_BIG_ENDIAN);
401
402
        /* RFC2637 Section 4.1 : Enhanced GRE Header */
403
6.19k
        if (is_ppp) {
404
4.51k
            proto_tree_add_item(fv_tree, hf_gre_flags_ack, tvb, offset, 2, ENC_BIG_ENDIAN);
405
406
4.51k
            proto_tree_add_item(fv_tree, hf_gre_flags_reserved_ppp, tvb, offset, 2, ENC_BIG_ENDIAN);
407
4.51k
        }
408
1.67k
        else {
409
1.67k
            proto_tree_add_item(fv_tree, hf_gre_flags_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
410
1.67k
        }
411
412
6.19k
        proto_tree_add_item(fv_tree, hf_gre_flags_version, tvb, offset, 2, ENC_BIG_ENDIAN);
413
414
6.19k
        offset += 2;
415
416
6.19k
        proto_tree_add_item(gre_tree, hf_gre_proto, tvb, offset, 2, ENC_BIG_ENDIAN);
417
6.19k
        offset += 2;
418
419
6.19k
        if (gre_hdr_info.flags_and_ver & GRE_CHECKSUM || gre_hdr_info.flags_and_ver & GRE_ROUTING) {
420
1.46k
            unsigned length, reported_length;
421
1.46k
            vec_t cksum_vec[1];
422
423
            /* Checksum check !... */
424
1.46k
            length = tvb_captured_length(tvb);
425
1.46k
            reported_length = tvb_reported_length(tvb);
426
            /* The Checksum Present bit is set, and the packet isn't part of a
427
               fragmented datagram and isn't truncated, so we can checksum it. */
428
1.46k
            if ((gre_hdr_info.flags_and_ver & GRE_CHECKSUM) && !pinfo->fragmented && length >= reported_length) {
429
1.42k
                SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, reported_length);
430
1.42k
                proto_tree_add_checksum(gre_tree, tvb, offset, hf_gre_checksum, hf_gre_checksum_status, &ei_gre_checksum_incorrect, pinfo, in_cksum(cksum_vec, 1),
431
1.42k
                                ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
432
1.42k
            } else {
433
35
                proto_tree_add_checksum(gre_tree, tvb, offset, hf_gre_checksum, hf_gre_checksum_status, &ei_gre_checksum_incorrect, pinfo, 0,
434
35
                                ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
435
35
            }
436
1.46k
            offset += 2;
437
438
1.46k
            proto_tree_add_item(gre_tree, hf_gre_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
439
1.46k
            offset += 2;
440
1.46k
        }
441
442
6.19k
        if (gre_hdr_info.flags_and_ver & GRE_KEY) {
443
            /* RFC2637 Section 4.1 : Enhanced GRE Header */
444
2.31k
            if (is_ppp && type!=ETHERTYPE_CDMA2000_A10_UBS) {
445
446
1
                proto_tree_add_item(gre_tree, hf_gre_key_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN);
447
1
                offset += 2;
448
449
1
                proto_tree_add_item(gre_tree, hf_gre_key_call_id, tvb, offset, 2, ENC_BIG_ENDIAN);
450
1
                offset += 2;
451
1
            }
452
2.31k
            else {
453
2.31k
                proto_tree_add_item_ret_uint(gre_tree, hf_gre_key, tvb, offset, 4, ENC_BIG_ENDIAN, &gre_hdr_info.key);
454
2.31k
                offset += 4;
455
2.31k
            }
456
2.31k
        }
457
6.19k
        if (gre_hdr_info.flags_and_ver & GRE_SEQUENCE) {
458
459
2.08k
            proto_tree_add_item(gre_tree, hf_gre_sequence_number , tvb, offset, 4, ENC_BIG_ENDIAN);
460
2.08k
            offset += 4;
461
2.08k
        }
462
6.19k
        if (is_ppp && (gre_hdr_info.flags_and_ver & GRE_ACK)) {
463
464
1.52k
            proto_tree_add_item(gre_tree, hf_gre_ack_number , tvb, offset, 4, ENC_BIG_ENDIAN);
465
1.52k
            offset += 4;
466
1.52k
        }
467
6.19k
        if (gre_hdr_info.flags_and_ver & GRE_ROUTING) {
468
64
            proto_item *it_routing;
469
64
            proto_tree *r_tree;
470
330
            for (;;) {
471
472
330
                it_routing = proto_tree_add_item(gre_tree, hf_gre_routing, tvb, offset, -1, ENC_NA);
473
330
                r_tree = proto_item_add_subtree(ti, ett_gre_routing);
474
475
330
                proto_tree_add_item_ret_uint16(r_tree, hf_gre_routing_address_family , tvb, offset, 2, ENC_BIG_ENDIAN, &sre_af);
476
330
                offset += 2;
477
478
330
                proto_tree_add_item(r_tree, hf_gre_routing_sre_offset , tvb, offset, 1, ENC_BIG_ENDIAN);
479
330
                offset += 1;
480
481
330
                proto_tree_add_item_ret_uint8(r_tree, hf_gre_routing_sre_length , tvb, offset, 1, ENC_BIG_ENDIAN, &sre_length);
482
330
                offset += 1;
483
484
330
                proto_item_set_len(it_routing, 2 + 1 +1 + sre_length);
485
330
                if (sre_af == 0 && sre_length == 0)
486
44
                    break;
487
488
286
                proto_tree_add_item(r_tree, hf_gre_routing_information , tvb, offset, sre_length, ENC_NA);
489
286
                offset += sre_length;
490
286
            }
491
64
        }
492
493
6.19k
        if (type == GRE_WCCP && is_wccp2) {
494
1
            dissect_gre_wccp2_redirect_header(tvb, offset, gre_tree);
495
1
            offset += 4;
496
1
        }
497
6.19k
        if (type == ETHERTYPE_3GPP2) {
498
22
            offset = dissect_gre_3gpp2_attribs(tvb, pinfo, offset, gre_tree);
499
22
        }
500
501
6.19k
        proto_item_set_len(ti, offset);
502
503
        /* If the S bit is not set, this packet might not have a payload, so
504
           check whether there's any data left, first.
505
506
           XXX - the S bit isn't in RFC 2784, which deprecates that bit
507
           and some other bits in RFC 1701 and says that they should be
508
           zero for RFC 2784-compliant GRE; as such, the absence of the
509
           S bit doesn't necessarily mean there's no payload.  */
510
6.19k
        if (!(gre_hdr_info.flags_and_ver & GRE_SEQUENCE)) {
511
4.08k
            if (tvb_reported_length_remaining(tvb, offset) <= 0)
512
6
                return offset; /* no payload */
513
4.08k
        }
514
6.18k
        next_tvb = tvb_new_subset_remaining(tvb, offset);
515
6.18k
        pinfo->flags.in_gre_pkt = true;
516
6.18k
        if (!dissector_try_uint_with_data(gre_dissector_table, type, next_tvb, pinfo, tree, true, &gre_hdr_info))
517
22
            if (!dissector_try_payload_with_data(gre_subdissector_table, next_tvb, pinfo, tree, true, &gre_hdr_info)) {
518
22
              call_data_dissector(next_tvb, pinfo, gre_tree);
519
22
            }
520
6.18k
    }
521
6.18k
    return tvb_captured_length(tvb);
522
6.19k
}
523
524
static void
525
gre_prompt(packet_info *pinfo _U_, char* result)
526
0
{
527
0
  snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "GRE proto as");
528
0
}
529
530
void
531
proto_register_gre(void)
532
14
{
533
14
    static hf_register_info hf[] = {
534
14
        { &hf_gre_proto,
535
14
          { "Protocol Type", "gre.proto",
536
14
            FT_UINT16, BASE_HEX, VALS(gre_typevals), 0x0,
537
14
            "The protocol that is GRE encapsulated", HFILL }
538
14
        },
539
14
        { &hf_gre_flags_and_version,
540
14
          { "Flags and Version", "gre.flags_and_version",
541
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
542
14
            "The GRE flags are encoded in the first two octets", HFILL }
543
14
        },
544
14
        { &hf_gre_flags_checksum,
545
14
          { "Checksum Bit", "gre.flags.checksum",
546
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_CHECKSUM,
547
14
            "Indicates if the Checksum field is present", HFILL }
548
14
        },
549
14
        { &hf_gre_flags_routing,
550
14
          { "Routing Bit", "gre.flags.routing",
551
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_ROUTING,
552
14
            "Indicates if the Routing and Checksum/Offset field are present", HFILL }
553
14
        },
554
14
        { &hf_gre_flags_key,
555
14
          { "Key Bit", "gre.flags.key",
556
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_KEY,
557
14
            "Indicates if the Key field is present", HFILL }
558
14
        },
559
14
        { &hf_gre_flags_sequence_number,
560
14
          { "Sequence Number Bit", "gre.flags.sequence_number",
561
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_SEQUENCE,
562
14
            "Indicates if the Sequence Number field is present", HFILL }
563
14
        },
564
14
        { &hf_gre_flags_strict_source_route,
565
14
          { "Strict Source Route Bit", "gre.flags.strict_source_route",
566
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_STRICTSOURCE,
567
14
            NULL, HFILL }
568
14
        },
569
14
        { &hf_gre_flags_recursion_control,
570
14
          { "Recursion control", "gre.flags.recursion_control",
571
14
            FT_UINT16, BASE_DEC, NULL, GRE_RECURSION,
572
14
            NULL, HFILL }
573
14
        },
574
14
        { &hf_gre_flags_ack,
575
14
          { "Acknowledgment", "gre.flags.ack",
576
14
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), GRE_ACK,
577
14
            "Indicates if the packet contains an Acknowledgment Number to be used for acknowledging previously transmitted data", HFILL }
578
14
        },
579
14
        { &hf_gre_flags_reserved,
580
14
          { "Flags (Reserved)", "gre.flags.reserved",
581
14
            FT_UINT16, BASE_DEC, NULL, GRE_RESERVED,
582
14
            NULL, HFILL }
583
14
        },
584
14
        { &hf_gre_flags_reserved_ppp,
585
14
          { "Flags (Reserved)", "gre.flags.reserved",
586
14
            FT_UINT16, BASE_DEC, NULL, GRE_RESERVED_PPP,
587
14
            NULL, HFILL }
588
14
        },
589
14
        { &hf_gre_flags_version,
590
14
          { "Version", "gre.flags.version",
591
14
            FT_UINT16, BASE_DEC, VALS(gre_version), GRE_VERSION,
592
14
            NULL, HFILL }
593
14
        },
594
14
        { &hf_gre_checksum,
595
14
          { "Checksum", "gre.checksum",
596
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
597
14
            "The Checksum field contains the IP (one's complement) checksum of the GRE header and the payload packet", HFILL }
598
14
        },
599
14
        { &hf_gre_checksum_status,
600
14
          { "Checksum Status", "gre.checksum.status",
601
14
            FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
602
14
            NULL, HFILL }
603
14
        },
604
14
        { &hf_gre_offset,
605
14
          { "Offset", "gre.offset",
606
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
607
14
            "The offset field indicates the octet offset from the start of the Routing field to the first octet of the active Source Route Entry to be examined", HFILL }
608
14
        },
609
14
        { &hf_gre_key,
610
14
          { "Key", "gre.key",
611
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
612
14
            "The Key field contains a four octet number which was inserted by the encapsulator", HFILL }
613
14
        },
614
14
        { &hf_gre_key_payload_length,
615
14
          { "Payload Length", "gre.key.payload_length",
616
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
617
14
            "Size of the payload, not including the GRE header", HFILL }
618
14
        },
619
14
        { &hf_gre_key_call_id,
620
14
          { "Call ID", "gre.key.call_id",
621
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
622
14
            "Contains the Peer's Call ID for the session to which this packet belongs.", HFILL }
623
14
        },
624
14
        { &hf_gre_sequence_number,
625
14
          { "Sequence Number", "gre.sequence_number",
626
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
627
14
            "The Sequence Number field contains an unsigned 32 bit integer which is inserted by the encapsulator", HFILL }
628
14
        },
629
14
        { &hf_gre_ack_number,
630
14
          { "Acknowledgment Number", "gre.ack_number",
631
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
632
14
            "Contains the sequence number of the highest numbered GRE packet received by the sending peer for this user session", HFILL }
633
14
        },
634
14
        { &hf_gre_routing,
635
14
          { "Routing", "gre.routing",
636
14
            FT_NONE, BASE_NONE, NULL, 0x0,
637
14
            "The Routing field is a list of Source Route Entries (SREs)", HFILL }
638
14
        },
639
14
        { &hf_gre_routing_address_family,
640
14
          { "Address Family", "gre.routing.address_family",
641
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
642
14
            "The Address Family field contains a two octet value which indicates the syntax and semantics of the Routing Information field", HFILL }
643
14
        },
644
14
        { &hf_gre_routing_sre_offset,
645
14
          { "SRE Offset", "gre.routing.sre_offset",
646
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
647
14
            "The Address Family field contains a two octet value which indicates the syntax and semantics of the Routing Information field", HFILL }
648
14
        },
649
14
        { &hf_gre_routing_sre_length,
650
14
          { "SRE Length", "gre.routing.src_length",
651
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
652
14
            "The SRE Length field contains the number of octets in the SRE", HFILL }
653
14
        },
654
14
        { &hf_gre_routing_information,
655
14
          { "Routing Information", "gre.routing.information",
656
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
657
14
            "The Routing Information field contains data which may be used in routing this packet", HFILL }
658
14
        },
659
14
        { &hf_gre_3gpp2_attrib,
660
14
          { "3GPP2 Attributes", "gre.3gpp2_attrib",
661
14
            FT_NONE, BASE_NONE, NULL, 0x0,
662
14
            NULL, HFILL }
663
14
        },
664
14
        { &hf_gre_3gpp2_attrib_id,
665
14
          { "Type", "gre.3gpp2_attrib_id",
666
14
            FT_UINT8, BASE_HEX, VALS(gre_3gpp2_attrib_id_vals), 0x7f,
667
14
            NULL, HFILL }
668
14
        },
669
14
        { &hf_gre_3gpp2_attrib_length,
670
14
          { "Length", "gre.3gpp2_attrib_length",
671
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
672
14
            NULL, HFILL }
673
14
        },
674
14
        { &hf_gre_3gpp2_sdi,
675
14
          { "SDI/DOS", "gre.3gpp2_sdi",
676
14
            FT_BOOLEAN, 16, TFS(&gre_3gpp2_sdi_val), 0x8000,
677
14
            "Short Data Indicator(SDI)/Data Over Signaling (DOS)", HFILL }
678
14
        },
679
14
        { &hf_gre_3gpp2_fci,
680
14
          { "Flow Control Indicator", "gre.3gpp2_fci",
681
14
            FT_BOOLEAN, 16, TFS(&gre_3gpp2_fci_val), 0x8000,
682
14
            NULL, HFILL }
683
14
        },
684
14
        { &hf_gre_3gpp2_di,
685
14
          { "Duration Indicator", "gre.3gpp2_di",
686
14
            FT_BOOLEAN, 16, TFS(&gre_3gpp2_di_val), 0x4000,
687
14
            NULL, HFILL }
688
14
        },
689
14
        { &hf_gre_3gpp2_flow_disc,
690
14
          { "Flow ID", "gre.ggp2_flow_disc",
691
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
692
14
            NULL, HFILL }
693
14
        },
694
14
        { &hf_gre_3gpp2_seg,
695
14
          { "Type", "gre.ggp2_3gpp2_seg",
696
14
            FT_UINT16, BASE_HEX, VALS(gre_3gpp2_seg_vals), 0xc000,
697
14
            NULL, HFILL }
698
14
        },
699
700
14
        { &hf_gre_wccp_redirect_header,
701
14
          { "Redirect Header", "gre.wccp.redirect_header",
702
14
            FT_NONE, BASE_NONE, NULL, 0x0,
703
14
            NULL, HFILL }
704
14
        },
705
14
        { &hf_gre_wccp_dynamic_service,
706
14
          { "Dynamic Service", "gre.wccp.dynamic_service",
707
14
            FT_BOOLEAN, 8, TFS(&gre_wccp_dynamic_service_val), 0x01,
708
14
            NULL, HFILL }
709
14
        },
710
14
        { &hf_gre_wccp_alternative_bucket_used,
711
14
          { "Alternative bucket used", "gre.wccp.alternative_bucket_used",
712
14
            FT_BOOLEAN, 8, TFS(&gre_wccp_alternative_bucket_used_val), 0x02,
713
14
            NULL, HFILL }
714
14
        },
715
14
        { &hf_gre_wccp_redirect_header_valid,
716
14
          { "WCCP Redirect header is valid", "gre.wccp.redirect_header_valid",
717
14
            FT_BOOLEAN, 8, TFS(&gre_wccp_redirect_header_valid_val), 0x04,
718
14
            NULL, HFILL }
719
14
        },
720
14
        { &hf_gre_wccp_service_id,
721
14
          { "Service ID", "gre.wccp.service_id",
722
14
            FT_UINT8, BASE_DEC, VALS(service_id_vals), 0x00,
723
14
            "Service Group identifier", HFILL }
724
14
        },
725
14
        { &hf_gre_wccp_alternative_bucket,
726
14
          { "Alternative Bucket", "gre.wccp.alternative_bucket",
727
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
728
14
            "Alternative bucket index used to redirect the packet.", HFILL }
729
14
        },
730
14
        { &hf_gre_wccp_primary_bucket,
731
14
          { "Primary Bucket", "gre.wccp.primary_bucket",
732
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
733
14
            "Primary bucket index used to redirect the packet.", HFILL  }
734
14
        },
735
14
    };
736
14
    static int *ett[] = {
737
14
        &ett_gre,
738
14
        &ett_gre_flags,
739
14
        &ett_gre_routing,
740
14
        &ett_gre_wccp2_redirect_header,
741
14
        &ett_3gpp2_attribs,
742
14
        &ett_3gpp2_attr,
743
14
    };
744
745
746
14
    static ei_register_info ei[] = {
747
14
        { &ei_gre_checksum_incorrect, { "gre.checksum.incorrect", PI_PROTOCOL, PI_WARN, "Incorrect GRE Checksum", EXPFILL }},
748
14
    };
749
750
14
    expert_module_t* expert_gre;
751
752
14
    proto_gre = proto_register_protocol("Generic Routing Encapsulation",
753
14
                                        "GRE", "gre");
754
14
    gre_handle = register_dissector("gre", dissect_gre, proto_gre);
755
14
    gre_cap_handle = register_capture_dissector("gre", capture_gre, proto_gre);
756
14
    proto_register_field_array(proto_gre, hf, array_length(hf));
757
14
    proto_register_subtree_array(ett, array_length(ett));
758
14
    expert_gre = expert_register_protocol(proto_gre);
759
14
    expert_register_field_array(expert_gre, ei, array_length(ei));
760
761
    /*
762
     * Dissector table.
763
     *
764
     * XXX - according to
765
     *
766
     *    https://www.iana.org/assignments/gre-parameters/gre-parameters.xhtml#gre-parameters-1
767
     *
768
     * these are just Ethertypes; should we use "gre.proto" only for
769
     * protocols *not* registered as Ethertypes, such as those listed
770
     * in the table in "Current List of Protocol Types" in RFC 1701
771
     * ("For historical reasons, a number of other values have been
772
     * used for some protocols."), and for protocols encapsulated in GRE
773
     * differently from the way they're encapsulated over LAN protocols
774
     * (for example, Cisco MetaData), and if we don't get a match there,
775
     * use the "ethertype" table?
776
     *
777
     * And should we also somehow do something similar for mapping values
778
     * to strings, falling back on etype_vals?
779
     */
780
14
    gre_dissector_table = register_dissector_table("gre.proto",
781
14
                                                   "GRE protocol type", proto_gre, FT_UINT16, BASE_HEX);
782
783
14
    gre_subdissector_table = register_decode_as_next_proto(proto_gre, "gre.subproto",
784
14
                                                                "GRE protocol type", gre_prompt);
785
14
}
786
787
void
788
proto_reg_handoff_gre(void)
789
14
{
790
14
    dissector_add_uint("ip.proto", IP_PROTO_GRE, gre_handle);
791
14
    dissector_add_uint("udp.port", GRE_IN_UDP_PORT, gre_handle);
792
14
    capture_dissector_add_uint("ip.proto", IP_PROTO_GRE, gre_cap_handle);
793
14
}
794
795
/*
796
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
797
 *
798
 * Local variables:
799
 * c-basic-offset: 4
800
 * tab-width: 8
801
 * indent-tabs-mode: nil
802
 * End:
803
 *
804
 * vi: set shiftwidth=4 tabstop=8 expandtab:
805
 * :indentSize=4:tabSize=8:noTabs=true:
806
 */