diff options
-rw-r--r-- | lib/easy.c | 3 | ||||
-rw-r--r-- | lib/url.c | 173 | ||||
-rw-r--r-- | lib/urldata.h | 1 |
3 files changed, 176 insertions, 1 deletions
diff --git a/lib/easy.c b/lib/easy.c index f45132b9d..8f2de5ece 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -109,6 +109,9 @@ CURL *curl_easy_init(void) return NULL; data->interf = CURLI_EASY; /* mark it as an easy one */ + /* SAC */ + data->device = NULL; + return data; } @@ -52,7 +52,6 @@ #include <errno.h> - #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #include <winsock.h> #include <time.h> @@ -498,6 +497,9 @@ CURLcode curl_setopt(CURL *curl, CURLoption option, ...) case CURLOPT_QUOTE: data->quote = va_arg(param, struct curl_slist *); break; + case CURLOPT_INTERFACE: + data->device = va_arg(param, char *); + break; default: /* unknown tag and its companion, just ignore: */ return CURLE_READ_ERROR; /* correct this */ @@ -1176,6 +1178,136 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect) conn->serv_addr.sin_family = conn->hp->h_addrtype; conn->serv_addr.sin_port = htons(data->port); +/* sck 8/31/2000 add support for specifing device to bind socket to */ +/* #ifdef LINUX */ +/* I am using this, but it may not work everywhere, only tested on RedHat 6.2 */ +#ifdef HAVE_INET_NTOA + +#ifndef INADDR_NONE +#define INADDR_NONE (unsigned long) ~0 +#endif + + if (data->device && (strlen(data->device)<255)) { + struct ifreq ifr; + struct sockaddr_in sa; + struct hostent *h=NULL; + size_t size; + unsigned short porttouse; + char myhost[256] = ""; + unsigned long in; + + if(if2ip(data->device, myhost, sizeof(myhost))) { + h = GetHost(data, myhost, hostent_buf, sizeof(hostent_buf)); + } + else { + if(strlen(data->device)>1) { + h = GetHost(data, data->device, hostent_buf, + sizeof(hostent_buf)); + } + if(h) { + strcpy(myhost,data->device); + } + } + + if(! *myhost) { + /* need to fix this + h=GetHost(data, + getmyhost(*myhost,sizeof(myhost)), + hostent_buf, + sizeof(hostent_buf)); + */ + printf("in here\n"); + } + + infof(data, "We connect from %s\n", myhost); + + if ( (in=inet_addr(myhost)) != INADDR_NONE ) { + + if ( h ) { + memset((char *)&sa, 0, sizeof(sa)); + memcpy((char *)&sa.sin_addr, + h->h_addr, + h->h_length); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = in; + sa.sin_port = 0; /* get any port */ + + if( bind(data->firstsocket, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { + /* we succeeded to bind */ + struct sockaddr_in add; + + size = sizeof(add); + if(getsockname(data->firstsocket, (struct sockaddr *) &add, + (int *)&size)<0) { + failf(data, "getsockname() failed"); + return CURLE_HTTP_PORT_FAILED; + } + } + else { + switch(errno) { + case EBADF: + failf(data, "Invalid descriptor: %d", errno); + break; + case EINVAL: + failf(data, "Invalid request: %d", errno); + break; + case EACCES: + failf(data, "Address is protected, user not superuser: %d", errno); + break; + case ENOTSOCK: + failf(data, + "Argument is a descriptor for a file, not a socket: %d", + errno); + break; + case EFAULT: + failf(data, "Inaccessable memory error: %d", errno); + break; + case ENAMETOOLONG: + failf(data, "Address too long: %d", errno); + break; + case ENOMEM: + failf(data, "Insufficient kernel memory was available: %d", errno); + break; +#if 0 + case EROFS: + failf(data, + "Socket inode would reside on a read-only file system: %d", + errno); + break; + case ENOENT: + failf(data, "File does not exist: %d", errno); + break; + case ENOTDIR: + failf(data, "Component of path prefix is not a directory: %d", + errno); + break; + case ELOOP: + failf(data,"Too many symbolic links encountered: %d",errno); + break; +#endif + default: + failf(data,"errno %d\n"); + } /* end of switch */ + + return CURLE_HTTP_PORT_FAILED; + } /* end of else */ + + } /* end of if h */ + else { + failf(data,"could't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; + } + + } /* end of inet_addr */ + + else { + failf(data, "could't find my own IP address (%s)", myhost); + return CURLE_HTTP_PORT_FAILED; + } + + } /* end of device selection support */ +#endif /* end of HAVE_INET_NTOA */ + if (connect(data->firstsocket, (struct sockaddr *) &(conn->serv_addr), sizeof(conn->serv_addr) @@ -1186,12 +1318,51 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect) case ECONNREFUSED: failf(data, "Connection refused"); break; + case EFAULT: + failf(data, "Invalid socket address: %d",errno); + break; + case EISCONN: + failf(data, "Socket already connected: %d",errno); + break; + case ETIMEDOUT: + failf(data, "Timeout while accepting connection, server busy: %d",errno); + break; + case ENETUNREACH: + failf(data, "Network is unreachable: %d",errno); + break; + case EADDRINUSE: + failf(data, "Local address already in use: %d",errno); + break; + case EINPROGRESS: + failf(data, "Socket is nonblocking and connection can not be completed immediately: %d",errno); + break; + case EALREADY: + failf(data, "Socket is nonblocking and a previous connection attempt not completed: %d",errno); + break; + case EAGAIN: + failf(data, "No more free local ports: %d",errno); + break; + case EACCES: + case EPERM: + failf(data, "Attempt to connect to broadcast address without socket broadcast flag or local firewall rule violated: %d",errno); + break; #endif #ifdef EINTR case EINTR: failf(data, "Connection timeouted"); break; #endif +#if 0 + case EAFNOSUPPORT: + failf(data, "Incorrect address family: %d",errno); + break; + case ENOTSOCK: + failf(data, "File descriptor is not a socket: %d",errno); + break; + case EBADF: + failf(data, "File descriptor is not a valid index in descriptor table: %d",errno); + break; +#endif default: failf(data, "Can't connect to server: %d", errno); break; diff --git a/lib/urldata.h b/lib/urldata.h index 8b28632f9..4d268bd55 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -356,6 +356,7 @@ struct UrlData { char *useragent; /* User-Agent string */ char *ftpport; /* port to send with the PORT command */ + char *device; /* Interface to use */ /* function that stores the output:*/ curl_write_callback fwrite; |