Andrew spotted a potential issue with the short-circuit ordering, so
here is a newer diff.
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 24 Nov 2022 18:18:51 -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 non-cloned 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 19:19:55 -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,55 @@ 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;
+
+ 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 idx, skip = 0;
+ char *cp;
+ size_t len;
+
+ /* MACs on cloned devices are ignored */
+ for (len = 0; ifa->ifa_name[len]; len++)
+ if (isdigit((unsigned
char)ifa->ifa_name[len]))
+ break;
+ for (cp = ifcr->ifcr_buffer, idx = 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) { /* same MAC on multiple ifp */
+ freeifaddrs(ifap);
+ return 1;
+ }
+ }
+ }
+ }
+ if (ifnam)
+ printf("%s\n", ifnam);
+ free(ifcr->ifcr_buffer);
+ freeifaddrs(ifap);
+ return 0;
+}