r14402: Generate seperate headers for RPC client functions.
[kamenim/samba.git] / source4 / torture / rpc / scanner.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    scanner for rpc calls
5
6    Copyright (C) Andrew Tridgell 2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "librpc/gen_ndr/ndr_mgmt.h"
26 #include "librpc/gen_ndr/ndr_mgmt_c.h"
27 #include "librpc/rpc/dcerpc_table.h"
28 #include "torture/rpc/rpc.h"
29
30 /*
31   work out how many calls there are for an interface
32  */
33 static BOOL test_num_calls(const struct dcerpc_interface_table *iface,
34                            TALLOC_CTX *mem_ctx,
35                            struct dcerpc_syntax_id *id)
36 {
37         struct dcerpc_pipe *p;
38         NTSTATUS status;
39         int i;
40         DATA_BLOB stub_in, stub_out;
41         int idl_calls;
42         struct dcerpc_interface_table tbl;
43
44         /* FIXME: This should be fixed when torture_rpc_connection 
45          * takes a dcerpc_syntax_id */
46         tbl.name = iface->name;
47         tbl.uuid = id->uuid;
48         tbl.if_version = id->if_version;
49
50         status = torture_rpc_connection(mem_ctx, &p, iface);
51         if (!NT_STATUS_IS_OK(status)) {
52                 char *uuid_str = GUID_string(mem_ctx, &id->uuid);
53                 printf("Failed to connect to '%s' on '%s' - %s\n", 
54                        uuid_str, iface->name, nt_errstr(status));
55                 talloc_free(uuid_str);
56                 return False;
57         }
58
59         /* make null calls */
60         stub_in = data_blob(NULL, 1000);
61         memset(stub_in.data, 0xFF, stub_in.length);
62
63         for (i=0;i<200;i++) {
64                 status = dcerpc_request(p, NULL, False, i, mem_ctx, &stub_in, &stub_out);
65                 if (!NT_STATUS_IS_OK(status) &&
66                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
67                         break;
68                 }
69
70                 if (!NT_STATUS_IS_OK(status) && p->last_fault_code == 5) {
71                         printf("\tpipe disconnected at %d\n", i);
72                         goto done;
73                 }
74
75                 if (!NT_STATUS_IS_OK(status) && p->last_fault_code == 0x80010111) {
76                         printf("\terr 0x80010111 at %d\n", i);
77                         goto done;
78                 }
79         }
80
81         printf("\t%d calls available\n", i);
82         idl_calls = idl_num_calls(&id->uuid, id->if_version);
83         if (idl_calls == -1) {
84                 printf("\tinterface not known in local IDL\n");
85         } else if (i != idl_calls) {
86                 printf("\tWARNING: local IDL defines %u calls\n", idl_calls);
87         } else {
88                 printf("\tOK: matches num_calls in local IDL\n");
89         }
90
91 done:
92         talloc_free(p);
93         return True;
94 }
95
96 /*
97   ask the server what interface IDs are available on this endpoint
98 */
99 static BOOL test_inq_if_ids(struct dcerpc_pipe *p, 
100                             TALLOC_CTX *mem_ctx,
101                             const struct dcerpc_interface_table *iface)
102 {
103         NTSTATUS status;
104         struct mgmt_inq_if_ids r;
105         int i;
106         
107         status = dcerpc_mgmt_inq_if_ids(p, mem_ctx, &r);
108         if (!NT_STATUS_IS_OK(status)) {
109                 printf("inq_if_ids failed - %s\n", nt_errstr(status));
110                 return False;
111         }
112
113         if (!W_ERROR_IS_OK(r.out.result)) {
114                 printf("inq_if_ids gave error code %s\n", win_errstr(r.out.result));
115                 return False;
116         }
117
118         if (!r.out.if_id_vector) {
119                 printf("inq_if_ids gave NULL if_id_vector\n");
120                 return False;
121         }
122
123         for (i=0;i<r.out.if_id_vector->count;i++) {
124                 const char *uuid;
125                 struct dcerpc_syntax_id *id = r.out.if_id_vector->if_id[i].id;
126                 if (!id) continue;
127
128                 uuid = GUID_string(mem_ctx, &id->uuid),
129
130                 printf("\n\tuuid %s  version 0x%08x '%s'\n",
131                        uuid,
132                        id->if_version, idl_pipe_name(&id->uuid, id->if_version));
133
134                 test_num_calls(iface, mem_ctx, id);
135         }
136
137         return True;
138 }
139
140
141 BOOL torture_rpc_scanner(void)
142 {
143         NTSTATUS status;
144         struct dcerpc_pipe *p;
145         TALLOC_CTX *mem_ctx, *loop_ctx;
146         BOOL ret = True;
147         const struct dcerpc_interface_list *l;
148         const char *binding = lp_parm_string(-1, "torture", "binding");
149         struct dcerpc_binding *b;
150
151         mem_ctx = talloc_init("torture_rpc_scanner");
152
153         if (!binding) {
154                 talloc_free(mem_ctx);
155                 printf("You must supply a ncacn binding string\n");
156                 return False;
157         }
158         
159         status = dcerpc_parse_binding(mem_ctx, binding, &b);
160         if (!NT_STATUS_IS_OK(status)) {
161                 talloc_free(mem_ctx);
162                 printf("Failed to parse binding '%s'\n", binding);
163                 return False;
164         }
165
166         for (l=librpc_dcerpc_pipes();l;l=l->next) {             
167                 loop_ctx = talloc_named(mem_ctx, 0, "torture_rpc_scanner loop context");
168                 /* some interfaces are not mappable */
169                 if (l->table->num_calls == 0 ||
170                     strcmp(l->table->name, "mgmt") == 0) {
171                         talloc_free(loop_ctx);
172                         continue;
173                 }
174
175                 printf("\nTesting pipe '%s'\n", l->table->name);
176
177                 if (b->transport == NCACN_IP_TCP) {
178                         status = dcerpc_epm_map_binding(mem_ctx, b, l->table, NULL);
179                         if (!NT_STATUS_IS_OK(status)) {
180                                 printf("Failed to map port for uuid %s\n", 
181                                            GUID_string(loop_ctx, &l->table->uuid));
182                                 talloc_free(loop_ctx);
183                                 continue;
184                         }
185                 } else {
186                         b->endpoint = talloc_strdup(b, l->table->name);
187                 }
188
189                 lp_set_cmdline("torture:binding", dcerpc_binding_string(mem_ctx, b));
190
191                 status = torture_rpc_connection(loop_ctx, &p, &dcerpc_table_mgmt);
192                 if (!NT_STATUS_IS_OK(status)) {
193                         talloc_free(loop_ctx);
194                         ret = False;
195                         continue;
196                 }
197         
198                 if (!test_inq_if_ids(p, mem_ctx, l->table)) {
199                         ret = False;
200                 }
201         }
202
203         return ret;
204 }