s3-libads: use ldap_init_fd() to initialize a ldap session if possible
[bbaumbach/samba-autobuild/.git] / source4 / lib / socket / socket.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Socket functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Tim Potter      2000-2001
6    Copyright (C) Stefan Metzmacher 2004
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/socket/socket.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "param/param.h"
27 #include "../lib/tsocket/tsocket.h"
28 #include "lib/util/util_net.h"
29
30 /*
31   auto-close sockets on free
32 */
33 static int socket_destructor(struct socket_context *sock)
34 {
35         if (sock->ops->fn_close && 
36             !(sock->flags & SOCKET_FLAG_NOCLOSE)) {
37                 sock->ops->fn_close(sock);
38         }
39         return 0;
40 }
41
42 _PUBLIC_ void socket_tevent_fd_close_fn(struct tevent_context *ev,
43                                         struct tevent_fd *fde,
44                                         int fd,
45                                         void *private_data)
46 {
47         /* this might be the socket_wrapper swrap_close() */
48         close(fd);
49 }
50
51 _PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
52                                          struct socket_context **new_sock, 
53                                          enum socket_type type, uint32_t flags)
54 {
55         NTSTATUS status;
56
57         (*new_sock) = talloc(mem_ctx, struct socket_context);
58         if (!(*new_sock)) {
59                 return NT_STATUS_NO_MEMORY;
60         }
61
62         (*new_sock)->type = type;
63         (*new_sock)->state = SOCKET_STATE_UNDEFINED;
64         (*new_sock)->flags = flags;
65
66         (*new_sock)->fd = -1;
67
68         (*new_sock)->private_data = NULL;
69         (*new_sock)->ops = ops;
70         (*new_sock)->backend_name = NULL;
71
72         status = (*new_sock)->ops->fn_init((*new_sock));
73         if (!NT_STATUS_IS_OK(status)) {
74                 talloc_free(*new_sock);
75                 return status;
76         }
77
78         /* by enabling "testnonblock" mode, all socket receive and
79            send calls on non-blocking sockets will randomly recv/send
80            less data than requested */
81
82         if (type == SOCKET_TYPE_STREAM &&
83                 getenv("SOCKET_TESTNONBLOCK") != NULL) {
84                 (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK;
85         }
86
87         /* we don't do a connect() on dgram sockets, so need to set
88            non-blocking at socket create time */
89         if (type == SOCKET_TYPE_DGRAM) {
90                 set_blocking(socket_get_fd(*new_sock), false);
91         }
92
93         talloc_set_destructor(*new_sock, socket_destructor);
94
95         return NT_STATUS_OK;
96 }
97
98 _PUBLIC_ NTSTATUS socket_create(TALLOC_CTX *mem_ctx,
99                                 const char *name, enum socket_type type,
100                                 struct socket_context **new_sock, uint32_t flags)
101 {
102         const struct socket_ops *ops;
103
104         ops = socket_getops_byname(name, type);
105         if (!ops) {
106                 return NT_STATUS_INVALID_PARAMETER;
107         }
108
109         return socket_create_with_ops(mem_ctx, ops, new_sock, type, flags);
110 }
111
112 _PUBLIC_ NTSTATUS socket_connect(struct socket_context *sock,
113                                  const struct socket_address *my_address, 
114                                  const struct socket_address *server_address,
115                                  uint32_t flags)
116 {
117         if (sock == NULL) {
118                 return NT_STATUS_CONNECTION_DISCONNECTED;
119         }
120         if (sock->state != SOCKET_STATE_UNDEFINED) {
121                 return NT_STATUS_INVALID_PARAMETER;
122         }
123
124         if (!sock->ops->fn_connect) {
125                 return NT_STATUS_NOT_IMPLEMENTED;
126         }
127
128         return sock->ops->fn_connect(sock, my_address, server_address, flags);
129 }
130
131 _PUBLIC_ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags)
132 {
133         if (!sock->ops->fn_connect_complete) {
134                 return NT_STATUS_NOT_IMPLEMENTED;
135         }
136         return sock->ops->fn_connect_complete(sock, flags);
137 }
138
139 _PUBLIC_ NTSTATUS socket_listen(struct socket_context *sock, 
140                                 const struct socket_address *my_address, 
141                                 int queue_size, uint32_t flags)
142 {
143         if (sock == NULL) {
144                 return NT_STATUS_CONNECTION_DISCONNECTED;
145         }
146         if (sock->state != SOCKET_STATE_UNDEFINED) {
147                 return NT_STATUS_INVALID_PARAMETER;
148         }
149
150         if (!sock->ops->fn_listen) {
151                 return NT_STATUS_NOT_IMPLEMENTED;
152         }
153
154         return sock->ops->fn_listen(sock, my_address, queue_size, flags);
155 }
156
157 _PUBLIC_ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock)
158 {
159         NTSTATUS status;
160
161         if (sock == NULL) {
162                 return NT_STATUS_CONNECTION_DISCONNECTED;
163         }
164         if (sock->type != SOCKET_TYPE_STREAM) {
165                 return NT_STATUS_INVALID_PARAMETER;
166         }
167
168         if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
169                 return NT_STATUS_INVALID_PARAMETER;
170         }
171
172         if (!sock->ops->fn_accept) {
173                 return NT_STATUS_NOT_IMPLEMENTED;
174         }
175
176         status = sock->ops->fn_accept(sock, new_sock);
177
178         if (NT_STATUS_IS_OK(status)) {
179                 talloc_set_destructor(*new_sock, socket_destructor);
180                 (*new_sock)->flags = 0;
181         }
182
183         return status;
184 }
185
186 _PUBLIC_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, 
187                               size_t wantlen, size_t *nread)
188 {
189         if (sock == NULL) {
190                 return NT_STATUS_CONNECTION_DISCONNECTED;
191         }
192         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
193             sock->state != SOCKET_STATE_SERVER_CONNECTED &&
194             sock->type  != SOCKET_TYPE_DGRAM) {
195                 return NT_STATUS_INVALID_PARAMETER;
196         }
197
198         if (!sock->ops->fn_recv) {
199                 return NT_STATUS_NOT_IMPLEMENTED;
200         }
201
202         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) 
203             && wantlen > 1) {
204
205                 if (random() % 10 == 0) {
206                         *nread = 0;
207                         return STATUS_MORE_ENTRIES;
208                 }
209                 return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread);
210         }
211         return sock->ops->fn_recv(sock, buf, wantlen, nread);
212 }
213
214 _PUBLIC_ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, 
215                                   size_t wantlen, size_t *nread, 
216                                   TALLOC_CTX *mem_ctx, struct socket_address **src_addr)
217 {
218         if (sock == NULL) {
219                 return NT_STATUS_CONNECTION_DISCONNECTED;
220         }
221         if (sock->type != SOCKET_TYPE_DGRAM) {
222                 return NT_STATUS_INVALID_PARAMETER;
223         }
224
225         if (!sock->ops->fn_recvfrom) {
226                 return NT_STATUS_NOT_IMPLEMENTED;
227         }
228
229         return sock->ops->fn_recvfrom(sock, buf, wantlen, nread, 
230                                       mem_ctx, src_addr);
231 }
232
233 _PUBLIC_ NTSTATUS socket_send(struct socket_context *sock, 
234                               const DATA_BLOB *blob, size_t *sendlen)
235 {
236         if (sock == NULL) {
237                 return NT_STATUS_CONNECTION_DISCONNECTED;
238         }
239         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
240             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
241                 return NT_STATUS_INVALID_PARAMETER;
242         }
243
244         if (!sock->ops->fn_send) {
245                 return NT_STATUS_NOT_IMPLEMENTED;
246         }
247         
248         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
249             && blob->length > 1) {
250                 DATA_BLOB blob2 = *blob;
251                 if (random() % 10 == 0) {
252                         *sendlen = 0;
253                         return STATUS_MORE_ENTRIES;
254                 }
255                 /* The random size sends are incompatible with TLS and SASL
256                  * sockets, which require re-sends to be consistant */
257                 if (!(sock->flags & SOCKET_FLAG_ENCRYPT)) {
258                         blob2.length = 1+(random() % blob2.length);
259                 } else {
260                         /* This is particularly stressful on buggy
261                          * LDAP clients, that don't expect on LDAP
262                          * packet in many SASL packets */
263                         blob2.length = 1 + blob2.length/2;
264                 }
265                 return sock->ops->fn_send(sock, &blob2, sendlen);
266         }
267         return sock->ops->fn_send(sock, blob, sendlen);
268 }
269
270
271 _PUBLIC_ NTSTATUS socket_sendto(struct socket_context *sock, 
272                                 const DATA_BLOB *blob, size_t *sendlen, 
273                                 const struct socket_address *dest_addr)
274 {
275         if (sock == NULL) {
276                 return NT_STATUS_CONNECTION_DISCONNECTED;
277         }
278         if (sock->type != SOCKET_TYPE_DGRAM) {
279                 return NT_STATUS_INVALID_PARAMETER;
280         }
281
282         if (sock->state == SOCKET_STATE_CLIENT_CONNECTED ||
283             sock->state == SOCKET_STATE_SERVER_CONNECTED) {
284                 return NT_STATUS_INVALID_PARAMETER;
285         }
286
287         if (!sock->ops->fn_sendto) {
288                 return NT_STATUS_NOT_IMPLEMENTED;
289         }
290
291         return sock->ops->fn_sendto(sock, blob, sendlen, dest_addr);
292 }
293
294
295 /*
296   ask for the number of bytes in a pending incoming packet
297 */
298 _PUBLIC_ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending)
299 {
300         if (sock == NULL) {
301                 return NT_STATUS_CONNECTION_DISCONNECTED;
302         }
303         if (!sock->ops->fn_pending) {
304                 return NT_STATUS_NOT_IMPLEMENTED;
305         }
306         return sock->ops->fn_pending(sock, npending);
307 }
308
309
310 _PUBLIC_ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
311 {
312         if (sock == NULL) {
313                 return NT_STATUS_CONNECTION_DISCONNECTED;
314         }
315         if (!sock->ops->fn_set_option) {
316                 return NT_STATUS_NOT_IMPLEMENTED;
317         }
318
319         return sock->ops->fn_set_option(sock, option, val);
320 }
321
322 _PUBLIC_ char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
323 {
324         if (!sock->ops->fn_get_peer_name) {
325                 return NULL;
326         }
327
328         return sock->ops->fn_get_peer_name(sock, mem_ctx);
329 }
330
331 _PUBLIC_ struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
332 {
333         if (!sock->ops->fn_get_peer_addr) {
334                 return NULL;
335         }
336
337         return sock->ops->fn_get_peer_addr(sock, mem_ctx);
338 }
339
340 _PUBLIC_ struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
341 {
342         if (!sock->ops->fn_get_my_addr) {
343                 return NULL;
344         }
345
346         return sock->ops->fn_get_my_addr(sock, mem_ctx);
347 }
348
349 _PUBLIC_ struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx,
350                                                                    const struct socket_address *a)
351 {
352         struct tsocket_address *r;
353         int ret;
354
355         if (!a) {
356                 return NULL;
357         }
358         if (a->sockaddr) {
359                 ret = tsocket_address_bsd_from_sockaddr(mem_ctx,
360                                                         a->sockaddr,
361                                                         a->sockaddrlen,
362                                                         &r);
363         } else {
364                 ret = tsocket_address_inet_from_strings(mem_ctx,
365                                                         a->family,
366                                                         a->addr,
367                                                         a->port,
368                                                         &r);
369         }
370
371         if (ret != 0) {
372                 return NULL;
373         }
374
375         return r;
376 }
377
378 _PUBLIC_ void socket_address_set_port(struct socket_address *a,
379                                       uint16_t port)
380 {
381         if (a->sockaddr) {
382                 set_sockaddr_port(a->sockaddr, port);
383         } else {
384                 a->port = port;
385         }
386
387 }
388
389 _PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
390                                                                   const struct tsocket_address *a)
391 {
392         ssize_t ret;
393         struct sockaddr_storage ss;
394         size_t sslen = sizeof(ss);
395
396         ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen);
397         if (ret < 0) {
398                 return NULL;
399         }
400
401         return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret);
402 }
403
404 _PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
405 {
406         struct socket_address *a;
407         struct tsocket_address *r;
408
409         a = socket_get_peer_addr(sock, mem_ctx);
410         if (a == NULL) {
411                 return NULL;
412         }
413
414         r = socket_address_to_tsocket_address(mem_ctx, a);
415         talloc_free(a);
416         return r;
417 }
418
419 _PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
420 {
421         struct socket_address *a;
422         struct tsocket_address *r;
423
424         a = socket_get_my_addr(sock, mem_ctx);
425         if (a == NULL) {
426                 return NULL;
427         }
428
429         r = socket_address_to_tsocket_address(mem_ctx, a);
430         talloc_free(a);
431         return r;
432 }
433
434 _PUBLIC_ int socket_get_fd(struct socket_context *sock)
435 {
436         if (!sock->ops->fn_get_fd) {
437                 return -1;
438         }
439
440         return sock->ops->fn_get_fd(sock);
441 }
442
443 /*
444   call dup() on a socket, and close the old fd. This is used to change
445   the fd to the lowest available number, to make select() more
446   efficient (select speed depends on the maxiumum fd number passed to
447   it)
448 */
449 _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock)
450 {
451         int fd;
452         if (sock->fd == -1) {
453                 return NT_STATUS_INVALID_HANDLE;
454         }
455         fd = dup(sock->fd);
456         if (fd == -1) {
457                 return map_nt_error_from_unix_common(errno);
458         }
459         close(sock->fd);
460         sock->fd = fd;
461         return NT_STATUS_OK;
462         
463 }
464
465 /* Create a new socket_address.  The type must match the socket type.
466  * The host parameter may be an IP or a hostname 
467  */
468
469 _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx,
470                                                             const char *family,
471                                                             const char *host,
472                                                             int port)
473 {
474         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
475         if (!addr) {
476                 return NULL;
477         }
478
479         if (strcmp(family, "ip") == 0 && is_ipaddress_v6(host)) {
480                 /* leaving as "ip" would force IPv4 */
481                 family = "ipv6";
482         }
483
484         addr->family = family;
485         addr->addr = talloc_strdup(addr, host);
486         if (!addr->addr) {
487                 talloc_free(addr);
488                 return NULL;
489         }
490         addr->port = port;
491         addr->sockaddr = NULL;
492         addr->sockaddrlen = 0;
493
494         return addr;
495 }
496
497 /* Create a new socket_address.  Copy the struct sockaddr into the new
498  * structure.  Used for hooks in the kerberos libraries, where they
499  * supply only a struct sockaddr */
500
501 _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, 
502                                                              struct sockaddr *sockaddr, 
503                                                              size_t sockaddrlen)
504 {
505         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
506         if (!addr) {
507                 return NULL;
508         }
509         switch (sockaddr->sa_family) {
510         case AF_INET:
511                 addr->family = "ipv4";
512                 break;
513 #ifdef HAVE_IPV6
514         case AF_INET6:
515                 addr->family = "ipv6";
516                 break;
517 #endif
518         case AF_UNIX:
519                 addr->family = "unix";
520                 break;
521         }
522         addr->addr = NULL;
523         addr->port = 0;
524         addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen);
525         if (!addr->sockaddr) {
526                 talloc_free(addr);
527                 return NULL;
528         }
529         addr->sockaddrlen = sockaddrlen;
530         return addr;
531 }
532
533
534 /*
535    Create a new socket_address from sockaddr_storage
536  */
537 _PUBLIC_ struct socket_address *socket_address_from_sockaddr_storage(TALLOC_CTX *mem_ctx,
538                                                                      const struct sockaddr_storage *sockaddr,
539         uint16_t port)
540 {
541         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
542         char addr_str[INET6_ADDRSTRLEN+1];
543         const char *str;
544
545         if (!addr) {
546                 return NULL;
547         }
548         addr->port = port;
549         switch (sockaddr->ss_family) {
550         case AF_INET:
551                 addr->family = "ipv4";
552                 break;
553 #ifdef HAVE_IPV6
554         case AF_INET6:
555                 addr->family = "ipv6";
556                 break;
557 #endif
558         default:
559                 talloc_free(addr);
560                 return NULL;
561         }
562
563         str = print_sockaddr(addr_str, sizeof(addr_str), sockaddr);
564         if (str == NULL) {
565                 talloc_free(addr);
566                 return NULL;
567         }
568         addr->addr = talloc_strdup(addr, str);
569         if (addr->addr == NULL) {
570                 talloc_free(addr);
571                 return NULL;
572         }
573
574         return addr;
575 }
576
577 /* Copy a socket_address structure */
578 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
579                                            const struct socket_address *oaddr)
580 {
581         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
582         if (!addr) {
583                 return NULL;
584         }
585         addr->family    = oaddr->family;
586         if (oaddr->addr) {
587                 addr->addr      = talloc_strdup(addr, oaddr->addr);
588                 if (!addr->addr) {
589                         goto nomem;
590                 }
591         }
592         addr->port      = oaddr->port;
593         if (oaddr->sockaddr) {
594                 addr->sockaddr = (struct sockaddr *)talloc_memdup(addr,
595                                                                   oaddr->sockaddr,
596                                                                   oaddr->sockaddrlen);
597                 if (!addr->sockaddr) {
598                         goto nomem;
599                 }
600                 addr->sockaddrlen = oaddr->sockaddrlen;
601         }
602
603         return addr;
604
605 nomem:
606         talloc_free(addr);
607         return NULL;
608 }
609
610 _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum socket_type type)
611 {
612         extern const struct socket_ops *socket_ipv4_ops(enum socket_type);
613         extern const struct socket_ops *socket_ipv6_ops(enum socket_type);
614         extern const struct socket_ops *socket_unixdom_ops(enum socket_type);
615
616         if (strcmp("ip", family) == 0 || 
617             strcmp("ipv4", family) == 0) {
618                 return socket_ipv4_ops(type);
619         }
620
621 #ifdef HAVE_IPV6
622         if (strcmp("ipv6", family) == 0) {
623                 return socket_ipv6_ops(type);
624         }
625 #endif
626
627         if (strcmp("unix", family) == 0) {
628                 return socket_unixdom_ops(type);
629         }
630
631         return NULL;
632 }
633
634 /*
635   set some flags on a socket 
636  */
637 void socket_set_flags(struct socket_context *sock, unsigned flags)
638 {
639         sock->flags |= flags;
640 }