/* * Copyright (c) 1998 JSC Rinet, Novosibirsk, Russia * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * Redistribution in binary form may occur without any restrictions. * * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND. */ /* getarptab.c -- translate MAC addresses to IP addresses using ARP table */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_RTF_LLINFO /* BSD systems */ #include #include #include #include #include #include #include #include #include #ifdef ETHER_ADDR_LEN #define MAC_ADDR_LEN ETHER_ADDR_LEN #else #define MAC_ADDR_LEN 6 #endif u_char * getarptab(ep) u_char *ep; { int mib[6]; size_t needed; char *lim, *buf, *next; struct rt_msghdr *rtm; static struct sockaddr_inarp *sin; struct sockaddr_dl *sdl; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_FLAGS; mib[5] = RTF_LLINFO; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) error(1, "getarptab: sysctl"); if ((buf = (char *)malloc(needed)) == NULL) error(1, "getarptab: malloc"); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) error(1, "getarptab: sysctl"); lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; sin = (struct sockaddr_inarp *)(rtm + 1); sdl = (struct sockaddr_dl *)(sin + 1); if (sdl->sdl_alen && !memcmp(ep, (u_char *)LLADDR(sdl), MAC_ADDR_LEN)) { free(buf); return ((u_char *)&sin->sin_addr); } } free(buf); return (u_char *)0; } #elif HAVE_PROC_NET_ARP /* Linux systems */ #include #include #include #include #include u_char * getarptab(ep) u_char *ep; { FILE *fp; char *req, *ip, *mac, buf[100]; static struct in_addr addr; if ((fp = fopen("/proc/net/arp", "r")) != NULL) { req = (char *)entoa(ep); while (fgets(buf, sizeof(buf), fp) != NULL) { buf[sizeof(buf)-1] = '\0'; if ((ip = strtok(buf, " \t")) == NULL) continue; while ((mac = strtok(NULL, " \t")) != NULL) { if (!strcasecmp(req, mac)) { if (inet_aton(ip, &addr)) { (void) fclose(fp); return ((u_char *)&addr); } break; } } } (void) fclose(fp); } return (u_char *)0; } #else /* XXX. Get ARP table not implemented yet for SYSV systems */ u_char * getarptab(ep) u_char *ep; { return (u_char *)0; } #endif