if (i > maxfd)
if (fd > maxfd)
void do_listen(connection_attributes *attrs){	address *remote, *local;	int nfd, i, fd, err, ns = -1, maxfd = -1;	struct addrinfo hints, *res = NULL, *ptr;	char hbuf_num[NI_MAXHOST + 1];	char sbuf_num[NI_MAXSERV + 1];	fd_set accept_fdset;	assert(attrs != NULL);	remote = &(attrs->remote_address);	local = &(attrs->local_address);	/* make sure all the preconditions are respected */	assert(local->address == NULL || strlen(local->address) > 0);	assert(local->service != NULL && strlen(local->service) > 0);	assert(remote->address == NULL || strlen(remote->address) > 0);	assert(remote->service == NULL || strlen(remote->service) > 0);	/* initialize accept_fdset */	FD_ZERO(&accept_fdset);		/* setup hints structure to be passed to getaddrinfo */	memset(&hints, 0, sizeof(hints));	connection_attributes_to_addrinfo(&hints, attrs);	hints.ai_flags = AI_PASSIVE;	if (is_flag_set(NUMERIC_MODE) == TRUE)		hints.ai_flags |= AI_NUMERICHOST;	/* get the IP address of the local end of the connection */	err = getaddrinfo(local->address, local->service, &hints, &res);	if (err != 0) 		fatal("forward host lookup failed for local endpoint %s (%s): %s",		      local->address? local->address : "[unspecified]",			  local->service, gai_strerror(err));			/* check the results of getaddrinfo */	assert(res != NULL);	/* Some systems (eg. linux) will bind to both ipv6 AND ipv4 when	 * listening.  Connections will still be accepted from either ipv6 or	 * ipv4 clients (ipv4 will be mapped into ipv6).  However, this means	 * that we MUST bind the ipv6 address ONLY for these hosts.	 *	 * TODO: until we add a configure check to determine if the current	 * host does this double binding, we will just ensure that ipv6	 * sockets are bound first and then attempt to bind the ipv4 ones.  On	 * systems that double bind ipv6/ipv4 the ipv4 bind will simply fail.	 */	res = order_ipv6_first(res);	/* try binding to all of the addresses returned by getaddrinfo */	nfd = 0;		for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {		/* only accept socktypes we can handle */		if (ptr->ai_socktype != SOCK_STREAM && ptr->ai_socktype != SOCK_DGRAM)			continue;		/* sanity check */		assert((attrs->type == UDP_SOCKET && ptr->ai_socktype == SOCK_DGRAM) || 		       (attrs->type == TCP_SOCKET && ptr->ai_socktype == SOCK_STREAM));		/* get the numeric name for this source as a string */		err = getnameinfo(ptr->ai_addr, ptr->ai_addrlen,		        hbuf_num, sizeof(hbuf_num), sbuf_num, 		        sizeof(sbuf_num), NI_NUMERICHOST | NI_NUMERICSERV);		/* this should never happen */		if (err != 0)			fatal("getnameinfo failed: %s", gai_strerror(err));		/* create the socket */		fd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);		if (fd < 0) fatal("cannot create the socket: %s", strerror(errno));#ifdef IPV6_V6ONLY		if (ptr->ai_family == AF_INET6) {			int on = 1;			/* in case of error, we will go on anyway... */			err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));			if (err < 0) perror("error with sockopt IPV6_V6ONLY");		}#endif 			/* set the reuse address socket option */		if (!(is_flag_set(DONT_REUSE_ADDR) == TRUE)) {			int on = 1;			/* in case of error, we will go on anyway... */			err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));			if (err < 0) perror("error with sockopt SO_REUSEADDR");		}		/* bind to the local address */		err = bind(fd, ptr->ai_addr, ptr->ai_addrlen);		if (err != 0) {			warn("bind to source %s (%s) failed: %s",			     hbuf_num, sbuf_num, strerror(errno));			close(fd);			continue;		}		/* for stream based sockets, the socket needs to listen for incoming		 * connections. the backlog parameter is set to 5 for backward		 * compatibility (it seems that at least some BSD-derived system limit		 * the backlog parameter to this value). */		if (ptr->ai_socktype == SOCK_STREAM) {			err = listen(fd, 5);			if (err != 0)				fatal("cannot listen on %s (%s): %s",				      hbuf_num, sbuf_num, strerror(errno));		}		if (is_flag_set(VERBOSE_MODE) == TRUE)			warn("listening on %s (%s) ...",			      hbuf_num, sbuf_num, strerror(errno));		/* add fd to accept_fdset */		FD_SET(fd, &accept_fdset);		maxfd = MAX(maxfd, fd);		nfd++;	}	freeaddrinfo(res);		if (nfd == 0)		fatal("failed to bind to any local addr/port");	/* enter into the accept loop */ 	for (;;) {		fd_set tmp_ap_fdset;		struct sockaddr_storage dest;		socklen_t destlen;		char c_hbuf_rev[NI_MAXHOST + 1];		char c_hbuf_num[NI_MAXHOST + 1];		char c_sbuf_num[NI_MAXSERV + 1];		/* make a copy of accept_fdset before passing to select */		memcpy(&tmp_ap_fdset, &accept_fdset, sizeof(fd_set));		/* wait for an incoming connection */		err = select(maxfd + 1, &tmp_ap_fdset, NULL, NULL, NULL);				if (err < 0) {			if (errno == EINTR) continue;			fatal("select error: %s", strerror(errno));		}		/* find the ready filedescriptor */		for (i = 0; i <= maxfd && !FD_ISSET(i, &tmp_ap_fdset); ++i)			;		/* if none were ready, loop to select again */		if (i > maxfd)			continue;		destlen = sizeof(dest);			/* for stream sockets we can simply accept a new connection, while for 		 * dgram sockets we have to use MSG_PEEK to determine the sender */		if (attrs->type == TCP_SOCKET) {			ns = accept(i, (struct sockaddr *)&dest, &destlen);			if (ns < 0)				fatal("cannot accept connection: %s", strerror(errno));		} else {			err = recvfrom(i, NULL, 0, MSG_PEEK,			        (struct sockaddr*)&dest, &destlen);			if (err < 0)				fatal("cannot recv from socket: %s", strerror(errno));			ns = dup(i);			if (ns < 0)				fatal("cannot duplicate file descriptor %d: %s",				      i, strerror(errno));		}		/* get names for each end of the connection */		if (is_flag_set(VERBOSE_MODE) == TRUE) {			struct sockaddr_storage src;			socklen_t srclen = sizeof(src);			/* find out what address the connection was to */			err = getsockname(ns, (struct sockaddr *)&src, &srclen);			if (err < 0)				fatal("getsockname failed: %s", strerror(errno));			/* get the numeric name for this source as a string */			err = getnameinfo((struct sockaddr *)&src, srclen,			        hbuf_num, sizeof(hbuf_num), NULL, 0,			        NI_NUMERICHOST | NI_NUMERICSERV);			/* this should never happen */			if (err != 0)				fatal("getnameinfo failed: %s", gai_strerror(err));			/* get the numeric name for this client as a string */			err = getnameinfo((struct sockaddr *)&dest, destlen,			        c_hbuf_num, sizeof(c_hbuf_num), c_sbuf_num, 					  sizeof(c_sbuf_num), NI_NUMERICHOST | NI_NUMERICSERV);			if (err != 0)				fatal("getnameinfo failed: %s", gai_strerror(err));			/* get the real name for this client as a string */			if (is_flag_set(NUMERIC_MODE) == FALSE) {				err = getnameinfo((struct sockaddr *)&dest, destlen,					c_hbuf_rev, sizeof(c_hbuf_rev), NULL, 0, 0);				if (err != 0)					warn("inverse lookup failed for %s: %s",					      c_hbuf_num, gai_strerror(err));			} else {				err = 1;			}			if (err != 0) {				strcpy(c_hbuf_rev, c_hbuf_num);			}		}		/* check if connections from this client are allowed */		if ((remote == NULL) ||		    (remote->address == NULL && remote->service == NULL) ||		    (is_allowed((struct sockaddr*)&dest, remote, attrs) == TRUE)) {			if (attrs->type == UDP_SOCKET) {				/* connect the socket to ensure we only talk with this client */				err = connect(ns, (struct sockaddr*)&dest, destlen);				if (err != 0)					fatal("cannot connect datagram socket: %s",					      strerror(errno));			}			if (is_flag_set(VERBOSE_MODE) == TRUE) {				warn("connect to %s (%s) from %s [%s] %s",				      hbuf_num, sbuf_num, c_hbuf_rev, c_hbuf_num, c_sbuf_num);			}			break;		} else {			if (attrs->type == UDP_SOCKET) {				/* the connection wasn't accepted - remove the queued packet */				recvfrom(ns, NULL, 0, 0, NULL, 0);			}			close(ns);			ns = -1;			if (is_flag_set(VERBOSE_MODE) == TRUE) {				warn("refused connect to %s (%s) from %s [%s] %s",					hbuf_num, sbuf_num, c_hbuf_rev, c_hbuf_num, c_sbuf_num);			}		}	}	/* close the listening sockets */	for (i = 0; i <= maxfd; ++i) {		if (FD_ISSET(i, &accept_fdset) != 0) close(i);	}	/* create io_streams for the local and remote streams */	ios_assign_stdio(&(attrs->local_stream));	ios_assign_socket(&(attrs->remote_stream), ns, attrs->type);}