socket.c revision edf8e79280a78350a13ad519ce035ec12c79be0f
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * Copyright (C) 1998-2003 Internet Software Consortium.
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * Permission to use, copy, modify, and distribute this software for any
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * purpose with or without fee is hereby granted, provided that the above
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * copyright notice and this permission notice appear in all copies.
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * PERFORMANCE OF THIS SOFTWARE.
d25afd60ee2286cb171c4960a790f3d7041b6f85Bob Halley/* $Id: socket.c,v 1.267 2007/01/04 00:01:13 marka Exp $ */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* ISC_PLATFORM_USETHREADS */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Some systems define the socket length argument as an int, some as size_t,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * some as socklen_t. This is here so it can be easily changed if needed.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define ISC_SOCKADDR_LEN_T unsigned int
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Define what the possible "soft" errors can be. These are non-fatal returns
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * of various network related functions, like recv() and so on.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * For some reason, BSDI (and perhaps others) will sometimes return <0
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * from recv() but will have errno==0. This is broken, but we have to
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * work around it here.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DLVL(90) -- Function entry/exit and other tracing.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DLVL(70) -- Socket "correctness" -- including returning of events, etc.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DLVL(60) -- Socket data send/receive
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DLVL(50) -- Event tracing, including receiving/sending completion events.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DLVL(20) -- Socket creation/destruction.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o')
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * IPv6 control information. If the socket is an IPv6 socket we want
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * to collect the destination address and interface so the client can
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * set them on outgoing packets.
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley * NetBSD and FreeBSD can timestamp packets. XXXMLG Should we have
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * a setsockopt() like interface to request timestamps, and if the OS
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * doesn't do it for us, call gettimeofday() on every UDP receive?
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * The size to raise the recieve buffer to (from BIND 8).
70fdfcd1fa7ebd059deffa9a2cecc29df96dfe52Bob Halley * The number of times a send operation is repeated if the result is EINTR.
70fdfcd1fa7ebd059deffa9a2cecc29df96dfe52Bob Halley /* Not locked. */
70fdfcd1fa7ebd059deffa9a2cecc29df96dfe52Bob Halley unsigned int magic;
08c8a934ceb2dfc6a5ebfd3be4ba5a1b3243bc73Bob Halley /* Locked by socket lock. */
08c8a934ceb2dfc6a5ebfd3be4ba5a1b3243bc73Bob Halley unsigned int references;
95f78a208ad6dfb8359320c77ab30c670c773922Mark Andrews * Internal events. Posted when a descriptor is readable or
8db3b065b4659f593f7b8eaa7c9ca0c3daa4da02Bob Halley * writable. These are statically allocated and never freed.
8db3b065b4659f593f7b8eaa7c9ca0c3daa4da02Bob Halley * They will be set to non-purgable before use.
5f120ce962b03e4dcf6f1974b9b896f0fa7cacb0Bob Halley isc_sockaddr_t peer_address; /* remote address */
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley unsigned char overflow; /* used for MSG_TRUNC fake */
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley /* Not locked. */
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley unsigned int magic;
577179503f2eb7695ec668d8eeb41889a150e28fBob Halley /* Locked by manager lock. */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#else /* ISC_PLATFORM_USETHREADS */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley unsigned int refs;
3740b569ae76295b941d57a724a43beb75b533baBob Halley#endif /* ISC_PLATFORM_USETHREADS */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* ISC_PLATFORM_USETHREADS */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * send() and recv() iovec counts
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
3740b569ae76295b941d57a724a43beb75b533baBob Halley# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void send_senddone_event(isc_socket_t *, isc_socketevent_t **);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_accept(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_connect(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_recv(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_send(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_fdwatch_write(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void internal_fdwatch_read(isc_task_t *, isc_event_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleystatic void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define SELECT_POKE_ACCEPT (-3) /*%< Same as _READ */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define SELECT_POKE_CONNECT (-4) /*%< Same as _WRITE */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley const char *fmt, ...)
ce3761f64d3d734cc94605026985898900ecc474Bob Halleysocket_log(isc_socket_t *sock, isc_sockaddr_t *address,
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halleysocket_log(isc_socket_t *sock, isc_sockaddr_t *address,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley const char *fmt, ...)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_log_iwrite(isc_lctx, category, module, level,
ce3761f64d3d734cc94605026985898900ecc474Bob Halley isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
ce3761f64d3d734cc94605026985898900ecc474Bob Halley isc_log_iwrite(isc_lctx, category, module, level,
ce3761f64d3d734cc94605026985898900ecc474Bob Halleywakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * This is a wakeup on a socket. If the socket is not in the
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * process of being closed, start watching it for either reads
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * or writes.
ce3761f64d3d734cc94605026985898900ecc474Bob Halley || manager->fdstate[fd] == MANAGER_CLOSE_PENDING) {
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Set requested bit.
00d81794884f1eee59ca058a292f2d1e50d9547cBob Halley * Poke the select loop when there is something for us to do.
00d81794884f1eee59ca058a292f2d1e50d9547cBob Halley * The write is required (by POSIX) to complete. That is, we
00d81794884f1eee59ca058a292f2d1e50d9547cBob Halley * will not get partial writes.
00d81794884f1eee59ca058a292f2d1e50d9547cBob Halleyselect_poke(isc_socketmgr_t *mgr, int fd, int msg) {
f18f3c93e7fecf120302658f93addae573a6e874Bob Halley * Treat ENOSR as EAGAIN but loop slowly as it is
f18f3c93e7fecf120302658f93addae573a6e874Bob Halley * unlikely to clear fast.
f18f3c93e7fecf120302658f93addae573a6e874Bob Halley "write() failed "
f18f3c93e7fecf120302658f93addae573a6e874Bob Halley "during watcher poke: %s"),
f18f3c93e7fecf120302658f93addae573a6e874Bob Halley * Read a message on the internal fd.
f18f3c93e7fecf120302658f93addae573a6e874Bob Halleyselect_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
bcfcece57e9411ee4bd352b45a8b1ac1dbcf01f4Bob Halley "read() failed "
bcfcece57e9411ee4bd352b45a8b1ac1dbcf01f4Bob Halley "during watcher poke: %s"),
bcfcece57e9411ee4bd352b45a8b1ac1dbcf01f4Bob Halley#else /* ISC_PLATFORM_USETHREADS */
bcfcece57e9411ee4bd352b45a8b1ac1dbcf01f4Bob Halley * Update the state of the socketmgr when something changes.
1366b7833c86343de278480b9abd71754e418bfaBob Halleyselect_poke(isc_socketmgr_t *manager, int fd, int msg) {
1366b7833c86343de278480b9abd71754e418bfaBob Halley else if (fd >= 0)
1366b7833c86343de278480b9abd71754e418bfaBob Halley#endif /* ISC_PLATFORM_USETHREADS */
1366b7833c86343de278480b9abd71754e418bfaBob Halley * Make a fd non-blocking.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * In order to ensure as much portability as possible, we provide wrapper
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * functions of these macros.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Note that cmsg_space() could run slow on OSes that do not have
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * CMSG_SPACE.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * is correct.
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL));
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * XXX: The buffer length is an ad-hoc value, but should be enough
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * in a practical sense.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley return ((char *)cmsgp - (char *)msg.msg_control);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* USE_CMSG */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Process control messages received on a socket.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleyprocess_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * sock is used only when ISC_NET_BSD44MSGHDR and USE_CMSG are defined.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * msg and dev are used only when ISC_NET_BSD44MSGHDR is defined.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * They are all here, outside of the CPP tests, because it is
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * more consistent with the usual ISC coding style.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley if (msg->msg_controllen == 0U || msg->msg_control == NULL)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PROCESSCMSG,
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley sizeof(struct in6_pktinfo));
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley "interface received on ifindex %u",
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley dev->timestamp.nanoseconds = timevalp->tv_usec * 1000;
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley#endif /* USE_CMSG */
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley#endif /* ISC_NET_BSD44MSGHDR */
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Construct an iov array and attach it to the msghdr passed in. This is
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * the SEND constructor, which will use the used region of the buffer
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * (if using a buffer list) or will use the internal region (if a single
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * buffer I/O is requested).
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Nothing can be NULL, and the done event must list at least one buffer
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * on the buffer linked list for this function to be meaningful.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * If write_countp != NULL, *write_countp will hold the number of bytes
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * this transaction can send.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halleybuild_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley struct msghdr *msg, struct iovec *iov, size_t *write_countp)
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley unsigned int iovcount;
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Single buffer I/O? Skip what we've done so far in this region.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley iov[0].iov_base = (void *)(dev->region.base + dev->n);
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Multibuffer I/O.
29b487b0a458d655f0aad9257ca46021f4903d08Bob Halley * Skip the data in the buffer list that we have already written.
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley iov[iovcount].iov_len = used.length - skip_count;
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SENDTODATA,
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley "sendto pktinfo data, ifindex %u",
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley#else /* ISC_NET_BSD44MSGHDR */
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley#endif /* ISC_NET_BSD44MSGHDR */
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * Construct an iov array and attach it to the msghdr passed in. This is
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * the RECV constructor, which will use the avialable region of the buffer
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * (if using a buffer list) or will use the internal region (if a single
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * buffer I/O is requested).
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * Nothing can be NULL, and the done event must list at least one buffer
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * on the buffer linked list for this function to be meaningful.
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * If read_countp != NULL, *read_countp will hold the number of bytes
6957b87f931bb110ba4d0adf495932691ba550b1Bob Halley * this transaction can receive.
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrewsbuild_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews struct msghdr *msg, struct iovec *iov, size_t *read_countp)
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews unsigned int iovcount;
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews memset(&dev->address, 0, sizeof(dev->address));
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_name = (void *)&dev->address.type.sin;
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_namelen = sizeof(dev->address.type.sin6);
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_name = (void *)&dev->address.type.sin6;
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_namelen = sizeof(dev->address.type.sin6);
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_name = (void *)&dev->address.type.sunix;
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews msg->msg_namelen = sizeof(dev->address.type.sunix);
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews /* If needed, steal one iovec for overflow detection. */
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews } else { /* TCP */
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews * Single buffer I/O? Skip what we've done so far in this region.
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews iov[0].iov_base = (void *)(dev->region.base + dev->n);
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews * Multibuffer I/O.
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews * Skip empty buffers.
aa8e34546c1e51e69f5a4935d28cb0c543e7401aAndreas Gustafsson INSIST(iovcount < MAXSCATTERGATHER_RECV);
aa8e34546c1e51e69f5a4935d28cb0c543e7401aAndreas Gustafsson isc_buffer_availableregion(buffer, &available);
7c0539bea56022274da04263eb41fbb5b8835c38Mark Andrews iov[iovcount].iov_base = (void *)(available.base);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * If needed, set up to receive that one extra byte. Note that
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * we know there is at least one iov left, since we stole it
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * at the top of this function.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley iov[iovcount].iov_base = (void *)(&sock->overflow);
d2b77d720f1dcdc85a761b1de1a94d32fbdef81aBrian Wellington msg->msg_controllen = sock->recvcmsgbuflen;
d2b77d720f1dcdc85a761b1de1a94d32fbdef81aBrian Wellington#endif /* USE_CMSG */
d2b77d720f1dcdc85a761b1de1a94d32fbdef81aBrian Wellington#else /* ISC_NET_BSD44MSGHDR */
d2b77d720f1dcdc85a761b1de1a94d32fbdef81aBrian Wellington#endif /* ISC_NET_BSD44MSGHDR */
d2b77d720f1dcdc85a761b1de1a94d32fbdef81aBrian Wellingtonset_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley isc_socketevent_t *ev = (isc_socketevent_t *)event;
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halleyallocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley unsigned int i;
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley printf("\tcontrol %p, controllen %d\n", msg->msg_control,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleydoio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley isc__strerror(recv_errno, strbuf, sizeof(strbuf));
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley "doio_recv: recvmsg(%d) %d bytes, err %d/%s",
bd53af8229e28cfec8bfd9572b4d31514ea97f48Bob Halley /* HPUX 11.11 can return EADDRNOTAVAIL. */
bd53af8229e28cfec8bfd9572b4d31514ea97f48Bob Halley * On TCP, zero length reads indicate EOF, while on
bd53af8229e28cfec8bfd9572b4d31514ea97f48Bob Halley * UDP, zero length reads are perfectly valid, although
bd53af8229e28cfec8bfd9572b4d31514ea97f48Bob Halley if ((sock->type == isc_sockettype_tcp) && (cc == 0))
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "dropping source port zero packet");
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley "packet received correctly");
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews * Overflow bit detection. If we received MORE bytes than we should,
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews * this indicates an overflow situation. Set the flag in the
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews * dev entry and adjust how much we read by one.
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * If there are control messages attached, run through them and pull
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * out the interesting bits.
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews * update the buffers (if any) and the i/o count
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley if (isc_buffer_availablelength(buffer) <= actual_count) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley actual_count -= isc_buffer_availablelength(buffer);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * If we read less than we expected, update counters,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * and let the upper layer poke the descriptor.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley if (((size_t)cc != read_count) && (dev->n < dev->minimum))
38d2d0e9326a2f70b5893302b89a26978b539405Bob Halley * Full reads are posted, or partials if partials are ok.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DOIO_SUCCESS The operation succeeded. dev->result contains
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * ISC_R_SUCCESS.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DOIO_HARD A hard or unexpected I/O error was encountered.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * dev->result contains the appropriate error.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * DOIO_SOFT A soft I/O error was encountered. No senddone
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * event was sent. The operation should be retried.
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * No other return values are possible.
ce3761f64d3d734cc94605026985898900ecc474Bob Halleydoio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Check for error or block condition.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley if (send_errno == EINTR && ++attempts < NRETRIES)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * The other error types depend on whether or not the
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * socket is UDP or TCP. If it is UDP, some errors
8db3b065b4659f593f7b8eaa7c9ca0c3daa4da02Bob Halley * that we expect to be fatal under TCP are merely
38d2d0e9326a2f70b5893302b89a26978b539405Bob Halley * annoying, and are really soft errors.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * However, these soft errors are still returned as
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
cee7525336d4710a64368875d92eb439d4d3efb1Mark Andrews isc__strerror(send_errno, strbuf, sizeof(strbuf));
cee7525336d4710a64368875d92eb439d4d3efb1Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "internal_send: send() %s 0",
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * If we write less than we expected, update counters, poke.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Exactly what we wanted to write. We're done with this
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * entry. Post its completion event.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Caller must ensure that the socket is not locked and no external
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * references exist.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley REQUIRE(sock->fd >= 0 && sock->fd < (int)FD_SETSIZE);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * No one has this socket open, so the watcher doesn't have to be
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * poked, and the socket doesn't have to be locked.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley manager->fdstate[sock->fd] = MANAGER_CLOSE_PENDING;
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley select_poke(manager, sock->fd, SELECT_POKE_CLOSE);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* ISC_PLATFORM_USETHREADS */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * XXX should reset manager->maxfd here
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halleyallocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley sock = isc_mem_get(manager->mctx, sizeof(*sock));
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * set up cmsg buffers
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley cmsgbuflen += cmsg_space(sizeof(struct timeval));
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * set up list of readers and writers to be initially empty
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * initialize the lock
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Initialize readable and writable events
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t),
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR,
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t),
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * This event requires that the various lists be empty, that the reference
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * count be 1, and that the magic number is valid. The other socket bits,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * like the lock, must be initialized as well. The fd associated must be
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * marked as closed, by setting it to -1 on close, or this routine will
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * also close the socket.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Create a new 'type' socket managed by 'manager'. Events
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * will be posted to 'task' and when dispatched 'action' will be
af3459443207253f197cd684567bfea0311ab76dMark Andrews * called with 'arg' as the arg value. The new socket is returned
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * in 'socketp'.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleyisc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Leave a space for stdio to work in.
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence "%s: too many open file descriptors", "socket");
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence * Linux 2.2 (and maybe others) return EINVAL instead of
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence * EAFNOSUPPORT.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "setsockopt(%d, SO_BSDCOMPAT) %s: %s",
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence /* Press on... */
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence isc__strerror(errno, strbuf, sizeof(strbuf));
213a9ec2addc5bcf3b168fe507312e7b25960e0bDavid Lawrence "setsockopt(%d, SO_TIMESTAMP) %s: %s",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley /* Press on... */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* SO_TIMESTAMP */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley if (pf == AF_INET6 && sock->recvcmsgbuflen == 0U) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Warn explicitly because this anomaly can be hidden
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * in usual operation (and unexpectedly appear later).
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley "No buffer available to receive "
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley "IPv6 destination");
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley /* 2292bis */
af3459443207253f197cd684567bfea0311ab76dMark Andrews && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "setsockopt(%d, IPV6_RECVPKTINFO) "
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
38d2d0e9326a2f70b5893302b89a26978b539405Bob Halley "setsockopt(%d, IPV6_PKTINFO) %s: %s",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* IPV6_RECVPKTINFO */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley /* use minimum MTU */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley#endif /* ISC_PLATFORM_HAVEIPV6 */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley#endif /* defined(USE_CMSG) */
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "setsockopt(%d, SO_RCVBUF, %d) %s: %s",
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * Note we don't have to lock the socket like we normally would because
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * there are no external references to it yet.
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Create a new 'type' socket managed by 'manager'. Events
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * will be posted to 'task' and when dispatched 'action' will be
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * called with 'arg' as the arg value. The new socket is returned
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * in 'socketp'.
8db3b065b4659f593f7b8eaa7c9ca0c3daa4da02Bob Halleyisc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley result = allocate_socket(manager, isc_sockettype_fdwatch, &sock);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Note we don't have to lock the socket like we normally would because
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * there are no external references to it yet.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Attach to a socket. Caller must explicitly detach when it is done.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleyisc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Dereference a socket. If this is the last reference to it, clean things
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * up by destroying the socket.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * I/O is possible on a given socket. Schedule an event to this task that
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * will call an internal function to do the I/O. This will charge the
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * task with the I/O operation and let our select loop handler get back
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * to doing something real as fast as possible.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * The socket and manager must be locked before calling this function.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "dispatch_recv: event %p -> task %p",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "dispatch_send: event %p -> task %p",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Dispatch an internal accept event.
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley * Are there any done events left, or were they all canceled
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley * before the manager got the socket lock?
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley sock->references++; /* keep socket around for this internal event */
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley sock->references++; /* keep socket around for this internal event */
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley * Dequeue an item off the given socket's read queue, set the result code
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley * in the done event to the one provided, and send it to the task it was
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * destined for.
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * If the event to be sent is on a list, remove it before sending. If
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * asked to, send and detach from the socket as well.
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * Caller must have the socket locked if the event is attached to the socket.
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellingtonsend_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley isc_task_sendanddetach(&task, (isc_event_t **)dev);
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * See comments for send_recvdone_event() above.
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellington * Caller must have the socket locked if the event is attached to the socket.
e22d03eb45fdc504bca3d6227725d45a3ff7d192Brian Wellingtonsend_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
6e952e42e56e01e4b49d4a41a40a4e8f4cb0e8bfBob Halley isc_task_sendanddetach(&task, (isc_event_t **)dev);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Call accept() on a socket, to get the new file descriptor. The listen
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * socket is used as a prototype to create a new isc_socket_t. The new
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * socket has one outstanding reference. The task receiving the event
86131d8d7aaf1bb8b8bfc7819985d05ea369b708Bob Halley * will be detached from just after the event is delivered.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * On entry to this function, the event delivered is the internal
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * readable event, and the first item on the accept_list should be
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * the done event we want to send. If the list is empty, this is a no-op,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * so just unlock and return.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halleyinternal_accept(isc_task_t *me, isc_event_t *ev) {
b5b97de45a561784bd88fb8fa7e1464a28ad9a44Bob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
b5b97de45a561784bd88fb8fa7e1464a28ad9a44Bob Halley "internal_accept called, locked socket");
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley sock->references--; /* the internal event is done with this socket */
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley * Get the first item off the accept list.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * If it is empty, unlock the socket and return.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Try to accept the new connection. If the accept fails with
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * EAGAIN or EINTR, simply poke the watcher to watch this socket
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * again. Also ignore ECONNRESET, which has been reported to
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * be spuriously returned on Linux 2.2.19 although it is not
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * a documented error for accept(). ECONNABORTED has been
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * reported for Solaris 8. The rest are thrown in not because
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * we have seen them but because they are ignored by other
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * deamons such as BIND 8 and Apache.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley addrlen = sizeof(dev->newsocket->peer_address.type);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley memset(&dev->newsocket->peer_address.type.sa, 0, addrlen);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley fd = accept(sock->fd, &dev->newsocket->peer_address.type.sa,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Leave a space for stdio to work in.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "internal_accept(): "
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "accept() failed to return "
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "remote address");
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley } else if (dev->newsocket->peer_address.type.sa.sa_family !=
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "internal_accept(): "
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "accept() returned peer address "
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "family %u (expected %u)",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley "%s: too many open file descriptors",
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Pull off the done event.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Poke watcher if there are more pending accepts.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * -1 means the new socket didn't happen.
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
c50fd34a4e0e6978f8ca5f6f3ad8545549c3cfeeBob Halley * Save away the remote address
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley socket_log(sock, &dev->newsocket->peer_address, CREATION,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley "accepted connection, new socket %p",
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Fill in the done event details and send it off.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
ce3761f64d3d734cc94605026985898900ecc474Bob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley sock->references--; /* the internal event is done with this socket */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Try to do as much I/O as possible on this socket. There are no
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * limits here, currently.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * read of 0 means the remote end was closed.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Run through the event queue and dispatch all
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * the events with an EOF result code.
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrence select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Find out what socket this is and lock it.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
1ef8965366d91e02a4672c35a187d30aa4a4c72cMark Andrews sock->references--; /* the internal event is done with this socket */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * Try to do as much I/O as possible on this socket. There are no
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley * limits here, currently.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
1ef8965366d91e02a4672c35a187d30aa4a4c72cMark Andrewsinternal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
1ef8965366d91e02a4672c35a187d30aa4a4c72cMark Andrews * Find out what socket this is and lock it.
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley "internal_fdwatch_write: task %p got event %p", me, ev);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
c5839c39bd07c9dd3d4cd598035deb0537098475Bob Halley sock->references--; /* the internal event is done with this socket */
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halleyinternal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews * Find out what socket this is and lock it.
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley "internal_fdwatch_read: task %p got event %p", me, ev);
95c86af1e92dae4ff837a39e7e2dcb7308dd9cceBob Halley more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews sock->references--; /* the internal event is done with this socket */
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrewsprocess_fds(isc_socketmgr_t *manager, int maxfd,
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews * Process read/writes on other fds here. Avoid locking
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews * and unlocking twice if both reads and writes are possible.
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews for (i = 0; i < maxfd; i++) {
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews#endif /* ISC_PLATFORM_USETHREADS */
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews * If we need to close the socket, do it now.
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrence || manager->fdstate[i] == MANAGER_CLOSE_PENDING) {
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews * This is the thread that will loop forever, always in a select or poll
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * When select returns something to do, track down what thread gets to do
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * this I/O and post the event to it.
518be7faab2498c795e6dc9bb25ac10ca38b3a8dMark Andrews * Get the control fd here. This will never change.
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley cc = select(maxfd, &readfds, &writefds, NULL, NULL);
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley "select() %s: %s",
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley } while (cc < 0);
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * Process reads on internal, control fd.
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley "watcher got message %d"
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley " for socket %d"),
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * Nothing to read?
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * Handle shutdown message. We really should
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * jump out of this loop right away, but
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * it doesn't matter if we have to do a little
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * more work first.
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * This is a wakeup on a socket. Look
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley * at the event queue for both read and write,
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * and decide if we need to watch on it now
84c3294183a1cca851ce3f7f33c86772cd57bee1Bob Halley process_fds(manager, maxfd, &readfds, &writefds);
ce3761f64d3d734cc94605026985898900ecc474Bob Halley#endif /* ISC_PLATFORM_USETHREADS */
ce3761f64d3d734cc94605026985898900ecc474Bob Halley * Create a new socket manager.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrenceisc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence REQUIRE(managerp != NULL && *managerp == NULL);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence manager = isc_mem_get(mctx, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_mem_put(mctx, manager, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_mem_put(mctx, manager, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "isc_condition_init() %s",
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Create the special fds that will be used to wake up the
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * select/poll loop when something internal needs to be done.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_mem_put(mctx, manager, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc__strerror(errno, strbuf, sizeof(strbuf));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "pipe() %s: %s",
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence RUNTIME_CHECK(make_nonblock(manager->pipe_fds[0]) == ISC_R_SUCCESS);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#else /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Set up initial state for the select loop
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence FD_SET(manager->pipe_fds[0], &manager->read_fds);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#else /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence memset(manager->fdstate, 0, sizeof(manager->fdstate));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Start up the select/poll thread.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence if (isc_thread_create(watcher, manager, &manager->watcher) !=
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_mem_put(mctx, manager, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "isc_thread_create() %s",
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrenceisc_socketmgr_destroy(isc_socketmgr_t **managerp) {
402b05ddea16c6179fd251e4e740606dd973d593Bob Halley * Destroy a socket manager.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Wait for all sockets to be destroyed.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "sockets exist"));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#else /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Hope all sockets have been destroyed.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "sockets exist"));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Here, poke our select/poll thread. Do this by closing the write
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * half of the pipe, which will send EOF to the read half.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * This is currently a no-op in the non-threaded case.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence select_poke(manager, 0, SELECT_POKE_SHUTDOWN);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Wait for thread to exit.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence if (isc_thread_join(manager->watcher, NULL) != ISC_R_SUCCESS)
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "isc_thread_join() %s",
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence (void)isc_condition_destroy(&manager->shutdown_ok);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence#endif /* ISC_PLATFORM_USETHREADS */
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence for (i = 0; i < (int)FD_SETSIZE; i++)
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence isc_mem_put(mctx, manager, sizeof(*manager));
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrencesocket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence unsigned int flags)
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * We couldn't read all or part of the request right now, so
a41d348e14b0465c6444cdfd2d59f9370fd44fe8Mark Andrews * Attach to socket and to task
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * Enqueue the request. If the socket was previously not being
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence * watched, poke the watcher to start paying attention to it.
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence "socket_recv: event %p -> task %p",
605ae28c5a73ad6c86425dfc0ed1d49652141c67David Lawrence /* fallthrough */
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halleyisc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley unsigned int iocount;
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley iocount = isc_bufferlist_availablecount(buflist);
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley * UDP sockets are always partial read
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley * Move each buffer from the passed in list to our internal one.
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halleyisc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
453603c018a9e7c3ee7726868f27c95798544ed7Bob Halley isc_task_t *task, isc_taskaction_t action, const void *arg)
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
8326257468615966b10820260beb3ee96eee94b5Bob Halley return (isc_socket_recv2(sock, region, minimum, task, dev, 0));
402b05ddea16c6179fd251e4e740606dd973d593Bob Halleyisc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
6f5c11ea91e890e78eaa31a73e309e07f09f0ec0Bob Halley * UDP sockets are always partial read.
6f5c11ea91e890e78eaa31a73e309e07f09f0ec0Bob Halleysocket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
6f5c11ea91e890e78eaa31a73e309e07f09f0ec0Bob Halley isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
6f5c11ea91e890e78eaa31a73e309e07f09f0ec0Bob Halley unsigned int flags)
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (!isc_sockaddr_issitelocal(&dev->address) &&
8326257468615966b10820260beb3ee96eee94b5Bob Halley "pktinfo structure provided, ifindex %u "
8326257468615966b10820260beb3ee96eee94b5Bob Halley * Set the pktinfo index to 0 here, to let the
8326257468615966b10820260beb3ee96eee94b5Bob Halley * kernel decide what interface it should send on.
000027219d9824bdfb0b2c1865ec4d4bc839b631Mark Andrews * We couldn't send all or part of the request right now, so
000027219d9824bdfb0b2c1865ec4d4bc839b631Mark Andrews * queue it unless ISC_SOCKFLAG_NORETRY is set.
345a84c9f1e87c179a6ec9053200a94d5888fa13Bob Halley * Enqueue the request. If the socket was previously
345a84c9f1e87c179a6ec9053200a94d5888fa13Bob Halley * not being watched, poke the watcher to start
345a84c9f1e87c179a6ec9053200a94d5888fa13Bob Halley * paying attention to it.
345a84c9f1e87c179a6ec9053200a94d5888fa13Bob Halley "socket_send: event %p -> task %p",
case DOIO_HARD:
case DOIO_SUCCESS:
if (have_lock)
return (result);
NULL));
return (ISC_R_NOMEMORY);
NULL));
unsigned int iocount;
return (ISC_R_NOMEMORY);
event->n = 0;
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifndef S_ISSOCK
#ifndef S_ISFIFO
#ifndef S_ISFIFO
#ifndef S_ISSOCK
if (active) {
switch (errno) {
goto cleanup;
goto cleanup;
switch (errno) {
case ECONNREFUSED:
case ECONNRESET:
strbuf);
close(s);
#ifdef ISC_PLATFORM_HAVESYSUNH
#ifdef NEED_SECURE_DIRECTORY
char *slash;
#ifdef NEED_SECURE_DIRECTORY
strbuf);
return (result);
return (ISC_R_NOTIMPLEMENTED);
return (ISC_R_FAMILYMISMATCH);
#ifdef AF_UNIX
goto bind_socket;
sizeof(on)) < 0) {
#ifdef AF_UNIX
switch (errno) {
case EACCES:
return (ISC_R_NOPERM);
case EADDRNOTAVAIL:
return (ISC_R_ADDRNOTAVAIL);
case EADDRINUSE:
return (ISC_R_ADDRINUSE);
case EINVAL:
return (ISC_R_BOUND);
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
#ifdef SO_ACCEPTFILTER
#ifdef SO_ACCEPTFILTER
strbuf);
return (ISC_R_FAILURE);
return (ISC_R_SUCCESS);
return (ISC_R_NOTIMPLEMENTED);
if (backlog == 0)
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (result);
if (do_poke)
return (ISC_R_SUCCESS);
int cc;
return (ISC_R_MULTICAST);
sizeof(*dev));
return (ISC_R_NOMEMORY);
if (cc < 0) {
goto queue;
switch (errno) {
#ifdef EHOSTDOWN
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
if (cc == 0) {
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
int cc;
if (errno != 0) {
switch (errno) {
#ifdef EHOSTDOWN
sizeof(peerbuf));
return (result);
goto out;
strbuf);
goto out;
out:
return (result);
if (how == 0)
ev_link);
return (val);
#if defined(IPV6_V6ONLY)
#ifdef IPV6_V6ONLY
#ifndef ISC_PLATFORM_USETHREADS
*maxfd = 0;
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
#ifdef HAVE_LIBXML2
#ifndef ISC_PLATFORM_USETHREADS
sizeof(peerbuf));