summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/network.c')
-rw-r--r--mdk-stage1/network.c649
1 files changed, 535 insertions, 114 deletions
diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c
index ae2c685d2..ab512399a 100644
--- a/mdk-stage1/network.c
+++ b/mdk-stage1/network.c
@@ -1,7 +1,7 @@
/*
- * Guillaume Cottenceau (gc@mandrakesoft.com)
+ * Guillaume Cottenceau (gc)
*
- * Copyright 2000 MandrakeSoft
+ * Copyright 2000 Mandriva
*
* This software may be freely redistributed under the terms of the GNU
* public license.
@@ -19,9 +19,11 @@
*
*/
+#include "stage1.h"
+
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
@@ -29,14 +31,17 @@
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <stdio.h>
+#include <fcntl.h>
#include <netdb.h>
#include <resolv.h>
+#include <sys/utsname.h>
-#include "stage1.h"
#include "frontend.h"
#include "modules.h"
#include "probing.h"
#include "log.h"
+#include "tools.h"
+#include "utils.h"
#include "mount.h"
#include "automatic.h"
#include "dhcp.h"
@@ -45,7 +50,12 @@
#include "dns.h"
#include "network.h"
+#include "directory.h"
+#include "wireless.h"
+#ifndef DISABLE_KA
+#include "ka.h"
+#endif
static void error_message_net(void) /* reduce code size */
{
@@ -237,7 +247,8 @@ static int add_default_route(void)
}
-static int write_resolvconf(void) {
+static int write_resolvconf(void)
+{
char * filename = "/etc/resolv.conf";
FILE * f;
@@ -265,7 +276,8 @@ static int write_resolvconf(void) {
}
-static int save_netinfo(struct interface_info * intf) {
+static int save_netinfo(struct interface_info * intf)
+{
char * file_network = "/tmp/network";
char file_intf[500];
FILE * f;
@@ -279,11 +291,8 @@ static int save_netinfo(struct interface_info * intf) {
fprintf(f, "NETWORKING=yes\n");
fprintf(f, "FORWARD_IPV4=false\n");
- if (hostname)
+ if (hostname && !(intf->boot_proto == BOOTPROTO_DHCP))
fprintf(f, "HOSTNAME=%s\n", hostname);
- if (domain)
- fprintf(f, "DOMAINNAME=%s\n", domain);
-
if (gateway.s_addr != 0)
fprintf(f, "GATEWAY=%s\n", inet_ntoa(gateway));
@@ -301,18 +310,27 @@ static int save_netinfo(struct interface_info * intf) {
fprintf(f, "DEVICE=%s\n", intf->device);
- if (intf->boot_proto == BOOTPROTO_DHCP)
+ if (intf->boot_proto == BOOTPROTO_DHCP) {
fprintf(f, "BOOTPROTO=dhcp\n");
- else if (intf->boot_proto == BOOTPROTO_STATIC) {
+ if (dhcp_hostname && !streq(dhcp_hostname, ""))
+ fprintf(f, "DHCP_HOSTNAME=%s\n", dhcp_hostname);
+ } else if (intf->boot_proto == BOOTPROTO_STATIC) {
fprintf(f, "BOOTPROTO=static\n");
fprintf(f, "IPADDR=%s\n", inet_ntoa(intf->ip));
fprintf(f, "NETMASK=%s\n", inet_ntoa(intf->netmask));
fprintf(f, "NETWORK=%s\n", inet_ntoa(intf->network));
fprintf(f, "BROADCAST=%s\n", inet_ntoa(intf->broadcast));
+ if (domain)
+ fprintf(f, "DOMAIN=%s\n", domain);
+ if (dns_server.s_addr != 0)
+ fprintf(f, "DNS1=%s\n", inet_ntoa(dns_server));
+ if (dns_server2.s_addr != 0)
+ fprintf(f, "DNS2=%s\n", inet_ntoa(dns_server2));
} else if (intf->boot_proto == BOOTPROTO_ADSL_PPPOE) {
fprintf(f, "BOOTPROTO=adsl_pppoe\n");
fprintf(f, "USER=%s\n", intf->user);
fprintf(f, "PASS=%s\n", intf->pass);
+ fprintf(f, "ACNAME=%s\n", intf->acname);
}
fclose(f);
@@ -342,12 +360,27 @@ char * guess_netmask(char * ip_addr)
}
+char * guess_domain_from_hostname(char *hostname)
+{
+ char *domain = strchr(strdup(hostname), '.');
+ if (!domain || domain[1] == '\0') {
+ log_message("unable to guess domain from hostname: %s", hostname);
+ return NULL;
+ }
+ return domain + 1; /* skip '.' */
+}
+
+
static void static_ip_callback(char ** strings)
{
struct in_addr addr;
- if (!inet_aton(strings[0], &addr))
+ static int done = 0;
+ if (done)
+ return;
+ if (streq(strings[0], "") || !inet_aton(strings[0], &addr))
return;
+ done = 1;
if (!strcmp(strings[1], "")) {
char * ptr;
@@ -368,11 +401,11 @@ static void static_ip_callback(char ** strings)
static enum return_type setup_network_interface(struct interface_info * intf)
{
enum return_type results;
- char * bootprotos[] = { "Static", "DHCP", "ADSL", NULL };
- char * bootprotos_auto[] = { "static", "dhcp", "adsl" };
+ char * bootprotos[] = { "DHCP", "Static", "ADSL", NULL };
+ char * bootprotos_auto[] = { "dhcp", "static", "adsl" };
char * choice;
- results = ask_from_list_auto("Please choose the desired IP attribution.", bootprotos, &choice, "network", bootprotos_auto);
+ results = ask_from_list_auto("Please select your network connection type.", bootprotos, &choice, "network", bootprotos_auto);
if (results != RETURN_OK)
return results;
@@ -382,7 +415,7 @@ static enum return_type setup_network_interface(struct interface_info * intf)
static char ** answers = NULL;
struct in_addr addr;
- results = ask_from_entries_auto("Please enter the network information. (leave netmask void for Internet standard)",
+ results = ask_from_entries_auto("Please enter the network information. (leave netmask blank for Internet standard)",
questions, &answers, 16, questions_auto, static_ip_callback);
if (results != RETURN_OK)
return setup_network_interface(intf);
@@ -398,6 +431,11 @@ static enum return_type setup_network_interface(struct interface_info * intf)
dns_server.s_addr = 0; /* keep an understandable state */
}
+ if (streq(answers[0], answers[1])) {
+ log_message("IP and DNS are the same, guess you don't want a DNS, disabling it");
+ dns_server.s_addr = 0; /* keep an understandable state */
+ }
+
if (!inet_aton(answers[2], &gateway)) {
log_message("invalid gateway");
gateway.s_addr = 0; /* keep an understandable state */
@@ -464,25 +502,33 @@ static enum return_type configure_network(struct interface_info * intf)
dnshostname = mygethostbyaddr(inet_ntoa(intf->ip));
if (dnshostname) {
- hostname = strdup(dnshostname);
- domain = strchr(strdup(hostname), '.') + 1;
- log_message("got hostname and domain from dns entry, %s and %s", hostname, domain);
- return RETURN_OK;
- }
-
- log_message("reverse name lookup on self failed");
+ if (intf->boot_proto == BOOTPROTO_STATIC)
+ hostname = strdup(dnshostname);
+ domain = guess_domain_from_hostname(dnshostname);
+ if (domain) {
+ log_message("got hostname and domain from dns entry, %s and %s", dnshostname, domain);
+ return RETURN_OK;
+ }
+ } else
+ log_message("reverse name lookup on self failed");
if (domain)
return RETURN_OK;
+ dnshostname = NULL;
if (dns_server.s_addr != 0) {
wait_message("Trying to resolve dns...");
dnshostname = mygethostbyaddr(inet_ntoa(dns_server));
remove_wait_message();
- }
+ if (dnshostname) {
+ log_message("got DNS fullname, %s", dnshostname);
+ domain = guess_domain_from_hostname(dnshostname);
+ } else
+ log_message("reverse name lookup on DNS failed");
+ } else
+ log_message("no DNS, unable to guess domain");
- if (dnshostname) {
- domain = strchr(strdup(dnshostname), '.') + 1;
+ if (domain) {
log_message("got domain from DNS fullname, %s", domain);
} else {
enum return_type results;
@@ -490,15 +536,21 @@ static enum return_type configure_network(struct interface_info * intf)
char * questions_auto[] = { "hostname", "domain" };
static char ** answers = NULL;
char * boulet;
-
- log_message("reverse name lookup on DNS failed");
-
- results = ask_from_entries_auto("I could not guess hostname and domain name; please fill in this information. "
- "Valid answers are for example: `mybox' for hostname and `mynetwork.com' for "
- "domain name, for a machine called `mybox.mynetwork.com' on the Internet.",
- questions, &answers, 32, questions_auto, NULL);
- if (results != RETURN_OK)
+
+ if (dhcp_hostname || dhcp_domain) {
+ answers = (char **) calloc(1, sizeof(questions));
+ answers[0] = strdup(dhcp_hostname);
+ answers[1] = strdup(dhcp_domain);
+ }
+
+ if (!dhcp_hostname || !dhcp_domain) {
+ results = ask_from_entries_auto("I could not guess hostname and domain name; please fill in this information. "
+ "Valid answers are for example: `mybox' for hostname and `mynetwork.com' for "
+ "domain name, for a machine called `mybox.mynetwork.com' on the Internet.",
+ questions, &answers, 32, questions_auto, NULL);
+ if (results != RETURN_OK)
return results;
+ }
hostname = answers[0];
if ((boulet = strchr(hostname, '.')) != NULL)
@@ -506,6 +558,9 @@ static enum return_type configure_network(struct interface_info * intf)
domain = answers[1];
}
+ log_message("using hostname %s", hostname);
+ log_message("using domain %s", domain);
+
return RETURN_OK;
}
@@ -513,17 +568,34 @@ static enum return_type configure_network(struct interface_info * intf)
static enum return_type bringup_networking(struct interface_info * intf)
{
static struct interface_info loopback;
- enum return_type results = RETURN_ERROR;
-
- my_insmod("af_packet", ANY_DRIVER_TYPE, NULL);
+ enum return_type results;
+ int fd;
+
+ /* try to find if module already loaded or built-in to avoid failing */
+ /* badly */
+ fd = open("/proc/net/packet", O_RDONLY);
+ if (fd < 0)
+ my_modprobe("af_packet", ANY_DRIVER_TYPE, NULL);
+ else
+ close(fd);
+
+ do {
+ results = configure_wireless(intf->device);
+ } while (results == RETURN_ERROR);
- while (results != RETURN_OK) {
+ if (results == RETURN_BACK)
+ return RETURN_BACK;
+
+ do {
results = setup_network_interface(intf);
if (results != RETURN_OK)
return results;
write_resolvconf();
results = configure_network(intf);
- }
+ } while (results == RETURN_ERROR);
+
+ if (results == RETURN_BACK)
+ return bringup_networking(intf);
write_resolvconf(); /* maybe we have now domain to write also */
@@ -545,6 +617,63 @@ static enum return_type bringup_networking(struct interface_info * intf)
}
+static char * auto_select_up_intf(int detection_mode)
+{
+#define SIOCETHTOOL 0x8946
+#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */
+
+ struct ethtool_value {
+ uint32_t cmd;
+ uint32_t data;
+ };
+
+ char ** interfaces, ** ptr;
+ interfaces = get_net_devices();
+
+ int s;
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ return NULL;
+ }
+
+ ptr = interfaces;
+ while (ptr && *ptr) {
+ if (detection_mode != AUTO_DETECTION_WIRED || !wireless_is_aware(s, *interfaces)) {
+ struct ifreq ifr;
+ struct ethtool_value edata;
+ strncpy(ifr.ifr_name, *ptr, IFNAMSIZ);
+ edata.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (caddr_t)&edata;
+ if (ioctl(s, SIOCETHTOOL, &ifr) == 0 && edata.data) {
+ close(s);
+ log_message("NETWORK: choosing interface %s (link beat detected)", *ptr);
+ return *ptr;
+ }
+ }
+ ptr++;
+ }
+
+ log_message("NETWORK: no interface has a link beat");
+
+ if (detection_mode == AUTO_DETECTION_WIRED) {
+ ptr = interfaces;
+ while (ptr && *ptr) {
+ if (!wireless_is_aware(s, *interfaces)) {
+ close(s);
+ log_message("NETWORK: choosing interface %s (wired interface)", *ptr);
+ return *ptr;
+ }
+ ptr++;
+ }
+ log_message("NETWORK: no interface is wired");
+ }
+
+ close(s);
+
+ return NULL;
+}
+
+
static char * interface_select(void)
{
char ** interfaces, ** ptr;
@@ -572,6 +701,20 @@ static char * interface_select(void)
if (count == 1)
return *interfaces;
+ /* this can't be done in ask_from_list_comments_auto because "auto" and "wired" are not in the interfaces list */
+ if (IS_AUTOMATIC) {
+ enum auto_detection_type auto_detect = AUTO_DETECTION_NONE;
+ if (streq(get_auto_value("interface"), "auto"))
+ auto_detect = AUTO_DETECTION_ALL;
+ else if (streq(get_auto_value("interface"), "wired"))
+ auto_detect = AUTO_DETECTION_WIRED;
+ if (auto_detect != AUTO_DETECTION_NONE) {
+ choice = auto_select_up_intf(auto_detect);
+ if (choice)
+ return choice;
+ }
+ }
+
i = 0;
while (interfaces[i]) {
descriptions[i] = get_net_intf_description(interfaces[i]);
@@ -587,12 +730,171 @@ static char * interface_select(void)
return choice;
}
+static enum return_type get_http_proxy(char **http_proxy_host, char **http_proxy_port)
+{
+ char *questions[] = { "HTTP proxy host", "HTTP proxy port", NULL };
+ char *questions_auto[] = { "proxy_host", "proxy_port", NULL };
+ static char ** answers = NULL;
+ enum return_type results;
+
+ results = ask_from_entries_auto("Please enter HTTP proxy host and port if you need it, else leave them blank or cancel.",
+ questions, &answers, 40, questions_auto, NULL);
+ if (results == RETURN_OK) {
+ *http_proxy_host = answers[0];
+ *http_proxy_port = answers[1];
+ } else {
+ *http_proxy_host = NULL;
+ *http_proxy_port = NULL;
+ }
+
+ return results;
+}
+
+
+static int url_split(const char *url, const char *protocol, char **host, char **path)
+{
+ char *protocol_sep, *host_sep;
+
+ protocol_sep = strstr(url, "://");
+ if (!protocol_sep) {
+ log_message("NETWORK: no protocol in \"%s\"", url);
+ return -1;
+ }
+
+ if (strncmp(protocol, url, protocol_sep - url))
+ return -1;
+
+ url = protocol_sep + 3;
+ host_sep = strchr(url, '/');
+ if (!host_sep || host_sep == url) {
+ log_message("NETWORK: no hostname in \"%s\"", url);
+ return -1;
+ }
+
+ *host = strndup(url, host_sep - url);
+ *path = strdup(host_sep);
+
+ return 0;
+}
+
+#define MIRRORLIST_MAX_ITEMS 500
+typedef char *mirrorlist_t[2][MIRRORLIST_MAX_ITEMS+1];
+
+static enum return_type get_mirrorlist(mirrorlist_t mirrorlist, int start, char *version, const char *protocol, char *http_proxy_host, char *http_proxy_port) {
+ int fd, size, line_pos = 0;
+ char path[1024];
+ char line[1024];
+ char type[100] = DISTRIB_TYPE;
+ int mirror_idx = start;
+
+ int use_http_proxy = http_proxy_host && http_proxy_port && !streq(http_proxy_host, "") && !streq(http_proxy_port, "");
+ lowercase(type);
+ snprintf(path, sizeof(path), "%s/%s.%s.%s.list", MIRRORLIST_PATH, type, version, ARCH);
+
+ fd = http_download_file(MIRRORLIST_HOST, path, &size, use_http_proxy ? "http" : NULL, http_proxy_host, http_proxy_port);
+ if (fd < 0) {
+ log_message("HTTP: unable to get mirrors list from %s (%s)", MIRRORLIST_HOST, path);
+ return RETURN_ERROR;
+ }
+
+ while (read(fd, line + line_pos, 1) > 0) {
+ if (line[line_pos] == '\n') {
+ char *url;
+ line[line_pos] = '\0';
+ line_pos = 0;
+
+ /* skip medium if it does not look like a distrib path */
+ if (!strstr(line, ",type=distrib,"))
+ continue;
+
+ url = strstr(line, ",url=");
+ if (!url)
+ continue;
+ url += 5;
+
+ if (url_split(url, protocol, &mirrorlist[0][mirror_idx], &mirrorlist[1][mirror_idx]) < 0)
+ continue;
+
+ mirror_idx++;
+ } else {
+ line_pos++;
+ }
+
+ if (mirror_idx >= MIRRORLIST_MAX_ITEMS)
+ break;
+ }
+ close(fd);
+
+ mirrorlist[0][mirror_idx] = NULL;
+ mirrorlist[1][mirror_idx] = NULL;
+
+ return RETURN_OK;
+}
+
+static int choose_mirror_from_host_list(mirrorlist_t mirrorlist, char **selected_host, char **filepath)
+{
+ enum return_type results;
+ int mirror_idx = 0;
+
+ do {
+ results = ask_from_list_index("Please select a mirror from the list below.",
+ mirrorlist[0], NULL, &mirror_idx);
+
+ if (results == RETURN_BACK) {
+ return RETURN_ERROR;
+ } else if (results == RETURN_OK) {
+ if (mirror_idx == 0) {
+ /* enter the mirror manually */
+ return RETURN_OK;
+ }
+ *selected_host = strdup(mirrorlist[0][mirror_idx]);
+ *filepath = strdup(mirrorlist[1][mirror_idx]);
+ return RETURN_OK;
+ }
+ } while (results == RETURN_ERROR);
+
+ return RETURN_ERROR;
+}
+
+
+static int choose_mirror_from_list(char *http_proxy_host, char *http_proxy_port, const char *protocol, char **selected_host, char **filepath)
+{
+ enum return_type results;
+ char *versions[] = { "Specify the mirror manually", DISTRIB_NAME " " DISTRIB_VERSION, NULL };
+ char *version = DISTRIB_NAME " " DISTRIB_VERSION;
+
+ do {
+ results = ask_from_list("Please select a medium from the list below.", versions, &version);
+
+ if (results == RETURN_BACK) {
+ return RETURN_BACK;
+ } else if (results == RETURN_OK) {
+ if (!strcmp(version, versions[0])) {
+ /* enter the mirror manually */
+ return RETURN_OK;
+ } else {
+ /* a medium has been selected */
+ mirrorlist_t mirrorlist;
+ mirrorlist[0][0] = "Specify the mirror manually";
+ mirrorlist[1][0] = NULL;
+
+ results = get_mirrorlist(mirrorlist, 1, DISTRIB_VERSION, protocol, http_proxy_host, http_proxy_port);
+ if (results == RETURN_ERROR)
+ return RETURN_ERROR;
+
+ results = choose_mirror_from_host_list(mirrorlist, selected_host, filepath);
+ }
+ }
+ } while (results == RETURN_ERROR);
+
+ return results;
+}
/* -=-=-- */
-static enum return_type intf_select_and_up(void)
+enum return_type intf_select_and_up()
{
static struct interface_info intf[20];
static int num_interfaces = 0;
@@ -619,7 +921,7 @@ static enum return_type intf_select_and_up(void)
if (results == RETURN_OK)
save_netinfo(sel_intf);
-
+
return results;
}
@@ -631,7 +933,7 @@ enum return_type nfs_prepare(void)
char * questions_auto[] = { "server", "directory", NULL };
static char ** answers = NULL;
char * nfsmount_location;
- enum return_type results = intf_select_and_up();
+ enum return_type results = intf_select_and_up(NULL, NULL);
if (results != RETURN_OK)
return results;
@@ -641,7 +943,7 @@ enum return_type nfs_prepare(void)
"and the directory containing the " DISTRIB_NAME " Distribution.",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
- unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
+ unset_automatic(); /* we are in a fallback mode */
return nfs_prepare();
}
@@ -650,33 +952,21 @@ enum return_type nfs_prepare(void)
strcat(nfsmount_location, ":");
strcat(nfsmount_location, answers[1]);
- if (my_mount(nfsmount_location, IMAGE_LOCATION, "nfs", 0) == -1) {
+ if (my_mount(nfsmount_location, MEDIA_LOCATION, "nfs", 0) == -1) {
stg1_error_message("I can't mount the directory from the NFS server.");
results = RETURN_BACK;
continue;
}
+ free(nfsmount_location); nfsmount_location = NULL;
- if (access(IMAGE_LOCATION LIVE_LOCATION, R_OK)) {
- stg1_error_message("That NFS volume does not seem to contain the " DISTRIB_NAME " Distribution.");
- umount(IMAGE_LOCATION);
- results = RETURN_BACK;
- }
+ results = try_with_directory(MEDIA_LOCATION, "nfs", "nfs-iso");
+ if (results != RETURN_OK)
+ umount(MEDIA_LOCATION);
+ if (results == RETURN_ERROR)
+ return RETURN_ERROR;
}
while (results == RETURN_BACK);
- log_message("found the " DISTRIB_NAME " Installation, good news!");
-
- if (IS_SPECIAL_STAGE2) {
- if (load_ramdisk() != RETURN_OK) {
- stg1_error_message("Could not load program into memory.");
- return nfs_prepare();
- }
- }
-
- if (IS_RESCUE)
- umount(IMAGE_LOCATION);
-
- method_name = strdup("nfs");
return RETURN_OK;
}
@@ -687,10 +977,13 @@ enum return_type ftp_prepare(void)
char * questions_auto[] = { "server", "directory", "user", "pass", NULL };
static char ** answers = NULL;
enum return_type results;
+ struct utsname kernel_uname;
+ char *http_proxy_host, *http_proxy_port;
+ int use_http_proxy;
if (!ramdisk_possible()) {
- stg1_error_message("FTP install needs more than %d Mbytes of memory (detected %d Mbytes).",
- MEM_LIMIT_RAMDISK, total_memory());
+ stg1_error_message("FTP install needs more than %d Mbytes of memory (detected %d Mbytes). You may want to try an NFS install.",
+ MEM_LIMIT_DRAKX, total_memory());
return RETURN_ERROR;
}
@@ -699,68 +992,138 @@ enum return_type ftp_prepare(void)
if (results != RETURN_OK)
return results;
+ get_http_proxy(&http_proxy_host, &http_proxy_port);
+ use_http_proxy = http_proxy_host && http_proxy_port && !streq(http_proxy_host, "") && !streq(http_proxy_port, "");
+
+ uname(&kernel_uname);
+
do {
char location_full[500];
- int ftp_serv_response;
+ int ftp_serv_response = -1;
int fd, size;
+ int need_arch = 0;
+ char ftp_hostname[500];
+
+ if (!IS_AUTOMATIC) {
+ if (answers == NULL)
+ answers = (char **) calloc(1, sizeof(questions));
+
+ results = choose_mirror_from_list(http_proxy_host, http_proxy_port, "ftp", &answers[0], &answers[1]);
+
+ if (results == RETURN_BACK)
+ return ftp_prepare();
+
+ if (use_http_proxy) {
+ results = ask_yes_no("Do you want to use this HTTP proxy for FTP connections too ?");
+
+ if (results == RETURN_BACK)
+ return ftp_prepare();
+
+ use_http_proxy = results == RETURN_OK;
+ }
+ }
results = ask_from_entries_auto("Please enter the name or IP address of the FTP server, "
"the directory containing the " DISTRIB_NAME " Distribution, "
- "and the login/pass if necessary (leave login blank for anonymous).",
+ "and the login/pass if necessary (leave login blank for anonymous). ",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
- unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
+ unset_automatic(); /* we are in a fallback mode */
return ftp_prepare();
}
- log_message("FTP: trying to connect to %s", answers[0]);
+ strcpy(location_full, answers[1][0] == '/' ? "" : "/");
+ strcat(location_full, answers[1]);
- ftp_serv_response = ftp_open_connection(answers[0], answers[2], answers[3], "");
- if (ftp_serv_response < 0) {
- log_message("FTP: error connect %d", ftp_serv_response);
- if (ftp_serv_response == FTPERR_BAD_HOSTNAME)
- stg1_error_message("Error: bad hostname.");
- else if (ftp_serv_response == FTPERR_FAILED_CONNECT)
- stg1_error_message("Error: failed to connect to remote host.");
- else
- stg1_error_message("Error: couldn't connect.");
- results = RETURN_BACK;
- continue;
- }
- strcpy(location_full, answers[1]);
- strcat(location_full, get_ramdisk_realname());
+ if (use_http_proxy) {
+ log_message("FTP: don't connect to %s directly, will use proxy", answers[0]);
+ } else {
+ log_message("FTP: trying to connect to %s", answers[0]);
+ ftp_serv_response = ftp_open_connection(answers[0], answers[2], answers[3], "");
+ if (ftp_serv_response < 0) {
+ log_message("FTP: error connect %d", ftp_serv_response);
+ if (ftp_serv_response == FTPERR_BAD_HOSTNAME)
+ stg1_error_message("Error: bad hostname.");
+ else if (ftp_serv_response == FTPERR_FAILED_CONNECT)
+ stg1_error_message("Error: failed to connect to remote host.");
+ else
+ stg1_error_message("Error: couldn't connect.");
+ results = RETURN_BACK;
+ continue;
+ }
+ }
+
+ strcat(location_full, COMPRESSED_FILE_REL("/"));
log_message("FTP: trying to retrieve %s", location_full);
- fd = ftp_start_download(ftp_serv_response, location_full, &size);
+ if (use_http_proxy) {
+ if (strcmp(answers[2], "")) {
+ strcpy(ftp_hostname, answers[2]); /* user name */
+ strcat(ftp_hostname, ":");
+ strcat(ftp_hostname, answers[3]); /* password */
+ strcat(ftp_hostname, "@");
+ } else {
+ strcpy(ftp_hostname, "");
+ }
+ strcat(ftp_hostname, answers[0]);
+ fd = http_download_file(ftp_hostname, location_full, &size, "ftp", http_proxy_host, http_proxy_port);
+ } else {
+ fd = ftp_start_download(ftp_serv_response, location_full, &size);
+ }
+
+ /* Try arched directory */
if (fd < 0) {
- log_message("FTP: error get %d", fd);
- if (fd == FTPERR_PASSIVE_ERROR)
- stg1_error_message("Error: error with passive connection.");
- else if (fd == FTPERR_FILE_NOT_FOUND)
- stg1_error_message("Error: file not found (%s).", location_full);
- else if (fd == FTPERR_BAD_SERVER_RESPONSE)
- stg1_error_message("Error: bad server response (server too busy?).");
- else
- stg1_error_message("Error: couldn't retrieve Installation program.");
+ log_message("%s failed.", location_full);
+ char *with_arch = asprintf_("%s%s/%s/%s", answers[1][0] == '/' ? "" : "/", answers[1], ARCH, COMPRESSED_FILE_REL("/"));
+ log_message("trying %s...", with_arch);
+ if (use_http_proxy)
+ fd = http_download_file(answers[0], with_arch, &size, use_http_proxy ? "http" : NULL, http_proxy_host, http_proxy_port);
+ else
+ fd = ftp_start_download(ftp_serv_response, with_arch, &size);
+ if (0 < fd) {
+ strcpy(location_full, with_arch);
+ need_arch = 1;
+ }
+ }
+
+ if (fd < 0) {
+ char *msg = str_ftp_error(fd);
+ log_message("FTP: error get %d for remote file %s", fd, location_full);
+ stg1_error_message("Error: %s.", msg ? msg : "couldn't retrieve Installation program");
results = RETURN_BACK;
continue;
}
log_message("FTP: size of download %d bytes", size);
- results = load_ramdisk_fd(fd, size);
- if (results == RETURN_OK)
- ftp_end_data_command(ftp_serv_response);
- else
+ results = load_compressed_fd(fd, size);
+ if (results == RETURN_OK) {
+ if (!use_http_proxy)
+ ftp_end_data_command(ftp_serv_response);
+ } else {
+ unset_automatic(); /* we are in a fallback mode */
return results;
+ }
- method_name = strdup("ftp");
- add_to_env("HOST", answers[0]);
- add_to_env("PREFIX", answers[1]);
- if (strcmp(answers[2], "")) {
- add_to_env("LOGIN", answers[2]);
- add_to_env("PASSWORD", answers[3]);
+ if (use_http_proxy) {
+ add_to_env("METHOD", "http");
+ snprintf(location_full, sizeof(location_full), "ftp://%s%s", ftp_hostname, answers[1]);
+ if (need_arch)
+ strcat(location_full, "/" ARCH);
+ add_to_env("URLPREFIX", location_full);
+ add_to_env("PROXY", http_proxy_host);
+ add_to_env("PROXYPORT", http_proxy_port);
+ } else {
+ add_to_env("METHOD", "ftp");
+ add_to_env("HOST", answers[0]);
+ if (need_arch)
+ strcat(answers[1], "/" ARCH);
+ add_to_env("PREFIX", answers[1]);
+ if (!streq(answers[2], "")) {
+ add_to_env("LOGIN", answers[2]);
+ add_to_env("PASSWORD", answers[3]);
+ }
}
}
while (results == RETURN_BACK);
@@ -774,10 +1137,11 @@ enum return_type http_prepare(void)
char * questions_auto[] = { "server", "directory", NULL };
static char ** answers = NULL;
enum return_type results;
+ char *http_proxy_host, *http_proxy_port;
if (!ramdisk_possible()) {
- stg1_error_message("HTTP install needs more than %d Mbytes of memory (detected %d Mbytes).",
- MEM_LIMIT_RAMDISK, total_memory());
+ stg1_error_message("HTTP install needs more than %d Mbytes of memory (detected %d Mbytes). You may want to try an NFS install.",
+ MEM_LIMIT_DRAKX, total_memory());
return RETURN_ERROR;
}
@@ -786,24 +1150,53 @@ enum return_type http_prepare(void)
if (results != RETURN_OK)
return results;
+ get_http_proxy(&http_proxy_host, &http_proxy_port);
+
do {
char location_full[500];
- int fd, size;
+ int fd, size, need_arch = 0;
+ int use_http_proxy;
+
+ if (!IS_AUTOMATIC) {
+ if (answers == NULL)
+ answers = (char **) calloc(1, sizeof(questions));
+
+ results = choose_mirror_from_list(http_proxy_host, http_proxy_port, "http", &answers[0], &answers[1]);
+
+ if (results == RETURN_BACK)
+ return http_prepare();
+ }
results = ask_from_entries_auto("Please enter the name or IP address of the HTTP server, "
"and the directory containing the " DISTRIB_NAME " Distribution.",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
- unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
+ unset_automatic(); /* we are in a fallback mode */
return http_prepare();
}
- strcpy(location_full, answers[1]);
- strcat(location_full, get_ramdisk_realname());
+ strcpy(location_full, answers[1][0] == '/' ? "" : "/");
+ strcat(location_full, answers[1]);
+ strcat(location_full, COMPRESSED_FILE_REL("/"));
- log_message("HTTP: trying to retrieve %s", location_full);
+ log_message("HTTP: trying to retrieve %s from %s", location_full, answers[0]);
- fd = http_download_file(answers[0], location_full, &size);
+ use_http_proxy = http_proxy_host && http_proxy_port && !streq(http_proxy_host, "") && !streq(http_proxy_port, "");
+
+ fd = http_download_file(answers[0], location_full, &size, use_http_proxy ? "http" : NULL, http_proxy_host, http_proxy_port);
+
+ /* Try arched directory */
+ if (fd < 0) {
+ log_message("%s failed.", location_full);
+ char *with_arch = asprintf_("%s%s/%s/%s", answers[1][0] == '/' ? "" : "/", answers[1], ARCH, COMPRESSED_FILE_REL("/"));
+ log_message("trying %s...", with_arch);
+ fd = http_download_file(answers[0], with_arch, &size, use_http_proxy ? "http" : NULL, http_proxy_host, http_proxy_port);
+ if (0 < fd) {
+ strcpy(location_full, with_arch);
+ need_arch = 1;
+ }
+ }
+
if (fd < 0) {
log_message("HTTP: error %d", fd);
if (fd == FTPERR_FAILED_CONNECT)
@@ -816,15 +1209,43 @@ enum return_type http_prepare(void)
log_message("HTTP: size of download %d bytes", size);
- if (load_ramdisk_fd(fd, size) != RETURN_OK)
+ if (load_compressed_fd(fd, size) != RETURN_OK) {
+ unset_automatic(); /* we are in a fallback mode */
return RETURN_ERROR;
+ }
- method_name = strdup("http");
- sprintf(location_full, "http://%s/%s", answers[0], answers[1]);
+ add_to_env("METHOD", "http");
+ sprintf(location_full, "http://%s%s%s", answers[0], answers[1][0] == '/' ? "" : "/", answers[1]);
+ if (need_arch)
+ strcat(location_full, "/" ARCH);
add_to_env("URLPREFIX", location_full);
+ if (!streq(http_proxy_host, ""))
+ add_to_env("PROXY", http_proxy_host);
+ if (!streq(http_proxy_port, ""))
+ add_to_env("PROXYPORT", http_proxy_port);
}
while (results == RETURN_BACK);
return RETURN_OK;
}
+
+#ifndef DISABLE_KA
+enum return_type ka_prepare(void)
+{
+ enum return_type results;
+
+ if (!ramdisk_possible()) {
+ stg1_error_message("KA install needs more than %d Mbytes of memory (detected %d Mbytes).",
+ MEM_LIMIT_DRAKX, total_memory());
+ return RETURN_ERROR;
+ }
+
+ results = intf_select_and_up();
+
+ if (results != RETURN_OK)
+ return results;
+
+ return perform_ka();
+}
+#endif