The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
socket.h
Go to the documentation of this file.
1#pragma once
2
3/*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19/** Functions for establishing and managing low level sockets
20 *
21 * @file src/lib/util/socket.c
22 *
23 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 * @author Alan DeKok (aland@freeradius.org)
25 *
26 * @copyright 2015 The FreeRADIUS project
27 */
28RCSIDH(socket_h, "$Id: 6a6460f79064afa6d29cc8c117a24a719ab3b6a7 $")
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34#include <freeradius-devel/build.h>
35#include <freeradius-devel/missing.h>
36#include <freeradius-devel/util/inet.h>
37#include <freeradius-devel/util/time.h>
38
39#include <stdbool.h>
40#include <stdint.h>
41#include <string.h>
42#include <sys/time.h>
43
44#ifdef HAVE_SYS_UN_H
45# include <sys/un.h>
46/*
47 * The linux headers define the macro as:
48 *
49 * # define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
50 * + strlen ((ptr)->sun_path))
51 *
52 * Which trips UBSAN, because it sees an operation on a NULL pointer.
53 */
54# undef SUN_LEN
55# define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
56#endif
57
58/** Holds information necessary for binding or connecting to a socket.
59 *
60 * May also be used in protocol contexts to store information necessary for
61 * returning packets to their originators.
62 */
63typedef struct {
64 union {
65 struct {
66 int ifindex; //!< Source interface to bind to or originate the packet from.
67 uint16_t src_port; //!< Port to bind to, or originate the packet from.
68 uint16_t dst_port; //!< Port to connect to or send the packet to.
69
70 fr_ipaddr_t src_ipaddr; //!< IP address to bind to, or originate the packet from.
71 fr_ipaddr_t dst_ipaddr; //!< IP address to connect to, or send the packet to.
72 } inet;
73
74 struct {
75 char const *path; //!< Unix socket path.
76 } unix;
77 };
78 int af; //!< AF_INET, AF_INET6, or AF_UNIX
79 int type; //!< SOCK_STREAM, SOCK_DGRAM, etc.
80
81 int fd; //!< File descriptor if this is a live socket.
83
84/** Check the proto value is sane/supported
85 *
86 * @param[in] proto to check
87 * @return
88 * - true if it is.
89 * - false if it's not.
90 */
91static inline bool fr_socket_proto_is_known(int proto)
92{
93 /*
94 * Check the protocol is sane
95 */
96 switch (proto) {
97 case IPPROTO_UDP:
98 case IPPROTO_TCP:
99#ifdef IPPROTO_SCTP
100 case IPPROTO_SCTP:
101#endif
102 return true;
103
104 default:
105 fr_strerror_printf("Unknown IP protocol %d", proto);
106 return false;
107 }
108}
109
110#define FR_SOCKET_ADDR_ALLOC_DEF_FUNC(_func, ...) \
111 fr_socket_t *addr; \
112 addr = talloc(ctx, fr_socket_t); \
113 if (unlikely(!addr)) return NULL; \
114 return _func(addr, ##__VA_ARGS__);
115
116/** Swap src/dst information of a fr_socket_t
117 *
118 * @param[out] dst Where to write the swapped addresses. May be the same as src.
119 * @param[in] src Socket address to swap.
120 */
121static inline void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
122{
123 fr_socket_t tmp = *src;
124
125 if (dst != src) *dst = tmp; /* copy non-address fields over */
126
127 dst->inet.dst_ipaddr = tmp.inet.src_ipaddr;
128 dst->inet.dst_port = tmp.inet.src_port;
129 dst->inet.src_ipaddr = tmp.inet.dst_ipaddr;
130 dst->inet.src_port = tmp.inet.dst_port;
131}
132
133/** Initialise a fr_socket_t for connecting to a remote host using a specific src interface, address and port
134 *
135 * Can also be used to record information from an incoming packet so that we can
136 * identify the correct return path later.
137 *
138 * @param[out] addr to initialise.
139 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
140 * @param[in] ifindex The interface to originate the packet from Pass <= 0 to
141 * indicate an unknown or unspecified interface.
142 * @param[in] src_ipaddr The source IP address of the packet, or source interface for
143 * packets to egress out of.
144 * @param[in] src_port The source port of the packet or the source
145 * @param[in] dst_ipaddr The destination IP address of the packet.
146 * @param[in] dst_port The destination port of the packet.
147 * @return
148 * - NULL if invalid parameters are provided.
149 * - An initialised fr_socket_t struct.
150 */
152 int proto,
153 int ifindex, fr_ipaddr_t const *src_ipaddr, int src_port,
154 fr_ipaddr_t const *dst_ipaddr, int dst_port)
155{
156 if (!fr_socket_proto_is_known(proto)) return NULL;
157
158 *addr = (fr_socket_t){
159 .af = src_ipaddr->af,
160 .type = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM,
161 .inet = {
162 .ifindex = ifindex,
163 .src_ipaddr = *src_ipaddr,
164 .src_port = src_port,
165 .dst_ipaddr = *dst_ipaddr,
166 .dst_port = dst_port
167 }
168 };
169
170 return addr;
171}
172
173/** Initialise a fr_socket_t for connecting to a remote host using a specific src interface, address and port
174 *
175 * Can also be used to record information from an incoming packet so that we can
176 * identify the correct return path later.
177 *
178 * @param[in] ctx to allocate a new #fr_socket_t struct in.
179 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
180 * @param[in] ifindex The interface to originate the packet from Pass <= 0 to
181 * indicate an unknown or unspecified interface.
182 * @param[in] src_ipaddr The source IP address of the packet, or source interface for
183 * packets to egress out of.
184 * @param[in] src_port The source port of the packet or the source
185 * @param[in] dst_ipaddr The destination IP address of the packet.
186 * @param[in] dst_port The destination port of the packet.
187 * @return
188 * - NULL if invalid parameters are provided.
189 * - An initialised fr_socket_t struct.
190 */
191static inline fr_socket_t *fr_socket_addr_alloc_inet(TALLOC_CTX *ctx, int proto,
192 int ifindex, fr_ipaddr_t const *src_ipaddr, int src_port,
193 fr_ipaddr_t const *dst_ipaddr, int dst_port)
194{
196 proto, ifindex, src_ipaddr, src_port, dst_ipaddr, dst_port)
197}
198
199/** A variant of fr_socket_addr_alloc_inet will also allocates a #fr_socket_t
200 *
201
202 * @param[out] addr to initialise.
203 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
204 * @param[in] ifindex The interface to originate the packet from Pass <= 0 to
205 * indicate an unknown or unspecified interface.
206 * @param[in] ipaddr The IP address to bind to. May be all zeros to bind to
207 * all addresses, but the AF must still be specified.
208 * @param[in] port The source port to bind to.
209 * @return
210 * - NULL if invalid parameters are provided.
211 * - An initialised fr_socket_t struct.
212 */
214 int proto, int ifindex, fr_ipaddr_t const *ipaddr, int port)
215{
216 if (!fr_socket_proto_is_known(proto)) return NULL;
217
218 *addr = (fr_socket_t){
219 .af = ipaddr->af,
220 .type = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM,
221 .inet = {
222 .ifindex = ifindex,
223 .src_ipaddr = *ipaddr,
224 .src_port = port
225 }
226 };
227
228 return addr;
229}
230
231/** A variant of fr_socket_addr_init_inet_src will also allocates a #fr_socket_t
232 *
233 * @param[in] ctx to allocate a new #fr_socket_t struct in.
234 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
235 * @param[in] ifindex The interface to originate the packet from Pass <= 0 to
236 * indicate an unknown or unspecified interface.
237 * @param[in] ipaddr The IP address to bind to. May be all zeros to bind to
238 * all addresses, but the AF must still be specified.
239 * @param[in] port The source port to bind to.
240 * @return
241 * - NULL if invalid parameters are provided.
242 * - An initialised fr_socket_t struct.
243 */
244static inline fr_socket_t *fr_socket_addr_alloc_inet_src(TALLOC_CTX *ctx, int proto,
245 int ifindex, fr_ipaddr_t const *ipaddr, int port)
246{
248}
249/** Initialise a #fr_socket_t for connecting to a remote host
250 *
251 * @param[out] addr to initialise.
252 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
253 * @param[in] ipaddr The IP address to bind to. May be all zeros to bind to
254 * all addresses, but the AF must still be specified.
255 * @param[in] port The source port to bind to.
256 * @return
257 * - NULL if invalid parameters are provided.
258 * - An initialised fr_socket_t struct.
259 */
260static inline fr_socket_t *fr_socket_addr_init_inet_dst(fr_socket_t *addr, int proto, fr_ipaddr_t const *ipaddr, int port)
261{
262 if (!fr_socket_proto_is_known(proto)) return NULL;
263
264 *addr = (fr_socket_t){
265 .af = ipaddr->af,
266 .type = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM,
267 .inet = {
268 .dst_ipaddr = *ipaddr,
269 .dst_port = port
270 }
271 };
272
273 return addr;
274}
275
276/** A variant of fr_socket_addr_alloc_inet_dst that will also allocates a #fr_socket_t
277 *
278 * @param[in] ctx to allocate new #fr_socket_t struct in.
279 * @param[in] proto one of the IPPROTO_* macros, i.e. IPPROTO_TCP, IPPROTO_UDP
280 * @param[in] ipaddr The IP address to bind to. May be all zeros to bind to
281 * all addresses, but the AF must still be specified.
282 * @param[in] port The source port to bind to.
283 * @return
284 * - NULL if invalid parameters are provided.
285 * - An initialised fr_socket_t struct.
286 */
287static inline fr_socket_t *fr_socket_addr_alloc_inet_dst(TALLOC_CTX *ctx, int proto,
288 fr_ipaddr_t const *ipaddr, int port)
289{
291}
292
293int fr_socket_client_unix(char const *path, bool async);
294
295int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port,
296 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async);
297
298int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr,
299 fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async);
301
302int fr_socket_server_udp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const *port_name, bool async);
303
304int fr_socket_server_tcp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const *port_name, bool async);
305
306int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port);
307
308#ifdef __cplusplus
309}
310#endif
#define RCSIDH(h, id)
Definition build.h:484
static int sockfd
Definition dhcpclient.c:56
int af
Address family.
Definition inet.h:64
IPv4/6 prefix.
unsigned short uint16_t
static char const * proto(int id, int porttype)
Definition radwho.c:85
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
static fr_socket_t * fr_socket_addr_alloc_inet_src(TALLOC_CTX *ctx, int proto, int ifindex, fr_ipaddr_t const *ipaddr, int port)
A variant of fr_socket_addr_init_inet_src will also allocates a fr_socket_t.
Definition socket.h:244
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:78
int fd
File descriptor if this is a live socket.
Definition socket.h:81
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Definition socket.h:79
static fr_socket_t * fr_socket_addr_init_inet(fr_socket_t *addr, int proto, int ifindex, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port)
Initialise a fr_socket_t for connecting to a remote host using a specific src interface,...
Definition socket.h:151
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
Definition socket.c:634
int fr_socket_server_tcp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const *port_name, bool async)
Open an IPv4/IPv6 TCP socket.
Definition socket.c:969
int fr_socket_server_udp(fr_ipaddr_t const *ipaddr, uint16_t *port, char const *port_name, bool async)
Open an IPv4/IPv6 unconnected UDP socket.
Definition socket.c:867
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition socket.c:729
static fr_socket_t * fr_socket_addr_alloc_inet_dst(TALLOC_CTX *ctx, int proto, fr_ipaddr_t const *ipaddr, int port)
A variant of fr_socket_addr_alloc_inet_dst that will also allocates a fr_socket_t.
Definition socket.h:287
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition socket.c:229
static bool fr_socket_proto_is_known(int proto)
Check the proto value is sane/supported.
Definition socket.h:91
static fr_socket_t * fr_socket_addr_alloc_inet(TALLOC_CTX *ctx, int proto, int ifindex, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port)
Initialise a fr_socket_t for connecting to a remote host using a specific src interface,...
Definition socket.h:191
static fr_socket_t * fr_socket_addr_init_inet_src(fr_socket_t *addr, int proto, int ifindex, fr_ipaddr_t const *ipaddr, int port)
A variant of fr_socket_addr_alloc_inet will also allocates a fr_socket_t.
Definition socket.h:213
int fr_socket_wait_for_connect(int sockfd, fr_time_delta_t timeout)
Wait for a socket to be connected, with an optional timeout.
Definition socket.c:803
#define FR_SOCKET_ADDR_ALLOC_DEF_FUNC(_func,...)
Definition socket.h:110
static fr_socket_t * fr_socket_addr_init_inet_dst(fr_socket_t *addr, int proto, fr_ipaddr_t const *ipaddr, int port)
Initialise a fr_socket_t for connecting to a remote host.
Definition socket.h:260
int fr_socket_client_unix(char const *path, bool async)
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition socket.h:121
Holds information necessary for binding or connecting to a socket.
Definition socket.h:63
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64