Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / inet_connect.c
blob3cdb4344d5a570a17f5f878c467d0bd3db0eef52
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* inet_connect 3
6 /* SUMMARY
7 /* connect to TCP listener
8 /* SYNOPSIS
9 /* #include <connect.h>
11 /* int inet_windowsize;
13 /* int inet_connect(addr, block_mode, timeout)
14 /* const char *addr;
15 /* int block_mode;
16 /* int timeout;
17 /* DESCRIPTION
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.
24 /* Arguments:
25 /* .IP addr
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.
30 /* .IP block_mode
31 /* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
32 /* blocking mode.
33 /* .IP timeout
34 /* Bounds the number of seconds that the operation may take. Specify
35 /* a value <= 0 to disable the time limit.
36 /* DIAGNOSTICS
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
39 /* variable.
40 /* Fatal errors: other system call failures.
41 /* LICENSE
42 /* .ad
43 /* .fi
44 /* The Secure Mailer license must be distributed with this software.
45 /* AUTHOR(S)
46 /* Wietse Venema
47 /* IBM T.J. Watson Research
48 /* P.O. Box 704
49 /* Yorktown Heights, NY 10598, USA
50 /*--*/
52 /* System interfaces. */
54 #include <sys_defs.h>
55 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <string.h>
58 #include <unistd.h>
59 #include <errno.h>
60 #include <netdb.h>
62 /* Utility library. */
64 #include "mymalloc.h"
65 #include "msg.h"
66 #include "iostuff.h"
67 #include "host_port.h"
68 #include "sane_connect.h"
69 #include "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)
81 char *buf;
82 char *host;
83 char *port;
84 const char *parse_err;
85 struct addrinfo *res;
86 struct addrinfo *res0;
87 int aierr;
88 int sock;
89 MAI_HOSTADDR_STR hostaddr;
90 INET_PROTO_INFO *proto_info;
91 int found;
94 * Translate address information to internal form. No host defaults to
95 * the local host.
97 buf = mystrdup(addr);
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));
103 myfree(buf);
105 proto_info = inet_proto_info();
106 for (sock = -1, found = 0, res = res0; res != 0; res = res->ai_next) {
109 * Safety net.
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);
114 continue;
116 found++;
119 * In case of multiple addresses, show what address we're trying now.
121 if (msg_verbose) {
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) {
127 if (msg_verbose)
128 msg_info("%m");
129 } else
130 break;
132 if (found == 0)
133 msg_fatal("host not found: %s", addr);
134 freeaddrinfo(res0);
135 return (sock);
138 /* inet_connect_one - try to connect to one address */
140 static int inet_connect_one(struct addrinfo * res, int block_mode, int timeout)
142 int sock;
145 * Create a client socket.
147 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
148 if (sock < 0)
149 return (-1);
152 * Window scaling workaround.
154 if (inet_windowsize > 0)
155 set_inet_windowsize(sock, inet_windowsize);
158 * Timed connect.
160 if (timeout > 0) {
161 non_blocking(sock, NON_BLOCKING);
162 if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
163 close(sock);
164 return (-1);
166 if (block_mode != NON_BLOCKING)
167 non_blocking(sock, block_mode);
168 return (sock);
172 * Maybe block until connected.
174 else {
175 non_blocking(sock, block_mode);
176 if (sane_connect(sock, res->ai_addr, res->ai_addrlen) < 0
177 && errno != EINPROGRESS) {
178 close(sock);
179 return (-1);
181 return (sock);