Browse Source

giant amounts of work in progress. DO NOT UPLOAD

r15194
master
Joshua Kwan 19 years ago
parent
commit
d8caf656c1
  1. 8
      Makefile
  2. 10
      debian/changelog
  3. 14
      debian/netcfg-dhcp.templates
  4. 311
      dhcp.c
  5. 104
      netcfg-common.c
  6. 10
      netcfg.c
  7. 9
      netcfg.h
  8. 3
      static.c
  9. 2
      wireless.c

8
Makefile

@ -7,7 +7,7 @@ CFLAGS = -W -Wall
COMMON_OBJS = netcfg-common.o mii-lite.o wireless.o
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0 -g
CFLAGS += -O0 -g3
else
CFLAGS += -Os -fomit-frame-pointer
endif
@ -22,13 +22,13 @@ netcfg-static: netcfg-static.o static.o
netcfg: netcfg.o dhcp.o static.o
$(TARGETS): $(COMMON_OBJS)
$(CC) $(LDOPTS) -o $@ $^
$(CC) -o $@ $^ $(LDOPTS)
$(STRIP) $@
%.o: %.c
$(CC) -c $(CFLAGS) $(INCS) -o $@ $<
$(CC) -c $(CFLAGS) $(DEFS) $(INCS) -o $@ $<
clean:
rm -f $(TARGETS) *.o
rm -f $(TARGETS) *.o build-stamp
.PHONY: all clean

10
debian/changelog

@ -1,6 +1,13 @@
netcfg (0.64) UNRELEASED; urgency=low
* Joshua Kwan
- Split out all functions into static.c, dhcp.c, wireless.c.
- Redesign DHCP strategy with a new template that uses a select,
allowing the user to clearly alternate to static network config
(Closes: #244901, #227722)
- Now we can ask for a DHCP hostname to add. (Closes: #236533, #239591)
- If we didn't use one, see if the server is offering us one and seed
netcfg/get_hostname with it. (Closes: #237395, #240701)
- For idempotency reasons, down all interfaces after finding each
one so that we can start from a clean slate.
- Silently load af_packet. (Closes: #244441)
@ -12,9 +19,6 @@ netcfg (0.64) UNRELEASED; urgency=low
up on subsequent questions.
- Bump the DHCP wait to 15 seconds. The magic number seems to be just
over 10 for me. (Closes: #244819)
- Ask for a hostname at the very beginning. This will be the DHCP
hostname for netcfg and netcfg-dhcp.
- As such, rip out netcfg_get_dhcp and netcfg_get_dhcp_hostname.
- Template cleanups: netcfg/static-title, netcfg/dhcp-title,
netcfg/internal-pcmcia
- Remove a lot of calls to /sbin/this and /sbin/that in response to Joey's

14
debian/netcfg-dhcp.templates

@ -26,11 +26,15 @@ _Description: No DHCP client found
The DHCP configuration process will be aborted.
Template: netcfg/dhcp_retry
Type: boolean
Default: false
_Description: Do you want to retry DHCP network configuration?
No IP address was found during automatic network configuration with DHCP.
DHCP servers are sometimes really slow. If you wish, you can retry.
Type: select
__Choices: Retry network autoconfiguration, Retry network autoconfiguration with a DHCP hostname, Configure network manually, Do not configure the network at this time
Default: Retry network autoconfiguration
_Description: Do you want to retry network autoconfiguration?
Network autoconfiguration failed. This is typically due to a slow DHCP
server on the network, so you probably want to try again. You may also
specify a DHCP hostname to send to the server if you think it needs one.
Otherwise, you may configure the network manually, or choose not to configure
it at all right now.
Template: debian-installer/netcfg-dhcp/title
Type: text

311
dhcp.c

@ -1,15 +1,23 @@
/*
* DHCP module for netcfg/netcfg-dhcp.
*
* Licensed under the terms of the GNU General Public License
*/
#include "netcfg.h"
#include <stdlib.h>
#include <unistd.h>
#include <debian-installer.h>
#include <stdio.h>
#include <assert.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <time.h>
#include <netdb.h>
/* Set if DHCP client exits */
volatile int dhcp_running = 0; /* not running */
int dhcp_exit_status = -1; /* failed */
int dhcp_running = 0, dhcp_exit_status = 1;
/* Signal handler for DHCP client child */
static void dhcp_client_sigchld(int sig __attribute__ ((unused)))
@ -17,6 +25,7 @@ static void dhcp_client_sigchld(int sig __attribute__ ((unused)))
if (dhcp_running == 1) {
dhcp_running = 0;
wait(&dhcp_exit_status);
dhcp_pid = -1;
}
}
@ -51,125 +60,217 @@ static void netcfg_write_dhcp (char* prebaseconfig, char *iface)
#define DHCP_SECONDS 15
int netcfg_activate_dhcp(struct debconfclient *client)
{
char buf[128];
struct stat stat_buf;
time_t start_time, now;
pid_t pid = 0;
int retry = 1;
char *ptr;
FILE *dc = NULL;
enum { PUMP, DHCLIENT, DHCLIENT3, UDHCPC } dhcp_client;
if (stat("/var/lib/dhcp3", &stat_buf) == 0)
dhcp_client = DHCLIENT3;
if (stat("/sbin/dhclient", &stat_buf) == 0)
dhcp_client = DHCLIENT;
else if (stat("/sbin/udhcpc", &stat_buf) == 0)
dhcp_client = UDHCPC;
else if (stat("/sbin/pump", &stat_buf) == 0)
dhcp_client = PUMP;
else {
debconf_input(client, "critical", "netcfg/no_dhcp_client");
debconf_go(client);
exit(1);
}
deconfigure_network();
/*
* This function will start whichever DHCP client is available (if
* necessary). That's all. The meat of the DHCP code is really in
* poll_dhcp_client.
*
* Its PID will be left in dhcp_pid.
* If the client is not running, dhcp_pid will always get set to -1.
*/
/* setup loopback */
di_exec_shell_log("ifconfig lo 127.0.0.1");
int start_dhcp_client (struct debconfclient *client, char* dhostname)
{
char buf[128];
FILE *dc = NULL;
dhclient_t dhcp_client;
/* load kernel module for network sockets silently */
di_exec_shell("modprobe af_packet");
if (access("/var/lib/dhcp3", F_OK) == 0)
dhcp_client = DHCLIENT3;
else if (access("/sbin/dhclient", F_OK) == 0)
dhcp_client = DHCLIENT;
else if (access("/sbin/pump", F_OK) == 0)
dhcp_client = PUMP;
else if (access("/sbin/udhcpc", F_OK) == 0)
dhcp_client = UDHCPC;
else {
debconf_input(client, "critical", "netcfg/no_dhcp_client");
debconf_go(client);
exit(1);
}
/* get dhcp lease */
switch (dhcp_client) {
/* get dhcp lease */
switch (dhcp_client) {
case PUMP:
snprintf(buf, sizeof(buf), "pump -i %s -h %s", interface, hostname);
break;
if (dhostname)
snprintf(buf, sizeof(buf), "pump -i %s -h %s", interface, dhostname);
else
snprintf(buf, sizeof(buf), "pump -i %s", interface);
break;
case DHCLIENT:
/* First, set up dhclient.conf */
if ((dc = file_open(DHCLIENT_CONF, "w")))
{
fprintf(dc, "send host-name %s\n", hostname);
fclose(dc);
}
snprintf(buf, sizeof(buf), "dhclient -e %s", interface);
break;
/* First, set up dhclient.conf if necessary */
if (dhostname)
{
if ((dc = file_open(DHCLIENT_CONF, "w")))
{
fprintf(dc, "send host-name %s\n", hostname);
fclose(dc);
}
}
snprintf(buf, sizeof(buf), "dhclient -e %s", interface);
break;
case DHCLIENT3:
/* Different place.. */
if ((dc = file_open(DHCLIENT3_CONF, "w")))
{
fprintf(dc, "send host-name %s\n", hostname);
fclose(dc);
}
snprintf(buf, sizeof(buf), "dhclient %s", interface);
break;
/* Different place.. */
if (dhostname)
{
if ((dc = file_open(DHCLIENT3_CONF, "w")))
{
fprintf(dc, "send host-name %s\n", hostname);
fclose(dc);
}
}
snprintf(buf, sizeof(buf), "dhclient %s", interface);
break;
case UDHCPC:
snprintf(buf, sizeof(buf), "udhcpc -i %s -n -H %s", hostname, interface);
break;
}
if (dhostname)
snprintf(buf, sizeof(buf), "udhcpc -i %s -n -H %s", interface, hostname);
else
snprintf(buf, sizeof(buf), "udhcpc -i %s -n", interface);
break;
}
while (retry == 1) {
/* show progress bar */
debconf_progress_start(client, 0, DHCP_SECONDS, "netcfg/dhcp_progress");
debconf_progress_info(client, "netcfg/dhcp_progress_note");
netcfg_progress_displayed = 1;
now = start_time = time(NULL);
if (! (dhcp_running || (dhcp_exit_status == 0))) {
if ((pid = fork()) == 0) {
int ret = di_exec_shell_log(buf);
((WIFEXITED(ret) && (WEXITSTATUS(ret) != 0)) || WIFSIGNALED(ret)) ?
_exit(EXIT_FAILURE) : _exit(EXIT_SUCCESS);
}
if (pid)
dhcp_running = 1;
else
return 1;
signal(SIGCHLD, &dhcp_client_sigchld);
}
if ((dhcp_pid = fork()) == 0) /* child */
{
int ret;
/* wait 10s for a DHCP lease */
while (dhcp_running && ((now - start_time) < DHCP_SECONDS)) {
sleep(1);
debconf_progress_step(client, 1);
now = time(NULL);
}
/* these guys log to syslog already */
if (dhcp_client == DHCLIENT || dhcp_client == DHCLIENT3)
ret = di_exec_shell(buf);
else
ret = di_exec_shell_log(buf);
_exit(!!ret);
}
else if (dhcp_pid == -1)
return 1;
else
{
dhcp_running = 1;
signal(SIGCHLD, &dhcp_client_sigchld);
return 0;
}
}
/* Poll the started DHCP cilent for ten seconds, and return 0 if a lease was
* acquired, 1 otherwise. The client should die once a lease is acquired.
*
* It will NOT reap the DHCP client after an unsuccessful poll.
*/
int poll_dhcp_client (struct debconfclient *client)
{
time_t start_time, now;
/* show progress bar */
debconf_progress_start(client, 0, DHCP_SECONDS, "netcfg/dhcp_progress");
debconf_progress_info(client, "netcfg/dhcp_progress_note");
netcfg_progress_displayed = 1;
now = start_time = time(NULL);
/* wait 10s for a DHCP lease */
while (dhcp_running && ((now - start_time) < DHCP_SECONDS)) {
sleep(1);
debconf_progress_step(client, 1);
now = time(NULL);
}
/* stop progress bar */
debconf_progress_stop(client);
netcfg_progress_displayed = 0;
/* stop progress bar */
debconf_progress_stop(client);
netcfg_progress_displayed = 0;
/* got a lease? */
if (!dhcp_running && (dhcp_exit_status == 0)) {
assert(hostname != NULL);
/* got a lease? */
if (!dhcp_running && (dhcp_exit_status == 0))
{
assert(hostname != NULL);
assert(dhcp_pid == -1);
/* write configuration */
netcfg_write_common("40netcfg", ipaddress, hostname, domain);
netcfg_write_dhcp("40netcfg", interface);
return 0;
}
return 1;
}
/* write configuration */
netcfg_write_common("40netcfg", ipaddress, hostname, domain);
netcfg_write_dhcp("40netcfg", interface);
int ask_dhcp_retry (struct debconfclient *client)
{
return 0;
}
/* Here comes another Satan machine. */
int netcfg_activate_dhcp (struct debconfclient *client)
{
enum { START, POLL, DHCP_HOSTNAME, HOSTNAME, STATIC, END } state = START;
loop_setup();
for (;;)
{
switch (state)
{
case START:
if (start_dhcp_client(client, NULL))
netcfg_die(client); /* change later */
else
state = POLL;
break;
return 0;
case DHCP_HOSTNAME:
break;
case POLL:
if (poll_dhcp_client(client)) /* could not get a lease */
{
/* ooh, now it's a select */
switch (ask_dhcp_retry (client))
{
case 0: state = POLL; break;
case 1: state = DHCP_HOSTNAME; break;
case 2: state = STATIC; break;
case 3: /* no net config at this time :( */
kill_dhcp_client();
exit(0);
}
}
else
{
char buf[MAXHOSTNAMELEN + 1];
/* ask if user wants to retry */
if (my_debconf_input(client, "high", "netcfg/dhcp_retry", &ptr) == 30) {
if (dhcp_running) {
kill(pid, SIGTERM);
}
return 30; /* backup */
}
retry = strstr(ptr, "true") ? 1 : 0;
}
/* dhcp hostname, ask for one with the dhcp hostname
* as a seed */
if (gethostname(buf, sizeof(buf)) == 0)
debconf_set(client, "netcfg/get_hostname", buf);
else
seed_hostname_from_dns(client);
state = HOSTNAME;
}
break;
case HOSTNAME:
if (netcfg_get_hostname (client, "netcfg/get_hostname", &hostname))
exit(10); /* go back */
else
state = END;
break;
if (dhcp_running) {
kill(pid, SIGTERM);
case STATIC:
break;
case END:
return 0;
}
return 1;
}
}
}

104
netcfg-common.c

@ -22,6 +22,7 @@
#include "netcfg.h"
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <sys/socket.h>
@ -36,6 +37,7 @@
#include <cdebconf/debconfclient.h>
#include <debian-installer.h>
#include <time.h>
#include <netdb.h>
/* Set if there is currently a progress bar displayed. */
int netcfg_progress_displayed = 0;
@ -47,6 +49,8 @@ char *domain = NULL;
struct in_addr ipaddress = { 0 };
int have_domain = 0;
pid_t dhcp_pid = -1;
int my_debconf_input(struct debconfclient *client, char *priority,
char *template, char **p)
{
@ -285,7 +289,7 @@ int netcfg_get_interface(struct debconfclient *client, char **interface,
int ret;
int num_interfaces = 0;
char *ptr = NULL;
char *ifdsc;
char *ifdsc = NULL;
if (*interface) {
free(*interface);
@ -299,6 +303,7 @@ int netcfg_get_interface(struct debconfclient *client, char **interface,
*ptr = '\0';
getif_start();
while ((inter = getif(1)) != NULL) {
size_t newchars;
@ -363,7 +368,7 @@ int netcfg_get_interface(struct debconfclient *client, char **interface,
* Set the hostname.
* @return 0 on success, 30 on BACKUP being selected.
*/
int netcfg_get_hostname(struct debconfclient *client, char **hostname)
int netcfg_get_hostname(struct debconfclient *client, char *template, char **hostname)
{
static const char *valid_chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.";
@ -373,7 +378,7 @@ int netcfg_get_hostname(struct debconfclient *client, char **hostname)
do {
have_domain = 0;
ret = my_debconf_input(client, "high", "netcfg/get_hostname", &p);
ret = my_debconf_input(client, "high", template, &p);
if (ret == 30) /* backup */
return ret;
free(*hostname);
@ -392,7 +397,7 @@ int netcfg_get_hostname(struct debconfclient *client, char **hostname)
debconf_go(client);
free(*hostname);
*hostname = NULL;
debconf_set(client, "netcfg/get_hostname", "debian");
debconf_set(client, template, "debian");
}
} while (!*hostname);
@ -419,7 +424,6 @@ int netcfg_get_hostname(struct debconfclient *client, char **hostname)
void netcfg_write_common(const char *prebaseconfig, struct in_addr ipaddress,
char *hostname, char *domain)
{
char ptr1[INET_ADDRSTRLEN];
FILE *fp;
if ((fp = file_open(INTERFACES_FILE, "w"))) {
@ -443,19 +447,17 @@ void netcfg_write_common(const char *prebaseconfig, struct in_addr ipaddress,
}
/* Currently busybox, hostname is not available. */
if ((fp = file_open("/proc/sys/kernel/hostname", "w"))) {
fprintf(fp, "%s\n", hostname);
fclose(fp);
}
sethostname (hostname, strlen(hostname) + 1);
if ((fp = file_open(HOSTNAME_FILE, "w"))) {
fprintf(fp, "%s\n", hostname);
fclose(fp);
di_system_prebaseconfig_append(prebaseconfig, "cp %s %s\n",
di_system_prebaseconfig_append(prebaseconfig, "cp %s %s\n",
HOSTNAME_FILE, "/target" HOSTNAME_FILE);
}
if ((fp = file_open(HOSTS_FILE, "w"))) {
char ptr1[INET_ADDRSTRLEN];
if (ipaddress.s_addr) {
fprintf(fp, "127.0.0.1\tlocalhost\t%s\n", hostname);
if (domain && !empty_str(domain))
@ -477,43 +479,27 @@ void netcfg_write_common(const char *prebaseconfig, struct in_addr ipaddress,
}
int kill_dhcp_client(void) {
FILE *ps;
char *pid_char = NULL;
int pid_int = 0;
size_t linesize = 0;
ssize_t ret = 0;
int kill_dhcp_client(void)
{
if (dhcp_pid != -1)
{
int s[] = { SIGTERM, SIGKILL, 0 }, *sigs = s;
/* kill running dhcp client */
while (*sigs)
{
kill(dhcp_pid, 0);
if ((ps = popen("ps xa | grep 'udhcpc\\|dhclient\\|pump' | grep -v grep | sed 's/^ *//' | cut -d ' ' -f 1", "r")) == NULL)
/* looks like it died */
if (errno == ESRCH)
return 1;
ret = getline(&pid_char, &linesize, ps);
if (ret < 1)
return 2;
pclose(ps);
pid_int = atoi(pid_char);
if (kill(pid_int, SIGTERM) != 0)
return 3;
sleep(2);
if (kill(pid_int, SIGTERM) == 0)
kill(pid_int, SIGKILL);
else
return 0;
sleep(2);
if (kill(pid_int, SIGTERM) == 0)
return 4;
return 0;
kill(dhcp_pid, *sigs);
sleep(2);
}
}
return 0;
}
int deconfigure_network(void) {
@ -566,3 +552,37 @@ int ifconfig_down (char* iface)
return ret;
}
void loop_setup(void)
{
static int afpacket_notloaded = 1;
deconfigure_network();
if (afpacket_notloaded)
afpacket_notloaded = di_exec_shell("modprobe af_packet"); /* should become 0 */
di_exec_shell_log("ifconfig lo 127.0.0.1 up");
}
void seed_hostname_from_dns (struct debconfclient * client)
{
struct addrinfo hints = {
.ai_family = PF_UNSPEC,
.ai_socktype = 0,
.ai_protocol = 0,
.ai_flags = AI_CANONNAME
};
struct addrinfo *res;
char ip[16]; /* 255.255.255.255 + 1 */
/* convert ipaddress into a char* */
inet_ntop(AF_INET, (void*)&ipaddress, ip, 16);
/* attempt resolution */
getaddrinfo(ip, NULL, &hints, &res);
/* got it */
if (res->ai_canonname && !empty_str(res->ai_canonname))
debconf_set(client, "netcfg/get_hostname", res->ai_canonname);
}

10
netcfg.c

@ -62,7 +62,7 @@ response_t netcfg_get_method(struct debconfclient *client)
int main(void)
{
int num_interfaces = 0;
enum { BACKUP, GET_HOSTNAME, GET_INTERFACE, GET_METHOD, GET_DHCP, GET_STATIC, WCONFIG, QUIT } state = GET_HOSTNAME;
enum { BACKUP, GET_INTERFACE, GET_METHOD, GET_DHCP, GET_STATIC, WCONFIG, QUIT } state = GET_INTERFACE;
static struct debconfclient *client;
static int requested_wireless_tools = 0;
response_t res;
@ -76,17 +76,11 @@ int main(void)
while (1) {
switch(state) {
case GET_HOSTNAME:
if (netcfg_get_hostname(client, &hostname))
state = BACKUP;
else
state = GET_INTERFACE;
break;
case BACKUP:
return 10;
case GET_INTERFACE:
if(netcfg_get_interface(client, &interface, &num_interfaces))
state = GET_HOSTNAME;
state = BACKUP;
else
{
if (is_wireless_iface (interface))

9
netcfg.h

@ -25,11 +25,13 @@
typedef enum { NOT_ASKED = 30, GO_BACK } response_t;
typedef enum { DHCP, STATIC, DUNNO } method_t;
typedef enum { ADHOC = 1, MANAGED = 2 } wifimode_t;
typedef enum { DHCLIENT, DHCLIENT3, PUMP, UDHCPC } dhclient_t;
extern int netcfg_progress_displayed;
extern int wfd;
extern int input_result;
extern int have_domain;
extern pid_t dhcp_pid;
/* network config */
extern char *interface;
@ -65,7 +67,7 @@ extern void netcfg_die (struct debconfclient *client);
extern int netcfg_get_interface(struct debconfclient *client, char **interface, int *num_interfaces);
extern int netcfg_get_hostname(struct debconfclient *client, char **hostname);
extern int netcfg_get_hostname(struct debconfclient *client, char *template, char **hostname);
extern int netcfg_get_nameservers (struct debconfclient *client, char **nameservers);
@ -77,6 +79,8 @@ extern int netcfg_get_static(struct debconfclient *client);
extern int netcfg_activate_dhcp(struct debconfclient *client);
extern int kill_dhcp_client(void);
extern int ask_dhcp_retry (struct debconfclient *client);
extern int netcfg_activate_static(struct debconfclient *client);
extern int my_debconf_input(struct debconfclient *client, char *priority, char *template, char **result);
@ -100,4 +104,7 @@ extern method_t mii_diag_status_lite (char *ifname);
extern int ifconfig_up (char*);
extern int ifconfig_down (char*);
extern void loop_setup(void);
extern void seed_hostname_from_dns(struct debconfclient *client);
#endif /* _NETCFG_H_ */

3
static.c

@ -312,9 +312,6 @@ int netcfg_activate_static(struct debconfclient *client)
#else
deconfigure_network();
/* configure loopback */
di_exec_shell_log("ifconfig lo 127.0.0.1");
snprintf(buf, sizeof(buf), "ifconfig %s %s",
interface, inet_ntop (AF_INET, &ipaddress, ptr1, sizeof (ptr1)));
di_snprintfcat(buf, sizeof(buf), " netmask %s", inet_ntop (AF_INET, &netmask, ptr1, sizeof (ptr1)));

2
wireless.c

@ -81,6 +81,7 @@ automatic:
debconf_progress_start(client, 0, MAX_SECS, "netcfg/wifi_progress_title");
debconf_progress_info(client, "netcfg/wifi_progress_info");
netcfg_progress_displayed = 1;
for (i = 0; i <= MAX_SECS; i++)
{
@ -102,6 +103,7 @@ automatic:
}
debconf_progress_stop(client);
netcfg_progress_displayed = 0;
if (success)
return 0;

Loading…
Cancel
Save