Remove trailing whitespace.
[dockapps.git] / wmbiff / wmbiff / socket.c
blobff2c81947ada025390e0ad5d882d5e0977814910
1 /* $Id: socket.c,v 1.14 2004/10/01 21:05:36 bluehal Exp $ */
2 /* Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
3 * (C) 1999 Trent Piepho <xyzzy@speakeasy.org>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <fcntl.h>
24 #include <time.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <netdb.h>
32 #include <stdio.h>
33 #include "regulo.h"
35 #ifdef USE_DMALLOC
36 #include <dmalloc.h>
37 #endif
39 /* be paranoid about leaking passwords as hostnames, enough
40 that we'll avoid attempting lookups on things that aren't
41 host names */
42 extern int Relax;
43 static int sanity_check_hostname(const char *hostname)
45 struct in_addr dummy;
46 return (Relax
47 || regulo_match("^[A-Za-z][-_A-Za-z0-9.]+$", hostname, NULL)
48 || inet_aton(hostname, &dummy));
51 static int ipv4_sock_connect(struct in_addr *address, short port)
53 struct sockaddr_in addr;
54 int fd, i;
55 fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
56 if (fd == -1) {
57 perror("Error opening socket");
58 printf("socket() failed.\n");
59 return (-1);
62 addr.sin_family = AF_INET;
63 addr.sin_addr.s_addr = *(u_long *) address;
64 addr.sin_port = htons(port);
65 i = connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr));
66 if (i == -1) {
67 int saved_errno = errno;
68 perror("Error connecting");
69 printf("connect(%s:%d) failed: %s\n", inet_ntoa(addr.sin_addr),
70 port, strerror(saved_errno));
71 close(fd);
72 return (-1);
74 return (fd);
77 /* nspring/blueHal, 10 Apr 2002; added some extra error
78 printing, in line with the debug-messages-to-stdout
79 philosophy of the rest of the wmbiff code */
80 /* 1 June 2002; incorporated IPv6 support by
81 Jun-ichiro itojun Hagino <itojun@iijlab.net>, thanks! */
83 int sock_connect(const char *hostname, int port)
85 #ifdef HAVE_GETADDRINFO
86 struct addrinfo hints, *res, *res0;
87 struct sockaddr_in addr;
88 int fd;
89 char pbuf[NI_MAXSERV];
90 int error;
92 if (!sanity_check_hostname(hostname)) {
93 printf
94 ("socket/connect to '%s' aborted: it does not appear to be a valid hostname\n",
95 hostname);
96 printf("if you really want this, use wmbiff's -relax option.\n");
97 return -1;
100 /* we were given an IP address, no need to try getaddrinfo on it */
101 if (inet_aton(hostname, &addr.sin_addr)) {
102 return ipv4_sock_connect(&addr.sin_addr, port);
105 memset(&hints, 0, sizeof(hints));
106 hints.ai_socktype = SOCK_STREAM;
107 snprintf(pbuf, sizeof(pbuf), "%d", port);
108 error = getaddrinfo(hostname, pbuf, &hints, &res0);
109 if (error) {
110 static int last_error;
111 if (last_error != error) {
112 /* only report a problem if it's new. this is an
113 approximation that minimizes kept state. */
114 printf("%s: %s\n", hostname, gai_strerror(error));
115 last_error = error;
117 return -1;
120 fd = -1;
121 for (res = res0; res; res = res->ai_next) {
122 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
123 if (fd < 0)
124 continue;
125 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
126 close(fd);
127 fd = -1;
128 continue;
130 break;
132 freeaddrinfo(res0);
133 if (fd < 0) {
134 static int last_connecterr;
135 if (errno != last_connecterr) {
136 /* only report a problem if it's new.
137 EHOSTUNREACH is common when the net is down,
138 for example; again, this is an approximation
139 to minimize kept state. */
140 last_connecterr = errno;
141 fprintf(stderr, "Error connecting to %s:%d: %s\n",
142 hostname, port, strerror(errno));
143 printf("socket/connect to %s failed: %s (%d)\n", hostname,
144 strerror(errno), errno);
146 return -1;
148 return fd;
149 #else
150 #warning "This build will not support IPv6"
151 struct hostent *host;
153 if (!sanity_check_hostname(hostname)) {
154 printf
155 ("socket/connect to '%s' aborted: it does not appear to be a valid hostname\n",
156 hostname);
157 printf("if you really want this, use wmbiff's -relax option.\n");
158 return -1;
161 host = gethostbyname(hostname);
162 if (host == NULL) {
163 herror("gethostbyname");
164 printf("gethostbyname(%s) failed.\n", hostname);
165 return (-1);
168 return ipv4_sock_connect(host->h_addr_list[0], port);
170 #endif
173 /* vim:set ts=4: */
175 * Local Variables:
176 * tab-width: 4
177 * c-indent-level: 4
178 * c-basic-offset: 4
179 * End: