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;
+}

Reply via email to