/* * Copyright (c) 1999, 2000 Seth Kingsley. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * This product includes software developed by Seth Kingsley and * contributors. * 4. Neither the author's name, nor any of the contributors names may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ethcodes.h" static const char rcsid[] = "$Id$"; static void ping(struct in_addr *inp) { int ec = 1; char *fs = "ping -qc 1 %s > /dev/null", *cs, *as = inet_ntoa(*inp); cs = malloc(sizeof(fs) + strlen(as)); sprintf(cs, fs, as); ec = system(cs); if (ec) errx(1, "Error pinging host: command returned error code %d", ec); } /* Various parts of this stolen were from BSD arp.c */ #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) static struct ether_addr *in2eth(struct in_addr *in, int pf) { static int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO }; size_t s; char *buf, *p; struct rt_msghdr *rtmp; struct sockaddr_inarp *sin; struct sockaddr_dl *sdl; struct ether_addr *ea; if (!in) return NULL; if (sysctl(mib, 6, NULL, &s, NULL, 0) == -1) err(1, "route-sysctl-estimate"); if (!(buf = malloc(s))) err(1, "Cannot allocate memory"); if (sysctl(mib, 6, buf, &s, NULL, 0) == -1) err(1, "Cannot get routing table"); for (p = buf; (p - buf) < s; p+= rtmp->rtm_msglen) { rtmp = (struct rt_msghdr *)p; sin = (struct sockaddr_inarp *)(rtmp + 1); (char *)sdl = (char *)sin + ROUNDUP(sin->sin_len); if (in->s_addr == sin->sin_addr.s_addr && sdl->sdl_alen) { if (!(ea = malloc(sizeof(struct ether_addr)))) err(1, "Cannot allocate memory"); bcopy(sdl->sdl_data + sdl->sdl_nlen, ea, sizeof(struct ether_addr)); return ea; } } free(buf); if (!pf) { fputs("Pinging host\n", stderr); ping(in); in2eth(in, 1); } else warnx("Ethernet address not found in routing table."); return NULL; } #undef ROUNDUP static struct in_addr *ip2in(char *ip) { struct in_addr *inp = malloc(sizeof(struct in_addr)); if (!inp) err(1, "Error allocating memory"); if (!inet_aton(ip, inp)) return NULL; return inp; } static struct in_addr *host2in(char *hn) { struct hostent *h = gethostbyname(hn); struct in_addr *iap; if (!h) { warnx("Cannot resolve hostname %s: %s", hn, hstrerror(h_errno)); return NULL; } if (!(iap = malloc(sizeof(struct in_addr)))) err(1, "Cannot allocate memory"); bcopy(h->h_addr_list[0], iap, h->h_length); return iap; } int main(int ac, char *av[]) { char *prog; register int i; struct ether_addr *eap; u_int32_t rea; prog = strrchr(av[0], '/'); prog = (prog) ? prog + 1 : av[0]; if (ac != 2) { fprintf(stderr, "Usage: %s ||\n", prog); return EX_USAGE; } if (!(eap = ether_aton(av[1])) && !(eap = in2eth(ip2in(av[1]), 0)) && !(eap = in2eth(host2in(av[1]), 0))) return 1; rea = eap->octet[0] << 16 | eap->octet[1] << 8 | eap->octet[2]; for (i = 0; eth_vend[i].ev_addr; ++i) { if (rea == eth_vend[i].ev_addr) { printf("%s: (%s) Vendor: %s", av[1], ether_ntoa(eap), eth_vend[i].ev_name); if (eth_vend[i].ev_note) printf("\t<%s>", eth_vend[i].ev_note); putchar('\n'); return EX_OK; } } printf("No matching ethernet vendor found for %s\n", ether_ntoa(eap)); return 1; }