+++ /dev/null
-/*
-arp.c
-
-Created: Jan 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
-
-Manipulate ARP table
-*/
-
-#define _POSIX_C_SOURCE 2
-#define _NETBSD_SOURCE 1
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/ioctl.h>
-
-#include <net/netlib.h>
-#include <net/gen/ether.h>
-#include <net/gen/if_ether.h>
-#include <net/gen/in.h>
-#include <net/gen/inet.h>
-#include <net/gen/ip_io.h>
-#include <netdb.h>
-#include <net/gen/socket.h>
-
-#include <net/gen/arp_io.h>
-
-#include <arpa/inet.h>
-
-char *progname;
-static int ipfd= -1;
-static int do_setuid= 0;
-
-static void do_open(char *devname);
-static void show_one(char *hostname, int do_num);
-static void show_all(int do_num);
-static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num);
-static void delete_all(void);
-static void delete(char *hostname);
-static void do_set(char *hostname, char *ethername, int temp, int pub,
- int optdelete);
-static ipaddr_t nametoipaddr(char *hostname);
-static void fatal(const char *fmt, ...);
-static void usage(void);
-
-int main(int argc, char *argv[])
-{
- int c;
- char *hostname, *ethername;
- int do_temp, do_pub;
- int a_flag, d_flag, n_flag, s_flag, S_flag;
- char *I_arg;
-
- (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
-
- a_flag= d_flag= n_flag= s_flag= S_flag= 0;
- I_arg= NULL;
- while(c= getopt(argc, argv, "adnsS?I:"), c != -1)
- {
- switch(c)
- {
- case '?': usage();
- case 'a': a_flag= 1; break;
- case 'd': d_flag= 1; break;
- case 'n': n_flag= 1; break;
- case 's': s_flag= 1; break;
- case 'S': S_flag= 1; break;
- case 'I': I_arg= optarg; break;
- default: fatal("getopt failed: '%c'", c);
- }
- }
-
- hostname= NULL; /* lint */
- ethername= NULL; /* lint */
- do_temp= do_pub= 0; /* lint */
-
- if (n_flag + d_flag + s_flag + S_flag > 1)
- usage();
- if (s_flag || S_flag)
- {
- if (optind >= argc) usage();
- hostname= argv[optind++];
-
- if (optind >= argc) usage();
- ethername= argv[optind++];
-
- do_temp= do_pub= 0;
- while (optind < argc)
- {
- if (strcasecmp(argv[optind], "temp") == 0)
- {
- do_temp= 1;
- optind++;
- continue;
- }
- if (strcasecmp(argv[optind], "pub") == 0)
- {
- do_pub= 1;
- optind++;
- continue;
- }
- usage();
- }
- }
- else if (d_flag)
- {
- if (!a_flag)
- {
- if (optind >= argc)
- usage();
- hostname= argv[optind++];
- if (optind != argc)
- usage();
- }
- }
- else if (a_flag)
- {
- if (optind != argc)
- usage();
- do_setuid= 1;
- }
- else
- {
- if (optind >= argc)
- usage();
- hostname= argv[optind++];
- if (optind != argc)
- usage();
- do_setuid= 1;
- }
-
- do_open(I_arg);
- if (d_flag)
- {
- if (a_flag)
- delete_all();
- else
- delete(hostname);
- }
- else if (s_flag || S_flag)
- do_set(hostname, ethername, do_temp, do_pub, S_flag);
- else if (a_flag)
- show_all(n_flag);
- else
- show_one(hostname, n_flag);
- exit(0);
-}
-
-static void do_open(char *devname)
-{
- size_t l;
- char *check;
-
- if (do_setuid && devname)
- {
- /* Only strings that consist of IP_DEVICE optionally
- * followed by a number are allowed.
- */
- l= strlen(IP_DEVICE);
- if (strncmp(devname, IP_DEVICE, l) != 0)
- do_setuid= 0;
- else if (strlen(devname) == l)
- ; /* OK */
- else
- {
- strtoul(devname+l, &check, 10);
- if (check[0] != '\0')
- do_setuid= 0;
- }
- }
- if (!devname)
- devname= IP_DEVICE;
- if (!do_setuid)
- {
- setuid(getuid());
- setgid(getgid());
- }
- ipfd= open(devname, O_RDWR);
- if (ipfd == -1)
- fatal("unable to open '%s': %s", devname, strerror(errno));
-}
-
-static void show_one(char *hostname, int do_num)
-{
- int r;
- ipaddr_t ipaddr;
- nwio_arp_t arp;
-
- ipaddr= nametoipaddr(hostname);
-
- arp.nwa_ipaddr= ipaddr;
- r= ioctl(ipfd, NWIOARPGIP, &arp);
- if (r == -1 && errno == ENOENT)
- {
- print_one(ipaddr, NULL, do_num);
- exit(1);
- }
- if (r == -1)
- fatal("NWIOARPGIP failed: %s", strerror(errno));
- print_one(ipaddr, &arp, do_num);
-}
-
-static void show_all(int do_num)
-{
- int ind, max, i, r;
- nwio_arp_t *arptab;
- nwio_arp_t arp;
-
- /* First get all entries */
- max= 10;
- ind= 0;
- arptab= malloc(max * sizeof(*arptab));
- if (arptab == NULL)
- {
- fatal("out of memory, can't get %d bytes",
- max*sizeof(*arptab));
- }
- arp.nwa_entno= 0;
- for (;;)
- {
- if (ind == max)
- {
- max *= 2;
- arptab= realloc(arptab, max * sizeof(*arptab));
- if (!arptab)
- {
- fatal("out of memory, can't get %d bytes",
- max*sizeof(*arptab));
- }
- }
- r= ioctl(ipfd, NWIOARPGNEXT, &arp);
- if (r == -1 && errno == ENOENT)
- break;
- if (r == -1)
- fatal("NWIOARPGNEXT failed: %s", strerror(errno));
- arptab[ind]= arp;
- ind++;
- }
-
- for (i= 0; i<ind; i++)
- print_one(0, &arptab[i], do_num);
-}
-
-static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num)
-{
- u32_t flags;
- struct hostent *he;
-
- if (arpp)
- ipaddr= arpp->nwa_ipaddr;
- if (!do_num)
- he= gethostbyaddr((char *)&ipaddr, sizeof(ipaddr), AF_INET);
- else
- he= NULL;
- if (he)
- printf("%s (%s)", he->h_name,
- inet_ntoa(*(struct in_addr *)&ipaddr));
- else
- printf("%s", inet_ntoa(*(struct in_addr *)&ipaddr));
- if (!arpp)
- {
- printf(" -- no entry\n");
- return;
- }
- flags= arpp->nwa_flags;
- if (flags & NWAF_INCOMPLETE)
- printf(" is incomplete");
- else if (flags & NWAF_DEAD)
- printf(" is dead");
- else
- {
- printf(" is at %s", ether_ntoa(&arpp->nwa_ethaddr));
- if (flags & NWAF_PERM)
- printf(" permanent");
- if (flags & NWAF_PUB)
- printf(" published");
- }
- printf("\n");
-}
-
-static void delete_all(void)
-{
- int ind, max, i, r;
- nwio_arp_t *arptab;
- nwio_arp_t arp;
-
- /* First get all entries */
- max= 10;
- ind= 0;
- arptab= malloc(max * sizeof(*arptab));
- if (arptab == NULL)
- {
- fatal("out of memory, can't get %d bytes",
- max*sizeof(*arptab));
- }
- arp.nwa_entno= 0;
- for (;;)
- {
- if (ind == max)
- {
- max *= 2;
- arptab= realloc(arptab, max * sizeof(*arptab));
- if (arptab == NULL)
- {
- fatal("out of memory, can't get %d bytes",
- max*sizeof(*arptab));
- }
- }
- r= ioctl(ipfd, NWIOARPGNEXT, &arp);
- if (r == -1 && errno == ENOENT)
- break;
- if (r == -1)
- fatal("NWIOARPGNEXT failed: %s", strerror(errno));
- arptab[ind]= arp;
- ind++;
- }
-
- for (i= 0; i<ind; i++)
- {
- r= ioctl(ipfd, NWIOARPDIP, &arptab[i]);
- if (r == 0)
- continue;
- if (errno == EINVAL || errno == ENOENT)
- {
- /* Entry is incomplete of entry is already deleted */
- continue;
- }
- fatal("unable to delete host %s: %s",
- inet_ntoa(*(struct in_addr *)&arptab[i].nwa_ipaddr),
- strerror(errno));
- }
-}
-
-static void delete(char *hostname)
-{
- int r;
- ipaddr_t ipaddr;
- nwio_arp_t arp;
-
- ipaddr= nametoipaddr(hostname);
- arp.nwa_ipaddr= ipaddr;
- r= ioctl(ipfd, NWIOARPDIP, &arp);
- if (r == 0)
- return;
- if (errno == ENOENT)
- {
- print_one(ipaddr, NULL, 0);
- exit(1);
- }
- fatal("unable to delete host %s: %s",
- inet_ntoa(*(struct in_addr *)&ipaddr),
- errno == EINVAL ? "entry is incomplete" : strerror(errno));
-}
-
-static void do_set(char *hostname, char *ethername, int temp, int pub,
- int optdelete)
-{
- int r;
- ipaddr_t ipaddr;
- ether_addr_t *eap;
- ether_addr_t ethaddr;
- nwio_arp_t arp;
- nwio_ipconf_t ipconf;
-
- ipaddr= nametoipaddr(hostname);
- if (pub && strcasecmp(ethername, "auto") == 0)
- {
- r= ioctl(ipfd, NWIOGIPCONF, &ipconf);
- if (r == -1)
- fatal("NWIOGIPCONF failed: %s", strerror(errno));
- arp.nwa_ipaddr= ipconf.nwic_ipaddr;
- r= ioctl(ipfd, NWIOARPGIP, &arp);
- if (r == -1)
- fatal("NWIOARPGIP failed: %s", strerror(errno));
- ethaddr= arp.nwa_ethaddr;
- }
- else if (eap= ether_aton(ethername), eap != NULL)
- ethaddr= *eap;
- else if (ether_hostton(ethername, ðaddr) != 0)
- {
- fatal("unable to parse ethernet address '%s'",
- ethername);
- }
-
- if (optdelete)
- {
- arp.nwa_ipaddr= ipaddr;
- r= ioctl(ipfd, NWIOARPDIP, &arp);
- if (r == -1 && errno != ENOENT)
- {
- fatal("unable to delete entry for host %s: %s",
- inet_ntoa(*(struct in_addr *)&ipaddr),
- errno == EINVAL ? "incomplete entry" :
- strerror(errno));
- }
- }
-
- arp.nwa_ipaddr= ipaddr;
- arp.nwa_ethaddr= ethaddr;
- arp.nwa_flags= 0;
- if (pub)
- arp.nwa_flags |= NWAF_PUB;
- if (!temp)
- arp.nwa_flags |= NWAF_PERM;
- r= ioctl(ipfd, NWIOARPSIP, &arp);
- if (r == -1)
- {
- fatal("unable to set arp entry: %s",
- errno == EEXIST ? "entry exists" : strerror(errno));
- }
-}
-
-static ipaddr_t nametoipaddr(char *hostname)
-{
- ipaddr_t ipaddr;
- struct hostent *he;
-
- if (inet_aton(hostname, (struct in_addr *)&ipaddr) == 0)
- {
- he= gethostbyname(hostname);
- if (!he)
- fatal("unknown hostname '%s'", hostname);
- if (he->h_addrtype != AF_INET ||
- he->h_length != sizeof(ipaddr))
- {
- fatal("strange host '%s': addrtype %d, length %d",
- he->h_addrtype, he->h_length);
- }
- memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
- }
- return ipaddr;
-}
-
-#if 0
-static char *ether_ntoa(struct ether_addr *eap)
-{
- static char buf[]= "xx:xx:xx:xx:xx:xx";
-
- sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
- eap->ea_addr[0], eap->ea_addr[1],
- eap->ea_addr[2], eap->ea_addr[3],
- eap->ea_addr[4], eap->ea_addr[5]);
- return buf;
-}
-#endif
-
-static void fatal(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- fprintf(stderr, "%s: ", progname);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-
- exit(1);
-}
-
-static void usage(void)
-{
- fprintf(stderr, "Usage:\tarp [-I ip-dev] [-n] hostname\n"
- "\tarp [-I ip-dev] [-n] -a\n"
- "\tarp [-I ip-dev] -d hostname\n"
- "\tarp [-I ip-dev] -d -a\n"
- "\tarp [-I ip-dev] -s hostname ether-addr [temp] [pub]\n"
- "\tarp [-I ip-dev] -S hostname ether-addr [temp] [pub]\n");
- exit(1);
-}
-
-/*
- * $PchId: arp.c,v 1.3 2005/01/31 22:31:45 philip Exp $
- */