summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--isys/dns.c178
-rw-r--r--isys/dns.h2
-rw-r--r--isys/nfsmount.c22
-rw-r--r--loader2/Makefile26
-rw-r--r--loader2/ftp.c563
-rw-r--r--loader2/ftp.h5
-rw-r--r--loader2/loader.c14
-rw-r--r--loader2/method.c9
-rw-r--r--loader2/urls.c32
-rw-r--r--urlinstall.py48
11 files changed, 434 insertions, 484 deletions
diff --git a/ChangeLog b/ChangeLog
index 269e36dea..b0e9a89d3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2006-07-26 David Cantrell <dcantrell@redhat.com>
+
+ * 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.
+
2006-07-26 Peter Jones <pjones@redhat.com>
* partRequests.py (RaidRequestSpec.__init__): fslabel, not fslabe.
diff --git a/isys/dns.c b/isys/dns.c
index 06d127683..8b594b2fb 100644
--- a/isys/dns.c
+++ b/isys/dns.c
@@ -1,189 +1,37 @@
#include <alloca.h>
#include <sys/socket.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <stdlib.h>
#include <string.h>
-
-/* This is dumb, but glibc doesn't like to do hostname lookups w/o libc.so */
-
-#ifndef DIET
-union dns_response{
- HEADER hdr;
- u_char buf[PACKETSZ];
-} ;
-
-static int doQuery(char * query, int queryType,
- char ** domainName, struct in_addr * ipNum) {
- int len, ancount, type;
- u_char * data, * end;
- char name[MAXDNAME];
- union dns_response static_response, *response = &static_response;
- size_t response_len = sizeof(static_response);
-
- /* Give time to finish ethernet negotiation */
- _res.retry = 3;
-
- do {
- len = res_search(query, C_IN, queryType, (void*) response,
- response_len);
- if (len <= 0) return -1;
- if (len < response_len) break;
- if (response != &static_response) free(response);
- if (len > 0x10000) return -1;
- response_len = len + 1024;
- response = malloc(response_len);
- if (response == NULL) return -1;
- } while (1);
-
- if (len < sizeof(response->hdr)) {
- if (response != &static_response) free(response);
- return -1;
- }
- if (ntohs(response->hdr.rcode) != NOERROR) {
- if (response != &static_response) free(response);
- return -1;
- }
- ancount = ntohs(response->hdr.ancount);
- if (ancount < 1) {
- if (response != &static_response) free(response);
- return -1;
- }
-
- data = response->buf + sizeof(HEADER);
- end = response->buf + len;
-
- /* skip the question */
- len = dn_skipname(data, end);
- if (len <= 0) {
- if (response != &static_response) free(response);
- return -1;
- }
- data += len + QFIXEDSZ;
-
- /* parse the answer(s) */
- while (--ancount >= 0 && data < end) {
-
- /* skip the domain name portion of the RR record */
- data += dn_skipname(data, end);
-
- /* get RR information */
- if (data + 3 * INT16SZ + INT32SZ > end) {
- if (response != &static_response) free(response);
- return -1;
- }
- GETSHORT(type, data);
- data += INT16SZ; /* skip class */
- data += INT32SZ; /* skip TTL */
- GETSHORT(len, data);
-
- if (type == T_PTR) {
- /* we got a pointer */
- len = dn_expand(response->buf, end, data, name, sizeof(name));
- if (len <= 0) {
- if (response != &static_response) free(response);
- return -1;
- }
- if (queryType == T_PTR && domainName) {
- /* we wanted a pointer */
- *domainName = malloc(strlen(name) + 1);
- strcpy(*domainName, name);
- if (response != &static_response) free(response);
- return 0;
- }
- } else if (type == T_A) {
- /* we got an address */
- if (queryType == T_A && ipNum) {
- /* we wanted an address */
- memcpy(ipNum, data, sizeof(*ipNum));
- if (response != &static_response) free(response);
- return 0;
- }
- }
-
- /* move ahead to next RR */
- data += len;
- }
-
- if (response != &static_response) free(response);
- return -1;
-}
-
-char * mygethostbyaddr(char * ipnum) {
- int rc;
- char * result;
- char * strbuf;
- char * chptr;
- char * splits[4];
- int i;
-
- _res.retry = 1;
-
- strbuf = alloca(strlen(ipnum) + 1);
- strcpy(strbuf, ipnum);
-
- ipnum = alloca(strlen(strbuf) + 20);
-
- for (i = 0; i < 4; i++) {
- chptr = strbuf;
- while (*chptr && *chptr != '.') chptr++;
- *chptr = '\0';
-
- if (chptr - strbuf > 3) return NULL;
- splits[i] = strbuf;
- strbuf = chptr + 1;
- }
-
- sprintf(ipnum, "%s.%s.%s.%s.in-addr.arpa", splits[3], splits[2],
- splits[1], splits[0]);
-
- rc = doQuery(ipnum, T_PTR, &result, NULL);
- if (rc)
- rc = doQuery(ipnum, T_PTR, &result, NULL);
-
- if (rc)
- return NULL;
- else
- return result;
-}
-
-int mygethostbyname(char * name, struct in_addr * addr) {
- return doQuery(name, T_A, NULL, addr);
-}
-
-#else
#include <netdb.h>
-#include <sys/socket.h>
-#include <string.h>
-int mygethostbyname(char * host, struct in_addr * address) {
+#if 0
+int mygethostbyname(char * host, void * address, int family) {
struct hostent * hostinfo;
hostinfo = gethostbyname(host);
- if (!hostinfo) return 1;
+ if (hostinfo) return 1;
memcpy(address, hostinfo->h_addr_list[0], hostinfo->h_length);
return 0;
}
+#endif
-char * mygethostbyaddr(const char * ipnum) {
- struct hostent * he;
+struct hostent * mygethostbyaddr(const char * ipnum, int family) {
+ struct hostent * he = NULL;
struct in_addr addr;
+ struct in6_addr addr6;
- if (!inet_aton(ipnum, &addr))
- return NULL;
-
- he = gethostbyaddr(&addr, sizeof(struct in_addr), AF_INET);
- if (he)
- return he->h_name;
- else
- return NULL;
-}
+ if (family == AF_INET)
+ he = gethostbyaddr(&addr, sizeof(struct in_addr), AF_INET);
+ else if (family == AF_INET6)
+ he = gethostbyaddr(&addr6, sizeof(struct in6_addr), AF_INET6);
-#endif
+ return he;
+}
#if 0
int
diff --git a/isys/dns.h b/isys/dns.h
index 45bcb38bf..c19fe2571 100644
--- a/isys/dns.h
+++ b/isys/dns.h
@@ -3,7 +3,9 @@
#include <netinet/in.h>
+#if 0
int mygethostbyname(char * name, struct in_addr * addr);
+#endif
char * mygethostbyaddr(char * ipnum);
#endif
diff --git a/isys/nfsmount.c b/isys/nfsmount.c
index 53353434a..84002d6ce 100644
--- a/isys/nfsmount.c
+++ b/isys/nfsmount.c
@@ -310,11 +310,13 @@ int nfsmount(const char *spec, const char *node, int *flags,
if (!inet_aton(hostname, &server_addr.sin_addr))
#endif
{
- if (mygethostbyname(hostname, &server_addr.sin_addr)) {
+ struct hostent * he = gethostbyname(hostname);
+ if (he) {
+ memcpy(&server_addr.sin_addr, he->h_addr_list[0], he->h_length);
+ server_addr.sin_family = AF_INET;
+ } else {
myerror = ERROR_HOSTNAME;
goto fail;
- } else {
- server_addr.sin_family = AF_INET;
}
}
@@ -548,12 +550,14 @@ int nfsmount(const char *spec, const char *node, int *flags,
mount_server_addr.sin_family = AF_INET;
mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
} else {
- if (mygethostbyname(hostname, &mount_server_addr.sin_addr)) {
- myerror = ERROR_HOSTNAME;
- goto fail;
- } else {
- mount_server_addr.sin_family = AF_INET;
- }
+ struct hostent * he = gethostbyname(hostname);
+ if (he) {
+ memcpy(&server_addr.sin_addr, he->h_addr_list[0], he->h_length);
+ server_addr.sin_family = AF_INET;
+ } else {
+ myerror = ERROR_HOSTNAME;
+ goto fail;
+ }
}
}
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;
diff --git a/urlinstall.py b/urlinstall.py
index a6be87a15..340e1c516 100644
--- a/urlinstall.py
+++ b/urlinstall.py
@@ -19,6 +19,7 @@ import time
import string
import struct
import socket
+import urlparse
import urlgrabber.grabber as grabber
from snack import *
@@ -157,37 +158,28 @@ class UrlInstallMethod(InstallMethod):
def __init__(self, url, rootPath, intf):
InstallMethod.__init__(self, url, rootPath, intf)
- if url.startswith("ftp"):
- isFtp = 1
- else:
- isFtp = 0
+ (scheme, netloc, path, query, fragid) = urlparse.urlsplit(url)
- # build up the url. this is tricky so that we can replace
- # the first instance of // with /%3F to do absolute URLs right
- i = string.index(url, '://') + 3
- self.baseUrl = url[:i]
- rem = url[i:]
+ try:
+ socket.inet_pton(socket.AF_INET6, netloc)
+ netloc = '[' + netloc + ']'
+ except:
+ pass
- i = string.index(rem, '/') + 1
- self.baseUrl = self.baseUrl + rem[:i]
- rem = rem[i:]
-
# encoding fun so that we can handle absolute paths
- if rem.startswith("/") and isFtp:
- rem = "%2F" + rem[1:]
-
- self.baseUrl = self.baseUrl + rem
+ if path[1] == '/' and scheme == 'ftp':
+ path = "/%2F" + path[1:]
- if self.baseUrl[-1] == "/":
- self.baseUrl = self.baseUrl[:-1]
+ self.baseUrl = urlparse.urlunsplit((scheme,netloc,path,query,fragid))
- # self.baseUrl points at the path which contains the 'product'
- # directory with the hdlist.
-
- if self.baseUrl[-6:] == "/disc1":
- self.multiDiscs = 1
- self.pkgUrl = self.baseUrl[:-6]
- else:
- self.multiDiscs = 0
- self.pkgUrl = self.baseUrl
+ # FIXME: does not work
+# # self.baseUrl points at the path which contains the 'product'
+# # directory with the hdlist.
+#
+# if self.baseUrl[-6:] == "/disc1":
+# self.multiDiscs = 1
+# self.pkgUrl = self.baseUrl[:-6]
+# else:
+# self.multiDiscs = 0
+# self.pkgUrl = self.baseUrl