xref: /illumos-gate/usr/src/lib/libresolv2/common/isc/ev_connects.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
17c478bd9Sstevel@tonic-gate /*
2*9525b14bSRao Shoaib  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
37c478bd9Sstevel@tonic-gate  * Copyright (c) 1995-1999 by Internet Software Consortium
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software for any
67c478bd9Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
77c478bd9Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
87c478bd9Sstevel@tonic-gate  *
9*9525b14bSRao Shoaib  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*9525b14bSRao Shoaib  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*9525b14bSRao Shoaib  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12*9525b14bSRao Shoaib  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*9525b14bSRao Shoaib  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*9525b14bSRao Shoaib  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*9525b14bSRao Shoaib  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate /* ev_connects.c - implement asynch connect/accept for the eventlib
197c478bd9Sstevel@tonic-gate  * vix 16sep96 [initial]
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #include "port_before.h"
237c478bd9Sstevel@tonic-gate #include "fd_setsize.h"
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/socket.h>
277c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <unistd.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <isc/eventlib.h>
327c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
337c478bd9Sstevel@tonic-gate #include "eventlib_p.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "port_after.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* Macros. */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define GETXXXNAME(f, s, sa, len) ( \
407c478bd9Sstevel@tonic-gate 	(f((s), (&sa), (&len)) >= 0) ? 0 : \
417c478bd9Sstevel@tonic-gate 		(errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \
427c478bd9Sstevel@tonic-gate 			memset(&(sa), 0, sizeof (sa)), \
437c478bd9Sstevel@tonic-gate 			(len) = sizeof (sa), \
447c478bd9Sstevel@tonic-gate 			(sa).sa_family = AF_UNIX, \
457c478bd9Sstevel@tonic-gate 			0 \
467c478bd9Sstevel@tonic-gate 		) \
477c478bd9Sstevel@tonic-gate 	)
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /* Forward. */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static void	listener(evContext ctx, void *uap, int fd, int evmask);
527c478bd9Sstevel@tonic-gate static void	connector(evContext ctx, void *uap, int fd, int evmask);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* Public. */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate int
evListen(evContext opaqueCtx,int fd,int maxconn,evConnFunc func,void * uap,evConnID * id)577c478bd9Sstevel@tonic-gate evListen(evContext opaqueCtx, int fd, int maxconn,
587c478bd9Sstevel@tonic-gate 	 evConnFunc func, void *uap, evConnID *id)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
617c478bd9Sstevel@tonic-gate 	evConn *new;
627c478bd9Sstevel@tonic-gate 	int mode;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	OKNEW(new);
657c478bd9Sstevel@tonic-gate 	new->flags = EV_CONN_LISTEN;
66*9525b14bSRao Shoaib 	OKFREE(mode = fcntl(fd, F_GETFL, NULL), new);	/*%< side effect: validate fd. */
677c478bd9Sstevel@tonic-gate 	/*
687c478bd9Sstevel@tonic-gate 	 * Remember the nonblocking status.  We assume that either evSelectFD
697c478bd9Sstevel@tonic-gate 	 * has not been done to this fd, or that if it has then the caller
707c478bd9Sstevel@tonic-gate 	 * will evCancelConn before they evDeselectFD.  If our assumptions
717c478bd9Sstevel@tonic-gate 	 * are not met, then we might restore the old nonblocking status
727c478bd9Sstevel@tonic-gate 	 * incorrectly.
737c478bd9Sstevel@tonic-gate 	 */
747c478bd9Sstevel@tonic-gate 	if ((mode & PORT_NONBLOCK) == 0) {
757c478bd9Sstevel@tonic-gate #ifdef USE_FIONBIO_IOCTL
767c478bd9Sstevel@tonic-gate 		int on = 1;
77*9525b14bSRao Shoaib 		OKFREE(ioctl(fd, FIONBIO, (char *)&on), new);
787c478bd9Sstevel@tonic-gate #else
79*9525b14bSRao Shoaib 		OKFREE(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK), new);
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate 		new->flags |= EV_CONN_BLOCK;
827c478bd9Sstevel@tonic-gate 	}
83*9525b14bSRao Shoaib 	OKFREE(listen(fd, maxconn), new);
847c478bd9Sstevel@tonic-gate 	if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){
857c478bd9Sstevel@tonic-gate 		int save = errno;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 		FREE(new);
887c478bd9Sstevel@tonic-gate 		errno = save;
897c478bd9Sstevel@tonic-gate 		return (-1);
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 	new->flags |= EV_CONN_SELECTED;
927c478bd9Sstevel@tonic-gate 	new->func = func;
937c478bd9Sstevel@tonic-gate 	new->uap = uap;
947c478bd9Sstevel@tonic-gate 	new->fd = fd;
957c478bd9Sstevel@tonic-gate 	if (ctx->conns != NULL)
967c478bd9Sstevel@tonic-gate 		ctx->conns->prev = new;
977c478bd9Sstevel@tonic-gate 	new->prev = NULL;
987c478bd9Sstevel@tonic-gate 	new->next = ctx->conns;
997c478bd9Sstevel@tonic-gate 	ctx->conns = new;
1007c478bd9Sstevel@tonic-gate 	if (id)
1017c478bd9Sstevel@tonic-gate 		id->opaque = new;
1027c478bd9Sstevel@tonic-gate 	return (0);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate int
evConnect(evContext opaqueCtx,int fd,const void * ra,int ralen,evConnFunc func,void * uap,evConnID * id)1067c478bd9Sstevel@tonic-gate evConnect(evContext opaqueCtx, int fd, const void *ra, int ralen,
1077c478bd9Sstevel@tonic-gate 	  evConnFunc func, void *uap, evConnID *id)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1107c478bd9Sstevel@tonic-gate 	evConn *new;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	OKNEW(new);
1137c478bd9Sstevel@tonic-gate 	new->flags = 0;
1147c478bd9Sstevel@tonic-gate 	/* Do the select() first to get the socket into nonblocking mode. */
1157c478bd9Sstevel@tonic-gate 	if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL,
1167c478bd9Sstevel@tonic-gate 		       connector, new, &new->file) < 0) {
1177c478bd9Sstevel@tonic-gate 		int save = errno;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 		FREE(new);
1207c478bd9Sstevel@tonic-gate 		errno = save;
1217c478bd9Sstevel@tonic-gate 		return (-1);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 	new->flags |= EV_CONN_SELECTED;
1247c478bd9Sstevel@tonic-gate 	if (connect(fd, ra, ralen) < 0 &&
1257c478bd9Sstevel@tonic-gate 	    errno != EWOULDBLOCK &&
1267c478bd9Sstevel@tonic-gate 	    errno != EAGAIN &&
1277c478bd9Sstevel@tonic-gate 	    errno != EINPROGRESS) {
1287c478bd9Sstevel@tonic-gate 		int save = errno;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 		(void) evDeselectFD(opaqueCtx, new->file);
1317c478bd9Sstevel@tonic-gate 		FREE(new);
1327c478bd9Sstevel@tonic-gate 		errno = save;
1337c478bd9Sstevel@tonic-gate 		return (-1);
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 	/* No error, or EWOULDBLOCK.  select() tells when it's ready. */
1367c478bd9Sstevel@tonic-gate 	new->func = func;
1377c478bd9Sstevel@tonic-gate 	new->uap = uap;
1387c478bd9Sstevel@tonic-gate 	new->fd = fd;
1397c478bd9Sstevel@tonic-gate 	if (ctx->conns != NULL)
1407c478bd9Sstevel@tonic-gate 		ctx->conns->prev = new;
1417c478bd9Sstevel@tonic-gate 	new->prev = NULL;
1427c478bd9Sstevel@tonic-gate 	new->next = ctx->conns;
1437c478bd9Sstevel@tonic-gate 	ctx->conns = new;
1447c478bd9Sstevel@tonic-gate 	if (id)
1457c478bd9Sstevel@tonic-gate 		id->opaque = new;
1467c478bd9Sstevel@tonic-gate 	return (0);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate int
evCancelConn(evContext opaqueCtx,evConnID id)1507c478bd9Sstevel@tonic-gate evCancelConn(evContext opaqueCtx, evConnID id) {
1517c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1527c478bd9Sstevel@tonic-gate 	evConn *this = id.opaque;
1537c478bd9Sstevel@tonic-gate 	evAccept *acc, *nxtacc;
1547c478bd9Sstevel@tonic-gate 	int mode;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_SELECTED) != 0)
1577c478bd9Sstevel@tonic-gate 		(void) evDeselectFD(opaqueCtx, this->file);
1587c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_BLOCK) != 0) {
1597c478bd9Sstevel@tonic-gate 		mode = fcntl(this->fd, F_GETFL, NULL);
1607c478bd9Sstevel@tonic-gate 		if (mode == -1) {
1617c478bd9Sstevel@tonic-gate 			if (errno != EBADF)
1627c478bd9Sstevel@tonic-gate 				return (-1);
1637c478bd9Sstevel@tonic-gate 		} else {
1647c478bd9Sstevel@tonic-gate #ifdef USE_FIONBIO_IOCTL
165*9525b14bSRao Shoaib 			int off = 0;
166*9525b14bSRao Shoaib 			OK(ioctl(this->fd, FIONBIO, (char *)&off));
1677c478bd9Sstevel@tonic-gate #else
168*9525b14bSRao Shoaib 			OK(fcntl(this->fd, F_SETFL, mode & ~PORT_NONBLOCK));
1697c478bd9Sstevel@tonic-gate #endif
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	/* Unlink from ctx->conns. */
1747c478bd9Sstevel@tonic-gate 	if (this->prev != NULL)
1757c478bd9Sstevel@tonic-gate 		this->prev->next = this->next;
1767c478bd9Sstevel@tonic-gate 	else
1777c478bd9Sstevel@tonic-gate 		ctx->conns = this->next;
1787c478bd9Sstevel@tonic-gate 	if (this->next != NULL)
1797c478bd9Sstevel@tonic-gate 		this->next->prev = this->prev;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/*
1827c478bd9Sstevel@tonic-gate 	 * Remove `this' from the ctx->accepts list (zero or more times).
1837c478bd9Sstevel@tonic-gate 	 */
1847c478bd9Sstevel@tonic-gate 	for (acc = HEAD(ctx->accepts), nxtacc = NULL;
1857c478bd9Sstevel@tonic-gate 	     acc != NULL;
1867c478bd9Sstevel@tonic-gate 	     acc = nxtacc)
1877c478bd9Sstevel@tonic-gate 	{
1887c478bd9Sstevel@tonic-gate 		nxtacc = NEXT(acc, link);
1897c478bd9Sstevel@tonic-gate 		if (acc->conn == this) {
1907c478bd9Sstevel@tonic-gate 			UNLINK(ctx->accepts, acc, link);
1917c478bd9Sstevel@tonic-gate 			close(acc->fd);
1927c478bd9Sstevel@tonic-gate 			FREE(acc);
1937c478bd9Sstevel@tonic-gate 		}
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	/* Wrap up and get out. */
1977c478bd9Sstevel@tonic-gate 	FREE(this);
1987c478bd9Sstevel@tonic-gate 	return (0);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
evHold(evContext opaqueCtx,evConnID id)2017c478bd9Sstevel@tonic-gate int evHold(evContext opaqueCtx, evConnID id) {
2027c478bd9Sstevel@tonic-gate 	evConn *this = id.opaque;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_LISTEN) == 0) {
2057c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2067c478bd9Sstevel@tonic-gate 		return (-1);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_SELECTED) == 0)
2097c478bd9Sstevel@tonic-gate 		return (0);
2107c478bd9Sstevel@tonic-gate 	this->flags &= ~EV_CONN_SELECTED;
2117c478bd9Sstevel@tonic-gate 	return (evDeselectFD(opaqueCtx, this->file));
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
evUnhold(evContext opaqueCtx,evConnID id)2147c478bd9Sstevel@tonic-gate int evUnhold(evContext opaqueCtx, evConnID id) {
2157c478bd9Sstevel@tonic-gate 	evConn *this = id.opaque;
2167c478bd9Sstevel@tonic-gate 	int ret;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_LISTEN) == 0) {
2197c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2207c478bd9Sstevel@tonic-gate 		return (-1);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	if ((this->flags & EV_CONN_SELECTED) != 0)
2237c478bd9Sstevel@tonic-gate 		return (0);
2247c478bd9Sstevel@tonic-gate 	ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this,
2257c478bd9Sstevel@tonic-gate 			 &this->file);
2267c478bd9Sstevel@tonic-gate 	if (ret == 0)
2277c478bd9Sstevel@tonic-gate 		this->flags |= EV_CONN_SELECTED;
2287c478bd9Sstevel@tonic-gate 	return (ret);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate int
evTryAccept(evContext opaqueCtx,evConnID id,int * sys_errno)2327c478bd9Sstevel@tonic-gate evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) {
2337c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
2347c478bd9Sstevel@tonic-gate 	evConn *conn = id.opaque;
2357c478bd9Sstevel@tonic-gate 	evAccept *new;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if ((conn->flags & EV_CONN_LISTEN) == 0) {
2387c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2397c478bd9Sstevel@tonic-gate 		return (-1);
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 	OKNEW(new);
2427c478bd9Sstevel@tonic-gate 	new->conn = conn;
2437c478bd9Sstevel@tonic-gate 	new->ralen = sizeof new->ra;
2447c478bd9Sstevel@tonic-gate 	new->fd = accept(conn->fd, &new->ra.sa, &new->ralen);
2457c478bd9Sstevel@tonic-gate 	if (new->fd > ctx->highestFD) {
2467c478bd9Sstevel@tonic-gate 		close(new->fd);
2477c478bd9Sstevel@tonic-gate 		new->fd = -1;
2487c478bd9Sstevel@tonic-gate 		new->ioErrno = ENOTSOCK;
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 	if (new->fd >= 0) {
2517c478bd9Sstevel@tonic-gate 		new->lalen = sizeof new->la;
2527c478bd9Sstevel@tonic-gate 		if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) {
2537c478bd9Sstevel@tonic-gate 			new->ioErrno = errno;
2547c478bd9Sstevel@tonic-gate 			(void) close(new->fd);
2557c478bd9Sstevel@tonic-gate 			new->fd = -1;
2567c478bd9Sstevel@tonic-gate 		} else
2577c478bd9Sstevel@tonic-gate 			new->ioErrno = 0;
2587c478bd9Sstevel@tonic-gate 	} else {
2597c478bd9Sstevel@tonic-gate 		new->ioErrno = errno;
2607c478bd9Sstevel@tonic-gate 		if (errno == EAGAIN || errno == EWOULDBLOCK) {
2617c478bd9Sstevel@tonic-gate 			FREE(new);
2627c478bd9Sstevel@tonic-gate 			return (-1);
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 	INIT_LINK(new, link);
2667c478bd9Sstevel@tonic-gate 	APPEND(ctx->accepts, new, link);
2677c478bd9Sstevel@tonic-gate 	*sys_errno = new->ioErrno;
2687c478bd9Sstevel@tonic-gate 	return (0);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate /* Private. */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate static void
listener(evContext opaqueCtx,void * uap,int fd,int evmask)2747c478bd9Sstevel@tonic-gate listener(evContext opaqueCtx, void *uap, int fd, int evmask) {
2757c478bd9Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
2767c478bd9Sstevel@tonic-gate 	evConn *conn = uap;
2777c478bd9Sstevel@tonic-gate 	union {
2787c478bd9Sstevel@tonic-gate 		struct sockaddr    sa;
2797c478bd9Sstevel@tonic-gate 		struct sockaddr_in in;
2807c478bd9Sstevel@tonic-gate #ifndef NO_SOCKADDR_UN
2817c478bd9Sstevel@tonic-gate 		struct sockaddr_un un;
2827c478bd9Sstevel@tonic-gate #endif
2837c478bd9Sstevel@tonic-gate 	} la, ra;
2847c478bd9Sstevel@tonic-gate 	int new;
2857c478bd9Sstevel@tonic-gate 	ISC_SOCKLEN_T lalen = 0, ralen;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	REQUIRE((evmask & EV_READ) != 0);
2887c478bd9Sstevel@tonic-gate 	ralen = sizeof ra;
2897c478bd9Sstevel@tonic-gate 	new = accept(fd, &ra.sa, &ralen);
2907c478bd9Sstevel@tonic-gate 	if (new > ctx->highestFD) {
2917c478bd9Sstevel@tonic-gate 		close(new);
2927c478bd9Sstevel@tonic-gate 		new = -1;
2937c478bd9Sstevel@tonic-gate 		errno = ENOTSOCK;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 	if (new >= 0) {
2967c478bd9Sstevel@tonic-gate 		lalen = sizeof la;
2977c478bd9Sstevel@tonic-gate 		if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) {
2987c478bd9Sstevel@tonic-gate 			int save = errno;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 			(void) close(new);
3017c478bd9Sstevel@tonic-gate 			errno = save;
3027c478bd9Sstevel@tonic-gate 			new = -1;
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 	} else if (errno == EAGAIN || errno == EWOULDBLOCK)
3057c478bd9Sstevel@tonic-gate 		return;
3067c478bd9Sstevel@tonic-gate 	(*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate static void
connector(evContext opaqueCtx,void * uap,int fd,int evmask)3107c478bd9Sstevel@tonic-gate connector(evContext opaqueCtx, void *uap, int fd, int evmask) {
3117c478bd9Sstevel@tonic-gate 	evConn *conn = uap;
3127c478bd9Sstevel@tonic-gate 	union {
3137c478bd9Sstevel@tonic-gate 		struct sockaddr    sa;
3147c478bd9Sstevel@tonic-gate 		struct sockaddr_in in;
3157c478bd9Sstevel@tonic-gate #ifndef NO_SOCKADDR_UN
3167c478bd9Sstevel@tonic-gate 		struct sockaddr_un un;
3177c478bd9Sstevel@tonic-gate #endif
3187c478bd9Sstevel@tonic-gate 	} la, ra;
3197c478bd9Sstevel@tonic-gate 	ISC_SOCKLEN_T lalen, ralen;
320*9525b14bSRao Shoaib #ifndef NETREAD_BROKEN
3217c478bd9Sstevel@tonic-gate 	char buf[1];
322*9525b14bSRao Shoaib #endif
3237c478bd9Sstevel@tonic-gate 	void *conn_uap;
3247c478bd9Sstevel@tonic-gate 	evConnFunc conn_func;
3257c478bd9Sstevel@tonic-gate 	evConnID id;
3267c478bd9Sstevel@tonic-gate 	int socket_errno = 0;
3277c478bd9Sstevel@tonic-gate 	ISC_SOCKLEN_T optlen;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	UNUSED(evmask);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	lalen = sizeof la;
3327c478bd9Sstevel@tonic-gate 	ralen = sizeof ra;
3337c478bd9Sstevel@tonic-gate 	conn_uap = conn->uap;
3347c478bd9Sstevel@tonic-gate 	conn_func = conn->func;
3357c478bd9Sstevel@tonic-gate 	id.opaque = conn;
3367c478bd9Sstevel@tonic-gate #ifdef SO_ERROR
3377c478bd9Sstevel@tonic-gate 	optlen = sizeof socket_errno;
3387c478bd9Sstevel@tonic-gate 	if (fd < 0 &&
3397c478bd9Sstevel@tonic-gate 	    getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno,
3407c478bd9Sstevel@tonic-gate 		       &optlen) < 0)
3417c478bd9Sstevel@tonic-gate 		socket_errno = errno;
3427c478bd9Sstevel@tonic-gate 	else
3437c478bd9Sstevel@tonic-gate 		errno = socket_errno;
3447c478bd9Sstevel@tonic-gate #endif
3457c478bd9Sstevel@tonic-gate 	if (evCancelConn(opaqueCtx, id) < 0 ||
3467c478bd9Sstevel@tonic-gate 	    socket_errno ||
3477c478bd9Sstevel@tonic-gate #ifdef NETREAD_BROKEN
3487c478bd9Sstevel@tonic-gate 	    0 ||
3497c478bd9Sstevel@tonic-gate #else
3507c478bd9Sstevel@tonic-gate 	    read(fd, buf, 0) < 0 ||
3517c478bd9Sstevel@tonic-gate #endif
3527c478bd9Sstevel@tonic-gate 	    GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 ||
3537c478bd9Sstevel@tonic-gate 	    GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) {
3547c478bd9Sstevel@tonic-gate 		int save = errno;
3557c478bd9Sstevel@tonic-gate 
356*9525b14bSRao Shoaib 		(void) close(fd);	/*%< XXX closing caller's fd */
3577c478bd9Sstevel@tonic-gate 		errno = save;
3587c478bd9Sstevel@tonic-gate 		fd = -1;
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 	(*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen);
3617c478bd9Sstevel@tonic-gate }
362*9525b14bSRao Shoaib 
363*9525b14bSRao Shoaib /*! \file */
364