Merge commit 'release-4-0-0alpha15' into master4-tmp
[nivanova/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 (!(flags & SOCKET_FLAG_BLOCK) &&
83             type == SOCKET_TYPE_STREAM &&
84                 getenv("SOCKET_TESTNONBLOCK") != NULL) {
85                 (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK;
86         }
87
88         /* we don't do a connect() on dgram sockets, so need to set
89            non-blocking at socket create time */
90         if (!(flags & SOCKET_FLAG_BLOCK) && type == SOCKET_TYPE_DGRAM) {
91                 set_blocking(socket_get_fd(*new_sock), false);
92         }
93
94         talloc_set_destructor(*new_sock, socket_destructor);
95
96         return NT_STATUS_OK;
97 }
98
99 _PUBLIC_ NTSTATUS socket_create(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(NULL, 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->sockaddr) {
356                 ret = tsocket_address_bsd_from_sockaddr(mem_ctx,
357                                                         a->sockaddr,
358                                                         a->sockaddrlen,
359                                                         &r);
360         } else {
361                 ret = tsocket_address_inet_from_strings(mem_ctx,
362                                                         a->family,
363                                                         a->addr,
364                                                         a->port,
365                                                         &r);
366         }
367
368         if (ret != 0) {
369                 return NULL;
370         }
371
372         return r;
373 }
374
375 _PUBLIC_ void socket_address_set_port(struct socket_address *a,
376                                       uint16_t port)
377 {
378         if (a->sockaddr) {
379                 set_sockaddr_port(a->sockaddr, port);
380         } else {
381                 a->port = port;
382         }
383
384 }
385
386 _PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
387                                                                   const struct tsocket_address *a)
388 {
389         ssize_t ret;
390         struct sockaddr_storage ss;
391         size_t sslen = sizeof(ss);
392
393         ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen);
394         if (ret < 0) {
395                 return NULL;
396         }
397
398         return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret);
399 }
400
401 _PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
402 {
403         struct socket_address *a;
404         struct tsocket_address *r;
405
406         a = socket_get_peer_addr(sock, mem_ctx);
407         if (a == NULL) {
408                 return NULL;
409         }
410
411         r = socket_address_to_tsocket_address(mem_ctx, a);
412         talloc_free(a);
413         return r;
414 }
415
416 _PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
417 {
418         struct socket_address *a;
419         struct tsocket_address *r;
420
421         a = socket_get_my_addr(sock, mem_ctx);
422         if (a == NULL) {
423                 return NULL;
424         }
425
426         r = socket_address_to_tsocket_address(mem_ctx, a);
427         talloc_free(a);
428         return r;
429 }
430
431 _PUBLIC_ int socket_get_fd(struct socket_context *sock)
432 {
433         if (!sock->ops->fn_get_fd) {
434                 return -1;
435         }
436
437         return sock->ops->fn_get_fd(sock);
438 }
439
440 /*
441   call dup() on a socket, and close the old fd. This is used to change
442   the fd to the lowest available number, to make select() more
443   efficient (select speed depends on the maxiumum fd number passed to
444   it)
445 */
446 _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock)
447 {
448         int fd;
449         if (sock->fd == -1) {
450                 return NT_STATUS_INVALID_HANDLE;
451         }
452         fd = dup(sock->fd);
453         if (fd == -1) {
454                 return map_nt_error_from_unix_common(errno);
455         }
456         close(sock->fd);
457         sock->fd = fd;
458         return NT_STATUS_OK;
459         
460 }
461
462 /* Create a new socket_address.  The type must match the socket type.
463  * The host parameter may be an IP or a hostname 
464  */
465
466 _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx,
467                                                             const char *family,
468                                                             const char *host,
469                                                             int port)
470 {
471         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
472         if (!addr) {
473                 return NULL;
474         }
475
476         if (strcmp(family, "ip") == 0 && is_ipaddress_v6(host)) {
477                 /* leaving as "ip" would force IPv4 */
478                 family = "ipv6";
479         }
480
481         addr->family = family;
482         addr->addr = talloc_strdup(addr, host);
483         if (!addr->addr) {
484                 talloc_free(addr);
485                 return NULL;
486         }
487         addr->port = port;
488         addr->sockaddr = NULL;
489         addr->sockaddrlen = 0;
490
491         return addr;
492 }
493
494 /* Create a new socket_address.  Copy the struct sockaddr into the new
495  * structure.  Used for hooks in the kerberos libraries, where they
496  * supply only a struct sockaddr */
497
498 _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, 
499                                                              struct sockaddr *sockaddr, 
500                                                              size_t sockaddrlen)
501 {
502         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
503         if (!addr) {
504                 return NULL;
505         }
506         switch (sockaddr->sa_family) {
507         case AF_INET:
508                 addr->family = "ipv4";
509                 break;
510 #ifdef HAVE_IPV6
511         case AF_INET6:
512                 addr->family = "ipv6";
513                 break;
514 #endif
515         case AF_UNIX:
516                 addr->family = "unix";
517                 break;
518         }
519         addr->addr = NULL;
520         addr->port = 0;
521         addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen);
522         if (!addr->sockaddr) {
523                 talloc_free(addr);
524                 return NULL;
525         }
526         addr->sockaddrlen = sockaddrlen;
527         return addr;
528 }
529
530
531 /*
532    Create a new socket_address from sockaddr_storage
533  */
534 _PUBLIC_ struct socket_address *socket_address_from_sockaddr_storage(TALLOC_CTX *mem_ctx,
535                                                                      const struct sockaddr_storage *sockaddr,
536         uint16_t port)
537 {
538         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
539         char addr_str[INET6_ADDRSTRLEN+1];
540         const char *str;
541
542         if (!addr) {
543                 return NULL;
544         }
545         addr->port = port;
546         switch (sockaddr->ss_family) {
547         case AF_INET:
548                 addr->family = "ipv4";
549                 break;
550 #ifdef HAVE_IPV6
551         case AF_INET6:
552                 addr->family = "ipv6";
553                 break;
554 #endif
555         default:
556                 talloc_free(addr);
557                 return NULL;
558         }
559
560         str = print_sockaddr(addr_str, sizeof(addr_str), sockaddr);
561         if (str == NULL) {
562                 talloc_free(addr);
563                 return NULL;
564         }
565         addr->addr = talloc_strdup(addr, str);
566         if (addr->addr == NULL) {
567                 talloc_free(addr);
568                 return NULL;
569         }
570
571         return addr;
572 }
573
574 /* Copy a socket_address structure */
575 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
576                                            const struct socket_address *oaddr)
577 {
578         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
579         if (!addr) {
580                 return NULL;
581         }
582         addr->family    = oaddr->family;
583         if (oaddr->addr) {
584                 addr->addr      = talloc_strdup(addr, oaddr->addr);
585                 if (!addr->addr) {
586                         goto nomem;
587                 }
588         }
589         addr->port      = oaddr->port;
590         if (oaddr->sockaddr) {
591                 addr->sockaddr = (struct sockaddr *)talloc_memdup(addr,
592                                                                   oaddr->sockaddr,
593                                                                   oaddr->sockaddrlen);
594                 if (!addr->sockaddr) {
595                         goto nomem;
596                 }
597                 addr->sockaddrlen = oaddr->sockaddrlen;
598         }
599
600         return addr;
601
602 nomem:
603         talloc_free(addr);
604         return NULL;
605 }
606
607 _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum socket_type type)
608 {
609         extern const struct socket_ops *socket_ipv4_ops(enum socket_type);
610         extern const struct socket_ops *socket_ipv6_ops(enum socket_type);
611         extern const struct socket_ops *socket_unixdom_ops(enum socket_type);
612
613         if (strcmp("ip", family) == 0 || 
614             strcmp("ipv4", family) == 0) {
615                 return socket_ipv4_ops(type);
616         }
617
618 #if HAVE_IPV6
619         if (strcmp("ipv6", family) == 0) {
620                 return socket_ipv6_ops(type);
621         }
622 #endif
623
624         if (strcmp("unix", family) == 0) {
625                 return socket_unixdom_ops(type);
626         }
627
628         return NULL;
629 }
630
631 /*
632   set some flags on a socket 
633  */
634 void socket_set_flags(struct socket_context *sock, unsigned flags)
635 {
636         sock->flags |= flags;
637 }