Index: src/sbin/ifconfig/ifconfig.c =================================================================== RCS file: /home/ncvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.104 diff -u -r1.104 ifconfig.c --- src/sbin/ifconfig/ifconfig.c 30 Apr 2004 22:34:12 -0000 1.104 +++ src/sbin/ifconfig/ifconfig.c 20 May 2004 16:02:44 -0000 @@ -145,6 +145,9 @@ void usage(void); void ifmaybeload(char *name); +static char *findifname(const char *); +static void parseaddr(const char *, struct sockaddr_dl *); + #ifdef INET6 void in6_fillscopeid(struct sockaddr_in6 *sin6); int prefix(void *, int); @@ -509,6 +512,14 @@ if (argc < 1) usage(); + if (!strncmp(*argv, "hw-", 3)) { + char *tmp; + + tmp = findifname(*argv + 3); + if (tmp == NULL) + errx(1, "no interface with address %s", *argv); + *argv = tmp; + } strncpy(name, *argv, sizeof(name)); argc--, argv++; @@ -1947,3 +1958,57 @@ */ printname = 0; } + +/* + * Return the name of the interface with this link-level address, or NULL + */ +char * +findifname(const char *addr) +{ + struct ifaddrs *l, *c; + struct sockaddr_dl *sdl, templ; + char *name; + + parseaddr(addr, &templ); + + if (getifaddrs(&l) == -1) + err(1, "getifaddrs"); + name = NULL; + for (c = l; c != NULL; c = c->ifa_next) { + if (c->ifa_addr == NULL || c->ifa_addr->sa_family != AF_LINK) + continue; + sdl = (struct sockaddr_dl *)c->ifa_addr; + if (sdl->sdl_alen == templ.sdl_alen && + memcmp(sdl->sdl_data + sdl->sdl_nlen, + templ.sdl_data + templ.sdl_nlen, + sdl->sdl_alen) == 0) { + name = strdup(c->ifa_name); + break; + } + } + freeifaddrs(l); + return (name); +} + +/* + * Parse the interface address into a sockaddr_dl structure + */ +static void +parseaddr(const char *addr, struct sockaddr_dl *dst) +{ + struct sockaddr_dl sdl; + struct ether_addr *e; + + /* Init the sockaddr_dl structure */ + memset(&sdl, 0, sizeof(sdl)); + sdl.sdl_len = sizeof(sdl); + sdl.sdl_family = AF_LINK; + sdl.sdl_nlen = 0; + e = ether_aton(addr); + if (e == NULL) + errx(1, "Invalid link-level address format: %s", addr); + memcpy(sdl.sdl_data, e, sizeof(*e)); + sdl.sdl_alen = 6; + sdl.sdl_slen = 0; + memcpy(dst, &sdl, sizeof(*dst)); +}