Theo de Raadt <dera...@openbsd.org> wrote: > Vitaliy Makkoveev <m...@openbsd.org> wrote: > > > > On 24 Nov 2022, at 19:20, Theo de Raadt <dera...@openbsd.org> 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; +}