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