2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Almost completely rewritten by (C) Jeremy Allison 2005 - 2010
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.
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.
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/>.
21 #include "librpc/rpc/dcerpc.h"
22 #include "srv_pipe_internal.h"
23 #include "rpc_server/srv_pipe_register.h"
26 #define DBGC_CLASS DBGC_RPC_SRV
33 struct ndr_syntax_id rpc_interface
;
34 const struct api_struct
*cmds
;
36 bool (*shutdown_fn
)(void *private_data
);
40 static struct rpc_table
*rpc_lookup
;
41 static uint32_t rpc_lookup_size
;
43 static struct rpc_table
*rpc_srv_get_pipe_by_id(const struct ndr_syntax_id
*id
)
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
];
56 bool rpc_srv_pipe_exists_by_id(const struct ndr_syntax_id
*id
)
60 for (i
= 0; i
< rpc_lookup_size
; i
++) {
61 if (ndr_syntax_id_equal(&rpc_lookup
[i
].rpc_interface
, id
)) {
69 bool rpc_srv_pipe_exists_by_cli_name(const char *cli_name
)
73 for (i
= 0; i
< rpc_lookup_size
; i
++) {
74 if (strequal(rpc_lookup
[i
].pipe
.clnt
, cli_name
)) {
82 bool rpc_srv_pipe_exists_by_srv_name(const char *srv_name
)
86 for (i
= 0; i
< rpc_lookup_size
; i
++) {
87 if (strequal(rpc_lookup
[i
].pipe
.srv
, srv_name
)) {
95 const char *rpc_srv_get_pipe_cli_name(const struct ndr_syntax_id
*id
)
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
;
108 const char *rpc_srv_get_pipe_srv_name(const struct ndr_syntax_id
*id
)
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
;
121 uint32_t rpc_srv_get_pipe_num_cmds(const struct ndr_syntax_id
*id
)
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
;
134 const struct api_struct
*rpc_srv_get_pipe_cmds(const struct ndr_syntax_id
*id
)
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
;
147 bool rpc_srv_get_pipe_interface_by_cli_name(const char *cli_name
,
148 struct ndr_syntax_id
*id
)
152 for (i
= 0; i
< rpc_lookup_size
; i
++) {
153 if (strequal(rpc_lookup
[i
].pipe
.clnt
, cli_name
)) {
155 *id
= rpc_lookup
[i
].rpc_interface
;
164 /*******************************************************************
165 Register commands to an RPC pipe
166 *******************************************************************/
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
)
173 struct rpc_table
*rpc_entry
;
175 if (!clnt
|| !srv
|| !cmds
) {
176 return NT_STATUS_INVALID_PARAMETER
;
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
;
187 /* Don't register the same command twice */
188 if (rpc_srv_pipe_exists_by_id(&iface
->syntax_id
)) {
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
198 rpc_entry
= SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(rpc_lookup
, struct rpc_table
, rpc_lookup_size
);
199 if (NULL
== rpc_entry
) {
201 DEBUG(0, ("rpc_srv_register: memory allocation failed\n"));
202 return NT_STATUS_NO_MEMORY
;
204 rpc_lookup
= rpc_entry
;
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
;
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
;
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
;
230 NTSTATUS
rpc_srv_unregister(const struct ndr_interface_table
*iface
)
232 struct rpc_table
*rpc_entry
= rpc_srv_get_pipe_by_id(&iface
->syntax_id
);
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
;