if (connect_attempted == FALSE) {
if (connect_attempted == FALSE)
void do_connect(const address *remote, const address *local,		const connection_attributes *attrs){	io_stream remote_stream, local_stream;	int err, fd = -1;	struct addrinfo hints, *res = NULL, *ptr;	bool have_rev = FALSE;	bool connect_attempted = FALSE;	char hbuf_rev[NI_MAXHOST + 1]; /* MAX_IP_ADDRLEN + 1 should be enough */	char hbuf_num[NI_MAXHOST + 1];	char sbuf_rev[NI_MAXSERV + 1]; /* MAX_PORTLEN + 1 should be enough */	char sbuf_num[NI_MAXSERV + 1];	/* make sure that all the preconditions are respected */	assert(remote != NULL);	assert(remote->address != NULL);	assert(remote->port != NULL);	assert(local == NULL || ((local->address == NULL || strlen(local->address) > 0) &&	                         (local->port    == NULL || strlen(local->port)    > 0)));	assert(attrs != NULL);		/* setup hints structure to be passed to getaddrinfo */	memset(&hints, 0, sizeof(hints));	switch (attrs->proto) {		case PROTO_IPv6:			hints.ai_family = AF_INET6;			break;		case PROTO_IPv4:			hints.ai_family = AF_INET;			break;		case PROTO_UNSPECIFIED:			hints.ai_family = AF_UNSPEC;			break;		default:			fatal("internal error: unknown socket domain");	}		switch (attrs->type) {		case UDP_SOCKET:			hints.ai_socktype = SOCK_DGRAM;			break;		case TCP_SOCKET:			hints.ai_socktype = SOCK_STREAM;			break;		default:			fatal("internal error: unknown socket type");	}#ifdef HAVE_GETADDRINFO_AI_ADDRCONFIG	hints.ai_flags |= AI_ADDRCONFIG;#endif		if (is_flag_set(NUMERIC_MODE) == TRUE)		hints.ai_flags |= AI_NUMERICHOST;	/* get the address of the remote end of the connection */	err = getaddrinfo(remote->address, remote->port, &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) {		/* reset have_rev */		have_rev = FALSE;				/* only accept socktypes we can handle */		if (ptr->ai_socktype != SOCK_STREAM && ptr->ai_socktype != SOCK_DGRAM)			continue;		/* 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 ((is_flag_set(NUMERIC_MODE) == FALSE) && 		    (is_flag_set(VERY_VERBOSE_MODE) == TRUE)) { /* should this be VERBOSE_MODE? */						/* try reverse dns lookup */			err = getnameinfo(ptr->ai_addr, ptr->ai_addrlen,				          hbuf_rev, sizeof(hbuf_rev), sbuf_rev, 				          sizeof(sbuf_rev), 0);			if(err != 0) {				/* this is not a fatal error */				warn("inverse lookup failed for %s: %s",				     hbuf_num, gai_strerror(err));			} else {				/* we have reverse dns information */				have_rev = TRUE; 			}		}		/* 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) warn("error with sockopt IPV6_V6ONLY");		}#endif 		/* setup local source address and/or ports */		if (local != NULL && (local->address != NULL || local->port != 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 IP address of the local end of the connection */			err = getaddrinfo(local->address, local->port, &hints, &src_res);			if(err != 0) {				warn("forward host lookup failed for local endpoint %s: %s",				     local->address, gai_strerror(err));				close(fd);				fd = -1;				continue;			}			/* check the results of getaddrinfo */			assert(src_res != NULL);			/* try binding to any of the addresses returned by getaddrinfo */			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 the addresses returned by 				 * getaddrinfo */				assert(src_ptr->ai_next == NULL);								/* print error message */				if (have_rev == TRUE) {					warn("bind to source addr/port failed when "					     "connecting to %s (addr. %s, rev. name %s) "					     "port %s (number %s, name %s): %s",					     remote->address, hbuf_num, hbuf_rev, 					     remote->port, sbuf_num, sbuf_rev, strerror(errno));				} else {					warn("bind to source addr/port failed when "					     "connecting to %s (addr. %s) "					     "port %s (number %s): %s",					     remote->address, hbuf_num,  					     remote->port, sbuf_num, strerror(errno));				}								freeaddrinfo(src_res);				close(fd);				fd = -1;				continue;			}			freeaddrinfo(src_res);		}				/* perform the connection */		err = connect(fd, ptr->ai_addr, ptr->ai_addrlen);		if (err != 0) {			if (is_flag_set(VERBOSE_MODE) == TRUE) {				if (have_rev == TRUE) {					warn("connection to %s (addr. %s, rev. name %s) "					     "port %s (number %s, name %s) failed: %s",					     remote->address, hbuf_num, hbuf_rev, 					     remote->port, sbuf_num, sbuf_rev, strerror(errno));				} else {					warn("connection to %s (addr. %s) "					     "port %s (number %s) failed: %s",					     remote->address, hbuf_num,  					     remote->port, sbuf_num, strerror(errno));				}			}			close(fd);			fd = -1;			continue;		}		if (fd >= 0)			break;	}	assert(ptr == NULL || fd >= 0);		/* if the connection failed, output an error message */	if (ptr == NULL) {		if (connect_attempted == FALSE) {			fatal("forward lookup returned no usable socket types");		} else {			fatal("cannot connect to %s port %s", 			      remote->address, remote->port);		}	}	/* cleanup addrinfo structure */	freeaddrinfo(res);	/* let the user know the connection has been established */	if (is_flag_set(VERBOSE_MODE)) {		if (have_rev == TRUE) {			warn("connection to %s (addr. %s, rev. name %s) "			     "port %s (number %s, name %s) opened",			     remote->address, hbuf_num, hbuf_rev, 			     remote->port, sbuf_num, sbuf_rev);		} else {			warn("connection to %s (addr. %s) "			     "port %s (number %s) opened",			     remote->address, hbuf_num,  			     remote->port, sbuf_num);		}	}	/* create io_streams for the local and remote streams */	stdio_to_io_stream(&local_stream);	socket_to_io_stream(&remote_stream, fd, ptr->ai_socktype);	/* read and write from the streams until they are closed */	readwrite(&remote_stream, &local_stream);}