[RFC] ifconfig: match by link-level address
Peter Pentchev
roam at ringlet.net
Thu May 20 16:29:22 GMT 2004
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 at straylight ~/fbsd/r/src/sbin/ifconfig]> ./ifconfig hw-00:03:0d:08:dc:a7
sis0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=8<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 at straylight ~/fbsd/r/src/sbin/ifconfig]>
This could be the first step towards teaching rc.conf about something like
network_interfaces_rename="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
--
Peter Pentchev roam at ringlet.net roam at sbnd.net roam at 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 finished reading.
-------------- next part --------------
Index: src/sbin/ifconfig/ifconfig.c
===================================================================
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);
+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();
+ if (!strncmp(*argv, "hw-", 3)) {
+ char *tmp;
+
+ tmp = findifname(*argv + 3);
+ if (tmp == NULL)
+ errx(1, "no interface with address %s", *argv);
+ *argv = tmp;
+ }
strncpy(name, *argv, sizeof(name));
argc--, argv++;
@@ -1947,3 +1958,57 @@
*/
printname = 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;
+
+ parseaddr(addr, &templ);
+
+ if (getifaddrs(&l) == -1)
+ err(1, "getifaddrs");
+ name = NULL;
+ for (c = l; c != NULL; c = c->ifa_next) {
+ if (c->ifa_addr == NULL || c->ifa_addr->sa_family != AF_LINK)
+ continue;
+ sdl = (struct sockaddr_dl *)c->ifa_addr;
+ if (sdl->sdl_alen == templ.sdl_alen &&
+ memcmp(sdl->sdl_data + sdl->sdl_nlen,
+ templ.sdl_data + templ.sdl_nlen,
+ sdl->sdl_alen) == 0) {
+ name = 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 = sizeof(sdl);
+ sdl.sdl_family = AF_LINK;
+ sdl.sdl_nlen = 0;
+ e = ether_aton(addr);
+ if (e == NULL)
+ errx(1, "Invalid link-level address format: %s", addr);
+ memcpy(sdl.sdl_data, e, sizeof(*e));
+ sdl.sdl_alen = 6;
+ sdl.sdl_slen = 0;
+ memcpy(dst, &sdl, sizeof(*dst));
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20040520/1ab31836/attachment.bin
More information about the freebsd-net
mailing list