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

📄 ipv6addr.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This program manages IPv6 address. * * Author: Huang Zhen <zhenh@cn.ibm.com> * Copyright (c) 2004 International Business Machines * * 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 * */ /* * It can add an IPv6 address, or remove one. * * Usage:  IPv6addr ipv6-address {start|stop|status|monitor} * * The "start" arg adds an IPv6 address. * The "stop" arg removes one. * The "status" arg shows whether the IPv6 address exists * The "monitor" arg shows whether the IPv6 address can be pinged (ICMPv6 ECHO) */ /* * ipv6-address: * * currently the following forms are legal: *	address *	address/prefix * *     E.g. *	3ffe:ffff:0:f101::1 *	3ffe:ffff:0:f101::1/64 * */ /* * start: * 	1.IPv6addr will choice a proper interface for the new address. *	2.Then assign the new address to the interface. *	3.Wait until the new address is available (reply ICMPv6 ECHO packet) *	4.Send out the unsolicited advertisements. * *	return 0(LSB_EXIT_OK) for success *	return 1(LSB_EXIT_GENERIC) for failure * * * stop: *	remove the address from the inferface. * *	return 0(LSB_EXIT_OK) for success *	return 1(LSB_EXIT_GENERIC) for failure * * status: *	return the status of the address. only check whether it exists. * *	return 0(LSB_STATUS_OK) for existing *	return 1(LSB_STATUS_STOPPED) for not existing * * * monitor: *	ping the address by ICMPv6 ECHO request. * *	return 0(LSB_STATUS_OK) for response correctly. *	return 1(LSB_STATUS_STOPPED) for no response. * */ #include <config.h>#include <asm/types.h>#include <libgen.h>#include <syslog.h>#include <clplumbing/cl_log.h>#include <libnet.h>#include <linux/icmpv6.h>#include <clplumbing/lsb_exitcodes.h>#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ < 2#	include <sys/uio.h>#endif #define PIDDIR HA_VARRUNDIR#define PIDFILE_BASE PIDDIR "/IPv6addr-"const char* IF_INET6	 	= "/proc/net/if_inet6";const char* APP_NAME		= "IPv6addr";const char*	START_CMD 	= "start";const char*	STOP_CMD  	= "stop";const char*	STATUS_CMD 	= "status";const char*	MONITOR_CMD 	= "monitor";const char*	ADVT_CMD	= "advt";char		BCAST_ADDR[]	= "ff02::1";const int	UA_REPEAT_COUNT	= 5;const int	QUERY_COUNT	= 5;struct in6_ifreq {    struct in6_addr ifr6_addr;    __u32 ifr6_prefixlen;    unsigned int ifr6_ifindex;};static int start_addr6(struct in6_addr* addr6, int prefix_len);static int stop_addr6(struct in6_addr* addr6, int prefix_len);static int status_addr6(struct in6_addr* addr6, int prefix_len);static int monitor_addr6(struct in6_addr* addr6, int prefix_len);static int advt_addr6(struct in6_addr* addr6, int prefix_len);static void usage(const char* self);int write_pid_file(const char *pid_file);int create_pid_directory(const char *pid_file);static void byebye(int nsig);static char* find_if(struct in6_addr* addr_target, int* plen_target);static char* get_if(struct in6_addr* addr_target, int* plen_target);static int assign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name);static int unassign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name);int is_addr6_available(struct in6_addr* addr6);static int send_ua(struct in6_addr* src_ip, char* if_name);intmain(int argc, char* argv[]){	char		pid_file[256];	int		ret;	char*		cp;	int		prefix_len;	struct in6_addr	addr6;	/* Check the count of parameters first */	if (argc < 3) {		usage(argv[0]);		return EXIT_FAILURE;	}	/* set termination signal */	siginterrupt(SIGTERM, 1);	signal(SIGTERM, byebye);	/* open system log */	openlog(APP_NAME, LOG_CONS | LOG_PID, LOG_USER);	/* check the first parameter, should be a IPv6 address */	if ((cp = strchr(argv[1], '/'))) {		prefix_len = atol(cp + 1);		if ((prefix_len < 0) || (prefix_len > 128)) {			usage(argv[0]);			return EXIT_FAILURE;		} 		*cp=0;	} else {		prefix_len = 0;	}		if (inet_pton(AF_INET6, argv[1], &addr6) <= 0) {		usage(argv[0]);		return EXIT_FAILURE;	}		/* Check whether this system supports IPv6 */	if (access(IF_INET6, R_OK)) {		cl_log(LOG_ERR, "No support for INET6 on this system.");		return EXIT_FAILURE;	}		/* create the pid file so we can make sure that only one IPv6addr	 * for this address is running	 */	if (snprintf(pid_file, sizeof(pid_file), "%s%s", PIDFILE_BASE, argv[1])		>= (int)sizeof(pid_file)) {		cl_log(LOG_ERR, "Pid file truncated");		return EXIT_FAILURE;	}	if (write_pid_file(pid_file) < 0) {		return EXIT_FAILURE;	}	/* switch the command */	if (0 == strncmp(START_CMD,argv[2], strlen(START_CMD))) {		ret = start_addr6(&addr6, prefix_len);	}else if (0 == strncmp(STOP_CMD,argv[2], strlen(STOP_CMD))) {		ret = stop_addr6(&addr6, prefix_len);	}else if (0 == strncmp(STATUS_CMD,argv[2], strlen(STATUS_CMD))) {		ret = status_addr6(&addr6, prefix_len);	}else if (0 ==strncmp(MONITOR_CMD,argv[2], strlen(MONITOR_CMD))) {		ret = monitor_addr6(&addr6, prefix_len);	}else if (0 ==strncmp(ADVT_CMD,argv[2], strlen(MONITOR_CMD))) {		ret = advt_addr6(&addr6, prefix_len);	}else{		usage(argv[0]);		ret = EXIT_FAILURE;	}		/* release the pid file */	unlink(pid_file);	return ret;}intstart_addr6(struct in6_addr* addr6, int prefix_len){	/* First, we need to find a proper device to assign the address */	int	i;	char*	if_name = find_if(addr6, &prefix_len);	if (NULL == if_name) {		cl_log(LOG_ERR, "no valid mecahnisms");		return LSB_EXIT_GENERIC;	}	/* Assign the address */	if (0 != assign_addr6(addr6, prefix_len, if_name)) {		cl_log(LOG_ERR, "failed to assign the address to %s", if_name);		return LSB_EXIT_GENERIC;	}	/* Check whether the address available */	for (i = 0; i < QUERY_COUNT; i++) {		if (0 == is_addr6_available(addr6)) {			break;		}		sleep(1);	}	if (i == QUERY_COUNT) {		cl_log(LOG_ERR, "failed to ping the address");		return LSB_EXIT_GENERIC;	}		/* Send unsolicited advertisement packet to neighbor */	for (i = 0; i < UA_REPEAT_COUNT; i++) {		send_ua(addr6, if_name);		sleep(1);	}	return LSB_EXIT_OK;}intadvt_addr6(struct in6_addr* addr6, int prefix_len){	/* First, we need to find a proper device to assign the address */	char*	if_name = get_if(addr6, &prefix_len);	int	i;	if (NULL == if_name) {		cl_log(LOG_ERR, "no valid mecahnisms");		return LSB_EXIT_GENERIC;	}	/* Send unsolicited advertisement packet to neighbor */	for (i = 0; i < UA_REPEAT_COUNT; i++) {		send_ua(addr6, if_name);		sleep(1);	}	return LSB_STATUS_OK;}	intstop_addr6(struct in6_addr* addr6, int prefix_len){	char* if_name = get_if(addr6, &prefix_len);	if (NULL == if_name) {		cl_log(LOG_ERR, "no valid mechanisms.");		/* I think this should be a success exit according to LSB. */		return LSB_EXIT_GENERIC;	}	/* Unassign the address */	if (0 != unassign_addr6(addr6, prefix_len, if_name)) {		cl_log(LOG_ERR, "failed to assign the address to %s", if_name);		return LSB_EXIT_GENERIC;	}	return LSB_EXIT_OK;}intstatus_addr6(struct in6_addr* addr6, int prefix_len){	char* if_name = get_if(addr6, &prefix_len);	if (NULL == if_name) {		return LSB_STATUS_STOPPED;	}	return LSB_STATUS_OK;}	intmonitor_addr6(struct in6_addr* addr6, int prefix_len){	if(0 == is_addr6_available(addr6)) {		return LSB_STATUS_OK;	}	return LSB_STATUS_STOPPED;}/* Send an unsolicited advertisement packet * Please refer to rfc2461 */intsend_ua(struct in6_addr* src_ip, char* if_name){	libnet_t *l;	char errbuf[LIBNET_ERRBUF_SIZE];	struct libnet_in6_addr dst_ip;	struct libnet_ether_addr *mac_address;	char payload[24];	if ((l=libnet_init(LIBNET_RAW6, if_name, errbuf)) == NULL) {		cl_log(LOG_ERR, "libnet_init failure on %s", if_name);		return -1;	}	mac_address = libnet_get_hwaddr(l);	if (!mac_address) {		cl_log(LOG_ERR, "libnet_get_hwaddr: %s", errbuf);		return -1;	}	dst_ip = libnet_name2addr6(l, BCAST_ADDR, LIBNET_DONT_RESOLVE);	memcpy(payload,src_ip->s6_addr,16);	payload[16] = 2; /* 2 for Target Link-layer Address */	payload[17] = 1; /* The length of the option */	memcpy(payload+18,mac_address->ether_addr_octet, 6);	libnet_seed_prand(l);	/* 0x2000: RSO */	libnet_build_icmpv4_echo(136,0,0,0x2000,0,(unsigned char*)payload,sizeof(payload),				 l,LIBNET_PTAG_INITIALIZER);	libnet_build_ipv6(0,0,LIBNET_ICMPV6_H + sizeof(payload),IPPROTO_ICMP6,				255,*(struct libnet_in6_addr*)src_ip,				dst_ip,NULL,0,l,0);        if (libnet_write(l) == -1)        {		cl_log(LOG_ERR, "libnet_write: %s", libnet_geterror(l));		return -1;	}	return 0;}/* find a proper network interface to assign the address */char*find_if(struct in6_addr* addr_target, int* plen_target){	FILE *f;	char addr6[40];	static char devname[20]="";	struct in6_addr addr;	struct in6_addr mask;	int		plen;	int		scope;	int		dad_status;	int		if_idx;	char addr6p[8][5];	/* open /proc/net/if_inet6 file */	if ((f = fopen(IF_INET6, "r")) == NULL) {		return NULL;	}	/* Loop for each entry */	while ( fscanf(f,"%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",			addr6p[0], addr6p[1], addr6p[2], addr6p[3],			addr6p[4], addr6p[5], addr6p[6], addr6p[7],			&if_idx, &plen, &scope, &dad_status, devname) != EOF){		int		i;		int		n;		int		s;		gboolean	same = TRUE;		sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",			addr6p[0], addr6p[1], addr6p[2], addr6p[3],			addr6p[4], addr6p[5], addr6p[6], addr6p[7]);

⌨️ 快捷键说明

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