Merge from 3.0:
[gd/samba/.git] / source3 / rpc_parse / parse_epmapper.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba end point mapper functions
4    Copyright (C) Jim McDonough (jmcd@us.ibm.com)     2003.
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_PARSE
25
26 static uint32 internal_referent_id = 0;
27
28
29 /*******************************************************************
30  Reads or writes a handle.
31 ********************************************************************/
32 BOOL epm_io_handle(const char *desc, EPM_HANDLE *handle, prs_struct *ps,
33                    int depth)
34 {
35         if (!prs_align(ps))
36                 return False;
37
38         if (!prs_uint8s(False, "data", ps, depth, handle->data, 
39                         sizeof(handle->data)))
40                 return False;
41
42         return True;
43 }
44
45 /*******************************************************************
46  inits an EPM_FLOOR structure.
47 ********************************************************************/
48 NTSTATUS init_epm_floor(EPM_FLOOR *floor, uint8 protocol)
49 {
50         /* handle lhs */
51         floor->lhs.protocol = protocol;
52         floor->lhs.length = sizeof(floor->lhs.protocol);
53
54         switch(floor->lhs.protocol) {
55         case EPM_FLOOR_UUID:
56                 floor->lhs.length += sizeof(floor->lhs.uuid.uuid);
57                 floor->lhs.length += sizeof(floor->lhs.uuid.version);
58                 break;
59         default:
60                 break;
61         }
62
63         /* handle rhs */
64         switch(floor->lhs.protocol) {
65         case EPM_FLOOR_RPC:
66         case EPM_FLOOR_UUID:
67                 floor->rhs.length = sizeof(floor->rhs.unknown);
68                 break;
69         case EPM_FLOOR_TCP:
70                 floor->rhs.length = sizeof(floor->rhs.tcp.port);
71                 break;
72         case EPM_FLOOR_IP:
73                 floor->rhs.length = sizeof(floor->rhs.ip.addr);
74                 break;
75         case EPM_FLOOR_NMPIPES:
76         case EPM_FLOOR_LRPC:
77         case EPM_FLOOR_NETBIOS:
78                 floor->rhs.length = strlen(floor->rhs.string) + 1;
79                 break;
80         default:
81                 break;
82         }
83
84         return NT_STATUS_OK;
85 }
86         
87 /*******************************************************************
88  inits an EPM_FLOOR structure with a UUID
89 ********************************************************************/
90 NTSTATUS init_epm_floor_uuid(EPM_FLOOR *floor,
91                              const struct uuid uuid, uint16 version)
92 {
93         memcpy(&floor->lhs.uuid.uuid, &uuid, sizeof(uuid));
94         floor->lhs.uuid.version = version;
95         floor->rhs.unknown = 0;
96         return init_epm_floor(floor, EPM_FLOOR_UUID);
97 }
98
99 /*******************************************************************
100  inits an EPM_FLOOR structure for RPC
101 ********************************************************************/
102 NTSTATUS init_epm_floor_rpc(EPM_FLOOR *floor)
103 {
104         floor->rhs.unknown = 0;
105         return init_epm_floor(floor, EPM_FLOOR_RPC);
106 }
107
108 /*******************************************************************
109  inits an EPM_FLOOR structure for TCP
110 ********************************************************************/
111 NTSTATUS init_epm_floor_tcp(EPM_FLOOR *floor, uint16 port)
112 {
113         floor->rhs.tcp.port = htons(port);
114         return init_epm_floor(floor, EPM_FLOOR_TCP);
115 }
116
117 /*******************************************************************
118  inits an EPM_FLOOR structure for IP
119 ********************************************************************/
120 NTSTATUS init_epm_floor_ip(EPM_FLOOR *floor, uint8 addr[4])
121 {
122         memcpy(&floor->rhs.ip.addr, addr, sizeof(addr));
123         return init_epm_floor(floor, EPM_FLOOR_IP);
124 }
125
126 /*******************************************************************
127  inits an EPM_FLOOR structure for named pipe
128 ********************************************************************/
129 NTSTATUS init_epm_floor_np(EPM_FLOOR *floor, const char *pipe_name)
130 {
131         safe_strcpy(floor->rhs.string, pipe_name, sizeof(floor->rhs.string)-1);
132         return init_epm_floor(floor, EPM_FLOOR_NMPIPES);
133 }
134
135 /*******************************************************************
136  inits an EPM_FLOOR structure for named pipe
137 ********************************************************************/
138 NTSTATUS init_epm_floor_lrpc(EPM_FLOOR *floor, const char *pipe_name)
139 {
140         safe_strcpy(floor->rhs.string, pipe_name, sizeof(floor->rhs.string)-1);
141         return init_epm_floor(floor, EPM_FLOOR_LRPC);
142 }
143
144 /*******************************************************************
145  inits an EPM_FLOOR structure for named pipe
146 ********************************************************************/
147 NTSTATUS init_epm_floor_nb(EPM_FLOOR *floor, char *host_name)
148 {
149         safe_strcpy(floor->rhs.string, host_name, sizeof(floor->rhs.string)-1);
150         return init_epm_floor(floor, EPM_FLOOR_NETBIOS);
151 }
152
153 /*******************************************************************
154  reads and writes EPM_FLOOR.
155 ********************************************************************/
156 BOOL epm_io_floor(const char *desc, EPM_FLOOR *floor,
157                   prs_struct *ps, int depth)
158 {
159         prs_debug(ps, depth, desc, "epm_io_floor");
160         depth++;
161
162         if (!prs_uint16("lhs_length", ps, depth, &floor->lhs.length))
163                 return False;
164         if (!prs_uint8("protocol", ps, depth, &floor->lhs.protocol))
165                 return False;
166
167         switch (floor->lhs.protocol) {
168         case EPM_FLOOR_UUID:
169                 if (!smb_io_uuid("uuid", &floor->lhs.uuid.uuid, ps, depth))
170                         return False;
171                 if (!prs_uint16("version", ps, depth, 
172                                 &floor->lhs.uuid.version))
173                         return False;
174                 break;
175         }
176
177         if (!prs_uint16("rhs_length", ps, depth, &floor->rhs.length))
178                 return False;
179
180         switch (floor->lhs.protocol) {
181         case EPM_FLOOR_UUID:
182         case EPM_FLOOR_RPC:
183                 if (!prs_uint16("unknown", ps, depth, &floor->rhs.unknown))
184                         return False;
185                 break;
186         case EPM_FLOOR_TCP:
187                 if (!prs_uint16("tcp_port", ps, depth, &floor->rhs.tcp.port))
188                         return False;
189                 break;
190         case EPM_FLOOR_IP:
191                 if (!prs_uint8s(False, "ip_addr", ps, depth, 
192                                 floor->rhs.ip.addr,
193                                 sizeof(floor->rhs.ip.addr)))
194                         return False;
195                 break;
196         case EPM_FLOOR_NMPIPES:
197         case EPM_FLOOR_LRPC:
198         case EPM_FLOOR_NETBIOS:
199                 if (!prs_uint8s(False, "string", ps, depth,
200                                 floor->rhs.string,
201                                 floor->rhs.length))
202                         return False;
203                 break;
204         default:
205                 break;
206         }
207
208         return True;
209 }
210
211 /*******************************************************************
212  Inits a EPM_TOWER structure.
213 ********************************************************************/
214 NTSTATUS init_epm_tower(TALLOC_CTX *ctx, EPM_TOWER *tower, 
215                         const EPM_FLOOR *floors, int num_floors)
216 {
217         int size = 0;
218         int i;
219
220         DEBUG(5, ("init_epm_tower\n"));
221
222         size += sizeof(uint16); /* number of floors is in tower length */
223         for (i = 0; i < num_floors; i++) {
224                 size += (sizeof(uint16) * 2);
225                 size += floors[i].lhs.length;
226                 size += floors[i].rhs.length;
227         }
228
229         tower->max_length = tower->length = size;
230         tower->num_floors = num_floors;
231         tower->floors = talloc(ctx, sizeof(EPM_FLOOR) * num_floors);
232         if (!tower->floors) {
233                 return NT_STATUS_NO_MEMORY;
234         }
235         memcpy(tower->floors, floors, sizeof(EPM_FLOOR) * num_floors);
236         tower->unknown = 0x7e;
237
238         return NT_STATUS_OK;
239 }
240
241 /*******************************************************************
242  Reads or writes an EPM_TOWER structure.
243 ********************************************************************/
244 BOOL epm_io_tower(const char *desc, EPM_TOWER *tower,
245                   prs_struct *ps, int depth)
246 {
247         int i;
248
249         prs_debug(ps, depth, desc, "epm_io_tower");
250         depth++;
251
252         if (!prs_align(ps))
253                 return False;
254
255         if (!prs_uint32("max_length", ps, depth, &tower->max_length))
256                 return False;
257         if (!prs_uint32("length", ps, depth, &tower->length))
258                 return False;
259         if (!prs_uint16("num_floors", ps, depth, &tower->num_floors))
260                 return False;
261
262         if (UNMARSHALLING(ps)) {
263                 tower->floors = talloc(ps->mem_ctx,
264                                        sizeof(EPM_FLOOR) * tower->num_floors);
265                 if (!tower->floors)
266                         return False;
267         }
268
269         for (i = 0; i < tower->num_floors; i++) {
270                 if (!epm_io_floor("floor", tower->floors + i, ps, depth))
271                         return False;
272         }
273
274         return True;
275 }
276
277 /*******************************************************************
278  Initialize an EPM_TOWER_ARRAY structure
279 ********************************************************************/
280 NTSTATUS init_epm_tower_array(TALLOC_CTX *ctx, EPM_TOWER_ARRAY *array,
281                               const EPM_TOWER *towers, int num_towers)
282 {
283         int i;
284
285         array->max_count = num_towers;
286         array->offset = 0;
287         array->count = num_towers;
288         array->tower_ref_ids = talloc(ctx, sizeof(uint32) * num_towers);
289         if (!array->tower_ref_ids) {
290                 return NT_STATUS_NO_MEMORY;
291         }
292         for (i=0;i<num_towers;i++)
293                 array->tower_ref_ids[i] = ++internal_referent_id;
294
295         array->towers = talloc(ctx, sizeof(EPM_TOWER) * num_towers);
296         if (!array->towers) {
297                 return NT_STATUS_NO_MEMORY;
298         }
299         memcpy(array->towers, towers, sizeof(EPM_TOWER) * num_towers);
300
301         return NT_STATUS_OK;
302 }
303
304 /*******************************************************************
305  Reads or writes an EPM_TOWER_ARRAY structure.
306 ********************************************************************/
307 BOOL epm_io_tower_array(const char *desc, EPM_TOWER_ARRAY *array,
308                         prs_struct *ps, int depth)
309 {
310         int i;
311
312         prs_debug(ps, depth, desc, "epm_io_tower_array");
313         depth++;
314
315         if (!prs_uint32("max_count", ps, depth, &array->max_count))
316                 return False;
317         if (!prs_uint32("offset", ps, depth, &array->offset))
318                 return False;
319         if (!prs_uint32("count", ps, depth, &array->count))
320                 return False;
321
322
323         if (UNMARSHALLING(ps)) {
324                 array->tower_ref_ids = talloc(ps->mem_ctx,
325                                               sizeof(uint32) * array->count);
326                 if (!array->tower_ref_ids) {
327                         return False;
328                 }
329         }
330         for (i=0; i < array->count; i++) {
331                 if (!prs_uint32("ref_id", ps, depth, &array->tower_ref_ids[i])) {
332                         return False;
333                 } else {
334                         if (array->tower_ref_ids[i] > internal_referent_id) {
335                                 internal_referent_id = array->tower_ref_ids[i];
336                         }
337                 }
338         }
339                         
340                         
341
342         if (!prs_set_offset(ps, prs_offset(ps) + array->offset))
343                 return False;
344
345         if (UNMARSHALLING(ps)) {
346                 array->towers = talloc(ps->mem_ctx,
347                                        sizeof(EPM_TOWER) * array->count);
348                 if (!array->towers) {
349                         return False;
350                 }
351         }
352
353         for (i = 0; i < array->count; i++) {
354                 if (!epm_io_tower("tower", &array->towers[i], ps, depth))
355                         return False;
356         }
357
358         return True;
359 }
360
361 /*******************************************************************
362   Initialize EPM_R_MAP structure
363 ******************************************************************/
364 NTSTATUS init_epm_r_map(TALLOC_CTX *ctx, EPM_R_MAP *r_map, 
365                         const EPM_HANDLE *handle, const EPM_TOWER_ARRAY *array,
366                         int num_elements, uint32 status)
367 {
368         memcpy(&r_map->handle, handle, sizeof(*handle));
369         r_map->num_results = num_elements;
370         r_map->results = talloc(ctx, sizeof(EPM_TOWER_ARRAY) * num_elements);
371         if (!r_map->results) {
372                 return NT_STATUS_NO_MEMORY;
373         }
374         memcpy(r_map->results, array, sizeof(EPM_TOWER_ARRAY) * num_elements);
375         r_map->status = status;
376         return NT_STATUS_OK;
377 }
378
379 /*************************************************************************
380  Inits a EPM_Q_MAP structure.
381 **************************************************************************
382 * We attempt to hide the ugliness of the wire format by taking a EPM_TOWER
383 * array with a defined size 
384 **************************************************************************/
385 NTSTATUS init_epm_q_map(TALLOC_CTX *ctx, EPM_Q_MAP *q_map,
386                         const EPM_TOWER *towers, int num_towers)
387 {
388         static uint32 handle = 1;
389
390         ZERO_STRUCTP(q_map);
391
392         DEBUG(5, ("init_epm_q_map\n"));
393         q_map->handle.data[0] = (handle >>  0) & 0xFF;
394         q_map->handle.data[1] = (handle >>  8) & 0xFF;
395         q_map->handle.data[2] = (handle >> 16) & 0xFF;
396         q_map->handle.data[3] = (handle >> 24) & 0xFF;
397
398         q_map->tower = talloc(ctx, sizeof(EPM_TOWER) * (num_towers + 1));
399         if (!q_map->tower) {
400                 return NT_STATUS_NO_MEMORY;
401         }
402
403         memcpy(q_map->tower, towers, sizeof(EPM_TOWER) * num_towers);
404
405         ZERO_STRUCT(q_map->tower[num_towers]);
406
407         /* For now let's not take more than 4 towers per result */
408         q_map->max_towers = num_towers * 4;
409
410         q_map->tower_ref_id = ++internal_referent_id;
411
412         handle++;
413
414         return NT_STATUS_OK;
415 }
416
417 /*****************************************************************
418   epm_io_q_map - read or write EPM_Q_MAP structure
419 ******************************************************************/
420 BOOL epm_io_q_map(const char *desc, EPM_Q_MAP *io_map, prs_struct *ps, 
421                   int depth)
422 {
423         prs_debug(ps, depth, desc, "epm_io_q_map");
424         depth++;
425         
426         if (!epm_io_handle("handle", &io_map->handle, ps, depth))
427                 return False;
428
429         if (!prs_uint32("referent_id", ps, 0, &io_map->tower_ref_id))
430                 return False;
431         if (io_map->tower_ref_id > internal_referent_id)
432                 internal_referent_id = io_map->tower_ref_id;
433
434         /* HACK: We need a more elegant way of doing this */
435         if (UNMARSHALLING(ps)) {
436                 io_map->tower = talloc(ps->mem_ctx, sizeof(EPM_TOWER));
437                 if (!io_map->tower)
438                         return False;
439         }               
440         if (!epm_io_tower("tower", io_map->tower, ps, depth))
441                 return False;
442         if (!epm_io_handle("term_handle", &io_map->term_handle, ps, depth))
443                 return False;
444
445         if (!prs_uint32("max_towers", ps, 0, &io_map->max_towers))
446                 return False;
447
448         return True;
449 }
450
451 /*******************************************************************
452   epm_io_r_map - Read/Write EPM_R_MAP structure
453 ******************************************************************/
454 BOOL epm_io_r_map(const char *desc, EPM_R_MAP *io_map,
455                   prs_struct *ps, int depth)
456 {
457         prs_debug(ps, depth, desc, "epm_io_r_map");
458         depth++;
459
460         if (!epm_io_handle("handle", &io_map->handle, ps, depth))
461                 return False;
462         if (!prs_uint32("num_results", ps, depth, &io_map->num_results))
463                 return False;
464
465         if (UNMARSHALLING(ps)) {
466                 io_map->results = talloc(ps->mem_ctx,
467                                          sizeof(EPM_TOWER_ARRAY) * 
468                                          io_map->num_results);
469                 if (!io_map->results)
470                         return False;
471         }
472         if (!epm_io_tower_array("results", io_map->results, ps, depth))
473                         return False;
474
475         if (!prs_align(ps))
476                 return False;
477
478         if (!prs_uint32("status", ps, depth, &io_map->status))
479                 return False;
480
481         return True;
482 }