1 /**
2 * @file udp.c User Datagram Protocol
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #include <stdlib.h>
7 #ifdef HAVE_UNISTD_H
8 #include <unistd.h>
9 #endif
10 #ifdef HAVE_IO_H
11 #include <io.h>
12 #endif
13 #if !defined(WIN32)
14 #define __USE_POSIX 1 /**< Use POSIX flag */
multicast_update(struct udp_sock * us,const struct sa * group,bool join)15 #define __USE_XOPEN2K 1/**< Use POSIX.1:2001 code */
16 #include <netdb.h>
17 #endif
18 #include <string.h>
19 #ifdef HAVE_STRINGS_H
20 #include <strings.h>
21 #endif
22 #ifdef __APPLE__
23 #include "TargetConditionals.h"
24 #endif
25 #include <re_types.h>
26 #include <re_fmt.h>
27 #include <re_mem.h>
28 #include <re_mbuf.h>
29 #include <re_list.h>
30 #include <re_main.h>
31 #include <re_sa.h>
32 #include <re_net.h>
33 #include <re_udp.h>
34
35
36 #define DEBUG_MODULE "udp"
37 #define DEBUG_LEVEL 5
38 #include <re_dbg.h>
39
40
41 /** Platform independent buffer type cast */
42 #ifdef WIN32
43 #define BUF_CAST (char *)
44 #define SOK_CAST (int)
45 #define SIZ_CAST (int)
46 #define close closesocket
47 #else
48 #define BUF_CAST
49 #define SOK_CAST
50 #define SIZ_CAST
51 #endif
52
53
54 enum {
55 UDP_RXSZ_DEFAULT = 8192
56 };
57
58
59 /** Defines a UDP socket */
60 struct udp_sock {
udp_multicast_join(struct udp_sock * us,const struct sa * group)61 struct list helpers; /**< List of UDP Helpers */
62 udp_recv_h *rh; /**< Receive handler */
63 udp_error_h *eh; /**< Error handler */
64 void *arg; /**< Handler argument */
65 int fd; /**< Socket file descriptor */
66 int fd6; /**< IPv6 socket file descriptor */
udp_multicast_leave(struct udp_sock * us,const struct sa * group)67 bool conn; /**< Connected socket flag */
68 size_t rxsz; /**< Maximum receive chunk size */
69 size_t rx_presz; /**< Preallocated rx buffer size */
70 };
71
72 /** Defines a UDP helper */
73 struct udp_helper {
74 struct le le;
75 int layer;
76 udp_helper_send_h *sendh;
77 udp_helper_recv_h *recvh;
78 void *arg;
79 };
80
81
82 static void dummy_udp_recv_handler(const struct sa *src,
83 struct mbuf *mb, void *arg)
84 {
85 (void)src;
86 (void)mb;
87 (void)arg;
88 }
89
90
91 static bool helper_send_handler(int *err, struct sa *dst,
92 struct mbuf *mb, void *arg)
93 {
94 (void)err;
95 (void)dst;
96 (void)mb;
97 (void)arg;
98 return false;
99 }
100
101
102 static bool helper_recv_handler(struct sa *src,
103 struct mbuf *mb, void *arg)
104 {
105 (void)src;
106 (void)mb;
107 (void)arg;
108 return false;
109 }
110
111
112 static void udp_destructor(void *data)
113 {
114 struct udp_sock *us = data;
115
116 list_flush(&us->helpers);
117
118 if (-1 != us->fd) {
119 fd_close(us->fd);
120 (void)close(us->fd);
121 }
122
123 if (-1 != us->fd6) {
124 fd_close(us->fd6);
125 (void)close(us->fd6);
126 }
127 }
128
129
130 static void udp_read(struct udp_sock *us, int fd)
131 {
132 struct mbuf *mb = mbuf_alloc(us->rxsz);
133 struct sa src;
134 struct le *le;
135 int err = 0;
136 ssize_t n;
137
138 if (!mb)
139 return;
140
141 src.len = sizeof(src.u);
142 n = recvfrom(fd, BUF_CAST mb->buf + us->rx_presz,
143 mb->size - us->rx_presz, 0,
144 &src.u.sa, &src.len);
145 if (n < 0) {
146 err = errno;
147
148 if (EAGAIN == err)
149 goto out;
150
151 #ifdef EWOULDBLOCK
152 if (EWOULDBLOCK == err)
153 goto out;
154 #endif
155
156 #if TARGET_OS_IPHONE
157 if (ENOTCONN == err) {
158
159 struct udp_sock *us_new;
160 struct sa laddr;
161
162 err = udp_local_get(us, &laddr);
163 if (err)
164 goto out;
165
166 if (-1 != us->fd) {
167 fd_close(us->fd);
168 (void)close(us->fd);
169 us->fd = -1;
170 }
171
172 if (-1 != us->fd6) {
173 fd_close(us->fd6);
174 (void)close(us->fd6);
175 us->fd6 = -1;
176 }
177
178 err = udp_listen(&us_new, &laddr, NULL, NULL);
179 if (err)
180 goto out;
181
182 us->fd = us_new->fd;
183 us->fd6 = us_new->fd6;
184
185 us_new->fd = -1;
186 us_new->fd6 = -1;
187
188 mem_deref(us_new);
189
190 udp_thread_attach(us);
191
192 goto out;
193 }
194 #endif
195 if (us->eh)
196 us->eh(err, us->arg);
197
198 goto out;
199 }
200
201 mb->pos = us->rx_presz;
202 mb->end = n + us->rx_presz;
203
204 (void)mbuf_resize(mb, mb->end);
205
206 /* call helpers */
207 le = us->helpers.head;
208 while (le) {
209 struct udp_helper *uh = le->data;
210 bool hdld;
211
212 le = le->next;
213
214 hdld = uh->recvh(&src, mb, uh->arg);
215 if (hdld)
216 goto out;
217 }
218
219 us->rh(&src, mb, us->arg);
220
221 out:
222 mem_deref(mb);
223 }
224
225
226 static void udp_read_handler(int flags, void *arg)
227 {
228 struct udp_sock *us = arg;
229
230 (void)flags;
231
232 udp_read(us, us->fd);
233 }
234
235
236 static void udp_read_handler6(int flags, void *arg)
237 {
238 struct udp_sock *us = arg;
239
240 (void)flags;
241
242 udp_read(us, us->fd6);
243 }
244
245
246 /**
247 * Create and listen on a UDP Socket
248 *
249 * @param usp Pointer to returned UDP Socket
250 * @param local Local network address
251 * @param rh Receive handler
252 * @param arg Handler argument
253 *
254 * @return 0 if success, otherwise errorcode
255 */
256 int udp_listen(struct udp_sock **usp, const struct sa *local,
257 udp_recv_h *rh, void *arg)
258 {
259 struct addrinfo hints, *res = NULL, *r;
260 struct udp_sock *us = NULL;
261 char addr[64];
262 char serv[6] = "0";
263 int af, error, err = 0;
264
265 if (!usp)
266 return EINVAL;
267
268 us = mem_zalloc(sizeof(*us), udp_destructor);
269 if (!us)
270 return ENOMEM;
271
272 list_init(&us->helpers);
273
274 us->fd = -1;
275 us->fd6 = -1;
276
277 if (local) {
278 af = sa_af(local);
279 (void)re_snprintf(addr, sizeof(addr), "%H",
280 sa_print_addr, local);
281 (void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
282 }
283 else {
284 #ifdef HAVE_INET6
285 af = AF_UNSPEC;
286 #else
287 af = AF_INET;
288 #endif
289 }
290
291 memset(&hints, 0, sizeof(hints));
292 /* set-up hints structure */
293 hints.ai_family = af;
294 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
295 hints.ai_socktype = SOCK_DGRAM;
296 hints.ai_protocol = IPPROTO_UDP;
297
298 error = getaddrinfo(local ? addr : NULL, serv, &hints, &res);
299 if (error) {
300 #ifdef WIN32
301 DEBUG_WARNING("listen: getaddrinfo: wsaerr=%d\n",
302 WSAGetLastError());
303 #endif
304 DEBUG_WARNING("listen: getaddrinfo: %s:%s (%s)\n",
305 addr, serv, gai_strerror(error));
306 err = EADDRNOTAVAIL;
307 goto out;
308 }
309
310 for (r = res; r; r = r->ai_next) {
311 int fd = -1;
312
313 if (us->fd > 0)
314 continue;
315
316 DEBUG_INFO("listen: for: af=%d addr=%j\n",
317 r->ai_family, r->ai_addr);
318
319 fd = SOK_CAST socket(r->ai_family, SOCK_DGRAM, IPPROTO_UDP);
320 if (fd < 0) {
321 err = errno;
322 continue;
323 }
324
325 err = net_sockopt_blocking_set(fd, false);
326 if (err) {
327 DEBUG_WARNING("udp listen: nonblock set: %m\n", err);
328 (void)close(fd);
329 continue;
330 }
331
332 if (bind(fd, r->ai_addr, SIZ_CAST r->ai_addrlen) < 0) {
333 err = errno;
334 DEBUG_INFO("listen: bind(): %m (%J)\n", err, local);
335 (void)close(fd);
336 continue;
337 }
338
339 /* Can we do both IPv4 and IPv6 on same socket? */
340 if (AF_INET6 == r->ai_family) {
341 struct sa sa;
342 int on = 1; /* assume v6only */
343
344 #if defined (IPPROTO_IPV6) && defined (IPV6_V6ONLY)
345 socklen_t on_len = sizeof(on);
346 if (0 != getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
347 (char *)&on, &on_len)) {
348 on = 1;
349 }
350 #endif
351 /* Extra check for unspec addr - MAC OS X/Solaris */
352 if (0==sa_set_sa(&sa, r->ai_addr) && sa_is_any(&sa)) {
353 on = 1;
354 }
355 DEBUG_INFO("socket %d: IPV6_V6ONLY is %d\n", fd, on);
356 if (on) {
357 us->fd6 = fd;
358 continue;
359 }
360 }
361
362 /* OK */
363 us->fd = fd;
364 break;
365 }
366
367 freeaddrinfo(res);
368
369 /* We must have at least one socket */
370 if (-1 == us->fd && -1 == us->fd6) {
371 if (0 == err)
372 err = EADDRNOTAVAIL;
373 goto out;
374 }
375
376 err = udp_thread_attach(us);
377 if (err)
378 goto out;
379
380 us->rh = rh ? rh : dummy_udp_recv_handler;
381 us->arg = arg;
382 us->rxsz = UDP_RXSZ_DEFAULT;
383
384 out:
385 if (err)
386 mem_deref(us);
387 else
388 *usp = us;
389
390 return err;
391 }
392
393
394 /**
395 * Connect a UDP Socket to a specific peer.
396 * When connected, this UDP Socket will only receive data from that peer.
397 *
398 * @param us UDP Socket
399 * @param peer Peer network address
400 *
401 * @return 0 if success, otherwise errorcode
402 */
403 int udp_connect(struct udp_sock *us, const struct sa *peer)
404 {
405 int fd;
406
407 if (!us || !peer)
408 return EINVAL;
409
410 /* choose a socket */
411 if (AF_INET6 == sa_af(peer) && -1 != us->fd6)
412 fd = us->fd6;
413 else
414 fd = us->fd;
415
416 if (0 != connect(fd, &peer->u.sa, peer->len))
417 return errno;
418
419 us->conn = true;
420
421 return 0;
422 }
423
424
425 static int udp_send_internal(struct udp_sock *us, const struct sa *dst,
426 struct mbuf *mb, struct le *le)
427 {
428 struct sa hdst;
429 int err = 0, fd;
430
431 /* choose a socket */
432 if (AF_INET6 == sa_af(dst) && -1 != us->fd6)
433 fd = us->fd6;
434 else
435 fd = us->fd;
436
437 /* call helpers in reverse order */
438 while (le) {
439 struct udp_helper *uh = le->data;
440
441 le = le->prev;
442
443 if (dst != &hdst) {
444 sa_cpy(&hdst, dst);
445 dst = &hdst;
446 }
447
448 if (uh->sendh(&err, &hdst, mb, uh->arg) || err)
449 return err;
450 }
451
452 /* Connected socket? */
453 if (us->conn) {
454 if (send(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos,
455 0) < 0)
456 return errno;
457 }
458 else {
459 if (sendto(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos,
460 0, &dst->u.sa, dst->len) < 0)
461 return errno;
462 }
463
464 return 0;
465 }
466
467
468 /**
469 * Send a UDP Datagram to a peer
470 *
471 * @param us UDP Socket
472 * @param dst Destination network address
473 * @param mb Buffer to send
474 *
475 * @return 0 if success, otherwise errorcode
476 */
477 int udp_send(struct udp_sock *us, const struct sa *dst, struct mbuf *mb)
478 {
479 if (!us || !dst || !mb)
480 return EINVAL;
481
482 return udp_send_internal(us, dst, mb, us->helpers.tail);
483 }
484
485
486 /**
487 * Send an anonymous UDP Datagram to a peer
488 *
489 * @param dst Destination network address
490 * @param mb Buffer to send
491 *
492 * @return 0 if success, otherwise errorcode
493 */
494 int udp_send_anon(const struct sa *dst, struct mbuf *mb)
495 {
496 struct udp_sock *us;
497 int err;
498
499 if (!dst || !mb)
500 return EINVAL;
501
502 err = udp_listen(&us, NULL, NULL, NULL);
503 if (err)
504 return err;
505
506 err = udp_send_internal(us, dst, mb, NULL);
507 mem_deref(us);
508
509 return err;
510 }
511
512
513 /**
514 * Get the local network address on the UDP Socket
515 *
516 * @param us UDP Socket
517 * @param local The returned local network address
518 *
519 * @return 0 if success, otherwise errorcode
520 *
521 * @todo bug no way to specify AF
522 */
523 int udp_local_get(const struct udp_sock *us, struct sa *local)
524 {
525 if (!us || !local)
526 return EINVAL;
527
528 local->len = sizeof(local->u);
529
530 if (0 == getsockname(us->fd, &local->u.sa, &local->len))
531 return 0;
532
533 if (0 == getsockname(us->fd6, &local->u.sa, &local->len))
534 return 0;
535
536 return errno;
537 }
538
539
540 /**
541 * Set socket options on the UDP Socket
542 *
543 * @param us UDP Socket
544 * @param level Socket level
545 * @param optname Option name
546 * @param optval Option value
547 * @param optlen Option length
548 *
549 * @return 0 if success, otherwise errorcode
550 */
551 int udp_setsockopt(struct udp_sock *us, int level, int optname,
552 const void *optval, uint32_t optlen)
553 {
554 int err = 0;
555
556 if (!us)
557 return EINVAL;
558
559 if (-1 != us->fd) {
560 if (0 != setsockopt(us->fd, level, optname,
561 BUF_CAST optval, optlen))
562 err |= errno;
563 }
564
565 if (-1 != us->fd6) {
566 if (0 != setsockopt(us->fd6, level, optname,
567 BUF_CAST optval, optlen))
568 err |= errno;
569 }
570
571 return err;
572 }
573
574
575 /**
576 * Set the send/receive buffer size on a UDP Socket
577 *
578 * @param us UDP Socket
579 * @param size Buffer size in bytes
580 *
581 * @return 0 if success, otherwise errorcode
582 */
583 int udp_sockbuf_set(struct udp_sock *us, int size)
584 {
585 int err = 0;
586
587 if (!us)
588 return EINVAL;
589
590 err |= udp_setsockopt(us, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
591 err |= udp_setsockopt(us, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
592
593 return err;
594 }
595
596
597 /**
598 * Set the maximum receive chunk size on a UDP Socket
599 *
600 * @param us UDP Socket
601 * @param rxsz Maximum receive chunk size
602 */
603 void udp_rxsz_set(struct udp_sock *us, size_t rxsz)
604 {
605 if (!us)
606 return;
607
608 us->rxsz = rxsz;
609 }
610
611
612 /**
613 * Set preallocated space on receive buffer.
614 *
615 * @param us UDP Socket
616 * @param rx_presz Size of preallocate space.
617 */
618 void udp_rxbuf_presz_set(struct udp_sock *us, size_t rx_presz)
619 {
620 if (!us)
621 return;
622
623 us->rx_presz = rx_presz;
624 }
625
626
627 /**
628 * Set receive handler on a UDP Socket
629 *
630 * @param us UDP Socket
631 * @param rh Receive handler
632 * @param arg Handler argument
633 */
634 void udp_handler_set(struct udp_sock *us, udp_recv_h *rh, void *arg)
635 {
636 if (!us)
637 return;
638
639 us->rh = rh ? rh : dummy_udp_recv_handler;
640 us->arg = arg;
641 }
642
643
644 /**
645 * Set error handler on a UDP Socket
646 *
647 * @param us UDP Socket
648 * @param eh Error handler
649 */
650 void udp_error_handler_set(struct udp_sock *us, udp_error_h *eh)
651 {
652 if (!us)
653 return;
654
655 us->eh = eh;
656 }
657
658
659 /**
660 * Get the File Descriptor from a UDP Socket
661 *
662 * @param us UDP Socket
663 * @param af Address Family
664 *
665 * @return File Descriptor, or -1 for errors
666 */
667 int udp_sock_fd(const struct udp_sock *us, int af)
668 {
669 if (!us)
670 return -1;
671
672 switch (af) {
673
674 default:
675 case AF_INET: return us->fd;
676 case AF_INET6: return (us->fd6 != -1) ? us->fd6 : us->fd;
677 }
678 }
679
680
681 /**
682 * Attach the current thread to the UDP Socket
683 *
684 * @param us UDP Socket
685 *
686 * @return 0 if success, otherwise errorcode
687 */
688 int udp_thread_attach(struct udp_sock *us)
689 {
690 int err = 0;
691
692 if (!us)
693 return EINVAL;
694
695 if (-1 != us->fd) {
696 err = fd_listen(us->fd, FD_READ, udp_read_handler, us);
697 if (err)
698 goto out;
699 }
700
701 if (-1 != us->fd6) {
702 err = fd_listen(us->fd6, FD_READ, udp_read_handler6, us);
703 if (err)
704 goto out;
705 }
706
707 out:
708 if (err)
709 udp_thread_detach(us);
710
711 return err;
712 }
713
714
715 /**
716 * Detach the current thread from the UDP Socket
717 *
718 * @param us UDP Socket
719 */
720 void udp_thread_detach(struct udp_sock *us)
721 {
722 if (!us)
723 return;
724
725 if (-1 != us->fd)
726 fd_close(us->fd);
727
728 if (-1 != us->fd6)
729 fd_close(us->fd6);
730 }
731
732
733 static void helper_destructor(void *data)
734 {
735 struct udp_helper *uh = data;
736
737 list_unlink(&uh->le);
738 }
739
740
741 static bool sort_handler(struct le *le1, struct le *le2, void *arg)
742 {
743 struct udp_helper *uh1 = le1->data, *uh2 = le2->data;
744 (void)arg;
745
746 return uh1->layer <= uh2->layer;
747 }
748
749
750 /**
751 * Register a UDP protocol stack helper
752 *
753 * @param uhp Pointer to allocated UDP helper object
754 * @param us UDP socket
755 * @param layer Layer number; higher number means higher up in stack
756 * @param sh Send handler
757 * @param rh Receive handler
758 * @param arg Handler argument
759 *
760 * @return 0 if success, otherwise errorcode
761 */
762 int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us,
763 int layer,
764 udp_helper_send_h *sh, udp_helper_recv_h *rh,
765 void *arg)
766 {
767 struct udp_helper *uh;
768
769 if (!us)
770 return EINVAL;
771
772 uh = mem_zalloc(sizeof(*uh), helper_destructor);
773 if (!uh)
774 return ENOMEM;
775
776 list_append(&us->helpers, &uh->le, uh);
777
778 uh->layer = layer;
779 uh->sendh = sh ? sh : helper_send_handler;
780 uh->recvh = rh ? rh : helper_recv_handler;
781 uh->arg = arg;
782
783 list_sort(&us->helpers, sort_handler, NULL);
784
785 if (uhp)
786 *uhp = uh;
787
788 return 0;
789 }
790
791
792 /**
793 * Send a UDP Datagram to a remote peer bypassing this helper and
794 * the helpers above it.
795 *
796 * @param us UDP Socket
797 * @param dst Destination network address
798 * @param mb Buffer to send
799 * @param uh UDP Helper
800 *
801 * @return 0 if success, otherwise errorcode
802 */
803 int udp_send_helper(struct udp_sock *us, const struct sa *dst,
804 struct mbuf *mb, struct udp_helper *uh)
805 {
806 if (!us || !dst || !mb || !uh)
807 return EINVAL;
808
809 return udp_send_internal(us, dst, mb, uh->le.prev);
810 }
811
812
813 /**
814 * Find a UDP-helper on a UDP socket
815 *
816 * @param us UDP socket
817 * @param layer Layer number
818 *
819 * @return UDP-helper if found, NULL if not found
820 */
821 struct udp_helper *udp_helper_find(const struct udp_sock *us, int layer)
822 {
823 struct le *le;
824
825 if (!us)
826 return NULL;
827
828 for (le = us->helpers.head; le; le = le->next) {
829
830 struct udp_helper *uh = le->data;
831
832 if (layer == uh->layer)
833 return uh;
834 }
835
836 return NULL;
837 }
838