r11815: A bit more comments and spaces for better readability.
[metze/samba/wip.git] / source4 / libnet / libnet_rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Stefan Metzmacher  2004
5    Copyright (C) Rafal Szczesniak   2005
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "libnet/libnet.h"
24
25
26 /**
27  * Connects rpc pipe on remote server
28  * 
29  * @param ctx initialised libnet context
30  * @param mem_ctx memory context of this call
31  * @param r data structure containing necessary parameters and return values
32  * @return nt status of the call
33  **/
34
35 static NTSTATUS libnet_RpcConnectSrv(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
36 {
37         NTSTATUS status;
38         const char *binding = NULL;
39
40         /* prepare binding string */
41         switch (r->level) {
42         case LIBNET_RPC_CONNECT_PDC:
43         case LIBNET_RPC_CONNECT_SERVER:
44                 binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.domain_name);
45                 break;
46
47         case LIBNET_RPC_CONNECT_BINDING:
48                 binding = r->in.binding;
49                 break;
50         }
51
52         /* connect to remote dcerpc pipe */
53         status = dcerpc_pipe_connect(mem_ctx, &r->out.dcerpc_pipe,
54                                      binding, r->in.dcerpc_iface_uuid, r->in.dcerpc_iface_version,
55                                      ctx->cred, ctx->event_ctx);
56
57         if (!NT_STATUS_IS_OK(status)) {
58                 r->out.error_string = talloc_asprintf(mem_ctx,
59                                                       "dcerpc_pipe_connect to pipe %s failed with %s\n",
60                                                       r->in.dcerpc_iface_name, binding);
61                 return status;
62         }
63
64         r->out.error_string = NULL;
65         ctx->pipe = r->out.dcerpc_pipe;
66
67         return status;
68 }
69
70
71 /**
72  * Connects rpc pipe on domain pdc
73  * 
74  * @param ctx initialised libnet context
75  * @param mem_ctx memory context of this call
76  * @param r data structure containing necessary parameters and return values
77  * @return nt status of the call
78  **/
79
80 static NTSTATUS libnet_RpcConnectPdc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
81 {
82         NTSTATUS status;
83         struct libnet_RpcConnect r2;
84         struct libnet_Lookup f;
85
86         f.in.hostname  = r->in.domain_name;
87         f.in.methods   = NULL;
88         f.out.address  = NULL;
89
90         /* find the domain pdc first */
91         status = libnet_LookupPdc(ctx, mem_ctx, &f);
92         if (!NT_STATUS_IS_OK(status)) {
93                 r->out.error_string = talloc_asprintf(mem_ctx, "libnet_LookupPdc failed: %s",
94                                                       nt_errstr(status));
95                 return status;
96         }
97
98         /* ok, pdc has been found so do attempt to rpc connect */
99         r2.level                    = LIBNET_RPC_CONNECT_SERVER;
100         r2.in.domain_name           = talloc_strdup(mem_ctx, f.out.address[0]);
101         r2.in.dcerpc_iface_name     = r->in.dcerpc_iface_name;
102         r2.in.dcerpc_iface_uuid     = r->in.dcerpc_iface_uuid;
103         r2.in.dcerpc_iface_version  = r->in.dcerpc_iface_version;
104         
105         status = libnet_RpcConnect(ctx, mem_ctx, &r2);
106
107         r->out.dcerpc_pipe          = r2.out.dcerpc_pipe;
108         r->out.error_string         = r2.out.error_string;
109
110         ctx->pipe = r->out.dcerpc_pipe;
111
112         return status;
113 }
114
115
116 /**
117  * Connects to rpc pipe on remote server or pdc
118  * 
119  * @param ctx initialised libnet context
120  * @param mem_ctx memory context of this call
121  * @param r data structure containing necessary parameters and return values
122  * @return nt status of the call
123  **/
124
125 NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
126 {
127         switch (r->level) {
128                 case LIBNET_RPC_CONNECT_SERVER:
129                         return libnet_RpcConnectSrv(ctx, mem_ctx, r);
130
131                 case LIBNET_RPC_CONNECT_BINDING:
132                         return libnet_RpcConnectSrv(ctx, mem_ctx, r);
133
134                 case LIBNET_RPC_CONNECT_PDC:
135                         return libnet_RpcConnectPdc(ctx, mem_ctx, r);
136         }
137
138         return NT_STATUS_INVALID_LEVEL;
139 }