r2447: let the server code use the new lib/socket/ stuff
[jelmer/samba4-debian.git] / source / rpc_server / dcerpc_tcp.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc over tcp code
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher 2004   
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 struct dcesrv_socket_context {
27         const struct dcesrv_endpoint *endpoint;
28         struct dcesrv_context *dcesrv_ctx;      
29 };
30
31 /*
32   write_fn callback for dcesrv_output()
33 */
34 static ssize_t dcerpc_write_fn(void *private, DATA_BLOB *out)
35 {
36         NTSTATUS status;
37         struct socket_context *sock = private;
38         size_t sendlen;
39
40         status = socket_send(sock, sock, out, &sendlen, 0);
41         if (!NT_STATUS_IS_OK(status)) {
42                 return -1;
43         }
44
45         return sendlen;
46 }
47
48 void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
49 {
50         server_terminate_connection(dce_conn->srv_conn, reason);
51 }
52
53 /*
54   add a socket address to the list of events, one event per dcerpc endpoint
55 */
56 static void add_socket_rpc(struct server_service *service, 
57                        const struct model_ops *model_ops,
58                        struct dcesrv_context *dce_ctx, 
59                        struct in_addr *ifip)
60 {
61         struct dcesrv_endpoint *e;
62         char *ip_str = talloc_strdup(service->mem_ctx, inet_ntoa(*ifip));
63
64         for (e=dce_ctx->endpoint_list;e;e=e->next) {
65                 if (e->ep_description.type == ENDPOINT_TCP) {
66                         struct server_socket *sock;
67                         struct dcesrv_socket_context *dcesrv_sock;
68
69                         sock = service_setup_socket(service,model_ops, ip_str, &e->ep_description.info.tcp_port);
70                         if (!sock) {
71                                 DEBUG(0,("service_setup_socket(port=%u) failed\n",e->ep_description.info.tcp_port));
72                                 continue;
73                         }
74
75                         dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context);
76                         if (!dcesrv_sock) {
77                                 DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n"));
78                                 continue;
79                         }
80
81                         /* remeber the enpoint of this socket */
82                         dcesrv_sock->endpoint           = e;
83                         dcesrv_sock->dcesrv_ctx         = dce_ctx;
84
85                         sock->private_data = dcesrv_sock;
86                 }
87         }
88
89         talloc_free(ip_str);
90 }
91
92 /****************************************************************************
93  Open the listening sockets for RPC over TCP
94 ****************************************************************************/
95 void dcesrv_tcp_init(struct server_service *service, const struct model_ops *model_ops, struct dcesrv_context *dce_ctx)
96 {
97         DEBUG(1,("dcesrv_tcp_init\n"));
98
99         if (lp_interfaces() && lp_bind_interfaces_only()) {
100                 int num_interfaces = iface_count();
101                 int i;
102                 for(i = 0; i < num_interfaces; i++) {
103                         struct in_addr *ifip = iface_n_ip(i);
104                         if (ifip == NULL) {
105                                 continue;
106                         }
107                         add_socket_rpc(service, model_ops, dce_ctx,  ifip);
108                 }
109         } else {
110                 struct in_addr *ifip;
111                 TALLOC_CTX *mem_ctx = talloc_init("open_sockets_smbd");
112                 if (!mem_ctx) {
113                         smb_panic("No memory");
114                 }
115
116                 ifip = interpret_addr2(mem_ctx, lp_socket_address());
117                 add_socket_rpc(service, model_ops, dce_ctx,  ifip);
118                 talloc_destroy(mem_ctx);
119         }
120
121         return; 
122 }
123
124 void dcesrv_tcp_accept(struct server_connection *conn)
125 {
126         NTSTATUS status;
127         struct dcesrv_socket_context *dcesrv_sock = conn->server_socket->private_data;
128         struct dcesrv_connection *dcesrv_conn = NULL;
129
130         DEBUG(5,("dcesrv_tcp_accept\n"));
131
132         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx, dcesrv_sock->endpoint, &dcesrv_conn);
133         if (!NT_STATUS_IS_OK(status)) {
134                 DEBUG(0,("dcesrv_tcp_accept: dcesrv_endpoint_connect failed: %s\n", 
135                         nt_errstr(status)));
136                 return;
137         }
138
139         dcesrv_conn->srv_conn = conn;
140
141         conn->private_data = dcesrv_conn;
142
143         return; 
144 }
145
146 void dcesrv_tcp_recv(struct server_connection *conn, time_t t, uint16_t flags)
147 {
148         NTSTATUS status;
149         struct dcesrv_connection *dce_conn = conn->private_data;
150         DATA_BLOB tmp_blob;
151
152         DEBUG(10,("dcesrv_tcp_recv\n"));
153
154         status = socket_recv(conn->socket, conn->socket, &tmp_blob, 0x4000, 0);
155         if (!NT_STATUS_IS_OK(status)) {
156                 if (NT_STATUS_IS_ERR(status)) {
157                         dcesrv_terminate_connection(dce_conn, "eof on socket");
158                         return;
159                 }
160                 return;
161         }
162
163         status = dcesrv_input(dce_conn, &tmp_blob);
164         talloc_free(tmp_blob.data);
165         if (!NT_STATUS_IS_OK(status)) {
166                 dcesrv_terminate_connection(dce_conn, "eof on socket");
167                 return;
168         }
169
170         if (dce_conn->call_list && dce_conn->call_list->replies) {
171                 conn->event.fde->flags |= EVENT_FD_WRITE;
172         }
173
174         return; 
175 }
176
177 void dcesrv_tcp_send(struct server_connection *conn, time_t t, uint16_t flags)
178 {
179         struct dcesrv_connection *dce_conn = conn->private_data;
180         NTSTATUS status;
181
182         DEBUG(10,("dcesrv_tcp_send\n"));
183
184         status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn);
185         if (!NT_STATUS_IS_OK(status)) {
186                 dcesrv_terminate_connection(dce_conn, "eof on socket");
187                 return;
188         }
189
190         if (!dce_conn->call_list || !dce_conn->call_list->replies) {
191                 conn->event.fde->flags &= ~EVENT_FD_WRITE;
192         }
193
194         return;
195 }
196
197 void dcesrv_tcp_idle(struct server_connection *conn, time_t t)
198 {
199         DEBUG(10,("dcesrv_tcp_idle\n"));
200         conn->event.idle->next_event = t + 5;
201
202         return; 
203 }
204
205 void dcesrv_tcp_close(struct server_connection *conn, const char *reason)
206 {
207         struct dcesrv_connection *dce_conn = conn->private_data;
208
209         DEBUG(5,("dcesrv_tcp_close: %s\n",reason));
210
211         talloc_destroy(dce_conn->mem_ctx);
212
213         return;
214 }
215
216 void dcesrv_tcp_exit(struct server_service *service, const char *reason)
217 {
218         DEBUG(1,("dcesrv_tcp_exit: %s\n",reason));
219         return;
220 }