this file use tools ip, brctl, ifconfig to provide the functionalities.
Signed-off-by: Wayne Xia <xiawenc(a)linux.vnet.ibm.com>
---
libxkutil/host_network_implement_cmdline.c | 2002 ++++++++++++++++++++++++++++
libxkutil/host_network_implement_cmdline.h | 55 +
2 files changed, 2057 insertions(+), 0 deletions(-)
create mode 100644 libxkutil/host_network_implement_cmdline.c
create mode 100644 libxkutil/host_network_implement_cmdline.h
diff --git a/libxkutil/host_network_implement_cmdline.c
b/libxkutil/host_network_implement_cmdline.c
new file mode 100644
index 0000000..fc9226b
--- /dev/null
+++ b/libxkutil/host_network_implement_cmdline.c
@@ -0,0 +1,2002 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc(a)cn.ibm.com>
+ *
+ * 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.
+ *
+ * Note:
+ * the string example used below is all reformed to avoid code format check
+ * errors, so it just says the command output format as a reference.
+ * char "tab" is changed to "space", tailing space is removed, lines
over 80
+ * characters was foldered.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "host_network_implement_cmdline.h"
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+/* macro defines */
+#define COMMAND_NOTFOUND_STRING "command not found"
+#define COMMAND_NOPERMISSION_STRING "Permission denied"
+#define BRCTL_EXPECT_STRING "bridge name"
+#define VLAN8021Q_CAT_ETH_EXPECT_STRING "REORDER_HDR:"
+#define VLAN8021Q_CONFIG_EXPECT_STRING "VLAN Dev name"
+
+#define IFACE_CONFIG_FILE_PREFIX_RH "/etc/sysconfig/network-scripts/ifcfg-"
+
+#define CONT_BUFF_SIZE 256
+
+/* the bridge seems have 0 value when it is up , so adjust the value,
+ and found out which are physical cards */
+static int host_iface_adjust(EthIface *piface)
+{
+ if (piface->eth_type == ETH_TYPE_BRIDGE) {
+ if (piface->run_prop.state == ETH_TYPE_UNKNOWN) {
+ piface->run_prop.state = ETH_STATE_UP;
+ }
+ }
+ if (1 == eth_iface_filter_peths(piface, NULL)) {
+ piface->eth_type = ETH_TYPE_PHYSICAL;
+ }
+ return 1;
+}
+
+int host_ifacelist_is_present_cmd(EthIfacesList *plist, int *retvalues,
+ int compare_name_only)
+{
+ EthIfacesList ifaces_list;
+ int retvalue;
+ int i, j;
+ eth_iface_filter_func func;
+
+ eth_ifaceslist_init(&ifaces_list);
+ retvalue = get_host_eth_ifaces_ip_addr(ifaces_list.pifaces,
+ &ifaces_list.count, MAX_IFACE_NUM, NULL, NULL);
+ if (retvalue != 1) {
+ goto out;
+ }
+
+ if (compare_name_only == 0) {
+ func = eth_iface_filter_by_refname;
+ } else {
+ func = eth_iface_filter_by_ref;
+ }
+ i = 0;
+ while (i < plist->count) {
+ retvalues[i] = 0;
+ j = 0;
+ while (j < ifaces_list.count) {
+ if (1 == func(ifaces_list.pifaces[j], plist->pifaces[i])) {
+ retvalues[i] = 1;
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+
+ out:
+ eth_ifaceslist_uninit(&ifaces_list);
+ return retvalue;
+}
+
+static int host_iface_is_present_cmd(EthIface *piface)
+{
+ EthIface *pifaces[1];
+ int retvalue;
+ int ifaces_num;
+ int exist_flag = 0;
+ EthIface ref;
+ eth_iface_init(&ref);
+ ref.name = SAFE_STRDUP(piface->name);
+
+ retvalue = get_host_eth_ifaces_ip_addr(pifaces, &ifaces_num,
+ 1, eth_iface_filter_by_ref, &ref);
+
+ if ((retvalue == 1) && (ifaces_num == 1)) {
+ exist_flag = 1;
+ }
+ eth_ifaces_clear(pifaces, ifaces_num);
+ eth_iface_uninit(&ref);
+ return exist_flag;
+}
+
+static int host_br_is_present_cmd(EthIface *piface)
+{
+ EthIface *pifaces[1];
+ int retvalue;
+ int ifaces_num;
+ int exist_flag = 0;
+ EthIface ref;
+ eth_iface_init(&ref);
+ ref.name = SAFE_STRDUP(piface->name);
+
+ retvalue = get_host_eth_ifaces_brctl(pifaces, &ifaces_num,
+ 1, eth_iface_filter_by_ref, &ref);
+
+ if ((retvalue == 1) && (ifaces_num == 1)) {
+ exist_flag = 1;
+ }
+ eth_ifaces_clear(pifaces, ifaces_num);
+ eth_iface_uninit(&ref);
+ return exist_flag;
+}
+
+/* 1: the bridge have the iface attached
+ 2: the iface is attached to other bridge
+ other: not found */
+int host_br_have_iface_attached_cmd(EthIface *pbr, EthIface *piface,
+ EthIface **ppbr_result)
+{
+ int ret = 0;
+ BR_Prop *pbr_prop;
+ EthIface **pifaces = NULL;
+ int retvalue;
+ int ifaces_num = 0;
+ int i, j;
+
+ if (0 == host_iface_is_present_cmd(piface)) {
+ return -1;
+ }
+
+ SAFE_CALLOC(pifaces, MAX_IFACE_NUM, sizeof(EthIface *));
+
+ retvalue = get_host_eth_ifaces_brctl(pifaces, &ifaces_num,
+ MAX_IFACE_NUM, NULL, NULL);
+
+ if ((retvalue == 1) && (ifaces_num > 0)) {
+ i = 0;
+ while (i < ifaces_num) {
+ if (0 == strcmp(pbr->name, pifaces[i]->name)) {
+ /* found the bridge */
+ pbr_prop = pifaces[i]->pbr_prop;
+ j = 0;
+ while (j < pbr_prop->port_num) {
+ if (0 == strcmp(piface->name, pbr_prop->port_names[j])) {
+ ret = 1;
+ break;
+ }
+ j++;
+ }
+ if (ppbr_result != NULL) {
+ *ppbr_result = pifaces[i];
+ pifaces[i] = NULL;
+ }
+ goto out;
+ } else {
+ /* not the bridge */
+ pbr_prop = pifaces[i]->pbr_prop;
+ j = 0;
+ while (j < pbr_prop->port_num) {
+ if (0 == strcmp(piface->name, pbr_prop->port_names[j])) {
+ ret = 2;
+ goto out;
+ }
+ j++;
+ }
+ }
+ i++;
+ }
+ } else {
+ ret = -2;
+ }
+
+ out:
+ if (pifaces != NULL) {
+ eth_ifaces_clear(pifaces, ifaces_num);
+ SAFE_FREE(pifaces);
+ }
+ return ret;
+}
+
+static int host_vlan_is_present_8021q_cmd(EthIface *piface)
+{
+ EthIface *pifaces[1];
+ int retvalue;
+ int ifaces_num;
+ int exist_flag = 0;
+ EthIface ref;
+ eth_iface_init(&ref);
+ ref.name = SAFE_STRDUP(piface->name);
+
+ retvalue = get_host_eth_ifaces_cat_vlan_config(pifaces, &ifaces_num,
+ 1, eth_iface_filter_by_ref, &ref);
+
+ if ((retvalue == 1) && (ifaces_num == 1)) {
+ exist_flag = 1;
+ }
+ eth_ifaces_clear(pifaces, ifaces_num);
+ eth_iface_uninit(&ref);
+ return exist_flag;
+}
+
+int get_host_eth_ifaces_ip_addr(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ EthIface tcard, **ppdest;
+ char *temp, *temp2, *temp3;
+ char *search_str;
+ int count = 0;
+ int filter_ret;
+ int line_count = 0;
+ struct in_addr addr;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ cmd[0] = '\0';
+ strcat(cmd, "ip addr");
+ stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ eth_iface_init(&tcard);
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CMD_DEBUG(3, "%s", buff);
+ if (line_count == 0) {
+ if (NULL != strstr(buff, COMMAND_NOTFOUND_STRING)) {
+ CU_DEBUG("Got [%s] with command [%s], check u environment.\n",
+ COMMAND_NOTFOUND_STRING, cmd);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+ if (NULL != strstr(buff, COMMAND_NOPERMISSION_STRING)) {
+ CU_DEBUG("Got [%s] with command [%s], check u environment.\n",
+ COMMAND_NOPERMISSION_STRING, cmd);
+ ret = ERR_COMMAND_NO_PERMISSION;
+ goto out;
+ }
+ }
+ line_count++;
+ /*analysis the output, example is something like following:
+
+3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc \
+pfifo_fast run_prop.state UP qlen 1000
+ link/ether 08:00:27:e3:13:f8 brd ff:ff:ff:ff:ff:ff
+ inet 10.0.3.15/24 brd 10.0.3.255 scope global eth1
+ inet6 fe80::a00:27ff:fee3:13f8/64 scope link
+ valid_lft forever preferred_lft forever
+4: eth1.5@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc \
+noqueue run_prop.state UP
+ link/ether 08:00:27:e3:13:f8 brd ff:ff:ff:ff:ff:ff
+ inet6 fe80::a00:27ff:fee3:13f8/64 scope link
+ valid_lft forever preferred_lft forever
+
+ */
+ /* for line that divide two devices */
+ if ((0 != strncmp(buff, " ", 1)) && (0 != strncmp(buff,
"\t", 1))) {
+ if (tcard.name != NULL) {
+ /* device found, copy the content */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ eth_iface_uninit(&tcard);
+ eth_iface_init(&tcard);
+ }
+ /* discovery names */
+ search_str = ": ";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ temp2 = strstr(temp, search_str);
+ if (temp2 != NULL) {
+ /* found string that contains names,
+ start point is temp, end point is temp2 */
+ search_str = "@";
+ temp3 = strstr(temp, search_str);
+ if ((temp3 != NULL) && (temp3 < temp2)) {
+ /* have parent dev, temp3 holds the division */
+ SAFE_FREE(tcard.dep_ifname);
+ tcard.dep_ifname = strndup(temp3+1, temp2-temp3-1);
+ SAFE_FREE(tcard.name);
+ tcard.name = strndup(temp, temp3-temp);
+ } else {
+ SAFE_FREE(tcard.name);
+ tcard.name = strndup(temp, temp2-temp);
+ }
+ }
+ }
+ /* discovery run_prop.state */
+ search_str = "state ";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ if (0 == strncmp(temp, "UP", 2)) {
+ tcard.run_prop.state = ETH_STATE_UP;
+ } else if (0 == strncmp(temp, "DOWN", 4)) {
+ tcard.run_prop.state = ETH_STATE_DOWN;
+ } else if (0 == strncmp(temp, "UNKNOWN", 7)) {
+ tcard.run_prop.state = ETH_STATE_UNKNOWN;
+ }
+ }
+ continue;
+ }
+ /* for lines that saying other properties */
+ /* dicovering mac */
+ search_str = "ether ";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ SAFE_FREE(tcard.mac);
+ tcard.mac = strtok_onetime(temp, " ");
+ }
+ /* dicovering ip and ip_mask for ipv4 */
+ search_str = "inet ";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ temp2 = strstr(temp, "/");
+ if (temp2 != NULL) {
+ /* found the ip and mask, temp2 holds the division */
+ SAFE_FREE(tcard.ipv4_prop.ip);
+ tcard.ipv4_prop.ip = strndup(temp, temp2-temp);
+ if (1 == netmask_easy_to_inaddr(&addr, temp2+1)) {
+ SAFE_FREE(tcard.ipv4_prop.ip_mask);
+ SAFE_MALLOC(tcard.ipv4_prop.ip_mask, INET_ADDRSTRLEN);
+ tcard.ipv4_prop.ip_mask[INET_ADDRSTRLEN-1] = '\0';
+ if (NULL == inet_ntop(AF_INET, &addr,
+ tcard.ipv4_prop.ip_mask, INET_ADDRSTRLEN)) {
+ SAFE_FREE(tcard.ipv4_prop.ip_mask);
+ }
+ }
+ }
+ }
+ }
+
+ /* because the output have no indication about end, so need to try add
+ the latest device found to the list */
+ if (tcard.name != NULL) {
+ /* device found, copy the content */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ }
+
+ ret = 1;
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ eth_iface_uninit(&tcard);
+ SAFE_FREE(buff);
+ *retnum = count;
+
+ return ret;
+}
+
+int get_host_eth_ifaces_ifconfig(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ EthIface tcard, **ppdest;
+ char *temp, *temp2;
+ char *search_str;
+ int count = 0;
+ int filter_ret;
+ int line_count = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ cmd[0] = '\0';
+ strcat(cmd, "ifconfig");
+ stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ eth_iface_init(&tcard);
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CMD_DEBUG(3, "%s", buff);
+ if (line_count == 0) {
+ if (NULL != strstr(buff, COMMAND_NOTFOUND_STRING)) {
+ CU_DEBUG("Got [%s] with command [%s], check u environment.\n",
+ COMMAND_NOTFOUND_STRING, cmd);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+ if (NULL != strstr(buff, COMMAND_NOPERMISSION_STRING)) {
+ CU_DEBUG("Got [%s] with command [%s], check u environment.\n",
+ COMMAND_NOPERMISSION_STRING, cmd);
+ ret = ERR_COMMAND_NO_PERMISSION;
+ goto out;
+ }
+ }
+ line_count++;
+ /*analysis the output, example is something like following:
+
+eth1 Link encap:Ethernet HWaddr 08:00:27:E3:13:F8
+ inet addr:10.0.3.15 Bcast:10.0.3.255 Mask:255.255.255.0
+ inet6 addr: fe80::a00:27ff:fee3:13f8/64 Scope:Link
+ UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
+ RX packets:236 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:346 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:1000
+ RX bytes:100464 (98.1 KiB) TX bytes:30721 (30.0 KiB)
+
+eth1.5 Link encap:Ethernet HWaddr 08:00:27:E3:13:F8
+ ...
+
+ */
+ /* for line that divide two devices */
+ if (0 == strncmp(buff, "\n", 1)) {
+ /* device found, copy the content */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ eth_iface_uninit(&tcard);
+ eth_iface_init(&tcard);
+ continue;
+ }
+ /* for line that saying other properties */
+ if (0 == strncmp(buff, " ", 1)) {
+ /* discovery ip for ip v4 */
+ search_str = "inet addr:";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ SAFE_FREE(tcard.ipv4_prop.ip);
+ tcard.ipv4_prop.ip = strtok_onetime(temp, " ");
+ /* discovery ip mask*/
+ search_str = "Mask";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ SAFE_FREE(tcard.ipv4_prop.ip_mask);
+ tcard.ipv4_prop.ip_mask = strtok_onetime(temp, " ");
+ if (tcard.ipv4_prop.ip_mask == NULL) {
+ tcard.ipv4_prop.ip_mask = strtok_onetime(temp, "\n");
+ }
+ }
+ }
+
+ /* discovery RX and TX bytes */
+ search_str = "RX bytes:";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ tcard.run_prop.rx_bytes = strtoll(temp, &temp2, 10);
+ if (temp == temp2) {
+ /*failed to get the value, restore it to default */
+ tcard.run_prop.rx_bytes = NUM_NOT_GOT;
+ }
+ search_str = "TX bytes:";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ tcard.run_prop.tx_bytes = strtoll(temp, &temp2, 10);
+ if (temp == temp2) {
+ /*failed to get the value, restore it to default */
+ tcard.run_prop.tx_bytes = NUM_NOT_GOT;
+ }
+ }
+ }
+ continue;
+ }
+ /* for lines that saying the device with title */
+ /* discovery name */
+ SAFE_FREE(tcard.name);
+ tcard.name = strtok_onetime(buff, " ");
+ /* discovery mac */
+ search_str = "HWaddr ";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ temp += strlen(search_str);
+ SAFE_FREE(tcard.mac);
+ tcard.mac = strtok_onetime(temp, " ");
+ if (tcard.mac == NULL) {
+ tcard.mac = strtok_onetime(temp, "\n");
+ }
+ }
+ /* discovery type */
+ search_str = "Local Loopback";
+ temp = strstr(buff, search_str);
+ if (temp != NULL) {
+ tcard.eth_type = ETH_TYPE_LOOPBACK;
+ }
+ continue;
+ }
+
+ ret = 1;
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ eth_iface_uninit(&tcard);
+ SAFE_FREE(buff);
+ *retnum = count;
+
+ return ret;
+}
+
+int get_host_eth_ifaces_brctl(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ EthIface tcard, **ppdest;
+ BR_Prop tbr;
+ char *last = NULL, *iter;
+ char *char_stp = NULL;
+ char *port_name = NULL;
+ int count = 0;
+ int filter_ret;
+ int line_count = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ cmd[0] = '\0';
+ strcat(cmd, "brctl show");
+ stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ eth_iface_init(&tcard);
+ br_prop_init(&tbr);
+ tbr.port_num = 0;
+ port_name = NULL;
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CMD_DEBUG(3, "%s", buff);
+/* output string should be something like following
+
+bridge name bridge id STP enabled interfaces
+testbr 8000.000000000000 no
+virbr0 8000.5254004ac14c yes virbr0-nic
+ vnet0
+virbr3 8000.5254004ac16c yes virbr3-nic
+...
+*/
+ if (line_count == 0) {
+ if (NULL == strstr(buff, BRCTL_EXPECT_STRING)) {
+ CU_DEBUG("[%s] not found with command [%s],"
+ "check u environment.\n",
+ BRCTL_EXPECT_STRING, cmd);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+ line_count++;
+ continue;
+ }
+ if ((buff[0] == ' ') || (buff[0] == '\t')) {
+ /* the line saying ifaces it attached */
+ port_name = strtok_r(buff, "\n", &last);
+ if (port_name == NULL) {
+ CU_DEBUG("command [%s] did not output as expected.", cmd);
+ continue;
+ }
+ port_name = strtok_r(buff, "\t", &last);
+ if (port_name == NULL) {
+ CU_DEBUG("command [%s] did not output as expected.", cmd);
+ continue;
+ }
+ /* adding the port */
+ if (tbr.port_names == NULL) {
+ SAFE_CALLOC(tbr.port_names, MAX_IFACE_NUM, sizeof(char *));
+ tbr.port_num = 0;
+ }
+ if (tbr.port_num >= MAX_IFACE_NUM) {
+ CU_DEBUG("bridge [%s] have too much eth attached!",
+ tcard.name);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ tbr.port_names[tbr.port_num] = SAFE_STRDUP(port_name);
+ tbr.port_num++;
+ } else {
+ /* the line saying a new bridge */
+ if (tcard.name != NULL) {
+ /* have a valid iface, so add it to the list */
+ tcard.pbr_prop = &tbr;
+ tcard.eth_type = ETH_TYPE_BRIDGE;
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ CU_DEBUG("too much bridge found, max is %d",
+ maxnum);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ tcard.pbr_prop = NULL;
+ eth_iface_uninit(&tcard);
+ eth_iface_init(&tcard);
+ br_prop_uninit(&tbr);
+ br_prop_init(&tbr);
+ tbr.port_num = 0;
+ }
+ SAFE_STRDUP_WITH_FUNC(tcard.name,
+ strtok_r(buff, "\t", &last), iter);
+ SAFE_STRDUP_WITH_FUNC(tbr.bridge_id,
+ strtok_r(NULL, "\t", &last), iter);
+ char_stp = strtok_r(NULL, "\t", &last);
+ if (char_stp != NULL) {
+ if (0 == strcmp(char_stp, "yes")) {
+ tbr.STP = 1;
+ } else if (0 == strcmp(char_stp, "no")) {
+ tbr.STP = 0;
+ }
+ }
+ if (last != NULL) {
+ if ((*last == '\0') || (*(last+1) == '\0')) {
+ CU_DEBUG("command [%s] did not output as expected,"
+ "string left [%s].", cmd, last);
+ continue;
+ }
+ last++;
+ }
+ if (*last == '\t') {
+ port_name = NULL;
+ } else {
+ port_name = strtok_r(NULL, "\n", &last);
+ if (port_name != NULL) {
+ /* adding the port */
+ if (tbr.port_names == NULL) {
+ SAFE_CALLOC(tbr.port_names,
+ MAX_IFACE_NUM, sizeof(char *));
+ tbr.port_num = 0;
+ }
+ if (tbr.port_num >= MAX_IFACE_NUM) {
+ CU_DEBUG("bridge [%s] have too much eth attached!",
+ tcard.name);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ tbr.port_names[tbr.port_num] = SAFE_STRDUP(port_name);
+ tbr.port_num++;
+ }
+ }
+ }
+ line_count++;
+ }
+
+ if (tcard.name != NULL) {
+ /* have a valid iface, so add it to the list */
+ tcard.pbr_prop = &tbr;
+ tcard.eth_type = ETH_TYPE_BRIDGE;
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ CU_DEBUG("too much bridge found, max is %d",
+ maxnum);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ tcard.pbr_prop = NULL;
+ }
+
+ ret = 1;
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ br_prop_uninit(&tbr);
+ eth_iface_uninit(&tcard);
+ SAFE_FREE(buff);
+ *retnum = count;
+
+ return ret;
+}
+
+static int get_iface_cat_vlan_one_eth_8021q(EthIface *piface)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *cmd_prefix = "cat /proc/net/vlan/";
+ char *buff = NULL;
+ VLAN_Prop_8021q *pprop_8021q;
+ char *last = NULL;
+ char *char_temp = NULL;
+ char *search_str, *iter, *temp1, *temp2, *temp3, *qos;
+ int ret = 0;
+ int line_count = -1;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if ((piface->name == NULL) ||
+ ((strlen(piface->name)+strlen(cmd_prefix)) > (sizeof(cmd)-1))) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ memcpy(cmd, cmd_prefix, strlen(cmd_prefix)+1);
+ strcat(cmd, piface->name);
+
+ stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ if (piface->pvlan_prop == NULL) {
+ SAFE_MALLOC(piface->pvlan_prop, sizeof(VLAN_Prop));
+ vlan_prop_init(piface->pvlan_prop, VLAN_TYPE_802_1_Q);
+ }
+ if (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q) {
+ ret = 0;
+ goto out;
+ }
+ pprop_8021q = &(piface->pvlan_prop->props.prop_8021q);
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ line_count++;
+ CMD_DEBUG(3, "%s", buff);
+/* output is expected some thing like following
+eth1.7.7 VID: 7 REORDER_HDR: 1 dev->priv_flags: 1
+ total frames received 0
+ total bytes received 0
+ Broadcast/Multicast Rcvd 0
+
+ total frames transmitted 0
+ total bytes transmitted 0
+ total headroom inc 0
+ total encap on xmit 0
+Device: eth1.7
+INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
+ EGRESS priority mappings:
+*/
+ if (line_count == 0) {
+ if (NULL == strstr(buff, VLAN8021Q_CAT_ETH_EXPECT_STRING)) {
+ CU_DEBUG("[%s] not found with command [%s],"
+ "check u environment.\n",
+ VLAN8021Q_CAT_ETH_EXPECT_STRING, cmd);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+ }
+ search_str = "VID: ";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ /* first line */
+ temp1 += strlen(search_str);
+ search_str = "REORDER_HDR: ";
+ temp2 = strstr(buff, search_str);
+ if (temp2 != NULL) {
+ temp2 += strlen(search_str);
+ }
+ search_str = "priv_flags: ";
+ temp3 = strstr(buff, search_str);
+ if (temp3 != NULL) {
+ temp3 += strlen(search_str);
+ }
+ if ((temp2 != NULL) && (temp3 != NULL)) {
+ char_temp = strtok_r(temp1, " ", &last);
+ if (char_temp != NULL) {
+ pprop_8021q->vlan_id = strtol(char_temp, &iter, 10);
+ }
+ char_temp = strtok_r(temp2, " ", &last);
+ if (char_temp != NULL) {
+ pprop_8021q->reorder_hdr = strtol(char_temp, &iter, 10);
+ }
+ char_temp = strtok_r(temp3, " ", &last);
+ if (char_temp != NULL) {
+ pprop_8021q->priv_flag = strtol(char_temp, &iter, 10);
+ }
+ }
+ continue;
+ }
+ search_str = "total bytes received";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ temp1 += strlen(search_str);
+ char_temp = strtok_r(temp1, " ", &last);
+ if (char_temp != NULL) {
+ piface->run_prop.rx_bytes = strtoll(char_temp, &iter, 10);
+ }
+ continue;
+ }
+ search_str = "total bytes transmitted";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ temp1 += strlen(search_str);
+ char_temp = strtok_r(temp1, " ", &last);
+ if (char_temp != NULL) {
+ piface->run_prop.tx_bytes = strtoll(char_temp, &iter, 10);
+ }
+ continue;
+ }
+ search_str = "Device: ";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ temp1 += strlen(search_str);
+ pprop_8021q->parent = strtok_onetime(temp1, " ");
+ if (pprop_8021q->parent == NULL) {
+ pprop_8021q->parent = strtok_onetime(temp1, "\n");
+ }
+ continue;
+ }
+ search_str = "INGRESS priority mappings: ";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ temp1 += strlen(search_str);
+ if (NULL != strstr(temp1, ":")) {
+ qos = strtok_onetime(temp1, "\n");
+ if (qos != NULL) {
+ vlan_8021q_qos_str_to_num(&(pprop_8021q->ingress), qos);
+ SAFE_FREE(qos);
+ }
+ }
+ continue;
+ }
+ search_str = "EGRESS priority mappings: ";
+ temp1 = strstr(buff, search_str);
+ if (temp1 != NULL) {
+ temp1 += strlen(search_str);
+ if (NULL != strstr(temp1, ":")) {
+ qos = strtok_onetime(temp1, "\n");
+ if (qos != NULL) {
+ vlan_8021q_qos_str_to_num(&(pprop_8021q->egress), qos);
+ SAFE_FREE(qos);
+ }
+ }
+ continue;
+ }
+ }
+ piface->eth_type = ETH_TYPE_VLAN;
+ ret = 1;
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int get_host_eth_ifaces_cat_vlan_config(EthIface **ppifaces, int *retnum,
+ int maxnum, eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ EthIface tcard, **ppdest;
+ VLAN_Prop tvlan;
+ int count = 0;
+ int filter_ret;
+ int line_count = -1;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ cmd[0] = '\0';
+ strcat(cmd, "cat /proc/net/vlan/config");
+ stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ eth_iface_init(&tcard);
+ vlan_prop_init(&tvlan, VLAN_TYPE_802_1_Q);
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ line_count++;
+ CMD_DEBUG(3, "%s", buff);
+/* output string should be something like following
+
+VLAN Dev name | VLAN ID
+Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
+eth1.5 | 5 | eth1
+...
+*/
+ if (line_count == 0) {
+ if (NULL == strstr(buff, VLAN8021Q_CONFIG_EXPECT_STRING)) {
+ CU_DEBUG("[%s] not found with command [%s],"
+ "check u environment.\n",
+ VLAN8021Q_CONFIG_EXPECT_STRING, cmd);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+ continue;
+ }
+ if (line_count < 2) {
+ continue;
+ }
+
+ /* the line saying a new bridge */
+ if (tcard.name != NULL) {
+ /* have a valid iface, so add it to the list */
+ tcard.pvlan_prop = &tvlan;
+ /* get additional information for this vlan */
+ get_iface_cat_vlan_one_eth_8021q(&tcard);
+ /* filt it */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ CU_DEBUG("too much vlan found, max is %d",
+ maxnum);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ tcard.pvlan_prop = NULL;
+ eth_iface_uninit(&tcard);
+ eth_iface_init(&tcard);
+ vlan_prop_uninit(&tvlan);
+ vlan_prop_init(&tvlan, VLAN_TYPE_802_1_Q);
+ }
+ /* get the name, other properties would be got in special file */
+ tcard.name = strtok_onetime(buff, " ");
+ }
+
+ if (tcard.name != NULL) {
+ /* have a valid iface, so add it to the list */
+ tcard.pvlan_prop = &tvlan;
+ /* get additional information for this vlan */
+ get_iface_cat_vlan_one_eth_8021q(&tcard);
+ /* filt it */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(&tcard, filter_opaque);
+ }
+ /* found a device match the requirement, put it to the list */
+ if (filter_ret == 1) {
+ if (count >= maxnum) {
+ CU_DEBUG("too much vlan found, max is %d",
+ maxnum);
+ ret = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ ppdest = ppifaces + count;
+ SAFE_MALLOC(*ppdest, sizeof(EthIface));
+ eth_iface_dup(*ppdest, &tcard);
+ count++;
+ }
+ tcard.pvlan_prop = NULL;
+ }
+
+ ret = 1;
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ vlan_prop_uninit(&tvlan);
+ eth_iface_uninit(&tcard);
+ SAFE_FREE(buff);
+ *retnum = count;
+
+ return ret;
+}
+
+int change_state_host_iface_cmd(EthIface *piface, int state)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *cmd_prefix = "ifconfig ";
+ char *cmd_suffix = NULL;
+ char *buff = NULL;
+ int ret = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (state == ETH_STATE_UP) {
+ cmd_suffix = " up";
+ } else if (state == ETH_STATE_DOWN) {
+ cmd_suffix = " down";
+ }
+
+ if (cmd_suffix == NULL) {
+ CU_DEBUG("state change have not target state set.");
+ goto out;
+ }
+
+ if (piface->name == NULL) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("bridge name not set, direct goto out.");
+ goto out;
+ }
+
+ if (0 == host_iface_is_present_cmd(piface)) {
+ CU_DEBUG("iface %s do not exist, can't change state.",
piface->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ if ((strlen(cmd_prefix)+strlen(piface->name)+strlen(cmd_suffix))
+ > (sizeof(cmd)-1)) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s%s", cmd_prefix, piface->name,
cmd_suffix);
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_NOT_SUPPORT;
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int add_host_br_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *cmd_prefix = "brctl addbr ";
+ char *path;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *cont, *c_stp;
+ char *buff = NULL;
+ int ret = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (piface->name == NULL) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("bridge name not set, direct goto out.");
+ goto out;
+ }
+
+ if (1 == host_iface_is_present_cmd(piface)) {
+ CU_DEBUG("%s already exist, cann't create it as bridge.",
piface->name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+
+ if ((strlen(cmd_prefix)+strlen(piface->name)) > (sizeof(cmd)-1)) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s", cmd_prefix, piface->name);
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if ((piface->pbr_prop != NULL) &&
+ (piface->pbr_prop->STP == 1)) {
+ c_stp = "on";
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ cmd_prefix = "brctl stp ";
+ if ((strlen(cmd_prefix)+strlen(piface->name)
+ +strlen(c_stp)) > (sizeof(cmd)-2)) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
+ piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s %s", cmd_prefix, piface->name,
c_stp);
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r",
&ret);
+ if (stream == NULL) {
+ goto out;
+ }
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+ } else {
+ c_stp = "off";
+ }
+
+ if (persist_flag == 1) {
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ SAFE_CALLOC(cont, 1024, sizeof(char));
+ cont[1023] = 1;
+ snprintf(cont, 1024,
+ "DEVICE=%s\nTYPE=Bridge\nBOOTPROTO=dhcp\n"
+ "ONBOOT=yes\nDELAY=0\nSTP=%s\n",
+ piface->name, c_stp);
+ if (cont[1023] == '\0') {
+ CU_DEBUG("failed to build up contents, check the parameter.");
+ ret = ERR_FILE_CONT_TOO_LARGE;
+ SAFE_FREE(path);
+ SAFE_FREE(cont);
+ goto out;
+ }
+ ret = configure_file_update(path, cont);
+ SAFE_FREE(path);
+ SAFE_FREE(cont);
+ if (ret != 1) {
+ goto out;
+ }
+
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int del_host_br_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *cmd_prefix = "brctl delbr ";
+ char *path;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *buff = NULL;
+ int ret = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (piface->name == NULL) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("bridge name not set, direct goto out.");
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ ret = configure_file_remove(path);
+ SAFE_FREE(path);
+ if (ret != 1) {
+ goto out;
+ }
+ }
+
+ if (0 == host_br_is_present_cmd(piface)) {
+ CU_DEBUG("bridge %s do not exist, can't delete it.",
piface->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ if ((strlen(cmd_prefix)+strlen(piface->name)) > (sizeof(cmd)-1)) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s", cmd_prefix, piface->name);
+
+ /* bring down the iface */
+ change_state_host_iface_cmd(piface, ETH_STATE_DOWN);
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int mod_host_br_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *cmd_prefix = "brctl stp ";
+ char *path;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *c_stp;
+ char *buff = NULL;
+ int ret = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (piface->name == NULL) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("bridge name not set, direct goto out.");
+ goto out;
+ }
+
+ if (0 == host_br_is_present_cmd(piface)) {
+ CU_DEBUG("bridge %s do not exist, cann't modify it.",
piface->name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+
+ if ((piface->pbr_prop != NULL) &&
+ (piface->pbr_prop->STP == 1)) {
+ c_stp = "on";
+ } else {
+ c_stp = "off";
+ }
+
+ if ((strlen(cmd_prefix)+strlen(piface->name)
+ +strlen(c_stp)) > (sizeof(cmd)-2)) {
+ CU_DEBUG("error in building up cmd line, name is %s.",
piface->name);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s %s", cmd_prefix, piface->name, c_stp);
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ ret = configure_file_replace_attr(path, "STP=", c_stp);
+ SAFE_FREE(path);
+ if (ret != 1) {
+ CU_DEBUG("error happened in persisting file.");
+ goto out;
+ }
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+static int append_vlan_8021q_parameters(char *cmd, int cmd_size,
+ VLAN_Prop_8021q *p_8021q)
+{
+ char *reorder = NULL;
+ char *egress = NULL, *ingress = NULL;
+ char *cmd_prefix;
+ int ret = 0;
+
+ if (p_8021q->reorder_hdr == 1) {
+ reorder = " reorder_hdr on";
+ } else if (p_8021q->reorder_hdr == 0) {
+ reorder = " reorder_hdr off";
+ }
+ if (reorder != NULL) {
+ if ((strlen(reorder)+strlen(cmd)) < (cmd_size-1)) {
+ strcat(cmd, reorder);
+ } else {
+ CU_DEBUG("cmd line too long, it is [%s]+[%s].", cmd, reorder);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ }
+
+ vlan_8021q_qos_num_to_str(&ingress, &(p_8021q->ingress));
+ if (ingress != NULL) {
+ cmd_prefix = " ingress-qos-map ";
+ if ((strlen(ingress)+strlen(cmd)+strlen(cmd_prefix)) < (cmd_size-1)) {
+ strcat(cmd, cmd_prefix);
+ strcat(cmd, ingress);
+ } else {
+ CU_DEBUG("cmd line too long, it is [%s]+[%s]+[%s].",
+ cmd, cmd_prefix, ingress);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ }
+
+ vlan_8021q_qos_num_to_str(&egress, &(p_8021q->egress));
+ if (egress != NULL) {
+ cmd_prefix = " egress-qos-map ";
+ if ((strlen(egress)+strlen(cmd)+strlen(cmd_prefix)) < (cmd_size-1)) {
+ strcat(cmd, cmd_prefix);
+ strcat(cmd, egress);
+ } else {
+ CU_DEBUG("cmd line too long, it is [%s]+[%s]+[%s].",
+ cmd, cmd_prefix, egress);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+ }
+
+ ret = 1;
+
+ out:
+ SAFE_FREE(ingress);
+ SAFE_FREE(egress);
+ return ret;
+}
+
+int add_host_vlan_8021q_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[192];
+ char *path;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *cont;
+ char *buff = NULL;
+ int ret = 0;
+ int str_size;
+ EthIface iface;
+ VLAN_Prop_8021q *p_8021q;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ eth_iface_init(&iface);
+ if (piface->pvlan_prop == NULL) {
+ CU_DEBUG("pvlan_prop not set, direct goto out.");
+ goto out;
+ }
+ if (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q) {
+ CU_DEBUG("not a 802.1.q vlan, direct goto out.");
+ goto out;
+ }
+ p_8021q = &(piface->pvlan_prop->props.prop_8021q);
+ if ((p_8021q->vlan_id < 1) || (p_8021q->vlan_id > 4095)) {
+ CU_DEBUG("vlan_id for 802.1.q must be 0-4095, "
+ "and 0 is kept by system, request is %d.",
p_8021q->vlan_id);
+ goto out;
+ }
+ if ((p_8021q->parent == NULL)) {
+ CU_DEBUG("creation of vlan iface for 802.1.q need parent iface set");
+ goto out;
+ }
+ iface.name = p_8021q->parent;
+ if (0 == host_iface_is_present_cmd(&iface)) {
+ CU_DEBUG("iface %s do not exist, cann't use it as parent iface.",
+ iface.name);
+ iface.name = NULL;
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ }
+
+ /* restrict the iface name to ethx.x, so the name would be combined here */
+ str_size = strlen(p_8021q->parent)+6;
+ SAFE_MALLOC(iface.name, str_size);
+ snprintf(iface.name, str_size, "%s.%d",
+ p_8021q->parent, p_8021q->vlan_id);
+ if (1 == host_iface_is_present_cmd(&iface)) {
+ CU_DEBUG("iface %s already exist, cann't create it as a 802.1.q
vlan.",
+ iface.name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+
+ /* building up command line */
+ cmd[sizeof(cmd)-1] = 1;
+ snprintf(cmd, sizeof(cmd), "ip link add link %s name %s type vlan id %d",
+ p_8021q->parent, iface.name, p_8021q->vlan_id);
+ if (cmd[sizeof(cmd)-1] == '\0') {
+ CU_DEBUG("cmd line too long, it is [%s].", cmd);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+
+ ret = append_vlan_8021q_parameters(cmd, sizeof(cmd), p_8021q);
+ if (ret != 1) {
+ goto out;
+ }
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, iface.name);
+ SAFE_CALLOC(cont, 1024, sizeof(char));
+ cont[1023] = 1;
+ snprintf(cont, 1024,
+ "DEVICE=%s\nPEERDNS=yes\nVLAN=yes\n", iface.name);
+ if (cont[1023] == '\0') {
+ CU_DEBUG("failed to build up contents, check the parameter.");
+ ret = ERR_FILE_CONT_TOO_LARGE;
+ SAFE_FREE(path);
+ SAFE_FREE(cont);
+ goto out;
+ }
+ ret = configure_file_update(path, cont);
+ SAFE_FREE(path);
+ SAFE_FREE(cont);
+ if (ret != 1) {
+ goto out;
+ }
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ eth_iface_uninit(&iface);
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int del_host_vlan_8021q_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[128];
+ char *path;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *buff = NULL;
+ int ret = 0;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (piface->name == NULL) {
+ CU_DEBUG("piface name was not set, direct goto out.");
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ ret = configure_file_remove(path);
+ SAFE_FREE(path);
+ if (ret != 1) {
+ goto out;
+ }
+ }
+
+ if (piface->pvlan_prop == NULL) {
+ CU_DEBUG("pvlan_prop not set, direct goto out.");
+ goto out;
+ }
+ if (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q) {
+ CU_DEBUG("not a 802.1.q vlan, direct goto out.");
+ goto out;
+ }
+
+ if (0 == host_vlan_is_present_8021q_cmd(piface)) {
+ CU_DEBUG("vlan %s do not exist, cann't delete it.",
piface->name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+
+ /* building up command line */
+ cmd[sizeof(cmd)-1] = 1;
+ snprintf(cmd, sizeof(cmd), "ip link del %s", piface->name);
+ if (cmd[sizeof(cmd)-1] == '\0') {
+ CU_DEBUG("cmd line too long, it is [%s].", cmd);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ ret = ERR_COMMAND_PIPE_ERR;
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int mod_host_vlan_8021q_cmd(EthIface *piface, int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[192];
+ char *buff = NULL;
+ int ret = 0;
+ VLAN_Prop_8021q *p_8021q;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if (piface->name == NULL) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("piface name was not set, direct goto out.");
+ goto out;
+ }
+ if (piface->pvlan_prop == NULL) {
+ CU_DEBUG("pvlan_prop not set, direct goto out.");
+ goto out;
+ }
+ if (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q) {
+ CU_DEBUG("not a 802.1.q vlan, direct goto out.");
+ goto out;
+ }
+ if (0 == host_vlan_is_present_8021q_cmd(piface)) {
+ CU_DEBUG("vlan %s do not exist, cann't modify it.",
piface->name);
+ ret = ERR_DEVICE_EXIST;
+ goto out;
+ }
+ p_8021q = &(piface->pvlan_prop->props.prop_8021q);
+
+ /* building up command line */
+ cmd[sizeof(cmd)-1] = 1;
+ snprintf(cmd, sizeof(cmd), "ip link set %s type vlan",
+ piface->name);
+ if (cmd[sizeof(cmd)-1] == '\0') {
+ CU_DEBUG("cmd line too long, it is [%s].", cmd);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+
+ ret = append_vlan_8021q_parameters(cmd, sizeof(cmd), p_8021q);
+ if (ret != 1) {
+ goto out;
+ }
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ /* modification is logged by linux system itself in /proc/net/vlan */
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int add_host_iface_to_br_cmd(EthIface *piface, EthIface *pbr,
+ int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ int check_value;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *path;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if ((piface->name == NULL) || (pbr->name == NULL)) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("name was not set, direct goto out.");
+ goto out;
+ }
+
+ check_value = host_br_have_iface_attached_cmd(pbr, piface, NULL);
+ if (check_value < 0) {
+ CU_DEBUG("iface %s or bridge %s do not exist, direct goto out.",
+ piface->name, pbr->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ } else if (check_value == 1) {
+ CU_DEBUG("iface %s already attached to bridge %s, can't do it
again.",
+ piface->name, pbr->name);
+ ret = ERR_DEVICE_ALREADY_DONE;
+ goto out;
+ } else if (check_value == 2) {
+ CU_DEBUG("iface %s is attached to another bridge, "
+ "can't direct change it.",
+ piface->name);
+ ret = ERR_DEVICE_CONNECT_OTHER;
+ goto out;
+ }
+
+ /* building up command line */
+ cmd[sizeof(cmd)-1] = 1;
+ snprintf(cmd, sizeof(cmd), "brctl addif %s %s",
+ pbr->name, piface->name);
+ if (cmd[sizeof(cmd)-1] == '\0') {
+ CU_DEBUG("cmd line too long, it is [%s].", cmd);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ /* if the configuration file do not exist, would not create it */
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ ret = configure_file_replace_attr(path, "BRIDGE=", pbr->name);
+ SAFE_FREE(path);
+ if (ret != 1) {
+ CU_DEBUG("error happened in persisting file.");
+ goto out;
+ }
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+int remove_host_iface_from_br_cmd(EthIface *piface, EthIface *pbr,
+ int persist_flag)
+{
+ FILE *stream = NULL;
+ char cmd[64];
+ char *buff = NULL;
+ int ret = 0;
+ int check_value;
+ char *path_prefix = IFACE_CONFIG_FILE_PREFIX_RH;
+ char *path;
+
+ SAFE_MALLOC(buff, CONT_BUFF_SIZE);
+ if ((piface->name == NULL) || (pbr->name == NULL)) {
+ ret = ERR_COMMAND_PARAMETER_WRONG;
+ CU_DEBUG("name was not set, direct goto out.");
+ goto out;
+ }
+
+ check_value = host_br_have_iface_attached_cmd(pbr, piface, NULL);
+ if (check_value < 0) {
+ CU_DEBUG("iface %s or bridge %s do not exist, direct goto out.",
+ piface->name, pbr->name);
+ ret = ERR_DEVICE_NOT_EXIST;
+ goto out;
+ } else if (check_value == 0) {
+ CU_DEBUG("iface %s is not attached to bridge %s, can't remove
it.",
+ piface->name, pbr->name);
+ ret = ERR_DEVICE_ALREADY_DONE;
+ goto out;
+ } else if (check_value == 2) {
+ CU_DEBUG("iface %s is attached to another device, can't remove
it.",
+ piface->name);
+ ret = ERR_DEVICE_CONNECT_OTHER;
+ goto out;
+ }
+
+ /* building up command line */
+ cmd[sizeof(cmd)-1] = 1;
+ snprintf(cmd, sizeof(cmd), "brctl delif %s %s",
+ pbr->name, piface->name);
+ if (cmd[sizeof(cmd)-1] == '\0') {
+ CU_DEBUG("cmd line too long, it is [%s].", cmd);
+ ret = ERR_COMMAND_NO_READY;
+ goto out;
+ }
+
+ stream = pipe_excute_command_type_write(cmd, sizeof(cmd), "r", &ret);
+ if (stream == NULL) {
+ goto out;
+ }
+
+ while (fgets(buff, CONT_BUFF_SIZE, stream) != NULL) {
+ CU_DEBUG("get exception: %s", buff);
+ ret = ERR_COMMAND_EXECUTION;
+ goto out;
+ }
+
+ if (persist_flag == 1) {
+ /* if the configuration file do not exist, would not create it */
+ if (LINUX_REDHAT != get_host_linux_version()) {
+ ret = ERR_PERSIST_NOT_REDHAT;
+ CU_DEBUG("Host is not a RedHat version, return is %d",
+ get_host_linux_version());
+ goto out;
+ }
+ path = combine_file_name(path_prefix, piface->name);
+ ret = configure_file_replace_attr(path, "BRIDGE=", NULL);
+ SAFE_FREE(path);
+ if (ret != 1) {
+ CU_DEBUG("error happened in persisting file.");
+ goto out;
+ }
+ }
+ ret = 1;
+
+out:
+ if (stream != NULL) {
+ pclose(stream);
+ stream = NULL;
+ }
+ SAFE_FREE(buff);
+
+ return ret;
+}
+
+static void merge_eth_list(EthIfacesList *pdest, EthIfacesList *psrc, int flag)
+{
+ int i, j;
+ i = 0;
+ while (i < pdest->count) {
+ j = 0;
+ while (j < psrc->count) {
+ if (1 == eth_iface_compare(pdest->pifaces[i], psrc->pifaces[j])) {
+ /* found the matched device, merge them */
+ eth_iface_merge(pdest->pifaces[i], psrc->pifaces[j], flag);
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+ return;
+}
+
+static void find_iface_attached_bridge(EthIfacesList *peth_list, EthIface *pbr)
+{
+ int i, j;
+ char *name_on_br, *name_iface;
+ if (pbr->pbr_prop == NULL) {
+ return;
+ }
+ i = 0;
+ while (i < pbr->pbr_prop->port_num) {
+ name_on_br = pbr->pbr_prop->port_names[i];
+ j = 0;
+ while (j < peth_list->count) {
+ name_iface = peth_list->pifaces[j]->name;
+ if (0 == strcmp(name_on_br, name_iface)) {
+ if (peth_list->pifaces[j]->attach_bridge == NULL) {
+ peth_list->pifaces[j]->attach_bridge =
+ SAFE_STRDUP(pbr->name);
+ }
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+}
+
+/* assuming that one peth would be attached to at most 1 bridge */
+static void merge_eth_list_for_bridge(EthIfacesList *peth_list,
+ EthIfacesList *pbr_list,
+ int flag)
+{
+ int i, j;
+ i = 0;
+ while (i < pbr_list->count) {
+ find_iface_attached_bridge(peth_list, pbr_list->pifaces[i]);
+ j = 0;
+ while (j < peth_list->count) {
+ if (1 == eth_iface_compare(peth_list->pifaces[j],
+ pbr_list->pifaces[i])) {
+ /* found the matched device, merge them */
+ eth_iface_merge(peth_list->pifaces[j],
+ pbr_list->pifaces[i], flag);
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+ return;
+}
+
+int get_host_eth_ifaces_cmd_all(EthIfacesList *plist,
+ eth_iface_filter_func filter_func, void *filter_opaque)
+{
+ int retvalue;
+ EthIfacesList *ifaces1, *ifaces2;
+ int i;
+ int filter_ret;
+ int count = 0;
+ SAFE_MALLOC(ifaces1, sizeof(EthIfacesList));
+ SAFE_MALLOC(ifaces2, sizeof(EthIfacesList));
+ eth_ifaceslist_init(ifaces1);
+ eth_ifaceslist_init(ifaces2);
+
+ retvalue = get_host_eth_ifaces_ip_addr(ifaces1->pifaces,
&(ifaces1->count),
+ MAX_IFACE_NUM, NULL, NULL);
+ if (retvalue != 1) {
+ goto out;
+ }
+
+
+ retvalue = get_host_eth_ifaces_ifconfig(ifaces2->pifaces,
&(ifaces2->count),
+ MAX_IFACE_NUM, NULL, NULL);
+ if (retvalue != 1) {
+ goto out;
+ }
+ /* merge the information */
+ merge_eth_list(ifaces1, ifaces2, 1);
+ eth_ifaceslist_uninit(ifaces2);
+
+ retvalue = get_host_eth_ifaces_brctl(ifaces2->pifaces, &(ifaces2->count),
+ MAX_IFACE_NUM, NULL, NULL);
+ if (retvalue != 1) {
+ goto out;
+ }
+ /* merge the information */
+ merge_eth_list_for_bridge(ifaces1, ifaces2, 1);
+ eth_ifaceslist_uninit(ifaces2);
+
+ retvalue = get_host_eth_ifaces_cat_vlan_config(ifaces2->pifaces,
+ &(ifaces2->count), MAX_IFACE_NUM, NULL, NULL);
+ if (retvalue != 1) {
+ goto out;
+ }
+
+ /* merge the information */
+ merge_eth_list(ifaces1, ifaces2, 1);
+ eth_ifaceslist_uninit(ifaces2);
+
+ /* filter the result */
+ i = 0;
+ while (i < ifaces1->count) {
+ /* see if the result need to be put to the list */
+ filter_ret = 1;
+ if (filter_func != NULL) {
+ filter_ret = filter_func(ifaces1->pifaces[i], filter_opaque);
+ }
+ if (filter_ret == 1) {
+ if (count >= MAX_IFACE_NUM) {
+ retvalue = ERR_DEVICE_EXCEED_MAXNUM;
+ goto out;
+ }
+ host_iface_adjust(ifaces1->pifaces[i]);
+ plist->pifaces[count] = ifaces1->pifaces[i];
+ ifaces1->pifaces[i] = NULL;
+ count++;
+ }
+ i++;
+ }
+
+ out:
+ eth_ifaceslist_uninit(ifaces1);
+ SAFE_FREE(ifaces1);
+ eth_ifaceslist_uninit(ifaces2);
+ SAFE_FREE(ifaces2);
+ plist->count = count;
+ return retvalue;
+}
diff --git a/libxkutil/host_network_implement_cmdline.h
b/libxkutil/host_network_implement_cmdline.h
new file mode 100644
index 0000000..90e5891
--- /dev/null
+++ b/libxkutil/host_network_implement_cmdline.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc(a)cn.ibm.com>
+ *
+ * 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.
+ */
+
+#ifndef HOST_NETWORK_IMPLEMENT_CMDLINE_H
+#define HOST_NETWORK_IMPLEMENT_CMDLINE_H
+
+#include "host_network_basic.h"
+
+int get_host_eth_ifaces_ip_addr(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque);
+
+int get_host_eth_ifaces_ifconfig(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque);
+
+int get_host_eth_ifaces_brctl(EthIface **ppifaces, int *retnum, int maxnum,
+ eth_iface_filter_func filter_func, void *filter_opaque);
+
+int get_host_eth_ifaces_cat_vlan_config(EthIface **ppifaces, int *retnum,
+ int maxnum, eth_iface_filter_func filter_func, void *filter_opaque);
+
+int get_host_eth_ifaces_cmd_all(EthIfacesList *plist,
+ eth_iface_filter_func filter_func, void *filter_opaque);
+
+int add_host_br_cmd(EthIface *piface, int persist_flag);
+int del_host_br_cmd(EthIface *piface, int persist_flag);
+int mod_host_br_cmd(EthIface *piface, int persist_flag);
+int add_host_iface_to_br_cmd(EthIface *piface, EthIface *pbr,
+ int persist_flag);
+int remove_host_iface_from_br_cmd(EthIface *piface, EthIface *pbr,
+ int persist_flag);
+
+int add_host_vlan_8021q_cmd(EthIface *piface, int persist_flag);
+int del_host_vlan_8021q_cmd(EthIface *piface, int persist_flag);
+int mod_host_vlan_8021q_cmd(EthIface *piface, int persist_flag);
+
+int change_state_host_iface_cmd(EthIface *piface, int state);
+
+int host_br_have_iface_attached_cmd(EthIface *pbr, EthIface *piface,
+ EthIface **ppbr_result);
+
+/* check a batch of iface's state with one call of get_host_ifaces,
+ retvalues must be allocated big enough */
+int host_ifacelist_is_present_cmd(EthIfacesList *plist, int *retvalues,
+ int compare_name_only);
+
+#endif
--
1.7.6