aboutsummaryrefslogtreecommitdiff
path: root/src/util/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/network.c')
-rw-r--r--src/util/network.c1386
1 files changed, 0 insertions, 1386 deletions
diff --git a/src/util/network.c b/src/util/network.c
deleted file mode 100644
index 014701e02..000000000
--- a/src/util/network.c
+++ /dev/null
@@ -1,1386 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/network.c
23 * @brief basic, low-level networking interface
24 * @author Nils Durner
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "disk.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "util-network", __VA_ARGS__)
32#define LOG_STRERROR_FILE(kind, syscall, \
33 filename) GNUNET_log_from_strerror_file (kind, \
34 "util-network", \
35 syscall, \
36 filename)
37#define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
38 "util-network", \
39 syscall)
40
41#define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
42
43
44#ifndef INVALID_SOCKET
45#define INVALID_SOCKET -1
46#endif
47
48
49/**
50 * @brief handle to a socket
51 */
52struct GNUNET_NETWORK_Handle
53{
54 int fd;
55
56 /**
57 * Address family / domain.
58 */
59 int af;
60
61 /**
62 * Type of the socket
63 */
64 int type;
65
66 /**
67 * Number of bytes in addr.
68 */
69 socklen_t addrlen;
70
71 /**
72 * Address we were bound to, or NULL.
73 */
74 struct sockaddr *addr;
75};
76
77
78/**
79 * Test if the given protocol family is supported by this system.
80 *
81 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
82 * @return #GNUNET_OK if the PF is supported
83 */
84int
85GNUNET_NETWORK_test_pf (int pf)
86{
87 static int cache_v4 = -1;
88 static int cache_v6 = -1;
89 static int cache_un = -1;
90 int s;
91 int ret;
92
93 switch (pf)
94 {
95 case PF_INET:
96 if (-1 != cache_v4)
97 return cache_v4;
98 break;
99
100 case PF_INET6:
101 if (-1 != cache_v6)
102 return cache_v6;
103 break;
104
105#ifdef PF_UNIX
106 case PF_UNIX:
107 if (-1 != cache_un)
108 return cache_un;
109 break;
110#endif
111 }
112 s = socket (pf, SOCK_STREAM, 0);
113 if (-1 == s)
114 {
115 if (EAFNOSUPPORT != errno)
116 {
117 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
118 "socket");
119 return GNUNET_SYSERR;
120 }
121 ret = GNUNET_NO;
122 }
123 else
124 {
125 GNUNET_break (0 == close (s));
126 ret = GNUNET_OK;
127 }
128 switch (pf)
129 {
130 case PF_INET:
131 cache_v4 = ret;
132 break;
133
134 case PF_INET6:
135 cache_v6 = ret;
136 break;
137
138#ifdef PF_UNIX
139 case PF_UNIX:
140 cache_un = ret;
141 break;
142#endif
143 }
144 return ret;
145}
146
147
148/**
149 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
150 * shorten it to an acceptable length while keeping it unique
151 * and making sure it remains a valid filename (if possible).
152 *
153 * @param unixpath long path, will be freed (or same pointer returned
154 * with moved 0-termination).
155 * @return shortened unixpath, NULL on error
156 */
157char *
158GNUNET_NETWORK_shorten_unixpath (char *unixpath)
159{
160 struct sockaddr_un dummy;
161 size_t slen;
162 char *end;
163 struct GNUNET_HashCode sh;
164 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
165 size_t upm;
166
167 upm = sizeof(dummy.sun_path);
168 slen = strlen (unixpath);
169 if (slen < upm)
170 return unixpath; /* no shortening required */
171 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
172 while (16 + strlen (unixpath) >= upm)
173 {
174 if (NULL == (end = strrchr (unixpath, '/')))
175 {
176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
177 _ (
178 "Unable to shorten unix path `%s' while keeping name unique\n"),
179 unixpath);
180 GNUNET_free (unixpath);
181 return NULL;
182 }
183 *end = '\0';
184 }
185 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
186 ae.encoding[16] = '\0';
187 strcat (unixpath, (char *) ae.encoding);
188 return unixpath;
189}
190
191
192/**
193 * If services crash, they can leave a unix domain socket file on the
194 * disk. This needs to be manually removed, because otherwise both
195 * bind() and connect() for the respective address will fail. In this
196 * function, we test if such a left-over file exists, and if so,
197 * remove it (unless there is a listening service at the address).
198 *
199 * @param un unix domain socket address to check
200 */
201void
202GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un)
203{
204 int s;
205 int eno;
206 struct stat sbuf;
207 int ret;
208
209 s = socket (AF_UNIX, SOCK_STREAM, 0);
210 if (-1 == s)
211 {
212 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
213 "Failed to open AF_UNIX socket");
214 return;
215 }
216 ret = connect (s,
217 (struct sockaddr *) un,
218 sizeof(struct sockaddr_un));
219 eno = errno;
220 GNUNET_break (0 == close (s));
221 if (0 == ret)
222 return; /* another process is listening, do not remove! */
223 if (ECONNREFUSED != eno)
224 return; /* some other error, likely "no such file or directory" -- all well */
225 /* should unlink, but sanity checks first */
226 if (0 != stat (un->sun_path,
227 &sbuf))
228 return; /* failed to 'stat', likely does not exist after all */
229 if (S_IFSOCK != (S_IFMT & sbuf.st_mode))
230 return; /* refuse to unlink anything except sockets */
231 /* finally, really unlink */
232 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
233 "Removing left-over `%s' from previous exeuction\n",
234 un->sun_path);
235 if (0 != unlink (un->sun_path))
236 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
237 "unlink",
238 un->sun_path);
239}
240
241
242#ifndef FD_COPY
243#define FD_COPY(s, d) do { GNUNET_memcpy ((d), (s), sizeof(fd_set)); } while (0)
244#endif
245
246
247/**
248 * Set if a socket should use blocking or non-blocking IO.
249 *
250 * @param fd socket
251 * @param doBlock blocking mode
252 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
253 */
254int
255GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd,
256 int doBlock)
257{
258 int flags = fcntl (fd->fd, F_GETFL);
259
260 if (flags == -1)
261 {
262 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
263 "fcntl");
264 return GNUNET_SYSERR;
265 }
266 if (doBlock)
267 flags &= ~O_NONBLOCK;
268
269 else
270 flags |= O_NONBLOCK;
271 if (0 != fcntl (fd->fd,
272 F_SETFL,
273 flags))
274
275 {
276 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
277 "fcntl");
278 return GNUNET_SYSERR;
279 }
280 return GNUNET_OK;
281}
282
283
284/**
285 * Make a socket non-inheritable to child processes
286 *
287 * @param h the socket to make non-inheritable
288 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
289 * @warning Not implemented on Windows
290 */
291static int
292socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
293{
294 int i;
295 i = fcntl (h->fd, F_GETFD);
296 if (i < 0)
297 return GNUNET_SYSERR;
298 if (i == (i | FD_CLOEXEC))
299 return GNUNET_OK;
300 i |= FD_CLOEXEC;
301 if (fcntl (h->fd, F_SETFD, i) < 0)
302 return GNUNET_SYSERR;
303
304 return GNUNET_OK;
305}
306
307
308#ifdef DARWIN
309/**
310 * The MSG_NOSIGNAL equivalent on Mac OS X
311 *
312 * @param h the socket to make non-delaying
313 */
314static int
315socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
316{
317 int abs_value = 1;
318
319 if (0 !=
320 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
321 (const void *) &abs_value,
322 sizeof(abs_value)))
323 return GNUNET_SYSERR;
324 return GNUNET_OK;
325}
326
327
328#endif
329
330
331/**
332 * Disable delays when sending data via the socket.
333 * (GNUnet makes sure that messages are as big as
334 * possible already).
335 *
336 * @param h the socket to make non-delaying
337 */
338static void
339socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
340{
341 int value = 1;
342
343 if (0 !=
344 setsockopt (h->fd,
345 IPPROTO_TCP,
346 TCP_NODELAY,
347 &value, sizeof(value)))
348 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
349 "setsockopt");
350}
351
352
353/**
354 * Perform proper canonical initialization for a network handle.
355 * Set it to non-blocking, make it non-inheritable to child
356 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
357 * stream socket) and check that it is smaller than FD_SETSIZE.
358 *
359 * @param h socket to initialize
360 * @param af address family of the socket
361 * @param type socket type
362 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
363 * failed and the handle was destroyed
364 */
365static int
366initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
367 int af,
368 int type)
369{
370 int eno;
371
372 h->af = af;
373 h->type = type;
374 if (h->fd == INVALID_SOCKET)
375 {
376 eno = errno;
377 GNUNET_free (h);
378 errno = eno;
379 return GNUNET_SYSERR;
380 }
381
382 if (h->fd >= FD_SETSIZE)
383 {
384 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
385 errno = EMFILE;
386 return GNUNET_SYSERR;
387 }
388
389 if (GNUNET_OK != socket_set_inheritable (h))
390 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
391 "socket_set_inheritable");
392
393 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
394 {
395 eno = errno;
396 GNUNET_break (0);
397 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
398 errno = eno;
399 return GNUNET_SYSERR;
400 }
401#ifdef DARWIN
402 if (GNUNET_SYSERR == socket_set_nosigpipe (h))
403 {
404 eno = errno;
405 GNUNET_break (0);
406 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
407 errno = eno;
408 return GNUNET_SYSERR;
409 }
410#endif
411 if ((type == SOCK_STREAM)
412#ifdef AF_UNIX
413 && (af != AF_UNIX)
414#endif
415 )
416 socket_set_nodelay (h);
417 return GNUNET_OK;
418}
419
420
421/**
422 * accept a new connection on a socket
423 *
424 * @param desc bound socket
425 * @param address address of the connecting peer, may be NULL
426 * @param address_len length of @a address
427 * @return client socket
428 */
429struct GNUNET_NETWORK_Handle *
430GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
431 struct sockaddr *address,
432 socklen_t *address_len)
433{
434 struct GNUNET_NETWORK_Handle *ret;
435 int eno;
436
437 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
438#if DEBUG_NETWORK
439 {
440 struct sockaddr_storage name;
441 socklen_t namelen = sizeof(name);
442
443 int gsn = getsockname (desc->fd,
444 (struct sockaddr *) &name,
445 &namelen);
446
447 if (0 == gsn)
448 LOG (GNUNET_ERROR_TYPE_DEBUG,
449 "Accepting connection on `%s'\n",
450 GNUNET_a2s ((const struct sockaddr *) &name,
451 namelen));
452 }
453#endif
454 ret->fd = accept (desc->fd,
455 address,
456 address_len);
457 if (-1 == ret->fd)
458 {
459 eno = errno;
460 GNUNET_free (ret);
461 errno = eno;
462 return NULL;
463 }
464 if (GNUNET_OK !=
465 initialize_network_handle (ret,
466 (NULL != address) ? address->sa_family :
467 desc->af,
468 SOCK_STREAM))
469 {
470 return NULL;
471 }
472 return ret;
473}
474
475
476/**
477 * Bind a socket to a particular address.
478 *
479 * @param desc socket to bind
480 * @param address address to be bound
481 * @param address_len length of @a address
482 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
483 */
484int
485GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
486 const struct sockaddr *address,
487 socklen_t address_len)
488{
489 int ret;
490
491#ifdef IPV6_V6ONLY
492#ifdef IPPROTO_IPV6
493 {
494 const int on = 1;
495
496 if (AF_INET6 == desc->af)
497 if (setsockopt (desc->fd,
498 IPPROTO_IPV6,
499 IPV6_V6ONLY,
500 (const void *) &on,
501 sizeof(on)))
502 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
503 "setsockopt");
504 }
505#endif
506#endif
507 if (AF_UNIX == address->sa_family)
508 GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address);
509
510 {
511 const int on = 1;
512
513 if ( (SOCK_STREAM == desc->type) &&
514 (0 != setsockopt (desc->fd,
515 SOL_SOCKET,
516 SO_REUSEADDR,
517 &on, sizeof(on))) )
518 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
519 "setsockopt");
520 }
521 {
522 /* set permissions of newly created non-abstract UNIX domain socket to
523 "user-only"; applications can choose to relax this later */
524 mode_t old_mask = 0; /* assigned to make compiler happy */
525 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
526 int not_abstract = 0;
527
528 if ((AF_UNIX == address->sa_family)
529 && ('\0' != un->sun_path[0])) /* Not an abstract socket */
530 not_abstract = 1;
531 if (not_abstract)
532 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH
533 | S_IXOTH);
534
535 ret = bind (desc->fd,
536 address,
537 address_len);
538
539 if (not_abstract)
540 (void) umask (old_mask);
541 }
542 if (0 != ret)
543 return GNUNET_SYSERR;
544
545 desc->addr = GNUNET_malloc (address_len);
546 GNUNET_memcpy (desc->addr, address, address_len);
547 desc->addrlen = address_len;
548
549 return GNUNET_OK;
550}
551
552
553/**
554 * Close a socket
555 *
556 * @param desc socket
557 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
558 */
559int
560GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
561{
562 int ret;
563
564 ret = close (desc->fd);
565
566 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
567
568 /* Cleanup the UNIX domain socket and its parent directories in case of non
569 abstract sockets */
570 if ((AF_UNIX == desc->af) &&
571 (NULL != desc->addr) &&
572 ('\0' != un->sun_path[0]))
573 {
574 char *dirname = GNUNET_strndup (un->sun_path,
575 sizeof(un->sun_path));
576
577 if (0 != unlink (dirname))
578 {
579 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
580 "unlink",
581 dirname);
582 }
583 else
584 {
585 size_t len;
586
587 len = strlen (dirname);
588 while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
589 len--;
590 dirname[len] = '\0';
591 if ((0 != len) && (0 != rmdir (dirname)))
592 {
593 switch (errno)
594 {
595 case EACCES:
596 case ENOTEMPTY:
597 case EPERM:
598 /* these are normal and can just be ignored */
599 break;
600
601 default:
602 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
603 "rmdir",
604 dirname);
605 break;
606 }
607 }
608 }
609 GNUNET_free (dirname);
610 }
611 GNUNET_NETWORK_socket_free_memory_only_ (desc);
612 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
613}
614
615
616/**
617 * Only free memory of a socket, keep the file descriptor untouched.
618 *
619 * @param desc socket
620 */
621void
622GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
623{
624 GNUNET_free (desc->addr);
625 GNUNET_free (desc);
626}
627
628
629/**
630 * Box a native socket (and check that it is a socket).
631 *
632 * @param fd socket to box
633 * @return NULL on error (including not supported on target platform)
634 */
635struct GNUNET_NETWORK_Handle *
636GNUNET_NETWORK_socket_box_native (int fd)
637{
638 struct GNUNET_NETWORK_Handle *ret;
639
640 if (fcntl (fd, F_GETFD) < 0)
641 return NULL; /* invalid FD */
642 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
643 ret->fd = fd;
644 ret->af = AF_UNSPEC;
645 return ret;
646}
647
648
649/**
650 * Connect a socket to some remote address.
651 *
652 * @param desc socket
653 * @param address peer address
654 * @param address_len length of @a address
655 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
656 */
657int
658GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
659 const struct sockaddr *address,
660 socklen_t address_len)
661{
662 int ret;
663
664 ret = connect (desc->fd,
665 address,
666 address_len);
667
668 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
669}
670
671
672/**
673 * Get socket options
674 *
675 * @param desc socket
676 * @param level protocol level of the option
677 * @param optname identifier of the option
678 * @param optval options
679 * @param optlen length of @a optval
680 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
681 */
682int
683GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
684 int level,
685 int optname,
686 void *optval,
687 socklen_t *optlen)
688{
689 int ret;
690
691 ret = getsockopt (desc->fd,
692 level,
693 optname,
694 optval, optlen);
695
696 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
697}
698
699
700/**
701 * Listen on a socket
702 *
703 * @param desc socket
704 * @param backlog length of the listen queue
705 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
706 */
707int
708GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
709 int backlog)
710{
711 int ret;
712
713 ret = listen (desc->fd,
714 backlog);
715
716 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
717}
718
719
720/**
721 * How much data is available to be read on this descriptor?
722 *
723 * @param desc socket
724 * @returns #GNUNET_SYSERR if no data is available, or on error!
725 */
726ssize_t
727GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *desc)
728{
729 int error;
730
731 /* How much is there to be read? */
732 int pending;
733
734 error = ioctl (desc->fd,
735 FIONREAD,
736 &pending);
737 if (0 == error)
738 return (ssize_t) pending;
739 return GNUNET_SYSERR;
740}
741
742
743/**
744 * Read data from a socket (always non-blocking).
745 *
746 * @param desc socket
747 * @param buffer buffer
748 * @param length length of @a buffer
749 * @param src_addr either the source to recv from, or all zeroes
750 * to be filled in by recvfrom
751 * @param addrlen length of the @a src_addr
752 */
753ssize_t
754GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
755 void *buffer,
756 size_t length,
757 struct sockaddr *src_addr,
758 socklen_t *addrlen)
759{
760 int flags = 0;
761
762#ifdef MSG_DONTWAIT
763 flags |= MSG_DONTWAIT;
764#endif
765 return recvfrom (desc->fd,
766 buffer,
767 length,
768 flags,
769 src_addr,
770 addrlen);
771}
772
773
774/**
775 * Read data from a connected socket (always non-blocking).
776 *
777 * @param desc socket
778 * @param buffer buffer
779 * @param length length of @a buffer
780 * @return number of bytes received, -1 on error
781 */
782ssize_t
783GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle *desc,
784 void *buffer,
785 size_t length)
786{
787 int ret;
788 int flags;
789
790 flags = 0;
791
792#ifdef MSG_DONTWAIT
793 flags |= MSG_DONTWAIT;
794#endif
795 ret = recv (desc->fd,
796 buffer,
797 length,
798 flags);
799 return ret;
800}
801
802
803/**
804 * Send data (always non-blocking).
805 *
806 * @param desc socket
807 * @param buffer data to send
808 * @param length size of the @a buffer
809 * @return number of bytes sent, #GNUNET_SYSERR on error
810 */
811ssize_t
812GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle *desc,
813 const void *buffer,
814 size_t length)
815{
816 int ret;
817 int flags;
818
819 flags = 0;
820#ifdef MSG_DONTWAIT
821 flags |= MSG_DONTWAIT;
822#endif
823#ifdef MSG_NOSIGNAL
824 flags |= MSG_NOSIGNAL;
825#endif
826 ret = send (desc->fd,
827 buffer,
828 length,
829 flags);
830 return ret;
831}
832
833
834/**
835 * Send data to a particular destination (always non-blocking).
836 * This function only works for UDP sockets.
837 *
838 * @param desc socket
839 * @param message data to send
840 * @param length size of the @a message
841 * @param dest_addr destination address
842 * @param dest_len length of @a address
843 * @return number of bytes sent, #GNUNET_SYSERR on error
844 */
845ssize_t
846GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle *desc,
847 const void *message,
848 size_t length,
849 const struct sockaddr *dest_addr,
850 socklen_t dest_len)
851{
852 int flags = 0;
853
854#ifdef MSG_DONTWAIT
855 flags |= MSG_DONTWAIT;
856#endif
857#ifdef MSG_NOSIGNAL
858 flags |= MSG_NOSIGNAL;
859#endif
860 return sendto (desc->fd,
861 message,
862 length,
863 flags,
864 dest_addr,
865 dest_len);
866}
867
868
869/**
870 * Set socket option
871 *
872 * @param fd socket
873 * @param level protocol level of the option
874 * @param option_name option identifier
875 * @param option_value value to set
876 * @param option_len size of @a option_value
877 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
878 */
879int
880GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
881 int level,
882 int option_name,
883 const void *option_value,
884 socklen_t option_len)
885{
886 return (0 == setsockopt (fd->fd,
887 level,
888 option_name,
889 option_value,
890 option_len))
891 ? GNUNET_OK
892 : GNUNET_SYSERR;
893}
894
895
896/**
897 * Create a new socket. Configure it for non-blocking IO and
898 * mark it as non-inheritable to child processes (set the
899 * close-on-exec flag).
900 *
901 * @param domain domain of the socket
902 * @param type socket type
903 * @param protocol network protocol
904 * @return new socket, NULL on error
905 */
906struct GNUNET_NETWORK_Handle *
907GNUNET_NETWORK_socket_create (int domain,
908 int type,
909 int protocol)
910{
911 struct GNUNET_NETWORK_Handle *ret;
912 int fd;
913
914 fd = socket (domain, type, protocol);
915 if (-1 == fd)
916 return NULL;
917 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
918 ret->fd = fd;
919 if (GNUNET_OK !=
920 initialize_network_handle (ret,
921 domain,
922 type))
923 return NULL;
924 return ret;
925}
926
927
928/**
929 * Shut down socket operations
930 * @param desc socket
931 * @param how type of shutdown
932 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
933 */
934int
935GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc,
936 int how)
937{
938 int ret;
939
940 ret = shutdown (desc->fd, how);
941
942 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR;
943}
944
945
946/**
947 * Disable the "CORK" feature for communication with the given socket,
948 * forcing the OS to immediately flush the buffer on transmission
949 * instead of potentially buffering multiple messages. Essentially
950 * reduces the OS send buffers to zero.
951 *
952 * @param desc socket
953 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
954 */
955int
956GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
957{
958 int ret = 0;
959
960#ifdef __linux__
961 int value = 0;
962
963 if (0 !=
964 (ret =
965 setsockopt (desc->fd,
966 SOL_SOCKET,
967 SO_SNDBUF,
968 &value,
969 sizeof(value))))
970 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
971 "setsockopt");
972 if (0 !=
973 (ret =
974 setsockopt (desc->fd,
975 SOL_SOCKET,
976 SO_RCVBUF,
977 &value,
978 sizeof(value))))
979 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
980 "setsockopt");
981#endif
982 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
983}
984
985
986/**
987 * Reset FD set
988 *
989 * @param fds fd set
990 */
991void
992GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
993{
994 FD_ZERO (&fds->sds);
995 fds->nsds = 0;
996}
997
998
999/**
1000 * Add a socket to the FD set
1001 *
1002 * @param fds fd set
1003 * @param desc socket to add
1004 */
1005void
1006GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
1007 const struct GNUNET_NETWORK_Handle *desc)
1008{
1009 FD_SET (desc->fd,
1010 &fds->sds);
1011 fds->nsds = GNUNET_MAX (fds->nsds,
1012 desc->fd + 1);
1013}
1014
1015
1016/**
1017 * Check whether a socket is part of the fd set
1018 *
1019 * @param fds fd set
1020 * @param desc socket
1021 * @return 0 if the FD is not set
1022 */
1023int
1024GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
1025 const struct GNUNET_NETWORK_Handle *desc)
1026{
1027 return FD_ISSET (desc->fd,
1028 &fds->sds);
1029}
1030
1031
1032/**
1033 * Add one fd set to another
1034 *
1035 * @param dst the fd set to add to
1036 * @param src the fd set to add from
1037 */
1038void
1039GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
1040 const struct GNUNET_NETWORK_FDSet *src)
1041{
1042 int nfds;
1043
1044 for (nfds = src->nsds; nfds >= 0; nfds--)
1045 if (FD_ISSET (nfds, &src->sds))
1046 FD_SET (nfds, &dst->sds);
1047 dst->nsds = GNUNET_MAX (dst->nsds,
1048 src->nsds);
1049}
1050
1051
1052/**
1053 * Copy one fd set to another
1054 *
1055 * @param to destination
1056 * @param from source
1057 */
1058void
1059GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1060 const struct GNUNET_NETWORK_FDSet *from)
1061{
1062 FD_COPY (&from->sds,
1063 &to->sds);
1064 to->nsds = from->nsds;
1065}
1066
1067
1068/**
1069 * Return file descriptor for this network handle
1070 *
1071 * @param desc wrapper to process
1072 * @return POSIX file descriptor
1073 */
1074int
1075GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc)
1076{
1077 return desc->fd;
1078}
1079
1080
1081/**
1082 * Return sockaddr for this network handle
1083 *
1084 * @param desc wrapper to process
1085 * @return sockaddr
1086 */
1087struct sockaddr*
1088GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc)
1089{
1090 return desc->addr;
1091}
1092
1093
1094/**
1095 * Return sockaddr length for this network handle
1096 *
1097 * @param desc wrapper to process
1098 * @return socklen_t for sockaddr
1099 */
1100socklen_t
1101GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc)
1102{
1103 return desc->addrlen;
1104}
1105
1106
1107/**
1108 * Copy a native fd set
1109 *
1110 * @param to destination
1111 * @param from native source set
1112 * @param nfds the biggest socket number in from + 1
1113 */
1114void
1115GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1116 const fd_set *from,
1117 int nfds)
1118{
1119 FD_COPY (from,
1120 &to->sds);
1121 to->nsds = nfds;
1122}
1123
1124
1125/**
1126 * Set a native fd in a set
1127 *
1128 * @param to destination
1129 * @param nfd native FD to set
1130 */
1131void
1132GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
1133 int nfd)
1134{
1135 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1136 FD_SET (nfd, &to->sds);
1137 to->nsds = GNUNET_MAX (nfd + 1,
1138 to->nsds);
1139}
1140
1141
1142/**
1143 * Test native fd in a set
1144 *
1145 * @param to set to test, NULL for empty set
1146 * @param nfd native FD to test, or -1 for none
1147 * @return #GNUNET_YES if FD is set in the set
1148 */
1149int
1150GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1151 int nfd)
1152{
1153 if ((-1 == nfd) ||
1154 (NULL == to))
1155 return GNUNET_NO;
1156 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1157}
1158
1159
1160/**
1161 * Add a file handle to the fd set
1162 * @param fds fd set
1163 * @param h the file handle to add
1164 */
1165void
1166GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1167 const struct GNUNET_DISK_FileHandle *h)
1168{
1169 int fd;
1170
1171 GNUNET_assert (GNUNET_OK ==
1172 GNUNET_DISK_internal_file_handle_ (h,
1173 &fd,
1174 sizeof(int)));
1175 FD_SET (fd,
1176 &fds->sds);
1177 fds->nsds = GNUNET_MAX (fd + 1,
1178 fds->nsds);
1179}
1180
1181
1182/**
1183 * Add a file handle to the fd set
1184 * @param fds fd set
1185 * @param h the file handle to add
1186 */
1187void
1188GNUNET_NETWORK_fdset_handle_set_first (struct GNUNET_NETWORK_FDSet *fds,
1189 const struct GNUNET_DISK_FileHandle *h)
1190{
1191 GNUNET_NETWORK_fdset_handle_set (fds, h);
1192}
1193
1194
1195/**
1196 * Check if a file handle is part of an fd set
1197 *
1198 * @param fds fd set
1199 * @param h file handle
1200 * @return #GNUNET_YES if the file handle is part of the set
1201 */
1202int
1203GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1204 const struct GNUNET_DISK_FileHandle *h)
1205{
1206 return FD_ISSET (h->fd,
1207 &fds->sds);
1208}
1209
1210
1211/**
1212 * Checks if two fd sets overlap
1213 *
1214 * @param fds1 first fd set
1215 * @param fds2 second fd set
1216 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1217 */
1218int
1219GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1220 const struct GNUNET_NETWORK_FDSet *fds2)
1221{
1222 int nfds;
1223
1224 nfds = GNUNET_MIN (fds1->nsds,
1225 fds2->nsds);
1226 while (nfds > 0)
1227 {
1228 nfds--;
1229 if ((FD_ISSET (nfds,
1230 &fds1->sds)) &&
1231 (FD_ISSET (nfds,
1232 &fds2->sds)))
1233 return GNUNET_YES;
1234 }
1235 return GNUNET_NO;
1236}
1237
1238
1239/**
1240 * Creates an fd set
1241 *
1242 * @return a new fd set
1243 */
1244struct GNUNET_NETWORK_FDSet *
1245GNUNET_NETWORK_fdset_create ()
1246{
1247 struct GNUNET_NETWORK_FDSet *fds;
1248
1249 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1250 GNUNET_NETWORK_fdset_zero (fds);
1251 return fds;
1252}
1253
1254
1255/**
1256 * Releases the associated memory of an fd set
1257 *
1258 * @param fds fd set
1259 */
1260void
1261GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1262{
1263 GNUNET_free (fds);
1264}
1265
1266
1267/**
1268 * Test if the given @a port is available.
1269 *
1270 * @param ipproto transport protocol to test (e.g. IPPROTO_TCP)
1271 * @param port port number to test
1272 * @return #GNUNET_OK if the port is available, #GNUNET_NO if not
1273 */
1274int
1275GNUNET_NETWORK_test_port_free (int ipproto,
1276 uint16_t port)
1277{
1278 struct GNUNET_NETWORK_Handle *socket;
1279 int bind_status;
1280 int socktype;
1281 char open_port_str[6];
1282 struct addrinfo hint;
1283 struct addrinfo *ret;
1284 struct addrinfo *ai;
1285
1286 GNUNET_snprintf (open_port_str,
1287 sizeof(open_port_str),
1288 "%u",
1289 (unsigned int) port);
1290 socktype = (IPPROTO_TCP == ipproto) ? SOCK_STREAM : SOCK_DGRAM;
1291 ret = NULL;
1292 memset (&hint, 0, sizeof(hint));
1293 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
1294 hint.ai_socktype = socktype;
1295 hint.ai_protocol = ipproto;
1296 hint.ai_addrlen = 0;
1297 hint.ai_addr = NULL;
1298 hint.ai_canonname = NULL;
1299 hint.ai_next = NULL;
1300 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
1301 GNUNET_assert (0 == getaddrinfo (NULL,
1302 open_port_str,
1303 &hint,
1304 &ret));
1305 bind_status = GNUNET_NO;
1306 for (ai = ret; NULL != ai; ai = ai->ai_next)
1307 {
1308 socket = GNUNET_NETWORK_socket_create (ai->ai_family,
1309 ai->ai_socktype,
1310 ai->ai_protocol);
1311 if (NULL == socket)
1312 continue;
1313 bind_status = GNUNET_NETWORK_socket_bind (socket,
1314 ai->ai_addr,
1315 ai->ai_addrlen);
1316 GNUNET_NETWORK_socket_close (socket);
1317 if (GNUNET_OK != bind_status)
1318 break;
1319 }
1320 freeaddrinfo (ret);
1321 return bind_status;
1322}
1323
1324
1325/**
1326 * Check if sockets or pipes meet certain conditions
1327 *
1328 * @param rfds set of sockets or pipes to be checked for readability
1329 * @param wfds set of sockets or pipes to be checked for writability
1330 * @param efds set of sockets or pipes to be checked for exceptions
1331 * @param timeout relative value when to return
1332 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1333 */
1334int
1335GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1336 struct GNUNET_NETWORK_FDSet *wfds,
1337 struct GNUNET_NETWORK_FDSet *efds,
1338 const struct GNUNET_TIME_Relative timeout)
1339{
1340 int nfds;
1341 struct timeval tv;
1342
1343 if (NULL != rfds)
1344 nfds = rfds->nsds;
1345 else
1346 nfds = 0;
1347 if (NULL != wfds)
1348 nfds = GNUNET_MAX (nfds,
1349 wfds->nsds);
1350 if (NULL != efds)
1351 nfds = GNUNET_MAX (nfds,
1352 efds->nsds);
1353 if ((0 == nfds) &&
1354 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
1355 {
1356 GNUNET_break (0);
1357 LOG (GNUNET_ERROR_TYPE_ERROR,
1358 _ (
1359 "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1360 "select");
1361 }
1362 if (timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us > (unsigned
1363 long long)
1364 LONG_MAX)
1365 {
1366 tv.tv_sec = LONG_MAX;
1367 tv.tv_usec = 999999L;
1368 }
1369 else
1370 {
1371 tv.tv_sec = (long) (timeout.rel_value_us
1372 / GNUNET_TIME_UNIT_SECONDS.rel_value_us);
1373 tv.tv_usec =
1374 (timeout.rel_value_us
1375 - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1376 }
1377 return select (nfds,
1378 (NULL != rfds) ? &rfds->sds : NULL,
1379 (NULL != wfds) ? &wfds->sds : NULL,
1380 (NULL != efds) ? &efds->sds : NULL,
1381 (timeout.rel_value_us ==
1382 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1383}
1384
1385
1386/* end of network.c */