123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /* arp.c - manipulate the system ARP cache
- *
- * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com>
- * Copyright 2014 Kyungwan Han <asura321@gamil.com>
- * No Standard
- USE_ARP(NEWTOY(arp, "vi:nDsdap:A:H:[+Ap][!sd]", TOYFLAG_USR|TOYFLAG_BIN))
- config ARP
- bool "arp"
- default n
- help
- usage: arp
- [-vn] [-H HWTYPE] [-i IF] -a [HOSTNAME]
- [-v] [-i IF] -d HOSTNAME [pub]
- [-v] [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [temp]
- [-v] [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [netmask MASK] pub
- [-v] [-H HWTYPE] [-i IF] -Ds HOSTNAME IFACE [netmask MASK] pub
- Manipulate ARP cache.
- -a Display (all) hosts
- -s Set new ARP entry
- -d Delete a specified entry
- -v Verbose
- -n Don't resolve names
- -i IFACE Network interface
- -D Read <hwaddr> from given device
- -A,-p AF Protocol family
- -H HWTYPE Hardware address type
- */
- #define FOR_arp
- #include "toys.h"
- #include <net/if_arp.h>
- GLOBALS(
- char *hw_type;
- char *af_type_A;
- char *af_type_p;
- char *interface;
- int sockfd;
- char *device;
- )
- struct arpreq req;
- struct type {
- char *name;
- int val;
- };
- struct type hwtype[] = {
- {"ether", ARPHRD_ETHER },
- {"loop" ,ARPHRD_LOOPBACK},
- {"ppp" ,ARPHRD_PPP},
- {"infiniband" ,ARPHRD_INFINIBAND},
- {NULL, -1},
- };
- struct type aftype[] = {
- {"inet", AF_INET },
- {"inet6" ,AF_INET6},
- {"unspec" ,AF_UNSPEC},
- {NULL, -1},
- };
- struct type flag_type[] = {
- {"PERM", ATF_PERM },
- {"PUB" ,ATF_PUBL},
- {"DONTPUB" ,ATF_DONTPUB},
- {"TRAIL" ,ATF_USETRAILERS},
- {NULL, -1},
- };
- static int get_index(struct type arr[], char *name)
- {
- int i;
- for (i = 0; arr[i].name; i++)
- if (!strcmp(arr[i].name, name)) break;
- return arr[i].val;
- }
- static void resolve_host(char *host, struct sockaddr *sa)
- {
- struct addrinfo *ai = xgetaddrinfo(host, NULL, AF_INET, SOCK_STREAM, 0, 0);
- memcpy(sa, ai->ai_addr, ai->ai_addrlen);
- freeaddrinfo(ai);
- }
- static void check_flags(int *i, char** argv)
- {
- struct sockaddr sa;
- int flag = *i, j;
- struct flags {
- char *name;
- int or, flag;
- } f[] = {
- {"pub", 1 ,ATF_PUBL},
- {"priv", 0 ,~ATF_PUBL},
- {"trail", 1, ATF_USETRAILERS},
- {"temp", 0, ~ATF_PERM},
- {"dontpub",1, ATF_DONTPUB},
- };
-
- for (;*argv; argv++) {
- for (j = 0; j < ARRAY_LEN(f); j++) {
- if (!strcmp(*argv, f[j].name)) {
- (f[j].or) ?(flag |= f[j].flag):(flag &= f[j].flag);
- break;
- }
- }
- if (j > 4 && !strcmp(*argv, "netmask")) {
- if (!*++argv) error_exit("NULL netmask");
- if (strcmp(*argv, "255.255.255.255")) {
- resolve_host(toys.optargs[0], &sa);
- memcpy(&req.arp_netmask, &sa, sizeof(sa));
- flag |= ATF_NETMASK;
- } else argv++;
- } else if (j > 4 && !strcmp(*argv, "dev")) {
- if (!*++argv) error_exit("NULL dev");
- TT.device = *argv;
- } else if (j > 4) error_exit("invalid arg");
- }
- *i = flag;
- }
- static int set_entry(void)
- {
- int flags = 0;
-
- if (!toys.optargs[1]) error_exit("bad syntax");
- if (!FLAG(D)) {
- char *ptr = toys.optargs[1];
- char *p = ptr, *hw_addr = req.arp_ha.sa_data;
- while (*hw_addr && (p-ptr) < 6) {
- int val, len;
- if (*hw_addr == ':') hw_addr++;
- if (!sscanf(hw_addr, "%2x%n", &val, &len)) break;
- hw_addr += len;
- *p++ = val;
- }
- if ((p-ptr) != 6 || *hw_addr)
- error_exit("bad hw addr '%s'", req.arp_ha.sa_data);
- } else {
- struct ifreq ifre;
- xstrncpy(ifre.ifr_name, toys.optargs[1], IFNAMSIZ);
- xioctl(TT.sockfd, SIOCGIFHWADDR, &ifre);
- if (FLAG(H) && ifre.ifr_hwaddr.sa_family != ARPHRD_ETHER)
- error_exit("protocol type mismatch");
- memcpy(&req.arp_ha, &(ifre.ifr_hwaddr), sizeof(req.arp_ha));
- }
- flags = ATF_PERM | ATF_COM;
- if (toys.optargs[2]) check_flags(&flags, (toys.optargs+2));
- req.arp_flags = flags;
- xstrncpy(req.arp_dev, TT.device, sizeof(req.arp_dev));
- xioctl(TT.sockfd, SIOCSARP, &req);
- if (FLAG(v)) xprintf("Entry set for %s\n", toys.optargs[0]);
- return 0;
- }
- static int ip_to_host(struct sockaddr *sa, int flag)
- {
- int status = 0;
- char hbuf[NI_MAXHOST] = {0,}, sbuf[NI_MAXSERV] = {0,};
- socklen_t len = sizeof(struct sockaddr_in6);
-
- *toybuf = 0;
- if (!(status = getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf,
- sizeof(sbuf), flag))) {
- strcpy(toybuf, hbuf);
- return 0;
- }
- return 1;
- }
- static int delete_entry(void)
- {
- int flags = ATF_PERM;
- if (toys.optargs[1]) check_flags(&flags, (toys.optargs+1));
- req.arp_flags = flags;
- xstrncpy(req.arp_dev, TT.device, sizeof(req.arp_dev));
- xioctl(TT.sockfd, SIOCDARP, &req);
- if (FLAG(v)) xprintf("Delete entry for %s\n", toys.optargs[0]);
- return 0;
- }
- void arp_main(void)
- {
- struct sockaddr sa;
- char ip[16], hw_addr[30], mask[16], dev[16], *host_ip = NULL;
- FILE *fp;
- int h_type, type, flag, i, entries = 0, disp = 0;
- TT.device = "";
- memset(&sa, 0, sizeof(sa));
- TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
- if (FLAG(A) || FLAG(p)) {
- if ((type = get_index(aftype,
- (TT.af_type_A)?TT.af_type_A:TT.af_type_p)) != AF_INET)
- error_exit((type != -1)?"only inet supported by kernel":"unknown family");
- }
- req.arp_ha.sa_family = ARPHRD_ETHER;
- if (FLAG(H)) {
- if ((type = get_index(hwtype, TT.hw_type)) != ARPHRD_ETHER)
- error_exit((type != -1)?"h/w type not supported":"unknown h/w type");
- req.arp_ha.sa_family = type;
- }
- if (FLAG(s) || FLAG(d)) {
- if (!toys.optargs[0]) error_exit("-%c needs a host name", FLAG(d)?'d':'s');
- resolve_host(toys.optargs[0], &sa);
- memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));
- if (FLAG(s) && !set_entry()) return;
- if (FLAG(d) && !delete_entry()) return;
- }
- // Show arp cache.
- if (toys.optargs[0]) {
- resolve_host(toys.optargs[0], &sa);
- ip_to_host(&sa, NI_NUMERICHOST);
- host_ip = xstrdup(toybuf);
- }
- fp = xfopen("/proc/net/arp", "r");
- fgets(toybuf, sizeof(toybuf), fp); // Skip header.
- while (fscanf(fp, "%15s 0x%x 0x%x %29s %15s %15s",
- ip, &h_type, &flag, hw_addr, mask, dev) == 6) {
- char *host_name = "?";
- entries++;
- if ((FLAG(H) && get_index(hwtype, TT.hw_type) != h_type) ||
- (FLAG(i) && strcmp(TT.interface, dev)) ||
- (toys.optargs[0] && strcmp(host_ip, ip))) {
- continue;
- }
- resolve_host(ip, &sa);
- if (FLAG(n)) ip_to_host(&sa, NI_NUMERICHOST);
- else if (!ip_to_host(&sa, NI_NAMEREQD)) host_name = toybuf;
- disp++;
- printf("%s (%s) at" , host_name, ip);
- for (i = 0; hwtype[i].name; i++)
- if (hwtype[i].val & h_type) break;
- if (!hwtype[i].name) error_exit("unknown h/w type");
- if (!(flag & ATF_COM)) {
- if ((flag & ATF_PUBL)) printf(" *");
- else printf(" <incomplete>");
- } else printf(" %s [%s]", hw_addr, hwtype[i].name);
- if (flag & ATF_NETMASK) printf("netmask %s ", mask);
- for (i = 0; flag_type[i].name; i++)
- if (flag_type[i].val & flag) printf(" %s", flag_type[i].name);
- printf(" on %s\n", dev);
- }
- if (FLAG(v))
- xprintf("Entries: %d\tSkipped: %d\tFound: %d\n",
- entries, entries - disp, disp);
- if (toys.optargs[0] && !disp)
- xprintf("%s (%s) -- no entry\n", toys.optargs[0], host_ip);
- if (CFG_TOYBOX_FREE) {
- free(host_ip);
- fclose(fp);
- }
- }
|