7 /* connect to TCP listener
9 /* #include <connect.h>
11 /* int inet_windowsize;
13 /* int inet_connect(addr, block_mode, timeout)
18 /* inet_connect connects to a TCP listener at
19 /* the specified address, and returns the resulting file descriptor.
21 /* Specify an inet_windowsize value > 0 to override the TCP
22 /* window size that the client advertises to the server.
26 /* The destination to connect to. The format is host:port. If no
27 /* host is specified, a port on the local host is assumed.
28 /* Host and port information may be given in numerical form
29 /* or as symbolical names.
31 /* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
34 /* Bounds the number of seconds that the operation may take. Specify
35 /* a value <= 0 to disable the time limit.
37 /* The result is -1 when the connection could not be made.
38 /* The nature of the error is available via the global \fIerrno\fR
40 /* Fatal errors: other system call failures.
44 /* The Secure Mailer license must be distributed with this software.
47 /* IBM T.J. Watson Research
49 /* Yorktown Heights, NY 10598, USA
52 /* System interfaces. */
55 #include <sys/socket.h>
56 #include <netinet/in.h>
62 /* Utility library. */
67 #include "host_port.h"
68 #include "sane_connect.h"
70 #include "timed_connect.h"
71 #include "myaddrinfo.h"
72 #include "sock_addr.h"
73 #include "inet_proto.h"
75 static int inet_connect_one(struct addrinfo
*, int, int);
77 /* inet_connect - connect to TCP listener */
79 int inet_connect(const char *addr
, int block_mode
, int timeout
)
84 const char *parse_err
;
86 struct addrinfo
*res0
;
89 MAI_HOSTADDR_STR hostaddr
;
90 INET_PROTO_INFO
*proto_info
;
94 * Translate address information to internal form. No host defaults to
98 if ((parse_err
= host_port(buf
, &host
, "localhost", &port
, (char *) 0)) != 0)
99 msg_fatal("%s: %s", addr
, parse_err
);
100 if ((aierr
= hostname_to_sockaddr(host
, port
, SOCK_STREAM
, &res0
)) != 0)
101 msg_fatal("host/service %s/%s not found: %s",
102 host
, port
, MAI_STRERROR(aierr
));
105 proto_info
= inet_proto_info();
106 for (sock
= -1, found
= 0, res
= res0
; res
!= 0; res
= res
->ai_next
) {
111 if (strchr((char *) proto_info
->sa_family_list
, res
->ai_family
) == 0) {
112 msg_info("skipping address family %d for host %s",
113 res
->ai_family
, host
);
119 * In case of multiple addresses, show what address we're trying now.
122 SOCKADDR_TO_HOSTADDR(res
->ai_addr
, res
->ai_addrlen
,
123 &hostaddr
, (MAI_SERVPORT_STR
*) 0, 0);
124 msg_info("trying... [%s]", hostaddr
.buf
);
126 if ((sock
= inet_connect_one(res
, block_mode
, timeout
)) < 0) {
133 msg_fatal("host not found: %s", addr
);
138 /* inet_connect_one - try to connect to one address */
140 static int inet_connect_one(struct addrinfo
* res
, int block_mode
, int timeout
)
145 * Create a client socket.
147 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
152 * Window scaling workaround.
154 if (inet_windowsize
> 0)
155 set_inet_windowsize(sock
, inet_windowsize
);
161 non_blocking(sock
, NON_BLOCKING
);
162 if (timed_connect(sock
, res
->ai_addr
, res
->ai_addrlen
, timeout
) < 0) {
166 if (block_mode
!= NON_BLOCKING
)
167 non_blocking(sock
, block_mode
);
172 * Maybe block until connected.
175 non_blocking(sock
, block_mode
);
176 if (sane_connect(sock
, res
->ai_addr
, res
->ai_addrlen
) < 0
177 && errno
!= EINPROGRESS
) {