s3-libsmb: Remove use of cli_errstr()
[kai/samba.git] / source3 / rpc_server / srv_pipe_register.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Almost completely rewritten by (C) Jeremy Allison 2005 - 2010
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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "librpc/rpc/dcerpc.h"
22 #include "srv_pipe_internal.h"
23 #include "rpc_server/srv_pipe_register.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 struct rpc_table {
29         struct {
30                 const char *clnt;
31                 const char *srv;
32         } pipe;
33         struct ndr_syntax_id rpc_interface;
34         const struct api_struct *cmds;
35         uint32_t n_cmds;
36         bool (*shutdown_fn)(void *private_data);
37         void *shutdown_data;
38 };
39
40 static struct rpc_table *rpc_lookup;
41 static uint32_t rpc_lookup_size;
42
43 static struct rpc_table *rpc_srv_get_pipe_by_id(const struct ndr_syntax_id *id)
44 {
45         uint32_t i;
46
47         for (i = 0; i < rpc_lookup_size; i++) {
48                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
49                         return &rpc_lookup[i];
50                 }
51         }
52
53         return NULL;
54 }
55
56 bool rpc_srv_pipe_exists_by_id(const struct ndr_syntax_id *id)
57 {
58         uint32_t i;
59
60         for (i = 0; i < rpc_lookup_size; i++) {
61                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
62                         return true;
63                 }
64         }
65
66         return false;
67 }
68
69 bool rpc_srv_pipe_exists_by_cli_name(const char *cli_name)
70 {
71         uint32_t i;
72
73         for (i = 0; i < rpc_lookup_size; i++) {
74                 if (strequal(rpc_lookup[i].pipe.clnt, cli_name)) {
75                         return true;
76                 }
77         }
78
79         return false;
80 }
81
82 bool rpc_srv_pipe_exists_by_srv_name(const char *srv_name)
83 {
84         uint32_t i;
85
86         for (i = 0; i < rpc_lookup_size; i++) {
87                 if (strequal(rpc_lookup[i].pipe.srv, srv_name)) {
88                         return true;
89                 }
90         }
91
92         return false;
93 }
94
95 const char *rpc_srv_get_pipe_cli_name(const struct ndr_syntax_id *id)
96 {
97         uint32_t i;
98
99         for (i = 0; i < rpc_lookup_size; i++) {
100                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
101                         return rpc_lookup[i].pipe.clnt;
102                 }
103         }
104
105         return NULL;
106 }
107
108 const char *rpc_srv_get_pipe_srv_name(const struct ndr_syntax_id *id)
109 {
110         uint32_t i;
111
112         for (i = 0; i < rpc_lookup_size; i++) {
113                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
114                         return rpc_lookup[i].pipe.srv;
115                 }
116         }
117
118         return NULL;
119 }
120
121 uint32_t rpc_srv_get_pipe_num_cmds(const struct ndr_syntax_id *id)
122 {
123         uint32_t i;
124
125         for (i = 0; i < rpc_lookup_size; i++) {
126                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
127                         return rpc_lookup[i].n_cmds;
128                 }
129         }
130
131         return 0;
132 }
133
134 const struct api_struct *rpc_srv_get_pipe_cmds(const struct ndr_syntax_id *id)
135 {
136         uint32_t i;
137
138         for (i = 0; i < rpc_lookup_size; i++) {
139                 if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
140                         return rpc_lookup[i].cmds;
141                 }
142         }
143
144         return NULL;
145 }
146
147 bool rpc_srv_get_pipe_interface_by_cli_name(const char *cli_name,
148                                             struct ndr_syntax_id *id)
149 {
150         uint32_t i;
151
152         for (i = 0; i < rpc_lookup_size; i++) {
153                 if (strequal(rpc_lookup[i].pipe.clnt, cli_name)) {
154                         if (id) {
155                                 *id = rpc_lookup[i].rpc_interface;
156                         }
157                         return true;
158                 }
159         }
160
161         return false;
162 }
163
164 /*******************************************************************
165  Register commands to an RPC pipe
166 *******************************************************************/
167
168 NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv,
169                           const struct ndr_interface_table *iface,
170                           const struct api_struct *cmds, int size,
171                           const struct rpc_srv_callbacks *rpc_srv_cb)
172 {
173         struct rpc_table *rpc_entry;
174
175         if (!clnt || !srv || !cmds) {
176                 return NT_STATUS_INVALID_PARAMETER;
177         }
178
179         if (version != SMB_RPC_INTERFACE_VERSION) {
180                 DEBUG(0,("Can't register rpc commands!\n"
181                          "You tried to register a rpc module with SMB_RPC_INTERFACE_VERSION %d"
182                          ", while this version of samba uses version %d!\n",
183                          version,SMB_RPC_INTERFACE_VERSION));
184                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
185         }
186
187         /* Don't register the same command twice */
188         if (rpc_srv_pipe_exists_by_id(&iface->syntax_id)) {
189                 return NT_STATUS_OK;
190         }
191
192         /*
193          * We use a temporary variable because this call can fail and
194          * rpc_lookup will still be valid afterwards.  It could then succeed if
195          * called again later
196          */
197         rpc_lookup_size++;
198         rpc_entry = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(rpc_lookup, struct rpc_table, rpc_lookup_size);
199         if (NULL == rpc_entry) {
200                 rpc_lookup_size--;
201                 DEBUG(0, ("rpc_srv_register: memory allocation failed\n"));
202                 return NT_STATUS_NO_MEMORY;
203         } else {
204                 rpc_lookup = rpc_entry;
205         }
206
207         rpc_entry = rpc_lookup + (rpc_lookup_size - 1);
208         ZERO_STRUCTP(rpc_entry);
209         rpc_entry->pipe.clnt = SMB_STRDUP(clnt);
210         rpc_entry->pipe.srv = SMB_STRDUP(srv);
211         rpc_entry->rpc_interface = iface->syntax_id;
212         rpc_entry->cmds = cmds;
213         rpc_entry->n_cmds = size;
214
215         if (rpc_srv_cb != NULL) {
216                 rpc_entry->shutdown_fn = rpc_srv_cb->shutdown;
217                 rpc_entry->shutdown_data = rpc_srv_cb->private_data;
218
219                 if (rpc_srv_cb->init != NULL &&
220                     !rpc_srv_cb->init(rpc_srv_cb->private_data)) {
221                         DEBUG(0, ("rpc_srv_register: Failed to call the %s "
222                                   "init function!\n", srv));
223                         return NT_STATUS_UNSUCCESSFUL;
224                 }
225         }
226
227         return NT_STATUS_OK;
228 }
229
230 NTSTATUS rpc_srv_unregister(const struct ndr_interface_table *iface)
231 {
232         struct rpc_table *rpc_entry = rpc_srv_get_pipe_by_id(&iface->syntax_id);
233
234         if (rpc_entry != NULL && rpc_entry->shutdown_fn != NULL) {
235                 if (!rpc_entry->shutdown_fn(rpc_entry->shutdown_data)) {
236                         DEBUG(0, ("rpc_srv_unregister: Failed to call the %s "
237                                   "init function!\n", rpc_entry->pipe.srv));
238                         return NT_STATUS_UNSUCCESSFUL;
239                 }
240         }
241
242         return NT_STATUS_OK;
243 }