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