⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 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 + -