assert(attrs != NULL);
void do_connect(connection_attributes *attrs){	address *remote, *local;	int err, fd = -1;	struct addrinfo hints, *res = NULL, *ptr;	bool connect_attempted = FALSE;	bool numeric_mode      = FALSE;	bool verbose_mode      = FALSE;	char hbuf_rev[NI_MAXHOST + 1];	char hbuf_num[NI_MAXHOST + 1];	char sbuf_rev[NI_MAXSERV + 1];	char sbuf_num[NI_MAXSERV + 1];	/* make sure all the preconditions are respected */	assert(attrs != NULL);	assert(remote->address != NULL && strlen(remote->address) > 0);	assert(remote->service != NULL && strlen(remote->service) > 0);	assert(local->address == NULL || strlen(local->address) > 0);	assert(local->service == NULL || strlen(local->service) > 0);	/* setup flags */	numeric_mode      = is_flag_set(NUMERIC_MODE);	verbose_mode      = is_flag_set(VERBOSE_MODE);		/* setup the addresses of the two connection endpoints */	remote = &(attrs->remote_address);	local  = &(attrs->local_address);	/* setup hints structure to be passed to getaddrinfo */	memset(&hints, 0, sizeof(hints));	connection_attributes_to_addrinfo(&hints, attrs);#ifdef HAVE_GETADDRINFO_AI_ADDRCONFIG	hints.ai_flags |= AI_ADDRCONFIG;#endif		if (numeric_mode == TRUE)		hints.ai_flags |= AI_NUMERICHOST;	/* get the address of the remote end of the connection */	err = getaddrinfo(remote->address, remote->service, &hints, &res);	if (err != 0)		fatal("forward host lookup failed for remote enpoint %s: %s",		      remote->address, gai_strerror(err));	/* check the results of getaddrinfo */	assert(res != NULL);	/* try connecting to any of the addresses returned by getaddrinfo */	for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {		struct timeval tv, *tvp = NULL;		fd_set connect_fdset;		socklen_t len;		/* only accept socktypes we can handle */		if (ptr->ai_socktype != SOCK_STREAM &&		    ptr->ai_socktype != SOCK_DGRAM) 			continue;#if defined(PF_INET6) && !defined(ENABLE_IPV6)		/* skip IPv6 if disabled */		if (ptr->ai_family == PF_INET6)			continue;#endif		/* we are going to try to connect to this address */		connect_attempted = TRUE;		/* get the numeric name for this destination 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));		/* get the real name for this destination as a string */		if (verbose_mode == TRUE && numeric_mode == FALSE) {			/* get the real name for this destination as a string */			err = getnameinfo(ptr->ai_addr, ptr->ai_addrlen,			                  hbuf_rev, sizeof(hbuf_rev),					  sbuf_rev, sizeof(sbuf_rev), 0);			if (err != 0) {				warn("inverse lookup failed for %s: %s",				     hbuf_num, gai_strerror(err));				/* just make the real name the numeric string */				strcpy(hbuf_rev, hbuf_num);				strcpy(sbuf_rev, sbuf_num);			}		} else {			/* just make the real name the numeric string */			strcpy(hbuf_rev, hbuf_num);			strcpy(sbuf_rev, sbuf_num);		}		/* 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)) {				/* maybe tell the user that this behaviour is 				 * related to a weird implementation of 				 * getaddrinfo on his system? */				warn("cannot create the socket: %s", 				     strerror(errno));				errno = 0;				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");		}#endif 		/* setup local source address and/or service */		if (local->address != NULL || local->service != NULL) {			struct addrinfo *src_res = NULL, *src_ptr;					/* setup hints structure to be passed to getaddrinfo */			memset(&hints, 0, sizeof(hints));			hints.ai_family   = ptr->ai_family;			hints.ai_flags    = AI_PASSIVE;			hints.ai_socktype = ptr->ai_socktype;			hints.ai_protocol = ptr->ai_protocol;				if (is_flag_set(NUMERIC_MODE) == TRUE) 				hints.ai_flags |= AI_NUMERICHOST;					/* get the local IP address of the connection */			err = getaddrinfo(local->address, local->service,			                  &hints, &src_res);			if (err != 0)				fatal("forward host lookup failed "				      "for source address %s: %s",				      local->address, gai_strerror(err));			/* check the results of getaddrinfo */			assert(src_res != NULL);			/* try binding to any of the addresses */			for (src_ptr = src_res; src_ptr != NULL;			     src_ptr = src_ptr->ai_next) {				err = bind(fd, src_ptr->ai_addr,					   src_ptr->ai_addrlen);				if (err == 0) break;			}						if (err != 0) {				/* make sure we have tried all addresses */				assert(src_ptr == NULL);								if (verbose_mode == TRUE) {					warn("bind to source addr/port failed "					     "when connecting to "					     "%s [%s] %s (%s): %s",					     hbuf_rev, hbuf_num,					     sbuf_num, sbuf_rev,					     strerror(errno));				}				freeaddrinfo(src_res);				close(fd);				fd = -1;				continue;			}			freeaddrinfo(src_res);		}		/* set connect timeout */		if (attrs->connect_timeout > 0) {			tv.tv_sec = attrs->connect_timeout;			tv.tv_usec = 0;			tvp = &tv;		}		/* set fd to nonblocking */		nonblock(fd);				/* attempt the connection */		err = connect(fd, ptr->ai_addr, ptr->ai_addrlen);		if (err != 0 && errno == EINPROGRESS) {			/* connection is proceeding			 * it is complete (or failed) when select returns */			/* initialize connect_fdset */			FD_ZERO(&connect_fdset);			FD_SET(fd, &connect_fdset);			/* call select */			do {				err = select(					fd+1, NULL, &connect_fdset, NULL, tvp);			} while (err < 0 && errno == EINTR);			if (err < 0)				fatal("select error: %s", strerror(errno));			if (err == 0) {				/* connection timed out */				if (is_flag_set(VERBOSE_MODE) == TRUE) {					warn("%s [%s] %s (%s): "					     "connect timed out",					     hbuf_rev, hbuf_num,					     sbuf_num, sbuf_rev);				}				close(fd);				fd = -1;				continue;			}						/* select returned - test socket error for result */			len = sizeof(err);			if (getsockopt(fd, SOL_SOCKET,SO_ERROR, &err, &len) < 0)				fatal("getsockopt error: %s", strerror(errno));			if (err != 0)				errno = err;		}		if (err != 0) {			/* connection failed */			if (verbose_mode == TRUE) {				warn("%s [%s] %s (%s): %s",				     hbuf_rev, hbuf_num,				     sbuf_num, sbuf_rev,				     strerror(errno));			}			close(fd);			fd = -1;			continue;		}		if (fd >= 0)			break;	}	/* either all possibilities were exahusted, or a connection was made */	assert(ptr == NULL || fd >= 0);		/* if the connection failed, output an error message */	if (ptr == NULL) {		/* if a connection was attempted, an error has been output */		if (connect_attempted == FALSE) {			fatal("forward lookup returned no usable socket types");		} else {			fatal("unable to connect to address %s, service %s", 			      remote->address, remote->service);		}	}	/* let the user know the connection has been established */	if (verbose_mode == TRUE) {		warn("%s [%s] %s (%s) open",		     hbuf_rev, hbuf_num,		     sbuf_num, sbuf_rev);	}	/* fill out the remote io_stream */	ios_assign_socket(&(attrs->remote_stream), fd, ptr->ai_socktype);	/* cleanup addrinfo structure */	freeaddrinfo(res);}