Browse Source

now we search for interfaces and give the user a choice of which to configure

fixed some bugs/clumsyness

r261
master
David Whedon 23 years ago
parent
commit
ea87371446
  1. 7
      Makefile
  2. 8
      TODO
  3. 25
      debian/templates
  4. 231
      netcfg.c
  5. 170
      util.c
  6. 39
      util.h

7
Makefile

@ -6,12 +6,15 @@ INSTALL=install
STRIPTOOL=strip
STRIP = $(STRIPTOOL) --remove-section=.note --remove-section=.comment
OBJS=util.o
all: netcfg
$(STRIP) netcfg
size netcfg
netcfg: netcfg.c
$(CC) $(CFLAGS) netcfg.c -o netcfg $(INCS) $(LDOPTS)
netcfg: netcfg.c $(OBJS)
$(CC) $(CFLAGS) netcfg.c -o netcfg $(INCS) $(LDOPTS) $(OBJS)
install:
mkdir -p $(PREFIX)/bin/

8
TODO

@ -1,13 +1,9 @@
* menutest : check for existance and size, of conf files (any other checks?)
* search for network interfaces and allow the user to choose which one they want to configure
* put in checks so the user can't enter data that is clearly invalid (perhaps this will be done through debconf.
* dhcp: either another module, or in here
* fall back to safe defaults if the user doesn't enter a particular value (ex. gateway)
* create config dirs if they don't exist
* do other sorts of network configurations (pcmcia)
* inderstand the target_path() thing, and do it properly
* what do we do differently if it is a CD filesystem?
* make sure the gateway (if any) is reachable (i.e. is on the system's network)
* clear any DNS entries the user doesn't enter
* fix the strtok() DNS clumsyness
* decide what numbers you will actually present the user with for confirmation (you have overkill now)
* fix the note about what the user should do if we don't find any network interfaces. Since I don't now know what the flow of the installer is going to be I can't suggest what they should do, I've got the test in there from the old installer now.
* currently we get an internal error if the user has lots of network interfaces, find a better way of handling that.

25
debian/templates

@ -1,3 +1,20 @@
Template: netcfg/no_interfaces
Type: note
Description: no network devices found
No network interfaces were found. That means that the installation system
was unable to find a network device. If you do have a network card, then it
is possible that the module for it hasn't been selected yet. Go back to the
'Configure Device Driver Modules' menu and load the required kernel modules
first. If your only network connection is PPP, don't worry -- you will be
asked if you want PPP later in the process.
Template: netcfg/choose_interface
Type: select
Choices: ${ifchoices}
Description: Choose an interface
The following interfaces were detected. Choose the type of your primary
network interface that you will need for installing Debian (via NFS or HTTP).
Template: netcfg/dhcp_option
Type: boolean
Default: true
@ -52,13 +69,6 @@ Type: note
Description: The gateway you entered is unreachable.
You may have made an error entering your ipaddress, netmask and/or gateway.
Template: netcfg/get_domain
Type: string
Description: Choose the Domain name.
As with individual systems, every network has a name. This name is called the
domain name. Please enter your domain name or leave this field empty if you
don't have a domain.
Template: netcfg/get_nameservers
Type: string
Description: Choose the DNS Server Addresses
@ -72,6 +82,7 @@ Template: netcfg/confirm_static_cfg
Type: boolean
Default: true
Description: Is this configuration correct?
interface = ${interface}
hostname = ${hostname}
domain = ${domain}
ipaddress = ${ipaddress}

231
netcfg.c

@ -13,9 +13,11 @@
#include <sys/stat.h>
#include <debconfclient.h>
#include "util.h"
static char *interface = NULL;
static char *hostname = NULL;
static char *domain = NULL;
static char *iface = "eth0";
static u_int32_t ipaddress = 0;
static u_int32_t network = 0;
static u_int32_t broadcast = 0;
@ -27,13 +29,19 @@ static u_int32_t nameservers[4] = { 0 };
static struct debconfclient *client;
#define MAXLINE 128
static char cmd_buf[MAXLINE];
static char buf[MAXLINE];
#ifdef DEBUG
#define INTERFACES_FILE "etc/network/interfaces"
#define HOSTS_FILE "etc/hosts"
#define NETWORKS_FILE "etc/networks"
#define RESOLV_FILE "etc/resolv.conf"
#else
#define INTERFACES_FILE "/etc/network/interfaces"
#define HOSTS_FILE "/etc/hosts"
#define NETWORKS_FILE "/etc/networks"
#define RESOLV_FILE "/etc/resolv.conf"
#endif
/**
@ -80,6 +88,9 @@ num2dot (u_int32_t num)
int ix;
char *dot = num2dot_buf;
if (num == 0)
return NULL;
for (ix = 3; ix >= 0; ix--)
{
byte[ix] = num & 0xff;
@ -90,6 +101,7 @@ num2dot (u_int32_t num)
return dot;
}
char *
debconf_input (char *priority, char *template)
{
@ -100,112 +112,122 @@ debconf_input (char *priority, char *template)
}
void
debconf_subst (char *template, char *key, char *string){
client->command (client, "subst", "netcfg/confirm_static_cfg",
key, string, NULL);
debconf_subst (char *template, char *key, char *string)
{
if (string)
client->command (client, "subst", template, key, string, NULL);
else
client->command (client, "subst", template, key, "<none>", NULL);
}
void
debconf_unseen(char *template){
client->command (client, "fset", template, "seen",
"false", NULL);
debconf_unseen (char *template)
{
client->command (client, "fset", template, "seen", "false", NULL);
}
void
get_static_cfg (void)
{
int finished = 0;
char *ptr, *ns1, *ns2, *ns3;
char finished = 0;
char *ptr, *ns;
do
{
get_interface ();
debconf_unseen ("netcfg/get_hostname");
debconf_unseen ("netcfg/get_ipaddress");
debconf_unseen ("netcfg/get_netmask");
debconf_unseen ("netcfg/get_gateway");
debconf_unseen ("netcfg/get_nameservers");
debconf_unseen ("netcfg/confirm_static_cfg");
if (hostname)
free (hostname);
if (domain)
free (domain);
hostname = domain = NULL;
ipaddress = network = broadcast = netmask = gateway =
nameservers[0] = 0;
hostname = strdup (debconf_input ("high", "netcfg/get_hostname"));
debconf_subst("netcfg/confirm_static_cfg", "hostname", hostname);
debconf_subst ("netcfg/confirm_static_cfg", "hostname", hostname);
if ((ptr = debconf_input ("high", "netcfg/get_domain")))
{
domain = strdup (ptr);
debconf_subst("netcfg/confirm_static_cfg", "domain", domain);
}
domain = strdup (ptr);
debconf_subst ("netcfg/confirm_static_cfg", "domain", domain);
if ((ptr = debconf_input ("high", "netcfg/get_ipaddress")))
{
dot2num (&ipaddress, ptr);
debconf_subst("netcfg/confirm_static_cfg", "ipaddress", ptr);
}
dot2num (&ipaddress, ptr);
debconf_subst ("netcfg/confirm_static_cfg", "ipaddress",
num2dot (ipaddress));
if ((ptr = debconf_input ("high", "netcfg/get_netmask")))
{
dot2num (&netmask, ptr);
debconf_subst("netcfg/confirm_static_cfg", "netmask", ptr);
}
dot2num (&netmask, ptr);
debconf_subst ("netcfg/confirm_static_cfg", "netmask",
num2dot (netmask));
network = ipaddress & netmask;
debconf_subst ("netcfg/confirm_static_cfg", "network", num2dot (network));
debconf_subst ("netcfg/confirm_static_cfg", "network",
num2dot (network));
if (( ptr = debconf_input ("high", "netcfg/get_gateway")))
{
dot2num (&gateway, ptr);
debconf_subst("netcfg/confirm_static_cfg", "gateway", ptr);
}
if ((ptr = debconf_input ("high", "netcfg/get_gateway")))
dot2num (&gateway, ptr);
debconf_subst ("netcfg/confirm_static_cfg", "gateway",
num2dot (gateway));
if ((gateway & netmask) != (ipaddress & netmask))
{
client->command (client, "input", "high", "netcfg/gateway_unreachable", NULL);
{
client->command (client, "input", "high",
"netcfg/gateway_unreachable", NULL);
client->command (client, "go", NULL);
}
}
broadcast = (network | ~netmask);
debconf_subst("netcfg/confirm_static_cfg", "broadcast", num2dot(broadcast));
debconf_subst ("netcfg/confirm_static_cfg", "broadcast",
num2dot (broadcast));
ptr = debconf_input ("high", "netcfg/get_nameservers");
if (ptr)
{
char *save;
save = ptr = strdup (ptr);
ns = strtok_r (ptr, " ", &ptr);
debconf_subst ("netcfg/confirm_static_cfg", "primary_DNS", ns);
dot2num (&nameservers[0], ns);
ns = strtok_r (NULL, " ", &ptr);
debconf_subst ("netcfg/confirm_static_cfg", "secondary_DNS", ns);
dot2num (&nameservers[1], ns);
ns = strtok_r (NULL, " ", &ptr);
debconf_subst ("netcfg/confirm_static_cfg", "tertiary_DNS", ns);
dot2num (&nameservers[2], ns);
ptr = strdup (ptr);
ns1 = strtok (ptr, " ");
ns2 = strtok (NULL, " ");
ns3 = strtok (NULL, " ");
if (ns1 != NULL)
debconf_subst("netcfg/confirm_static_cfg", "primary_DNS", ns1);
else
debconf_subst("netcfg/confirm_static_cfg", "primary_DNS", "none");
if (ns2 != NULL)
debconf_subst("netcfg/confirm_static_cfg", "secondary_DNS", ns1);
else
debconf_subst("netcfg/confirm_static_cfg", "secondary_DNS", "none");
if (ns3 != NULL)
debconf_subst("netcfg/confirm_static_cfg", "tertiary_DNS", ns1);
else
debconf_subst("netcfg/confirm_static_cfg", "tertiary_DNS", "none");
free (ptr);
free (save);
}
else
{
debconf_subst ("netcfg/confirm_static_cfg", "primary_DNS", NULL);
debconf_subst ("netcfg/confirm_static_cfg", "secondary_DNS", NULL);
debconf_subst ("netcfg/confirm_static_cfg", "tertiary_DNS", NULL);
}
ptr = debconf_input ("high", "netcfg/confirm_static_cfg");
if (strstr (ptr, "true"))
finished = 1;
else
{
debconf_unseen ("netcfg/get_hostname");
debconf_unseen ("netcfg/get_ipaddress");
debconf_unseen ("netcfg/get_netmask");
debconf_unseen ("netcfg/get_gateway");
debconf_unseen ("netcfg/get_nameservers");
debconf_unseen ("netcfg/get_confirm_static_cfg");
free (hostname);
free (domain);
hostname = domain = NULL;
ipaddress = network = broadcast = netmask = gateway = nameservers[0] = 0 ;
}
}
while (!finished);
@ -213,14 +235,15 @@ get_static_cfg (void)
}
FILE *
file_open(char *path){
FILE *fp;
if (( fp = fopen(path, "w")))
return fp;
else
file_open (char *path)
{
FILE *fp;
if ((fp = fopen (path, "w")))
return fp;
else
{
perror("fopen");
return NULL;
perror ("fopen");
return NULL;
}
}
@ -231,6 +254,7 @@ void
write_static_cfg (void)
{
FILE *fp;
int i;
if ((fp = file_open (HOSTS_FILE)))
{
@ -256,7 +280,7 @@ write_static_cfg (void)
if ((fp = file_open (RESOLV_FILE)))
{
int i = 0;
i = 0;
if (domain)
fprintf (fp, "search %s\n", domain);
while (nameservers[i])
@ -271,7 +295,7 @@ write_static_cfg (void)
fprintf (fp,
"\n# The first network card - this entry was created during the Debian installation\n");
fprintf (fp, "# (network, broadcast and gateway are optional)\n");
fprintf (fp, "iface eth0 inet static\n");
fprintf (fp, "iface %s inet static\n", interface);
fprintf (fp, "\taddress %s\n", num2dot (ipaddress));
fprintf (fp, "\tnetmask %s\n", num2dot (netmask));
fprintf (fp, "\tnetwork %s\n", num2dot (network));
@ -290,14 +314,60 @@ activate_static_net ()
system ("/sbin/ifconfig lo 127.0.0.1");
snprintf (cmd_buf, sizeof (cmd_buf),
"/sbin/ifconfig %s %s netmask %s broadcast %s", iface,
snprintf (buf, sizeof (buf),
"/sbin/ifconfig %s %s netmask %s broadcast %s", interface,
num2dot (ipaddress), num2dot (netmask), num2dot (broadcast));
system ("cmd_buf");
system ("buf");
return 0;
}
/*
* Get all available interfaces from the kernel and ask the user which one
* he wants to configure
*/
int
get_interface ()
{
char *ptr = buf;
char *inter;
debconf_unseen ("netcfg/choose_interface");
getif_start ();
while ((inter = getif (1)) != NULL)
{
ptr +=
snprintf (ptr, sizeof (buf) - strlen (buf), "%s: %s, ", inter,
get_ifdsc (inter));
if (ptr > (buf + sizeof (buf)))
{
fprintf (stderr, "Internal error.\n");
exit (1);
}
}
getif_end ();
if (ptr == buf)
{
client->command (client, "input", "high", "netcfg/no_interfaces", NULL);
client->command (client, "go", NULL);
return -1;
}
debconf_subst ("netcfg/choose_interface", "ifchoices", buf);
ptr = debconf_input ("critical", "netcfg/choose_interface");
*(strchr (ptr, ':')) = '\0';
interface = strdup (ptr);
debconf_subst ("netcfg/confirm_static_cfg", "interface", interface);
return 0;
}
int
@ -308,7 +378,6 @@ main (int argc, char *argv[])
client->command (client, "title", "Network Configuration", NULL);
get_static_cfg ();
write_static_cfg ();

170
util.c

@ -0,0 +1,170 @@
/*
* file: util.c
* These functions were taken mostly untouched from dbootstrap
*
* */
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include "util.h"
int
is_interface_up (char *inter)
{
struct ifreq ifr;
int sfd = -1, ret = -1;
if ((sfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
goto int_up_done;
strncpy (ifr.ifr_name, inter, sizeof (ifr.ifr_name));
if (ioctl (sfd, SIOCGIFFLAGS, &ifr) < 0)
goto int_up_done;
ret = (ifr.ifr_flags & IFF_UP) ? 1 : 0;
int_up_done:
if (sfd != -1)
close (sfd);
return ret;
}
static FILE *ifs = NULL;
static char ibuf[512];
void
getif_start (void)
{
if (ifs != NULL)
{
fclose (ifs);
ifs = NULL;
}
if ((ifs = fopen ("/proc/net/dev", "r")) != NULL)
{
fgets (ibuf, sizeof (ibuf), ifs); /* eat header */
fgets (ibuf, sizeof (ibuf), ifs); /* ditto */
}
return;
}
void
getif_end (void)
{
if (ifs != NULL)
{
fclose (ifs);
ifs = NULL;
}
return;
}
char *
getif (int all)
{
char rbuf[512];
if (ifs == NULL)
return NULL;
if (fgets (rbuf, sizeof (rbuf), ifs) != NULL)
{
get_name (ibuf, rbuf);
if (!strcmp (ibuf, "lo")) /* ignore the loopback */
return getif (all); /* seriously doubt there is an infinite number of lo devices */
if (all || is_interface_up (ibuf) == 1)
return ibuf;
}
return NULL;
}
void
get_name (char *name, char *p)
{
while (isspace (*p))
p++;
while (*p)
{
if (isspace (*p))
break;
if (*p == ':')
{ /* could be an alias */
char *dot = p, *dotname = name;
*name++ = *p++;
while (isdigit (*p))
*name++ = *p++;
if (*p != ':')
{ /* it wasn't, backup */
p = dot;
name = dotname;
}
if (*p == '\0')
return;
p++;
break;
}
*name++ = *p++;
}
*name++ = '\0';
return;
}
/*
* Get a description for an interface (i.e. "Ethernet" for ethX).
*/
char *
get_ifdsc (const char *ifp)
{
int i;
struct if_alist_struct
{
char *interface;
char *description;
}
interface_alist[] =
{
/*
* A _("string") is an element of a char *[], and the linker will
* know where to find the elements. This works with `pointerize';
* perhaps that's different with `gettext'... though if it expands
* to a function call, this initializer should still work fine.
* Also see the 1.66 version of choose_cdrom(), which uses the
* similar technique. If it works there, it will work here.
*/
{
"eth", "Ethernet or Fast Ethernet"}
,
{
"pcmcia", "PC-Card (PCMCIA) Ethernet or Token Ring"}
,
{
"tr", "Token Ring"}
,
{
"arc", "Arcnet"}
,
{
"slip", "Serial-line IP"}
,
{
"plip", "Parallel-line IP"}
,
{
NULL, NULL}
};
for (i = 0; interface_alist[i].interface != NULL; i++)
if (!strncmp (ifp, interface_alist[i].interface,
strlen (interface_alist[i].interface)))
return interface_alist[i].description;
return NULL;
}

39
util.h

@ -0,0 +1,39 @@
#ifndef __UTIL_H
#define __UTIL_H
#define MAXLINE 1024
/*
* Get a description for an interface (i.e. "Ethernet" for ethX).
*/
extern char *get_ifdsc (const char *ifp);
/* Checks to see if any network interfaces are active (excepting the
* loopback interface "lo" - Returns the number of active interfaces. If
* all is non-zero, all interfaces are counted, even if not up */
int is_network_up (int all);
/* Checks to see if the named interface, "inter", is up - Returns 1 if it
* is, 0 if it is down. -1 is returned if the interface does not exist. */
int is_interface_up (char *inter);
/* Takes the buffer "p" and reads the interface name from it. "p" must be
* a full line read in from /proc/net/dev. The interface name is places
* into the "name" buffer (which must already be allocated) */
void get_name (char *name, char *p);
/* Get listing of interfaces on the system. getif_start() must be called
* first in order to initialize the setup. After which, each successive
* call get getif() will return a pointer to the next interface, ending
* with NULL, when no more interfaces are available. If you call getif and
* all is non-zero, it will return all interfaces, even ones that are not
* active. Finally when done, call getif_end().
*/
void getif_start (void);
char *getif (int all);
void getif_end (void);
#endif /* __UTIL_H */
Loading…
Cancel
Save