Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-igrp.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-igrp.c
2
 * Routines for IGRP dissection
3
 * Copyright 2000, Paul Ionescu <paul@acorp.ro>
4
 *
5
 * See
6
 *
7
 *   http://www.cisco.com/en/US/tech/tk365/technologies_white_paper09186a00800c8ae1.shtml
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * Copied from packet-syslog.c
14
 *
15
 * SPDX-License-Identifier: GPL-2.0-or-later
16
 */
17
18
#include "config.h"
19
20
#include <epan/packet.h>
21
#include <epan/expert.h>
22
#include <epan/to_str.h>
23
#include <epan/ipproto.h>
24
#include <epan/tfs.h>
25
#include <epan/unit_strings.h>
26
27
void proto_register_igrp(void);
28
void proto_reg_handoff_igrp(void);
29
30
49
#define IGRP_HEADER_LENGTH 12
31
1.06k
#define IGRP_ENTRY_LENGTH 14
32
33
static dissector_handle_t igrp_handle;
34
35
static int proto_igrp;
36
static int hf_igrp_update;
37
static int hf_igrp_as;
38
/* Generated from convert_proto_tree_add_text.pl */
39
static int hf_igrp_load;
40
static int hf_igrp_bandwidth;
41
static int hf_igrp_command;
42
static int hf_igrp_reliability;
43
static int hf_igrp_network;
44
static int hf_igrp_version;
45
static int hf_igrp_interior_routes;
46
static int hf_igrp_mtu;
47
static int hf_igrp_hop_count;
48
static int hf_igrp_exterior_routes;
49
static int hf_igrp_delay;
50
static int hf_igrp_checksum;
51
static int hf_igrp_system_routes;
52
static int ett_igrp;
53
static int ett_igrp_vektor;
54
static int ett_igrp_net;
55
56
static expert_field ei_igrp_version;
57
58
static void dissect_vektor_igrp (packet_info *pinfo, tvbuff_t *tvb, proto_tree *igrp_vektor_tree, uint8_t network);
59
60
static int dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
61
49
{
62
49
  uint8_t ver_and_opcode,version,opcode,network;
63
49
  int offset=IGRP_HEADER_LENGTH;
64
49
  uint16_t ninterior,nsystem,nexterior;
65
49
  const uint8_t *ipsrc;
66
49
  proto_item *ti;
67
49
  proto_tree *igrp_tree, *igrp_vektor_tree;
68
49
  tvbuff_t   *next_tvb;
69
70
49
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP");
71
49
  col_clear(pinfo->cinfo, COL_INFO);
72
73
49
  ver_and_opcode = tvb_get_uint8(tvb,0);
74
75
49
  switch (ver_and_opcode) {
76
0
  case 0x11:
77
0
    col_set_str(pinfo->cinfo, COL_INFO, "Response" );
78
0
    break;
79
0
  case 0x12:
80
0
    col_set_str(pinfo->cinfo, COL_INFO, "Request" );
81
0
    break;
82
49
  default:
83
49
    col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
84
49
  }
85
86
87
49
  if (tree) {
88
49
    ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
89
49
                                        "Cisco IGRP");
90
91
49
    igrp_tree = proto_item_add_subtree(ti, ett_igrp);
92
93
49
    version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
94
49
    opcode = ver_and_opcode&0x0f ;       /* opcode is the last half of the byte */
95
96
49
    ti = proto_tree_add_item(igrp_tree, hf_igrp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
97
49
    if (version != 1)
98
43
        expert_add_info(pinfo, ti, &ei_igrp_version);
99
49
    ti = proto_tree_add_item(igrp_tree, hf_igrp_command, tvb, 0, 1, ENC_BIG_ENDIAN);
100
49
    if (opcode==1)
101
2
        proto_item_append_text(ti, " (Response)");
102
47
    else
103
47
        proto_item_append_text(ti, " (Request)");
104
49
    proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, ENC_BIG_ENDIAN);
105
49
    proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, ENC_BIG_ENDIAN);
106
107
49
    ninterior = tvb_get_ntohs(tvb,4);
108
49
    nsystem = tvb_get_ntohs(tvb,6);
109
49
    nexterior = tvb_get_ntohs(tvb,8);
110
111
    /* this is a ugly hack to find the first byte of the IP source address */
112
49
    if (pinfo->net_src.type == AT_IPv4) {
113
24
      ipsrc = (const uint8_t *)pinfo->net_src.data;
114
24
      network = ipsrc[0];
115
24
    } else
116
25
      network = 0; /* XXX - shouldn't happen */
117
118
49
    ti = proto_tree_add_item(igrp_tree, hf_igrp_interior_routes, tvb, 4, 2, ENC_BIG_ENDIAN);
119
217
    for( ; ninterior>0 ; ninterior-- ) {
120
168
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
121
168
      next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
122
168
      dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,network);
123
168
      offset+=IGRP_ENTRY_LENGTH;
124
168
    }
125
126
49
    ti = proto_tree_add_item(igrp_tree, hf_igrp_system_routes, tvb, 6, 2, ENC_BIG_ENDIAN);
127
234
    for( ; nsystem>0 ; nsystem-- ) {
128
185
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
129
185
      next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
130
185
      dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,0);
131
185
      offset+=IGRP_ENTRY_LENGTH;
132
185
    }
133
134
49
    ti = proto_tree_add_item(igrp_tree, hf_igrp_exterior_routes, tvb, 8, 2, ENC_BIG_ENDIAN);
135
226
    for( ; nexterior>0 ; nexterior-- ) {
136
177
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
137
177
      next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
138
177
      dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,0);
139
177
      offset+=IGRP_ENTRY_LENGTH;
140
177
    }
141
142
49
    proto_tree_add_checksum(igrp_tree, tvb, 10, hf_igrp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
143
49
  }
144
49
  return tvb_captured_length(tvb);
145
49
}
146
147
static void dissect_vektor_igrp (packet_info *pinfo, tvbuff_t *tvb, proto_tree *igrp_vektor_tree, uint8_t network)
148
487
{
149
487
  union {
150
487
    uint8_t addr_bytes[4];
151
487
    uint32_t addr_word;
152
487
  } addr;
153
487
  address ip_addr;
154
155
487
  if (network != 0) {
156
    /*
157
     * Interior route; network is the high-order byte, and the three
158
     * bytes in the vector are the lower 3 bytes.
159
     */
160
66
    addr.addr_bytes[0]=network;
161
66
    addr.addr_bytes[1]=tvb_get_uint8(tvb,0);
162
66
    addr.addr_bytes[2]=tvb_get_uint8(tvb,1);
163
66
    addr.addr_bytes[3]=tvb_get_uint8(tvb,2);
164
421
  } else {
165
    /*
166
     * System or exterior route; the three bytes in the vector are
167
     * the three high-order bytes, and the low-order byte is 0.
168
     */
169
421
    addr.addr_bytes[0]=tvb_get_uint8(tvb,0);
170
421
    addr.addr_bytes[1]=tvb_get_uint8(tvb,1);
171
421
    addr.addr_bytes[2]=tvb_get_uint8(tvb,2);
172
421
    addr.addr_bytes[3]=0;
173
421
  }
174
175
487
  set_address(&ip_addr, AT_IPv4, 4, &addr);
176
487
  igrp_vektor_tree = proto_tree_add_subtree_format(igrp_vektor_tree, tvb, 0 ,14,
177
487
                                                   ett_igrp_net, NULL, "Entry for network %s", address_to_str(pinfo->pool, &ip_addr));
178
487
  proto_tree_add_ipv4(igrp_vektor_tree, hf_igrp_network, tvb, 0, 3, addr.addr_word);
179
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_delay, tvb, 3, 3, ENC_BIG_ENDIAN);
180
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_bandwidth, tvb, 6, 3, ENC_BIG_ENDIAN);
181
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_mtu, tvb, 9, 2, ENC_BIG_ENDIAN);
182
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_reliability, tvb, 11, 1, ENC_BIG_ENDIAN);
183
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_load, tvb, 12, 1, ENC_BIG_ENDIAN);
184
487
  proto_tree_add_item(igrp_vektor_tree, hf_igrp_hop_count, tvb, 13, 1, ENC_BIG_ENDIAN);
185
487
}
186
187
188
/* Register the protocol with Wireshark */
189
void proto_register_igrp(void)
190
14
{
191
192
  /* Setup list of header fields */
193
14
  static hf_register_info hf[] = {
194
195
14
    { &hf_igrp_update,
196
14
      { "Update Release",           "igrp.update",
197
14
      FT_UINT8, BASE_DEC, NULL, 0x0 ,
198
14
      "Update Release number", HFILL }
199
14
    },
200
14
    { &hf_igrp_as,
201
14
      { "Autonomous System",           "igrp.as",
202
14
      FT_UINT16, BASE_DEC, NULL, 0x0 ,
203
14
      "Autonomous System number", HFILL }
204
14
    },
205
206
    /* Generated from convert_proto_tree_add_text.pl */
207
14
    { &hf_igrp_version, { "IGRP Version", "igrp.version", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
208
14
    { &hf_igrp_command, { "Command", "igrp.command", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
209
14
    { &hf_igrp_interior_routes, { "Interior routes", "igrp.interior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
210
14
    { &hf_igrp_system_routes, { "System routes", "igrp.system_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
211
14
    { &hf_igrp_exterior_routes, { "Exterior routes", "igrp.exterior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
212
14
    { &hf_igrp_checksum, { "Checksum", "igrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
213
14
    { &hf_igrp_network, { "Network", "igrp.network", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
214
14
    { &hf_igrp_delay, { "Delay", "igrp.delay", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
215
14
    { &hf_igrp_bandwidth, { "Bandwidth", "igrp.bandwidth", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
216
14
    { &hf_igrp_mtu, { "MTU", "igrp.mtu", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
217
14
    { &hf_igrp_reliability, { "Reliability", "igrp.reliability", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
218
14
    { &hf_igrp_load, { "Load", "igrp.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
219
14
    { &hf_igrp_hop_count, { "Hop count", "igrp.hop_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
220
14
  };
221
222
  /* Setup protocol subtree array */
223
14
  static int *ett[] = {
224
14
    &ett_igrp,
225
14
    &ett_igrp_vektor,
226
14
    &ett_igrp_net
227
14
  };
228
229
14
  static ei_register_info ei[] = {
230
14
    { &ei_igrp_version, { "igrp.version.invalid", PI_PROTOCOL, PI_WARN, "Unknown Version, The dissection may be inaccurate", EXPFILL }},
231
14
  };
232
233
14
  expert_module_t* expert_igrp;
234
235
  /* Register the protocol name and description */
236
14
  proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
237
14
                                       "IGRP", "igrp");
238
14
  igrp_handle = register_dissector("igrp", dissect_igrp, proto_igrp);
239
240
  /* Required function calls to register the header fields and subtrees used */
241
14
  proto_register_field_array(proto_igrp, hf, array_length(hf));
242
14
  proto_register_subtree_array(ett, array_length(ett));
243
14
  expert_igrp = expert_register_protocol(proto_igrp);
244
14
  expert_register_field_array(expert_igrp, ei, array_length(ei));
245
14
}
246
247
void
248
proto_reg_handoff_igrp(void)
249
14
{
250
14
  dissector_add_uint("ip.proto", IP_PROTO_IGRP, igrp_handle);
251
14
}
252
253
/*    IGRP Packet structure:
254
255
HEADER structure + k * VECTOR structure
256
where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
257
258
HEADER structure is 12 bytes as follows :
259
260
4  bits         Version (only version 1 is defined)
261
4  bits         Opcode (1=Replay, 2=Request)
262
8  bits         Update Release
263
16 bits         Autonomous system number
264
16 bits         Number of Interior routes
265
16 bits         Number of System routes
266
16 bits         Number of Exterior routes
267
16 bits         Checksum
268
-------
269
12 bytes in header
270
271
VECTOR structure is 14 bytes as follows :
272
24 bits         Network
273
24 bits         Delay
274
24 bits         Bandwidth
275
16 bits         MTU
276
8  bits         Reliability
277
8  bits         Load
278
8  bits         Hop count
279
-------
280
14 bytes in 1 vector
281
282
It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
283
If it is a interior route then this 3 bytes are the final bytes, and the first one is taken from the source ip address of the ip packet
284
If it is a system route or a exterior route then this 3 bytes are the first three and the last byte is not important
285
286
If the Delay is 0xFFFFFF then the network is unreachable
287
288
*/
289
290
/*
291
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
292
 *
293
 * Local Variables:
294
 * c-basic-offset: 2
295
 * tab-width: 8
296
 * indent-tabs-mode: nil
297
 * End:
298
 *
299
 * ex: set shiftwidth=2 tabstop=8 expandtab:
300
 * :indentSize=2:tabSize=8:noTabs=true:
301
 */