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.c717
1 files changed, 457 insertions, 260 deletions
diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c
index 7cae99e47..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,7 +19,10 @@
*
*/
+#include "stage1.h"
+
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -28,15 +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,11 +50,12 @@
#include "dns.h"
#include "network.h"
+#include "directory.h"
+#include "wireless.h"
-/* include it after config-stage1.h so that _GNU_SOURCE is defined and strndup is available */
-#include <string.h>
-
-static int choose_mirror_from_list(const char *desired_protocol, char **host, char **filepath);
+#ifndef DISABLE_KA
+#include "ka.h"
+#endif
static void error_message_net(void) /* reduce code size */
{
@@ -241,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;
@@ -269,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;
@@ -283,13 +291,8 @@ static int save_netinfo(struct interface_info * intf) {
fprintf(f, "NETWORKING=yes\n");
fprintf(f, "FORWARD_IPV4=false\n");
- if (hostname && !intf->boot_proto == BOOTPROTO_DHCP)
+ if (hostname && !(intf->boot_proto == BOOTPROTO_DHCP))
fprintf(f, "HOSTNAME=%s\n", hostname);
- if (domain)
- fprintf(f, "DOMAINNAME=%s\n", domain);
- if (dhcp_hostname && !streq(dhcp_hostname, ""))
- fprintf(f, "DHCP_HOSTNAME=%s\n", dhcp_hostname);
-
if (gateway.s_addr != 0)
fprintf(f, "GATEWAY=%s\n", inet_ntoa(gateway));
@@ -307,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);
@@ -348,6 +360,17 @@ 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;
@@ -378,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;
@@ -481,24 +504,31 @@ static enum return_type configure_network(struct interface_info * intf)
if (dnshostname) {
if (intf->boot_proto == BOOTPROTO_STATIC)
hostname = strdup(dnshostname);
- domain = strchr(strdup(dnshostname), '.') + 1;
- log_message("got hostname and domain from dns entry, %s and %s", dnshostname, domain);
- return RETURN_OK;
- }
-
- log_message("reverse name lookup on self failed");
+ 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;
@@ -506,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)
@@ -522,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;
}
@@ -529,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, 1);
+ 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 */
@@ -561,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;
@@ -578,8 +691,7 @@ static char * interface_select(void)
}
if (count == 0) {
- stg1_error_message("No NET device found.\n"
- "Hint: if you're using a Laptop, note that PCMCIA Network adapters are now supported either with `pcmcia.img' or `network.img', please try both these bootdisks.");
+ stg1_error_message("No NET device found.");
i = ask_insmod(NETWORK_DEVICES);
if (i == RETURN_BACK)
return NULL;
@@ -589,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]);
@@ -604,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;
@@ -636,7 +921,7 @@ static enum return_type intf_select_and_up(void)
if (results == RETURN_OK)
save_netinfo(sel_intf);
-
+
return results;
}
@@ -648,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;
@@ -658,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();
}
@@ -667,53 +952,38 @@ 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;
-#ifdef MANDRAKE_MOVE
- if (access(IMAGE_LOCATION "/live_tree/etc/fstab", R_OK) && access(IMAGE_LOCATION "/live_tree.clp", R_OK)) {
-#else
- if (access(IMAGE_LOCATION LIVE_LOCATION, R_OK)) {
-#endif
- 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);
-
- add_to_env("METHOD", "nfs");
return RETURN_OK;
}
enum return_type ftp_prepare(void)
{
- char * questions[] = { "FTP server", DISTRIB_NAME " directory", "Login", "Password", "HTTP proxy host", "HTTP proxy port", NULL };
- char * questions_auto[] = { "server", "directory", "user", "pass", "proxy_host", "proxy_port", NULL };
+ char * questions[] = { "FTP server", DISTRIB_NAME " directory", "Login", "Password", NULL };
+ char * questions_auto[] = { "server", "directory", "user", "pass", NULL };
static char ** answers = NULL;
enum return_type results;
- char modules_cz[500];
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). You may want to try an NFS install.",
- MEM_LIMIT_RAMDISK, total_memory());
+ MEM_LIMIT_DRAKX, total_memory());
return RETURN_ERROR;
}
@@ -722,30 +992,48 @@ 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 = -1;
int fd, size;
- int use_http_proxy;
+ int need_arch = 0;
char ftp_hostname[500];
- if (answers == NULL)
- answers = (char **) malloc(sizeof(questions));
- results = choose_mirror_from_list("ftp", &answers[0], &answers[1]);
+ 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). "
- "Please enter HTTP proxy host and port if you need it.",
+ "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();
}
- use_http_proxy = !streq(answers[4], "") && !streq(answers[5], "");
+ strcpy(location_full, answers[1][0] == '/' ? "" : "/");
+ strcat(location_full, answers[1]);
if (use_http_proxy) {
log_message("FTP: don't connect to %s directly, will use proxy", answers[0]);
@@ -763,21 +1051,9 @@ enum return_type ftp_prepare(void)
results = RETURN_BACK;
continue;
}
-
- strcpy(modules_cz, answers[1]);
- strcat(modules_cz, LIVE_LOCATION "lib/modules.cz-");
- strcat(modules_cz, kernel_uname.release);
-
- log_message("checking presence of modules.cz file : \"%s\"", modules_cz);
- if (ftp_get_filesize(ftp_serv_response, modules_cz) <= 0) {
- stg1_info_message("The modules for this kernel (%s) can't be found on this mirror, please update your boot disk", kernel_uname.release);
- results = RETURN_BACK;
- continue;
- }
}
- strcpy(location_full, answers[1]);
- strcat(location_full, get_ramdisk_realname());
+ strcat(location_full, COMPRESSED_FILE_REL("/"));
log_message("FTP: trying to retrieve %s", location_full);
@@ -791,46 +1067,58 @@ enum return_type ftp_prepare(void)
strcpy(ftp_hostname, "");
}
strcat(ftp_hostname, answers[0]);
- fd = http_download_file(ftp_hostname, location_full, &size, "ftp", answers[4], answers[5]);
+ 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_FAILED_CONNECT)
- stg1_error_message("Error: couldn't connect to server.");
- 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);
+ 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;
}
if (use_http_proxy) {
add_to_env("METHOD", "http");
- sprintf(location_full, "ftp://%s%s", ftp_hostname, answers[1]);
+ 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", answers[4]);
- add_to_env("PROXYPORT", answers[5]);
+ 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]);
@@ -845,14 +1133,15 @@ enum return_type ftp_prepare(void)
enum return_type http_prepare(void)
{
- char * questions[] = { "HTTP server", DISTRIB_NAME " directory", "HTTP proxy host", "HTTP proxy port", NULL };
- char * questions_auto[] = { "server", "directory", "proxy_host", "proxy_port", NULL };
+ char * questions[] = { "HTTP server", DISTRIB_NAME " directory", NULL };
+ 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). You may want to try an NFS install.",
- MEM_LIMIT_RAMDISK, total_memory());
+ MEM_LIMIT_DRAKX, total_memory());
return RETURN_ERROR;
}
@@ -861,28 +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."
- "Please enter HTTP proxy host and port if you need it.",
+ "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 from %s", location_full, answers[0]);
- use_http_proxy = !streq(answers[2], "") && !streq(answers[3], "");
+ 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;
+ }
+ }
- fd = http_download_file(answers[0], location_full, &size, use_http_proxy ? "http" : NULL, answers[2], answers[3]);
if (fd < 0) {
log_message("HTTP: error %d", fd);
if (fd == FTPERR_FAILED_CONNECT)
@@ -895,16 +1209,20 @@ 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;
+ }
add_to_env("METHOD", "http");
- sprintf(location_full, "http://%s%s", answers[0], answers[1]);
+ 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(answers[2], ""))
- add_to_env("PROXY", answers[2]);
- if (!streq(answers[3], ""))
- add_to_env("PROXYPORT", answers[3]);
+ 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);
@@ -912,143 +1230,22 @@ enum return_type http_prepare(void)
}
-static int mirrorlist_entry_split(const char *entry, char *mirror[4]) /* mirror = { medium, protocol, host, path } */
+#ifndef DISABLE_KA
+enum return_type ka_prepare(void)
{
- char *medium_sep, *protocol_sep, *host_sep, *path_sep;
-
- medium_sep = strchr(entry, ':');
- if (!medium_sep || medium_sep == entry) {
- log_message("NETWORK: no medium in \"%s\"", entry);
- return -1;
- }
-
- mirror[0] = strndup(entry, medium_sep - entry);
- entry = medium_sep + 1;
-
- protocol_sep = strstr(entry, "://");
- if (!protocol_sep || protocol_sep == entry) {
- log_message("NETWORK: no protocol in \"%s\"", entry);
- return -1;
- }
-
- mirror[1] = strndup(entry, protocol_sep - entry);
- entry = protocol_sep + 3;
-
- host_sep = strchr(entry, '/');
- if (!host_sep || host_sep == entry) {
- log_message("NETWORK: no hostname in \"%s\"", entry);
- return -1;
- }
-
- mirror[2] = strndup(entry, host_sep - entry);
- entry = host_sep;
-
- path_sep = strstr(entry, "/Mandrake/RPMS");
- if (!path_sep || path_sep == entry) {
- log_message("NETWORK: this path isn't valid : \"%s\"", entry);
- return -1;
- }
-
- mirror[3] = strndup(entry, path_sep - entry);
-
- return 0;
-}
-
-static int choose_mirror_from_list(const char *protocol, char **selected_host, char **filepath) {
enum return_type results;
- char *mirrorlist[MIRRORLIST_MAX_ITEMS][4];
- char *medialist[MIRRORLIST_MAX_MEDIA+1];
- int mirrorlist_number = 0, media_number = 0;
- int fd, size, line_pos = 0;
- char line[500];
-
- if (IS_AUTOMATIC)
- return RETURN_OK;
-
- fd = http_download_file(MIRRORLIST_HOST, MIRRORLIST_PATH, &size, NULL, NULL, NULL);
- if (fd < 0) {
- log_message("HTTP: unable to get mirrors list");
+ 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;
}
- while (read(fd, line + line_pos, 1) > 0) {
- if (line[line_pos] == '\n') {
- line[line_pos] = '\0';
- line_pos = 0;
-
- /* skip medium if it looks like an updates one */
- if (strstr(line, "updates"))
- continue;
-
- if (mirrorlist_entry_split(line, mirrorlist[mirrorlist_number]) < 0)
- continue;
-
- /* add medium in media list if different from previous one */
- if (media_number < 1 ||
- strcmp(mirrorlist[mirrorlist_number][0], medialist[media_number-1])) {
- medialist[media_number] = mirrorlist[mirrorlist_number][0];
- media_number++;
- }
-
- mirrorlist_number++;
- } else {
- line_pos++;
- }
-
- if (mirrorlist_number >= MIRRORLIST_MAX_ITEMS || media_number >= MIRRORLIST_MAX_MEDIA)
- break;
- }
- close(fd);
-
- medialist[media_number] = NULL;
-
- do {
- char *hosts[MIRRORLIST_MAX_ITEMS+1];
- char *selected_medium;
- int host_index = 0, mirrorlist_index;
-
- results = ask_from_list("Please select a medium in the list, "
- "or cancel to specify the mirror.",
- medialist, &selected_medium);
-
- if (results != RETURN_OK)
- break;
-
- /* select hosts matching medium and protocol */
- for (mirrorlist_index = 0; mirrorlist_index < mirrorlist_number; mirrorlist_index++) {
- if (!strcmp(mirrorlist[mirrorlist_index][0], selected_medium) &&
- !strcmp(mirrorlist[mirrorlist_index][1], protocol)) {
- hosts[host_index] = mirrorlist[mirrorlist_index][2];
- host_index++;
- if (host_index == MIRRORLIST_MAX_ITEMS)
- break;
- }
-
- }
- hosts[host_index+1] = NULL;
-
- results = ask_from_list("Please select a mirror in the list, "
- "or cancel to specify it.",
- hosts, selected_host);
- if (results != RETURN_OK) {
- break;
- }
-
- /* select the path according to medium, protocol and host */
- for (mirrorlist_index = 0; mirrorlist_index < mirrorlist_number; mirrorlist_index++) {
- if (!strcmp(mirrorlist[mirrorlist_index][0], selected_medium) &&
- !strcmp(mirrorlist[mirrorlist_index][1], protocol) &&
- !strcmp(mirrorlist[mirrorlist_index][2], *selected_host)) {
- *filepath = mirrorlist[mirrorlist_index][3];
- return RETURN_OK;
- }
- }
+ results = intf_select_and_up();
- stg1_info_message("Unable to find the path for this mirror, please select another one");
- results = RETURN_BACK;
-
- } while (results == RETURN_BACK);
+ if (results != RETURN_OK)
+ return results;
- return RETURN_ERROR;
+ return perform_ka();
}
+#endif