f61dff3f509689de2f90986025b6abd979e65e8d
[metze/wireshark/wip.git] / epan / dissectors / packet-dcerpc-witness-cnf.c
1 #include "packet-smb-common.h"
2
3 struct notify_response {
4         guint32 length;
5         guint32 num;
6         guint32 type;
7 };
8
9 static const int* witness_move_ipaddr_list_flags_fields[] = {
10         &hf_witness_move_ipaddr_list_flags_ipv4,
11         &hf_witness_move_ipaddr_list_flags_ipv6,
12 };
13
14 static const true_false_string valid_tfs = {
15         "Valid", "Not valid"
16 };
17
18 static const value_string witness_change_type_vals[] = {
19         {0x00, "Unknown"},
20         {0x01, "Available"},
21         {0xFF, "Unavailable"},
22         {0, NULL}
23 };
24
25 static int witness_dissect_move_ipaddr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
26 {
27         proto_item *ti = proto_tree_add_text(tree, tvb, offset, -1, "IP");
28         proto_tree *tr = proto_item_add_subtree(ti, ett_witness_move_ipaddr);
29
30         guint32 flags = tvb_get_letohl(tvb, offset);
31         proto_tree_add_bitmask(tr, tvb, offset,
32                                hf_witness_move_ipaddr_list_flags,
33                                ett_witness_move_ipaddr_list_flags,
34                                witness_move_ipaddr_list_flags_fields,
35                                ENC_LITTLE_ENDIAN);
36         offset  += 4;
37
38         proto_tree_add_item(tr, hf_witness_move_ipaddr_list_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
39         //proto_tree_add_ipv4
40         if (flags & 1) {
41                 const char *ip = tvb_ip_to_str(tvb, offset);
42                 proto_item_append_text(tr, " %s", ip);
43                 proto_item_append_text(tree, " %s", ip);
44                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", ip);
45         }
46         offset  += 4;
47
48         proto_tree_add_item(tr, hf_witness_move_ipaddr_list_ipv6, tvb, offset, 16, ENC_BIG_ENDIAN);
49         //proto_tree_add_ipv6
50         if (flags & 2) {
51                 const char *ip = tvb_ip6_to_str(tvb, offset);
52                 proto_item_append_text(tr, " %s", ip);
53                 proto_item_append_text(tree, " %s", ip);
54                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", ip);
55         }
56         offset  += 16;
57
58         proto_item_set_end(ti, tvb, offset);
59         return offset;
60 }
61
62 static int witness_dissect_move_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
63 {
64         guint32 length, num, n;
65
66         proto_item *ti = proto_tree_add_text(tree, tvb, offset, -1, "Move");
67         proto_tree *tr = proto_item_add_subtree(ti, ett_message_buffer);
68
69         length = tvb_get_letohl(tvb, offset);
70         proto_tree_add_text(tr, tvb, offset, 4, "Length: %u", length);
71         offset += 4;
72
73         proto_tree_add_text(tr, tvb, offset, 4, "Reserved");
74         offset += 4;
75
76         num = tvb_get_letohl(tvb, offset);
77         proto_tree_add_text(tr, tvb, offset, 4, "Num: %u", num);
78         offset += 4;
79
80         for (n=0; n<num; n++) {
81                 offset = witness_dissect_move_ipaddr(tvb, offset, pinfo, tr);
82         }
83
84         proto_item_set_end(ti, tvb, offset);
85         return offset;
86 }
87
88
89
90 static int witness_dissect_resource_change(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
91 {
92         guint32 length, type;
93         char *name;
94         const int old_offset = offset;
95
96         proto_item *ti = proto_tree_add_text(tree, tvb, offset, -1, "Change");
97         proto_tree *tr = proto_item_add_subtree(ti, ett_message_buffer);
98
99         length = tvb_get_letohl(tvb, offset);
100         proto_tree_add_text(tr, tvb, offset, 4, "Length: %u", length);
101         offset += 4;
102
103         type = tvb_get_letohl(tvb, offset);
104         proto_tree_add_item(tr, hf_witness_change_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
105         offset += 4;
106
107         name = tvb_get_ephemeral_unicode_string(tvb, offset, length-8, ENC_LITTLE_ENDIAN);
108         proto_tree_add_string(tr, hf_witness_change_name, tvb, offset, length-8, name);
109
110         proto_item_append_text(ti, ": %s -> %s", name,
111                                val_to_str(type, witness_change_type_vals,
112                                           "Invalid (0x04%x)"));
113
114         proto_item_set_len(ti, length);
115
116         return old_offset + length;
117 }
118
119 static int
120 witness_dissect_notifyResponse_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
121                                        void * notify_response)
122 {
123         const int old_offset = offset;
124         int (*dissect)(tvbuff_t *, int, packet_info*, proto_tree *);
125         const char *msg;
126         unsigned n;
127
128 //      struct notify_response *resp = pinfo->private_data;
129         struct notify_response *resp = notify_response;
130
131         switch (resp->type) {
132         case CLIENT_MOVE:
133                 msg = "Client Move";
134                 dissect = &witness_dissect_move_request;
135                 break;
136         case RESOURCE_CHANGE:
137                 msg = "Resource Change";
138                 dissect = &witness_dissect_resource_change;
139                 break;
140         case SHARE_MOVE:
141                 msg = "Share Move";
142                 dissect = &witness_dissect_move_request;
143                 break;
144         case IP_CHANGE:
145                 msg = "IP Change";
146                 dissect = &witness_dissect_move_request;
147                 break;
148         default:
149                 DISSECTOR_ASSERT(FALSE);
150         }
151
152
153         col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", msg);
154
155         for (n=0; n < resp->num; n++) {
156                 offset = dissect(tvb, offset, pinfo, tree);
157         }
158
159         DISSECTOR_ASSERT((unsigned)offset == (unsigned)old_offset + resp->length);
160         return offset;
161 }
162
163 static int
164 dissect_ndr_ucbuffer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
165                      proto_tree *tree, guint8 *drep,
166                      int (*dissect)(tvbuff_t *, int, packet_info*, proto_tree*, void*),
167                      void *private_data)
168 {
169         dcerpc_info *di = pinfo->private_data;
170         const int old_offset = offset;
171         int conformance_size = di->call_data->flags & DCERPC_IS_NDR64 ? 8 : 4;
172
173         if (di->conformant_run) {
174                 guint64 val;
175
176                 /* conformant run, just dissect the max_count header */
177                 di->conformant_run = 0;
178                 offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
179                                               hf_dcerpc_array_max_count, &val);
180                 di->array_max_count = (gint32)val;
181                 di->array_max_count_offset = offset-conformance_size;
182                 di->conformant_run = 1;
183                 di->conformant_eaten = offset-old_offset;
184         } else {
185                 tvbuff_t *subtvb;
186
187                 /* we don't remember where in the bytestream this field was */
188                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb,
189                                     di->array_max_count_offset, conformance_size,
190                                     di->array_max_count);
191
192                 /* real run, dissect the elements */
193                 tvb_ensure_bytes_exist(tvb, offset, di->array_max_count);
194                 subtvb = tvb_new_subset(tvb, offset, di->array_max_count, di->array_max_count);
195
196 //              pinfo->private_data = private_data;
197                 offset += dissect(subtvb, 0, pinfo, tree, private_data);
198 //              pinfo->private_data = di;
199
200                 DISSECTOR_ASSERT((unsigned)offset == (unsigned)old_offset + di->array_max_count);
201     }
202
203     return offset;
204 }
205
206 static int
207 witness_dissect_element_notifyResponse_message_buffer_(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info* di, guint8 *drep)
208 {
209         offset = dissect_ndr_ucbuffer(tvb, offset, pinfo, tree, drep, witness_dissect_notifyResponse_message, di->private_data);
210
211         return offset;
212 }
213
214 int
215 witness_dissect_struct_notifyResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, dcerpc_info* di, guint8 *drep, int hf_index, guint32 param _U_)
216 {
217         proto_item *item = NULL;
218         proto_tree *tree = NULL;
219         const int old_offset = offset;
220
221         struct notify_response response;
222
223         ALIGN_TO_5_BYTES;
224
225         if (parent_tree) {
226                 item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, ENC_NA);
227                 tree = proto_item_add_subtree(item, ett_witness_witness_notifyResponse);
228         }
229
230         offset = witness_dissect_enum_notifyResponse_type(tvb, offset, pinfo, tree, di, drep,
231                                                           hf_witness_witness_notifyResponse_message_type, &response.type);
232
233         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_witness_witness_notifyResponse_length, &response.length);
234
235         offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_witness_witness_notifyResponse_num_messages, &response.num);
236
237         if (!di->conformant_run) {
238                 if (di->private_data) {
239                         DISSECTOR_ASSERT(memcmp(di->private_data, &response, sizeof(response)) == 0);
240                 } else {
241                         di->private_data = ep_memdup(&response, sizeof(response));
242                 }
243         }
244
245         offset = witness_dissect_element_notifyResponse_message_buffer(tvb, offset, pinfo, tree, di, drep);
246
247         proto_item_set_len(item, offset-old_offset);
248
249         if (di->call_data->flags & DCERPC_IS_NDR64) {
250                 ALIGN_TO_5_BYTES;
251         }
252
253         return offset;
254 }
255
256 static int
257 witness_dissect_element_interfaceInfo_group_name(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *parent_tree, dcerpc_info *di _U_, guint8 *drep _U_)
258 {
259         const gchar *str;
260         int len = 260;
261         guint16 bc = tvb_length_remaining(tvb, offset);
262
263         str = get_unicode_or_ascii_string(tvb, &offset, TRUE, &len, TRUE, TRUE, &bc);
264
265         if (str) {
266                 proto_item *pi;
267                 pi = proto_tree_add_string(parent_tree, hf_witness_witness_interfaceInfo_group_name, tvb, offset, 2*260, str);
268                 proto_item_append_text(pi, " [%d]", len);
269                 proto_item_append_text(parent_tree, ": %s", str);
270
271         } else {
272                 //proto_tree_add_bytes
273         }
274
275         return offset + 2*260;
276 }
277
278 static int
279 PIDL_dissect_ipv4address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep _U_, int hfindex, guint32 param)
280 {
281 //      guint32 ip = tvb_get_ipv4(tvb,offset); //tvb_get_ntohl(tvb, offset);
282         if (di->conformant_run) {
283                 /* just a run to handle conformant arrays, no scalars to dissect */
284                 return offset;
285         }
286
287
288         if (!di->no_align && (offset % 4)) {
289                 offset += 4 - (offset % 4);
290         }
291
292         proto_tree_add_item(tree, hfindex, tvb, offset, 4, ENC_BIG_ENDIAN);
293
294
295         if (param & PIDL_SET_COL_INFO) {
296                 const char *ip = tvb_ip_to_str(tvb, offset);
297                 header_field_info *hf_info = proto_registrar_get_nth(hfindex);
298
299                 proto_item_append_text(proto_tree_get_parent(tree), " %s:%s", hf_info->name, ip);
300
301                 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, ip);
302         }
303         return offset + 4;
304 }
305
306 static int
307 PIDL_dissect_ipv6address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep _U_, int hfindex, guint32 param)
308 {
309 //      tvb_get_ipv6(tvb, offset, &addr);
310         if (di->conformant_run) {
311                 /* just a run to handle conformant arrays, no scalars to dissect */
312                 return offset;
313         }
314
315
316         if (!di->no_align && (offset % 2)) {
317                 offset += 2 - (offset % 2);
318         }
319
320         proto_tree_add_item(tree, hfindex, tvb, offset, 16, ENC_BIG_ENDIAN);
321
322         if (param & PIDL_SET_COL_INFO) {
323                 const char *ip = tvb_ip6_to_str(tvb, offset);
324                 header_field_info *hf_info = proto_registrar_get_nth(hfindex);
325
326                 proto_item_append_text(proto_tree_get_parent(tree), " %s:%s", hf_info->name, ip);
327
328                 col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, ip);
329         }
330
331         return offset + 16;
332 }
333
334
335 int
336 witness_dissect_enum_interfaceInfo_state(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32* param _U_)
337 {
338         return PIDL_dissect_uint16(tvb, offset, pinfo, tree, di, drep, hf_index, PIDL_SET_COL_INFO);
339 }