diff options
author | David Cantrell <dcantrell@redhat.com> | 2006-07-26 21:27:11 +0000 |
---|---|---|
committer | David Cantrell <dcantrell@redhat.com> | 2006-07-26 21:27:11 +0000 |
commit | af9c49fa0485c76ebeb0b2dd560effccd3821751 (patch) | |
tree | fcac21399ac629cff537b38fb4d67e1c0f48ebe9 /loader2 | |
parent | af6c15155a36f2ee5eace7fa88c2ec2daa8c9e16 (diff) | |
download | anaconda-af9c49fa0485c76ebeb0b2dd560effccd3821751.tar.gz anaconda-af9c49fa0485c76ebeb0b2dd560effccd3821751.tar.xz anaconda-af9c49fa0485c76ebeb0b2dd560effccd3821751.zip |
* loader2/urls.c (urlinstStartTransfer): Determine address family
and pass that to the ftpOpen() call.
* urlinstall.py (UrlInstallMethod.__init__): Use urlparse.
* isys/dns.c, isys/dns.h: Updated for IPv6 support.
* loader2/Makefile: Cleanups.
* loader2/ftp.c, loader2/ftp.h: Updated for IPv6 support.
* loader2/loader.c: Whitespace consistency.
* loader2/method.c: Whitespace consistency.
* loader2/urls.c: Updated for IPv6 support.
Diffstat (limited to 'loader2')
-rw-r--r-- | loader2/Makefile | 26 | ||||
-rw-r--r-- | loader2/ftp.c | 563 | ||||
-rw-r--r-- | loader2/ftp.h | 5 | ||||
-rw-r--r-- | loader2/loader.c | 14 | ||||
-rw-r--r-- | loader2/method.c | 9 | ||||
-rw-r--r-- | loader2/urls.c | 32 |
6 files changed, 367 insertions, 282 deletions
diff --git a/loader2/Makefile b/loader2/Makefile index 7cafd9434..f69594fd1 100644 --- a/loader2/Makefile +++ b/loader2/Makefile @@ -7,27 +7,27 @@ else TARGET=depend $(PROGS) endif +LIBS = -lnewt -lslang -lz -ldevmapper -lpopt ../isys/libisys.a + # glib - for utility stuff -GLIB = $(shell pkg-config --libs glib-2.0) +LIBS += $(shell pkg-config --libs glib-2.0) CFLAGS += $(shell pkg-config --cflags glib-2.0) # dhcp library flags -DHCP = $(shell pkg-config --libs libdhcp) +LIBS += $(shell pkg-config --libs libdhcp) CFLAGS += $(shell pkg-config --cflags libdhcp) # nash library flags -NASH = $(shell pkg-config --libs libnash) +LIBS += $(shell pkg-config --libs libnash) CFLAGS += $(shell pkg-config --cflags libnash) -SLANGLIB = -lslang -NEWTLIB = -lnewt -ISYSLIB = ../isys/libisys.a -GUNZIP = -lz -DMLIB = -ldevmapper ifeq (1, $(USESELINUX)) -DMLIB += -lselinux -lsepol +LIBS += -lselinux -lsepol endif +# These libs need to be on the end of the link list +LIBS += -lresolv -lm + BINS = loader HWOBJS = pcmcia.o usb.o firewire.o hardware.o @@ -42,7 +42,7 @@ NETOBJS = net.o urls.o ftp.o telnet.o telnetd.o PCMCIAOBJS = pcmcia.o $(NETOBJS) SOURCES = $(subst .o,.c,$(OBJS)) loader.c -HWLIBS = -lkudzu_loader -lpci +LIBS += -lkudzu_loader -lpci # NSS linker flags NSSFLAGS = -Wl,-rpath-link,/nss @@ -51,7 +51,7 @@ CFLAGS += -DUSE_LOGDEV -DVERSION='"$(VERSION)"' STATIC = -static REALCC=gcc -UNICODELIB = ../stubs/libunicode-lite.a ../wlite/libwlite.a +LIBS += ../stubs/libunicode-lite.a ../wlite/libwlite.a # linuxrc + shutdown on s390, init everywhere else ifneq (,$(filter s390 s390x,$(ARCH))) @@ -114,9 +114,7 @@ loader-net.o: loader.c $(CC) -DINCLUDE_NETWORK $(CFLAGS) -o $@ -c $< loader: loader.o $(OBJS) $(NETOBJS) - $(CC) -g $(STATIC) $(NSSFLAGS) -o $@ $^ -lpopt \ - $(HWLIBS) $(ISYSLIB) $(GUNZIP) $(UNICODELIB) \ - -lresolv $(NEWTLIB) $(SLANGLIB) $(DMLIB) $(GLIB) $(DHCP) $(NASH) -lm + $(CC) -g $(STATIC) $(NSSFLAGS) -o $@ $^ $(LIBS) clean: rm -f *.o *~ .depend init ctype.c mkctype \ diff --git a/loader2/ftp.c b/loader2/ftp.c index 6efd6a2cd..6e6d402a9 100644 --- a/loader2/ftp.c +++ b/loader2/ftp.c @@ -4,8 +4,9 @@ * Erik Troan <ewt@redhat.com> * Matt Wilson <msw@redhat.com> * Jeremy Katz <katzj@redhat.com> + * David Cantrell <dcantrell@redhat.com> * - * Copyright 1997 - 2002 Red Hat, Inc. + * Copyright 1997 - 2006 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * General Public License. @@ -15,8 +16,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - #define HAVE_ALLOCA_H 1 #define HAVE_NETINET_IN_SYSTM_H 1 #define HAVE_SYS_SOCKET_H 1 @@ -69,10 +68,11 @@ extern int h_errno; #endif #include "ftp.h" +#include "log.h" static int ftpCheckResponse(int sock, char ** str); static int ftpCommand(int sock, char * command, ...); -static int getHostAddress(const char * host, struct in_addr * address); +static int getHostAddress(const char * host, void * address, int family); static int ftpCheckResponse(int sock, char ** str) { static char buf[BUFFER_SIZE + 1]; @@ -87,76 +87,76 @@ static int ftpCheckResponse(int sock, char ** str) { errorCode[0] = '\0'; do { - FD_ZERO(&emptySet); - FD_ZERO(&readSet); - FD_SET(sock, &readSet); + FD_ZERO(&emptySet); + FD_ZERO(&readSet); + FD_SET(sock, &readSet); - timeout.tv_sec = TIMEOUT_SECS; - timeout.tv_usec = 0; + timeout.tv_sec = TIMEOUT_SECS; + timeout.tv_usec = 0; - rc = select(sock + 1, &readSet, &emptySet, &emptySet, &timeout); - if (rc < 1) { - if (rc==0) - return FTPERR_BAD_SERVER_RESPONSE; - else - rc = FTPERR_UNKNOWN; - } else - rc = 0; - - bytesRead = read(sock, buf + bufLength, sizeof(buf) - bufLength - 1); - - bufLength += bytesRead; - - buf[bufLength] = '\0'; - - /* divide the response into lines, checking each one to see if - we are finished or need to continue */ - - start = chptr = buf; - - do { - while (*chptr != '\n' && *chptr) chptr++; - - if (*chptr == '\n') { - *chptr = '\0'; - if (*(chptr - 1) == '\r') *(chptr - 1) = '\0'; - if (str) *str = start; - - if (errorCode[0]) { - if (!strncmp(start, errorCode, 3) && start[3] == ' ') - doesContinue = 0; - } else { - strncpy(errorCode, start, 3); - errorCode[3] = '\0'; - if (start[3] != '-') { - doesContinue = 0; - } - } - - start = chptr + 1; - chptr++; - } else { - chptr++; - } - } while (*chptr); - - if (doesContinue && chptr > start) { - memcpy(buf, start, chptr - start - 1); - bufLength = chptr - start - 1; - } else { - bufLength = 0; - } + rc = select(sock + 1, &readSet, &emptySet, &emptySet, &timeout); + if (rc < 1) { + if (rc==0) + return FTPERR_BAD_SERVER_RESPONSE; + else + rc = FTPERR_UNKNOWN; + } else { + rc = 0; + } + + bytesRead = read(sock, buf + bufLength, sizeof(buf) - bufLength - 1); + + bufLength += bytesRead; + + buf[bufLength] = '\0'; + + /* divide the response into lines, checking each one to see if + we are finished or need to continue */ + + start = chptr = buf; + + do { + while (*chptr != '\n' && *chptr) chptr++; + + if (*chptr == '\n') { + *chptr = '\0'; + if (*(chptr - 1) == '\r') *(chptr - 1) = '\0'; + if (str) *str = start; + + if (errorCode[0]) { + if (!strncmp(start, errorCode, 3) && start[3] == ' ') + doesContinue = 0; + } else { + strncpy(errorCode, start, 3); + errorCode[3] = '\0'; + if (start[3] != '-') { + doesContinue = 0; + } + } + + start = chptr + 1; + chptr++; + } else { + chptr++; + } + } while (*chptr); + + if (doesContinue && chptr > start) { + memcpy(buf, start, chptr - start - 1); + bufLength = chptr - start - 1; + } else { + bufLength = 0; + } } while (doesContinue && !rc); if (*errorCode == '4' || *errorCode == '5') { - if (!strncmp(errorCode, "421", 3)) { - return FTPERR_TOO_MANY_CONNECTIONS; - } - else if (!strncmp(errorCode, "550", 3)) { - return FTPERR_FILE_NOT_FOUND; - } - - return FTPERR_BAD_SERVER_RESPONSE; + if (!strncmp(errorCode, "421", 3)) { + return FTPERR_TOO_MANY_CONNECTIONS; + } else if (!strncmp(errorCode, "550", 3)) { + return FTPERR_FILE_NOT_FOUND; + } + + return FTPERR_BAD_SERVER_RESPONSE; } if (rc) return rc; @@ -175,8 +175,8 @@ int ftpCommand(int sock, char * command, ...) { len = strlen(command) + 2; s = va_arg(ap, char *); while (s) { - len += strlen(s) + 1; - s = va_arg(ap, char *); + len += strlen(s) + 1; + s = va_arg(ap, char *); } va_end(ap); @@ -187,9 +187,9 @@ int ftpCommand(int sock, char * command, ...) { strcat(buf, " "); s = va_arg(ap, char *); while (s) { - strcat(buf, s); - strcat(buf, " "); - s = va_arg(ap, char *); + strcat(buf, s); + strcat(buf, " "); + s = va_arg(ap, char *); } va_end(ap); @@ -202,31 +202,54 @@ int ftpCommand(int sock, char * command, ...) { } if ((rc = ftpCheckResponse(sock, NULL))) - return rc; + return rc; return 0; } - -static int getHostAddress(const char * host, struct in_addr * address) { - if (isdigit(host[0])) { - if (!inet_pton(AF_INET, host, address)) { - return FTPERR_BAD_HOST_ADDR; - } +static int getHostAddress(const char * host, void * address, int family) { + struct hostent * he; + + if (family == AF_INET) { + if (isdigit(host[0])) { + if (inet_pton(AF_INET, host, (struct in_addr *)address) >= 1) + return 0; + else + return FTPERR_BAD_HOST_ADDR; + } else { + he = gethostbyname2(host, AF_INET); + if (he == NULL) { + errno = h_errno; + return FTPERR_BAD_HOSTNAME; + } else { + address = he->h_addr_list[0]; + return 0; + } + } + } else if (family == AF_INET6) { + if (strchr(host, ':')) { + if (inet_pton(AF_INET6, host, (struct in_addr6 *)address) >= 1) { + return 0; + } else + return FTPERR_BAD_HOST_ADDR; + } else { + he = gethostbyname2(host, AF_INET6); + if (he == NULL) { + errno = h_errno; + return FTPERR_BAD_HOSTNAME; + } else { + address = he->h_addr_list[0]; + return 0; + } + } } else { - if (mygethostbyname((char *) host, address)) { - errno = h_errno; - return FTPERR_BAD_HOSTNAME; - } + return FTPERR_UNSUPPORTED_FAMILY; } - - return 0; } -int ftpOpen(char * host, char * name, char * password, char * proxy, - int port) { +int ftpOpen(char *host, int family, char *name, char *password, + char *proxy, int port) { static int sock; - /*static char * lastHost = NULL;*/ struct in_addr serverAddress; struct sockaddr_in destPort; struct passwd * pw; @@ -236,28 +259,27 @@ int ftpOpen(char * host, char * name, char * password, char * proxy, if (port < 0) port = IPPORT_FTP; if (!name) - name = "anonymous"; + name = "anonymous"; if (!password) { - password = "root@"; - if (getuid()) { - pw = getpwuid(getuid()); - if (pw) { - password = alloca(strlen(pw->pw_name) + 2); - strcpy(password, pw->pw_name); - strcat(password, "@"); - } - } + password = "root@"; + if (getuid()) { + pw = getpwuid(getuid()); + if (pw) { + password = alloca(strlen(pw->pw_name) + 2); + strcpy(password, pw->pw_name); + strcat(password, "@"); + } + } } if (proxy) { - buf = alloca(strlen(name) + strlen(host) + 5); - sprintf(buf, "%s@%s", name, host); - name = buf; - host = proxy; + asprintf(&buf, "%s@%s", name, host); + name = buf; + host = proxy; } - if ((rc = getHostAddress(host, &serverAddress))) return rc; + if ((rc = getHostAddress(host, &serverAddress, AF_INET))) return rc; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { @@ -269,13 +291,13 @@ int ftpOpen(char * host, char * name, char * password, char * proxy, destPort.sin_addr = serverAddress; if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { - close(sock); + close(sock); return FTPERR_FAILED_CONNECT; } /* ftpCheckResponse() assumes the socket is nonblocking */ if (fcntl(sock, F_SETFL, O_NONBLOCK)) { - close(sock); + close(sock); return FTPERR_FAILED_CONNECT; } @@ -284,18 +306,18 @@ int ftpOpen(char * host, char * name, char * password, char * proxy, } if ((rc = ftpCommand(sock, "USER", name, NULL))) { - close(sock); - return rc; + close(sock); + return rc; } if ((rc = ftpCommand(sock, "PASS", password, NULL))) { - close(sock); - return rc; + close(sock); + return rc; } if ((rc = ftpCommand(sock, "TYPE", "I", NULL))) { - close(sock); - return rc; + close(sock); + return rc; } return sock; @@ -314,7 +336,7 @@ int ftpGetFileDesc(int sock, char * remotename) { return FTPERR_SERVER_IO_ERROR; } if ((rc = ftpCheckResponse(sock, &passReply))) - return FTPERR_PASSIVE_ERROR; + return FTPERR_PASSIVE_ERROR; chptr = passReply; while (*chptr && *chptr != '(') chptr++; @@ -337,17 +359,17 @@ int ftpGetFileDesc(int sock, char * remotename) { dataAddress.sin_family = AF_INET; if (sscanf(chptr, "%d,%d", &i, &j) != 2) { - return FTPERR_PASSIVE_ERROR; + return FTPERR_PASSIVE_ERROR; } dataAddress.sin_port = htons((i << 8) + j); chptr = passReply; while (*chptr++) { - if (*chptr == ',') *chptr = '.'; + if (*chptr == ',') *chptr = '.'; } if (!inet_pton(AF_INET, passReply, &dataAddress.sin_addr)) - return FTPERR_PASSIVE_ERROR; + return FTPERR_PASSIVE_ERROR; dataSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (dataSocket < 0) { @@ -363,14 +385,14 @@ int ftpGetFileDesc(int sock, char * remotename) { } if (connect(dataSocket, (struct sockaddr *) &dataAddress, - sizeof(dataAddress))) { - close(dataSocket); + sizeof(dataAddress))) { + close(dataSocket); return FTPERR_FAILED_DATA_CONNECT; } if ((rc = ftpCheckResponse(sock, NULL))) { - close(dataSocket); - return rc; + close(dataSocket); + return rc; } return dataSocket; @@ -378,58 +400,73 @@ int ftpGetFileDesc(int sock, char * remotename) { int ftpGetFileDone(int sock) { if (ftpCheckResponse(sock, NULL)) { - return FTPERR_BAD_SERVER_RESPONSE; + return FTPERR_BAD_SERVER_RESPONSE; } return 0; } const char *ftpStrerror(int errorNumber, urlprotocol protocol) { - switch (errorNumber) { - case FTPERR_BAD_SERVER_RESPONSE: - return(protocol == URL_METHOD_FTP ? "Bad FTP server response" : - "Bad HTTP server response"); - - case FTPERR_SERVER_IO_ERROR: - return(protocol == URL_METHOD_FTP ? "FTP IO error" : "HTTP IO error"); - - case FTPERR_SERVER_TIMEOUT: - return(protocol == URL_METHOD_FTP ? "FTP server timeout" : - "HTTP server timeout"); - - case FTPERR_BAD_HOST_ADDR: - return(protocol == URL_METHOD_FTP ? "Unable to lookup FTP server host address" : - "Unable to lookup HTTP server host address"); - - case FTPERR_BAD_HOSTNAME: - return(protocol == URL_METHOD_FTP ? "Unable to lookup FTP server host name" : - "Unable to lookup HTTP server host name"); - - case FTPERR_FAILED_CONNECT: - return(protocol == URL_METHOD_FTP ? "Failed to connect to FTP server" : - "Failed to connect to HTTP server"); - - case FTPERR_FAILED_DATA_CONNECT: - return(protocol == URL_METHOD_FTP ? "Failed to establish data connection to FTP server" : - "Failed to establish data connection to HTTP server"); - - case FTPERR_FILE_IO_ERROR: - return("IO error to local file"); - - case FTPERR_PASSIVE_ERROR: - return("Error setting remote server to passive mode"); - - case FTPERR_FILE_NOT_FOUND: - return("File not found on server"); - - case FTPERR_TOO_MANY_CONNECTIONS: - return(protocol == URL_METHOD_FTP ? "Too many connections to FTP server" : - "Too many connections to HTTP server"); - - case FTPERR_UNKNOWN: - default: - return("Unknown or unexpected error"); - } + switch (errorNumber) { + case FTPERR_PERMISSION_DENIED: + return(protocol == URL_METHOD_FTP ? "FTP permission denied" : + "HTTP permission denied"); + + case FTPERR_BAD_SERVER_RESPONSE: + return(protocol == URL_METHOD_FTP ? "Bad FTP server response" : + "Bad HTTP server response"); + + case FTPERR_SERVER_IO_ERROR: + return(protocol == URL_METHOD_FTP ? "FTP IO error" : + "HTTP IO error"); + + case FTPERR_SERVER_TIMEOUT: + return(protocol == URL_METHOD_FTP ? "FTP server timeout" : + "HTTP server timeout"); + + case FTPERR_BAD_HOST_ADDR: + return(protocol == URL_METHOD_FTP ? + "Unable to lookup FTP server host address" : + "Unable to lookup HTTP server host address"); + + case FTPERR_BAD_HOSTNAME: + return(protocol == URL_METHOD_FTP ? + "Unable to lookup FTP server host name" : + "Unable to lookup HTTP server host name"); + + case FTPERR_FAILED_CONNECT: + return(protocol == URL_METHOD_FTP ? + "Failed to connect to FTP server" : + "Failed to connect to HTTP server"); + + case FTPERR_FAILED_DATA_CONNECT: + return(protocol == URL_METHOD_FTP ? + "Failed to establish data connection to FTP server" : + "Failed to establish data connection to HTTP server"); + + case FTPERR_FILE_IO_ERROR: + return("IO error to local file"); + + case FTPERR_PASSIVE_ERROR: + return("Error setting remote server to passive mode"); + + case FTPERR_FILE_NOT_FOUND: + return("File not found on server"); + + case FTPERR_TOO_MANY_CONNECTIONS: + return(protocol == URL_METHOD_FTP ? + "Too many connections to FTP server" : + "Too many connections to HTTP server"); + + case FTPERR_UNSUPPORTED_FAMILY: + return(protocol == URL_METHOD_FTP ? + "Unsupported address family on FTP server" : + "Unsupported address family on HTTP server"); + + case FTPERR_UNKNOWN: + default: + return("Unknown or unexpected error"); + } } /* extraHeaders is either NULL or a string with extra headers separated by '\r\n', ending with @@ -443,46 +480,72 @@ int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHea char *realhost; char *hstr; int checkedCode; - struct in_addr serverAddress; + int family; + struct in_addr addr; + struct in6_addr addr6; int sock; int rc; struct sockaddr_in destPort; + struct sockaddr_in6 destPort6; fd_set readSet; + /* XXX: this won't work correctly for IPv6 */ +/* realhost = hostname; if (port < 0) { - char *colonptr = strchr(hostname, ':'); - if (colonptr != NULL) { - int realhostlen = colonptr - hostname; - port = atoi(colonptr + 1); - realhost = alloca (realhostlen + 1); - memcpy (realhost, hostname, realhostlen); - realhost[realhostlen] = '\0'; - } else { - port = 80; - } + char *colonptr = strchr(hostname, ':'); + if (colonptr != NULL) { + int realhostlen = colonptr - hostname; + port = atoi(colonptr + 1); + realhost = alloca (realhostlen + 1); + memcpy (realhost, hostname, realhostlen); + realhost[realhostlen] = '\0'; + } else { + port = 80; + } } +*/ + realhost = hostname; + port = 80; + + family = AF_INET; + rc = getHostAddress(realhost, &addr, family); + if (rc) { + family = AF_INET6; + rc = getHostAddress(realhost, &addr6, family); + if (rc) + return rc; + } - if ((rc = getHostAddress(realhost, &serverAddress))) return rc; - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + sock = socket(family, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { return FTPERR_FAILED_CONNECT; } - destPort.sin_family = AF_INET; - destPort.sin_port = htons(port); - destPort.sin_addr = serverAddress; - - if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { - close(sock); - return FTPERR_FAILED_CONNECT; + if (family == AF_INET) { + destPort.sin_family = family; + destPort.sin_port = htons(port); + destPort.sin_addr = addr; + + if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { + close(sock); + return FTPERR_FAILED_CONNECT; + } + } else if (family == AF_INET6) { + destPort6.sin6_family = family; + destPort6.sin6_port = htons(port); + destPort6.sin6_addr = addr6; + + if (connect(sock, (struct sockaddr *) &destPort6, sizeof(destPort6))) { + close(sock); + return FTPERR_FAILED_CONNECT; + } } if (extraHeaders) - hstr = extraHeaders; + hstr = extraHeaders; else - hstr = ""; + hstr = ""; buf = alloca(strlen(remotename) + strlen(realhost) + strlen(hstr) + 25); sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s\r\n", remotename, realhost, hstr); @@ -490,70 +553,74 @@ int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHea /* This is fun; read the response a character at a time until we: - 1) Get our first \r\n; which lets us check the return code - 2) Get a \r\n\r\n, which means we're done */ + 1) Get our first \r\n; which lets us check the return code + 2) Get a \r\n\r\n, which means we're done */ *nextChar = '\0'; checkedCode = 0; while (!strstr(headers, "\r\n\r\n")) { - FD_ZERO(&readSet); - FD_SET(sock, &readSet); + FD_ZERO(&readSet); + FD_SET(sock, &readSet); - timeout.tv_sec = TIMEOUT_SECS; - timeout.tv_usec = 0; + timeout.tv_sec = TIMEOUT_SECS; + timeout.tv_usec = 0; - rc = select(sock + 1, &readSet, NULL, NULL, &timeout); - if (rc == 0) { - close(sock); - return FTPERR_SERVER_TIMEOUT; - } else if (rc < 0) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - if (read(sock, nextChar, 1) != 1) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - nextChar++; - *nextChar = '\0'; - - if (nextChar - headers == sizeof(headers)) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - if (!checkedCode && strstr(headers, "\r\n")) { - char * start, * end; - - checkedCode = 1; - start = headers; - while (!isspace(*start) && *start) start++; - if (!*start) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - start++; - - end = start; - while (!isspace(*end) && *end) end++; - if (!*end) { - close(sock); - return FTPERR_SERVER_IO_ERROR; - } - - *end = '\0'; - if (!strcmp(start, "404")) { - close(sock); - return FTPERR_FILE_NOT_FOUND; - } else if (strcmp(start, "200")) { - close(sock); - return FTPERR_BAD_SERVER_RESPONSE; - } - - *end = ' '; - } + rc = select(sock + 1, &readSet, NULL, NULL, &timeout); + if (rc == 0) { + close(sock); + return FTPERR_SERVER_TIMEOUT; + } else if (rc < 0) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + if (read(sock, nextChar, 1) != 1) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + nextChar++; + *nextChar = '\0'; + + if (nextChar - headers == sizeof(headers)) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + if (!checkedCode && strstr(headers, "\r\n")) { + char * start, * end; + + checkedCode = 1; + start = headers; + while (!isspace(*start) && *start) start++; + if (!*start) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + start++; + + end = start; + while (!isspace(*end) && *end) end++; + if (!*end) { + close(sock); + return FTPERR_SERVER_IO_ERROR; + } + + *end = '\0'; + if (!strcmp(start, "404")) { + close(sock); + return FTPERR_FILE_NOT_FOUND; + } else if (!strcmp(start, "403")) { + close(sock); + return FTPERR_PERMISSION_DENIED; + } else if (strcmp(start, "200")) { + close(sock); + logMessage(ERROR, "bad HTTP response: %s", start); + return FTPERR_BAD_SERVER_RESPONSE; + } + + *end = ' '; + } } return sock; diff --git a/loader2/ftp.h b/loader2/ftp.h index d68d29326..99f7329d3 100644 --- a/loader2/ftp.h +++ b/loader2/ftp.h @@ -18,9 +18,12 @@ const char * ftpStrerror(int ftpErrno, urlprotocol protocol); #define FTPERR_TOO_MANY_CONNECTIONS -11 #define FTPERR_BAD_URL -12 #define FTPERR_TOO_MANY_REDIRECTS -13 +#define FTPERR_UNSUPPORTED_FAMILY -14 +#define FTPERR_PERMISSION_DENIED -15 #define FTPERR_UNKNOWN -100 -int ftpOpen(char * host, char * name, char * password, char * proxy, int port); +int ftpOpen(char * host, int family, char * name, char * password, + char * proxy, int port); int ftpGetFile(int sock, char * remotename, int dest); int ftpGetFileDesc(int sock, char * remotename); int ftpGetFileDone(int sock); diff --git a/loader2/loader.c b/loader2/loader.c index f92d6371e..985b637bf 100644 --- a/loader2/loader.c +++ b/loader2/loader.c @@ -180,22 +180,22 @@ static void initProductInfo(void) { f = fopen("/.buildstamp", "r"); if (!f) { productName = strdup("anaconda"); - productPath = strdup("anaconda"); + productPath = strdup("anaconda"); } else { - productName = malloc(256); - productPath = malloc(256); + productName = malloc(256); + productPath = malloc(256); productName = fgets(productName, 256, f); /* stamp time */ productName = fgets(productName, 256, f); /* product name */ - productPath = fgets(productPath, 256, f); /* product version */ - productPath = fgets(productPath, 256, f); /* product path */ + productPath = fgets(productPath, 256, f); /* product version */ + productPath = fgets(productPath, 256, f); /* product path */ i = strlen(productName) - 1; - while (isspace(*(productName + i))) { + while (isspace(*(productName + i))) { *(productName + i) = '\0'; i--; } i = strlen(productPath) - 1; - while (isspace(*(productPath + i))) { + while (isspace(*(productPath + i))) { *(productPath + i) = '\0'; i--; } diff --git a/loader2/method.c b/loader2/method.c index a507f67a6..47e070485 100644 --- a/loader2/method.c +++ b/loader2/method.c @@ -690,7 +690,7 @@ void setMethodFromCmdline(char * arg, struct loaderData_s * ld) { c = strtok(NULL, ":"); if (!strncmp(arg, "nfs:", 4)) { - ld->method = strdup("nfs"); + ld->method = strdup("nfs"); ld->methodData = calloc(sizeof(struct nfsInstallData *), 1); ((struct nfsInstallData *)ld->methodData)->host = strdup(c); if ((c = strtok(NULL, ":"))) { @@ -698,14 +698,14 @@ void setMethodFromCmdline(char * arg, struct loaderData_s * ld) { } } else if (!strncmp(arg, "ftp:", 4) || !strncmp(arg, "http:", 5)) { - ld->method = strcmp(arg, "ftp") ? strdup("ftp") : strdup("http"); + ld->method = strcmp(arg, "ftp") ? strdup("ftp") : strdup("http"); ld->methodData = calloc(sizeof(struct urlInstallData *), 1); ((struct urlInstallData *)ld->methodData)->url = strdup(arg); } else if (!strncmp(arg, "cdrom:", 6)) { - ld->method = strdup("cdrom"); + ld->method = strdup("cdrom"); } else if (!strncmp(arg, "harddrive:", 10) || !strncmp(arg, "hd:", 3)) { - ld->method = strdup("hd"); + ld->method = strdup("hd"); ld->methodData = calloc(sizeof(struct hdInstallData *), 1); ((struct hdInstallData *)ld->methodData)->partition = strdup(c); if ((c = strtok(NULL, ":"))) { @@ -714,5 +714,4 @@ void setMethodFromCmdline(char * arg, struct loaderData_s * ld) { } } free(dup); - } diff --git a/loader2/urls.c b/loader2/urls.c index 53e92ea39..d13a83f5f 100644 --- a/loader2/urls.c +++ b/loader2/urls.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <netdb.h> #include "../isys/dns.h" @@ -154,7 +155,10 @@ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, char *extraHeaders, int silentErrors) { char * buf; int fd; + int family = -1; char * finalPrefix; + struct in_addr addr; + struct in6_addr addr6; if (!strcmp(ui->prefix, "/")) finalPrefix = ""; @@ -171,8 +175,16 @@ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, ui->protocol == URL_METHOD_FTP ? "ftp" : "http", ui->address, buf); + if (inet_pton(AF_INET, ui->address, &addr) >= 1) + family = AF_INET; + else if (inet_pton(AF_INET6, ui->address, &addr6) >= 1) + family = AF_INET6; + else + logMessage(ERROR, "cannot determine address family of %s", + ui->address); + if (ui->protocol == URL_METHOD_FTP) { - ui->ftpPort = ftpOpen(ui->address, + ui->ftpPort = ftpOpen(ui->address, family, ui->login ? ui->login : "anonymous", ui->password ? ui->password : "rhinstall@", NULL, -1); @@ -189,8 +201,8 @@ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, close(ui->ftpPort); if (!silentErrors) newtWinMessage(_("Error"), _("OK"), - _("Failed to retrieve %s: %s"), buf, - ftpStrerror(fd, ui->protocol)); + _("Failed to retrieve %s: %s"), buf, + ftpStrerror(fd, ui->protocol)); return -1; } } else { @@ -198,8 +210,8 @@ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, if (fd < 0) { if (!silentErrors) newtWinMessage(_("Error"), _("OK"), - _("Failed to retrieve %s: %s"), buf, - ftpStrerror(fd, ui->protocol)); + _("Failed to retrieve %s: %s"), buf, + ftpStrerror(fd, ui->protocol)); return -1; } } @@ -223,12 +235,18 @@ int urlinstFinishTransfer(struct iurlinfo * ui, int fd) { } char * addrToIp(char * hostname) { + struct hostent *he; struct in_addr ad; struct in6_addr ad6; char *ret; - if (mygethostbyname(hostname, &ad)) - return hostname; + he = gethostbyname2(hostname, AF_INET); + if (he) + return he->h_name; + + he = gethostbyname2(hostname, AF_INET6); + if (he) + return he->h_name; if ((ret = malloc(48)) == NULL) return hostname; |