[klibc] problems with ipconfig command (no static config possible)

Olaf Hering olh at suse.de
Thu Aug 19 12:09:11 PDT 2004


 On Sun, Aug 15, H. Peter Anvin wrote:

> Dirk von Suchodoletz wrote:
> >
> >I got a version from Olaf Hering of SuSE which at least was able to set 
> >the IP number statically the way examples above. Unfortunately this 
> >version does not honour the netmask settings :-( So I'm running into 
> >trouble because the automatic setting of the 132.X.Y.Z delivers a class B 
> >netmask (and not class C as required).
> >
> 
> Olaf/Dirk... could either of you send me the diff?

ipconfig has at least 2 bugs. 

'ipconfig all' will not work with any kernel. It uses the SIOCGIFCONF
ioctl, which returns only interfaces in the UP state. So its almost
useless for early boot because no interface is up at this time. I'm not
sure if there is an ioctl to retreive all available interface names. I
implemented a 'ls -A /sys/class/net/' like lookup in the patch below.

This fixes 'ipconfig all', it looks now for all ethernet devices.

Another bug is the broadcast handling, the broadcast address is not
setup correctly. I dont have a patch for it right now, but I will try to
provide a fix.

Date: Sun, 30 May 2004 23:14:18 +0200
Subject: Re: [klibc] ipconfig related question (do not get static IP setting)
From: Olaf Hering <olh at suse.de>
To: Dirk von Suchodoletz <dirk at goe.net>
Cc: klibc at zytor.com

 On Fri, May 28, Dirk von Suchodoletz wrote:

>
> Hi!! I found your ipconfig stuff in the udev rpm in SuSE 9.1. I'm about to
> setup a initramfs (pretty cool - much better than initrd) to boot linux
> diskless clients over the net. All the tools I would need, seem to be
> there with ipconfig/nfsmount ...
>
> I like to use the information I get from PXE/syslinux or Etherboot
> writing something like:
> ip=10.8.4.204:10.8.4.254:10.8.4.254:255.255.255.0:machine01 (etherboot)
> ip=10.8.4.204:10.8.4.254:10.8.4.254:255.255.255.0 (pxe/syslinux)

2.6 has a broken SIOCGIFCONF ioctl, it does only return interfaces in UP
state. So the eth0 is not seen by ipconfig, and your ip= line contains
no interface. As a result, no config happens if the interface data are
specified manually.

this simple patch uses sysfs to find the available interfaces, it adds
only ethernet links.



diff -p -purN klibc-0.116/ipconfig/README klibc-0.116.ipconfig/ipconfig/README
--- klibc-0.116/ipconfig/README	2003-05-01 21:10:35.000000000 +0200
+++ klibc-0.116.ipconfig/ipconfig/README	2004-05-30 18:44:56.000000000 +0200
@@ -32,12 +32,13 @@ An interface spec can be either short fo
 an interface (eth0 or whatever), or long form.  The long form consists
 of up to six elements, separated by colons:
 
-addr:server:gateway:netmask:interface:proto
+addr:server:gateway:netmask:hostname:interface:proto
 
 addr		the local IP address
 server		the server's IP address (doubles as DNS server)
 gateway		default gateway
 netmask		netmask
+hostname	hostname of the client
 interface	name of the interface (empty string is synonym for "all")
 proto		the autoconfig protocol to use, as outlined above
 
diff -p -purN klibc-0.116/ipconfig/main.c klibc-0.116.ipconfig/ipconfig/main.c
--- klibc-0.116/ipconfig/main.c	2003-05-06 00:15:09.000000000 +0200
+++ klibc-0.116.ipconfig/ipconfig/main.c	2004-05-25 03:03:02.000000000 +0200
@@ -9,6 +9,11 @@
 #include <stdlib.h>
 #include <time.h>
 #include <arpa/inet.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#include <linux/if_arp.h>
 
 #include "ipconfig.h"
 #include "netdev.h"
@@ -17,6 +22,7 @@
 #include "dhcp_proto.h"
 #include "packet.h"
 
+static const char sysfs_class_net[] = "/sys/class/net";
 static const char *progname;
 static char do_not_config;
 static unsigned int default_caps = CAP_DHCP | CAP_BOOTP | CAP_RARP;
@@ -427,62 +433,7 @@ static unsigned int parse_proto(const ch
 	return caps;
 }
 
-static void bringup_device(struct netdev *dev)
-{
-	if (netdev_up(dev) == 0) {
-		if (dev->caps) {
-			add_one_dev(dev);
-		} else {
-			complete_device(dev);
-		}
-	}
-}
-
-static struct netdev *add_device(const char *info);
-
-static void add_all_devices(struct netdev *template)
-{
-#define MAX_IFS 128
-	struct ifreq ifr[MAX_IFS];
-	struct ifconf ifc;
-	int fd, nif, i;
-
-	fd = packet_open();
-
-	ifc.ifc_len = sizeof(ifr);
-	ifc.ifc_req = ifr;
-
-	if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
-		perror("SIOCGIFCONF");
-		exit(1);
-	}
-	nif = ifc.ifc_len / sizeof(ifr[0]);
-
-	for (i = 0; i < nif; i++) {
-		struct netdev *dev;
-
-		if (strcmp(ifr[i].ifr_name, "lo") == 0)
-			continue;
-		if ((dev = add_device(ifr[i].ifr_name)) == NULL)
-			continue;
-
-		if (template->ip_addr != INADDR_NONE)
-			dev->ip_addr = template->ip_addr;
-		if (template->ip_server != INADDR_NONE)
-			dev->ip_server = template->ip_server;
-		if (template->ip_gateway != INADDR_NONE)
-			dev->ip_gateway = template->ip_gateway;
-		if (template->ip_nameserver[0] != INADDR_NONE)
-			dev->ip_nameserver[0] = template->ip_nameserver[0];
-		if (template->ip_nameserver[1] != INADDR_NONE)
-			dev->ip_nameserver[1] = template->ip_nameserver[1];
-		if (template->hostname[0] != '\0')
-			strcpy(dev->hostname, template->hostname);
-		dev->caps &= template->caps;
-
-		bringup_device(dev);
-	}
-}
+static void add_all_devices(struct netdev *template);
 
 static int parse_device(struct netdev *dev, const char *ip)
 {
@@ -549,6 +500,36 @@ static int parse_device(struct netdev *d
 	return 1;
 }
 
+static void bringup_device(struct netdev *dev)
+{
+	if (netdev_up(dev) == 0) {
+		if (dev->caps) {
+			add_one_dev(dev);
+		} else {
+			complete_device(dev);
+		}
+	}
+}
+
+static void bringup_one_dev(struct netdev *template, struct netdev *dev)
+{
+		if (template->ip_addr != INADDR_NONE)
+			dev->ip_addr = template->ip_addr;
+		if (template->ip_server != INADDR_NONE)
+			dev->ip_server = template->ip_server;
+		if (template->ip_gateway != INADDR_NONE)
+			dev->ip_gateway = template->ip_gateway;
+		if (template->ip_nameserver[0] != INADDR_NONE)
+			dev->ip_nameserver[0] = template->ip_nameserver[0];
+		if (template->ip_nameserver[1] != INADDR_NONE)
+			dev->ip_nameserver[1] = template->ip_nameserver[1];
+		if (template->hostname[0] != '\0')
+			strcpy(dev->hostname, template->hostname);
+		dev->caps &= template->caps;
+
+		bringup_device(dev);
+}
+
 static struct netdev *add_device(const char *info)
 {
 	struct netdev *dev;
@@ -585,6 +566,81 @@ static struct netdev *add_device(const c
 	return NULL;
 }
 
+static int add_all_sysfs_net_devices(struct netdev *template)
+{
+	DIR *d;
+	struct dirent *de;
+	struct netdev *dev;
+	char t[PATH_MAX], p[255];
+	int i, fd;
+	unsigned long type;
+
+	d = opendir(sysfs_class_net);
+	if (!d)
+		return 0;
+
+	while((de = readdir(d)) != NULL ) {
+		if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+			continue;
+		i = snprintf(t, PATH_MAX-1, "%s/%s/type", sysfs_class_net, de->d_name);
+		if (i < 0 || i >= PATH_MAX-1)
+			continue;
+		t[i] = '\0';
+		fd = open(t, O_RDONLY);
+		if (fd < 0) {
+			perror(t);
+			continue;
+		}
+		i = read(fd, &p, sizeof(p) - 1);
+		close(fd);
+		if (i == -1) {
+			perror(t);
+			continue;
+		}
+		p[i] = '\0';
+		type = strtoul(p, NULL, 10);
+		if (type != ARPHRD_ETHER)
+			continue;
+		if ((dev = add_device(de->d_name)) == NULL)
+			continue;
+		bringup_one_dev(template, dev);
+	}
+	closedir(d);
+	return 1;
+}
+
+static void add_all_devices(struct netdev *template)
+{
+#define MAX_IFS 128
+	struct ifreq ifr[MAX_IFS];
+	struct ifconf ifc;
+	int fd, nif, i;
+
+	if (add_all_sysfs_net_devices(template))
+		return;
+
+	fd = packet_open();
+
+	ifc.ifc_len = sizeof(ifr);
+	ifc.ifc_req = ifr;
+
+	if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
+		perror("SIOCGIFCONF");
+		exit(1);
+	}
+	nif = ifc.ifc_len / sizeof(ifr[0]);
+
+	for (i = 0; i < nif; i++) {
+		struct netdev *dev;
+
+		if (strcmp(ifr[i].ifr_name, "lo") == 0)
+			continue;
+		if ((dev = add_device(ifr[i].ifr_name)) == NULL)
+			continue;
+		bringup_one_dev(template, dev);
+	}
+}
+
 static int check_autoconfig(void)
 {
 	int ndev = 0, nauto = 0;
-- 
USB is for mice, FireWire is for men!

sUse lINUX ag, nÜRNBERG



More information about the klibc mailing list