1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "internal.h"
24 
25 #include <assert.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #if defined(__MVS__)
31 #include <xti.h>
32 #endif
33 #include <sys/un.h>
34 
35 #define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
36 
37 #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
38 # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
39 #endif
40 
41 #if defined(IPV6_LEAVE_GROUP) && !defined(IPV6_DROP_MEMBERSHIP)
42 # define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
43 #endif
44 
45 union uv__sockaddr {
46   struct sockaddr_in6 in6;
47   struct sockaddr_in in;
48   struct sockaddr addr;
49 };
50 
51 static void uv__udp_run_completed(uv_udp_t* handle);
52 static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
53 static void uv__udp_recvmsg(uv_udp_t* handle);
54 static void uv__udp_sendmsg(uv_udp_t* handle);
55 static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
56                                        int domain,
57                                        unsigned int flags);
58 
59 #if HAVE_MMSG
60 
61 #define UV__MMSG_MAXWIDTH 20
62 
63 static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf);
64 static void uv__udp_sendmmsg(uv_udp_t* handle);
65 
66 static int uv__recvmmsg_avail;
67 static int uv__sendmmsg_avail;
68 static uv_once_t once = UV_ONCE_INIT;
69 
uv__udp_mmsg_init(void)70 static void uv__udp_mmsg_init(void) {
71   int ret;
72   int s;
73   s = uv__socket(AF_INET, SOCK_DGRAM, 0);
74   if (s < 0)
75     return;
76   ret = uv__sendmmsg(s, NULL, 0);
77   if (ret == 0 || errno != ENOSYS) {
78     uv__sendmmsg_avail = 1;
79     uv__recvmmsg_avail = 1;
80   } else {
81     ret = uv__recvmmsg(s, NULL, 0);
82     if (ret == 0 || errno != ENOSYS)
83       uv__recvmmsg_avail = 1;
84   }
85   uv__close(s);
86 }
87 
88 #endif
89 
uv__udp_close(uv_udp_t * handle)90 void uv__udp_close(uv_udp_t* handle) {
91   uv__io_close(handle->loop, &handle->io_watcher);
92   uv__handle_stop(handle);
93 
94   if (handle->io_watcher.fd != -1) {
95     uv__close(handle->io_watcher.fd);
96     handle->io_watcher.fd = -1;
97   }
98 }
99 
100 
uv__udp_finish_close(uv_udp_t * handle)101 void uv__udp_finish_close(uv_udp_t* handle) {
102   uv_udp_send_t* req;
103   QUEUE* q;
104 
105   assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
106   assert(handle->io_watcher.fd == -1);
107 
108   while (!QUEUE_EMPTY(&handle->write_queue)) {
109     q = QUEUE_HEAD(&handle->write_queue);
110     QUEUE_REMOVE(q);
111 
112     req = QUEUE_DATA(q, uv_udp_send_t, queue);
113     req->status = UV_ECANCELED;
114     QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
115   }
116 
117   uv__udp_run_completed(handle);
118 
119   assert(handle->send_queue_size == 0);
120   assert(handle->send_queue_count == 0);
121 
122   /* Now tear down the handle. */
123   handle->recv_cb = NULL;
124   handle->alloc_cb = NULL;
125   /* but _do not_ touch close_cb */
126 }
127 
128 
uv__udp_run_completed(uv_udp_t * handle)129 static void uv__udp_run_completed(uv_udp_t* handle) {
130   uv_udp_send_t* req;
131   QUEUE* q;
132 
133   assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING));
134   handle->flags |= UV_HANDLE_UDP_PROCESSING;
135 
136   while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
137     q = QUEUE_HEAD(&handle->write_completed_queue);
138     QUEUE_REMOVE(q);
139 
140     req = QUEUE_DATA(q, uv_udp_send_t, queue);
141     uv__req_unregister(handle->loop, req);
142 
143     handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs);
144     handle->send_queue_count--;
145 
146     if (req->bufs != req->bufsml)
147       uv__free(req->bufs);
148     req->bufs = NULL;
149 
150     if (req->send_cb == NULL)
151       continue;
152 
153     /* req->status >= 0 == bytes written
154      * req->status <  0 == errno
155      */
156     if (req->status >= 0)
157       req->send_cb(req, 0);
158     else
159       req->send_cb(req, req->status);
160   }
161 
162   if (QUEUE_EMPTY(&handle->write_queue)) {
163     /* Pending queue and completion queue empty, stop watcher. */
164     uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT);
165     if (!uv__io_active(&handle->io_watcher, POLLIN))
166       uv__handle_stop(handle);
167   }
168 
169   handle->flags &= ~UV_HANDLE_UDP_PROCESSING;
170 }
171 
172 
uv__udp_io(uv_loop_t * loop,uv__io_t * w,unsigned int revents)173 static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
174   uv_udp_t* handle;
175 
176   handle = container_of(w, uv_udp_t, io_watcher);
177   assert(handle->type == UV_UDP);
178 
179   if (revents & POLLIN)
180     uv__udp_recvmsg(handle);
181 
182   if (revents & POLLOUT) {
183     uv__udp_sendmsg(handle);
184     uv__udp_run_completed(handle);
185   }
186 }
187 
188 #if HAVE_MMSG
uv__udp_recvmmsg(uv_udp_t * handle,uv_buf_t * buf)189 static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
190   struct sockaddr_in6 peers[UV__MMSG_MAXWIDTH];
191   struct iovec iov[UV__MMSG_MAXWIDTH];
192   struct uv__mmsghdr msgs[UV__MMSG_MAXWIDTH];
193   ssize_t nread;
194   uv_buf_t chunk_buf;
195   size_t chunks;
196   int flags;
197   size_t k;
198 
199   /* prepare structures for recvmmsg */
200   chunks = buf->len / UV__UDP_DGRAM_MAXSIZE;
201   if (chunks > ARRAY_SIZE(iov))
202     chunks = ARRAY_SIZE(iov);
203   for (k = 0; k < chunks; ++k) {
204     iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE;
205     iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE;
206     msgs[k].msg_hdr.msg_iov = iov + k;
207     msgs[k].msg_hdr.msg_iovlen = 1;
208     msgs[k].msg_hdr.msg_name = peers + k;
209     msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]);
210     msgs[k].msg_hdr.msg_control = NULL;
211     msgs[k].msg_hdr.msg_controllen = 0;
212     msgs[k].msg_hdr.msg_flags = 0;
213   }
214 
215   do
216     nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks);
217   while (nread == -1 && errno == EINTR);
218 
219   if (nread < 1) {
220     if (nread == 0 || errno == EAGAIN || errno == EWOULDBLOCK)
221       handle->recv_cb(handle, 0, buf, NULL, 0);
222     else
223       handle->recv_cb(handle, UV__ERR(errno), buf, NULL, 0);
224   } else {
225     /* pass each chunk to the application */
226     for (k = 0; k < (size_t) nread && handle->recv_cb != NULL; k++) {
227       flags = UV_UDP_MMSG_CHUNK;
228       if (msgs[k].msg_hdr.msg_flags & MSG_TRUNC)
229         flags |= UV_UDP_PARTIAL;
230 
231       chunk_buf = uv_buf_init(iov[k].iov_base, iov[k].iov_len);
232       handle->recv_cb(handle,
233                       msgs[k].msg_len,
234                       &chunk_buf,
235                       msgs[k].msg_hdr.msg_name,
236                       flags);
237     }
238 
239     /* one last callback so the original buffer is freed */
240     if (handle->recv_cb != NULL)
241       handle->recv_cb(handle, 0, buf, NULL, UV_UDP_MMSG_FREE);
242   }
243   return nread;
244 }
245 #endif
246 
uv__udp_recvmsg(uv_udp_t * handle)247 static void uv__udp_recvmsg(uv_udp_t* handle) {
248   struct sockaddr_storage peer;
249   struct msghdr h;
250   ssize_t nread;
251   uv_buf_t buf;
252   int flags;
253   int count;
254 
255   assert(handle->recv_cb != NULL);
256   assert(handle->alloc_cb != NULL);
257 
258   /* Prevent loop starvation when the data comes in as fast as (or faster than)
259    * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
260    */
261   count = 32;
262 
263   do {
264     buf = uv_buf_init(NULL, 0);
265     handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
266     if (buf.base == NULL || buf.len == 0) {
267       handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
268       return;
269     }
270     assert(buf.base != NULL);
271 
272 #if HAVE_MMSG
273     if (uv_udp_using_recvmmsg(handle)) {
274       nread = uv__udp_recvmmsg(handle, &buf);
275       if (nread > 0)
276         count -= nread;
277       continue;
278     }
279 #endif
280 
281     memset(&h, 0, sizeof(h));
282     memset(&peer, 0, sizeof(peer));
283     h.msg_name = &peer;
284     h.msg_namelen = sizeof(peer);
285     h.msg_iov = (void*) &buf;
286     h.msg_iovlen = 1;
287 
288     do {
289       nread = recvmsg(handle->io_watcher.fd, &h, 0);
290     }
291     while (nread == -1 && errno == EINTR);
292 
293     if (nread == -1) {
294       if (errno == EAGAIN || errno == EWOULDBLOCK)
295         handle->recv_cb(handle, 0, &buf, NULL, 0);
296       else
297         handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
298     }
299     else {
300       flags = 0;
301       if (h.msg_flags & MSG_TRUNC)
302         flags |= UV_UDP_PARTIAL;
303 
304       handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags);
305     }
306     count--;
307   }
308   /* recv_cb callback may decide to pause or close the handle */
309   while (nread != -1
310       && count > 0
311       && handle->io_watcher.fd != -1
312       && handle->recv_cb != NULL);
313 }
314 
315 #if HAVE_MMSG
uv__udp_sendmmsg(uv_udp_t * handle)316 static void uv__udp_sendmmsg(uv_udp_t* handle) {
317   uv_udp_send_t* req;
318   struct uv__mmsghdr h[UV__MMSG_MAXWIDTH];
319   struct uv__mmsghdr *p;
320   QUEUE* q;
321   ssize_t npkts;
322   size_t pkts;
323   size_t i;
324 
325   if (QUEUE_EMPTY(&handle->write_queue))
326     return;
327 
328 write_queue_drain:
329   for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue);
330        pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue;
331        ++pkts, q = QUEUE_HEAD(q)) {
332     assert(q != NULL);
333     req = QUEUE_DATA(q, uv_udp_send_t, queue);
334     assert(req != NULL);
335 
336     p = &h[pkts];
337     memset(p, 0, sizeof(*p));
338     if (req->addr.ss_family == AF_UNSPEC) {
339       p->msg_hdr.msg_name = NULL;
340       p->msg_hdr.msg_namelen = 0;
341     } else {
342       p->msg_hdr.msg_name = &req->addr;
343       if (req->addr.ss_family == AF_INET6)
344         p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
345       else if (req->addr.ss_family == AF_INET)
346         p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in);
347       else if (req->addr.ss_family == AF_UNIX)
348         p->msg_hdr.msg_namelen = sizeof(struct sockaddr_un);
349       else {
350         assert(0 && "unsupported address family");
351         abort();
352       }
353     }
354     h[pkts].msg_hdr.msg_iov = (struct iovec*) req->bufs;
355     h[pkts].msg_hdr.msg_iovlen = req->nbufs;
356   }
357 
358   do
359     npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts);
360   while (npkts == -1 && errno == EINTR);
361 
362   if (npkts < 1) {
363     if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
364       return;
365     for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
366          i < pkts && q != &handle->write_queue;
367          ++i, q = QUEUE_HEAD(&handle->write_queue)) {
368       assert(q != NULL);
369       req = QUEUE_DATA(q, uv_udp_send_t, queue);
370       assert(req != NULL);
371 
372       req->status = UV__ERR(errno);
373       QUEUE_REMOVE(&req->queue);
374       QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
375     }
376     uv__io_feed(handle->loop, &handle->io_watcher);
377     return;
378   }
379 
380   for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
381        i < pkts && q != &handle->write_queue;
382        ++i, q = QUEUE_HEAD(&handle->write_queue)) {
383     assert(q != NULL);
384     req = QUEUE_DATA(q, uv_udp_send_t, queue);
385     assert(req != NULL);
386 
387     req->status = req->bufs[0].len;
388 
389     /* Sending a datagram is an atomic operation: either all data
390      * is written or nothing is (and EMSGSIZE is raised). That is
391      * why we don't handle partial writes. Just pop the request
392      * off the write queue and onto the completed queue, done.
393      */
394     QUEUE_REMOVE(&req->queue);
395     QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
396   }
397 
398   /* couldn't batch everything, continue sending (jump to avoid stack growth) */
399   if (!QUEUE_EMPTY(&handle->write_queue))
400     goto write_queue_drain;
401   uv__io_feed(handle->loop, &handle->io_watcher);
402   return;
403 }
404 #endif
405 
uv__udp_sendmsg(uv_udp_t * handle)406 static void uv__udp_sendmsg(uv_udp_t* handle) {
407   uv_udp_send_t* req;
408   struct msghdr h;
409   QUEUE* q;
410   ssize_t size;
411 
412 #if HAVE_MMSG
413   uv_once(&once, uv__udp_mmsg_init);
414   if (uv__sendmmsg_avail) {
415     uv__udp_sendmmsg(handle);
416     return;
417   }
418 #endif
419 
420   while (!QUEUE_EMPTY(&handle->write_queue)) {
421     q = QUEUE_HEAD(&handle->write_queue);
422     assert(q != NULL);
423 
424     req = QUEUE_DATA(q, uv_udp_send_t, queue);
425     assert(req != NULL);
426 
427     memset(&h, 0, sizeof h);
428     if (req->addr.ss_family == AF_UNSPEC) {
429       h.msg_name = NULL;
430       h.msg_namelen = 0;
431     } else {
432       h.msg_name = &req->addr;
433       if (req->addr.ss_family == AF_INET6)
434         h.msg_namelen = sizeof(struct sockaddr_in6);
435       else if (req->addr.ss_family == AF_INET)
436         h.msg_namelen = sizeof(struct sockaddr_in);
437       else if (req->addr.ss_family == AF_UNIX)
438         h.msg_namelen = sizeof(struct sockaddr_un);
439       else {
440         assert(0 && "unsupported address family");
441         abort();
442       }
443     }
444     h.msg_iov = (struct iovec*) req->bufs;
445     h.msg_iovlen = req->nbufs;
446 
447     do {
448       size = sendmsg(handle->io_watcher.fd, &h, 0);
449     } while (size == -1 && errno == EINTR);
450 
451     if (size == -1) {
452       if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
453         break;
454     }
455 
456     req->status = (size == -1 ? UV__ERR(errno) : size);
457 
458     /* Sending a datagram is an atomic operation: either all data
459      * is written or nothing is (and EMSGSIZE is raised). That is
460      * why we don't handle partial writes. Just pop the request
461      * off the write queue and onto the completed queue, done.
462      */
463     QUEUE_REMOVE(&req->queue);
464     QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
465     uv__io_feed(handle->loop, &handle->io_watcher);
466   }
467 }
468 
469 /* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional
470  * refinements for programs that use multicast.
471  *
472  * Linux as of 3.9 has a SO_REUSEPORT socket option but with semantics that
473  * are different from the BSDs: it _shares_ the port rather than steal it
474  * from the current listener.  While useful, it's not something we can emulate
475  * on other platforms so we don't enable it.
476  *
477  * zOS does not support getsockname with SO_REUSEPORT option when using
478  * AF_UNIX.
479  */
uv__set_reuse(int fd)480 static int uv__set_reuse(int fd) {
481   int yes;
482   yes = 1;
483 
484 #if defined(SO_REUSEPORT) && defined(__MVS__)
485   struct sockaddr_in sockfd;
486   unsigned int sockfd_len = sizeof(sockfd);
487   if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1)
488       return UV__ERR(errno);
489   if (sockfd.sin_family == AF_UNIX) {
490     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
491       return UV__ERR(errno);
492   } else {
493     if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
494        return UV__ERR(errno);
495   }
496 #elif defined(SO_REUSEPORT) && !defined(__linux__)
497   if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
498     return UV__ERR(errno);
499 #else
500   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
501     return UV__ERR(errno);
502 #endif
503 
504   return 0;
505 }
506 
507 
uv__udp_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)508 int uv__udp_bind(uv_udp_t* handle,
509                  const struct sockaddr* addr,
510                  unsigned int addrlen,
511                  unsigned int flags) {
512   int err;
513   int yes;
514   int fd;
515 
516   /* Check for bad flags. */
517   if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
518     return UV_EINVAL;
519 
520   /* Cannot set IPv6-only mode on non-IPv6 socket. */
521   if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6)
522     return UV_EINVAL;
523 
524   fd = handle->io_watcher.fd;
525   if (fd == -1) {
526     err = uv__socket(addr->sa_family, SOCK_DGRAM, 0);
527     if (err < 0)
528       return err;
529     fd = err;
530     handle->io_watcher.fd = fd;
531   }
532 
533   if (flags & UV_UDP_REUSEADDR) {
534     err = uv__set_reuse(fd);
535     if (err)
536       return err;
537   }
538 
539   if (flags & UV_UDP_IPV6ONLY) {
540 #ifdef IPV6_V6ONLY
541     yes = 1;
542     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
543       err = UV__ERR(errno);
544       return err;
545     }
546 #else
547     err = UV_ENOTSUP;
548     return err;
549 #endif
550   }
551 
552   if (bind(fd, addr, addrlen)) {
553     err = UV__ERR(errno);
554     if (errno == EAFNOSUPPORT)
555       /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
556        * socket created with AF_INET to an AF_INET6 address or vice versa. */
557       err = UV_EINVAL;
558     return err;
559   }
560 
561   if (addr->sa_family == AF_INET6)
562     handle->flags |= UV_HANDLE_IPV6;
563 
564   handle->flags |= UV_HANDLE_BOUND;
565   return 0;
566 }
567 
568 
uv__udp_maybe_deferred_bind(uv_udp_t * handle,int domain,unsigned int flags)569 static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
570                                        int domain,
571                                        unsigned int flags) {
572   union uv__sockaddr taddr;
573   socklen_t addrlen;
574 
575   if (handle->io_watcher.fd != -1)
576     return 0;
577 
578   switch (domain) {
579   case AF_INET:
580   {
581     struct sockaddr_in* addr = &taddr.in;
582     memset(addr, 0, sizeof *addr);
583     addr->sin_family = AF_INET;
584     addr->sin_addr.s_addr = INADDR_ANY;
585     addrlen = sizeof *addr;
586     break;
587   }
588   case AF_INET6:
589   {
590     struct sockaddr_in6* addr = &taddr.in6;
591     memset(addr, 0, sizeof *addr);
592     addr->sin6_family = AF_INET6;
593     addr->sin6_addr = in6addr_any;
594     addrlen = sizeof *addr;
595     break;
596   }
597   default:
598     assert(0 && "unsupported address family");
599     abort();
600   }
601 
602   return uv__udp_bind(handle, &taddr.addr, addrlen, flags);
603 }
604 
605 
uv__udp_connect(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen)606 int uv__udp_connect(uv_udp_t* handle,
607                     const struct sockaddr* addr,
608                     unsigned int addrlen) {
609   int err;
610 
611   err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
612   if (err)
613     return err;
614 
615   do {
616     errno = 0;
617     err = connect(handle->io_watcher.fd, addr, addrlen);
618   } while (err == -1 && errno == EINTR);
619 
620   if (err)
621     return UV__ERR(errno);
622 
623   handle->flags |= UV_HANDLE_UDP_CONNECTED;
624 
625   return 0;
626 }
627 
628 
uv__udp_disconnect(uv_udp_t * handle)629 int uv__udp_disconnect(uv_udp_t* handle) {
630     int r;
631     struct sockaddr addr;
632 
633     memset(&addr, 0, sizeof(addr));
634 
635     addr.sa_family = AF_UNSPEC;
636 
637     do {
638       errno = 0;
639       r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
640     } while (r == -1 && errno == EINTR);
641 
642     if (r == -1 && errno != EAFNOSUPPORT)
643       return UV__ERR(errno);
644 
645     handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
646     return 0;
647 }
648 
649 
uv__udp_send(uv_udp_send_t * req,uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen,uv_udp_send_cb send_cb)650 int uv__udp_send(uv_udp_send_t* req,
651                  uv_udp_t* handle,
652                  const uv_buf_t bufs[],
653                  unsigned int nbufs,
654                  const struct sockaddr* addr,
655                  unsigned int addrlen,
656                  uv_udp_send_cb send_cb) {
657   int err;
658   int empty_queue;
659 
660   assert(nbufs > 0);
661 
662   if (addr) {
663     err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
664     if (err)
665       return err;
666   }
667 
668   /* It's legal for send_queue_count > 0 even when the write_queue is empty;
669    * it means there are error-state requests in the write_completed_queue that
670    * will touch up send_queue_size/count later.
671    */
672   empty_queue = (handle->send_queue_count == 0);
673 
674   uv__req_init(handle->loop, req, UV_UDP_SEND);
675   assert(addrlen <= sizeof(req->addr));
676   if (addr == NULL)
677     req->addr.ss_family = AF_UNSPEC;
678   else
679     memcpy(&req->addr, addr, addrlen);
680   req->send_cb = send_cb;
681   req->handle = handle;
682   req->nbufs = nbufs;
683 
684   req->bufs = req->bufsml;
685   if (nbufs > ARRAY_SIZE(req->bufsml))
686     req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
687 
688   if (req->bufs == NULL) {
689     uv__req_unregister(handle->loop, req);
690     return UV_ENOMEM;
691   }
692 
693   memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
694   handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs);
695   handle->send_queue_count++;
696   QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
697   uv__handle_start(handle);
698 
699   if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) {
700     uv__udp_sendmsg(handle);
701 
702     /* `uv__udp_sendmsg` may not be able to do non-blocking write straight
703      * away. In such cases the `io_watcher` has to be queued for asynchronous
704      * write.
705      */
706     if (!QUEUE_EMPTY(&handle->write_queue))
707       uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
708   } else {
709     uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
710   }
711 
712   return 0;
713 }
714 
715 
uv__udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen)716 int uv__udp_try_send(uv_udp_t* handle,
717                      const uv_buf_t bufs[],
718                      unsigned int nbufs,
719                      const struct sockaddr* addr,
720                      unsigned int addrlen) {
721   int err;
722   struct msghdr h;
723   ssize_t size;
724 
725   assert(nbufs > 0);
726 
727   /* already sending a message */
728   if (handle->send_queue_count != 0)
729     return UV_EAGAIN;
730 
731   if (addr) {
732     err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
733     if (err)
734       return err;
735   } else {
736     assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
737   }
738 
739   memset(&h, 0, sizeof h);
740   h.msg_name = (struct sockaddr*) addr;
741   h.msg_namelen = addrlen;
742   h.msg_iov = (struct iovec*) bufs;
743   h.msg_iovlen = nbufs;
744 
745   do {
746     size = sendmsg(handle->io_watcher.fd, &h, 0);
747   } while (size == -1 && errno == EINTR);
748 
749   if (size == -1) {
750     if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
751       return UV_EAGAIN;
752     else
753       return UV__ERR(errno);
754   }
755 
756   return size;
757 }
758 
759 
uv__udp_set_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,uv_membership membership)760 static int uv__udp_set_membership4(uv_udp_t* handle,
761                                    const struct sockaddr_in* multicast_addr,
762                                    const char* interface_addr,
763                                    uv_membership membership) {
764   struct ip_mreq mreq;
765   int optname;
766   int err;
767 
768   memset(&mreq, 0, sizeof mreq);
769 
770   if (interface_addr) {
771     err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
772     if (err)
773       return err;
774   } else {
775     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
776   }
777 
778   mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
779 
780   switch (membership) {
781   case UV_JOIN_GROUP:
782     optname = IP_ADD_MEMBERSHIP;
783     break;
784   case UV_LEAVE_GROUP:
785     optname = IP_DROP_MEMBERSHIP;
786     break;
787   default:
788     return UV_EINVAL;
789   }
790 
791   if (setsockopt(handle->io_watcher.fd,
792                  IPPROTO_IP,
793                  optname,
794                  &mreq,
795                  sizeof(mreq))) {
796 #if defined(__MVS__)
797   if (errno == ENXIO)
798     return UV_ENODEV;
799 #endif
800     return UV__ERR(errno);
801   }
802 
803   return 0;
804 }
805 
806 
uv__udp_set_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,uv_membership membership)807 static int uv__udp_set_membership6(uv_udp_t* handle,
808                                    const struct sockaddr_in6* multicast_addr,
809                                    const char* interface_addr,
810                                    uv_membership membership) {
811   int optname;
812   struct ipv6_mreq mreq;
813   struct sockaddr_in6 addr6;
814 
815   memset(&mreq, 0, sizeof mreq);
816 
817   if (interface_addr) {
818     if (uv_ip6_addr(interface_addr, 0, &addr6))
819       return UV_EINVAL;
820     mreq.ipv6mr_interface = addr6.sin6_scope_id;
821   } else {
822     mreq.ipv6mr_interface = 0;
823   }
824 
825   mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
826 
827   switch (membership) {
828   case UV_JOIN_GROUP:
829     optname = IPV6_ADD_MEMBERSHIP;
830     break;
831   case UV_LEAVE_GROUP:
832     optname = IPV6_DROP_MEMBERSHIP;
833     break;
834   default:
835     return UV_EINVAL;
836   }
837 
838   if (setsockopt(handle->io_watcher.fd,
839                  IPPROTO_IPV6,
840                  optname,
841                  &mreq,
842                  sizeof(mreq))) {
843 #if defined(__MVS__)
844   if (errno == ENXIO)
845     return UV_ENODEV;
846 #endif
847     return UV__ERR(errno);
848   }
849 
850   return 0;
851 }
852 
853 
854 #if !defined(__OpenBSD__) &&                                        \
855     !defined(__NetBSD__) &&                                         \
856     !defined(__ANDROID__) &&                                        \
857     !defined(__DragonFly__) &                                       \
858     !defined(__QNX__)
uv__udp_set_source_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,const struct sockaddr_in * source_addr,uv_membership membership)859 static int uv__udp_set_source_membership4(uv_udp_t* handle,
860                                           const struct sockaddr_in* multicast_addr,
861                                           const char* interface_addr,
862                                           const struct sockaddr_in* source_addr,
863                                           uv_membership membership) {
864   struct ip_mreq_source mreq;
865   int optname;
866   int err;
867 
868   err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
869   if (err)
870     return err;
871 
872   memset(&mreq, 0, sizeof(mreq));
873 
874   if (interface_addr != NULL) {
875     err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
876     if (err)
877       return err;
878   } else {
879     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
880   }
881 
882   mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
883   mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
884 
885   if (membership == UV_JOIN_GROUP)
886     optname = IP_ADD_SOURCE_MEMBERSHIP;
887   else if (membership == UV_LEAVE_GROUP)
888     optname = IP_DROP_SOURCE_MEMBERSHIP;
889   else
890     return UV_EINVAL;
891 
892   if (setsockopt(handle->io_watcher.fd,
893                  IPPROTO_IP,
894                  optname,
895                  &mreq,
896                  sizeof(mreq))) {
897     return UV__ERR(errno);
898   }
899 
900   return 0;
901 }
902 
903 
uv__udp_set_source_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,const struct sockaddr_in6 * source_addr,uv_membership membership)904 static int uv__udp_set_source_membership6(uv_udp_t* handle,
905                                           const struct sockaddr_in6* multicast_addr,
906                                           const char* interface_addr,
907                                           const struct sockaddr_in6* source_addr,
908                                           uv_membership membership) {
909   struct group_source_req mreq;
910   struct sockaddr_in6 addr6;
911   int optname;
912   int err;
913 
914   err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
915   if (err)
916     return err;
917 
918   memset(&mreq, 0, sizeof(mreq));
919 
920   if (interface_addr != NULL) {
921     err = uv_ip6_addr(interface_addr, 0, &addr6);
922     if (err)
923       return err;
924     mreq.gsr_interface = addr6.sin6_scope_id;
925   } else {
926     mreq.gsr_interface = 0;
927   }
928 
929   STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr));
930   STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr));
931   memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr));
932   memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr));
933 
934   if (membership == UV_JOIN_GROUP)
935     optname = MCAST_JOIN_SOURCE_GROUP;
936   else if (membership == UV_LEAVE_GROUP)
937     optname = MCAST_LEAVE_SOURCE_GROUP;
938   else
939     return UV_EINVAL;
940 
941   if (setsockopt(handle->io_watcher.fd,
942                  IPPROTO_IPV6,
943                  optname,
944                  &mreq,
945                  sizeof(mreq))) {
946     return UV__ERR(errno);
947   }
948 
949   return 0;
950 }
951 #endif
952 
953 
uv__udp_init_ex(uv_loop_t * loop,uv_udp_t * handle,unsigned flags,int domain)954 int uv__udp_init_ex(uv_loop_t* loop,
955                     uv_udp_t* handle,
956                     unsigned flags,
957                     int domain) {
958   int fd;
959 
960   fd = -1;
961   if (domain != AF_UNSPEC) {
962     fd = uv__socket(domain, SOCK_DGRAM, 0);
963     if (fd < 0)
964       return fd;
965   }
966 
967   uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP);
968   handle->alloc_cb = NULL;
969   handle->recv_cb = NULL;
970   handle->send_queue_size = 0;
971   handle->send_queue_count = 0;
972   uv__io_init(&handle->io_watcher, uv__udp_io, fd);
973   QUEUE_INIT(&handle->write_queue);
974   QUEUE_INIT(&handle->write_completed_queue);
975 
976   return 0;
977 }
978 
979 
uv_udp_using_recvmmsg(const uv_udp_t * handle)980 int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
981 #if HAVE_MMSG
982   if (handle->flags & UV_HANDLE_UDP_RECVMMSG) {
983     uv_once(&once, uv__udp_mmsg_init);
984     return uv__recvmmsg_avail;
985   }
986 #endif
987   return 0;
988 }
989 
990 
uv_udp_open(uv_udp_t * handle,uv_os_sock_t sock)991 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
992   int err;
993 
994   /* Check for already active socket. */
995   if (handle->io_watcher.fd != -1)
996     return UV_EBUSY;
997 
998   if (uv__fd_exists(handle->loop, sock))
999     return UV_EEXIST;
1000 
1001   err = uv__nonblock(sock, 1);
1002   if (err)
1003     return err;
1004 
1005   err = uv__set_reuse(sock);
1006   if (err)
1007     return err;
1008 
1009   handle->io_watcher.fd = sock;
1010   if (uv__udp_is_connected(handle))
1011     handle->flags |= UV_HANDLE_UDP_CONNECTED;
1012 
1013   return 0;
1014 }
1015 
1016 
uv_udp_set_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,uv_membership membership)1017 int uv_udp_set_membership(uv_udp_t* handle,
1018                           const char* multicast_addr,
1019                           const char* interface_addr,
1020                           uv_membership membership) {
1021   int err;
1022   struct sockaddr_in addr4;
1023   struct sockaddr_in6 addr6;
1024 
1025   if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) {
1026     err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
1027     if (err)
1028       return err;
1029     return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
1030   } else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) {
1031     err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
1032     if (err)
1033       return err;
1034     return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
1035   } else {
1036     return UV_EINVAL;
1037   }
1038 }
1039 
1040 
uv_udp_set_source_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,const char * source_addr,uv_membership membership)1041 int uv_udp_set_source_membership(uv_udp_t* handle,
1042                                  const char* multicast_addr,
1043                                  const char* interface_addr,
1044                                  const char* source_addr,
1045                                  uv_membership membership) {
1046 #if !defined(__OpenBSD__) &&                                        \
1047     !defined(__NetBSD__) &&                                         \
1048     !defined(__ANDROID__) &&                                        \
1049     !defined(__DragonFly__) &&                                      \
1050     !defined(__QNX__)
1051   int err;
1052   union uv__sockaddr mcast_addr;
1053   union uv__sockaddr src_addr;
1054 
1055   err = uv_ip4_addr(multicast_addr, 0, &mcast_addr.in);
1056   if (err) {
1057     err = uv_ip6_addr(multicast_addr, 0, &mcast_addr.in6);
1058     if (err)
1059       return err;
1060     err = uv_ip6_addr(source_addr, 0, &src_addr.in6);
1061     if (err)
1062       return err;
1063     return uv__udp_set_source_membership6(handle,
1064                                           &mcast_addr.in6,
1065                                           interface_addr,
1066                                           &src_addr.in6,
1067                                           membership);
1068   }
1069 
1070   err = uv_ip4_addr(source_addr, 0, &src_addr.in);
1071   if (err)
1072     return err;
1073   return uv__udp_set_source_membership4(handle,
1074                                         &mcast_addr.in,
1075                                         interface_addr,
1076                                         &src_addr.in,
1077                                         membership);
1078 #else
1079   return UV_ENOSYS;
1080 #endif
1081 }
1082 
1083 
uv__setsockopt(uv_udp_t * handle,int option4,int option6,const void * val,socklen_t size)1084 static int uv__setsockopt(uv_udp_t* handle,
1085                          int option4,
1086                          int option6,
1087                          const void* val,
1088                          socklen_t size) {
1089   int r;
1090 
1091   if (handle->flags & UV_HANDLE_IPV6)
1092     r = setsockopt(handle->io_watcher.fd,
1093                    IPPROTO_IPV6,
1094                    option6,
1095                    val,
1096                    size);
1097   else
1098     r = setsockopt(handle->io_watcher.fd,
1099                    IPPROTO_IP,
1100                    option4,
1101                    val,
1102                    size);
1103   if (r)
1104     return UV__ERR(errno);
1105 
1106   return 0;
1107 }
1108 
uv__setsockopt_maybe_char(uv_udp_t * handle,int option4,int option6,int val)1109 static int uv__setsockopt_maybe_char(uv_udp_t* handle,
1110                                      int option4,
1111                                      int option6,
1112                                      int val) {
1113 #if defined(__sun) || defined(_AIX) || defined(__MVS__)
1114   char arg = val;
1115 #elif defined(__OpenBSD__)
1116   unsigned char arg = val;
1117 #else
1118   int arg = val;
1119 #endif
1120 
1121   if (val < 0 || val > 255)
1122     return UV_EINVAL;
1123 
1124   return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg));
1125 }
1126 
1127 
uv_udp_set_broadcast(uv_udp_t * handle,int on)1128 int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
1129   if (setsockopt(handle->io_watcher.fd,
1130                  SOL_SOCKET,
1131                  SO_BROADCAST,
1132                  &on,
1133                  sizeof(on))) {
1134     return UV__ERR(errno);
1135   }
1136 
1137   return 0;
1138 }
1139 
1140 
uv_udp_set_ttl(uv_udp_t * handle,int ttl)1141 int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
1142   if (ttl < 1 || ttl > 255)
1143     return UV_EINVAL;
1144 
1145 #if defined(__MVS__)
1146   if (!(handle->flags & UV_HANDLE_IPV6))
1147     return UV_ENOTSUP;  /* zOS does not support setting ttl for IPv4 */
1148 #endif
1149 
1150 /*
1151  * On Solaris and derivatives such as SmartOS, the length of socket options
1152  * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS,
1153  * so hardcode the size of these options on this platform,
1154  * and use the general uv__setsockopt_maybe_char call on other platforms.
1155  */
1156 #if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
1157     defined(__MVS__) || defined(__QNX__)
1158 
1159   return uv__setsockopt(handle,
1160                         IP_TTL,
1161                         IPV6_UNICAST_HOPS,
1162                         &ttl,
1163                         sizeof(ttl));
1164 
1165 #else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
1166            defined(__MVS__) || defined(__QNX__)) */
1167 
1168   return uv__setsockopt_maybe_char(handle,
1169                                    IP_TTL,
1170                                    IPV6_UNICAST_HOPS,
1171                                    ttl);
1172 
1173 #endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
1174           defined(__MVS__) || defined(__QNX__) */
1175 }
1176 
1177 
uv_udp_set_multicast_ttl(uv_udp_t * handle,int ttl)1178 int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
1179 /*
1180  * On Solaris and derivatives such as SmartOS, the length of socket options
1181  * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for
1182  * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
1183  * and use the general uv__setsockopt_maybe_char call otherwise.
1184  */
1185 #if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
1186     defined(__MVS__) || defined(__QNX__)
1187   if (handle->flags & UV_HANDLE_IPV6)
1188     return uv__setsockopt(handle,
1189                           IP_MULTICAST_TTL,
1190                           IPV6_MULTICAST_HOPS,
1191                           &ttl,
1192                           sizeof(ttl));
1193 #endif /* defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
1194     defined(__MVS__) || defined(__QNX__) */
1195 
1196   return uv__setsockopt_maybe_char(handle,
1197                                    IP_MULTICAST_TTL,
1198                                    IPV6_MULTICAST_HOPS,
1199                                    ttl);
1200 }
1201 
1202 
uv_udp_set_multicast_loop(uv_udp_t * handle,int on)1203 int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
1204 /*
1205  * On Solaris and derivatives such as SmartOS, the length of socket options
1206  * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for
1207  * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
1208  * and use the general uv__setsockopt_maybe_char call otherwise.
1209  */
1210 #if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
1211     defined(__MVS__) || defined(__QNX__)
1212   if (handle->flags & UV_HANDLE_IPV6)
1213     return uv__setsockopt(handle,
1214                           IP_MULTICAST_LOOP,
1215                           IPV6_MULTICAST_LOOP,
1216                           &on,
1217                           sizeof(on));
1218 #endif /* defined(__sun) || defined(_AIX) ||defined(__OpenBSD__) ||
1219     defined(__MVS__) || defined(__QNX__) */
1220 
1221   return uv__setsockopt_maybe_char(handle,
1222                                    IP_MULTICAST_LOOP,
1223                                    IPV6_MULTICAST_LOOP,
1224                                    on);
1225 }
1226 
uv_udp_set_multicast_interface(uv_udp_t * handle,const char * interface_addr)1227 int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
1228   struct sockaddr_storage addr_st;
1229   struct sockaddr_in* addr4;
1230   struct sockaddr_in6* addr6;
1231 
1232   addr4 = (struct sockaddr_in*) &addr_st;
1233   addr6 = (struct sockaddr_in6*) &addr_st;
1234 
1235   if (!interface_addr) {
1236     memset(&addr_st, 0, sizeof addr_st);
1237     if (handle->flags & UV_HANDLE_IPV6) {
1238       addr_st.ss_family = AF_INET6;
1239       addr6->sin6_scope_id = 0;
1240     } else {
1241       addr_st.ss_family = AF_INET;
1242       addr4->sin_addr.s_addr = htonl(INADDR_ANY);
1243     }
1244   } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
1245     /* nothing, address was parsed */
1246   } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
1247     /* nothing, address was parsed */
1248   } else {
1249     return UV_EINVAL;
1250   }
1251 
1252   if (addr_st.ss_family == AF_INET) {
1253     if (setsockopt(handle->io_watcher.fd,
1254                    IPPROTO_IP,
1255                    IP_MULTICAST_IF,
1256                    (void*) &addr4->sin_addr,
1257                    sizeof(addr4->sin_addr)) == -1) {
1258       return UV__ERR(errno);
1259     }
1260   } else if (addr_st.ss_family == AF_INET6) {
1261     if (setsockopt(handle->io_watcher.fd,
1262                    IPPROTO_IPV6,
1263                    IPV6_MULTICAST_IF,
1264                    &addr6->sin6_scope_id,
1265                    sizeof(addr6->sin6_scope_id)) == -1) {
1266       return UV__ERR(errno);
1267     }
1268   } else {
1269     assert(0 && "unexpected address family");
1270     abort();
1271   }
1272 
1273   return 0;
1274 }
1275 
uv_udp_getpeername(const uv_udp_t * handle,struct sockaddr * name,int * namelen)1276 int uv_udp_getpeername(const uv_udp_t* handle,
1277                        struct sockaddr* name,
1278                        int* namelen) {
1279 
1280   return uv__getsockpeername((const uv_handle_t*) handle,
1281                              getpeername,
1282                              name,
1283                              namelen);
1284 }
1285 
uv_udp_getsockname(const uv_udp_t * handle,struct sockaddr * name,int * namelen)1286 int uv_udp_getsockname(const uv_udp_t* handle,
1287                        struct sockaddr* name,
1288                        int* namelen) {
1289 
1290   return uv__getsockpeername((const uv_handle_t*) handle,
1291                              getsockname,
1292                              name,
1293                              namelen);
1294 }
1295 
1296 
uv__udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)1297 int uv__udp_recv_start(uv_udp_t* handle,
1298                        uv_alloc_cb alloc_cb,
1299                        uv_udp_recv_cb recv_cb) {
1300   int err;
1301 
1302   if (alloc_cb == NULL || recv_cb == NULL)
1303     return UV_EINVAL;
1304 
1305   if (uv__io_active(&handle->io_watcher, POLLIN))
1306     return UV_EALREADY;  /* FIXME(bnoordhuis) Should be UV_EBUSY. */
1307 
1308   err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
1309   if (err)
1310     return err;
1311 
1312   handle->alloc_cb = alloc_cb;
1313   handle->recv_cb = recv_cb;
1314 
1315   uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
1316   uv__handle_start(handle);
1317 
1318   return 0;
1319 }
1320 
1321 
uv__udp_recv_stop(uv_udp_t * handle)1322 int uv__udp_recv_stop(uv_udp_t* handle) {
1323   uv__io_stop(handle->loop, &handle->io_watcher, POLLIN);
1324 
1325   if (!uv__io_active(&handle->io_watcher, POLLOUT))
1326     uv__handle_stop(handle);
1327 
1328   handle->alloc_cb = NULL;
1329   handle->recv_cb = NULL;
1330 
1331   return 0;
1332 }
1333