]> diplodocus.org Git - nmh/blob - sbr/client.c
Fix invalid pointer arithmetic.
[nmh] / sbr / client.c
1 /* client.c -- connect to a server
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h>
9 #include <h/mts.h>
10 #include <h/utils.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <arpa/inet.h>
15 #include <errno.h>
16
17
18 int
19 client (char *server, char *service, char *response, int len_response,
20 int debug)
21 {
22 int sd, rc;
23 struct addrinfo hints, *res, *ai;
24
25 if (!server || *server == '\0') {
26 snprintf(response, len_response, "Internal error: NULL server name "
27 "passed to client()");
28 return NOTOK;
29 }
30
31 ZERO(&hints);
32 #ifdef AI_ADDRCONFIG
33 hints.ai_flags = AI_ADDRCONFIG;
34 #endif
35 hints.ai_family = PF_UNSPEC;
36 hints.ai_socktype = SOCK_STREAM;
37
38 if (debug) {
39 fprintf(stderr, "Trying to connect to \"%s\" ...\n", server);
40 }
41
42 rc = getaddrinfo(server, service, &hints, &res);
43
44 if (rc) {
45 snprintf(response, len_response, "Lookup of \"%s\" failed: %s",
46 server, gai_strerror(rc));
47 return NOTOK;
48 }
49
50 for (ai = res; ai != NULL; ai = ai->ai_next) {
51 if (debug) {
52 char address[NI_MAXHOST];
53 char port[NI_MAXSERV];
54
55 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
56 sizeof(address), port, sizeof port,
57 NI_NUMERICHOST | NI_NUMERICSERV);
58
59 fprintf(stderr, "Connecting to %s:%s...\n",
60 rc ? "unknown" : address, rc ? "--" : port);
61 }
62
63 sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
64
65 if (sd < 0) {
66 if (debug)
67 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
68 rc = errno;
69 continue;
70 }
71
72 if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
73 freeaddrinfo(res);
74 return sd;
75 }
76
77 rc = errno;
78
79 if (debug) {
80 fprintf(stderr, "Connection failed: %s\n", strerror(errno));
81 }
82
83 close(sd);
84 }
85
86 /*
87 * Improve error handling a bit. If we were given multiple IP addresses
88 * then return the old "no servers available" error, but point the user
89 * to -snoop (hopefully that's universal). Otherwise report a specific
90 * error.
91 */
92
93 if (res->ai_next)
94 snprintf(response, len_response, "no servers available (use -snoop "
95 "for details");
96 else
97 snprintf(response, len_response, "Connection to \"%s\" failed: %s",
98 server, strerror(errno));
99
100 freeaddrinfo(res);
101
102 return NOTOK;
103 }