diff options
Diffstat (limited to 'mdk-stage1/dhcp.c')
| -rw-r--r-- | mdk-stage1/dhcp.c | 112 |
1 files changed, 88 insertions, 24 deletions
diff --git a/mdk-stage1/dhcp.c b/mdk-stage1/dhcp.c index 44877fd8a..678031e85 100644 --- a/mdk-stage1/dhcp.c +++ b/mdk-stage1/dhcp.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. @@ -27,6 +27,7 @@ #include <stdlib.h> #include <unistd.h> +#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/ioctl.h> @@ -44,8 +45,11 @@ #include "stage1.h" #include "log.h" +#include "tools.h" +#include "utils.h" #include "network.h" #include "frontend.h" +#include "automatic.h" #include "dhcp.h" @@ -67,6 +71,8 @@ typedef short bp_int16; #define DHCP_OPTION_OPTIONREQ 55 #define DHCP_OPTION_MAXSIZE 57 +#define DHCP_OPTION_CLIENT_IDENTIFIER 61 + #define BOOTP_CLIENT_PORT 68 #define BOOTP_SERVER_PORT 67 @@ -207,9 +213,16 @@ static void parse_reply(struct bootp_request * breq, struct interface_info * int unsigned char * chptr; unsigned char option, length; + if (strlen(breq->bootfile) > 0) { + if (IS_NETAUTO) + add_to_env("KICKSTART", breq->bootfile); + else + log_message("warning: ignoring `bootfile' DHCP server parameter, since `netauto' boot parameter was not given; reboot with `linux netauto' (and anymore useful boot parameters) if you want `bootfile' to be used as a `auto_inst.cfg.pl' stage2 configuration file"); + } + memcpy(&intf->ip, &breq->yiaddr, 4); - chptr = breq->vendor; + chptr = (unsigned char *) breq->vendor; chptr += 4; while (*chptr != 0xFF && (void *) chptr < (void *) breq->vendor + DHCP_VENDOR_LENGTH) { char tmp_str[500]; @@ -250,13 +263,6 @@ static void parse_reply(struct bootp_request * breq, struct interface_info * int log_message("got gateway %s", inet_ntoa(gateway)); break; - case BOOTP_OPTION_HOSTNAME: - memcpy(tmp_str, chptr, length); - tmp_str[length] = '\0'; - hostname = strdup(tmp_str); - log_message("got hostname %s", hostname); - break; - } chptr += length; @@ -286,7 +292,7 @@ static int prepare_request(struct bootp_request * breq, int sock, char * device) return -1; } - breq->hw = 1; /* ethernet */ + breq->hw = req.ifr_hwaddr.sa_family; breq->hwlength = IFHWADDRLEN; memcpy(breq->hwaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); memcpy(gen_hwaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); @@ -303,7 +309,7 @@ static int get_vendor_code(struct bootp_request * bresp, unsigned char option, v unsigned char * chptr; unsigned int length, theOption; - chptr = bresp->vendor + 4; + chptr = (unsigned char*) bresp->vendor + 4; while (*chptr != 0xFF && *chptr != option) { theOption = *chptr++; if (!theOption) @@ -322,11 +328,11 @@ static int get_vendor_code(struct bootp_request * bresp, unsigned char option, v } -static int currticks(void) +static unsigned long currticks(void) { struct timeval tv; - long csecs; - int ticks_per_csec, ticks_per_usec; + unsigned long csecs; + unsigned long ticks_per_csec, ticks_per_usec; /* Note: 18.2 ticks/sec. */ @@ -340,7 +346,7 @@ static int currticks(void) #define BACKOFF_LIMIT 7 #define TICKS_PER_SEC 18 -#define MAX_ARP_RETRIES 4 +#define MAX_ARP_RETRIES 7 static void rfc951_sleep(int exp) { @@ -415,7 +421,7 @@ static int handle_transaction(int s, struct bootp_request * breq, struct bootp_r } /* We need to do some basic sanity checking of the header */ - if (j < (sizeof(*ip_hdr) + sizeof(*udp_hdr))) + if (j < (signed)(sizeof(*ip_hdr) + sizeof(*udp_hdr))) continue; ip_hdr = (void *) eth_packet; @@ -479,7 +485,7 @@ static void add_vendor_code(struct bootp_request * breq, unsigned char option, u unsigned char * chptr; int theOption, theLength; - chptr = breq->vendor; + chptr = (unsigned char*) breq->vendor; chptr += 4; while (*chptr != 0xFF && *chptr != option) { theOption = *chptr++; @@ -495,6 +501,8 @@ static void add_vendor_code(struct bootp_request * breq, unsigned char option, u } +char * dhcp_hostname = NULL; +char * dhcp_domain = NULL; enum return_type perform_dhcp(struct interface_info * intf) { @@ -508,11 +516,7 @@ enum return_type perform_dhcp(struct interface_info * intf) short aShort; int num_options; char requested_options[50]; - - if (strncmp(intf->device, "eth", 3)) { - stg1_error_message("DHCP available only for Ethernet networking."); - return RETURN_ERROR; - } + char * client_id_str, * client_id_hwaddr; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { @@ -520,6 +524,35 @@ enum return_type perform_dhcp(struct interface_info * intf) return RETURN_ERROR; } + { + enum return_type results; + char * questions[] = { "Host name", "Domain name", NULL }; + char * questions_auto[] = { "hostname", "domain" }; + static char ** answers = NULL; + char * boulet; + + client_id_str = client_id_hwaddr = NULL; + + results = ask_from_entries_auto("If the DHCP server needs to know you by 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) + { + dhcp_hostname = answers[0]; + if ((boulet = strchr(dhcp_hostname, '.')) != NULL) + boulet[0] = '\0'; + dhcp_domain = answers[1]; + + if (*dhcp_hostname && *dhcp_domain) { + /* if we have both, then create client id from them */ + client_id_str = malloc(1 + strlen(dhcp_hostname) + 1 + strlen(dhcp_domain) + 1); + client_id_str[0] = '\0'; + sprintf(client_id_str+1, "%s.%s", dhcp_hostname, dhcp_domain); + } + } + } + if (initial_setup_interface(intf->device, s) != 0) { close(s); return RETURN_ERROR; @@ -533,7 +566,28 @@ enum return_type perform_dhcp(struct interface_info * intf) messageType = DHCP_TYPE_DISCOVER; add_vendor_code(&breq, DHCP_OPTION_TYPE, 1, &messageType); - memset(&client_addr.sin_addr, 0, sizeof(&client_addr.sin_addr)); + /* add pieces needed to have DDNS/DHCP IP selection based on requested name */ + if (dhcp_hostname && *dhcp_hostname) { /* pick client id form based on absence or presence of domain name */ + if (*dhcp_domain) /* alternate style <hostname>.<domainname> */ + add_vendor_code(&breq, DHCP_OPTION_CLIENT_IDENTIFIER, strlen(client_id_str+1)+1, client_id_str); + else { /* usual style (aka windows / dhcpcd) */ + /* but put MAC in form required for client identifier first */ + client_id_hwaddr = malloc(IFHWADDRLEN+2); + /* (from pump-0.8.22/dhcp.c) + * Microsoft uses a client identifier field of the 802.3 address with a + * pre-byte of a "1". In order to re-use the DHCP address that they set + * for this interface, we have to mimic their identifier. + */ + client_id_hwaddr[0] = 1; /* set flag for ethernet */ + memcpy(client_id_hwaddr+1, gen_hwaddr, IFHWADDRLEN); + add_vendor_code(&breq, DHCP_OPTION_CLIENT_IDENTIFIER, IFHWADDRLEN+1, client_id_hwaddr); + } + /* this is the one that the dhcp server really wants for DDNS updates */ + add_vendor_code(&breq, BOOTP_OPTION_HOSTNAME, strlen(dhcp_hostname), dhcp_hostname); + log_message("DHCP: telling server to use name = %s", dhcp_hostname); + } + + memset(&client_addr.sin_addr, 0, sizeof(client_addr.sin_addr)); client_addr.sin_family = AF_INET; client_addr.sin_port = htons(BOOTP_CLIENT_PORT); /* bootp client */ @@ -572,6 +626,16 @@ enum return_type perform_dhcp(struct interface_info * intf) add_vendor_code(&breq, DHCP_OPTION_SERVER, 4, &server_addr.sin_addr); add_vendor_code(&breq, DHCP_OPTION_REQADDR, 4, &bresp.yiaddr); + /* if used the first time, then have to use it again */ + if (dhcp_hostname && *dhcp_hostname) { /* add pieces needed to have DDNS/DHCP IP selection based on requested name */ + if (dhcp_domain && *dhcp_domain) /* alternate style */ + add_vendor_code(&breq, DHCP_OPTION_CLIENT_IDENTIFIER, strlen(client_id_str+1)+1, client_id_str); + else /* usual style (aka windows / dhcpcd) */ + add_vendor_code(&breq, DHCP_OPTION_CLIENT_IDENTIFIER, IFHWADDRLEN+1, client_id_hwaddr); + /* this is the one that the dhcp server really wants for DDNS updates */ + add_vendor_code(&breq, BOOTP_OPTION_HOSTNAME, strlen(dhcp_hostname), dhcp_hostname); + } + aShort = ntohs(sizeof(struct bootp_request)); add_vendor_code(&breq, DHCP_OPTION_MAXSIZE, 2, &aShort); |
