-.\" $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 $
.\"
.\"
.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
.\"
-.Dd $Mdocdate: October 26 2022 $
+.Dd $Mdocdate: November 25 2022 $
.Dt IFCONFIG 8
.Os
.Sh NAME
.Sh SYNOPSIS
.Nm ifconfig
.Op Fl AaC
+.Op Fl M Ar lladdr
.Op Ar interface
.Op Ar address_family
.Oo
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
-/* $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 $ */
/*
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'
Cflag = 1;
nomore = 1;
break;
+ case 'M':
+ if (argv[1] == NULL)
+ usage();
+ exit(findmac(argv[1]));
+ break;
default:
usage();
break;
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));
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");
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
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);
/* 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;
+}