home *** CD-ROM | disk | FTP | other *** search
- /*
- arp.c
-
- ARP cache routines.
-
- Copyright (c) 1999 Dug Song <dugsong@monkey.org>
- All rights reserved, all wrongs reversed.
-
- 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. The name of author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``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.
-
- $Id: arp.c,v 1.3 2000/01/21 08:20:26 dugsong Exp $
- */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/socket.h>
- #ifdef BSD
- #include <sys/sysctl.h>
- #include <net/if_dl.h>
- #include <net/route.h>
- #ifdef __FreeBSD__ /* XXX */
- #define ether_addr_octet octet
- #endif
- #else /* !BSD */
- #include <sys/ioctl.h>
- #ifndef __linux__
- #include <sys/sockio.h>
- #endif
- #endif /* !BSD */
- #include <net/if.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/if_ether.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
-
- #ifdef BSD
-
- int
- arp_cache_lookup(u_long ip, struct ether_addr *ether)
- {
- int mib[6];
- size_t len;
- char *buf, *next, *end;
- struct rt_msghdr *rtm;
- struct sockaddr_inarp *sin;
- struct sockaddr_dl *sdl;
-
- mib[0] = CTL_NET;
- mib[1] = AF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_INET;
- mib[4] = NET_RT_FLAGS;
- mib[5] = RTF_LLINFO;
-
- if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
- return (-1);
-
- if ((buf = (char *)malloc(len)) == NULL)
- return (-1);
-
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
- free(buf);
- return (-1);
- }
- end = buf + len;
-
- for (next = buf ; next < end ; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)next;
- sin = (struct sockaddr_inarp *)(rtm + 1);
- sdl = (struct sockaddr_dl *)(sin + 1);
-
- if (sin->sin_addr.s_addr == ip && sdl->sdl_alen) {
- memcpy(ether->ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
- free(buf);
- return (0);
- }
- }
- free(buf);
-
- return (-1);
- }
-
- #else /* !BSD */
-
- #ifndef ETHER_ADDR_LEN /* XXX - Solaris */
- #define ETHER_ADDR_LEN 6
- #endif
-
- int
- arp_cache_lookup(u_long ip, struct ether_addr *ether)
- {
- int sock;
- struct arpreq ar;
- struct sockaddr_in *sin;
-
- memset((char *)&ar, 0, sizeof(ar));
- #ifdef __linux__
- strncpy(ar.arp_dev, "eth0", sizeof(ar.arp_dev)); /* XXX - *sigh* */
- #endif
- sin = (struct sockaddr_in *)&ar.arp_pa;
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = ip;
-
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- return (-1);
- }
- if (ioctl(sock, SIOCGARP, (caddr_t)&ar) == -1) {
- close(sock);
- return (-1);
- }
- close(sock);
- memcpy(ether->ether_addr_octet, ar.arp_ha.sa_data, ETHER_ADDR_LEN);
-
- return (0);
- }
-
- #endif /* !BSD */
-
- #ifdef STANDALONE
- int
- main(int argc, char *argv[])
- {
- struct ether_addr ether;
- u_long ip;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s ip\n", argv[0]);
- exit(1);
- }
- ip = inet_addr(argv[1]);
-
- if (arp_cache_lookup(ip, ðer) == -1) {
- perror("arp_table_lookup");
- exit(1);
- }
- printf("(%s) at %s\n", argv[1], ether_ntoa(ðer));
-
- exit(0);
- }
- #endif /* STANDALONE */
-
- /* 5000 */
-