From e31889e238c53438cd387b11fed03b8645ac24c0 Mon Sep 17 00:00:00 2001 From: Guillaume Cottenceau Date: Fri, 1 Jun 2001 19:09:27 +0000 Subject: - first draft of adsl support - get back some code for supporting broken glibc unable to resolve when linked statically --- mdk-stage1/adsl.c | 106 ++++++++++++++++++++++++++++ mdk-stage1/adsl.h | 34 +++++++++ mdk-stage1/dns.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++---- mdk-stage1/dns.h | 6 +- mdk-stage1/network.c | 65 ++++++++++------- mdk-stage1/network.h | 2 + mdk-stage1/nfsmount.c | 7 +- mdk-stage1/url.c | 9 +-- 8 files changed, 366 insertions(+), 54 deletions(-) create mode 100644 mdk-stage1/adsl.c create mode 100644 mdk-stage1/adsl.h diff --git a/mdk-stage1/adsl.c b/mdk-stage1/adsl.c new file mode 100644 index 000000000..c1ecae32c --- /dev/null +++ b/mdk-stage1/adsl.c @@ -0,0 +1,106 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stage1.h" +#include "log.h" +#include "network.h" +#include "modules.h" +#include "tools.h" +#include "frontend.h" + +#include "adsl.h" + +enum return_type perform_adsl(struct interface_info * intf) +{ + char * pppd_launch[] = { "/sbin/pppd", "pty", "/sbin/pppoe -p /var/run/pppoe.conf-adsl.pid.pppoe -I eth0 -T 80 -U -m 1412", + "noipdefault", "noauth", "default-asyncmap", "defaultroute", "hide-password", "nodetach", "usepeerdns", + "local", "mtu", "1492", "mru", "1492", "noaccomp", "noccp", "nobsdcomp", "nodeflate", "nopcomp", + "novj", "novjccomp", "user", "netissimo@netissimo", "lcp-echo-interval", "20", "lcp-echo-failure", + "3", NULL }; + int fd; + + struct in_addr addr; + + if (strncmp(intf->device, "eth", 3)) { + stg1_error_message("ADSL available only for Ethernet networking (through PPPoE)."); + return RETURN_ERROR; + } + + inet_aton("10.0.0.10", &addr); + memcpy(&intf->ip, &addr, sizeof(addr)); + + inet_aton("255.255.255.0", &addr); + memcpy(&intf->netmask, &addr, sizeof(addr)); + + *((uint32_t *) &intf->broadcast) = (*((uint32_t *) &intf->ip) & + *((uint32_t *) &intf->netmask)) | ~(*((uint32_t *) &intf->netmask)); + + intf->is_ptp = 0; + + if (configure_net_device(intf)) { + stg1_error_message("Could not configure.."); + return RETURN_ERROR; + } + + my_insmod("ppp_generic", ANY_DRIVER_TYPE, NULL); + my_insmod("ppp_async", ANY_DRIVER_TYPE, NULL); + my_insmod("ppp_synctty", ANY_DRIVER_TYPE, NULL); + my_insmod("ppp", ANY_DRIVER_TYPE, NULL); + + stg1_info_message("Interface %s seems ready.", intf->device); + + + fd = open("/dev/tty6", O_RDWR); + if (fd == -1) { + log_message("cannot open /dev/tty6 -- no pppd"); + return RETURN_ERROR; + } + else if (access(pppd_launch[0], X_OK)) { + log_message("cannot open pppd - %s doesn't exist", pppd_launch[0]); + return RETURN_ERROR; + } + + if (!fork()) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + close(fd); + setsid(); + if (ioctl(0, TIOCSCTTY, NULL)) + log_perror("could not set new controlling tty"); + + execve(pppd_launch[0], pppd_launch, grab_env()); + log_message("execve of %s failed: %s", pppd_launch[0], strerror(errno)); + } + + close(fd); + + stg1_info_message("Forked for %s.", intf->device); + + return RETURN_OK; + +} diff --git a/mdk-stage1/adsl.h b/mdk-stage1/adsl.h new file mode 100644 index 000000000..9d32cc631 --- /dev/null +++ b/mdk-stage1/adsl.h @@ -0,0 +1,34 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html + * + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * Portions from GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * Itself based on etherboot-4.6.4 by Martin Renters. + * + */ + +#ifndef _ADSL_H_ +#define _ADSL_H_ + +#include "stage1.h" +#include "network.h" + +enum return_type perform_adsl(struct interface_info * intf); + +#endif diff --git a/mdk-stage1/dns.c b/mdk-stage1/dns.c index 054001c58..d1e67c78d 100644 --- a/mdk-stage1/dns.c +++ b/mdk-stage1/dns.c @@ -20,29 +20,194 @@ */ #include + +// dietlibc can do hostname lookup, whereas glibc can't when linked statically :-( + +#ifdef __LIBC_DIETLIBC__ + #include #include #include +#include +#include #include "network.h" #include "log.h" #include "dns.h" +int mygethostbyname(char * name, struct in_addr * addr) +{ + struct hostent * h = gethostbyname(name); + if (!h) { + if (domain) { + // gethostbyname from dietlibc doesn't support domain handling + char fully_qualified[500]; + sprintf(fully_qualified, "%s.%s", name, domain); + h = gethostbyname(fully_qualified); + if (!h) { + log_message("unknown host %s", name); + return -1; + } + } else + return -1; + } + + if (h->h_addr_list && (h->h_addr_list)[0]) { + memcpy(addr, (h->h_addr_list)[0], sizeof(*addr)); + log_message("is-at: %s", inet_ntoa(*addr)); + return 0; + } + return -1; +} + +char * mygethostbyaddr(char * ipnum) +{ + struct in_addr in; + struct hostent * host; + if (!inet_aton(ipnum, &in)) + return NULL; + host = gethostbyaddr(&in, strlen((void *) &in), AF_INET); + if (host && host->h_name) + return host->h_name; + return NULL; +} + + +#else // __LIBC_DIETLIBC__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" + +#include "dns.h" + +/* This is dumb, but glibc doesn't like to do hostname lookups w/o libc.so */ + +union dns_response { + HEADER hdr; + u_char buf[PACKETSZ]; +} ; -// needs a wrapper since gethostbyname from dietlibc doesn't support domain handling -struct hostent *mygethostbyname(const char *name) +static int do_query(char * query, int queryType, char ** domainName, struct in_addr * ipNum) { - char fully_qualified[500]; - struct hostent * h; - h = gethostbyname(name); - if (h) - return h; - if (!domain) + int len, ancount, type; + u_char * data, * end; + char name[MAXDNAME]; + union dns_response response; + +#ifdef __sparc__ + /* from jj: */ + /* We have to wait till ethernet negotiation is done */ + _res.retry = 3; +#else + _res.retry = 2; +#endif + + + len = res_search(query, C_IN, queryType, (void *) &response, sizeof(response)); + if (len <= 0) + return -1; + + if (ntohs(response.hdr.rcode) != NOERROR) + return -1; + + ancount = ntohs(response.hdr.ancount); + if (ancount < 1) + return -1; + + data = response.buf + sizeof(HEADER); + end = response.buf + len; + + /* skip the question */ + data += dn_skipname(data, end) + 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 */ + GETSHORT(type, data); + data += INT16SZ; /* skipp class */ + data += INT32SZ; /* skipp 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) return -1; + if (queryType == T_PTR && domainName) { + /* we wanted a pointer */ + *domainName = malloc(strlen(name) + 1); + strcpy(*domainName, name); + 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)); + return 0; + } + } + + /* move ahead to next RR */ + data += len; + } + + 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 = do_query(ipnum, T_PTR, &result, NULL); + + if (rc) return NULL; - sprintf(fully_qualified, "%s.%s", name, domain); - h = gethostbyname(fully_qualified); - if (!h) - log_message("unknown host %s", name); - return h; + else + return result; +} + +int mygethostbyname(char * name, struct in_addr * addr) { + int rc = do_query(name, T_A, NULL, addr); + if (!rc) + log_message("is-at %s", inet_ntoa(*addr)); + return rc; } + +#endif diff --git a/mdk-stage1/dns.h b/mdk-stage1/dns.h index 8506db923..97af9c08a 100644 --- a/mdk-stage1/dns.h +++ b/mdk-stage1/dns.h @@ -22,9 +22,9 @@ #ifndef H_DNS #define H_DNS -#include +#include -// needs a wrapper since gethostbyname from dietlibc doesn't support domain handling -struct hostent *mygethostbyname(const char *name); +int mygethostbyname(char * name, struct in_addr * addr); +char * mygethostbyaddr(char * ipnum); #endif diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c index 4efecda13..48779cdfa 100644 --- a/mdk-stage1/network.c +++ b/mdk-stage1/network.c @@ -40,7 +40,9 @@ #include "mount.h" #include "automatic.h" #include "dhcp.h" +#include "adsl.h" #include "url.h" +#include "dns.h" #include "network.h" @@ -51,7 +53,7 @@ static void error_message_net(void) /* reduce code size */ } -static int configure_net_device(struct interface_info * intf) +int configure_net_device(struct interface_info * intf) { struct ifreq req; struct rtentry route; @@ -167,6 +169,15 @@ static int configure_net_device(struct interface_info * intf) intf->is_up = 1; + if (intf->boot_proto == BOOTPROTO_STATIC) { + /* I need to sleep a bit in order for kernel to finish + init of the network device; if not, first sendto() for + gethostbyaddr will get an EINVAL. */ + wait_message("Bringing up networking..."); + sleep(2); + remove_wait_message(); + } + return 0; } @@ -353,8 +364,8 @@ 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", NULL }; - char * bootprotos_auto[] = { "static", "dhcp" }; + char * bootprotos[] = { "Static", "DHCP", "ADSL", NULL }; + char * bootprotos_auto[] = { "static", "dhcp", "adsl" }; char * choice; results = ask_from_list_auto("Please choose the desired IP attribution.", bootprotos, &choice, "network", bootprotos_auto); @@ -409,7 +420,11 @@ static enum return_type setup_network_interface(struct interface_info * intf) intf->is_ptp = 0; } intf->boot_proto = BOOTPROTO_STATIC; - } else { + + if (configure_net_device(intf)) + return RETURN_ERROR; + + } else if (streq(choice, "DHCP")) { results = perform_dhcp(intf); if (results == RETURN_BACK) @@ -417,37 +432,37 @@ static enum return_type setup_network_interface(struct interface_info * intf) if (results == RETURN_ERROR) return results; intf->boot_proto = BOOTPROTO_DHCP; - } - - if (configure_net_device(intf)) - return RETURN_ERROR; - if (intf->boot_proto == BOOTPROTO_STATIC) { - /* I need to sleep a bit in order for kernel to finish - init of the network device; if not, first sendto() for - gethostbyaddr will get an EINVAL. */ - wait_message("Bringing up networking..."); - sleep(2); - remove_wait_message(); - } + if (configure_net_device(intf)) + return RETURN_ERROR; + } else if (streq(choice, "ADSL")) { + intf->boot_proto = BOOTPROTO_STATIC; + + results = perform_adsl(intf); + + if (results == RETURN_BACK) + return setup_network_interface(intf); + if (results == RETURN_ERROR) + return results; + } else + return RETURN_ERROR; + return add_default_route(); } static enum return_type configure_network(struct interface_info * intf) { - struct hostent * host; + char * dnshostname; if (hostname && domain) return RETURN_OK; - wait_message("Trying to resolve hostname..."); - host = gethostbyaddr(&(intf->ip), strlen((void *) &(intf->ip)), AF_INET); - remove_wait_message(); + dnshostname = mygethostbyaddr(inet_ntoa(intf->ip)); - if (host && host->h_name) { - hostname = strdup(host->h_name); + 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; @@ -460,12 +475,12 @@ static enum return_type configure_network(struct interface_info * intf) if (dns_server.s_addr != 0) { wait_message("Trying to resolve dns..."); - host = gethostbyaddr(&dns_server, strlen((void *) &dns_server), AF_INET); + dnshostname = mygethostbyaddr(inet_ntoa(dns_server)); remove_wait_message(); } - if (host && host->h_name) { - domain = strchr(strdup(host->h_name), '.') + 1; + if (dnshostname) { + domain = strchr(strdup(dnshostname), '.') + 1; log_message("got domain from DNS fullname, %s", domain); } else { enum return_type results; diff --git a/mdk-stage1/network.h b/mdk-stage1/network.h index aa5b9d38d..0848c715e 100644 --- a/mdk-stage1/network.h +++ b/mdk-stage1/network.h @@ -47,6 +47,8 @@ struct interface_info { char * guess_netmask(char * ip_addr); +int configure_net_device(struct interface_info * intf); + extern char * hostname; extern char * domain; extern struct in_addr gateway; diff --git a/mdk-stage1/nfsmount.c b/mdk-stage1/nfsmount.c index 66d09c5f2..032fde60c 100644 --- a/mdk-stage1/nfsmount.c +++ b/mdk-stage1/nfsmount.c @@ -150,12 +150,7 @@ int nfsmount_prepare(const char *spec, int *flags, char **mount_opts) /* first, try as IP address */ if (!inet_aton(hostname, &server_addr.sin_addr)) { /* failure, try as machine name */ - struct hostent * host; - host = mygethostbyname(hostname); - if (host && host->h_addr_list && (host->h_addr_list)[0]) { - server_addr.sin_addr = *((struct in_addr *) (host->h_addr_list)[0]); - log_message("is-at: %s", inet_ntoa(server_addr.sin_addr)); - } else + if (mygethostbyname(hostname, &server_addr.sin_addr)) goto fail; } diff --git a/mdk-stage1/url.c b/mdk-stage1/url.c index 4cde2ae30..236782a50 100644 --- a/mdk-stage1/url.c +++ b/mdk-stage1/url.c @@ -152,19 +152,14 @@ static int ftp_command(int sock, char * command, char * param) return 0; } -static int get_host_address(const char * host, struct in_addr * address) +static int get_host_address(char * host, struct in_addr * address) { if (isdigit(host[0])) { if (!inet_aton(host, address)) { return FTPERR_BAD_HOST_ADDR; } } else { - struct hostent * h; - h = mygethostbyname(host); - if (h && h->h_addr_list && (h->h_addr_list)[0]) { - *address = *((struct in_addr *) (h->h_addr_list)[0]); - log_message("is-at: %s", inet_ntoa(*address)); - } else + if (mygethostbyname(host, address)) return FTPERR_BAD_HOSTNAME; } -- cgit v1.2.1