From 846b8ba2848063dad7bfab6b5a55d301642a7c68 Mon Sep 17 00:00:00 2001 From: deraadt Date: Fri, 25 Nov 2022 23:09:20 +0000 Subject: [PATCH] ifconfig -M finds the address on an interface and prints it. cloned (virtual) interfaces are skipped, and if the MAC is on more than 1 interface, no answer either. The mac must be in same format as the ifconfig lladdr output (complete lowercase with :) idea from florian, ok afresh1 --- sbin/ifconfig/ifconfig.8 | 10 +++- sbin/ifconfig/ifconfig.c | 98 ++++++++++++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 16 deletions(-) diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 8ade4a90ae6..678c87c8588 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ifconfig.8,v 1.385 2022/10/26 17:06:31 kn Exp $ +.\" $OpenBSD: ifconfig.8,v 1.386 2022/11/25 23:09:20 deraadt Exp $ .\" $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $ .\" $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $ .\" @@ -31,7 +31,7 @@ .\" .\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94 .\" -.Dd $Mdocdate: October 26 2022 $ +.Dd $Mdocdate: November 25 2022 $ .Dt IFCONFIG 8 .Os .Sh NAME @@ -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 are given to 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 diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 2d0a09a254d..2ba0bc39f16 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifconfig.c,v 1.457 2022/10/26 17:06:31 kn Exp $ */ +/* $OpenBSD: ifconfig.c,v 1.458 2022/11/25 23:09:20 deraadt Exp $ */ /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ /* @@ -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 param) 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,57 @@ 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; + int ret = 0; + + 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) { + char *cp, *nam = ifa->ifa_name; + int idx, skip = 0; + size_t len; + + /* MACs on cloned devices are ignored */ + for (len = 0; nam[len]; len++) + if (isdigit((unsigned char)nam[len])) + break; + for (cp = ifcr->ifcr_buffer, idx = 0; + idx < ifcr->ifcr_count; + idx++, cp += IFNAMSIZ) { + if (strncmp(nam, cp, len) == 0) { + skip = 1; + break; + } + } + if (skip) + continue; + + if (ifnam) { /* same MAC on multiple ifp */ + ret = 1; + goto done; + } + ifnam = nam; + } + } + } + if (ifnam) + printf("%s\n", ifnam); +done: + free(ifcr->ifcr_buffer); + freeifaddrs(ifap); + return ret; +} -- 2.20.1