if (is_flag_set(VERY_VERBOSE_MODE) == TRUE) { warn("using %s socket", (ptr->ai_socktype == SOCK_STREAM)? "stream":"datagram"); }   freeaddrinfo(res);
void do_connect(connection_attributes *attrs){	address *remote, *local;	int err, fd = -1;	struct addrinfo hints, *res = NULL, *ptr;	bool connect_attempted = 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];	assert(attrs != NULL);	remote = &(attrs->remote_address);	local = &(attrs->local_address);	/* make sure all the preconditions are respected */	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 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 (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->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) {		/* 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(VERBOSE_MODE) == TRUE) &&		    (is_flag_set(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));		} else {			err = 1;		}		if (err != 0) {			/* 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) 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 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 IP address of the local end 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 returned by getaddrinfo */			for (src_ptr = src_res; src_ptr; 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);								if (is_flag_set(VERBOSE_MODE) == TRUE) {					warn("bind to source addr/port failed "						 "when connecting %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);		}				/* perform the connection */		err = connect(fd, ptr->ai_addr, ptr->ai_addrlen);		if (err != 0) {			if (is_flag_set(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;	}	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");		exit(EXIT_FAILURE);	}	/* cleanup addrinfo structure */	freeaddrinfo(res);	/* let the user know the connection has been established */	if (is_flag_set(VERBOSE_MODE)) {		warn("%s [%s] %s (%s) open", hbuf_rev, hbuf_num, sbuf_num, sbuf_rev);	}	/* fill out the io_streams for the local and remote */	ios_assign_stdio(&(attrs->local_stream));	ios_assign_socket(&(attrs->remote_stream), fd, ptr->ai_socktype);}