]> sjero.net Git - wget/blob - src/connect.c
[svn] Updated IPv6 code.
[wget] / src / connect.c
1 /* Establishing and handling network connections.
2    Copyright (C) 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <assert.h>
39
40 #ifndef WINDOWS
41 # include <sys/socket.h>
42 # include <netdb.h>
43 # include <netinet/in.h>
44 # ifndef __BEOS__
45 #  include <arpa/inet.h>
46 # endif
47 #endif /* not WINDOWS */
48
49 #include <errno.h>
50 #ifdef HAVE_STRING_H
51 # include <string.h>
52 #else
53 # include <strings.h>
54 #endif /* HAVE_STRING_H */
55 #ifdef HAVE_SYS_SELECT_H
56 # include <sys/select.h>
57 #endif /* HAVE_SYS_SELECT_H */
58
59 #include "wget.h"
60 #include "utils.h"
61 #include "host.h"
62 #include "connect.h"
63
64 #ifndef errno
65 extern int errno;
66 #endif
67
68 /* Variables shared by bindport and acceptport: */
69 static int msock = -1;
70 /*static struct sockaddr *addr;*/
71
72 static int
73 resolve_bind_address (int flags, ip_address *addr)
74 {
75   struct address_list *al = NULL;
76   int resolved = 0;
77
78   if (opt.bind_address != NULL)
79     {
80       al = lookup_host (opt.bind_address, flags | LH_SILENT | LH_PASSIVE);
81       if (al == NULL)
82         {
83           logprintf (LOG_NOTQUIET,
84                      _("Unable to convert `%s' to a bind address.  Reverting to ANY.\n"),
85                      opt.bind_address);
86         }
87       else 
88         resolved = 1;
89     }
90
91   if (al == NULL)
92     {
93       /* #### Is there really a need for this?  Shouldn't we simply
94          return 0 and have the caller use sockaddr_set_address to
95          specify INADDR_ANY/in6addr_any?  */
96       const char *unspecified_address = "0.0.0.0";
97 #ifdef ENABLE_IPV6
98       if (flags & BIND_ON_IPV6_ONLY)
99         unspecified_address = "::";
100 #endif
101       al = lookup_host (unspecified_address, LH_SILENT | LH_PASSIVE);
102     }
103
104   assert (al != NULL);
105
106   address_list_copy_one (al, 0, addr);
107   address_list_release (al);
108
109   return resolved;
110 }
111 \f
112 struct cwt_context {
113   int fd;
114   const struct sockaddr *addr;
115   socklen_t addrlen;
116   int result;
117 };
118
119 static void
120 connect_with_timeout_callback (void *arg)
121 {
122   struct cwt_context *ctx = (struct cwt_context *)arg;
123   ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
124 }
125
126 /* Like connect, but specifies a timeout.  If connecting takes longer
127    than TIMEOUT seconds, -1 is returned and errno is set to
128    ETIMEDOUT.  */
129
130 static int
131 connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
132                       double timeout)
133 {
134   struct cwt_context ctx;
135   ctx.fd = fd;
136   ctx.addr = addr;
137   ctx.addrlen = addrlen;
138
139   if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
140     {
141       errno = ETIMEDOUT;
142       return -1;
143     }
144   if (ctx.result == -1 && errno == EINTR)
145     errno = ETIMEDOUT;
146   return ctx.result;
147 }
148 \f
149 /* A kludge, but still better than passing the host name all the way
150    to connect_to_one.  */
151 static const char *connection_host_name;
152
153 void
154 set_connection_host_name (const char *host)
155 {
156   if (host)
157     assert (connection_host_name == NULL);
158   else
159     assert (connection_host_name != NULL);
160
161   connection_host_name = host;
162 }
163
164 /* Connect to a remote host whose address has been resolved. */
165 int
166 connect_to_one (ip_address *addr, unsigned short port, int silent)
167 {
168   struct sockaddr_storage ss;
169   struct sockaddr *sa = (struct sockaddr *)&ss;
170   int sock, save_errno;
171
172   /* Set port and protocol */
173   sockaddr_set_address (sa, port, addr);
174
175   if (!silent)
176     {
177       const char *pretty_addr = pretty_print_address (addr);
178       if (connection_host_name
179           && 0 != strcmp (connection_host_name, pretty_addr))
180         logprintf (LOG_VERBOSE, _("Connecting to %s[%s]:%hu... "),
181                    connection_host_name, pretty_addr, port);
182       else
183         logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "),
184                    pretty_addr, port);
185     }
186
187   /* Create the socket of the family appropriate for the address.  */
188   sock = socket (sa->sa_family, SOCK_STREAM, 0);
189   if (sock < 0)
190     goto out;
191
192   /* For very small rate limits, set the buffer size (and hence,
193      hopefully, the size of the kernel window) to the size of the
194      limit.  That way we don't sleep for more than 1s between network
195      reads.  */
196   if (opt.limit_rate && opt.limit_rate < 8192)
197     {
198       int bufsize = opt.limit_rate;
199       if (bufsize < 512)
200         bufsize = 512;
201 #ifdef SO_RCVBUF
202       setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
203                   (char *)&bufsize, sizeof (bufsize));
204 #endif
205       /* When we add opt.limit_rate support for writing, as with
206          `--post-file', also set SO_SNDBUF here.  */
207     }
208
209   if (opt.bind_address)
210     {
211       /* Bind the client side to the requested address. */
212       ip_address bind_address;
213       if (resolve_bind_address (0, &bind_address))
214         {
215           struct sockaddr_storage bss;
216           struct sockaddr *bsa = (struct sockaddr *)&bss;
217           sockaddr_set_address (bsa, 0, &bind_address);
218           if (bind (sock, bsa, sockaddr_len (bsa)))
219             {
220               CLOSE (sock);
221               sock = -1;
222               goto out;
223             }
224         }
225     }
226
227   /* Connect the socket to the remote host.  */
228   if (connect_with_timeout (sock, sa, sockaddr_len (sa),
229                             opt.connect_timeout) < 0)
230     {
231       CLOSE (sock);
232       sock = -1;
233       goto out;
234     }
235
236  out:
237   if (sock >= 0)
238     {
239       /* Success. */
240       if (!silent)
241         logprintf (LOG_VERBOSE, _("connected.\n"));
242       DEBUGP (("Created socket %d.\n", sock));
243     }
244   else
245     {
246       save_errno = errno;
247       if (!silent)
248         logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
249       errno = save_errno;
250     }
251
252   return sock;
253 }
254
255 /* Connect to a remote host whose address has been resolved. */
256 int
257 connect_to_many (struct address_list *al, unsigned short port, int silent)
258 {
259   int i, start, end;
260
261   address_list_get_bounds (al, &start, &end);
262   for (i = start; i < end; i++)
263     {
264       ip_address addr;
265       int sock;
266       address_list_copy_one (al, i, &addr);
267
268       sock = connect_to_one (&addr, port, silent);
269       if (sock >= 0)
270         /* Success. */
271         return sock;
272
273       address_list_set_faulty (al, i);
274
275       /* The attempt to connect has failed.  Continue with the loop
276          and try next address. */
277     }
278
279   return -1;
280 }
281
282 int
283 test_socket_open (int sock)
284 {
285 #ifdef HAVE_SELECT
286   fd_set check_set;
287   struct timeval to;
288
289   /* Check if we still have a valid (non-EOF) connection.  From Andrew
290    * Maholski's code in the Unix Socket FAQ.  */
291
292   FD_ZERO (&check_set);
293   FD_SET (sock, &check_set);
294
295   /* Wait one microsecond */
296   to.tv_sec = 0;
297   to.tv_usec = 1;
298
299   /* If we get a timeout, then that means still connected */
300   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
301     {
302       /* Connection is valid (not EOF), so continue */
303       return 1;
304     }
305   else
306     return 0;
307 #else
308   /* Without select, it's hard to know for sure. */
309   return 1;
310 #endif
311 }
312
313 /* Bind the local port PORT.  This does all the necessary work, which
314    is creating a socket, setting SO_REUSEADDR option on it, then
315    calling bind() and listen().  If *PORT is 0, a random port is
316    chosen by the system, and its value is stored to *PORT.  The
317    internal variable MPORT is set to the value of the ensuing master
318    socket.  Call acceptport() to block for and accept a connection.  */
319
320 uerr_t
321 bindport (const ip_address *bind_address, unsigned short *port)
322 {
323   int family = AF_INET;
324   int optval;
325   struct sockaddr_storage ss;
326   struct sockaddr *sa = (struct sockaddr *)&ss;
327   memset (&ss, 0, sizeof (ss));
328
329   msock = -1;
330
331 #ifdef ENABLE_IPV6
332   if (bind_address->type == IPV6_ADDRESS) 
333     family = AF_INET6;
334 #endif
335   
336   if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
337     return CONSOCKERR;
338
339 #ifdef SO_REUSEADDR
340   optval = 1;
341   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
342                   (char *)&optval, sizeof (optval)) < 0)
343     return CONSOCKERR;
344 #endif
345
346 #ifdef ENABLE_IPV6
347 # ifdef HAVE_IPV6_V6ONLY
348   if (family == AF_INET6)
349     {
350       optval = 1;
351       /* if setsockopt fails, go on anyway */
352       setsockopt (msock, IPPROTO_IPV6, IPV6_V6ONLY,
353                   (char *)&optval, sizeof (optval));
354     }
355 # endif
356 #endif
357   
358   sockaddr_set_address (sa, htons (*port), bind_address);
359   if (bind (msock, sa, sockaddr_len (sa)) < 0)
360     {
361       CLOSE (msock);
362       msock = -1;
363       return BINDERR;
364     }
365   DEBUGP (("Master socket fd %d bound.\n", msock));
366   if (!*port)
367     {
368       socklen_t sa_len = sockaddr_len (sa);
369       if (getsockname (msock, sa, &sa_len) < 0)
370         {
371           CLOSE (msock);
372           msock = -1;
373           return CONPORTERR;
374         }
375       *port = sockaddr_get_port (sa);
376       DEBUGP (("binding to address %s using port %i.\n", 
377                pretty_print_address (bind_address), *port));
378     }
379   if (listen (msock, 1) < 0)
380     {
381       CLOSE (msock);
382       msock = -1;
383       return LISTENERR;
384     }
385   return BINDOK;
386 }
387
388 #ifdef HAVE_SELECT
389 /* Wait for file descriptor FD to be available, timing out after
390    MAXTIME seconds.  "Available" means readable if writep is 0,
391    writeable otherwise.
392
393    Returns 1 if FD is available, 0 for timeout and -1 for error.  */
394
395 int
396 select_fd (int fd, double maxtime, int writep)
397 {
398   fd_set fds;
399   fd_set *rd = NULL, *wrt = NULL;
400   struct timeval tmout;
401   int result;
402
403   FD_ZERO (&fds);
404   FD_SET (fd, &fds);
405   *(writep ? &wrt : &rd) = &fds;
406
407   tmout.tv_sec = (long)maxtime;
408   tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
409
410   do
411     result = select (fd + 1, rd, wrt, NULL, &tmout);
412   while (result < 0 && errno == EINTR);
413
414   /* When we've timed out, set errno to ETIMEDOUT for the convenience
415      of the caller. */
416   if (result == 0)
417     errno = ETIMEDOUT;
418
419   return result;
420 }
421 #endif /* HAVE_SELECT */
422
423 /* Call accept() on MSOCK and store the result to *SOCK.  This assumes
424    that bindport() has been used to initialize MSOCK to a correct
425    value.  It blocks the caller until a connection is established.  If
426    no connection is established for OPT.CONNECT_TIMEOUT seconds, the
427    function exits with an error status.  */
428 uerr_t
429 acceptport (int *sock)
430 {
431   struct sockaddr_storage ss;
432   struct sockaddr *sa = (struct sockaddr *)&ss;
433   socklen_t addrlen = sizeof (ss);
434
435 #ifdef HAVE_SELECT
436   if (select_fd (msock, opt.connect_timeout, 0) <= 0)
437     return ACCEPTERR;
438 #endif
439   if ((*sock = accept (msock, sa, &addrlen)) < 0)
440     return ACCEPTERR;
441   DEBUGP (("Created socket fd %d.\n", *sock));
442   return ACCEPTOK;
443 }
444
445 /* Close SOCK, as well as the most recently remembered MSOCK, created
446    via bindport().  If SOCK is -1, close MSOCK only.  */
447 void
448 closeport (int sock)
449 {
450   /*shutdown (sock, 2);*/
451   if (sock != -1)
452     CLOSE (sock);
453   if (msock != -1)
454     CLOSE (msock);
455   msock = -1;
456 }
457
458 /* Return the local IP address associated with the connection on FD.  */
459
460 int
461 conaddr (int fd, ip_address *ip)
462 {
463   struct sockaddr_storage storage;
464   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
465   socklen_t addrlen = sizeof (storage);
466
467   if (getsockname (fd, sockaddr, &addrlen) < 0)
468     return 0;
469
470   switch (sockaddr->sa_family)
471     {
472 #ifdef ENABLE_IPV6
473     case AF_INET6:
474       {
475         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
476         ip->type = IPV6_ADDRESS;
477         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
478 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
479         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
480 #endif
481         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
482         return 1;
483       }
484 #endif
485     case AF_INET:
486       {
487         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
488         ip->type = IPV4_ADDRESS;
489         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
490         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
491         return 1;
492       }
493     default:
494       abort ();
495     }
496
497   return 0;
498 }
499
500 /* Read at most LEN bytes from FD, storing them to BUF.  This is
501    virtually the same as read(), but takes care of EINTR braindamage
502    and uses select() to timeout the stale connections (a connection is
503    stale if more than OPT.READ_TIMEOUT time is spent in select() or
504    read()).  */
505
506 int
507 iread (int fd, char *buf, int len)
508 {
509   int res;
510
511 #ifdef HAVE_SELECT
512   if (opt.read_timeout)
513     if (select_fd (fd, opt.read_timeout, 0) <= 0)
514       return -1;
515 #endif
516   do
517     res = READ (fd, buf, len);
518   while (res == -1 && errno == EINTR);
519
520   return res;
521 }
522
523 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
524    unlike iread(), it makes sure that all of BUF is actually written
525    to FD, so callers needn't bother with checking that the return
526    value equals to LEN.  Instead, you should simply check for -1.  */
527
528 int
529 iwrite (int fd, char *buf, int len)
530 {
531   int res = 0;
532
533   /* `write' may write less than LEN bytes, thus the outward loop
534      keeps trying it until all was written, or an error occurred.  The
535      inner loop is reserved for the usual EINTR f*kage, and the
536      innermost loop deals with the same during select().  */
537   while (len > 0)
538     {
539 #ifdef HAVE_SELECT
540       if (opt.read_timeout)
541         if (select_fd (fd, opt.read_timeout, 1) <= 0)
542           return -1;
543 #endif
544       do
545         res = WRITE (fd, buf, len);
546       while (res == -1 && errno == EINTR);
547       if (res <= 0)
548         break;
549       buf += res;
550       len -= res;
551     }
552   return res;
553 }