📄 ifenslave.c
字号:
dstaddr = ifr.ifr_dstaddr; strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) { memset(&broadaddr, 0, sizeof(struct sockaddr)); } else broadaddr = ifr.ifr_broadaddr; strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) { memset(&netmask, 0, sizeof(struct sockaddr)); } else netmask = ifr.ifr_netmask; return 0;}static void if_print(char *ifname){ char buff[1024]; struct ifconf ifc; struct ifreq *ifr; int i; if (ifname == (char *)NULL) { ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { perror("SIOCGIFCONF failed"); return; } ifr = ifc.ifc_req; for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if (if_getconfig(ifr->ifr_name) < 0) { fprintf(stderr, "%s: unknown interface.\n", ifr->ifr_name); continue; } if (((mif_flags & IFF_UP) == 0) && !opt_a) continue; /*ife_print(&ife);*/ } } else { if (if_getconfig(ifname) < 0) { fprintf(stderr, "%s: unknown interface.\n", ifname); } }}static int get_drv_info(char *master_ifname){ struct ifreq ifr; struct ethtool_drvinfo info; char *endptr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); ifr.ifr_data = (caddr_t)&info; info.cmd = ETHTOOL_GDRVINFO; strncpy(info.driver, "ifenslave", 32); snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) { if (errno == EOPNOTSUPP) { goto out; } saved_errno = errno; v_print("Master '%s': Error: get bonding info failed %s\n", master_ifname, strerror(saved_errno)); return 1; } abi_ver = strtoul(info.fw_version, &endptr, 0); if (*endptr) { v_print("Master '%s': Error: got invalid string as an ABI " "version from the bonding module\n", master_ifname); return 1; }out: v_print("ABI ver is %d\n", abi_ver); return 0;}static int change_active(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 not a slave\n", slave_ifname); return 1; } strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) && (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) { saved_errno = errno; v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: " "%s\n", master_ifname, strerror(saved_errno)); res = 1; } 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) { /* 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 it's 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 release(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 not a slave\n", slave_ifname); return 1; } strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) && (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) { saved_errno = errno; v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n", master_ifname, strerror(saved_errno)); return 1; } else if (abi_ver < 1) { /* The driver is using an old ABI, so we'll set the interface * down to avoid any conflicts due to same MAC/IP */ res = set_if_down(slave_ifname, slave_flags.ifr_flags); if (res) { fprintf(stderr, "Slave '%s': Error: bring interface " "down failed\n", slave_ifname); } } /* set to default mtu */ set_slave_mtu(slave_ifname, 1500); return res;}static int get_if_settings(char *ifname, struct dev_ifr ifra[]){ int i; int res = 0; for (i = 0; ifra[i].req_ifr; i++) { strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ); res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr); if (res < 0) { saved_errno = errno; v_print("Interface '%s': Error: %s failed: %s\n", ifname, ifra[i].req_name, strerror(saved_errno)); return saved_errno; } } return 0;}static int get_slave_flags(char *slave_ifname){ int res = 0; strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ); res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags); if (res < 0) { saved_errno = errno; v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n", slave_ifname, strerror(saved_errno)); } else { v_print("Slave %s: flags %04X.\n", slave_ifname, slave_flags.ifr_flags); } return res;}static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr){ unsigned char *addr = (unsigned char *)hwaddr->sa_data; struct ifreq ifr; int res = 0; strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); res = ioctl(skfd, SIOCSIFHWADDR, &ifr); if (res < 0) { saved_errno = errno; v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n", master_ifname, strerror(saved_errno)); return res; } else { v_print("Master '%s': hardware address set to " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } return res;}static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr){ unsigned char *addr = (unsigned char *)hwaddr->sa_data; struct ifreq ifr; int res = 0; strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); res = ioctl(skfd, SIOCSIFHWADDR, &ifr); if (res < 0) { saved_errno = errno; v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n", slave_ifname, strerror(saved_errno)); if (saved_errno == EBUSY) { v_print(" The device is busy: it must be idle " "before running this command.\n"); } else if (saved_errno == EOPNOTSUPP) { v_print(" The device does not support setting " "the MAC address.\n" " Your kernel likely does not support slave " "devices.\n"); } else if (saved_errno == EINVAL) { v_print(" The device's address type does not match " "the master's address type.\n"); } return res; } else { v_print("Slave '%s': hardware address set to " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } return res;}static int set_slave_mtu(char *slave_ifname, int mtu){ struct ifreq ifr; int res = 0; ifr.ifr_mtu = mtu; strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); res = ioctl(skfd, SIOCSIFMTU, &ifr); if (res < 0) { saved_errno = errno; v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n", slave_ifname, strerror(saved_errno)); } else { v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu); } return res;}static int set_if_flags(char *ifname, short flags){ struct ifreq ifr; int res = 0; ifr.ifr_flags = flags; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); res = ioctl(skfd, SIOCSIFFLAGS, &ifr); if (res < 0) { saved_errno = errno; v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n", ifname, strerror(saved_errno)); } else { v_print("Interface '%s': flags set to %04X.\n", ifname, flags); } return res;}static int set_if_up(char *ifname, short flags){ return set_if_flags(ifname, flags | IFF_UP);}static int set_if_down(char *ifname, short flags){ return set_if_flags(ifname, flags & ~IFF_UP);}static int clear_if_addr(char *ifname){ struct ifreq ifr; int res = 0; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); res = ioctl(skfd, SIOCSIFADDR, &ifr); if (res < 0) { saved_errno = errno; v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n", ifname, strerror(saved_errno)); } else { v_print("Interface '%s': address cleared\n", ifname); } return res;}static int set_if_addr(char *master_ifname, char *slave_ifname){ struct ifreq ifr; int res; unsigned char *ipaddr; int i; struct { char *req_name; char *desc; int g_ioctl; int s_ioctl; } ifra[] = { {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR}, {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR}, {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR}, {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK}, {NULL, NULL, 0, 0}, }; for (i = 0; ifra[i].req_name; i++) { strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); res = ioctl(skfd, ifra[i].g_ioctl, &ifr); if (res < 0) { int saved_errno = errno; v_print("Interface '%s': Error: SIOCG%s failed: %s\n", master_ifname, ifra[i].req_name, strerror(saved_errno)); ifr.ifr_addr.sa_family = AF_INET; memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); } strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); res = ioctl(skfd, ifra[i].s_ioctl, &ifr); if (res < 0) { int saved_errno = errno; v_print("Interface '%s': Error: SIOCS%s failed: %s\n", slave_ifname, ifra[i].req_name, strerror(saved_errno)); } ipaddr = ifr.ifr_addr.sa_data; v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n", slave_ifname, ifra[i].desc, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); } return 0;}/* * Local variables: * version-control: t * kept-new-versions: 5 * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -