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