This patch have help functions for libnetwork. It contains macro defines
and help functions for host network configuration. It also provide some basic
function such as conditional merge char*, int and properties of structure
EthIface.
Signed-off-by: Wenchao Xia <xiawenc(a)cn.ibm.com>
---
libnetwork/dll_magic.h | 13 ++
libnetwork/host_network_error.h | 23 ++++
libnetwork/host_network_helper.c | 266 ++++++++++++++++++++++++++++++++++++++
libnetwork/host_network_helper.h | 177 +++++++++++++++++++++++++
4 files changed, 479 insertions(+), 0 deletions(-)
create mode 100644 libnetwork/dll_magic.h
create mode 100644 libnetwork/host_network_error.h
create mode 100644 libnetwork/host_network_helper.c
create mode 100644 libnetwork/host_network_helper.h
diff --git a/libnetwork/dll_magic.h b/libnetwork/dll_magic.h
new file mode 100644
index 0000000..36bca83
--- /dev/null
+++ b/libnetwork/dll_magic.h
@@ -0,0 +1,13 @@
+#ifndef DLL_MAGIC_H
+#define DLL_MAGIC_H
+
+
+#if __GNUC__ >= 4
+ #ifdef DLL_BUILD
+ #define DLL_PUBLIC __attribute__ ((visibility ("default")))
+ #else
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+#endif
diff --git a/libnetwork/host_network_error.h b/libnetwork/host_network_error.h
new file mode 100644
index 0000000..1882172
--- /dev/null
+++ b/libnetwork/host_network_error.h
@@ -0,0 +1,23 @@
+#ifndef HOST_NETWORK_ERROR_H
+#define HOST_NETWORK_ERROR_H
+
+#define ERR_REQUEST_NOT_SUPPORT -1
+
+#define ERR_LIBNETLINK -80
+#define ERR_LIBBR -90
+
+#define ERR_DEVICE_EXCEED_MAXNUM -100
+#define ERR_DEVICE_EXIST -101
+#define ERR_DEVICE_NOT_EXIST -102
+#define ERR_DEVICE_ALREADY_DONE -103
+#define ERR_DEVICE_CONNECT_OTHER -104
+
+#define ERR_FILE_OP_FAIL -125
+#define ERR_FILE_EMPTY -126
+#define ERR_FILE_TOO_LARGE -127
+#define ERR_FILE_CONT_TOO_LARGE -128
+#define ERR_FILE_LOCK_FAIL -129
+
+#define ERR_PERSIST_NOT_REDHAT -200
+
+#endif
diff --git a/libnetwork/host_network_helper.c b/libnetwork/host_network_helper.c
new file mode 100644
index 0000000..cda2732
--- /dev/null
+++ b/libnetwork/host_network_helper.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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.
+ */
+
+
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+static int compare_qos_8021q(const void *p1, const void *p2)
+{
+ const VLAN_Qos_8021q_elem *qos1 = (VLAN_Qos_8021q_elem *)p1;
+ const VLAN_Qos_8021q_elem *qos2 = (VLAN_Qos_8021q_elem *)p2;
+ int ret = 0;
+ if ((qos1->from) > (qos2->from)) {
+ ret = 1;
+ }
+ return ret;
+}
+
+/* it need to be checked see whether these are the conditions */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos)
+{
+ int ret = 1;
+ int i = 0;
+ int last_num = -1;
+ if ((pqos->count < 0) || (pqos->count > 8)) {
+ ret = 0;
+ goto out;
+ } else if (pqos->count == 0) {
+ goto out;
+ }
+ qsort((void *)pqos->values, pqos->count, sizeof(VLAN_Qos_8021q_elem),
+ compare_qos_8021q);
+
+ while (i < pqos->count) {
+ if (pqos->values[i].from == last_num) {
+ CU_DEBUG("error: vlan 802.1.q qos setting have same <from> values:
"
+ "last is %d, new is %d", last_num,
pqos->values[i].from);
+ ret = 0;
+ goto out;
+ }
+ last_num = pqos->values[i].from;
+ if ((pqos->values[i].from < 0) || (pqos->values[i].from >= 8)) {
+ CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+ "from is %d.", pqos->values[i].from);
+ ret = 0;
+ goto out;
+ }
+ if ((pqos->values[i].to < 0) || (pqos->values[i].to >= 8)) {
+ CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+ "to is %d.", pqos->values[i].to);
+ ret = 0;
+ goto out;
+ }
+ i++;
+ }
+
+ out:
+ return ret;
+}
+
+int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char* str)
+{
+ int ret = 1;
+ char *str_line = NULL;
+ char *temp;
+ char *saveptr = NULL;
+ char *invalptr1, *invalptr2;
+ int qos_num1, qos_num2;
+ VLAN_Qos_8021q qos;
+
+ if (str == NULL) {
+ ret = 0;
+ goto out;
+ }
+ if (str[0] == '\0') {
+ ret = 1;
+ pqos->count = 0;
+ CU_DEBUG("empty vlan 802.1.q qos string found.");
+ goto out;
+ }
+ str_line = SAFE_STRDUP(str);
+ qos.count = 0;
+
+ temp = strtok_r(str_line, " ", &saveptr);
+ while (temp != NULL) {
+ qos_num1 = strtol(temp, &invalptr1, 10);
+ if (temp == invalptr1) {
+ ret = 0;
+ goto out;
+ }
+ if (*invalptr1 != ':') {
+ ret = 0;
+ goto out;
+ }
+ invalptr1++;
+ qos_num2 = strtol(invalptr1, &invalptr2, 10);
+ if (invalptr1 == invalptr2) {
+ ret = 0;
+ goto out;
+ }
+ if (*invalptr2 != '\0') {
+ ret = 0;
+ goto out;
+ }
+ if (qos.count >= 8) {
+ ret = 0;
+ CU_DEBUG("too many settings found in vlan 802.1.q qos string
[%s]",
+ str);
+ goto out;
+ }
+ qos.values[qos.count].from = qos_num1;
+ qos.values[qos.count].to = qos_num2;
+ qos.count++;
+ temp = strtok_r(NULL, " ", &saveptr);
+ }
+ ret = vlan_8021q_qos_check_valid(&qos);
+ if (ret == 1) {
+ *pqos = qos;
+ }
+
+ out:
+ if (ret != 1) {
+ CU_DEBUG("vlan 802.1.q qos string [%s] is invalid.", str);
+ }
+ SAFE_FREE(str_line);
+ return ret;
+}
+
+int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos)
+{
+ char temp[16];
+ int i;
+ VLAN_Qos_8021q qos = *pqos;
+ int ret = vlan_8021q_qos_check_valid(&qos);
+ if (ret != 1) {
+ goto out;
+ }
+ SAFE_MALLOC(*str, 64);
+ *str[0] = '\0';
+ if (qos.count == 0) {
+ goto out;
+ }
+ i = 0;
+ snprintf(temp, sizeof(temp), "%d:%d",
+ qos.values[i].from, qos.values[i].to);
+ strcat(*str, temp);
+ i++;
+ while (i < qos.count) {
+ strcat(*str, " ");
+ snprintf(temp, sizeof(temp), "%d:%d",
+ qos.values[i].from, qos.values[i].to);
+ strcat(*str, temp);
+ i++;
+ }
+
+ out:
+ return ret;
+}
+
+char *combine_file_name(const char *prefix, const char *name)
+{
+ char *ret = NULL;
+ int size;
+ size = strlen(prefix) + strlen(name) + 1;
+ SAFE_CALLOC(ret, size, sizeof(char));
+ snprintf(ret, size, "%s%s", prefix, name);
+ return ret;
+}
+
+char *translate_error_no(int errno)
+{
+ char *ret = NULL;
+ switch (errno) {
+ case ERR_REQUEST_NOT_SUPPORT:
+ ret = "request is not supported now";
+ break;
+
+ case ERR_LIBNETLINK:
+ ret = "error happend in netlink.";
+ break;
+ case ERR_LIBBR:
+ ret = "error happend in bridge commands.";
+ break;
+
+ case ERR_DEVICE_EXCEED_MAXNUM:
+ ret = "too many devices found or set, check the environment.";
+ break;
+ case ERR_DEVICE_EXIST:
+ ret = "device already exist, can not execute the command.";
+ break;
+ case ERR_DEVICE_NOT_EXIST:
+ ret = "device do not exist, can not execute the command.";
+ break;
+ case ERR_DEVICE_ALREADY_DONE:
+ ret = "the operation you want have been done before, "
+ "will not do it again.";
+ break;
+ case ERR_DEVICE_CONNECT_OTHER:
+ ret = "the device you want to connect have been connect to another"
+ " device, can't change it directly.";
+ break;
+
+ case ERR_FILE_OP_FAIL:
+ ret = "failed in accessing the file.";
+ break;
+ case ERR_FILE_EMPTY:
+ ret = "the file it want is empty.";
+ break;
+ case ERR_FILE_TOO_LARGE:
+ ret = "the file it want is too large.";
+ break;
+ case ERR_FILE_CONT_TOO_LARGE:
+ ret = "the content it want to combine to file is too large.";
+ break;
+ case ERR_FILE_LOCK_FAIL:
+ ret = "failed in locking the file, "
+ "check if other process is using it.";
+ break;
+
+ case ERR_PERSIST_NOT_REDHAT:
+ ret = "host is not a RedHat distribution, can't persist the "
+ "configuration, it would not take effect after host is "
+ "rebooted. Other version would be supported in the future. "
+ "If you are sure host is RedHat, make sure command "
+ "<lsb_release -a> could work.";
+ break;
+
+ default:
+ ret = "internal error.";
+ break;
+ }
+ return ret;
+}
+
+int get_simple_state(struct EthIface *piface)
+{
+ if ((piface->eth_type & ETH_TYPE_ETHER_ANY) &&
+ (piface->eth_type & ETH_TYPE_ETHER_SUB_BRIDGE)) {
+ if (piface->run_prop.status == IF_OPER_UNKNOWN) {
+ return 1;
+ }
+ }
+ if (piface->run_prop.status == IF_OPER_UP) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/libnetwork/host_network_helper.h b/libnetwork/host_network_helper.h
new file mode 100644
index 0000000..fea4f05
--- /dev/null
+++ b/libnetwork/host_network_helper.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * 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_HELPER_H
+#define HOST_NETWORK_HELPER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "dll_magic.h"
+#include "host_network_basic.h"
+
+#ifdef TESTLIB
+#include "TestDefines.h"
+#else
+#include <libcmpiutil/libcmpiutil.h>
+#endif
+
+#define CMD_DEBUG_LEVEL 2
+
+/* macro functions */
+#define CMD_DEBUG(lvl, fmt, args...) do { \
+ if (CMD_DEBUG_LEVEL && (lvl) <= CMD_DEBUG_LEVEL) { \
+ debug_print(fmt, ##args); \
+ } \
+} while (0)
+
+#define SAFE_MALLOC(p, size) \
+{ \
+ (p) = malloc((size)); \
+ if ((p) == NULL) { \
+ CU_DEBUG("malloc failed."); \
+ } \
+}
+
+#define SAFE_CALLOC(p, nmen, size) \
+{ \
+ (p) = calloc((nmen), (size)); \
+ if ((p) == NULL) { \
+ CU_DEBUG("calloc failed."); \
+ } \
+}
+
+#define SAFE_FREE(p) {free(p); (p) = NULL; }
+
+
+/* Macro used to compare two char*, it would skip if ref is NULL. It would
+ only set the result when src != ref, user need to set the result to 1 by
+ default before use the macro. If not set, the it could be used to do
+ check multi times in "one fail all die" mode. Empty lines is the place
+ where result should be set to 1. */
+#define CHARS_COMPARE_BY_REF(src, ref, result) do { \
+ if ((ref) == NULL) { \
+ ; \
+ } else { \
+ if ((src) == NULL) { \
+ (result) = 0; \
+ } else { \
+ if (0 == strcmp((src), (ref))) { \
+ ; \
+ } else { \
+ (result) = 0; \
+ } \
+ } \
+ } \
+} while (0)
+
+/* ignore case version */
+#define CHARS_COMPARE_CASE_BY_REF(src, ref, result) do { \
+ if ((ref) == NULL) { \
+ ; \
+ } else { \
+ if ((src) == NULL) { \
+ (result) = 0; \
+ } else { \
+ if (0 == strcasecmp((src), (ref))) { \
+ ; \
+ } else { \
+ (result) = 0; \
+ } \
+ } \
+ } \
+} while (0)
+
+/* compare the value if ref != default */
+#define NUM_COMPARE_BY_REF(src, ref, result, default) do { \
+ if ((ref) == (default)) { \
+ ; \
+ } else { \
+ if ((src) == (ref)) { \
+ ; \
+ } else { \
+ result = 0; \
+ } \
+ } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL */
+#define CHARS_MERGE_NORMAL(dest, src) do { \
+ if (((dest) == NULL) && ((src) != NULL)) { \
+ (dest) = strdup((src)); \
+ } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL,
+ pointer is moved instead of strdup */
+#define CHARS_MERGE_MOVE(dest, src) do { \
+ if (((dest) == NULL) && ((src) != NULL)) { \
+ (dest) = (src); \
+ (src) = NULL; \
+ } \
+} while (0)
+
+/* merge the value, only when dest == default */
+#define NUM_MERGE(dest, src, default) do { \
+ if ((dest) == (default)) { \
+ (dest) = (src); \
+ } \
+} while (0)
+
+/* this macro may cause "p" to be excuted twice if it is a function */
+#define SAFE_STRDUP(p) (p) == NULL ? NULL : strdup(p);
+
+/* this macro make sure "src" to be excuted once if it is function, so it is
+ safe for functions that have state logged, such as "strtok" */
+#define SAFE_STRDUP_WITH_FUNC(dest, src, iter) do { \
+ (iter) = (src); \
+ if ((iter) == NULL) { \
+ (dest) = NULL; \
+ } else { \
+ (dest) = strdup((iter)); \
+ } \
+} while (0)
+
+/* array version of SAFE_STRDUP, dest and src are char**. */
+#define SAFE_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter) do { \
+ (dest_num) = (src_num); \
+ (ppdest) = NULL; \
+ if (((ppsrc) != NULL) && ((src_num) > 0)) { \
+ SAFE_CALLOC((ppdest), (src_num), sizeof(char *)); \
+ (iter) = 0; \
+ while ((iter) < (src_num)) { \
+ *((ppdest)+(iter)) = SAFE_STRDUP(*((ppsrc)+(iter))); \
+ (iter)++; \
+ } \
+ } \
+} while (0)
+
+/* this function would sort the pqos and check its values. */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos);
+
+/* converting qos string of 802.1.Q, it should be as "0:0 1:0 2:0" */
+DLL_PUBLIC int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char *str);
+DLL_PUBLIC int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos);
+
+/* following functions would return string by malloc, so it need free later */
+char *combine_file_name(const char *prefix, const char *name);
+
+/* translate the iffstate to simple down or up, because orginal state is
+ complex for history reason in linux kernel */
+DLL_PUBLIC int get_simple_state(struct EthIface *piface);
+
+/* err message number to char* */
+char *translate_error_no(int errno);
+
+#endif
--
1.7.1