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

📄 send_arp.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: send_arp.c,v 1.13 2004/09/10 02:03:00 alan Exp $ *//*  * send_arp *  * This program sends out one ARP packet with source/target IP and Ethernet * hardware addresses suuplied by the user.  It uses the libnet libary from * Packet Factory (http://www.packetfactory.net/libnet/ ). It has been tested * on Linux, FreeBSD, and on Solaris. *  * This inspired by the sample application supplied by Packet Factory. * Matt Soffen * Copyright (C) 2001 Matt Soffen <matt@soffen.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <portability.h>#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <limits.h>#include <libnet.h>#include <syslog.h>#include <libgen.h>#include <clplumbing/timers.h>#include <clplumbing/cl_signal.h>#ifdef HAVE_LIBNET_1_0_API#	define	LTYPE	struct libnet_link_int#endif#ifdef HAVE_LIBNET_1_1_API#	define	LTYPE	libnet_t#endif#define PIDDIR       HA_VARLIBDIR "/" PACKAGE "/rsctmp/send_arp"#define PIDFILE_BASE PIDDIR "/send_arp-"static int send_arp(LTYPE* l, u_long ip, u_char *device, u_char mac[6],	u_char *broadcast, u_char *netmask, u_short arptype);static char print_usage[]={	"send_arp: sends out custom ARP packet. packetfactory.net\n"	"\tusage: send_arp [-i repeatinterval-ms] [-r repeatcount]"	" [-p pidfile] device src_ip_addr src_hw_addr broadcast_ip_addr netmask\n"	"\tIf src_hw_addr is \"auto\" then the address of device will be used"};static void convert_macaddr (u_char *macaddr, u_char enet_src[6]);static int get_hw_addr(char *device, u_char mac[6]);int write_pid_file(const char *pidfilename);int create_pid_directory(const char *piddirectory);#define AUTO_MAC_ADDR "auto"#ifndef LIBNET_ERRBUF_SIZE#	define LIBNET_ERRBUF_SIZE 256#endifstatic voidbyebye(int nsig){	(void)nsig;	/* Avoid an "error exit" log message if we're killed */	exit(0);}intmain(int argc, char *argv[]){	int	c = -1;	char	errbuf[LIBNET_ERRBUF_SIZE];	char*	device;	char*	ipaddr;	char*	macaddr;	char*	broadcast;	char*	netmask;	u_long	ip;	u_char  src_mac[6];	LTYPE*	l;	int	repeatcount = 1;	int	j;	long	msinterval = 1000;	int	flag;	char    pidfilenamebuf[64];	char    *pidfilename = NULL;	CL_SIGINTERRUPT(SIGTERM, 1);	CL_SIGNAL(SIGTERM, byebye);	openlog("send_arp", LOG_CONS | LOG_PID, LOG_USER);	while ((flag = getopt(argc, argv, "i:r:p:")) != EOF) {		switch(flag) {		case 'i':	msinterval= atol(optarg);				break;		case 'r':	repeatcount= atoi(optarg);				break;		case 'p':	pidfilename= optarg;				break;		default:	fprintf(stderr, "usage: %s\n\n", print_usage);				return 1;				break;		}	}	if (argc-optind != 5) {		fprintf(stderr, "usage: %s\n\n", print_usage);		return 1;	}	/*	 *	argv[optind+1] DEVICE		dc0,eth0:0,hme0:0,	 *	argv[optind+2] IP		192.168.195.186	 *	argv[optind+3] MAC ADDR		00a0cc34a878	 *	argv[optind+4] BROADCAST	192.168.195.186	 *	argv[optind+5] NETMASK		ffffffffffff	 */	device    = argv[optind];	ipaddr    = argv[optind+1];	macaddr   = argv[optind+2];	broadcast = argv[optind+3];	netmask   = argv[optind+4];	if (!pidfilename) {		if (snprintf(pidfilenamebuf, sizeof(pidfilenamebuf), "%s%s", 					PIDFILE_BASE, ipaddr) >= 				(int)sizeof(pidfilenamebuf)) {			syslog(LOG_INFO, "Pid file truncated");			return EXIT_FAILURE;		}		pidfilename = pidfilenamebuf;	}	if(write_pid_file(pidfilename) < 0) {		return EXIT_FAILURE;	}#if defined(HAVE_LIBNET_1_0_API)	if ((ip = libnet_name_resolve(ipaddr, 1)) == -1UL) {		syslog(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);		unlink(pidfilename);		return EXIT_FAILURE;	}	l = libnet_open_link_interface(device, errbuf);	if (!l) {		syslog(LOG_ERR, "libnet_open_link_interface on %s: %s"		,	device, errbuf);		unlink(pidfilename);		return EXIT_FAILURE;	}#elif defined(HAVE_LIBNET_1_1_API)	if ((l=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {		syslog(LOG_ERR, "libnet_init failure on %s", device);		unlink(pidfilename);		return EXIT_FAILURE;	}	if ((signed)(ip = libnet_name2addr4(l, ipaddr, 1)) == -1) {		syslog(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);		unlink(pidfilename);		return EXIT_FAILURE;	}#else#	error "Must have LIBNET API version defined."#endif	if (!strcasecmp(macaddr, AUTO_MAC_ADDR)) {		if (get_hw_addr(device, src_mac) < 0) {			 syslog(LOG_ERR, "Cannot find mac address for %s", 					 device);			 unlink(pidfilename);			 return EXIT_FAILURE;		}	}	else {		convert_macaddr(macaddr, src_mac);	}/* * We need to send both a broadcast ARP request as well as the ARP response we * were already sending.  All the interesting research work for this fix was * done by Masaki Hasegawa <masaki-h@pp.iij4u.or.jp> and his colleagues. */	for (j=0; j < repeatcount; ++j) {		c = send_arp(l, ip, device, src_mac, broadcast, 				netmask, ARPOP_REQUEST);		if (c < 0) {			break;		}		mssleep(msinterval / 2);		c = send_arp(l, ip, device, src_mac, broadcast, 				netmask, ARPOP_REPLY);		if (c < 0) {			break;		}		if (j != repeatcount-1) {			mssleep(msinterval / 2);		}	}	unlink(pidfilename);	return c < 0  ? EXIT_FAILURE : EXIT_SUCCESS;}voidconvert_macaddr (u_char *macaddr, u_char enet_src[6]){	int i, pos;	u_char bits[3];	pos = 0;	for (i = 0; i < 6; i++) {		/* Inserted to allow old-style MAC addresses */		if (*macaddr == ':') {			pos++;		}		bits[0] = macaddr[pos++];		bits[1] = macaddr[pos++];		bits[2] = '\0';		enet_src[i] = strtol(bits, (char **)NULL, 16);	}}#ifdef HAVE_LIBNET_1_0_APIintget_hw_addr(char *device, u_char mac[6]){	struct ether_addr	*mac_address;	struct libnet_link_int  *network;	char                    err_buf[LIBNET_ERRBUF_SIZE];	/* Get around bad prototype for libnet_error() */	char errmess1 [] = "libnet_open_link_interface: %s\n";	char errmess2 [] = "libnet_get_hwaddr: %s\n";	network = libnet_open_link_interface(device, err_buf);	if (!network) {		libnet_error(LIBNET_ERR_FATAL, errmess1, err_buf);		return -1;	}	mac_address = libnet_get_hwaddr(network, device, err_buf);	if (!mac_address) {		libnet_error(LIBNET_ERR_FATAL, errmess2, err_buf);		return -1;	}	memcpy(mac, mac_address->ether_addr_octet, 6);	return 0;}#endif#ifdef HAVE_LIBNET_1_1_APIintget_hw_addr(char *device, u_char mac[6]){	struct libnet_ether_addr	*mac_address;	libnet_t		*ln;	char			err_buf[LIBNET_ERRBUF_SIZE];	ln = libnet_init(LIBNET_LINK, device, err_buf);	if (!ln) {		fprintf(stderr, "libnet_open_link_interface: %s\n", err_buf);		return -1;	}	mac_address = libnet_get_hwaddr(ln);	if (!mac_address) {		fprintf(stderr,  "libnet_get_hwaddr: %s\n", err_buf);		return -1;	}	memcpy(mac, mac_address->ether_addr_octet, 6);	return 0;}#endif/* * Notes on send_arp() behaviour. Horms, 15th June 2004 * * 1. Target Hardware Address *    (In the ARP portion of the packet) * *    a) ARP Reply * *       Set to the MAC address we want associated with the VIP, *       as per RFC2002 (4.6). * *       Previously set to ff:ff:ff:ff:ff:ff * *    b) ARP Request * *       Set to 00:00:00:00:00:00. According to RFC2002 (4.6) *       this value is not used in an ARP request, so the value should *       not matter. However, I observed that typically (always?) this value *       is set to 00:00:00:00:00:00. It seems harmless enough to follow *       this trend. * *       Previously set to ff:ff:ff:ff:ff:ff * *  2. Source Hardware Address *     (Ethernet Header, not in the ARP portion of the packet) * *     Set to the MAC address of the interface that the packet is being *     sent to. Actually, due to the way that send_arp is called this would *     usually (always?) be the case anyway. Although this value should not *     really matter, it seems sensible to set the source address to where *     the packet is really coming from.  The other obvious choice would be *     the MAC address that is being associated for the VIP. Which was the *     previous values.  Again, these are typically the same thing. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -