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

📄 ifenslave.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Mode: C; * ifenslave.c: Configure network interfaces for parallel routing. * *	This program controls the Linux implementation of running multiple *	network interfaces in parallel. * * Author:	Donald Becker <becker@cesdis.gsfc.nasa.gov> *		Copyright 1994-1996 Donald Becker * *		This program is free software; you can redistribute it *		and/or modify it under the terms of the GNU General Public *		License as published by the Free Software Foundation. * *	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O *	Center of Excellence in Space Data and Information Sciences *	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 * *  Changes : *    - 2000/10/02 Willy Tarreau <willy at meta-x.org> : *       - few fixes. Master's MAC address is now correctly taken from *         the first device when not previously set ; *       - detach support : call BOND_RELEASE to detach an enslaved interface. *       - give a mini-howto from command-line help : # ifenslave -h * *    - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> : *       - Master is now brought down before setting the MAC address.  In *         the 2.4 kernel you can't change the MAC address while the device is *         up because you get EBUSY. * *    - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com> *       - Added the ability to change the active interface on a mode 1 bond *         at runtime. * *    - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> : *       - No longer set the MAC address of the master.  The bond device will *         take care of this itself *       - Try the SIOC*** versions of the bonding ioctls before using the *         old versions *    - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> : *       - ifr2.ifr_flags was not initialized in the hwaddr_notset case, *         SIOCGIFFLAGS now called before hwaddr_notset test * *    - 2002/10/31 Tony Cureington <tony.cureington * hp_com> : *       - If the master does not have a hardware address when the first slave *         is enslaved, the master is assigned the hardware address of that *         slave - there is a comment in bonding.c stating "ifenslave takes *         care of this now." This corrects the problem of slaves having *         different hardware addresses in active-backup mode when *         multiple interfaces are specified on a single ifenslave command *         (ifenslave bond0 eth0 eth1). * *    - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and *                   Shmulik Hen <shmulik.hen at intel dot com> *       - Moved setting the slave's mac address and openning it, from *         the application to the driver. This enables support of modes *         that need to use the unique mac address of each slave. *         The driver also takes care of closing the slave and restoring its *         original mac address upon release. *         In addition, block possibility of enslaving before the master is up. *         This prevents putting the system in an undefined state. * *    - 2003/05/01 - Amir Noam <amir.noam at intel dot com> *       - Added ABI version control to restore compatibility between *         new/old ifenslave and new/old bonding. *       - Prevent adding an adapter that is already a slave. *         Fixes the problem of stalling the transmission and leaving *         the slave in a down state. * *    - 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com> *       - Prevent enslaving if the bond device is down. *         Fixes the problem of leaving the system in unstable state and *         halting when trying to remove the module. *       - Close socket on all abnormal exists. *       - Add versioning scheme that follows that of the bonding driver. *         current version is 1.0.0 as a base line. * *    - 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com> *	 - ifenslave -c was broken; it's now fixed *	 - Fixed problem with routes vanishing from master during enslave *	   processing. * *    - 2003/05/27 - Amir Noam <amir.noam at intel dot com> *	 - Fix backward compatibility issues: *	   For drivers not using ABI versions, slave was set down while *	   it should be left up before enslaving. *	   Also, master was not set down and the default set_mac_address() *	   would fail and generate an error message in the system log. * 	 - For opt_c: slave should not be set to the master's setting *	   while it is running. It was already set during enslave. To *	   simplify things, it is now handled separately. * *    - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> *	 - Code cleanup and style changes *	   set version to 1.1.0 */#define APP_VERSION	"1.1.0"#define APP_RELDATE	"December 1, 2003"#define APP_NAME	"ifenslave"static char *version =APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n""o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n""o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n""o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n""  (ctindel at ieee dot org).\n";static const char *usage_msg ="Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n""       ifenslave -d   <master-if> <slave-if> [<slave-if>...]\n""       ifenslave -c   <master-if> <slave-if>\n""       ifenslave --help\n";static const char *help_msg ="\n""       To create a bond device, simply follow these three steps :\n""       - ensure that the required drivers are properly loaded :\n""         # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n""       - assign an IP address to the bond device :\n""         # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n""       - attach all the interfaces you need to the bond device :\n""         # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n""         If bond0 didn't have a MAC address, it will take eth0's. Then, all\n""         interfaces attached AFTER this assignment will get the same MAC addr.\n""         (except for ALB/TLB modes)\n""\n""       To set the bond device down and automatically release all the slaves :\n""         # ifconfig bond0 down\n""\n""       To detach a dead interface without setting the bond device down :\n""         # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n""\n""       To change active slave :\n""         # ifenslave {-c|--change-active} bond0 eth0\n""\n""       To show master interface info\n""         # ifenslave bond0\n""\n""       To show all interfaces info\n""       # ifenslave {-a|--all-interfaces}\n""\n""       To be more verbose\n""       # ifenslave {-v|--verbose} ...\n""\n""       # ifenslave {-u|--usage}   Show usage\n""       # ifenslave {-V|--version} Show version\n""       # ifenslave {-h|--help}    This message\n""\n";#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <linux/if.h>#include <net/if_arp.h>#include <linux/if_ether.h>#include <linux/if_bonding.h>#include <linux/sockios.h>typedef unsigned long long u64;	/* hack, so we may include kernel's ethtool.h */typedef __uint32_t u32;		/* ditto */typedef __uint16_t u16;		/* ditto */typedef __uint8_t u8;		/* ditto */#include <linux/ethtool.h>struct option longopts[] = {	/* { name  has_arg  *flag  val } */	{"all-interfaces",	0, 0, 'a'},	/* Show all interfaces. */	{"change-active",	0, 0, 'c'},	/* Change the active slave.  */	{"detach",		0, 0, 'd'},	/* Detach a slave interface. */	{"force",		0, 0, 'f'},	/* Force the operation. */	{"help",		0, 0, 'h'},	/* Give help */	{"usage",		0, 0, 'u'},	/* Give usage */	{"verbose",		0, 0, 'v'},	/* Report each action taken. */	{"version",		0, 0, 'V'},	/* Emit version information. */	{ 0, 0, 0, 0}};/* Command-line flags. */unsigned intopt_a = 0,	/* Show-all-interfaces flag. */opt_c = 0,	/* Change-active-slave flag. */opt_d = 0,	/* Detach a slave interface. */opt_f = 0,	/* Force the operation. */opt_h = 0,	/* Help */opt_u = 0,	/* Usage */opt_v = 0,	/* Verbose flag. */opt_V = 0;	/* Version */int skfd = -1;		/* AF_INET socket for ioctl() calls.*/int abi_ver = 0;	/* userland - kernel ABI version */int hwaddr_set = 0;	/* Master's hwaddr is set */int saved_errno;struct ifreq master_mtu, master_flags, master_hwaddr;struct ifreq slave_mtu, slave_flags, slave_hwaddr;struct dev_ifr {	struct ifreq *req_ifr;	char *req_name;	int req_type;};struct dev_ifr master_ifra[] = {	{&master_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},	{&master_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},	{&master_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},	{NULL, "", 0}};struct dev_ifr slave_ifra[] = {	{&slave_mtu,     "SIOCGIFMTU",     SIOCGIFMTU},	{&slave_flags,   "SIOCGIFFLAGS",   SIOCGIFFLAGS},	{&slave_hwaddr,  "SIOCGIFHWADDR",  SIOCGIFHWADDR},	{NULL, "", 0}};static void if_print(char *ifname);static int get_drv_info(char *master_ifname);static int get_if_settings(char *ifname, struct dev_ifr ifra[]);static int get_slave_flags(char *slave_ifname);static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr);static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr);static int set_slave_mtu(char *slave_ifname, int mtu);static int set_if_flags(char *ifname, short flags);static int set_if_up(char *ifname, short flags);static int set_if_down(char *ifname, short flags);static int clear_if_addr(char *ifname);static int set_if_addr(char *master_ifname, char *slave_ifname);static int change_active(char *master_ifname, char *slave_ifname);static int enslave(char *master_ifname, char *slave_ifname);static int release(char *master_ifname, char *slave_ifname);#define v_print(fmt, args...)	\	if (opt_v)		\		fprintf(stderr, fmt, ## args )int main(int argc, char *argv[]){	char **spp, *master_ifname, *slave_ifname;	int c, i, rv;	int res = 0;	int exclusive = 0;	while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {		switch (c) {		case 'a': opt_a++; exclusive++; break;		case 'c': opt_c++; exclusive++; break;		case 'd': opt_d++; exclusive++; break;		case 'f': opt_f++; exclusive++; break;		case 'h': opt_h++; exclusive++; break;		case 'u': opt_u++; exclusive++; break;		case 'v': opt_v++; break;		case 'V': opt_V++; exclusive++; break;		case '?':			fprintf(stderr, usage_msg);			res = 2;			goto out;		}	}	/* options check */	if (exclusive > 1) {		fprintf(stderr, usage_msg);		res = 2;		goto out;	}	if (opt_v || opt_V) {		printf(version);		if (opt_V) {			res = 0;			goto out;		}	}	if (opt_u) {		printf(usage_msg);		res = 0;		goto out;	}	if (opt_h) {		printf(usage_msg);		printf(help_msg);		res = 0;		goto out;	}	/* Open a basic socket */	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {		perror("socket");		res = 1;		goto out;	}	if (opt_a) {		if (optind == argc) {			/* No remaining args */			/* show all interfaces */			if_print((char *)NULL);			goto out;		} else {			/* Just show usage */			fprintf(stderr, usage_msg);			res = 2;			goto out;		}	}	/* Copy the interface name */	spp = argv + optind;	master_ifname = *spp++;	if (master_ifname == NULL) {		fprintf(stderr, usage_msg);		res = 2;		goto out;	}	/* exchange abi version with bonding module */	res = get_drv_info(master_ifname);	if (res) {		fprintf(stderr,			"Master '%s': Error: handshake with driver failed. "			"Aborting\n",			master_ifname);		goto out;	}	slave_ifname = *spp++;	if (slave_ifname == NULL) {		if (opt_d || opt_c) {			fprintf(stderr, usage_msg);			res = 2;			goto out;		}		/* A single arg means show the		 * configuration for this interface		 */		if_print(master_ifname);		goto out;	}	res = get_if_settings(master_ifname, master_ifra);	if (res) {		/* Probably a good reason not to go on */		fprintf(stderr,			"Master '%s': Error: get settings failed: %s. "			"Aborting\n",			master_ifname, strerror(res));		goto out;	}	/* check if master is indeed a master;	 * if not then fail any operation	 */	if (!(master_flags.ifr_flags & IFF_MASTER)) {		fprintf(stderr,			"Illegal operation; the specified interface '%s' "			"is not a master. Aborting\n",			master_ifname);		res = 1;		goto out;	}	/* check if master is up; if not then fail any operation */	if (!(master_flags.ifr_flags & IFF_UP)) {		fprintf(stderr,			"Illegal operation; the specified master interface "			"'%s' is not up.\n",			master_ifname);		res = 1;		goto out;	}	/* Only for enslaving */	if (!opt_c && !opt_d) {		sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;		unsigned char *hwaddr =			(unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;		/* The family '1' is ARPHRD_ETHER for ethernet. */		if (master_family != 1 && !opt_f) {			fprintf(stderr,				"Illegal operation: The specified master "				"interface '%s' is not ethernet-like.\n "				"This program is designed to work with "				"ethernet-like network interfaces.\n "				"Use the '-f' option to force the "				"operation.\n",				master_ifname);			res = 1;			goto out;		}		/* Check master's hw addr */		for (i = 0; i < 6; i++) {			if (hwaddr[i] != 0) {				hwaddr_set = 1;				break;			}		}		if (hwaddr_set) {			v_print("current hardware address of master '%s' "				"is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "				"type %d\n",				master_ifname,				hwaddr[0], hwaddr[1],				hwaddr[2], hwaddr[3],				hwaddr[4], hwaddr[5],				master_family);		}	}	/* Accepts only one slave */	if (opt_c) {		/* change active slave */		res = get_slave_flags(slave_ifname);		if (res) {			fprintf(stderr,				"Slave '%s': Error: get flags failed. "				"Aborting\n",				slave_ifname);			goto out;		}		res = change_active(master_ifname, slave_ifname);		if (res) {			fprintf(stderr,				"Master '%s', Slave '%s': Error: "				"Change active failed\n",				master_ifname, slave_ifname);		}	} else {		/* Accept multiple slaves */		do {			if (opt_d) {				/* detach a slave interface from the master */				rv = get_slave_flags(slave_ifname);				if (rv) {					/* Can't work with this slave. */					/* remember the error and skip it*/					fprintf(stderr,						"Slave '%s': Error: get flags "						"failed. Skipping\n",						slave_ifname);					res = rv;					continue;				}				rv = release(master_ifname, slave_ifname);				if (rv) {					fprintf(stderr,						"Master '%s', Slave '%s': Error: "						"Release failed\n",						master_ifname, slave_ifname);					res = rv;				}			} else {				/* attach a slave interface to the master */				rv = get_if_settings(slave_ifname, slave_ifra);				if (rv) {					/* Can't work with this slave. */					/* remember the error and skip it*/					fprintf(stderr,						"Slave '%s': Error: get "						"settings failed: %s. "						"Skipping\n",						slave_ifname, strerror(rv));					res = rv;					continue;				}				rv = enslave(master_ifname, slave_ifname);				if (rv) {					fprintf(stderr,						"Master '%s', Slave '%s': Error: "						"Enslave failed\n",						master_ifname, slave_ifname);					res = rv;				}			}		} while ((slave_ifname = *spp++) != NULL);	}out:	if (skfd >= 0) {		close(skfd);	}	return res;}static short mif_flags;/* Get the inteface configuration from the kernel. */static int if_getconfig(char *ifname){	struct ifreq ifr;	int metric, mtu;	/* Parameters of the master interface. */	struct sockaddr dstaddr, broadaddr, netmask;	unsigned char *hwaddr;	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)		return -1;	mif_flags = ifr.ifr_flags;	printf("The result of SIOCGIFFLAGS on %s is %x.\n",	       ifname, ifr.ifr_flags);	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)		return -1;	printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",	       ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],	       ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)		return -1;	/* Gotta convert from 'char' to unsigned for printf(). */	hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;	printf("The result of SIOCGIFHWADDR is type %d  "	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",	       ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],	       hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {		metric = 0;	} else		metric = ifr.ifr_metric;	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)		mtu = 0;	else		mtu = ifr.ifr_mtu;	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {		memset(&dstaddr, 0, sizeof(struct sockaddr));	} else

⌨️ 快捷键说明

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