Don't guard col_set_str (COL_PROTOCOL) with col_check
[obnox/wireshark/wip.git] / epan / dissectors / packet-igrp.c
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  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * Copied from packet-syslog.c
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39
40 #include <string.h>
41 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/ipproto.h>
44
45 #define IGRP_HEADER_LENGTH 12
46 #define IGRP_ENTRY_LENGTH 14
47
48 static gint proto_igrp = -1;
49 static gint hf_igrp_update = -1;
50 static gint hf_igrp_as = -1;
51
52 static gint ett_igrp = -1;
53 static gint ett_igrp_vektor = -1;
54 static gint ett_igrp_net = -1;
55
56 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network);
57
58 static void dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
59 {
60   guint8 ver_and_opcode,version,opcode,network;
61   gint offset=IGRP_HEADER_LENGTH;
62   guint16 ninterior,nsystem,nexterior;
63   const guint8 *ipsrc;
64   proto_item *ti;
65   proto_tree *igrp_tree, *igrp_vektor_tree;
66   tvbuff_t   *next_tvb;
67
68   col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP");
69   if (check_col(pinfo->cinfo, COL_INFO))
70     col_clear(pinfo->cinfo, COL_INFO);
71
72   ver_and_opcode = tvb_get_guint8(tvb,0);
73
74
75   if (check_col(pinfo->cinfo, COL_INFO)) {
76     switch (ver_and_opcode) {
77     case 0x11:
78         col_set_str(pinfo->cinfo, COL_INFO, "Response" );
79         break;
80     case 0x12:
81         col_set_str(pinfo->cinfo, COL_INFO, "Request" );
82         break;
83     default:
84         col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
85     }
86   }
87
88
89
90
91   if (tree) {
92     ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
93                                         "Cisco IGRP");
94
95     igrp_tree = proto_item_add_subtree(ti, ett_igrp);
96
97     version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
98     opcode = ver_and_opcode&0x0f ;       /* opcode is the last half of the byte */
99
100     proto_tree_add_text(igrp_tree,  tvb, 0,1,"IGRP Version  : %d %s",version,(version==1?" ":" -  Unknown Version, The dissection may be inaccurate"));
101     proto_tree_add_text(igrp_tree,  tvb, 0,1,"Command       : %d %s",opcode,(opcode==1?"(Response)":"(Request)"));
102     proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, FALSE);
103     proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, FALSE);
104
105     ninterior = tvb_get_ntohs(tvb,4);
106     nsystem = tvb_get_ntohs(tvb,6);
107     nexterior = tvb_get_ntohs(tvb,8);
108
109     /* this is a ugly hack to find the first byte of the IP source address */
110     if (pinfo->net_src.type == AT_IPv4) {
111       ipsrc = pinfo->net_src.data;
112       network = ipsrc[0];
113     } else
114       network = 0; /* XXX - shouldn't happen */
115
116     ti = proto_tree_add_text(igrp_tree,  tvb, 4,2,"Interior routes : %d",ninterior);
117     for( ; ninterior>0 ; ninterior-- ) {
118       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
119       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
120       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
121       offset+=IGRP_ENTRY_LENGTH;
122     }
123
124     ti = proto_tree_add_text(igrp_tree,  tvb, 6,2,"System routes   : %d",nsystem);
125     for( ; nsystem>0 ; nsystem-- ) {
126       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
127       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
128       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
129       offset+=IGRP_ENTRY_LENGTH;
130     }
131
132     ti = proto_tree_add_text(igrp_tree,  tvb, 8,2,"Exterior routes : %d",nexterior);
133     for( ; nexterior>0 ; nexterior-- ) {
134       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
135       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
136       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
137       offset+=IGRP_ENTRY_LENGTH;
138     }
139
140     proto_tree_add_text(igrp_tree, tvb, 10,2,"Checksum = 0x%4x",tvb_get_ntohs(tvb,10));
141   }
142 }
143
144 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network)
145 {
146         proto_item *ti;
147         guint8 *ptr_addr,addr[5];
148
149         addr[0]=network;
150         addr[1]=tvb_get_guint8(tvb,0);
151         addr[2]=tvb_get_guint8(tvb,1);
152         addr[3]=tvb_get_guint8(tvb,2);
153         addr[4]=0;
154
155         ptr_addr=addr;
156         if (network==0) ptr_addr=&addr[1];
157
158         ti = proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,14,
159           "Entry for network %s", ip_to_str(ptr_addr)) ;
160         igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_net);
161         proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,3,"Network     = %s",ip_to_str(ptr_addr)) ;
162         proto_tree_add_text (igrp_vektor_tree, tvb, 3 ,3,"Delay       = %d",tvb_get_ntoh24(tvb,3)) ;
163         proto_tree_add_text (igrp_vektor_tree, tvb, 6 ,3,"Bandwidth   = %d",tvb_get_ntoh24(tvb,6)) ;
164         proto_tree_add_text (igrp_vektor_tree, tvb, 9 ,2,"MTU         = %d  bytes",tvb_get_ntohs(tvb,9)) ;
165         proto_tree_add_text (igrp_vektor_tree, tvb, 11,1,"Reliability = %d",tvb_get_guint8(tvb,11)) ;
166         proto_tree_add_text (igrp_vektor_tree, tvb, 12,1,"Load        = %d",tvb_get_guint8(tvb,12)) ;
167         proto_tree_add_text (igrp_vektor_tree, tvb, 13,1,"Hop count   = %d  hops",tvb_get_guint8(tvb,13)) ;
168 }
169
170
171 /* Register the protocol with Wireshark */
172 void proto_register_igrp(void)
173 {
174
175   /* Setup list of header fields */
176   static hf_register_info hf[] = {
177
178     { &hf_igrp_update,
179       { "Update Release",           "igrp.update",
180       FT_UINT8, BASE_DEC, NULL, 0x0 ,
181       "Update Release number", HFILL }
182     },
183     { &hf_igrp_as,
184       { "Autonomous System",           "igrp.as",
185       FT_UINT16, BASE_DEC, NULL, 0x0 ,
186       "Autonomous System number", HFILL }
187     }
188   };
189
190   /* Setup protocol subtree array */
191   static gint *ett[] = {
192     &ett_igrp,
193     &ett_igrp_vektor,
194     &ett_igrp_net
195   };
196
197   /* Register the protocol name and description */
198   proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
199                                        "IGRP", "igrp");
200
201   /* Required function calls to register the header fields and subtrees used */
202   proto_register_field_array(proto_igrp, hf, array_length(hf));
203   proto_register_subtree_array(ett, array_length(ett));
204 }
205
206 void
207 proto_reg_handoff_igrp(void)
208 {
209   dissector_handle_t igrp_handle;
210
211   igrp_handle = create_dissector_handle(dissect_igrp, proto_igrp);
212   dissector_add("ip.proto", IP_PROTO_IGRP, igrp_handle);
213 }
214
215 /*      IGRP Packet structure:
216
217 HEADER structure + k * VECTOR structure
218 where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
219
220 HEADER structure is 12 bytes as follows :
221
222 4  bits         Version (only version 1 is defined)
223 4  bits         Opcode (1=Replay, 2=Request)
224 8  bits         Update Release
225 16 bits         Autonomous system number
226 16 bits         Number of Interior routes
227 16 bits         Number of System routes
228 16 bits         Number of Exterior routes
229 16 bits         Checksum
230 -------
231 12 bytes in header
232
233 VECTOR structure is 14 bytes as follows :
234 24 bits         Network
235 24 bits         Delay
236 24 bits         Bandwidth
237 16 bits         MTU
238 8  bits         Reliability
239 8  bits         Load
240 8  bits         Hop count
241 -------
242 14 bytes in 1 vector
243
244 It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
245 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
246 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
247
248 If the Delay is 0xFFFFFF then the network is unreachable
249
250 */