Theo de Raadt <[email protected]> wrote:
> Vitaliy Makkoveev <[email protected]> wrote:
>
> > > On 24 Nov 2022, at 19:20, Theo de Raadt <[email protected]> wrote:
> > >
> > >> I like to exclude pseudo devices. The pseudo device list is immutable,
> > >> so we need to get only once during /etc/netstart.
> > >
> > > Why do we need to excluse them?
> > >
> > > The users will learn when to use this, and when not to.
> > >
> >
> > So, I can't use hostname.lladdr and usb ethernet cards with vlan?
>
> Probably not.
>
> Please answer this question: Did you try the ifconfig change, and the
> script, in such a scenario?
>
> Or are you just musing without trying it?
How about this.
vlan's and other potential interfaces with this problem have the IFXF_CLONED
flag set, and I don't see any IFXF_CLONED we would want a hostname.MAC file
to work against. Unfortunately IFXF_CLONED is not visible in an ioctl.
But the IFXF_CLONED devices are in ifconfig -C output, so I have abstracted
that code into 'get the list' and 'print the list' functions, and reused
the 'get the list' function in findmac() so that I can exclude interfaces
with that root-name.
It is some ugly string mangling code, hope I got it right. My coffee cup
is still pretty full...
Index: ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.385
diff -u -p -u -r1.385 ifconfig.8
--- ifconfig.8 26 Oct 2022 17:06:31 -0000 1.385
+++ ifconfig.8 22 Nov 2022 15:04:09 -0000
@@ -40,6 +40,7 @@
.Sh SYNOPSIS
.Nm ifconfig
.Op Fl AaC
+.Op Fl M Ar lladdr
.Op Ar interface
.Op Ar address_family
.Oo
@@ -88,6 +89,11 @@ This is the default, if no parameters ar
Print the names of all network pseudo-devices that
can be created dynamically at runtime using
.Nm Cm create .
+.It Fl M Ar lladdr
+Scan the interface list for the MAC address
+.Ar lladdr
+and print the name of that interface.
+If the MAC address is found on multiple interfaces, print nothing.
.It Ar interface
The
.Ar interface
Index: ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.457
diff -u -p -u -r1.457 ifconfig.c
--- ifconfig.c 26 Oct 2022 17:06:31 -0000 1.457
+++ ifconfig.c 24 Nov 2022 17:39:40 -0000
@@ -368,6 +368,9 @@ void wg_status(int);
void setignore(const char *, int);
#endif
+struct if_clonereq *get_cloners(void);
+int findmac(const char *);
+
/*
* Media stuff. Whenever a media command is first performed, the
* currently select media is grabbed for this interface. If `media'
@@ -795,6 +798,11 @@ main(int argc, char *argv[])
Cflag = 1;
nomore = 1;
break;
+ case 'M':
+ if (argv[1] == NULL)
+ usage();
+ exit (findmac(argv[1]));
+ break;
default:
usage();
break;
@@ -1255,12 +1263,10 @@ clone_destroy(const char *addr, int para
err(1, "SIOCIFDESTROY");
}
-void
-list_cloners(void)
+struct if_clonereq *
+get_cloners(void)
{
- struct if_clonereq ifcr;
- char *cp, *buf;
- int idx;
+ static struct if_clonereq ifcr;
memset(&ifcr, 0, sizeof(ifcr));
@@ -1269,12 +1275,9 @@ list_cloners(void)
if (ioctl(sock, SIOCIFGCLONERS, &ifcr) == -1)
err(1, "SIOCIFGCLONERS for count");
- buf = calloc(ifcr.ifcr_total, IFNAMSIZ);
- if (buf == NULL)
+ if ((ifcr.ifcr_buffer = calloc(ifcr.ifcr_total, IFNAMSIZ)) == NULL)
err(1, "unable to allocate cloner name buffer");
-
ifcr.ifcr_count = ifcr.ifcr_total;
- ifcr.ifcr_buffer = buf;
if (ioctl(sock, SIOCIFGCLONERS, &ifcr) == -1)
err(1, "SIOCIFGCLONERS for names");
@@ -1285,17 +1288,30 @@ list_cloners(void)
if (ifcr.ifcr_count > ifcr.ifcr_total)
ifcr.ifcr_count = ifcr.ifcr_total;
- qsort(buf, ifcr.ifcr_count, IFNAMSIZ,
+ return &ifcr;
+}
+
+void
+list_cloners(void)
+{
+ struct if_clonereq *ifcr;
+ char *cp, *buf;
+ int idx;
+
+ ifcr = get_cloners();
+ buf = ifcr->ifcr_buffer;
+
+ qsort(buf, ifcr->ifcr_count, IFNAMSIZ,
(int(*)(const void *, const void *))strcmp);
- for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
+ for (cp = buf, idx = 0; idx < ifcr->ifcr_count; idx++, cp += IFNAMSIZ) {
if (idx > 0)
putchar(' ');
printf("%s", cp);
}
putchar('\n');
- free(buf);
+ free(ifcr->ifcr_buffer);
}
#define RIDADDR 0
@@ -6614,7 +6630,7 @@ __dead void
usage(void)
{
fprintf(stderr,
- "usage: ifconfig [-AaC] [interface] [address_family] "
+ "usage: ifconfig [-AaC] [-M lladdr] [interface] [address_family] "
"[address [dest_address]]\n"
"\t\t[parameters]\n");
exit(1);
@@ -6782,3 +6798,56 @@ setignore(const char *id, int param)
/* just digest the command */
}
#endif
+
+int
+findmac(const char *mac)
+{
+ struct ifaddrs *ifap, *ifa;
+ const char *ifnam = NULL;
+ struct if_clonereq *ifcr;
+ char *cp;
+ size_t len;
+ int idx;
+
+ ifcr = get_cloners();
+
+ if (getifaddrs(&ifap) != 0)
+ err(1, "getifaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+
+ if (sdl != NULL && sdl->sdl_alen &&
+ (sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_CARP)) {
+ if (strcmp(ether_ntoa((struct ether_addr *)LLADDR(sdl)),
+ mac) == 0) {
+ int skip;
+
+ if (ifnam) { /* same MAC on multiple ifp */
+ freeifaddrs(ifap);
+ return 1;
+ }
+
+ /* MACs on cloned devices are ignored */
+ for (cp = ifa->ifa_name, len = 0; *cp; cp++,
len++)
+ if (isdigit(*cp))
+ break;
+ for (cp = ifcr->ifcr_buffer, idx = 0, skip = 0;
+ idx < ifcr->ifcr_count;
+ idx++, cp += IFNAMSIZ) {
+ if (strncmp(ifa->ifa_name, cp, len) ==
0) {
+ skip = 1;
+ break;
+ }
+ }
+ if (!skip)
+ ifnam = ifa->ifa_name;
+ }
+ }
+ }
+ if (ifnam)
+ printf("%s\n", ifnam);
+ free(ifcr->ifcr_buffer);
+ freeifaddrs(ifap);
+ return 0;
+}