Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 May 2004 19:29:19 +0300
From:      Peter Pentchev <roam@ringlet.net>
To:        freebsd-net@FreeBSD.org
Subject:   [RFC] ifconfig: match by link-level address
Message-ID:  <20040520162919.GA1971@straylight.m.ringlet.net>

next in thread | raw e-mail | index | archive | help

--vGgW1X5XWziG23Ko
Content-Type: multipart/mixed; boundary="5mCyUwZo2JvN/JJP"
Content-Disposition: inline


--5mCyUwZo2JvN/JJP
Content-Type: text/plain; charset=windows-1251
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,

I found out recently that the Linux (or at least recent RedHat) startup
scripts could be configured to not bring up an Ethernet interface unless
it has a specified MAC address.  This, combined with the wonderful
interface renaming functionality recently committed to -CURRENT, led me
to the idea of interface renaming on boot-up, by hardware addresses -
something like 'I don't care how you detected this network card, or how
many others like it are there, but the card with MAC address
00:03:0d:08:dc:a7 will be known as sis0int from now on'.

The main missing piece was the ability to find an interface by MAC
address; hence the attached patch, also available at
http://www.ringlet.net/~roam/bsd-patches/src5/sbin-ifconfig-hwmatch.patch
http://people.FreeBSD.org/~roam/bsd-patches/src5/sbin-ifconfig-hwmatch.patch

It teaches ifconfig(8) to treat interface "names" beginning with 'hw-'
as link-level addresses; ifconfig tries to find an interface with this
address and behaves as if its name was specified on the command line:

[roam@straylight ~/fbsd/r/src/sbin/ifconfig]> ./ifconfig hw-00:03:0d:08:dc:=
a7
sis0: flags=3D8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=3D8<VLAN_MTU>
        inet 10.0.8.129 netmask 0xffff0000 broadcast 10.0.255.255
        inet 192.168.1.13 netmask 0xffffff00 broadcast 192.168.1.255
        ether 00:03:0d:08:dc:a7
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active
[roam@straylight ~/fbsd/r/src/sbin/ifconfig]>

This could be the first step towards teaching rc.conf about something like
network_interfaces_rename=3D"hw-00:03:0d:08:dc:a7 sis0int"

I had initially written my own function for parsing the user-supplied
address into a sequence of bytes instead of using ether_aton(); it would
have the advantage of being able to specify 'hw-' to match lo0's empty
link-level "address".  However, the odds of somebody actually wishing to
rename lo0 don't seem to be so high :)

G'luck,
Peter

--=20
Peter Pentchev	roam@ringlet.net    roam@sbnd.net    roam@FreeBSD.org
PGP key:	http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint	FDBA FD79 C26F 3C51 C95E  DF9E ED18 B68D 1619 4553
You have, of course, just begun reading the sentence that you have just fin=
ished reading.

--5mCyUwZo2JvN/JJP
Content-Type: text/plain; charset=windows-1251
Content-Disposition: attachment; filename="sbin-ifconfig-hwmatch.patch"
Content-Transfer-Encoding: quoted-printable

Index: src/sbin/ifconfig/ifconfig.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.104
diff -u -r1.104 ifconfig.c
--- src/sbin/ifconfig/ifconfig.c	30 Apr 2004 22:34:12 -0000	1.104
+++ src/sbin/ifconfig/ifconfig.c	20 May 2004 16:02:44 -0000
@@ -145,6 +145,9 @@
 void	usage(void);
 void	ifmaybeload(char *name);
=20
+static char	*findifname(const char *);
+static void	 parseaddr(const char *, struct sockaddr_dl *);
+
 #ifdef INET6
 void	in6_fillscopeid(struct sockaddr_in6 *sin6);
 int	prefix(void *, int);
@@ -509,6 +512,14 @@
 		if (argc < 1)
 			usage();
=20
+		if (!strncmp(*argv, "hw-", 3)) {
+			char *tmp;
+		=09
+			tmp =3D findifname(*argv + 3);
+			if (tmp =3D=3D NULL)
+				errx(1, "no interface with address %s", *argv);
+			*argv =3D tmp;
+		}
 		strncpy(name, *argv, sizeof(name));
 		argc--, argv++;
=20
@@ -1947,3 +1958,57 @@
 	 */
 	printname =3D 0;
 }
+
+/*
+ * Return the name of the interface with this link-level address, or NULL
+ */
+char *
+findifname(const char *addr)
+{
+	struct ifaddrs *l, *c;
+	struct sockaddr_dl *sdl, templ;
+	char *name;
+=09
+	parseaddr(addr, &templ);
+
+	if (getifaddrs(&l) =3D=3D -1)
+		err(1, "getifaddrs");
+	name =3D NULL;
+	for (c =3D l; c !=3D NULL; c =3D c->ifa_next) {
+		if (c->ifa_addr =3D=3D NULL || c->ifa_addr->sa_family !=3D AF_LINK)
+			continue;
+		sdl =3D (struct sockaddr_dl *)c->ifa_addr;
+		if (sdl->sdl_alen =3D=3D templ.sdl_alen &&
+		    memcmp(sdl->sdl_data + sdl->sdl_nlen,
+		    templ.sdl_data + templ.sdl_nlen,
+		    sdl->sdl_alen) =3D=3D 0) {
+			name =3D strdup(c->ifa_name);
+			break;
+		}
+	}
+	freeifaddrs(l);
+	return (name);
+}
+
+/*
+ * Parse the interface address into a sockaddr_dl structure
+ */
+static void
+parseaddr(const char *addr, struct sockaddr_dl *dst)
+{
+	struct sockaddr_dl sdl;
+	struct ether_addr *e;
+
+	/* Init the sockaddr_dl structure */
+	memset(&sdl, 0, sizeof(sdl));
+	sdl.sdl_len =3D sizeof(sdl);
+	sdl.sdl_family =3D AF_LINK;
+	sdl.sdl_nlen =3D 0;
+	e =3D ether_aton(addr);
+	if (e =3D=3D NULL)
+		errx(1, "Invalid link-level address format: %s", addr);
+	memcpy(sdl.sdl_data, e, sizeof(*e));
+	sdl.sdl_alen =3D 6;
+	sdl.sdl_slen =3D 0;
+	memcpy(dst, &sdl, sizeof(*dst));
+}

--5mCyUwZo2JvN/JJP--

--vGgW1X5XWziG23Ko
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQFArNzf7Ri2jRYZRVMRAqQAAJ9PRsutVwA1MbubrwFoM1Io3wNGvgCfYaBP
SMiecWpec8Iga+Hg32tPqsU=
=vUEg
-----END PGP SIGNATURE-----

--vGgW1X5XWziG23Ko--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040520162919.GA1971>