The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
udpfromto.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** API for sending and receiving packets on unconnected UDP sockets
18 *
19 * Like recvfrom, but also stores the destination IP address. Useful on multihomed hosts.
20 *
21 * @file src/lib/util/udpfromto.c
22 *
23 * @copyright 2007 Alan DeKok (aland@deployingradius.com)
24 * @copyright 2002 Miquel van Smoorenburg
25 */
26RCSID("$Id: 5a8e92fb8fb6a3855f0d1dc30d321799b92ea81e $")
27
28#include <freeradius-devel/util/udpfromto.h>
29
30#ifdef HAVE_SYS_UIO_H
31# include <sys/uio.h>
32#endif
33
34#include <fcntl.h>
35
36/*
37 * More portability idiocy
38 * Mac OSX Lion doesn't define SOL_IP. But IPPROTO_IP works.
39 */
40#ifndef SOL_IP
41# define SOL_IP IPPROTO_IP
42#endif
43
44/*
45 * glibc 2.4 and uClibc 0.9.29 introduce IPV6_RECVPKTINFO etc. and
46 * change IPV6_PKTINFO This is only supported in Linux kernel >=
47 * 2.6.14
48 *
49 * This is only an approximation because the kernel version that libc
50 * was compiled against could be older or newer than the one being
51 * run. But this should not be a problem -- we just keep using the
52 * old kernel interface.
53 */
54#ifdef __linux__
55# ifdef IPV6_RECVPKTINFO
56# include <linux/version.h>
57# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
58# ifdef IPV6_2292PKTINFO
59# undef IPV6_RECVPKTINFO
60# undef IPV6_PKTINFO
61# define IPV6_RECVPKTINFO IPV6_2292PKTINFO
62# define IPV6_PKTINFO IPV6_2292PKTINFO
63# endif
64# endif
65/* Fall back to the legacy socket option if IPV6_RECVPKTINFO isn't defined */
66# elif defined(IPV6_2292PKTINFO)
67# define IPV6_RECVPKTINFO IPV6_2292PKTINFO
68# endif
69#else
70
71/*
72 * For everything that's not Linux we assume RFC 3542 compliance
73 * - setsockopt() takes IPV6_RECVPKTINFO
74 * - cmsg_type is IPV6_PKTINFO (in sendmsg, recvmsg)
75 *
76 * If we don't have IPV6_RECVPKTINFO defined but do have IPV6_PKTINFO
77 * defined, chances are the API is RFC2292 compliant and we need to use
78 * IPV6_PKTINFO for both.
79 */
80# if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
81# define IPV6_RECVPKTINFO IPV6_PKTINFO
82
83/*
84 * Ensure IPV6_RECVPKTINFO is not defined somehow if we have we
85 * don't have IPV6_PKTINFO.
86 */
87# elif !defined(IPV6_PKTINFO)
88# undef IPV6_RECVPKTINFO
89# endif
90#endif
91
92int udpfromto_init(int s, int af)
93{
94 int proto = 0, flag = 0, opt = 1;
95
96 errno = ENOSYS;
97
98 if (af == AF_UNSPEC) {
99 struct sockaddr_storage si;
100 socklen_t si_len = sizeof(si);
101
102 /*
103 * Static analyzer doesn't see that getsockname initialises
104 * the memory passed to it.
105 */
106#ifdef STATIC_ANALYZER
107 memset(&si, 0, sizeof(si));
108#endif
109
110 if (getsockname(s, (struct sockaddr *) &si, &si_len) < 0) {
111 return -1;
112 }
113
114 af = si.ss_family;
115 }
116
117 if (af == AF_INET) {
118#ifdef HAVE_IP_PKTINFO
119 /*
120 * Linux
121 */
122 proto = SOL_IP;
123 flag = IP_PKTINFO;
124#else
125# ifdef IP_RECVDSTADDR
126
127 /*
128 * Set the IP_RECVDSTADDR option (BSD). Note:
129 * IP_RECVDSTADDR == IP_SENDSRCADDR
130 */
131 proto = IPPROTO_IP;
132 flag = IP_RECVDSTADDR;
133# else
134 return -1;
135# endif
136#endif
137
138#if defined(AF_INET6) && defined(IPV6_PKTINFO)
139 } else if (af == AF_INET6) {
140 /*
141 * This should actually be standard IPv6
142 */
143 proto = IPPROTO_IPV6;
144
145 /*
146 * Work around Linux-specific hackery.
147 */
148 flag = IPV6_RECVPKTINFO;
149 } else {
150#endif
151
152 /*
153 * Unknown AF. Return an error if possible.
154 */
155# ifdef EPROTONOSUPPORT
156 errno = EPROTONOSUPPORT;
157# endif
158 return -1;
159 }
160
161 return setsockopt(s, proto, flag, &opt, sizeof(opt));
162}
163
164/** Read a packet from a file descriptor, retrieving additional header information
165 *
166 * Abstracts away the complexity of using the complexity of using recvmsg().
167 *
168 * In addition to reading data from the file descriptor, the src and dst addresses
169 * and the receiving interface index are retrieved. This enables us to send
170 * replies using the correct IP interface, in the case where the server is multihomed.
171 * This is not normally possible on unconnected datagram sockets.
172 *
173 * @param[in] fd The file descriptor to read from.
174 * @param[out] buf Where to write the received datagram data.
175 * @param[in] len of buf.
176 * @param[in] flags passed unmolested to recvmsg.
177 * @param[out] ifindex The interface which received the datagram (may be NULL).
178 * Will only be populated if to is not NULL.
179 * @param[out] from Where to write the source address.
180 * @param[in] from_len Length of the structure pointed to by from.
181 * @param[out] to Where to write the destination address. If NULL recvmsg()
182 * will be used instead.
183 * @param[in] to_len Length of the structure pointed to by to.
184 * @param[out] when the packet was received (may be NULL). If SO_TIMESTAMP is
185 * not available or SO_TIMESTAMP Was not set on the socket,
186 * then another method will be used instead to get the time.
187 * @return
188 * - 0 on success.
189 * - -1 on failure.
190 */
191int recvfromto(int fd, void *buf, size_t len, int flags,
192 int *ifindex,
193 struct sockaddr *from, socklen_t *from_len,
194 struct sockaddr *to, socklen_t *to_len,
195 fr_time_t *when)
196{
197 struct msghdr msgh;
198 struct cmsghdr *cmsg;
199 struct iovec iov;
200 char cbuf[256];
201 int ret;
202 struct sockaddr_storage si;
203 socklen_t si_len = sizeof(si);
204
205#if !defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR) && !defined(IPV6_PKTINFO)
206 /*
207 * If the recvmsg() flags aren't defined, fall back to
208 * using recvfrom().
209 */
210 to = NULL:
211#endif
212
213 /*
214 * Catch the case where the caller passes invalid arguments.
215 */
216 if (!to || !to_len) {
217 if (when) *when = fr_time();
218 return recvfrom(fd, buf, len, flags, from, from_len);
219 }
220
221 /*
222 * Static analyzer doesn't see that getsockname initialises
223 * the memory passed to it.
224 */
225#ifdef STATIC_ANALYZER
226 memset(&si, 0, sizeof(si));
227#endif
228
229 /*
230 * recvmsg doesn't provide sin_port so we have to
231 * retrieve it using getsockname().
232 */
233 if (getsockname(fd, (struct sockaddr *)&si, &si_len) < 0) {
234 return -1;
235 }
236
237 /*
238 * Initialize the 'to' address. It may be INADDR_ANY here,
239 * with a more specific address given by recvmsg(), below.
240 */
241 if (si.ss_family == AF_INET) {
242#if !defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR)
243 return recvfrom(fd, buf, len, flags, from, from_len);
244#else
245 struct sockaddr_in *dst = (struct sockaddr_in *) to;
246 struct sockaddr_in *src = (struct sockaddr_in *) &si; //-V641
247
248 if (*to_len < sizeof(*dst)) {
249 errno = EINVAL;
250 return -1;
251 }
252 *to_len = sizeof(*dst);
253 *dst = *src;
254#endif
255 }
256
257#ifdef AF_INET6
258 else if (si.ss_family == AF_INET6) {
259#if !defined(IPV6_PKTINFO)
260 return recvfrom(fd, buf, len, flags, from, from_len);
261#else
262 struct sockaddr_in6 *dst = (struct sockaddr_in6 *) to;
263 struct sockaddr_in6 *src = (struct sockaddr_in6 *) &si; //-V641
264
265 if (*to_len < sizeof(*dst)) {
266 errno = EINVAL;
267 return -1;
268 }
269 *to_len = sizeof(*dst);
270 *dst = *src;
271#endif
272 }
273#endif
274 /*
275 * Unknown address family.
276 */
277 else {
278 errno = EINVAL;
279 return -1;
280 }
281
282 /* Set up iov and msgh structures. */
283 memset(&cbuf, 0, sizeof(cbuf));
284 memset(&msgh, 0, sizeof(struct msghdr));
285 iov.iov_base = buf;
286 iov.iov_len = len;
287 msgh.msg_control = cbuf;
288 msgh.msg_controllen = sizeof(cbuf);
289 msgh.msg_name = from;
290 msgh.msg_namelen = from_len ? *from_len : 0;
291 msgh.msg_iov = &iov;
292 msgh.msg_iovlen = 1;
293 msgh.msg_flags = 0;
294
295 /* Receive one packet. */
296 ret = recvmsg(fd, &msgh, flags);
297 if (ret < 0) return ret;
298
299 if (from_len) *from_len = msgh.msg_namelen;
300
301 if (ifindex) *ifindex = 0;
302 if (when) *when = fr_time_wrap(0);
303
304/*
305 * Needed for emscripten, seems to be an issue in CMSG_NXTHDR
306 */
307DIAG_OFF(sign-compare)
308 /* Process auxiliary received data in msgh */
309 for (cmsg = CMSG_FIRSTHDR(&msgh);
310 cmsg != NULL;
311 cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
312DIAG_ON(sign-compare)
313
314#ifdef IP_PKTINFO
315 if ((cmsg->cmsg_level == SOL_IP) &&
316 (cmsg->cmsg_type == IP_PKTINFO)) {
317 struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
318
319 ((struct sockaddr_in *)to)->sin_addr = i->ipi_addr;
320 *to_len = sizeof(struct sockaddr_in);
321
322 if (ifindex) *ifindex = i->ipi_ifindex;
323
324 break;
325 }
326#endif
327
328#ifdef IP_RECVDSTADDR
329 if ((cmsg->cmsg_level == IPPROTO_IP) &&
330 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
331 struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
332
333 ((struct sockaddr_in *)to)->sin_addr = *i;
334
335 *to_len = sizeof(struct sockaddr_in);
336
337 break;
338 }
339#endif
340
341#ifdef IPV6_PKTINFO
342 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
343 (cmsg->cmsg_type == IPV6_PKTINFO)) {
344 struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg);
345
346 ((struct sockaddr_in6 *)to)->sin6_addr = i->ipi6_addr;
347 *to_len = sizeof(struct sockaddr_in6);
348
349 if (ifindex) *ifindex = i->ipi6_ifindex;
350
351 break;
352 }
353#endif
354
355#ifdef SO_TIMESTAMP
356 if (when && (cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
357 *when = fr_time_from_timeval((struct timeval *)CMSG_DATA(cmsg));
358 }
359#endif
360
361#ifdef SO_TIMESTAMPNS
362 if (when && (cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
363 *when = fr_time_from_timespec((struct timespec *)CMSG_DATA(cmsg));
364 }
365#endif
366 }
367
368 if (when && fr_time_eq(*when, fr_time_wrap(0))) *when = fr_time();
369
370 return ret;
371}
372
373/** Send packet via a file descriptor, setting the src address and outbound interface
374 *
375 * Abstracts away the complexity of using the complexity of using sendmsg().
376 *
377 * @param[in] fd The file descriptor to write to.
378 * @param[in] buf Where to read datagram data from.
379 * @param[in] len of datagram data.
380 * @param[in] flags passed unmolested to sendmsg.
381 * @param[in] ifindex The interface on which to send the datagram.
382 * If automatic interface selection is desired, value should be 0.
383 * @param[in] from The source address.
384 * @param[in] from_len Length of the structure pointed to by from.
385 * @param[in] to The destination address.
386 * @param[in] to_len Length of the structure pointed to by to.
387 * @return
388 * - 0 on success.
389 * - -1 on failure.
390 */
391int sendfromto(int fd, void *buf, size_t len, int flags,
392 int ifindex,
393 struct sockaddr *from, socklen_t from_len,
394 struct sockaddr *to, socklen_t to_len)
395{
396 struct msghdr msgh;
397 struct iovec iov;
398 char cbuf[256];
399
400 /*
401 * Unknown address family, die.
402 */
403 if (from && (from->sa_family != AF_INET) && (from->sa_family != AF_INET6)) {
404 errno = EINVAL;
405 return -1;
406 }
407
408#ifdef __FreeBSD__
409 /*
410 * FreeBSD is extra pedantic about the use of IP_SENDSRCADDR,
411 * and sendmsg will fail with EINVAL if IP_SENDSRCADDR is used
412 * with a socket which is bound to something other than
413 * INADDR_ANY
414 */
415 {
416 struct sockaddr bound;
417 socklen_t bound_len = sizeof(bound);
418
419 if (getsockname(fd, &bound, &bound_len) < 0) {
420 return -1;
421 }
422
423 switch (bound.sa_family) {
424 case AF_INET:
425 if (((struct sockaddr_in *) &bound)->sin_addr.s_addr != INADDR_ANY) {
426 from = NULL;
427 }
428 break;
429
430 case AF_INET6:
431 if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) &bound)->sin6_addr)) {
432 from = NULL;
433 }
434 break;
435 }
436 }
437#endif /* !__FreeBSD__ */
438
439 /*
440 * If the sendmsg() flags aren't defined, fall back to
441 * using sendto(). These flags are defined on FreeBSD,
442 * but laying it out this way simplifies the look of the
443 * code.
444 */
445# if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR)
446 if (from && from->sa_family == AF_INET) from = NULL;
447# endif
448
449# if !defined(IPV6_PKTINFO)
450 if (from && from->sa_family == AF_INET6) from = NULL;
451# endif
452
453 /*
454 * No "from" or "from" is 0.0.0.0 or ::/0, and there's no
455 * interface binding, just use regular sendto.
456 */
457 if (!from || (from_len == 0) ||
458 ((ifindex == 0) &&
459 ((from->sa_family == AF_INET &&
460 (((struct sockaddr_in *) from)->sin_addr.s_addr == INADDR_ANY)) ||
461 (from->sa_family == AF_INET6 &&
462 IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) from)->sin6_addr))))) {
463 return sendto(fd, buf, len, flags, to, to_len);
464 }
465
466 /* Set up control buffer iov and msgh structures. */
467 memset(&cbuf, 0, sizeof(cbuf));
468 memset(&msgh, 0, sizeof(msgh));
469 memset(&iov, 0, sizeof(iov));
470 iov.iov_base = buf;
471 iov.iov_len = len;
472
473 msgh.msg_iov = &iov;
474 msgh.msg_iovlen = 1;
475 msgh.msg_name = to;
476 msgh.msg_namelen = to_len;
477
478# if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
479 if (from->sa_family == AF_INET) {
480 struct sockaddr_in *s4 = (struct sockaddr_in *) from;
481
482# ifdef IP_PKTINFO
483 struct cmsghdr *cmsg;
484 struct in_pktinfo *pkt;
485
486 msgh.msg_control = cbuf;
487 msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
488
489 cmsg = CMSG_FIRSTHDR(&msgh);
490 cmsg->cmsg_level = SOL_IP;
491 cmsg->cmsg_type = IP_PKTINFO;
492 cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
493
494 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
495 memset(pkt, 0, sizeof(*pkt));
496 pkt->ipi_spec_dst = s4->sin_addr;
497 pkt->ipi_ifindex = ifindex;
498
499# elif defined(IP_SENDSRCADDR)
500 struct cmsghdr *cmsg;
501 struct in_addr *in;
502
503 msgh.msg_control = cbuf;
504 msgh.msg_controllen = CMSG_SPACE(sizeof(*in));
505
506 cmsg = CMSG_FIRSTHDR(&msgh);
507 cmsg->cmsg_level = IPPROTO_IP;
508 cmsg->cmsg_type = IP_SENDSRCADDR;
509 cmsg->cmsg_len = CMSG_LEN(sizeof(*in));
510
511 in = (struct in_addr *) CMSG_DATA(cmsg);
512 *in = s4->sin_addr;
513# endif
514 }
515#endif
516
517# if defined(IPV6_PKTINFO)
518 if (from->sa_family == AF_INET6) {
519 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) from;
520
521 struct cmsghdr *cmsg;
522 struct in6_pktinfo *pkt;
523
524 msgh.msg_control = cbuf;
525 msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
526
527 cmsg = CMSG_FIRSTHDR(&msgh);
528 cmsg->cmsg_level = IPPROTO_IPV6;
529 cmsg->cmsg_type = IPV6_PKTINFO;
530 cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
531
532 pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
533 memset(pkt, 0, sizeof(*pkt));
534 pkt->ipi6_addr = s6->sin6_addr;
535 pkt->ipi6_ifindex = ifindex;
536 }
537# endif /* IPV6_PKTINFO */
538
539 return sendmsg(fd, &msgh, flags);
540}
541
542
543#ifdef TESTING
544/*
545 * Small test program to test recvfromto/sendfromto
546 *
547 * use a virtual IP address as first argument to test
548 *
549 * reply packet should originate from virtual IP and not
550 * from the default interface the alias is bound to
551 */
552# include <sys/wait.h>
553
554# define DEF_PORT 20000 /* default port to listen on */
555# define DESTIP "127.0.0.1" /* send packet to localhost per default */
556# define TESTSTRING "foo" /* what to send */
557# define TESTLEN 4 /* 4 bytes */
558
559int main(int argc, char **argv)
560{
561 struct sockaddr_in from, to, in;
562 char buf[TESTLEN];
563 char *destip = DESTIP;
564 uint16_t port = DEF_PORT;
565 int n, server_socket, client_socket, fl, tl, pid;
566 int ifindex;
567 fr_time_t when;
568
569 if (argc > 1) destip = argv[1];
570 if (argc > 2) port = atoi(argv[2]);
571
572 in.sin_family = AF_INET;
573 in.sin_addr.s_addr = INADDR_ANY;
574 in.sin_port = htons(port);
575 fl = tl = sizeof(struct sockaddr_in);
576 memset(&from, 0, sizeof(from));
577 memset(&to, 0, sizeof(to));
578
579 switch (pid = fork()) {
580 case -1:
581 perror("fork");
582 return 0;
583 case 0:
584 /* child */
585 usleep(100000);
586 goto client;
587 }
588
589 /* parent: server */
590 server_socket = socket(PF_INET, SOCK_DGRAM, 0);
591 if (udpfromto_init(server_socket, AF_INET) != 0) {
592 perror("udpfromto_init\n");
593 waitpid(pid, NULL, WNOHANG);
594 return 0;
595 }
596
597 if (bind(server_socket, (struct sockaddr *)&in, sizeof(in)) < 0) {
598 perror("server: bind");
599 waitpid(pid, NULL, WNOHANG);
600 return 0;
601 }
602
603 printf("server: waiting for packets on INADDR_ANY:%d\n", port);
604 if ((n = recvfromto(server_socket, buf, sizeof(buf), 0,
605 (struct sockaddr *)&from, &fl,
606 (struct sockaddr *)&to, &tl, &ifindex, &when)) < 0) {
607 perror("server: recvfromto");
608 waitpid(pid, NULL, WNOHANG);
609 return 0;
610 }
611
612 printf("server: received a packet of %d bytes [%s] ", n, buf);
613 printf("(src ip:port %s:%d ",
614 inet_ntoa(from.sin_addr), ntohs(from.sin_port));
615 printf(" dst ip:port %s:%d) via if %i\n",
616 inet_ntoa(to.sin_addr), ntohs(to.sin_port), ifindex);
617
618 printf("server: replying from address packet was received on to source address\n");
619
620 if ((n = sendfromto(server_socket, buf, n, 0,
621 0,
622 (struct sockaddr *)&to, tl,
623 (struct sockaddr *)&from, fl)) < 0) {
624 perror("server: sendfromto");
625 }
626
627 waitpid(pid, NULL, 0);
628 return 0;
629
630client:
631 close(server_socket);
632 client_socket = socket(PF_INET, SOCK_DGRAM, 0);
633 fr_assert_fatal_msg(udpfromto_init(client_socket, AF_INET) != 0, "udpfromto_init - %s", fr_syserror(errno));
634
635 /* bind client on different port */
636 in.sin_port = htons(port+1);
637 fr_assert_fatal_msg(bind(client_socket, (struct sockaddr *)&in, sizeof(in)) < 0,
638 "client: bind - %s", fr_syserror(errno));
639
640 in.sin_port = htons(port);
641 in.sin_addr.s_addr = inet_addr(destip);
642
643 printf("client: sending packet to %s:%d\n", destip, port);
644 fr_assert_fatal_msg(sendto(client_socket, TESTSTRING, TESTLEN, 0, (struct sockaddr *)&in, sizeof(in)) < 0,
645 "client: sendto");
646
647 printf("client: waiting for reply from server on INADDR_ANY:%d\n", port+1);
648
649 fr_assert_fatal_msg((n = recvfromto(client_socket, buf, sizeof(buf), 0,
650 (struct sockaddr *)&from, &fl,
651 (struct sockaddr *)&to, &tl, &ifindex, NULL)) < 0,
652 "client: recvfromto - %s", fr_syserror(errno));
653
654 printf("client: received a packet of %d bytes [%s] ", n, buf);
655 printf("(src ip:port %s:%d",
656 inet_ntoa(from.sin_addr), ntohs(from.sin_port));
657 printf(" dst ip:port %s:%d) via if %i\n",
658 inet_ntoa(to.sin_addr), ntohs(to.sin_port), ifindex);
659
660 return EXIT_SUCCESS;
661}
662
663#endif /* TESTING */
int n
Definition acutest.h:577
#define RCSID(id)
Definition build.h:483
#define DIAG_ON(_x)
Definition build.h:458
#define DIAG_OFF(_x)
Definition build.h:457
int main(int argc, char **argv)
Definition dhcpclient.c:524
static fr_slen_t in
Definition dict.h:824
waitpid(reap->pid_ev->pid, &status, 0)
static int client_socket(char const *server)
Definition radmin.c:182
unsigned short uint16_t
static char const * proto(int id, int porttype)
Definition radwho.c:85
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
Definition time.h:896
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_eq(_a, _b)
Definition time.h:241
static fr_time_t fr_time_from_timespec(struct timespec const *when_ts)
Convert a timespec (wallclock time) to a fr_time_t (internal time)
Definition time.h:878
"server local" time.
Definition time.h:69
close(uq->fd)
int sendfromto(int fd, void *buf, size_t len, int flags, int ifindex, struct sockaddr *from, socklen_t from_len, struct sockaddr *to, socklen_t to_len)
Send packet via a file descriptor, setting the src address and outbound interface.
Definition udpfromto.c:391
#define SOL_IP
Definition udpfromto.c:41
int udpfromto_init(int s, int af)
Definition udpfromto.c:92
int recvfromto(int fd, void *buf, size_t len, int flags, int *ifindex, struct sockaddr *from, socklen_t *from_len, struct sockaddr *to, socklen_t *to_len, fr_time_t *when)
Read a packet from a file descriptor, retrieving additional header information.
Definition udpfromto.c:191