From 1cfde0c27dfb57320a2fc44df50c3731336e4c33 Mon Sep 17 00:00:00 2001 From: hniksic Date: Thu, 13 Nov 2003 12:26:18 -0800 Subject: [PATCH] [svn] Correctly check for unsupported socket families. --- src/ChangeLog | 6 +++ src/connect.c | 102 +++++++++++++++++++++++++++++++++----------------- src/connect.h | 2 + src/wget.h | 18 ++++----- 4 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 068f92b3..0bd2ec89 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2003-11-13 Hrvoje Niksic + + * wget.h (CONNECT_ERROR): Use it. + + * connect.c (unsupported_socket_family_error): New function. + 2003-11-13 Hrvoje Niksic * connect.c (bind_local): Renamed bindport to bind_local; return diff --git a/src/connect.c b/src/connect.c index 46b0aa02..f73c9501 100644 --- a/src/connect.c +++ b/src/connect.c @@ -484,41 +484,6 @@ bind_local (const ip_address *bind_address, int *port) return sock; } -#ifdef HAVE_SELECT -/* Wait for file descriptor FD to be readable or writable or both, - timing out after MAXTIME seconds. Returns 1 if FD is available, 0 - for timeout and -1 for error. The argument WAIT_FOR can be a - combination of WAIT_READ and WAIT_WRITE. - - This is a mere convenience wrapper around the select call, and - should be taken as such. */ - -int -select_fd (int fd, double maxtime, int wait_for) -{ - fd_set fdset; - fd_set *rd = NULL, *wr = NULL; - struct timeval tmout; - int result; - - FD_ZERO (&fdset); - FD_SET (fd, &fdset); - if (wait_for & WAIT_FOR_READ) - rd = &fdset; - if (wait_for & WAIT_FOR_WRITE) - wr = &fdset; - - tmout.tv_sec = (long) maxtime; - tmout.tv_usec = 1000000L * (maxtime - (long) maxtime); - - do - result = select (fd + 1, rd, wr, NULL, &tmout); - while (result < 0 && errno == EINTR); - - return result; -} -#endif /* HAVE_SELECT */ - /* Like a call to accept(), but with the added check for timeout. In other words, accept a client connection on LOCAL_SOCK, and @@ -608,6 +573,73 @@ socket_ip_address (int sock, ip_address *ip, int endpoint) return 0; } + +/* Return non-zero of the errno code passed to the function is a + result of an attempt to create a socket of unsupported family. */ + +int +unsupported_socket_family_error (int err) +{ + /* Have to guard against some of these values not being defined. + Cannot use switch because some of the values might be equal. */ +#ifdef EAFNOSUPPORT + if (err == EAFNOSUPPORT) return 1; +#endif +#ifdef EPFNOSUPPORT + if (err == EPFNOSUPPORT) return 1; +#endif +#ifdef ESOCKTNOSUPPORT /* no, "sockt" is not a typo! */ + if (err == ESOCKTNOSUPPORT) return 1; +#endif +#ifdef EPROTONOSUPPORT + if (err == EPROTONOSUPPORT) return 1; +#endif +#ifdef ENOPROTOOPT + if (err == ENOPROTOOPT) return 1; +#endif + /* Apparently, older versions of Linux used EINVAL instead of + EAFNOSUPPORT. */ + if (err == EINVAL) return 1; + + return 0; +} + +#ifdef HAVE_SELECT + +/* Wait for file descriptor FD to be readable or writable or both, + timing out after MAXTIME seconds. Returns 1 if FD is available, 0 + for timeout and -1 for error. The argument WAIT_FOR can be a + combination of WAIT_READ and WAIT_WRITE. + + This is a mere convenience wrapper around the select call, and + should be taken as such. */ + +int +select_fd (int fd, double maxtime, int wait_for) +{ + fd_set fdset; + fd_set *rd = NULL, *wr = NULL; + struct timeval tmout; + int result; + + FD_ZERO (&fdset); + FD_SET (fd, &fdset); + if (wait_for & WAIT_FOR_READ) + rd = &fdset; + if (wait_for & WAIT_FOR_WRITE) + wr = &fdset; + + tmout.tv_sec = (long) maxtime; + tmout.tv_usec = 1000000L * (maxtime - (long) maxtime); + + do + result = select (fd + 1, rd, wr, NULL, &tmout); + while (result < 0 && errno == EINTR); + + return result; +} + +#endif /* HAVE_SELECT */ /* Basic socket operations, mostly EINTR wrappers. */ diff --git a/src/connect.h b/src/connect.h index 9d67d070..8872ee78 100644 --- a/src/connect.h +++ b/src/connect.h @@ -56,6 +56,8 @@ enum { }; int socket_ip_address PARAMS ((int, ip_address *, int)); +int unsupported_socket_family_error PARAMS ((int)); + /* Flags for select_fd's WAIT_FOR argument. */ enum { WAIT_FOR_READ = 1, diff --git a/src/wget.h b/src/wget.h index 6cdfbeb0..edc15990 100644 --- a/src/wget.h +++ b/src/wget.h @@ -223,15 +223,15 @@ typedef enum SSLERRCERTFILE,SSLERRCERTKEY,SSLERRCTXCREATE } uerr_t; -/* In case old systems don't have EAFNOSUPPORT, which we use below. */ -#ifndef EAFNOSUPPORT -# define EAFNOSUPPORT EINVAL -#endif - -#define CONNECT_ERROR(err) (( (err) == EAFNOSUPPORT \ - || (err) == EINVAL \ - || ((err) == ECONNREFUSED \ - && !opt.retry_connrefused)) \ +/* Whether the connection was unsuccessful or impossible. If the + connection is considered impossible (e.g. for unsupported socket + family errors), there is no sense in retrying. "Connection + refused" is normally not retried, except when opt.retry_connrefused + is specified. */ + +#define CONNECT_ERROR(err) ((unsupported_socket_family_error (err) \ + || ((err) == ECONNREFUSED \ + && !opt.retry_connrefused)) \ ? CONIMPOSSIBLE : CONERROR) #endif /* WGET_H */ -- 2.39.2