Mercurial > hg > toybox
view toys/pending/arp.c @ 1572:da1bf31ed322 draft
Tweak the "ignoring return value" fortify workaround for readlinkat.
We zero the buffer and if the link read fails that's left alone, so
it's ok for the symlink not to be there. Unfortunately, typecasting the
return value to (void) doesn't shut up gcc, and having an if(); with the
semicolon on the same line doesn't shut up llvm. (The semicolon on a new
line would, but C does not have significant whitespace and I'm not going
to humor llvm if it plans to start.)
So far, empty curly brackets consistently get the warning to shut up.
author | Rob Landley <rob@landley.net> |
---|---|
date | Mon, 24 Nov 2014 17:23:23 -0600 |
parents | 00c20f410c46 |
children | 41efba077b75 |
line wrap: on
line source
/* 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 IF 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; //Global request structure 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; } void get_hw_add(char *hw_addr, char *ptr) { char *p = ptr, *hw = hw_addr; while (*hw_addr && (p-ptr) < 6) { int val, len = 0; if (*hw_addr == ':') hw_addr++; sscanf(hw_addr, "%2x%n", &val, &len); if (!len || len > 2) break; hw_addr += len; *p++ = val; } if ((p-ptr) != 6 || *hw_addr) error_exit("bad hw addr '%s'", hw); } static void resolve_host(char *host, struct sockaddr *sa) { struct addrinfo hints, *res = NULL; int ret; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if ((ret = getaddrinfo(host, NULL, &hints, &res))) perror_exit("%s", gai_strerror(ret)); memcpy(sa, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } 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 (!(toys.optflags & FLAG_D)) get_hw_add(toys.optargs[1], (char*)&req.arp_ha.sa_data); else { struct ifreq ifre; xstrncpy(ifre.ifr_name, toys.optargs[1], IFNAMSIZ); xioctl(TT.sockfd, SIOCGIFHWADDR, &ifre); if ((toys.optflags & 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; strncpy(req.arp_dev, TT.device, sizeof(req.arp_dev)); xioctl(TT.sockfd, SIOCSARP, &req); if (toys.optflags & 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; flags = ATF_PERM; if (toys.optargs[1]) check_flags(&flags, (toys.optargs+1)); req.arp_flags = flags; strncpy(req.arp_dev, TT.device, sizeof(req.arp_dev)); xioctl(TT.sockfd, SIOCDARP, &req); if (toys.optflags & FLAG_v) xprintf("Delete entry for %s\n", toys.optargs[0]); return 0; } void arp_main(void) { struct sockaddr sa; char ip[128], hw_addr[128], mask[12], dev[128], *host_ip = NULL, *buf; int h_type, type, flag, i, fd, entries = 0, disp = 0; TT.device = ""; memset(&sa, 0, sizeof(sa)); memset(&req, 0, sizeof(req)); TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0); if ((toys.optflags & FLAG_A) || (toys.optflags & 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 (toys.optflags & 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 (((toys.optflags & FLAG_s) || toys.optflags & FLAG_d)) { if (!toys.optargs[0]) error_exit("host name req"); resolve_host(toys.optargs[0], &sa); memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr)); } if ((toys.optflags & FLAG_s) && !set_entry()) return; if ((toys.optflags & FLAG_d) && !delete_entry()) return; //show arp chache fd = xopen("/proc/net/arp", O_RDONLY); buf = get_line(fd); free(buf); //skip first line if (toys.optargs[0]) { resolve_host(toys.optargs[0], &sa); ip_to_host(&sa, NI_NUMERICHOST); host_ip = xstrdup(toybuf); } while ((buf = get_line(fd))) { char *host_name = "?"; if ((sscanf(buf, "%s 0x%x 0x%x %s %s %s\n", ip, &h_type, &flag, hw_addr, mask, dev )) != 6) break; entries++; if (((toys.optflags & FLAG_H) && (get_index(hwtype, TT.hw_type) != h_type)) || ((toys.optflags & FLAG_i) && strcmp(TT.interface, dev)) || (toys.optargs[0] && strcmp(host_ip, ip))) { free(buf); continue; } resolve_host(buf, &sa); if (!(toys.optflags & FLAG_n)) { if (!ip_to_host(&sa, NI_NAMEREQD)) host_name = toybuf; } else ip_to_host(&sa, NI_NUMERICHOST); 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); free(buf); } if (toys.optflags & FLAG_v) xprintf("Entries: %d\tSkipped: %d\tFound: %d\n", entries, entries - disp, disp); if (!disp) xprintf("No Match found in %d entries\n", entries); if (CFG_TOYBOX_FREE) { free(host_ip); free(buf); xclose(fd); } }