On Tue, Nov 22, 2022 at 08:09:11AM -0700, Theo de Raadt wrote:
> Florian Obser <[email protected]> wrote:
>
> > On 2022-11-22 18:06 +10, David Gwynne <[email protected]> wrote:
> > >
> > > There are a few things to keep in mind if we're going to use lladdrs like
> > > this.
> > >
> > > vlan interfaces start with their lladdr as 00:00:00:00:00:00 and then
> > > assume the lladdr of the parent interface when that is configured.
> > >
> > > Clonable devices (eg, egre, vport, aggr, etc) tend to generate random
> > > lladdrs when they're created. If you want a consistent lladdr for
> > > these you configure that in /etc/hostname.vportX or whatever you're
> > > using.
> >
> > ifconfig(8) already knows about these (see -C option). Which made me
> > think, it might be easier to just ask ifconfig(8).
> >
> > $ ifconfig -Q 00:80:41:7b:f3:c3
> > vio0
> >
> > Would that be helpful?
>
> I'm unsure about the rest of your proposal, where MAC works in place if
> the IF argument. Let's say we do this in ifcconfig. Do we do it in route?
> Or ten other commands? I think that is the wrong way to go.
>
> But this first idea is valid. We've now seen 3 monster functions trying to
> do this task of convering MAC to IF in shell. Here's code to do it in
> ifconfig.
>
> I've done it as -M
Better than [Q]uery.
>
> It fails if the same MAC is on multiple interfaces. Go back to using
> hostname.if# files, you heathen.
This reads like a viable approach, much cleaner than the netstart
globbing attempts.
Using ifconfig -M, I can give the shell bits a try later this week.
Nits inline.
>
> 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 22 Nov 2022 15:02:20 -0000
> @@ -368,6 +368,8 @@ void wg_status(int);
> void setignore(const char *, int);
> #endif
>
> +void findmac(char *);
> +
> /*
> * Media stuff. Whenever a media command is first performed, the
> * currently select media is grabbed for this interface. If `media'
> @@ -759,6 +761,7 @@ main(int argc, char *argv[])
> int create = 0;
> int Cflag = 0;
> int gflag = 0;
> + int Mflag = 0;
> int found_rulefile = 0;
> int i;
>
> @@ -795,6 +798,12 @@ main(int argc, char *argv[])
> Cflag = 1;
> nomore = 1;
> break;
> + case 'M':
> + if (argv[1] == NULL)
> + usage();
> + findmac(argv[1]);
> + exit(1);
Above main() already uses return, no need for exit here, I think:
return findmac(argv[1]);
> + break;
> default:
> usage();
> break;
> @@ -6614,7 +6623,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 +6791,30 @@ setignore(const char *id, int param)
> /* just digest the command */
> }
> #endif
> +
> +void
> +findmac(char *mac)
> +{
> + struct ifaddrs *ifap, *ifa;
> + char *ifnam = NULL;
Both *mac and *ifnam can be const.
> +
> + 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) {
> + if (ifnam) /* same MAC on multiple ifp */
> + exit(1);
> + ifnam = ifa->ifa_name;
> + }
> + }
> + }
> + if (ifnam)
> + printf("%s\n", ifnam);
> + exit(0);
And these exit()s can be return to fold the call as above.
> +}
>