s4:lib/socket: add socket_get_{remote|local}_addr() to get a tsocket_address instead...
[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
29 /*
30   auto-close sockets on free
31 */
32 static int socket_destructor(struct socket_context *sock)
33 {
34         if (sock->ops->fn_close && 
35             !(sock->flags & SOCKET_FLAG_NOCLOSE)) {
36                 sock->ops->fn_close(sock);
37         }
38         return 0;
39 }
40
41 _PUBLIC_ void socket_tevent_fd_close_fn(struct tevent_context *ev,
42                                         struct tevent_fd *fde,
43                                         int fd,
44                                         void *private_data)
45 {
46         /* this might be the socket_wrapper swrap_close() */
47         close(fd);
48 }
49
50 _PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
51                                          struct socket_context **new_sock, 
52                                          enum socket_type type, uint32_t flags)
53 {
54         NTSTATUS status;
55
56         (*new_sock) = talloc(mem_ctx, struct socket_context);
57         if (!(*new_sock)) {
58                 return NT_STATUS_NO_MEMORY;
59         }
60
61         (*new_sock)->type = type;
62         (*new_sock)->state = SOCKET_STATE_UNDEFINED;
63         (*new_sock)->flags = flags;
64
65         (*new_sock)->fd = -1;
66
67         (*new_sock)->private_data = NULL;
68         (*new_sock)->ops = ops;
69         (*new_sock)->backend_name = NULL;
70
71         status = (*new_sock)->ops->fn_init((*new_sock));
72         if (!NT_STATUS_IS_OK(status)) {
73                 talloc_free(*new_sock);
74                 return status;
75         }
76
77         /* by enabling "testnonblock" mode, all socket receive and
78            send calls on non-blocking sockets will randomly recv/send
79            less data than requested */
80
81         if (!(flags & SOCKET_FLAG_BLOCK) &&
82             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 (!(flags & SOCKET_FLAG_BLOCK) && 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(const char *name, enum socket_type type, 
99                                 struct socket_context **new_sock, uint32_t flags)
100 {
101         const struct socket_ops *ops;
102
103         ops = socket_getops_byname(name, type);
104         if (!ops) {
105                 return NT_STATUS_INVALID_PARAMETER;
106         }
107
108         return socket_create_with_ops(NULL, ops, new_sock, type, flags);
109 }
110
111 _PUBLIC_ NTSTATUS socket_connect(struct socket_context *sock,
112                                  const struct socket_address *my_address, 
113                                  const struct socket_address *server_address,
114                                  uint32_t flags)
115 {
116         if (sock == NULL) {
117                 return NT_STATUS_CONNECTION_DISCONNECTED;
118         }
119         if (sock->state != SOCKET_STATE_UNDEFINED) {
120                 return NT_STATUS_INVALID_PARAMETER;
121         }
122
123         if (!sock->ops->fn_connect) {
124                 return NT_STATUS_NOT_IMPLEMENTED;
125         }
126
127         return sock->ops->fn_connect(sock, my_address, server_address, flags);
128 }
129
130 _PUBLIC_ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags)
131 {
132         if (!sock->ops->fn_connect_complete) {
133                 return NT_STATUS_NOT_IMPLEMENTED;
134         }
135         return sock->ops->fn_connect_complete(sock, flags);
136 }
137
138 _PUBLIC_ NTSTATUS socket_listen(struct socket_context *sock, 
139                                 const struct socket_address *my_address, 
140                                 int queue_size, uint32_t flags)
141 {
142         if (sock == NULL) {
143                 return NT_STATUS_CONNECTION_DISCONNECTED;
144         }
145         if (sock->state != SOCKET_STATE_UNDEFINED) {
146                 return NT_STATUS_INVALID_PARAMETER;
147         }
148
149         if (!sock->ops->fn_listen) {
150                 return NT_STATUS_NOT_IMPLEMENTED;
151         }
152
153         return sock->ops->fn_listen(sock, my_address, queue_size, flags);
154 }
155
156 _PUBLIC_ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock)
157 {
158         NTSTATUS status;
159
160         if (sock == NULL) {
161                 return NT_STATUS_CONNECTION_DISCONNECTED;
162         }
163         if (sock->type != SOCKET_TYPE_STREAM) {
164                 return NT_STATUS_INVALID_PARAMETER;
165         }
166
167         if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
168                 return NT_STATUS_INVALID_PARAMETER;
169         }
170
171         if (!sock->ops->fn_accept) {
172                 return NT_STATUS_NOT_IMPLEMENTED;
173         }
174
175         status = sock->ops->fn_accept(sock, new_sock);
176
177         if (NT_STATUS_IS_OK(status)) {
178                 talloc_set_destructor(*new_sock, socket_destructor);
179                 (*new_sock)->flags = 0;
180         }
181
182         return status;
183 }
184
185 _PUBLIC_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, 
186                               size_t wantlen, size_t *nread)
187 {
188         if (sock == NULL) {
189                 return NT_STATUS_CONNECTION_DISCONNECTED;
190         }
191         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
192             sock->state != SOCKET_STATE_SERVER_CONNECTED &&
193             sock->type  != SOCKET_TYPE_DGRAM) {
194                 return NT_STATUS_INVALID_PARAMETER;
195         }
196
197         if (!sock->ops->fn_recv) {
198                 return NT_STATUS_NOT_IMPLEMENTED;
199         }
200
201         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) 
202             && wantlen > 1) {
203
204                 if (random() % 10 == 0) {
205                         *nread = 0;
206                         return STATUS_MORE_ENTRIES;
207                 }
208                 return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread);
209         }
210         return sock->ops->fn_recv(sock, buf, wantlen, nread);
211 }
212
213 _PUBLIC_ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, 
214                                   size_t wantlen, size_t *nread, 
215                                   TALLOC_CTX *mem_ctx, struct socket_address **src_addr)
216 {
217         if (sock == NULL) {
218                 return NT_STATUS_CONNECTION_DISCONNECTED;
219         }
220         if (sock->type != SOCKET_TYPE_DGRAM) {
221                 return NT_STATUS_INVALID_PARAMETER;
222         }
223
224         if (!sock->ops->fn_recvfrom) {
225                 return NT_STATUS_NOT_IMPLEMENTED;
226         }
227
228         return sock->ops->fn_recvfrom(sock, buf, wantlen, nread, 
229                                       mem_ctx, src_addr);
230 }
231
232 _PUBLIC_ NTSTATUS socket_send(struct socket_context *sock, 
233                               const DATA_BLOB *blob, size_t *sendlen)
234 {
235         if (sock == NULL) {
236                 return NT_STATUS_CONNECTION_DISCONNECTED;
237         }
238         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
239             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
240                 return NT_STATUS_INVALID_PARAMETER;
241         }
242
243         if (!sock->ops->fn_send) {
244                 return NT_STATUS_NOT_IMPLEMENTED;
245         }
246         
247         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
248             && blob->length > 1) {
249                 DATA_BLOB blob2 = *blob;
250                 if (random() % 10 == 0) {
251                         *sendlen = 0;
252                         return STATUS_MORE_ENTRIES;
253                 }
254                 /* The random size sends are incompatible with TLS and SASL
255                  * sockets, which require re-sends to be consistant */
256                 if (!(sock->flags & SOCKET_FLAG_ENCRYPT)) {
257                         blob2.length = 1+(random() % blob2.length);
258                 } else {
259                         /* This is particularly stressful on buggy
260                          * LDAP clients, that don't expect on LDAP
261                          * packet in many SASL packets */
262                         blob2.length = 1 + blob2.length/2;
263                 }
264                 return sock->ops->fn_send(sock, &blob2, sendlen);
265         }
266         return sock->ops->fn_send(sock, blob, sendlen);
267 }
268
269
270 _PUBLIC_ NTSTATUS socket_sendto(struct socket_context *sock, 
271                                 const DATA_BLOB *blob, size_t *sendlen, 
272                                 const struct socket_address *dest_addr)
273 {
274         if (sock == NULL) {
275                 return NT_STATUS_CONNECTION_DISCONNECTED;
276         }
277         if (sock->type != SOCKET_TYPE_DGRAM) {
278                 return NT_STATUS_INVALID_PARAMETER;
279         }
280
281         if (sock->state == SOCKET_STATE_CLIENT_CONNECTED ||
282             sock->state == SOCKET_STATE_SERVER_CONNECTED) {
283                 return NT_STATUS_INVALID_PARAMETER;
284         }
285
286         if (!sock->ops->fn_sendto) {
287                 return NT_STATUS_NOT_IMPLEMENTED;
288         }
289
290         return sock->ops->fn_sendto(sock, blob, sendlen, dest_addr);
291 }
292
293
294 /*
295   ask for the number of bytes in a pending incoming packet
296 */
297 _PUBLIC_ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending)
298 {
299         if (sock == NULL) {
300                 return NT_STATUS_CONNECTION_DISCONNECTED;
301         }
302         if (!sock->ops->fn_pending) {
303                 return NT_STATUS_NOT_IMPLEMENTED;
304         }
305         return sock->ops->fn_pending(sock, npending);
306 }
307
308
309 _PUBLIC_ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
310 {
311         if (sock == NULL) {
312                 return NT_STATUS_CONNECTION_DISCONNECTED;
313         }
314         if (!sock->ops->fn_set_option) {
315                 return NT_STATUS_NOT_IMPLEMENTED;
316         }
317
318         return sock->ops->fn_set_option(sock, option, val);
319 }
320
321 _PUBLIC_ char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
322 {
323         if (!sock->ops->fn_get_peer_name) {
324                 return NULL;
325         }
326
327         return sock->ops->fn_get_peer_name(sock, mem_ctx);
328 }
329
330 _PUBLIC_ struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
331 {
332         if (!sock->ops->fn_get_peer_addr) {
333                 return NULL;
334         }
335
336         return sock->ops->fn_get_peer_addr(sock, mem_ctx);
337 }
338
339 _PUBLIC_ struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
340 {
341         if (!sock->ops->fn_get_my_addr) {
342                 return NULL;
343         }
344
345         return sock->ops->fn_get_my_addr(sock, mem_ctx);
346 }
347
348 _PUBLIC_ struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx,
349                                                                    const struct socket_address *a)
350 {
351         struct tsocket_address *r;
352         int ret;
353
354         if (a->sockaddr) {
355                 ret = tsocket_address_bsd_from_sockaddr(mem_ctx,
356                                                         a->sockaddr,
357                                                         a->sockaddrlen,
358                                                         &r);
359         } else {
360                 ret = tsocket_address_inet_from_strings(mem_ctx,
361                                                         a->family,
362                                                         a->addr,
363                                                         a->port,
364                                                         &r);
365         }
366
367         if (ret != 0) {
368                 return NULL;
369         }
370
371         return r;
372 }
373
374 _PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
375                                                                   const struct tsocket_address *a)
376 {
377         ssize_t ret;
378         struct sockaddr_storage ss;
379         size_t sslen = sizeof(ss);
380
381         ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen);
382         if (ret < 0) {
383                 return NULL;
384         }
385
386         return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret);
387 }
388
389 _PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
390 {
391         struct socket_address *a;
392         struct tsocket_address *r;
393
394         a = socket_get_peer_addr(sock, mem_ctx);
395         if (a == NULL) {
396                 return NULL;
397         }
398
399         r = socket_address_to_tsocket_address(mem_ctx, a);
400         talloc_free(a);
401         return r;
402 }
403
404 _PUBLIC_ struct tsocket_address *socket_get_local_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_my_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_ int socket_get_fd(struct socket_context *sock)
420 {
421         if (!sock->ops->fn_get_fd) {
422                 return -1;
423         }
424
425         return sock->ops->fn_get_fd(sock);
426 }
427
428 /*
429   call dup() on a socket, and close the old fd. This is used to change
430   the fd to the lowest available number, to make select() more
431   efficient (select speed depends on the maxiumum fd number passed to
432   it)
433 */
434 _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock)
435 {
436         int fd;
437         if (sock->fd == -1) {
438                 return NT_STATUS_INVALID_HANDLE;
439         }
440         fd = dup(sock->fd);
441         if (fd == -1) {
442                 return map_nt_error_from_unix(errno);
443         }
444         close(sock->fd);
445         sock->fd = fd;
446         return NT_STATUS_OK;
447         
448 }
449
450 /* Create a new socket_address.  The type must match the socket type.
451  * The host parameter may be an IP or a hostname 
452  */
453
454 _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx,
455                                                             const char *family,
456                                                             const char *host,
457                                                             int port)
458 {
459         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
460         if (!addr) {
461                 return NULL;
462         }
463
464         addr->family = family;
465         addr->addr = talloc_strdup(addr, host);
466         if (!addr->addr) {
467                 talloc_free(addr);
468                 return NULL;
469         }
470         addr->port = port;
471         addr->sockaddr = NULL;
472         addr->sockaddrlen = 0;
473
474         return addr;
475 }
476
477 /* Create a new socket_address.  Copy the struct sockaddr into the new
478  * structure.  Used for hooks in the kerberos libraries, where they
479  * supply only a struct sockaddr */
480
481 _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, 
482                                                              struct sockaddr *sockaddr, 
483                                                              size_t sockaddrlen)
484 {
485         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
486         if (!addr) {
487                 return NULL;
488         }
489         addr->family = NULL; 
490         addr->addr = NULL;
491         addr->port = 0;
492         addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen);
493         if (!addr->sockaddr) {
494                 talloc_free(addr);
495                 return NULL;
496         }
497         addr->sockaddrlen = sockaddrlen;
498         return addr;
499 }
500
501 /* Copy a socket_address structure */
502 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
503                                            const struct socket_address *oaddr)
504 {
505         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
506         if (!addr) {
507                 return NULL;
508         }
509         addr->family    = oaddr->family;
510         if (oaddr->addr) {
511                 addr->addr      = talloc_strdup(addr, oaddr->addr);
512                 if (!addr->addr) {
513                         goto nomem;
514                 }
515         }
516         addr->port      = oaddr->port;
517         if (oaddr->sockaddr) {
518                 addr->sockaddr = (struct sockaddr *)talloc_memdup(addr,
519                                                                   oaddr->sockaddr,
520                                                                   oaddr->sockaddrlen);
521                 if (!addr->sockaddr) {
522                         goto nomem;
523                 }
524                 addr->sockaddrlen = oaddr->sockaddrlen;
525         }
526
527         return addr;
528
529 nomem:
530         talloc_free(addr);
531         return NULL;
532 }
533
534 _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum socket_type type)
535 {
536         extern const struct socket_ops *socket_ipv4_ops(enum socket_type);
537         extern const struct socket_ops *socket_ipv6_ops(enum socket_type);
538         extern const struct socket_ops *socket_unixdom_ops(enum socket_type);
539
540         if (strcmp("ip", family) == 0 || 
541             strcmp("ipv4", family) == 0) {
542                 return socket_ipv4_ops(type);
543         }
544
545 #if HAVE_IPV6
546         if (strcmp("ipv6", family) == 0) {
547                 return socket_ipv6_ops(type);
548         }
549 #endif
550
551         if (strcmp("unix", family) == 0) {
552                 return socket_unixdom_ops(type);
553         }
554
555         return NULL;
556 }
557
558 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
559
560 static const struct {
561         const char *name;
562         int level;
563         int option;
564         int value;
565         int opttype;
566 } socket_options[] = {
567   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
568   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
569   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
570 #ifdef TCP_NODELAY
571   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
572 #endif
573 #ifdef IPTOS_LOWDELAY
574   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
575 #endif
576 #ifdef IPTOS_THROUGHPUT
577   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
578 #endif
579 #ifdef SO_REUSEPORT
580   {"SO_REUSEPORT",      SOL_SOCKET,    SO_REUSEPORT,    0,                 OPT_BOOL},
581 #endif
582 #ifdef SO_SNDBUF
583   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
584 #endif
585 #ifdef SO_RCVBUF
586   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
587 #endif
588 #ifdef SO_SNDLOWAT
589   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
590 #endif
591 #ifdef SO_RCVLOWAT
592   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
593 #endif
594 #ifdef SO_SNDTIMEO
595   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
596 #endif
597 #ifdef SO_RCVTIMEO
598   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
599 #endif
600   {NULL,0,0,0,0}};
601
602
603 /**
604  Set user socket options.
605 **/
606 _PUBLIC_ void set_socket_options(int fd, const char *options)
607 {
608         const char **options_list = (const char **)str_list_make(NULL, options, " \t,");
609         int j;
610
611         if (!options_list)
612                 return;
613
614         for (j = 0; options_list[j]; j++) {
615                 const char *tok = options_list[j];
616                 int ret=0,i;
617                 int value = 1;
618                 char *p;
619                 bool got_value = false;
620
621                 if ((p = strchr(tok,'='))) {
622                         *p = 0;
623                         value = atoi(p+1);
624                         got_value = true;
625                 }
626
627                 for (i=0;socket_options[i].name;i++)
628                         if (strequal(socket_options[i].name,tok))
629                                 break;
630
631                 if (!socket_options[i].name) {
632                         DEBUG(0,("Unknown socket option %s\n",tok));
633                         continue;
634                 }
635
636                 switch (socket_options[i].opttype) {
637                 case OPT_BOOL:
638                 case OPT_INT:
639                         ret = setsockopt(fd,socket_options[i].level,
640                                                 socket_options[i].option,(char *)&value,sizeof(int));
641                         break;
642
643                 case OPT_ON:
644                         if (got_value)
645                                 DEBUG(0,("syntax error - %s does not take a value\n",tok));
646
647                         {
648                                 int on = socket_options[i].value;
649                                 ret = setsockopt(fd,socket_options[i].level,
650                                                         socket_options[i].option,(char *)&on,sizeof(int));
651                         }
652                         break;    
653                 }
654       
655                 if (ret != 0)
656                         DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
657         }
658
659         talloc_free(options_list);
660 }
661
662 /*
663   set some flags on a socket 
664  */
665 void socket_set_flags(struct socket_context *sock, unsigned flags)
666 {
667         sock->flags |= flags;
668 }