"Fossies" - the Fresh Open Source Software Archive 
Member "tlswrap-1.04/network.c" (25 Nov 2006, 10742 Bytes) of package /linux/privat/old/tlswrap-1.04.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "network.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * Copyright (c) 2002-2006 Tomas Svensson <ts@codepix.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "conf.h"
29
30 #define _POSIX_PII_SOCKET /* for Tru64 UNIX 5.1 */
31
32 #include <sys/types.h>
33 #ifdef WIN32
34 #include <Winsock2.h>
35 #include <process.h>
36 #define snprintf _snprintf
37 #define strcasecmp _stricmp
38 #define strncasecmp _strnicmp
39 typedef __int32 ssize_t;
40 typedef int socklen_t;
41 #define ECONNREFUSED WSAECONNREFUSED
42 #define EINPROGRESS WSAEWOULDBLOCK
43 #else
44 #include <sys/socket.h>
45 #include <netdb.h>
46 #include <sys/uio.h>
47 #include <unistd.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #endif
53 #include <fcntl.h>
54 #include <sys/types.h>
55
56
57 #include <string.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <errno.h>
61
62 extern int debug;
63
64 #include "tlswrap.h"
65 #include "network.h"
66 #include "misc.h"
67
68 #ifdef WIN32
69
70 int write(SOCKET s, void *buf, int len) {
71 return send(s, (char*)buf, len, 0);
72 }
73
74 int read(SOCKET s, void *buf, int len) {
75 return recv(s, (char*)buf, len, 0);
76 }
77
78 #endif
79
80 void setup_connect_1(struct user_data *ud, int index, char *serv,
81 char *port, int write_pipe) {
82 struct dns_msg dns;
83
84 dns.ud = index;
85 strlcpy(dns.port, port, sizeof(dns.port));
86 strlcpy(dns.hostname, serv, sizeof(dns.hostname));
87 if (write(write_pipe, &dns, sizeof(dns)) != sizeof(dns)) {
88 fprintf(stderr, "Error: Too many hostname lookups\n");
89 return;
90 }
91 ud->connected = CONN_DNS;
92 if (debug)
93 printf("Resolving %s on %d...\n",serv, index);
94 }
95
96 void
97 setup_connect_2(struct user_data *ud, struct dns_msg *dns, int data)
98 {
99 char *ep;
100 int result, tos = 0;
101
102 if (strlen(dns->hostname) == 0) {
103 if (debug)
104 printf("Error: Could not resolve hostname\n");
105 if (!(data)) {
106 ud->connected = CONN_NO;
107 print_to_ud(ud, "530 Could not resolve hostname.\r\n");
108 }
109 return;
110 }
111 ud->ssl_data = NULL; /* Could be data left from other session, which would crash dataclose */
112 ud->rport = strtol(dns->port, &ep, 10);
113 if (debug)
114 printf("Connecting to %s on port %s, please wait...\n", dns->hostname, dns->port);
115
116 if (data) {
117 ud->serv_data_fd = setup_connect(dns->hostname, dns->port, &ud->lport, &result);
118 #ifndef WIN32
119 tos = IPTOS_THROUGHPUT;
120 if ((setsockopt(ud->serv_data_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) && debug)
121 printf("Unable to set TOS=Throughput for data channel.\n");
122 #endif
123 } else {
124 ud->serv_fd = setup_connect(dns->hostname, dns->port,
125 &ud->lport, &result);
126 #ifndef WIN32
127 tos = IPTOS_THROUGHPUT;
128 if ((setsockopt(ud->serv_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) && debug)
129 printf("Unable to set TOS=Lowdelay for control channel.\n");
130 #endif
131 }
132
133 if (result == 0) {
134 if (data) {
135 if (debug)
136 printf("data connected\n");
137 ud->data_connected = CONN_YES;
138 } else {
139 ud->connected = CONN_YES;
140 ud->serv_status = SERV_CONN;
141 }
142 } else if (result == 2) {
143 print_to_ud(ud, "Can't find hostname, should not happen!");
144 ud->connected = CONN_CMD;
145 } else if (result == 3) {
146 print_to_ud(ud,"421 Connection refused by server.\r\n");
147 user_close(ud);
148 } else if (result == 4) {
149 print_to_ud(ud,"421 Software caused connection abort.\r\n");
150 user_close(ud);
151 } else {
152 if (debug)
153 printf("connection in progress\n");
154 if (!data)
155 ud->connected = CONN_IN_PROG;
156 else
157 ud->data_connected = CONN_IN_PROG;
158 }
159 }
160
161 #ifdef WIN32
162 SOCKET
163 #else
164 int
165 #endif
166 setup_connect(const char *host, const char *port,
167 unsigned int *lport, int *result)
168 {
169
170 int flags, sockopt;
171 char *ep;
172
173 struct sockaddr_in sin, *sin2;
174 unsigned short nport;
175 struct sockaddr sa;
176 socklen_t sa_len;
177 #ifdef WIN32
178 SOCKET conn_fd;
179 unsigned long nonblockopt = 1;
180 #else
181 int conn_fd;
182 #endif
183
184 conn_fd = socket(PF_INET, SOCK_STREAM, 0);
185
186 #ifdef WIN32
187 if (conn_fd == INVALID_SOCKET)
188 #else
189 if (conn_fd < 0)
190 #endif
191 sys_err("setup_connect_socket");
192
193 #ifdef WIN32
194 ioctlsocket(conn_fd, FIONBIO, &nonblockopt);
195 #else
196 flags = fcntl(conn_fd,F_GETFL);
197 fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
198 #endif
199
200 sockopt = 1;
201 #ifdef WIN32
202 if (setsockopt(conn_fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&sockopt, sizeof(sockopt)))
203 sys_err("setsockopt-keepalive");
204 #else
205 if (setsockopt(conn_fd, SOL_SOCKET, SO_KEEPALIVE, &sockopt, sizeof(sockopt)))
206 sys_err("setsockopt-keepalive");
207 #endif
208
209 memset(&sa,0,sizeof(sa));
210 sa.sa_family = PF_INET;
211 if (bind(conn_fd, &sa, sizeof(sa)) < 0)
212 perror("bind");
213
214 sa_len = sizeof(sa);
215 if (getsockname(conn_fd, &sa, &sa_len))
216 sys_err("getsockname");
217
218
219 memset(&sin, 0, sizeof(sin));
220 sin2 = (struct sockaddr_in *)&sa;
221 if (debug)
222 printf("host = %s, port = %s\n", host, port);
223 #if defined(HAVE_INET_ATON) || defined(HAVE_LIBRESOLV)
224 if (inet_aton(host, &sin.sin_addr) != 1)
225 sys_err(host);
226 #else
227 if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
228 sys_err("inet_addr");
229 #endif
230 *lport = ntohs(sin2->sin_port);
231 nport = (unsigned short)strtol(port, &ep, 10);
232 sin.sin_port = htons(nport);
233 sin.sin_family = PF_INET;
234 if (connect(conn_fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
235 #ifdef WIN32
236 errno = WSAGetLastError();
237 #endif
238 if (errno == ECONNREFUSED) {
239 *result = 3;
240 #ifdef WIN32
241 } else if (errno == WSAECONNABORTED) { // i.e. blocked by firewall or such
242 *result = 4;
243 #endif
244 } else {
245 if (errno != EINPROGRESS) {
246 if (debug) printf("socket error is %d", errno);
247 sys_err("connect");
248 }
249 *result = 1; /* Nonblocking operation */
250 }
251 } else
252 *result = 0; /* Connected */
253
254 return conn_fd;
255 }
256
257 #ifdef WIN32
258
259 extern int in_service;
260
261 void dns_helper(void *arg) { // __cdecl
262 SOCKET *sarg = (SOCKET*)arg;
263 SOCKET read_fd = sarg[0];
264 SOCKET write_fd = sarg[1];
265 #else
266 void dns_helper(int read_fd, int write_fd) {
267 #endif
268 struct dns_msg dns;
269 ssize_t bytes;
270
271 struct sockaddr_in saddr;
272 struct hostent *hptr;
273
274 #ifdef HAVE_SETPROCTITLE
275 char sp[40];
276 unsigned int serv = 0;
277 #endif
278 for(;;) {
279 #ifdef HAVE_SETPROCTITLE
280 snprintf(sp, sizeof(sp), "tlswrap-dns (serviced %u reqs)",
281 serv++);
282 setproctitle(sp);
283 #endif
284 bytes = read(read_fd, &dns, sizeof(dns));
285 if (bytes == 0) {
286 if (debug)
287 printf("Parent died, exiting...\n");
288 #ifdef WIN32
289 // if (in_service)
290 // closesocket(pipe1[1]);
291 //x closesocket(pipe1[0]);
292 //x closesocket(pipe2[0]);
293 //x closesocket(pipe2[1]);
294 closesocket(write_fd);
295 _endthread();
296 // else
297 #endif
298 exit(0);
299 }
300
301 memset(&saddr, 0, sizeof(saddr));
302 if ((hptr = gethostbyname(dns.hostname)) == NULL)
303 dns.hostname[0] = '\0';
304 else {
305 memcpy(&saddr.sin_addr, hptr->h_addr,
306 sizeof(saddr.sin_addr));
307 strlcpy(dns.hostname, inet_ntoa(saddr.sin_addr),
308 sizeof(dns.hostname));
309 }
310 bytes = write(write_fd, &dns, sizeof(dns));
311 }
312
313 }
314
315 #ifdef WIN32
316 SOCKET
317 #else
318 int
319 #endif
320 setup_listen(int max_users, const char *host, char *port, int portlen)
321 {
322 /* IP V4 only version */
323
324 /* Returns a non-blocking listening socket on the specified port.
325 Listen backlog is set to max_users. if portlen != 0 then blah */
326
327 int flags, sockopt;
328 unsigned short rport;
329 socklen_t slen;
330
331 struct sockaddr_in sin;
332 char *ep;
333 struct hostent *hptr;
334 #ifdef WIN32
335 unsigned long nonblockopt = 1;
336 SOCKET listen_socket;
337 #else
338 int listen_socket;
339 #endif
340
341
342 rport = (unsigned short)strtol(port, &ep, 10);
343
344 memset(&sin, 0, sizeof(sin));
345 sin.sin_family = PF_INET;
346 sin.sin_port = htons(rport);
347
348 if (host == NULL)
349 sin.sin_addr.s_addr = htonl(INADDR_ANY);
350 else {
351 if ((hptr = gethostbyname(host)) == NULL) {
352 printf("hostname = %s\n", host);
353 sys_err("can't resolve specified local hostname");
354 } else
355 memcpy(&sin.sin_addr, hptr->h_addr, sizeof(sin.sin_addr));
356 }
357 listen_socket = socket(PF_INET, SOCK_STREAM, 0);
358
359 #ifdef WIN32
360 if (listen_socket == INVALID_SOCKET)
361 #else
362 if (listen_socket < 0)
363 #endif
364 sys_err("socket_listen_ipv4");
365
366 sockopt = 1;
367 #ifdef WIN32
368 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&sockopt,
369 sizeof(sockopt)))
370 sys_err("setsockopt-reuseaddr");
371 #else
372 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &sockopt,
373 sizeof(sockopt)))
374 sys_err("setsockopt-reuseaddr");
375 #endif
376
377 if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)))
378 sys_err("bind");
379
380 slen = sizeof(struct sockaddr_in);
381 if (getsockname(listen_socket, (struct sockaddr*)&sin, &slen) < 0)
382 sys_err("getsockname");
383
384 if (listen(listen_socket, max_users))
385 sys_err("listen");
386
387
388 #ifdef WIN32
389 ioctlsocket(listen_socket, FIONBIO, &nonblockopt);
390 #else
391 flags = fcntl(listen_socket, F_GETFL);
392 fcntl(listen_socket, F_SETFL, flags | O_NONBLOCK);
393 #endif
394 if (portlen > 0)
395 snprintf(port, portlen, "%u", ntohs(sin.sin_port));
396
397 return listen_socket;
398 }
399
400
401 int get_local_ip(int fd, char *ip, int iplen)
402 {
403 socklen_t slen;
404 struct sockaddr_in sin;
405
406 slen = sizeof(struct sockaddr_in);
407 if (getsockname(fd, (struct sockaddr*)&sin, &slen) < 0)
408 sys_err("getsockname");
409
410 strlcpy(ip, inet_ntoa(sin.sin_addr), iplen);
411 return 0;
412 }
413
414 int get_remote_ip(int fd, char *ip, int iplen)
415 {
416 socklen_t slen;
417 struct sockaddr_in sin;
418
419 slen = sizeof(struct sockaddr_in);
420 if (getpeername(fd, (struct sockaddr*)&sin, &slen) < 0)
421 sys_err("getsockname");
422
423 strlcpy(ip, inet_ntoa(sin.sin_addr), iplen);
424 return 0;
425 }