📄 arp.c
字号:
/* arp.c * linqianghe@163.com * 2006-11-03 */#include "net-support.h"#include "log.h"#include "util.h"#include "af_inet.h"#include "dummy_ipv4.h"#include "pathnames.h"#include <unistd.h>#define _GNU_SOURCE#include <getopt.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <linux/if_arp.h>#include <sys/ioctl.h>#define DFLT_HW "ether"#define DFLT_AF "myinet"char *Release = "1.00", *Version = "arp for tcp/ip module 1.00 (2006-11-03)";int opt_n = 0; int opt_N = 0;int opt_v = 0;int opt_D = 0;int opt_e = 0;int opt_a = 0;struct aftype *ap;struct hwtype *hw;int sockfd = 0;int hw_set = 0;char device[16] = ""; static void version(void){ fprintf(stderr, "%s\n%s\n", Release, Version ); exit(E_VERSION);}static void usage(void){ fprintf(stderr, "Usage:\n arp [-vn] [<HW>] [-i <if>] [-a]" " [<hostname>] <-Display ARP cache\n"); fprintf(stderr, " arp [-v] [-i <if>] -d <hostname>" " [pub][nopub] <-Delete ARP entry\n"); fprintf(stderr, " arp [-vnD] [<HW>] [-i <if>] -f [<filename>]" " <-Add entry from file\n"); fprintf(stderr, " arp [-v] [<HW>] [-i <if>] -s <hostname>" " <hwaddr> [temp][nopub] <-Add entry\n"); fprintf(stderr, " arp [-v] [<HW>] [-i <if>] -s <hostname>" " <hwaddr> [netmask <nm>] pub <-''-\n"); fprintf(stderr, " arp [-v] [<HW>] [-i <if>] -Ds <hostname>" " <if> [netmask <nm>] pub <-''-\n\n"); fprintf(stderr, " -a display" " (all) hosts in alternative (BSD) style\n"); fprintf(stderr, " -s, --set set a new ARP entry\n"); fprintf(stderr, " -d, --delete delete a specified entry\n"); fprintf(stderr, " -v, --verbose be verbose\n"); fprintf(stderr, " -n, --numeric don't resolve names\n"); fprintf(stderr, " -i, --device specify network interface (e.g. eth0)\n"); fprintf(stderr, " -D, --use-device read <hwaddr> from given device\n"); fprintf(stderr, " -A, -p, --protocol specify protocol family\n"); fprintf(stderr, " -f, --file read new entries from" " file or from /etc/ethers\n\n"); fprintf(stderr, " <HW>=Use '-H <hw>' to specify hardware address" " type. Default: %s\n", DFLT_HW); fprintf(stderr, " List of possible hardware types (which support ARP):\n"); print_hwlist(1); exit(E_USAGE);}static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mask, char *dev){ static int title = 0; struct hwtype *xhw; char flags[10]; xhw = get_hwntype(type); if( xhw == NULL ) xhw = get_hwtype( DFLT_HW ); if( title++ == 0 ){ printf( "Address HWtype HWaddress" " Flags Mask Iface\n"); } flags[0] = '\0'; if( arp_flags & ATF_COM ) strcat(flags, "C"); if( arp_flags & ATF_PERM ) strcat(flags, "M"); if( arp_flags & ATF_PUBL ) strcat(flags, "P"); if( arp_flags & ATF_USETRAILERS ) strcat(flags, "T"); if( !(arp_flags & ATF_NETMASK) ) mask = ""; printf("%-23.23s ", name); if( !(arp_flags & ATF_COM) ){ if( arp_flags & ATF_PUBL ) printf("%-8.8s%-20.20s", "*", "*"); else printf("%-8.8s%-20.20s", "", "(incomplete)"); }else{ printf("%-8.8s%-20.20s", xhw->name, hwa); } printf("%-6.6s%-15.15s %s\n", flags, mask, dev);}static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, char *mask, char *dev){ struct hwtype *xhw; xhw = get_hwntype(type); if (xhw == NULL) xhw = get_hwtype(DFLT_HW); printf( "%s (%s) at ", name, ip ); if( !(arp_flags & ATF_COM) ){ if( arp_flags & ATF_PUBL ) printf( "* " ); else printf( "<incomplete> " ); }else{ printf( "%s [%s] ", hwa, xhw->name ); } if( arp_flags & ATF_NETMASK ) printf("netmask %s ", mask); if( arp_flags & ATF_PERM ) printf("PERM "); if( arp_flags & ATF_PUBL ) printf("PUP "); if( arp_flags & ATF_USETRAILERS ) printf("TRAIL "); printf("on %s\n", dev);}static int arp_show(char *name){ char host[100]; struct sockaddr sa; char ip[100]; char hwa[100]; char mask[100]; char line[200]; char dev[100]; int type, flags; FILE *fp; char *hostname; int num, entries = 0, showed = 0; host[0] = '\0'; if( name != NULL ){ safe_strncpy( host, name, (sizeof host) ); if( ap->input(0, host, &sa) < 0 ){ ap->herror( host ); return (-1); } safe_strncpy(host, ap->sprint(&sa, 1), sizeof(host)); } if( (fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL ){ PR_ERR( _PATH_PROCNET_ARP "%s", strerror(errno) ); return (-1); } if( fgets(line, sizeof(line), fp) != (char *) NULL ){ strcpy(mask, "-"); strcpy(dev, "-"); for(; fgets(line, sizeof(line), fp);) { num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n", ip, &type, &flags, hwa, mask, dev); if (num < 4) break; entries++; if( hw_set && (type != hw->type) ) continue; if( host[0] && strcmp(ip, host) ) continue; if( device[0] && strcmp(dev, device) ) continue; showed++; if( opt_n ) hostname = "?"; else{ if (ap->input(0, ip, &sa) < 0) hostname = ip; else hostname = ap->sprint( &sa, opt_n | 0x8000 ); if( strcmp(hostname, ip) == 0 ) hostname = "?"; } if( opt_e ) arp_disp_2(hostname[0] == '?' ? ip : hostname, type, flags, hwa, mask, dev); else arp_disp(hostname, ip, type, flags, hwa, mask, dev); } } if (opt_v) printf("Entries: %d\tSkipped: %d\tFound: %d\n", entries, entries - showed, showed); if( !showed ){ if (host[0] && !opt_a) printf("%s (%s) -- no entry\n", name, host); else if (hw_set || host[0] || device[0]) { printf("arp: in %d entries no match found.\n", entries); } } (void) fclose(fp); return (0);}static int arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw){ struct ifreq ifr; struct hwtype *xhw; strcpy(ifr.ifr_name, ifname); if( ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0 ){ PR_ERR("arp: cant get HW-Address for `%s': %s.\n", ifname, strerror(errno)); return (-1); } if (hw && (ifr.ifr_hwaddr.sa_family != hw->type)) { PR_ERR("arp: protocol type mismatch.\n"); return (-1); } memcpy((char *) sa, (char *) &(ifr.ifr_hwaddr), sizeof(struct sockaddr)); if (opt_v) { if( !(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->print == 0) ){ xhw = get_hwntype(-1); } PR_NOTICE("arp: device `%s' has HW address %s `%s'.\n", ifname, xhw->name, xhw->print((unsigned char *)&ifr.ifr_hwaddr.sa_data)); } return (0);}static int arp_set(char **args){ char host[128]; struct arpreq req; struct sockaddr sa; int flags; memset( (char *) &req, 0, sizeof(req) ); if (*args == NULL) { PR_ERR( "arp: need host name\n" ); return (-1); } safe_strncpy(host, *args++, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr)); if (*args == NULL) { PR_ERR("arp: need hardware address\n"); return (-1); } if( opt_D ){ if( arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL) < 0 ) return (-1); }else{ if( hw->input(*args++, &req.arp_ha) < 0 ){ PR_ERR("arp: invalid hardware address\n"); return (-1); } } flags = ATF_PERM | ATF_COM; while (*args != NULL) { if( !strcmp(*args, "temp") ){ flags &= ~ATF_PERM; args++; continue; } if( !strcmp(*args, "pub") ){ flags |= ATF_PUBL; args++; continue; } if( !strcmp(*args, "priv") ){ flags &= ~ATF_PUBL; args++; continue; } if( !strcmp(*args, "trail") ){ flags |= ATF_USETRAILERS; args++; continue; } if( !strcmp(*args, "dev") ){ if( *++args == NULL ) usage(); safe_strncpy(device, *args, sizeof(device)); args++; continue; } if( !strcmp(*args, "netmask") ){ if( *++args == NULL ) usage(); if( strcmp(*args, "255.255.255.255") != 0 ){ strcpy(host, *args); if( ap->input(0, host, &sa) < 0 ){ ap->herror(host); return (-1); } memcpy((char *) &req.arp_netmask, (char *) &sa, sizeof(struct sockaddr)); flags |= ATF_NETMASK; } args++; continue; } usage(); } req.arp_flags = flags; strcpy(req.arp_dev, device); if (opt_v) PR_DEBUG( "arp: SIOCSARP()\n" ); if( ioctl(sockfd, SIOCSARP, &req) < 0 ){ PR_ERR( "SIOCSARP: %s\n", strerror(errno) ); return (-1); } return (0);}static int arp_file(char *name){ char buff[1024]; char *sp, *args[32]; int linenr, argc; FILE *fp; if( (fp = fopen(name, "r")) == NULL ){ PR_ERR( "arp: cannot open etherfile %s !\n", name ); return (-1); } linenr = 0; while( fgets(buff, sizeof(buff), fp) != (char *) NULL ){ linenr++; if( opt_v == 1 ) fprintf(stderr, ">> %s", buff); if( (sp = strchr(buff, '\n')) != (char *) NULL ) *sp = '\0'; if( buff[0] == '#' || buff[0] == '\0' ) continue; argc = getargs( buff, args ); if( argc < 2 ){ PR_ERR("arp: format error on line %u of etherfile %s !\n", linenr, name); continue; } if( strchr (args[0], ':') != NULL ){ char *cp; cp = args[1]; args[1] = args[0]; args[0] = cp; } if( arp_set(args) != 0 ) PR_ERR( "arp: cannot set entry on line %u of etherfile %s !\n", linenr, name); } (void) fclose(fp); return (0);}static int arp_del(char **args){ char host[128]; struct arpreq req; struct sockaddr sa; int flags = 0; int err; memset((char *) &req, 0, sizeof(req)); if (*args == NULL) { PR_ERR( "arp: need host name\n" ); return (-1); } safe_strncpy(host, *args, (sizeof host)); if( ap->input(0, host, &sa) < 0 ){ ap->herror(host); return (-1); } memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr)); if( hw_set ) req.arp_ha.sa_family = hw->type; req.arp_flags = ATF_PERM; args++; while (*args != NULL) { if( opt_v ) fprintf(stderr, "args=%s\n", *args); if( !strcmp(*args, "pub") ){ flags |= 1; args++; continue; } if( !strcmp(*args, "priv") ){ flags |= 2; args++; continue; } if( !strcmp(*args, "temp") ){ req.arp_flags &= ~ATF_PERM; args++; continue; } if( !strcmp(*args, "trail") ){ req.arp_flags |= ATF_USETRAILERS; args++; continue; } if( !strcmp(*args, "dev") ){ if( *++args == NULL ) usage(); safe_strncpy(device, *args, sizeof(device)); args++; continue; } if( !strcmp(*args, "netmask") ){ if (*++args == NULL) usage(); if( strcmp(*args, "255.255.255.255") != 0 ){ strcpy(host, *args); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } memcpy((char *) &req.arp_netmask, (char *) &sa,sizeof(struct sockaddr)); req.arp_flags |= ATF_NETMASK; } args++; continue; } usage(); } if( flags == 0 ) flags = 3; strcpy( req.arp_dev, device ); err = -1; if( flags & 2 ){ if( opt_v ) fprintf(stderr, "arp: SIOCDARP(nopub)\n"); if( (err = ioctl(sockfd, SIOCDARP, &req) < 0) ){ if( errno == ENXIO ){ if( flags & 1 ) goto nopub; PR_ERR( "No ARP entry for %s\n", host ); return (-1); } PR_ERR( "SIOCDARP(priv): %s\n", strerror(errno) ); return (-1); } } if( (flags & 1) && (err) ){nopub: req.arp_flags |= ATF_PUBL; if( opt_v ) fprintf(stderr, "arp: SIOCDARP(pub)\n"); if( ioctl(sockfd, SIOCDARP, &req) < 0 ){ if( errno == ENXIO ){ PR_ERR( "No ARP entry for %s\n", host); return (-1); } PR_ERR("SIOCDARP(pub) %s\n", strerror(errno) ); return (-1); } } return (0);} int main(int argc, char **argv){ int i, lop, what; struct option longopts[] = { {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {"all", 0, 0, 'a'}, {"delete", 0, 0, 'd'}, {"file", 0, 0, 'f'}, {"numeric", 0, 0, 'n'}, {"set", 0, 0, 's'}, {"protocol", 1, 0, 'A'}, {"hw-type", 1, 0, 'H'}, {"device", 1, 0, 'i'}, {"help", 0, 0, 'h'}, {"use-device", 0, 0, 'D'}, {"symbolic", 0, 0, 'N'}, {NULL, 0, 0, 0} }; if( (hw = get_hwtype(DFLT_HW)) == NULL ){ PR_DEBUG("%s: hardware type not supported!\n", DFLT_HW); return (-1); } if( (ap = get_aftype(DFLT_AF)) == NULL ){ PR_DEBUG("%s: address family not supported!\n", DFLT_AF); return (-1); } what = 0; while( (i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV", longopts, &lop)) != EOF ) switch( i ){ case 'a': what = 1; opt_a = 1; break; case 'f': what = 2; break; case 'd': what = 3; break; case 's': what = 4; break; case 'e': opt_e = 1; break; case 'n': opt_n = FLAG_NUM; break; case 'D': opt_D = 1; break; case 'N': opt_N = FLAG_SYM; PR_ERR( "arp: -N not yet supported.\n" ); break; case 'v': opt_v = 1; break; case 'A': case 'p': ap = get_aftype( optarg ); if( ap == NULL ){ PR_ERR( "arp: %s: unknown address family.\n", optarg ); exit(-1); } break; case 'H': case 't': hw = get_hwtype(optarg); if( hw == NULL ) { PR_ERR( "arp: %s: unknown hardware type.\n", optarg ); exit(-1); } hw_set = 1; break; case 'i': safe_strncpy( device, optarg, sizeof(device) ); break; case 'V': version(); case '?': case 'h': default: usage(); } if( ap->af != MY_AF_INET ){ PR_ERR( "arp: %s: kernel only supports 'inet'.\n", ap->name); exit(-1); } if(hw_set==0) if( (hw = get_hwtype(DFLT_HW)) == NULL ){ PR_ERR("%s: hardware type not supported!\n", DFLT_HW ); return (-1); } if( hw->alen <= 0 ){ PR_ERR( "arp: %s: hardware type without ARP support.\n", hw->name ); exit(-1); } if( (sockfd = socket(MY_AF_INET, SOCK_DUMMY, IPPROTO_DUMMY)) < 0 ){ PR_ERR("socket: '%s\n", strerror(errno) ); exit(-1); } switch (what) { case 0: opt_e = 1; what = arp_show(argv[optind]); case 1: what = arp_show(argv[optind]); break; case 2: what = arp_file(argv[optind] ? argv[optind] : "/etc/ethers"); break; case 3: /* delete an ARP entry from the cache */ what = arp_del(&argv[optind]); break; case 4: /* set an ARP entry in the cache */ what = arp_set(&argv[optind]); break; default: usage(); } exit(what);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -