Rename "subsystems" directory to "base"
[oonf.git] / src / base / os_generic / os_fd_generic_configsocket.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /**
43  * @file
44  */
45
46 #include <errno.h>
47 #include <fcntl.h>
48
49 #include <oonf/oonf.h>
50 #include <oonf/libcommon/netaddr.h>
51 #include <oonf/libcommon/string.h>
52 #include <oonf/libcore/oonf_logging.h>
53 #include <oonf/base/os_interface.h>
54
55 #include <oonf/base/os_fd.h>
56 #include <oonf/base/os_generic/os_fd_generic_configsocket.h>
57
58 /**
59  * Configure a network socket
60  * @param sock filedescriptor
61  * @param bind_to ip/port to bind the socket to
62  * @param recvbuf size of input buffer for socket
63  * @param rawip true if socket is a raw ip socket, false otherwise
64  * @param os_if pointer to interface to bind socket on,
65  *   NULL if socket should not be bound to an interface
66  * @param log_src logging source for error messages
67  * @return -1 if an error happened, 0 otherwise
68  */
69 int
70 os_fd_generic_configsocket(struct os_fd *sock, const union netaddr_socket *bind_to, size_t recvbuf, bool rawip,
71   const struct os_interface *os_if, enum oonf_log_source log_src) {
72   union netaddr_socket bindto;
73   struct netaddr_str buf;
74   socklen_t addrlen;
75   int value;
76
77   /* temporary copy bindto address */
78   memcpy(&bindto, bind_to, sizeof(bindto));
79
80   if (os_fd_set_nonblocking(sock)) {
81     OONF_WARN(log_src, "Cannot make socket non-blocking %s: %s (%d)\n", netaddr_socket_to_string(&buf, &bindto),
82       strerror(errno), errno);
83     return -1;
84   }
85
86 #if defined(IPV6_V6ONLY)
87   if (!rawip && bind_to->std.sa_family == AF_INET6) {
88     value = 1;
89     if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&value, sizeof(value)) < 0) {
90       OONF_WARN(log_src, "Could not force socket to IPv6 only, continue: %s (%d)\n", strerror(errno), errno);
91     }
92   }
93 #endif
94
95 #if defined(SO_BINDTODEVICE)
96   /* this is binding the socket, not a multicast address */
97   if (os_if != NULL && !os_if->flags.any &&
98       setsockopt(sock->fd, SOL_SOCKET, SO_BINDTODEVICE, os_if->name, strlen(os_if->name) + 1) < 0) {
99     OONF_WARN(log_src, "Cannot bind socket to interface %s: %s (%d)\n", os_if->name, strerror(errno), errno);
100     return -1;
101   }
102 #endif
103
104 #if defined(SO_REUSEADDR)
105   /* allow to reuse address */
106   value = 1;
107   if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0) {
108     OONF_WARN(log_src, "Cannot reuse address for %s: %s (%d)\n", netaddr_socket_to_string(&buf, &bindto),
109       strerror(errno), errno);
110     return -1;
111   }
112 #endif
113
114 #if defined(IP_RECVIF)
115   if (os_if != NULL && setsockopt(sock, IPPROTO_IP, IP_RECVIF, &yes, sizeof(yes)) < 0) {
116     OONF_WARN(log_src, "Cannot apply IP_RECVIF for %s: %s (%d)\n", netaddr_socket_to_string(&buf, &bindto),
117       strerror(errno), errno);
118     return -1;
119   }
120 #endif
121
122 #if defined(SO_RCVBUF)
123   if (recvbuf > 0) {
124     while (recvbuf > 8192) {
125       if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, (void *)&recvbuf, sizeof(recvbuf)) == 0) {
126         break;
127       }
128
129       recvbuf -= 1024;
130     }
131
132     if (recvbuf < 8192) {
133       OONF_WARN(log_src, "Cannot setup receive buffer size for %s: %s (%d)\n", netaddr_socket_to_string(&buf, &bindto),
134         strerror(errno), errno);
135       return -1;
136     }
137   }
138 #endif
139
140   /* add ipv6 interface scope if necessary */
141   if (os_if != NULL && netaddr_socket_get_addressfamily(&bindto) == AF_INET6) {
142     bindto.v6.sin6_scope_id = os_if->index;
143   }
144
145   /* bind the socket to the port number */
146   addrlen = sizeof(bindto);
147   if (bind(sock->fd, &bindto.std, addrlen) < 0) {
148     OONF_WARN(log_src, "Cannot bind socket to address %s: %s (%d)\n", netaddr_socket_to_string(&buf, &bindto),
149       strerror(errno), errno);
150
151     return -1;
152   }
153
154   return 0;
155 }