numeric_mode    = is_flag_set(NUMERIC_MODE); verbose_mode    = is_flag_set(VERBOSE_MODE);
numeric_mode      = is_flag_set(NUMERIC_MODE); verbose_mode      = is_flag_set(VERBOSE_MODE); very_verbose_mode = is_flag_set(VERY_VERBOSE_MODE);
void do_listen_continuous(const connection_attributes* attrs,                          listen_callback callback, void* cdata, int max_accept){	const address *remote, *local;	int nfd, i, fd, err, maxfd = -1;	struct addrinfo hints, *res = NULL, *ptr;	bool numeric_mode      = FALSE;	bool verbose_mode      = FALSE;#ifdef ENABLE_IPV6	bool set_ipv6_only     = FALSE;	bool bound_ipv6_any    = FALSE;#endif	struct bound_socket_t* bound_sockets = NULL;	fd_set accept_fdset;	char name_buf[AI_STR_SIZE];	/* make sure that the arguments are correct */	assert(attrs != NULL);	assert(callback != NULL);		/* setup the addresses of the two connection endpoints */	remote = ca_remote_address(attrs);	local  = ca_local_address(attrs);	/* 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);	/* if max_accept is 0, just return */	if (max_accept == 0)		return;	/* setup flags */	numeric_mode    = is_flag_set(NUMERIC_MODE);	verbose_mode    = is_flag_set(VERBOSE_MODE);		/* initialize accept_fdset */	FD_ZERO(&accept_fdset);		/* setup hints structure to be passed to getaddrinfo */	memset(&hints, 0, sizeof(hints));	ca_to_addrinfo(&hints, attrs);	hints.ai_flags = AI_PASSIVE;	if (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);#ifdef ENABLE_IPV6	/* 	 * Some systems (notably Linux) with a shared stack for ipv6 and ipv4, 	 * have a broken bind(2) implementation. In these systems, binding an 	 * ipv6 socket to ipv6_addr_any (::) will also bind the socket to	 * the ipv4 unspecified address (0.0.0.0).	 * 	 * So when listening on ipv6_addr_any (::) accept(2) will return also	 * ipv4 connection attemptes, as ipv4 mapped ipv6 addresses.	 *	 * This is a problem, since when called with AF_UNSPEC and AI_PASSIVE, 	 * getaddrinfo will return results for both ipv6 AND ipv4, but if we 	 * try to bind on the ipv4 unspecified address (0.0.0.0) AFTER we have 	 * bound our socket to ipv6_addr_any (::), the syscall bind(2) will 	 * fail and return -1, setting errno to EADDRINUSE.	 *	 * The following algorithm is used to work around this error to some	 * degree:	 *	 * Ensure binds to IPv6 addresses are attempted before IPv4 addresses.	 * On broken systems where IPV6_V6ONLY is not defined or the setsockopt	 * fails:	 * 	 *   - Keep track of whether an IPv6 socket has been bound to 	 *     in6_addr_any.	 *   - If a bind to IPv4 fails with EADDRINUSE and an IPv6 socket	 *     has been bound, then just ignore the error.	 */	/* 	 * TODO: instead of reordering the results, just loop through the	 * results twice - once for ipv6 then for the rest.	 */	res = order_ipv6_first(res);#endif	/* try binding to all of the addresses returned by getaddrinfo */	nfd = 0;	for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {		/* only accept results we can handle */		if (skip_address(ptr) == TRUE) continue;				/* create the socket */		fd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);		if (fd < 0) {			/* ignore this address if it is not supported */			if (unsupported_sock_error(errno))				continue;			fatal(_("cannot create the socket: %s"),			      strerror(errno));		}#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY)		if (ptr->ai_family == PF_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)				warn(_("error with sockopt IPV6_V6ONLY"));			else				set_ipv6_only = TRUE;		}#endif 		/* setup configurable socket options */		set_sockopts(attrs, fd, ptr);			/* get the numeric name for this source address */		getnameinfo_ex(ptr->ai_addr, ptr->ai_addrlen, name_buf, 		               sizeof(name_buf), TRUE);		/* bind to the local address */		err = bind(fd, ptr->ai_addr, ptr->ai_addrlen);		if (err != 0) {#ifdef ENABLE_IPV6			/* suppress ADDRINUSE error for systems that double			 * bind ipv6 and ipv4 and pretend it succeeded */			if (errno == EADDRINUSE &&			    ptr->ai_family == PF_INET &&			    set_ipv6_only == FALSE &&			    bound_ipv6_any == TRUE)			{				if (verbose_mode == TRUE)					warn(_("listening on %s ..."),name_buf);				close(fd);				continue;			}#endif			warn(_("bind to source %s failed: %s"),			     name_buf, strerror(errno));			close(fd);			continue;		}		/* for stream based sockets, we need 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"),				      name_buf, strerror(errno));		}		if (verbose_mode == TRUE)			warn(_("listening on %s ..."), name_buf);#ifdef ENABLE_IPV6		/* check if this was an IPv6 socket bound to IN6_ADDR_ANY */		if (ptr->ai_family == PF_INET6 &&		    memcmp(&((struct sockaddr_in6*)(ptr->ai_addr))->sin6_addr,		           &in6addr_any, sizeof(struct in6_addr)) == 0)		{			bound_ipv6_any = TRUE;		}#endif		/* add fd to bound_sockets (just add to the head of the list) */		bound_sockets =	add_bound_socket(bound_sockets, fd, 				                 ptr->ai_socktype);		/* 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 timeval tv, *tvp = NULL;		struct sockaddr_storage dest;		socklen_t destlen;		int ns, socktype;		char c_name_buf[AI_STR_SIZE];		/* make a copy of accept_fdset before passing to select */		memcpy(&tmp_ap_fdset, &accept_fdset, sizeof(fd_set));		/* setup timeout */		if (ca_connect_timeout(attrs) > 0) {			tv.tv_sec = (time_t)ca_connect_timeout(attrs);			tv.tv_usec = 0;			tvp = &tv;		}		/* wait for an incoming connection */		err = select(maxfd + 1, &tmp_ap_fdset, NULL, NULL, tvp);		if (err == 0)			fatal(_("connection timed out"));				if (err < 0) {			if (errno == EINTR) continue;			fatal(_("select error: %s"), strerror(errno));		}		/* find the ready filedescriptor */		for (fd = 0; fd <= maxfd && !FD_ISSET(fd, &tmp_ap_fdset); ++fd)			;		/* if none were ready, loop to select again */		if (fd > maxfd)			continue;		/* find socket type in bound_sockets */		socktype = find_bound_socket(bound_sockets, fd);		destlen = sizeof(dest);			/* for stream sockets we accept a new connection, whereas for		 * dgram sockets we use MSG_PEEK to determine the sender */		if (socktype == SOCK_STREAM) {			ns = accept(fd, (struct sockaddr *)&dest, &destlen);			if (ns < 0)				fatal(_("accept failed: %s"),				      strerror(errno));		} else {			/* this is checked when binding listen sockets */			assert(socktype == SOCK_DGRAM);			err = recvfrom(fd, NULL, 0, MSG_PEEK,			               (struct sockaddr*)&dest, &destlen);			if (err < 0)				fatal(_("recvfrom failed: %s"),				      strerror(errno));			ns = dup(fd);			if (ns < 0)				fatal(_("dup failed: %s"), strerror(errno));		}		/* get names for each end of the connection */		if (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 */			getnameinfo_ex((struct sockaddr *)&src, srclen,			               name_buf, sizeof(name_buf), TRUE);			/* get the name for this client */			getnameinfo_ex((struct sockaddr *)&dest, destlen,			               c_name_buf, sizeof(c_name_buf),				       numeric_mode);		}		/* 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 (socktype == SOCK_DGRAM) {				/* connect the socket to ensure we only talk				 * with this client */				err = connect(ns, (struct sockaddr*)&dest, 				              destlen);				if (err != 0)					fatal(_("cannot failed on "					      "datagram socket: %s"),					      strerror(errno));			}			if (verbose_mode == TRUE) {				warn(_("connect to %s from %s"),				     name_buf, c_name_buf);			}			callback(ns, socktype, cdata);			if (max_accept > 0 && --max_accept == 0)				break;		} else {			if (socktype == SOCK_DGRAM) {				/* the connection wasn't accepted - 				 * remove the queued packet */				recvfrom(ns, NULL, 0, 0, NULL, 0);			}			close(ns);			if (verbose_mode == TRUE) {				warn(_("refused connect to %s from %s"),				     name_buf, c_name_buf);			}		}	}	/* close the listening sockets */	for (i = 0; i <= maxfd; ++i) {		if (FD_ISSET(i, &accept_fdset) != 0) close(i);	}	/* free the bound_socket list */	destroy_bound_sockets(bound_sockets);}