Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bonding: remove ifenslave.c from kernel source

As Stephen proposed:
Since bonding supports configuration via iproute (netlink) and sysfs, I think
it is time to purge the old ifenslave code out of Documentation/networking
and update the documentation.

Suggested-by: Stephen Hemminger <stephen@networkplumber.org>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Jay Vosburgh <fubar@us.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Cong Wang and committed by
David S. Miller
b1098bbe 3dd17ede

+10 -1157
-1
Documentation/networking/.gitignore
··· 1 - ifenslave
-2
Documentation/networking/00-INDEX
··· 88 88 - Gianfar Ethernet Driver. 89 89 ieee802154.txt 90 90 - Linux IEEE 802.15.4 implementation, API and drivers 91 - ifenslave.c 92 - - Configure network interfaces for parallel routing (bonding). 93 91 igb.txt 94 92 - README for the Intel Gigabit Ethernet Driver (igb). 95 93 igbvf.txt
-5
Documentation/networking/Makefile
··· 1 1 # kbuild trick to avoid linker error. Can be omitted if a module is built. 2 2 obj- := dummy.o 3 3 4 - # List of programs to build 5 - hostprogs-y := ifenslave 6 - 7 - HOSTCFLAGS_ifenslave.o += -I$(objtree)/usr/include 8 - 9 4 # Tell kbuild to always build the programs 10 5 always := $(hostprogs-y) 11 6
+10 -44
Documentation/networking/bonding.txt
··· 104 104 ============================== 105 105 106 106 Most popular distro kernels ship with the bonding driver 107 - already available as a module and the ifenslave user level control 108 - program installed and ready for use. If your distro does not, or you 107 + already available as a module. If your distro does not, or you 109 108 have need to compile bonding from source (e.g., configuring and 110 109 installing a mainline kernel from kernel.org), you'll need to perform 111 110 the following steps: ··· 123 124 driver as module since it is currently the only way to pass parameters 124 125 to the driver or configure more than one bonding device. 125 126 126 - Build and install the new kernel and modules, then continue 127 - below to install ifenslave. 127 + Build and install the new kernel and modules. 128 128 129 - 1.2 Install ifenslave Control Utility 129 + 1.2 Bonding Control Utility 130 130 ------------------------------------- 131 131 132 - The ifenslave user level control program is included in the 133 - kernel source tree, in the file Documentation/networking/ifenslave.c. 134 - It is generally recommended that you use the ifenslave that 135 - corresponds to the kernel that you are using (either from the same 136 - source tree or supplied with the distro), however, ifenslave 137 - executables from older kernels should function (but features newer 138 - than the ifenslave release are not supported). Running an ifenslave 139 - that is newer than the kernel is not supported, and may or may not 140 - work. 141 - 142 - To install ifenslave, do the following: 143 - 144 - # gcc -Wall -O -I/usr/src/linux/include ifenslave.c -o ifenslave 145 - # cp ifenslave /sbin/ifenslave 146 - 147 - If your kernel source is not in "/usr/src/linux," then replace 148 - "/usr/src/linux/include" in the above with the location of your kernel 149 - source include directory. 150 - 151 - You may wish to back up any existing /sbin/ifenslave, or, for 152 - testing or informal use, tag the ifenslave to the kernel version 153 - (e.g., name the ifenslave executable /sbin/ifenslave-2.6.10). 154 - 155 - IMPORTANT NOTE: 156 - 157 - If you omit the "-I" or specify an incorrect directory, you 158 - may end up with an ifenslave that is incompatible with the kernel 159 - you're trying to build it for. Some distros (e.g., Red Hat from 7.1 160 - onwards) do not have /usr/include/linux symbolically linked to the 161 - default kernel source include directory. 162 - 163 - SECOND IMPORTANT NOTE: 164 - If you plan to configure bonding using sysfs or using the 165 - /etc/network/interfaces file, you do not need to use ifenslave. 132 + It is recommended to configure bonding via iproute2 (netlink) 133 + or sysfs, the old ifenslave control utility is obsolete. 166 134 167 135 2. Bonding Driver Options 168 136 ========================= ··· 817 851 ============================== 818 852 819 853 You can configure bonding using either your distro's network 820 - initialization scripts, or manually using either ifenslave or the 854 + initialization scripts, or manually using either iproute2 or the 821 855 sysfs interface. Distros generally use one of three packages for the 822 856 network initialization scripts: initscripts, sysconfig or interfaces. 823 857 Recent versions of these packages have support for bonding, while older ··· 1126 1160 those instances, see the "Configuring Multiple Bonds Manually" section, 1127 1161 below. 1128 1162 1129 - 3.3 Configuring Bonding Manually with Ifenslave 1163 + 3.3 Configuring Bonding Manually with iproute2 1130 1164 ----------------------------------------------- 1131 1165 1132 1166 This section applies to distros whose network initialization ··· 1137 1171 The general method for these systems is to place the bonding 1138 1172 module parameters into a config file in /etc/modprobe.d/ (as 1139 1173 appropriate for the installed distro), then add modprobe and/or 1140 - ifenslave commands to the system's global init script. The name of 1174 + `ip link` commands to the system's global init script. The name of 1141 1175 the global init script differs; for sysconfig, it is 1142 1176 /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local. 1143 1177 ··· 1149 1183 modprobe bonding mode=balance-alb miimon=100 1150 1184 modprobe e100 1151 1185 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up 1152 - ifenslave bond0 eth0 1153 - ifenslave bond0 eth1 1186 + ip link set eth0 master bond0 1187 + ip link set eth1 master bond0 1154 1188 1155 1189 Replace the example bonding module parameters and bond0 1156 1190 network configuration (IP address, netmask, etc) with the appropriate
-1105
Documentation/networking/ifenslave.c
··· 1 - /* Mode: C; 2 - * ifenslave.c: Configure network interfaces for parallel routing. 3 - * 4 - * This program controls the Linux implementation of running multiple 5 - * network interfaces in parallel. 6 - * 7 - * Author: Donald Becker <becker@cesdis.gsfc.nasa.gov> 8 - * Copyright 1994-1996 Donald Becker 9 - * 10 - * This program is free software; you can redistribute it 11 - * and/or modify it under the terms of the GNU General Public 12 - * License as published by the Free Software Foundation. 13 - * 14 - * The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O 15 - * Center of Excellence in Space Data and Information Sciences 16 - * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 17 - * 18 - * Changes : 19 - * - 2000/10/02 Willy Tarreau <willy at meta-x.org> : 20 - * - few fixes. Master's MAC address is now correctly taken from 21 - * the first device when not previously set ; 22 - * - detach support : call BOND_RELEASE to detach an enslaved interface. 23 - * - give a mini-howto from command-line help : # ifenslave -h 24 - * 25 - * - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> : 26 - * - Master is now brought down before setting the MAC address. In 27 - * the 2.4 kernel you can't change the MAC address while the device is 28 - * up because you get EBUSY. 29 - * 30 - * - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com> 31 - * - Added the ability to change the active interface on a mode 1 bond 32 - * at runtime. 33 - * 34 - * - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> : 35 - * - No longer set the MAC address of the master. The bond device will 36 - * take care of this itself 37 - * - Try the SIOC*** versions of the bonding ioctls before using the 38 - * old versions 39 - * - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> : 40 - * - ifr2.ifr_flags was not initialized in the hwaddr_notset case, 41 - * SIOCGIFFLAGS now called before hwaddr_notset test 42 - * 43 - * - 2002/10/31 Tony Cureington <tony.cureington * hp_com> : 44 - * - If the master does not have a hardware address when the first slave 45 - * is enslaved, the master is assigned the hardware address of that 46 - * slave - there is a comment in bonding.c stating "ifenslave takes 47 - * care of this now." This corrects the problem of slaves having 48 - * different hardware addresses in active-backup mode when 49 - * multiple interfaces are specified on a single ifenslave command 50 - * (ifenslave bond0 eth0 eth1). 51 - * 52 - * - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and 53 - * Shmulik Hen <shmulik.hen at intel dot com> 54 - * - Moved setting the slave's mac address and openning it, from 55 - * the application to the driver. This enables support of modes 56 - * that need to use the unique mac address of each slave. 57 - * The driver also takes care of closing the slave and restoring its 58 - * original mac address upon release. 59 - * In addition, block possibility of enslaving before the master is up. 60 - * This prevents putting the system in an undefined state. 61 - * 62 - * - 2003/05/01 - Amir Noam <amir.noam at intel dot com> 63 - * - Added ABI version control to restore compatibility between 64 - * new/old ifenslave and new/old bonding. 65 - * - Prevent adding an adapter that is already a slave. 66 - * Fixes the problem of stalling the transmission and leaving 67 - * the slave in a down state. 68 - * 69 - * - 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com> 70 - * - Prevent enslaving if the bond device is down. 71 - * Fixes the problem of leaving the system in unstable state and 72 - * halting when trying to remove the module. 73 - * - Close socket on all abnormal exists. 74 - * - Add versioning scheme that follows that of the bonding driver. 75 - * current version is 1.0.0 as a base line. 76 - * 77 - * - 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com> 78 - * - ifenslave -c was broken; it's now fixed 79 - * - Fixed problem with routes vanishing from master during enslave 80 - * processing. 81 - * 82 - * - 2003/05/27 - Amir Noam <amir.noam at intel dot com> 83 - * - Fix backward compatibility issues: 84 - * For drivers not using ABI versions, slave was set down while 85 - * it should be left up before enslaving. 86 - * Also, master was not set down and the default set_mac_address() 87 - * would fail and generate an error message in the system log. 88 - * - For opt_c: slave should not be set to the master's setting 89 - * while it is running. It was already set during enslave. To 90 - * simplify things, it is now handled separately. 91 - * 92 - * - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> 93 - * - Code cleanup and style changes 94 - * set version to 1.1.0 95 - */ 96 - 97 - #define APP_VERSION "1.1.0" 98 - #define APP_RELDATE "December 1, 2003" 99 - #define APP_NAME "ifenslave" 100 - 101 - static char *version = 102 - APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n" 103 - "o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n" 104 - "o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n" 105 - "o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n" 106 - " (ctindel at ieee dot org).\n"; 107 - 108 - static const char *usage_msg = 109 - "Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n" 110 - " ifenslave -d <master-if> <slave-if> [<slave-if>...]\n" 111 - " ifenslave -c <master-if> <slave-if>\n" 112 - " ifenslave --help\n"; 113 - 114 - static const char *help_msg = 115 - "\n" 116 - " To create a bond device, simply follow these three steps :\n" 117 - " - ensure that the required drivers are properly loaded :\n" 118 - " # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n" 119 - " - assign an IP address to the bond device :\n" 120 - " # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n" 121 - " - attach all the interfaces you need to the bond device :\n" 122 - " # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n" 123 - " If bond0 didn't have a MAC address, it will take eth0's. Then, all\n" 124 - " interfaces attached AFTER this assignment will get the same MAC addr.\n" 125 - " (except for ALB/TLB modes)\n" 126 - "\n" 127 - " To set the bond device down and automatically release all the slaves :\n" 128 - " # ifconfig bond0 down\n" 129 - "\n" 130 - " To detach a dead interface without setting the bond device down :\n" 131 - " # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n" 132 - "\n" 133 - " To change active slave :\n" 134 - " # ifenslave {-c|--change-active} bond0 eth0\n" 135 - "\n" 136 - " To show master interface info\n" 137 - " # ifenslave bond0\n" 138 - "\n" 139 - " To show all interfaces info\n" 140 - " # ifenslave {-a|--all-interfaces}\n" 141 - "\n" 142 - " To be more verbose\n" 143 - " # ifenslave {-v|--verbose} ...\n" 144 - "\n" 145 - " # ifenslave {-u|--usage} Show usage\n" 146 - " # ifenslave {-V|--version} Show version\n" 147 - " # ifenslave {-h|--help} This message\n" 148 - "\n"; 149 - 150 - #include <unistd.h> 151 - #include <stdlib.h> 152 - #include <stdio.h> 153 - #include <ctype.h> 154 - #include <string.h> 155 - #include <errno.h> 156 - #include <fcntl.h> 157 - #include <getopt.h> 158 - #include <sys/types.h> 159 - #include <sys/socket.h> 160 - #include <sys/ioctl.h> 161 - #include <linux/if.h> 162 - #include <net/if_arp.h> 163 - #include <linux/if_ether.h> 164 - #include <linux/if_bonding.h> 165 - #include <linux/sockios.h> 166 - 167 - typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */ 168 - typedef __uint32_t u32; /* ditto */ 169 - typedef __uint16_t u16; /* ditto */ 170 - typedef __uint8_t u8; /* ditto */ 171 - #include <linux/ethtool.h> 172 - 173 - struct option longopts[] = { 174 - /* { name has_arg *flag val } */ 175 - {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */ 176 - {"change-active", 0, 0, 'c'}, /* Change the active slave. */ 177 - {"detach", 0, 0, 'd'}, /* Detach a slave interface. */ 178 - {"force", 0, 0, 'f'}, /* Force the operation. */ 179 - {"help", 0, 0, 'h'}, /* Give help */ 180 - {"usage", 0, 0, 'u'}, /* Give usage */ 181 - {"verbose", 0, 0, 'v'}, /* Report each action taken. */ 182 - {"version", 0, 0, 'V'}, /* Emit version information. */ 183 - { 0, 0, 0, 0} 184 - }; 185 - 186 - /* Command-line flags. */ 187 - unsigned int 188 - opt_a = 0, /* Show-all-interfaces flag. */ 189 - opt_c = 0, /* Change-active-slave flag. */ 190 - opt_d = 0, /* Detach a slave interface. */ 191 - opt_f = 0, /* Force the operation. */ 192 - opt_h = 0, /* Help */ 193 - opt_u = 0, /* Usage */ 194 - opt_v = 0, /* Verbose flag. */ 195 - opt_V = 0; /* Version */ 196 - 197 - int skfd = -1; /* AF_INET socket for ioctl() calls.*/ 198 - int abi_ver = 0; /* userland - kernel ABI version */ 199 - int hwaddr_set = 0; /* Master's hwaddr is set */ 200 - int saved_errno; 201 - 202 - struct ifreq master_mtu, master_flags, master_hwaddr; 203 - struct ifreq slave_mtu, slave_flags, slave_hwaddr; 204 - 205 - struct dev_ifr { 206 - struct ifreq *req_ifr; 207 - char *req_name; 208 - int req_type; 209 - }; 210 - 211 - struct dev_ifr master_ifra[] = { 212 - {&master_mtu, "SIOCGIFMTU", SIOCGIFMTU}, 213 - {&master_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, 214 - {&master_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, 215 - {NULL, "", 0} 216 - }; 217 - 218 - struct dev_ifr slave_ifra[] = { 219 - {&slave_mtu, "SIOCGIFMTU", SIOCGIFMTU}, 220 - {&slave_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, 221 - {&slave_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, 222 - {NULL, "", 0} 223 - }; 224 - 225 - static void if_print(char *ifname); 226 - static int get_drv_info(char *master_ifname); 227 - static int get_if_settings(char *ifname, struct dev_ifr ifra[]); 228 - static int get_slave_flags(char *slave_ifname); 229 - static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr); 230 - static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr); 231 - static int set_slave_mtu(char *slave_ifname, int mtu); 232 - static int set_if_flags(char *ifname, short flags); 233 - static int set_if_up(char *ifname, short flags); 234 - static int set_if_down(char *ifname, short flags); 235 - static int clear_if_addr(char *ifname); 236 - static int set_if_addr(char *master_ifname, char *slave_ifname); 237 - static int change_active(char *master_ifname, char *slave_ifname); 238 - static int enslave(char *master_ifname, char *slave_ifname); 239 - static int release(char *master_ifname, char *slave_ifname); 240 - #define v_print(fmt, args...) \ 241 - if (opt_v) \ 242 - fprintf(stderr, fmt, ## args ) 243 - 244 - int main(int argc, char *argv[]) 245 - { 246 - char **spp, *master_ifname, *slave_ifname; 247 - int c, i, rv; 248 - int res = 0; 249 - int exclusive = 0; 250 - 251 - while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) { 252 - switch (c) { 253 - case 'a': opt_a++; exclusive++; break; 254 - case 'c': opt_c++; exclusive++; break; 255 - case 'd': opt_d++; exclusive++; break; 256 - case 'f': opt_f++; exclusive++; break; 257 - case 'h': opt_h++; exclusive++; break; 258 - case 'u': opt_u++; exclusive++; break; 259 - case 'v': opt_v++; break; 260 - case 'V': opt_V++; exclusive++; break; 261 - 262 - case '?': 263 - fprintf(stderr, "%s", usage_msg); 264 - res = 2; 265 - goto out; 266 - } 267 - } 268 - 269 - /* options check */ 270 - if (exclusive > 1) { 271 - fprintf(stderr, "%s", usage_msg); 272 - res = 2; 273 - goto out; 274 - } 275 - 276 - if (opt_v || opt_V) { 277 - printf("%s", version); 278 - if (opt_V) { 279 - res = 0; 280 - goto out; 281 - } 282 - } 283 - 284 - if (opt_u) { 285 - printf("%s", usage_msg); 286 - res = 0; 287 - goto out; 288 - } 289 - 290 - if (opt_h) { 291 - printf("%s", usage_msg); 292 - printf("%s", help_msg); 293 - res = 0; 294 - goto out; 295 - } 296 - 297 - /* Open a basic socket */ 298 - if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 299 - perror("socket"); 300 - res = 1; 301 - goto out; 302 - } 303 - 304 - if (opt_a) { 305 - if (optind == argc) { 306 - /* No remaining args */ 307 - /* show all interfaces */ 308 - if_print((char *)NULL); 309 - goto out; 310 - } else { 311 - /* Just show usage */ 312 - fprintf(stderr, "%s", usage_msg); 313 - res = 2; 314 - goto out; 315 - } 316 - } 317 - 318 - /* Copy the interface name */ 319 - spp = argv + optind; 320 - master_ifname = *spp++; 321 - 322 - if (master_ifname == NULL) { 323 - fprintf(stderr, "%s", usage_msg); 324 - res = 2; 325 - goto out; 326 - } 327 - 328 - /* exchange abi version with bonding module */ 329 - res = get_drv_info(master_ifname); 330 - if (res) { 331 - fprintf(stderr, 332 - "Master '%s': Error: handshake with driver failed. " 333 - "Aborting\n", 334 - master_ifname); 335 - goto out; 336 - } 337 - 338 - slave_ifname = *spp++; 339 - 340 - if (slave_ifname == NULL) { 341 - if (opt_d || opt_c) { 342 - fprintf(stderr, "%s", usage_msg); 343 - res = 2; 344 - goto out; 345 - } 346 - 347 - /* A single arg means show the 348 - * configuration for this interface 349 - */ 350 - if_print(master_ifname); 351 - goto out; 352 - } 353 - 354 - res = get_if_settings(master_ifname, master_ifra); 355 - if (res) { 356 - /* Probably a good reason not to go on */ 357 - fprintf(stderr, 358 - "Master '%s': Error: get settings failed: %s. " 359 - "Aborting\n", 360 - master_ifname, strerror(res)); 361 - goto out; 362 - } 363 - 364 - /* check if master is indeed a master; 365 - * if not then fail any operation 366 - */ 367 - if (!(master_flags.ifr_flags & IFF_MASTER)) { 368 - fprintf(stderr, 369 - "Illegal operation; the specified interface '%s' " 370 - "is not a master. Aborting\n", 371 - master_ifname); 372 - res = 1; 373 - goto out; 374 - } 375 - 376 - /* check if master is up; if not then fail any operation */ 377 - if (!(master_flags.ifr_flags & IFF_UP)) { 378 - fprintf(stderr, 379 - "Illegal operation; the specified master interface " 380 - "'%s' is not up.\n", 381 - master_ifname); 382 - res = 1; 383 - goto out; 384 - } 385 - 386 - /* Only for enslaving */ 387 - if (!opt_c && !opt_d) { 388 - sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family; 389 - unsigned char *hwaddr = 390 - (unsigned char *)master_hwaddr.ifr_hwaddr.sa_data; 391 - 392 - /* The family '1' is ARPHRD_ETHER for ethernet. */ 393 - if (master_family != 1 && !opt_f) { 394 - fprintf(stderr, 395 - "Illegal operation: The specified master " 396 - "interface '%s' is not ethernet-like.\n " 397 - "This program is designed to work with " 398 - "ethernet-like network interfaces.\n " 399 - "Use the '-f' option to force the " 400 - "operation.\n", 401 - master_ifname); 402 - res = 1; 403 - goto out; 404 - } 405 - 406 - /* Check master's hw addr */ 407 - for (i = 0; i < 6; i++) { 408 - if (hwaddr[i] != 0) { 409 - hwaddr_set = 1; 410 - break; 411 - } 412 - } 413 - 414 - if (hwaddr_set) { 415 - v_print("current hardware address of master '%s' " 416 - "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " 417 - "type %d\n", 418 - master_ifname, 419 - hwaddr[0], hwaddr[1], 420 - hwaddr[2], hwaddr[3], 421 - hwaddr[4], hwaddr[5], 422 - master_family); 423 - } 424 - } 425 - 426 - /* Accepts only one slave */ 427 - if (opt_c) { 428 - /* change active slave */ 429 - res = get_slave_flags(slave_ifname); 430 - if (res) { 431 - fprintf(stderr, 432 - "Slave '%s': Error: get flags failed. " 433 - "Aborting\n", 434 - slave_ifname); 435 - goto out; 436 - } 437 - res = change_active(master_ifname, slave_ifname); 438 - if (res) { 439 - fprintf(stderr, 440 - "Master '%s', Slave '%s': Error: " 441 - "Change active failed\n", 442 - master_ifname, slave_ifname); 443 - } 444 - } else { 445 - /* Accept multiple slaves */ 446 - do { 447 - if (opt_d) { 448 - /* detach a slave interface from the master */ 449 - rv = get_slave_flags(slave_ifname); 450 - if (rv) { 451 - /* Can't work with this slave. */ 452 - /* remember the error and skip it*/ 453 - fprintf(stderr, 454 - "Slave '%s': Error: get flags " 455 - "failed. Skipping\n", 456 - slave_ifname); 457 - res = rv; 458 - continue; 459 - } 460 - rv = release(master_ifname, slave_ifname); 461 - if (rv) { 462 - fprintf(stderr, 463 - "Master '%s', Slave '%s': Error: " 464 - "Release failed\n", 465 - master_ifname, slave_ifname); 466 - res = rv; 467 - } 468 - } else { 469 - /* attach a slave interface to the master */ 470 - rv = get_if_settings(slave_ifname, slave_ifra); 471 - if (rv) { 472 - /* Can't work with this slave. */ 473 - /* remember the error and skip it*/ 474 - fprintf(stderr, 475 - "Slave '%s': Error: get " 476 - "settings failed: %s. " 477 - "Skipping\n", 478 - slave_ifname, strerror(rv)); 479 - res = rv; 480 - continue; 481 - } 482 - rv = enslave(master_ifname, slave_ifname); 483 - if (rv) { 484 - fprintf(stderr, 485 - "Master '%s', Slave '%s': Error: " 486 - "Enslave failed\n", 487 - master_ifname, slave_ifname); 488 - res = rv; 489 - } 490 - } 491 - } while ((slave_ifname = *spp++) != NULL); 492 - } 493 - 494 - out: 495 - if (skfd >= 0) { 496 - close(skfd); 497 - } 498 - 499 - return res; 500 - } 501 - 502 - static short mif_flags; 503 - 504 - /* Get the interface configuration from the kernel. */ 505 - static int if_getconfig(char *ifname) 506 - { 507 - struct ifreq ifr; 508 - int metric, mtu; /* Parameters of the master interface. */ 509 - struct sockaddr dstaddr, broadaddr, netmask; 510 - unsigned char *hwaddr; 511 - 512 - strcpy(ifr.ifr_name, ifname); 513 - if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) 514 - return -1; 515 - mif_flags = ifr.ifr_flags; 516 - printf("The result of SIOCGIFFLAGS on %s is %x.\n", 517 - ifname, ifr.ifr_flags); 518 - 519 - strcpy(ifr.ifr_name, ifname); 520 - if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) 521 - return -1; 522 - printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n", 523 - ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1], 524 - ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]); 525 - 526 - strcpy(ifr.ifr_name, ifname); 527 - if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) 528 - return -1; 529 - 530 - /* Gotta convert from 'char' to unsigned for printf(). */ 531 - hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data; 532 - printf("The result of SIOCGIFHWADDR is type %d " 533 - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", 534 - ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], 535 - hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); 536 - 537 - strcpy(ifr.ifr_name, ifname); 538 - if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) { 539 - metric = 0; 540 - } else 541 - metric = ifr.ifr_metric; 542 - printf("The result of SIOCGIFMETRIC is %d\n", metric); 543 - 544 - strcpy(ifr.ifr_name, ifname); 545 - if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) 546 - mtu = 0; 547 - else 548 - mtu = ifr.ifr_mtu; 549 - printf("The result of SIOCGIFMTU is %d\n", mtu); 550 - 551 - strcpy(ifr.ifr_name, ifname); 552 - if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) { 553 - memset(&dstaddr, 0, sizeof(struct sockaddr)); 554 - } else 555 - dstaddr = ifr.ifr_dstaddr; 556 - 557 - strcpy(ifr.ifr_name, ifname); 558 - if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) { 559 - memset(&broadaddr, 0, sizeof(struct sockaddr)); 560 - } else 561 - broadaddr = ifr.ifr_broadaddr; 562 - 563 - strcpy(ifr.ifr_name, ifname); 564 - if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) { 565 - memset(&netmask, 0, sizeof(struct sockaddr)); 566 - } else 567 - netmask = ifr.ifr_netmask; 568 - 569 - return 0; 570 - } 571 - 572 - static void if_print(char *ifname) 573 - { 574 - char buff[1024]; 575 - struct ifconf ifc; 576 - struct ifreq *ifr; 577 - int i; 578 - 579 - if (ifname == (char *)NULL) { 580 - ifc.ifc_len = sizeof(buff); 581 - ifc.ifc_buf = buff; 582 - if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { 583 - perror("SIOCGIFCONF failed"); 584 - return; 585 - } 586 - 587 - ifr = ifc.ifc_req; 588 - for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { 589 - if (if_getconfig(ifr->ifr_name) < 0) { 590 - fprintf(stderr, 591 - "%s: unknown interface.\n", 592 - ifr->ifr_name); 593 - continue; 594 - } 595 - 596 - if (((mif_flags & IFF_UP) == 0) && !opt_a) continue; 597 - /*ife_print(&ife);*/ 598 - } 599 - } else { 600 - if (if_getconfig(ifname) < 0) { 601 - fprintf(stderr, 602 - "%s: unknown interface.\n", ifname); 603 - } 604 - } 605 - } 606 - 607 - static int get_drv_info(char *master_ifname) 608 - { 609 - struct ifreq ifr; 610 - struct ethtool_drvinfo info; 611 - char *endptr; 612 - 613 - memset(&ifr, 0, sizeof(ifr)); 614 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 615 - ifr.ifr_data = (caddr_t)&info; 616 - 617 - info.cmd = ETHTOOL_GDRVINFO; 618 - strncpy(info.driver, "ifenslave", 32); 619 - snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); 620 - 621 - if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) { 622 - if (errno == EOPNOTSUPP) { 623 - goto out; 624 - } 625 - 626 - saved_errno = errno; 627 - v_print("Master '%s': Error: get bonding info failed %s\n", 628 - master_ifname, strerror(saved_errno)); 629 - return 1; 630 - } 631 - 632 - abi_ver = strtoul(info.fw_version, &endptr, 0); 633 - if (*endptr) { 634 - v_print("Master '%s': Error: got invalid string as an ABI " 635 - "version from the bonding module\n", 636 - master_ifname); 637 - return 1; 638 - } 639 - 640 - out: 641 - v_print("ABI ver is %d\n", abi_ver); 642 - 643 - return 0; 644 - } 645 - 646 - static int change_active(char *master_ifname, char *slave_ifname) 647 - { 648 - struct ifreq ifr; 649 - int res = 0; 650 - 651 - if (!(slave_flags.ifr_flags & IFF_SLAVE)) { 652 - fprintf(stderr, 653 - "Illegal operation: The specified slave interface " 654 - "'%s' is not a slave\n", 655 - slave_ifname); 656 - return 1; 657 - } 658 - 659 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 660 - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); 661 - if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) && 662 - (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) { 663 - saved_errno = errno; 664 - v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: " 665 - "%s\n", 666 - master_ifname, strerror(saved_errno)); 667 - res = 1; 668 - } 669 - 670 - return res; 671 - } 672 - 673 - static int enslave(char *master_ifname, char *slave_ifname) 674 - { 675 - struct ifreq ifr; 676 - int res = 0; 677 - 678 - if (slave_flags.ifr_flags & IFF_SLAVE) { 679 - fprintf(stderr, 680 - "Illegal operation: The specified slave interface " 681 - "'%s' is already a slave\n", 682 - slave_ifname); 683 - return 1; 684 - } 685 - 686 - res = set_if_down(slave_ifname, slave_flags.ifr_flags); 687 - if (res) { 688 - fprintf(stderr, 689 - "Slave '%s': Error: bring interface down failed\n", 690 - slave_ifname); 691 - return res; 692 - } 693 - 694 - if (abi_ver < 2) { 695 - /* Older bonding versions would panic if the slave has no IP 696 - * address, so get the IP setting from the master. 697 - */ 698 - set_if_addr(master_ifname, slave_ifname); 699 - } else { 700 - res = clear_if_addr(slave_ifname); 701 - if (res) { 702 - fprintf(stderr, 703 - "Slave '%s': Error: clear address failed\n", 704 - slave_ifname); 705 - return res; 706 - } 707 - } 708 - 709 - if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) { 710 - res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu); 711 - if (res) { 712 - fprintf(stderr, 713 - "Slave '%s': Error: set MTU failed\n", 714 - slave_ifname); 715 - return res; 716 - } 717 - } 718 - 719 - if (hwaddr_set) { 720 - /* Master already has an hwaddr 721 - * so set it's hwaddr to the slave 722 - */ 723 - if (abi_ver < 1) { 724 - /* The driver is using an old ABI, so 725 - * the application sets the slave's 726 - * hwaddr 727 - */ 728 - res = set_slave_hwaddr(slave_ifname, 729 - &(master_hwaddr.ifr_hwaddr)); 730 - if (res) { 731 - fprintf(stderr, 732 - "Slave '%s': Error: set hw address " 733 - "failed\n", 734 - slave_ifname); 735 - goto undo_mtu; 736 - } 737 - 738 - /* For old ABI the application needs to bring the 739 - * slave back up 740 - */ 741 - res = set_if_up(slave_ifname, slave_flags.ifr_flags); 742 - if (res) { 743 - fprintf(stderr, 744 - "Slave '%s': Error: bring interface " 745 - "down failed\n", 746 - slave_ifname); 747 - goto undo_slave_mac; 748 - } 749 - } 750 - /* The driver is using a new ABI, 751 - * so the driver takes care of setting 752 - * the slave's hwaddr and bringing 753 - * it up again 754 - */ 755 - } else { 756 - /* No hwaddr for master yet, so 757 - * set the slave's hwaddr to it 758 - */ 759 - if (abi_ver < 1) { 760 - /* For old ABI, the master needs to be 761 - * down before setting its hwaddr 762 - */ 763 - res = set_if_down(master_ifname, master_flags.ifr_flags); 764 - if (res) { 765 - fprintf(stderr, 766 - "Master '%s': Error: bring interface " 767 - "down failed\n", 768 - master_ifname); 769 - goto undo_mtu; 770 - } 771 - } 772 - 773 - res = set_master_hwaddr(master_ifname, 774 - &(slave_hwaddr.ifr_hwaddr)); 775 - if (res) { 776 - fprintf(stderr, 777 - "Master '%s': Error: set hw address " 778 - "failed\n", 779 - master_ifname); 780 - goto undo_mtu; 781 - } 782 - 783 - if (abi_ver < 1) { 784 - /* For old ABI, bring the master 785 - * back up 786 - */ 787 - res = set_if_up(master_ifname, master_flags.ifr_flags); 788 - if (res) { 789 - fprintf(stderr, 790 - "Master '%s': Error: bring interface " 791 - "up failed\n", 792 - master_ifname); 793 - goto undo_master_mac; 794 - } 795 - } 796 - 797 - hwaddr_set = 1; 798 - } 799 - 800 - /* Do the real thing */ 801 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 802 - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); 803 - if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) && 804 - (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) { 805 - saved_errno = errno; 806 - v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n", 807 - master_ifname, strerror(saved_errno)); 808 - res = 1; 809 - } 810 - 811 - if (res) { 812 - goto undo_master_mac; 813 - } 814 - 815 - return 0; 816 - 817 - /* rollback (best effort) */ 818 - undo_master_mac: 819 - set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr)); 820 - hwaddr_set = 0; 821 - goto undo_mtu; 822 - undo_slave_mac: 823 - set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr)); 824 - undo_mtu: 825 - set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu); 826 - return res; 827 - } 828 - 829 - static int release(char *master_ifname, char *slave_ifname) 830 - { 831 - struct ifreq ifr; 832 - int res = 0; 833 - 834 - if (!(slave_flags.ifr_flags & IFF_SLAVE)) { 835 - fprintf(stderr, 836 - "Illegal operation: The specified slave interface " 837 - "'%s' is not a slave\n", 838 - slave_ifname); 839 - return 1; 840 - } 841 - 842 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 843 - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); 844 - if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) && 845 - (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) { 846 - saved_errno = errno; 847 - v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n", 848 - master_ifname, strerror(saved_errno)); 849 - return 1; 850 - } else if (abi_ver < 1) { 851 - /* The driver is using an old ABI, so we'll set the interface 852 - * down to avoid any conflicts due to same MAC/IP 853 - */ 854 - res = set_if_down(slave_ifname, slave_flags.ifr_flags); 855 - if (res) { 856 - fprintf(stderr, 857 - "Slave '%s': Error: bring interface " 858 - "down failed\n", 859 - slave_ifname); 860 - } 861 - } 862 - 863 - /* set to default mtu */ 864 - set_slave_mtu(slave_ifname, 1500); 865 - 866 - return res; 867 - } 868 - 869 - static int get_if_settings(char *ifname, struct dev_ifr ifra[]) 870 - { 871 - int i; 872 - int res = 0; 873 - 874 - for (i = 0; ifra[i].req_ifr; i++) { 875 - strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ); 876 - res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr); 877 - if (res < 0) { 878 - saved_errno = errno; 879 - v_print("Interface '%s': Error: %s failed: %s\n", 880 - ifname, ifra[i].req_name, 881 - strerror(saved_errno)); 882 - 883 - return saved_errno; 884 - } 885 - } 886 - 887 - return 0; 888 - } 889 - 890 - static int get_slave_flags(char *slave_ifname) 891 - { 892 - int res = 0; 893 - 894 - strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ); 895 - res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags); 896 - if (res < 0) { 897 - saved_errno = errno; 898 - v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n", 899 - slave_ifname, strerror(saved_errno)); 900 - } else { 901 - v_print("Slave %s: flags %04X.\n", 902 - slave_ifname, slave_flags.ifr_flags); 903 - } 904 - 905 - return res; 906 - } 907 - 908 - static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr) 909 - { 910 - unsigned char *addr = (unsigned char *)hwaddr->sa_data; 911 - struct ifreq ifr; 912 - int res = 0; 913 - 914 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 915 - memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); 916 - res = ioctl(skfd, SIOCSIFHWADDR, &ifr); 917 - if (res < 0) { 918 - saved_errno = errno; 919 - v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n", 920 - master_ifname, strerror(saved_errno)); 921 - return res; 922 - } else { 923 - v_print("Master '%s': hardware address set to " 924 - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", 925 - master_ifname, addr[0], addr[1], addr[2], 926 - addr[3], addr[4], addr[5]); 927 - } 928 - 929 - return res; 930 - } 931 - 932 - static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr) 933 - { 934 - unsigned char *addr = (unsigned char *)hwaddr->sa_data; 935 - struct ifreq ifr; 936 - int res = 0; 937 - 938 - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); 939 - memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); 940 - res = ioctl(skfd, SIOCSIFHWADDR, &ifr); 941 - if (res < 0) { 942 - saved_errno = errno; 943 - 944 - v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n", 945 - slave_ifname, strerror(saved_errno)); 946 - 947 - if (saved_errno == EBUSY) { 948 - v_print(" The device is busy: it must be idle " 949 - "before running this command.\n"); 950 - } else if (saved_errno == EOPNOTSUPP) { 951 - v_print(" The device does not support setting " 952 - "the MAC address.\n" 953 - " Your kernel likely does not support slave " 954 - "devices.\n"); 955 - } else if (saved_errno == EINVAL) { 956 - v_print(" The device's address type does not match " 957 - "the master's address type.\n"); 958 - } 959 - return res; 960 - } else { 961 - v_print("Slave '%s': hardware address set to " 962 - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", 963 - slave_ifname, addr[0], addr[1], addr[2], 964 - addr[3], addr[4], addr[5]); 965 - } 966 - 967 - return res; 968 - } 969 - 970 - static int set_slave_mtu(char *slave_ifname, int mtu) 971 - { 972 - struct ifreq ifr; 973 - int res = 0; 974 - 975 - ifr.ifr_mtu = mtu; 976 - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); 977 - 978 - res = ioctl(skfd, SIOCSIFMTU, &ifr); 979 - if (res < 0) { 980 - saved_errno = errno; 981 - v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n", 982 - slave_ifname, strerror(saved_errno)); 983 - } else { 984 - v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu); 985 - } 986 - 987 - return res; 988 - } 989 - 990 - static int set_if_flags(char *ifname, short flags) 991 - { 992 - struct ifreq ifr; 993 - int res = 0; 994 - 995 - ifr.ifr_flags = flags; 996 - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 997 - 998 - res = ioctl(skfd, SIOCSIFFLAGS, &ifr); 999 - if (res < 0) { 1000 - saved_errno = errno; 1001 - v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n", 1002 - ifname, strerror(saved_errno)); 1003 - } else { 1004 - v_print("Interface '%s': flags set to %04X.\n", ifname, flags); 1005 - } 1006 - 1007 - return res; 1008 - } 1009 - 1010 - static int set_if_up(char *ifname, short flags) 1011 - { 1012 - return set_if_flags(ifname, flags | IFF_UP); 1013 - } 1014 - 1015 - static int set_if_down(char *ifname, short flags) 1016 - { 1017 - return set_if_flags(ifname, flags & ~IFF_UP); 1018 - } 1019 - 1020 - static int clear_if_addr(char *ifname) 1021 - { 1022 - struct ifreq ifr; 1023 - int res = 0; 1024 - 1025 - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 1026 - ifr.ifr_addr.sa_family = AF_INET; 1027 - memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); 1028 - 1029 - res = ioctl(skfd, SIOCSIFADDR, &ifr); 1030 - if (res < 0) { 1031 - saved_errno = errno; 1032 - v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n", 1033 - ifname, strerror(saved_errno)); 1034 - } else { 1035 - v_print("Interface '%s': address cleared\n", ifname); 1036 - } 1037 - 1038 - return res; 1039 - } 1040 - 1041 - static int set_if_addr(char *master_ifname, char *slave_ifname) 1042 - { 1043 - struct ifreq ifr; 1044 - int res; 1045 - unsigned char *ipaddr; 1046 - int i; 1047 - struct { 1048 - char *req_name; 1049 - char *desc; 1050 - int g_ioctl; 1051 - int s_ioctl; 1052 - } ifra[] = { 1053 - {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR}, 1054 - {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR}, 1055 - {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR}, 1056 - {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK}, 1057 - {NULL, NULL, 0, 0}, 1058 - }; 1059 - 1060 - for (i = 0; ifra[i].req_name; i++) { 1061 - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); 1062 - res = ioctl(skfd, ifra[i].g_ioctl, &ifr); 1063 - if (res < 0) { 1064 - int saved_errno = errno; 1065 - 1066 - v_print("Interface '%s': Error: SIOCG%s failed: %s\n", 1067 - master_ifname, ifra[i].req_name, 1068 - strerror(saved_errno)); 1069 - 1070 - ifr.ifr_addr.sa_family = AF_INET; 1071 - memset(ifr.ifr_addr.sa_data, 0, 1072 - sizeof(ifr.ifr_addr.sa_data)); 1073 - } 1074 - 1075 - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); 1076 - res = ioctl(skfd, ifra[i].s_ioctl, &ifr); 1077 - if (res < 0) { 1078 - int saved_errno = errno; 1079 - 1080 - v_print("Interface '%s': Error: SIOCS%s failed: %s\n", 1081 - slave_ifname, ifra[i].req_name, 1082 - strerror(saved_errno)); 1083 - 1084 - } 1085 - 1086 - ipaddr = (unsigned char *)ifr.ifr_addr.sa_data; 1087 - v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n", 1088 - slave_ifname, ifra[i].desc, 1089 - ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); 1090 - } 1091 - 1092 - return 0; 1093 - } 1094 - 1095 - /* 1096 - * Local variables: 1097 - * version-control: t 1098 - * kept-new-versions: 5 1099 - * c-indent-level: 4 1100 - * c-basic-offset: 4 1101 - * tab-width: 4 1102 - * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave" 1103 - * End: 1104 - */ 1105 -