Remove executable bit, from not executable files.
[metze/wireshark/wip.git] / epan / dissectors / packet-dsr.c
1 /* packet-dsr.c
2  * Routines for DSR dissection
3  * Copyright 2014, ENAC - Gilles Roudiere <gilles.roudiere@enac.fr or gilles@roudiere.net>
4  * ENAC's URL : http://www.enac.fr/
5  * Mail to : gilles.roudiere@enac.fr or nicolas.larrieu@enac.fr
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #include <epan/packet.h>
29 #include <epan/ipproto.h>
30 #include <epan/addr_resolv.h>
31
32 /* Please refer to rfc4728 for DSR protocol specifications */
33
34 /* Forward declaration that is needed below if using the
35  * proto_reg_handoff_dsr function as a callback for when protocol
36  * preferences get changed. */
37 void proto_reg_handoff_dsr(void);
38 void proto_register_dsr(void);
39
40 static dissector_table_t ip_dissector_table;
41
42 /* Initialize the protocol and registered fields */
43 static int proto_dsr = -1;
44 /* DSR global fields */
45 static int hf_dsr_nexthdr = -1;
46 static int hf_dsr_flowstate = -1;
47 static int hf_dsr_reserved = -1;
48 static int hf_dsr_length = -1;
49 static int hf_dsr_opttype = -1;
50 static int hf_dsr_optlen = -1;
51 static int hf_dsr_fs_hopcount = -1;
52 static int hf_dsr_fs_id = -1;
53 /* RREQ option fields */
54 static int hf_dsr_opt_rreq_id = -1;
55 static int hf_dsr_opt_rreq_targetaddress = -1;
56 static int hf_dsr_opt_rreq_address = -1;
57 /* RREP option fields */
58 static int hf_dsr_opt_rrep_lasthopex = -1;
59 static int hf_dsr_opt_rrep_reserved = -1;
60 static int hf_dsr_opt_rrep_address = -1;
61 /* RERR option fields */
62 static int hf_dsr_opt_err_type = -1;
63 static int hf_dsr_opt_err_reserved = -1;
64 static int hf_dsr_opt_err_salvage = -1;
65 static int hf_dsr_opt_err_src = -1;
66 static int hf_dsr_opt_err_dest = -1;
67 static int hf_dsr_opt_err_unreach_addr = -1;
68 static int hf_dsr_opt_err_unsupportedoption = -1;
69 static int hf_dsr_opt_err_unknownflow_dest = -1;
70 static int hf_dsr_opt_err_unknownflow_id = -1;
71 static int hf_dsr_opt_err_defaultflowunknown_dest = -1;
72 /* ACK REQuest option fields */
73 static int hf_dsr_opt_ack_req_id = -1;
74 static int hf_dsr_opt_ack_req_address = -1;
75 /* ACK option fields */
76 static int hf_dsr_opt_ack_id = -1;
77 static int hf_dsr_opt_ack_src = -1;
78 static int hf_dsr_opt_ack_dest = -1;
79 /* SRCRT option fields */
80 static int hf_dsr_opt_srcrt_firsthopext = -1;
81 static int hf_dsr_opt_srcrt_lasthopext = -1;
82 static int hf_dsr_opt_srcrt_reserved = -1;
83 static int hf_dsr_opt_srcrt_salvage = -1;
84 static int hf_dsr_opt_srcrt_segsleft = -1;
85 static int hf_dsr_opt_srcrt_address = -1;
86 /* Flow State Extentions */
87 /* Timout option fields */
88 static int hf_dsr_fs_opt_timeout_timeout = -1;
89 /* Flow ID / destination option fields */
90 static int hf_dsr_fs_opt_destflowid_id = -1;
91 static int hf_dsr_fs_opt_destflowid_dest = -1;
92
93 /* Initialize the subtree pointers */
94 static gint ett_dsr = -1;
95 /* DSR options tree */
96 static gint ett_dsr_options = -1;
97 static gint ett_dsr_rreq_opt = -1;
98 static gint ett_dsr_rrep_opt = -1;
99 static gint ett_dsr_rerr_opt = -1;
100 static gint ett_dsr_ackreq_opt = -1;
101 static gint ett_dsr_ack_opt = -1;
102 static gint ett_dsr_srcrt_opt = -1;
103 static gint ett_dsr_padn_opt = -1;
104 static gint ett_dsr_pad1_opt = -1;
105 static gint ett_dsr_fs_timeout_opt = -1;
106 static gint ett_dsr_fs_destflowid_opt = -1;
107
108 /* hoplist trees */
109 static gint ett_dsr_rreq_hoplist = -1;
110 static gint ett_dsr_rrep_hoplist = -1;
111 static gint ett_dsr_srcrt_hoplist = -1;
112
113 /* A sample #define of the minimum length (in bytes) of the protocol data.
114  * If data is received with fewer than this many bytes it is rejected by
115  * the current dissector. */
116 #define DSR_MIN_LENGTH 4
117
118 /* DSR option types */
119 #define DSR_OPT_TYPE_RREQ 1
120 #define DSR_OPT_TYPE_RREP 2
121 #define DSR_OPT_TYPE_RERR 3
122 #define DSR_OPT_TYPE_ACKREQ 160
123 #define DSR_OPT_TYPE_ACK 32
124 #define DSR_OPT_TYPE_SRCRT 96
125 #define DSR_OPT_TYPE_PAD1 224
126 #define DSR_OPT_TYPE_PADN 0
127 /* DSR Flow State extention types */
128 #define DSR_FS_OPT_TYPE_TIMEOUT 128
129 #define DSR_FS_OPT_TYPE_DESTFLOWID 129
130 /* Route error types */
131 #define DSR_RERR_TYPE_UNREACHABLE 1
132 #define DSR_RERR_TYPE_FLOWSTATENOTSUPPORTED 2
133 #define DSR_RERR_TYPE_OPTIONNOTSUPPORTED 3
134 #define DSR_RERR_TYPE_UNKNOWNFLOW 129
135 #define DSR_RERR_TYPE_DEFAULTFLOWUNKNOWN 130
136
137 /* DSR option names */
138 static const value_string dsropttypenames[] ={
139         {DSR_OPT_TYPE_RREQ,   "Route request"},
140         {DSR_OPT_TYPE_RREP,   "Route reply"},
141         {DSR_OPT_TYPE_RERR,   "Route error"},
142         {DSR_OPT_TYPE_ACKREQ, "Acknowledgement request"},
143         {DSR_OPT_TYPE_ACK,    "Acknowledgement"},
144         {DSR_OPT_TYPE_SRCRT,  "Source route"},
145         {DSR_OPT_TYPE_PAD1,   "Padding by 1"},
146         {DSR_OPT_TYPE_PADN,   "Padding by N"},
147         {0, NULL}
148 };
149
150 /* DSR Route error names */
151 static const value_string dsrrerrtypenames[] ={
152         {DSR_RERR_TYPE_UNREACHABLE,           "Unreachable node"},
153         {DSR_RERR_TYPE_FLOWSTATENOTSUPPORTED, "Flow state not supported"},
154         {DSR_RERR_TYPE_OPTIONNOTSUPPORTED,    "Option not supported"},
155         {DSR_RERR_TYPE_UNKNOWNFLOW,           "Unknown flow"},
156         {DSR_RERR_TYPE_UNKNOWNFLOW,           "Default flow unknown"},
157         {0, NULL}
158 };
159
160 /* Code to actually dissect the packets */
161 static int
162 dissect_dsr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
163         void *data _U_)
164 {
165     /* Set up structures needed to add the protocol subtree and manage it */
166     proto_item *ti_main, *ti, *ti_hoplist;
167     proto_tree *dsr_tree, *opt_tree, *options_tree, *opt_hoplist_tree;
168     /* Other misc. local variables. */
169     guint offset = 0;           /* Global offset in DSR packet */
170     guint offset_in_option = 0; /* Per-option offset */
171     guint nexthdr, opt_tot_len, opt_len, opt_type, opt_id, opt_err_type, flowstate_hdr;
172     guint i;
173
174     tvbuff_t *next_tvb;
175
176     /* Check that the packet is long enough for it to belong to us. */
177     if (tvb_reported_length(tvb) < DSR_MIN_LENGTH)
178         return 0;
179
180     /* Set the Protocol column to the constant string of dsr */
181     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSR");
182     col_add_str(pinfo->cinfo, COL_INFO, "Options : ");
183
184     /* create display subtree for the protocol */
185     ti_main = proto_tree_add_item(tree, proto_dsr, tvb, 0, -1, ENC_NA);
186     dsr_tree = proto_item_add_subtree(ti_main, ett_dsr);
187
188     proto_tree_add_item(dsr_tree, hf_dsr_nexthdr, tvb, offset, 1, ENC_BIG_ENDIAN); /* Next header */
189     nexthdr = tvb_get_guint8(tvb, offset);
190     offset += 1;
191
192     proto_tree_add_item(dsr_tree, hf_dsr_flowstate, tvb, offset, 1, ENC_BIG_ENDIAN); /* Flowstate */
193     flowstate_hdr = tvb_get_bits8(tvb, offset*8, 1);
194
195     /*DSR normal header*/
196     if (!flowstate_hdr) {
197         proto_tree_add_item(dsr_tree, hf_dsr_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); /* Reserved */
198         offset += 1;
199
200         proto_tree_add_item(dsr_tree, hf_dsr_length, tvb, offset, 2, ENC_BIG_ENDIAN);  /* Dsr opt tot length */
201         opt_tot_len = tvb_get_ntohs(tvb, offset);
202         proto_item_set_len(ti_main, opt_tot_len+4);
203         offset += 2;
204
205         options_tree = proto_tree_add_subtree(dsr_tree, tvb, offset, opt_tot_len, ett_dsr_options, NULL, "Options"); /* DSR options */
206
207         /* DSR options dissection */
208         while (offset - 4 < opt_tot_len) {
209                 opt_type = tvb_get_guint8(tvb, offset);
210                 offset_in_option = offset;
211                 opt_len = 0;
212                 switch(opt_type) {
213                         case DSR_OPT_TYPE_RREQ:
214                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_rreq_opt, &ti, "Route request"); /* Opt subtree */
215                                 col_append_str(pinfo->cinfo, COL_INFO, "Route request");
216
217                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
218                                 offset_in_option += 1;
219
220                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt len */
221                                 opt_len = tvb_get_guint8(tvb, offset_in_option);
222                                 proto_item_set_len(ti, opt_len+2);
223                                 offset_in_option += 1;
224
225                                 proto_tree_add_item(opt_tree, hf_dsr_opt_rreq_id, tvb, offset_in_option, 2, ENC_BIG_ENDIAN); /* Opt rreq id */
226                                 opt_id = tvb_get_ntohs(tvb, offset_in_option);
227                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (id=0x%x)", opt_id);
228                                 offset_in_option += 2;
229
230                                 proto_tree_add_item(opt_tree, hf_dsr_opt_rreq_targetaddress, tvb, offset_in_option, 4, ENC_NA); /* Opt rreq target address */
231                                 offset_in_option += 4;
232
233                                 if(opt_len > 6) {
234                                         opt_hoplist_tree = proto_tree_add_subtree(opt_tree, tvb, offset_in_option, 1, ett_dsr_rreq_hoplist, &ti_hoplist, "Hop list" ); /* Opt hop list */
235                                         proto_item_append_text(ti_hoplist, " :");
236                                         for(i=0;i<(opt_len-4)/4;i++) {
237                                                 proto_tree_add_item(opt_hoplist_tree, hf_dsr_opt_rreq_address, tvb, offset_in_option, 4, ENC_NA); /* Opt rreq address */
238                                                 proto_item_append_text(ti_hoplist, " %s", tvb_ip_to_str(tvb, offset_in_option));
239                                                 offset_in_option += 4;
240                                         }
241                                 }
242                                 break;
243                         case DSR_OPT_TYPE_RREP:
244                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_rrep_opt, &ti, "Route reply"); /* Opt subtree */
245                                 col_append_str(pinfo->cinfo, COL_INFO, "Route reply");
246
247                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
248                                 offset_in_option += 1;
249
250                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt len */
251                                 opt_len = tvb_get_guint8(tvb, offset_in_option);
252                                 proto_item_set_len(ti, opt_len+2);
253                                 offset_in_option += 1;
254
255                                 proto_tree_add_item(opt_tree, hf_dsr_opt_rrep_lasthopex, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt rrep reserved */
256                                 proto_tree_add_item(opt_tree, hf_dsr_opt_rrep_reserved, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt rrep reserved */
257                                 offset_in_option += 1;
258
259                                 if(opt_len > 2) {
260                                         opt_hoplist_tree = proto_tree_add_subtree(opt_tree, tvb, offset_in_option, 1, ett_dsr_rrep_hoplist, &ti_hoplist, "Hop list" ); /* Opt hop list */
261                                         proto_item_append_text(ti_hoplist, " :");
262                                         for(i=0;i<(opt_len-1)/4;i++) {
263                                                 proto_tree_add_item(opt_hoplist_tree, hf_dsr_opt_rrep_address, tvb, offset_in_option, 4, ENC_NA); /*Opt rrep address */
264                                                 proto_item_append_text(ti_hoplist, " %s", tvb_ip_to_str(tvb, offset_in_option));
265                                                 offset_in_option += 4;
266                                         }
267                                 }
268                                 break;
269                         case DSR_OPT_TYPE_RERR:
270                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_rerr_opt, &ti, "Route error"); /* Opt subtree */
271                                 col_append_str(pinfo->cinfo, COL_INFO, "Route error");
272
273                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
274                                 offset_in_option += 1;
275
276                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt len */
277                                 opt_len = tvb_get_guint8(tvb, offset_in_option);
278                                 proto_item_set_len(ti, opt_len+2);
279                                 offset_in_option += 1;
280
281                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_type, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt err type */
282                                 opt_err_type = tvb_get_guint8(tvb, offset_in_option);
283                                 offset_in_option += 1;
284
285                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_err_reserved, tvb, offset_in_option*8, 4, ENC_BIG_ENDIAN); /*Opt err reserved */
286                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_err_salvage, tvb, offset_in_option*8+4, 4, ENC_BIG_ENDIAN); /*Opt err salvage */
287                                 offset_in_option += 1;
288
289                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_src, tvb, offset_in_option, 4, ENC_NA); /*Opt err source address */
290                                 offset_in_option += 4;
291
292                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_dest, tvb, offset_in_option, 4, ENC_NA); /* Opt err dest address */
293                                 offset_in_option += 4;
294
295                                 switch(opt_err_type) {
296                                         case DSR_RERR_TYPE_UNREACHABLE:
297                                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_unreach_addr, tvb, offset_in_option, 4, ENC_NA); /* Opt err unreachable node address */
298                                                 /*offset_in_option += 4;*/
299                                                 break;
300                                         case DSR_RERR_TYPE_FLOWSTATENOTSUPPORTED:
301                                                 break;
302                                         case DSR_RERR_TYPE_OPTIONNOTSUPPORTED:
303                                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_unsupportedoption, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt err unsupported opt */
304                                                 /*offset_in_option += 1;*/
305                                                 break;
306                                         case DSR_RERR_TYPE_UNKNOWNFLOW:
307                                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_unknownflow_dest, tvb, offset_in_option, 4, ENC_NA);/* Opt err unknown flow original ip destination address */
308                                                 offset_in_option += 4;
309
310                                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_unknownflow_id, tvb, offset_in_option, 2, ENC_BIG_ENDIAN);/* Opt err unknown flow flow id */
311                                                 /*offset_in_option += 1;*/
312                                                 break;
313                                         case DSR_RERR_TYPE_DEFAULTFLOWUNKNOWN:
314                                                 proto_tree_add_item(opt_tree, hf_dsr_opt_err_defaultflowunknown_dest, tvb, offset_in_option, 4, ENC_NA);/* opt err default flow unknown original ip destination address */
315                                                 /*offset_in_option += 4;*/
316                                                 break;
317                                 }
318                                 break;
319                         case DSR_OPT_TYPE_ACKREQ:
320                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_ackreq_opt, &ti, "Acknowledgement request"); /* Opt subtree */
321                                 col_append_str(pinfo->cinfo, COL_INFO, "Ack request");
322
323                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
324                                 offset_in_option += 1;
325
326                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt len */
327                                 opt_len = tvb_get_guint8(tvb, offset_in_option);
328                                 proto_item_set_len(ti, opt_len+2);
329                                 offset_in_option += 1;
330
331                                 proto_tree_add_item(opt_tree, hf_dsr_opt_ack_req_id, tvb, offset_in_option, 2, ENC_BIG_ENDIAN); /* Opt ack req id */
332                                 opt_id = tvb_get_ntohs(tvb, offset_in_option);
333                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (id=0x%x)", opt_id);
334                                 offset_in_option += 2;
335
336                                 if(opt_len >= 6) {
337                                         proto_tree_add_item(opt_tree, hf_dsr_opt_ack_req_address, tvb, offset_in_option, 4, ENC_NA); /* Opt ack req id */
338                                         /*offset_in_option += 4;*/
339                                 }
340                                 break;
341                         case DSR_OPT_TYPE_ACK:
342                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_ack_opt, &ti, "Acknowledgement"); /* Opt subtree */
343                                 col_append_str(pinfo->cinfo, COL_INFO, "Ack");
344
345                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
346                                 offset_in_option += 1;
347
348                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt len */
349                                 opt_len = tvb_get_guint8(tvb, offset_in_option);
350                                 proto_item_set_len(ti, opt_len+2);
351                                 offset_in_option += 1;
352
353
354                                 proto_tree_add_item(opt_tree, hf_dsr_opt_ack_id, tvb, offset_in_option, 2, ENC_BIG_ENDIAN); /* Opt ack id */
355                                 opt_id = tvb_get_ntohs(tvb, offset_in_option);
356                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (id=0x%x)", opt_id);
357                                 offset_in_option += 2;
358
359                                 proto_tree_add_item(opt_tree, hf_dsr_opt_ack_src, tvb, offset_in_option, 4, ENC_NA); /* Opt ack source address */
360                                 offset_in_option += 4;
361
362                                 proto_tree_add_item(opt_tree, hf_dsr_opt_ack_dest, tvb, offset_in_option, 4, ENC_NA); /* Opt ack dest address */
363                                 /*offset_in_option += 4;*/
364                                 break;
365                         case DSR_OPT_TYPE_SRCRT:
366                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_srcrt_opt, &ti, "Source route"); /* Opt subtree */
367                                 col_append_str(pinfo->cinfo, COL_INFO, "Source route");
368
369                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
370                                 offset_in_option += 1;
371
372                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option,  1, ENC_BIG_ENDIAN); /* Opt len */
373                                 opt_len = tvb_get_guint8(tvb, offset_in_option );
374                                 proto_item_set_len(ti, opt_len+2);
375                                 offset_in_option += 1;
376
377                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_srcrt_firsthopext, tvb, offset_in_option*8, 1, ENC_BIG_ENDIAN); /* Opt srcrt first hop external */
378                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_srcrt_lasthopext, tvb, offset_in_option*8+1, 1, ENC_BIG_ENDIAN); /* Opt srcrt last hop external */
379                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_srcrt_reserved, tvb, offset_in_option*8+2, 4, ENC_BIG_ENDIAN); /* Opt srcrt reserved */
380                                 proto_tree_add_bits_item(opt_tree, hf_dsr_opt_srcrt_salvage, tvb, offset_in_option*8+6, 4, ENC_BIG_ENDIAN); /* Opt srcrt salvage */
381                                 offset_in_option += 1;
382                                 proto_tree_add_item(opt_tree, hf_dsr_opt_srcrt_segsleft, tvb, offset_in_option , 1, ENC_BIG_ENDIAN); /* Opt srcrt segs left */
383                                 offset_in_option  += 1;
384
385                                 if(opt_len > 2) {
386                                         opt_hoplist_tree = proto_tree_add_subtree(opt_tree, tvb, offset_in_option, 1, ett_dsr_srcrt_hoplist, &ti_hoplist, "Hop list" ); /* Opt hop list */
387
388                                         proto_item_append_text(ti_hoplist, " :");
389                                         for(i=0;i<(opt_len-2)/4;i++) {
390                                                 proto_tree_add_item(opt_hoplist_tree, hf_dsr_opt_srcrt_address, tvb, offset_in_option , 4, ENC_NA); /* Opt srcrt addresses */
391                                                 proto_item_append_text(ti_hoplist, " %s", tvb_ip_to_str(tvb, offset_in_option));
392                                                 offset_in_option  += 4;
393                                         }
394                                 }
395                                 break;
396                         case DSR_OPT_TYPE_PADN:
397                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_padn_opt, &ti, "PadN"); /* Opt subtree */
398
399                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option , 1, ENC_BIG_ENDIAN); /* Opt type */
400                                 offset_in_option  += 1;
401
402                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option , 1, ENC_BIG_ENDIAN); /* Opt len */
403                                 opt_len = tvb_get_guint8(tvb, offset_in_option );
404                                 proto_item_set_len(ti, opt_len+2);
405                                 /*offset_in_option += 1;
406                                 offset_in_option += opt_len;*/
407                                 break;
408                         case DSR_OPT_TYPE_PAD1:
409                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_pad1_opt, &ti, "Pad1"); /* Opt subtree */
410
411                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option , 1, ENC_BIG_ENDIAN); /* Opt type */
412                                 /*offset_in_option += 1;*/
413                                 break;
414
415                         case DSR_FS_OPT_TYPE_TIMEOUT :
416                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_fs_timeout_opt, &ti, "Timeout"); /* Opt subtree */
417                                 col_append_str(pinfo->cinfo, COL_INFO, "Timeout");
418
419                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
420                                 offset_in_option += 1;
421
422                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option,  1, ENC_BIG_ENDIAN); /* Opt len */
423                                 opt_len = tvb_get_guint8(tvb, offset_in_option );
424                                 proto_item_set_len(ti, opt_len+2);
425                                 offset_in_option += 1;
426
427                                 proto_tree_add_item(opt_tree, hf_dsr_fs_opt_timeout_timeout, tvb, offset_in_option, 2, ENC_BIG_ENDIAN); /* Timeout */
428                                 /*offset_in_option += 2;*/
429                                 break;
430                         case DSR_FS_OPT_TYPE_DESTFLOWID:
431                                 opt_tree = proto_tree_add_subtree(options_tree, tvb, offset_in_option, 1, ett_dsr_fs_destflowid_opt, &ti, "Destination and flow id"); /* Opt subtree */
432                                 col_append_str(pinfo->cinfo, COL_INFO, "Dest&FlowId");
433
434                                 proto_tree_add_item(opt_tree, hf_dsr_opttype, tvb, offset_in_option, 1, ENC_BIG_ENDIAN); /* Opt type */
435                                 offset_in_option += 1;
436
437                                 proto_tree_add_item(opt_tree, hf_dsr_optlen, tvb, offset_in_option,  1, ENC_BIG_ENDIAN); /* Opt len */
438                                 opt_len = tvb_get_guint8(tvb, offset_in_option );
439                                 proto_item_set_len(ti, opt_len+2);
440                                 offset_in_option += 1;
441
442                                 proto_tree_add_item(opt_tree, hf_dsr_fs_opt_destflowid_id, tvb, offset_in_option, 2, ENC_BIG_ENDIAN); /* Flow ID */
443                                 offset_in_option += 2;
444
445                                 proto_tree_add_item(opt_tree, hf_dsr_fs_opt_destflowid_dest, tvb, offset_in_option, 4, ENC_NA); /* Original IP Dest Address */
446                                 /*offset_in_option += 4;*/
447                                 break;
448                 }
449                 if (opt_type != DSR_OPT_TYPE_PAD1)
450                         offset += 2+opt_len;
451                 else
452                         offset += 1;
453                 if(offset-4 < opt_tot_len && opt_type != DSR_OPT_TYPE_PAD1 && opt_type != DSR_OPT_TYPE_PADN) {
454                         col_append_str(pinfo->cinfo, COL_INFO, ", ");
455                 }
456         }
457     } else { /* DSR Flow state header */
458         proto_tree_add_item(dsr_tree, hf_dsr_fs_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); /* Hop count */
459         offset += 1;
460
461         proto_tree_add_item(dsr_tree, hf_dsr_fs_id, tvb, offset, 1, ENC_BIG_ENDIAN); /* Flow identifier */
462         offset += 2;
463     }
464
465     /* Call other dissectors if needed */
466     next_tvb = tvb_new_subset_remaining(tvb, offset);
467     if (!dissector_try_uint(ip_dissector_table, nexthdr, next_tvb, pinfo, tree)) {
468         call_data_dissector(next_tvb, pinfo, tree);
469     }
470
471     return offset+4;
472 }
473
474 /* Register DSR with Wireshark.*/
475 void
476 proto_register_dsr(void)
477 {
478     /* Setup list of header fields */
479     static hf_register_info hf[] = {
480         { &hf_dsr_nexthdr,
481             { "Next header", "dsr.nexthdr",
482                FT_UINT8, BASE_HEX | BASE_EXT_STRING,
483                &ipproto_val_ext, 0x0,
484                "Next header protocol type", HFILL }
485         },
486         { &hf_dsr_flowstate,
487             { "Flow state", "dsr.flowstate",
488                FT_BOOLEAN, 8,
489                NULL, 0x80,
490                NULL, HFILL }
491         },
492         /* DSR normal header */
493         { &hf_dsr_reserved,
494             { "Reserved", "dsr.reserved",
495                FT_UINT8, BASE_HEX,
496                NULL, 0x7F,
497                NULL, HFILL }
498         },
499         { &hf_dsr_length,
500             { "Length", "dsr.len",
501                FT_UINT8, BASE_DEC,
502                NULL, 0x0,
503               "Payload length", HFILL }
504         },
505         { &hf_dsr_opttype,
506             { "Type", "dsr.option.type",
507                FT_UINT8, BASE_DEC,
508                VALS(dsropttypenames), 0x0,
509                NULL, HFILL }
510         },
511         { &hf_dsr_optlen,
512             { "Length", "dsr.option.len",
513                FT_UINT8, BASE_DEC,
514                NULL, 0x0,
515                "Option length", HFILL }
516         },
517         /* RREQ fields */
518         { &hf_dsr_opt_rreq_id,
519             { "Id", "dsr.option.rreq.id",
520                FT_UINT16, BASE_HEX_DEC,
521                NULL, 0x0,
522                NULL, HFILL }
523         },
524         { &hf_dsr_opt_rreq_targetaddress,
525             { "Target address", "dsr.option.rreq.targetaddress",
526                FT_IPv4, BASE_NONE,
527                NULL, 0x0,
528                "Target IP address", HFILL }
529         },
530         { &hf_dsr_opt_rreq_address,
531             { "Hop", "dsr.option.rreq.address",
532                FT_IPv4, BASE_NONE,
533                NULL, 0x0,
534                NULL, HFILL }
535         },
536         /* RREP fields */
537         { &hf_dsr_opt_rrep_lasthopex,
538             { "Last hop external", "dsr.option.rrep.lasthopex",
539                FT_BOOLEAN, 8,
540                NULL, 0x80,
541                NULL, HFILL }
542         },
543         { &hf_dsr_opt_rrep_reserved,
544             { "Reserved", "dsr.option.rrep.reserved",
545                FT_UINT8, BASE_HEX,
546                NULL, 0x7F,
547                NULL, HFILL }
548         },
549         { &hf_dsr_opt_rrep_address,
550             { "Hop", "dsr.option.rrep.address",
551                FT_IPv4, BASE_NONE,
552                NULL, 0x0,
553                NULL, HFILL }
554         },
555         /* RERR fields */
556         { &hf_dsr_opt_err_type,
557             { "Type", "dsr.option.err.type",
558                FT_UINT8, BASE_DEC,
559                VALS(dsrrerrtypenames), 0x0,
560                NULL, HFILL }
561         },
562         { &hf_dsr_opt_err_reserved,
563             {  "Reserved", "dsr.option.err.reserved",
564                FT_UINT8, BASE_HEX,
565                NULL, 0x00,
566                NULL, HFILL }
567         },
568         { &hf_dsr_opt_err_salvage,
569             {  "Salvage", "dsr.option.err.salvage",
570                FT_UINT8, BASE_HEX,
571
572                NULL, 0x00,
573                NULL, HFILL }
574         },
575         { &hf_dsr_opt_err_src,
576             {  "Source address", "dsr.option.err.src",
577                FT_IPv4, BASE_NONE,
578                NULL, 0x00,
579                "Source IP address", HFILL }
580         },
581         { &hf_dsr_opt_err_dest,
582             {  "Destination address", "dsr.option.err.dest",
583                FT_IPv4, BASE_NONE,
584                NULL, 0x00,
585                "Destination IP address", HFILL }
586         },
587         { &hf_dsr_opt_err_unreach_addr,
588             {  "Unreachable node address", "dsr.option.err.unreachablenode",
589                FT_IPv4, BASE_NONE,
590                NULL, 0x00,
591                "Unreachable node IP address", HFILL }
592         },
593         { &hf_dsr_opt_err_unsupportedoption,
594             {  "Unsupported option", "dsr.option.err.unsupportedoption",
595                FT_UINT8, BASE_HEX,
596                NULL, 0x00,
597                NULL, HFILL }
598         },
599         /* ACKREQ fields */
600         { &hf_dsr_opt_ack_req_id,
601             { "Id", "dsr.option.ackreq.id",
602                FT_UINT16, BASE_HEX_DEC,
603                NULL, 0x0,
604                NULL, HFILL }
605         },
606         { &hf_dsr_opt_ack_req_address,
607             { "Source address", "dsr.option.ackreq.address",
608                FT_IPv4, BASE_NONE,
609                NULL, 0x0,
610                "Source IP address", HFILL }
611         },
612         /* ACK fields */
613         { &hf_dsr_opt_ack_id,
614             { "Id", "dsr.option.ack.id",
615                FT_UINT16, BASE_HEX_DEC,
616                NULL, 0x0,
617                NULL, HFILL }
618         },
619         { &hf_dsr_opt_ack_src,
620             { "Source IP", "dsr.option.ack.source",
621                FT_IPv4, BASE_NONE,
622                NULL, 0x0,
623                "Source IP address", HFILL }
624         },
625         { &hf_dsr_opt_ack_dest,
626             { "Destination IP", "dsr.option.ack.dest",
627                FT_IPv4, BASE_NONE,
628                NULL, 0x0,
629                "Destination IP address", HFILL }
630         },
631         /* SRCRT fields */
632         { &hf_dsr_opt_srcrt_firsthopext,
633             { "First hop external", "dsr.option.srcrt.firsthopext",
634                FT_BOOLEAN, BASE_NONE,
635                NULL, 0x0,
636                NULL, HFILL }
637         },
638         { &hf_dsr_opt_srcrt_lasthopext,
639             { "Last hop external", "dsr.option.srcrt.lasthopext",
640                FT_BOOLEAN, BASE_NONE,
641                NULL, 0x0,
642                NULL, HFILL }
643         },
644         { &hf_dsr_opt_srcrt_reserved,
645             { "Reserved", "dsr.option.srcrt.reserved",
646                FT_UINT8, BASE_HEX,
647                NULL, 0x0,
648                NULL, HFILL }
649         },
650         { &hf_dsr_opt_srcrt_salvage,
651             { "Salvage", "dsr.option.srcrt.salvage",
652                FT_UINT8, BASE_HEX,
653                NULL, 0x0,
654                NULL, HFILL }
655         },
656         { &hf_dsr_opt_srcrt_segsleft,
657             { "Segments left", "dsr.option.srcrt.segsleft",
658                FT_UINT8, BASE_DEC,
659                NULL, 0x3F,
660                NULL, HFILL }
661         },
662         { &hf_dsr_opt_srcrt_address,
663             { "Hop", "dsr.option.ack.address",
664                FT_IPv4, BASE_NONE,
665                NULL, 0x0,
666                "Hop IP address", HFILL }
667         },
668         /* DSR flow state */
669         { &hf_dsr_fs_hopcount,
670             { "Hop count", "dsr.fs.hopcount",
671                FT_UINT8, BASE_DEC,
672                NULL, 0x7F,
673                NULL, HFILL }
674         },
675         { &hf_dsr_fs_id,
676             { "Flow id", "dsr.fs.id",
677                FT_UINT16, BASE_HEX_DEC,
678                NULL, 0x00,
679                NULL, HFILL }
680         },
681         { &hf_dsr_fs_opt_timeout_timeout,
682             { "Timeout", "dsr.option.timeout.timeout",
683                FT_UINT16, BASE_DEC,
684                NULL, 0x0,
685                NULL, HFILL }
686         },
687         { &hf_dsr_fs_opt_destflowid_id,
688             { "Flow id", "dsr.option.destflowid.id",
689                FT_UINT16, BASE_HEX_DEC,
690                NULL, 0x0,
691                "New flow identifier", HFILL }
692         },
693         { &hf_dsr_fs_opt_destflowid_dest,
694             { "Destination IP", "dsr.option.destflowid.dest",
695                FT_IPv4, BASE_NONE,
696                NULL, 0x0,
697                "New IP destination address", HFILL }
698         },
699         { &hf_dsr_opt_err_unknownflow_dest,
700             {  "Original IP destination", "dsr.option.err.unknownflow.dest",
701                FT_IPv4, BASE_NONE,
702                NULL, 0x00,
703                "Original IP destination address", HFILL }
704         },
705         { &hf_dsr_opt_err_unknownflow_id,
706             {  "Flow id", "dsr.option.err.unknownflow.id",
707                FT_UINT16, BASE_HEX_DEC,
708                NULL, 0x00,
709                NULL, HFILL }
710         },
711         { &hf_dsr_opt_err_defaultflowunknown_dest,
712             {  "Original IP destination", "dsr.option.err.defaultflowunknow.dest",
713                FT_IPv4, BASE_NONE,
714                NULL, 0x00,
715                "Original IP destination address", HFILL }
716         },
717     };
718
719     /* Setup protocol subtree array */
720     static gint *ett[] = {
721         &ett_dsr,
722         &ett_dsr_options,
723         &ett_dsr_rreq_opt,
724         &ett_dsr_rrep_opt,
725         &ett_dsr_rerr_opt,
726         &ett_dsr_ackreq_opt,
727         &ett_dsr_ack_opt,
728         &ett_dsr_srcrt_opt,
729         &ett_dsr_padn_opt,
730         &ett_dsr_pad1_opt,
731         &ett_dsr_fs_timeout_opt,
732         &ett_dsr_fs_destflowid_opt,
733         &ett_dsr_rreq_hoplist,
734         &ett_dsr_rrep_hoplist,
735         &ett_dsr_srcrt_hoplist
736     };
737
738     /* Register the protocol name and description */
739     proto_dsr = proto_register_protocol(
740                         "Dynamic Source Routing",
741                         "DSR",
742                         "dsr");
743
744     /* Required function calls to register the header fields and subtrees */
745     proto_register_field_array(proto_dsr, hf, array_length(hf));
746     proto_register_subtree_array(ett, array_length(ett));
747
748 }
749
750 void
751 proto_reg_handoff_dsr(void)
752 {
753     dissector_handle_t dsr_handle;
754
755     ip_dissector_table = find_dissector_table("ip.proto");
756
757     dsr_handle = create_dissector_handle(dissect_dsr, proto_dsr);
758     dissector_add_uint("ip.proto", IP_PROTO_DSR, dsr_handle);
759 }
760 /*
761  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
762  *
763  * Local variables:
764  * c-basic-offset: 4
765  * tab-width: 8
766  * indent-tabs-mode: nil
767  * End:
768  *
769  * vim: set shiftwidth=4 tabstop=8 expandtab:
770  * :indentSize=4:tabSize=8:noTabs=true:
771  */