static int enslave(char *master_ifname, char *slave_ifname)
{
	struct ifreq ifr;
	int res = 0;

	if (slave_flags.ifr_flags & IFF_SLAVE) {
		fprintf(stderr,
			"Illegal operation: The specified slave interface "
			"'%s' is already a slave\n",
			slave_ifname);
		return 1;
	}

	res = set_if_down(slave_ifname, slave_flags.ifr_flags);
	if (res) {
		fprintf(stderr,
			"Slave '%s': Error: bring interface down failed\n",
			slave_ifname);
		return res;
	}

	if (abi_ver < 2) {
		/* Older bonding versions would panic if the slave has no IP
		 * address, so get the IP setting from the master.
		 */
		set_if_addr(master_ifname, slave_ifname);
	} else {
		res = clear_if_addr(slave_ifname);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: clear address failed\n",
				slave_ifname);
			return res;
		}
	}

	if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
		res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: set MTU failed\n",
				slave_ifname);
			return res;
		}
	}

	if (hwaddr_set) {
		/* Master already has an hwaddr
		 * so set it's hwaddr to the slave
		 */
		if (abi_ver < 1) {
			/* The driver is using an old ABI, so
			 * the application sets the slave's
			 * hwaddr
			 */
			res = set_slave_hwaddr(slave_ifname,
					       &(master_hwaddr.ifr_hwaddr));
			if (res) {
				fprintf(stderr,
					"Slave '%s': Error: set hw address "
					"failed\n",
					slave_ifname);
				goto undo_mtu;
			}

			/* For old ABI the application needs to bring the
			 * slave back up
			 */
			res = set_if_up(slave_ifname, slave_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Slave '%s': Error: bring interface "
					"down failed\n",
					slave_ifname);
				goto undo_slave_mac;
			}
		}
		/* The driver is using a new ABI,
		 * so the driver takes care of setting
		 * the slave's hwaddr and bringing
		 * it up again
		 */
	} else {
		/* No hwaddr for master yet, so
		 * set the slave's hwaddr to it
		 */
		if (abi_ver < 1) {
			/* For old ABI, the master needs to be
			 * down before setting its hwaddr
			 */
			res = set_if_down(master_ifname, master_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Master '%s': Error: bring interface "
					"down failed\n",
					master_ifname);
				goto undo_mtu;
			}
		}

		res = set_master_hwaddr(master_ifname,
					&(slave_hwaddr.ifr_hwaddr));
		if (res) {
			fprintf(stderr,
				"Master '%s': Error: set hw address "
				"failed\n",
				master_ifname);
			goto undo_mtu;
		}

		if (abi_ver < 1) {
			/* For old ABI, bring the master
			 * back up
			 */
			res = set_if_up(master_ifname, master_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Master '%s': Error: bring interface "
					"up failed\n",
					master_ifname);
				goto undo_master_mac;
			}
		}

		hwaddr_set = 1;
	}

	/* Do the real thing */
	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
	strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
	if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) &&
	    (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) {
		saved_errno = errno;
		v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
			master_ifname, strerror(saved_errno));
		res = 1;
	}

	if (res) {
		goto undo_master_mac;
	}

	return 0;

/* rollback (best effort) */
undo_master_mac:
	set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr));
	hwaddr_set = 0;
	goto undo_mtu;
undo_slave_mac:
	set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr));
undo_mtu:
	set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
	return res;
}
static int enslave(char *master_ifname, char *slave_ifname)
{
	struct ifreq ifr;
	int res = 0;

	if (slave_flags.ifr_flags & IFF_SLAVE) {
		fprintf(stderr,
			"Illegal operation: The specified slave interface "
			"'%s' is already a slave\n",
			slave_ifname);
		return 1;
	}

	res = set_if_down(slave_ifname, slave_flags.ifr_flags);
	if (res) {
		fprintf(stderr,
			"Slave '%s': Error: bring interface down failed\n",
			slave_ifname);
		return res;
	}

	if (abi_ver < 2) {
		/*                                                          
                                                    
   */
		set_if_addr(master_ifname, slave_ifname);
	} else {
		res = clear_if_addr(slave_ifname);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: clear address failed\n",
				slave_ifname);
			return res;
		}
	}

	if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
		res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: set MTU failed\n",
				slave_ifname);
			return res;
		}
	}

	if (hwaddr_set) {
		/*                             
                                    
   */
		if (abi_ver < 1) {
			/*                                   
                                      
            
    */
			res = set_slave_hwaddr(slave_ifname,
					       &(master_hwaddr.ifr_hwaddr));
			if (res) {
				fprintf(stderr,
					"Slave '%s': Error: set hw address "
					"failed\n",
					slave_ifname);
				goto undo_mtu;
			}

			/*                                               
                   
    */
			res = set_if_up(slave_ifname, slave_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Slave '%s': Error: bring interface "
					"down failed\n",
					slave_ifname);
				goto undo_slave_mac;
			}
		}
		/*                               
                                        
                                    
                
   */
	} else {
		/*                             
                                 
   */
		if (abi_ver < 1) {
			/*                                    
                                    
    */
			res = set_if_down(master_ifname, master_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Master '%s': Error: bring interface "
					"down failed\n",
					master_ifname);
				goto undo_mtu;
			}
		}

		res = set_master_hwaddr(master_ifname,
					&(slave_hwaddr.ifr_hwaddr));
		if (res) {
			fprintf(stderr,
				"Master '%s': Error: set hw address "
				"failed\n",
				master_ifname);
			goto undo_mtu;
		}

		if (abi_ver < 1) {
			/*                              
             
    */
			res = set_if_up(master_ifname, master_flags.ifr_flags);
			if (res) {
				fprintf(stderr,
					"Master '%s': Error: bring interface "
					"up failed\n",
					master_ifname);
				goto undo_master_mac;
			}
		}

		hwaddr_set = 1;
	}

	/*                   */
	strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ);
	strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ);
	if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) &&
	    (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) {
		saved_errno = errno;
		v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
			master_ifname, strerror(saved_errno));
		res = 1;
	}

	if (res) {
		goto undo_master_mac;
	}

	return 0;

/*                        */
undo_master_mac:
	set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr));
	hwaddr_set = 0;
	goto undo_mtu;
undo_slave_mac:
	set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr));
undo_mtu:
	set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
	return res;
}