/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_sysvar.c,v $ $Revision: 1.20.10.1 $ * $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_sysvar.c,v $ * $Author: jsheng $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmip_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #ifdef IPMIP_USE_INET6 #include #endif #include #include #include #include /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2 #define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* Information required to process the 'forech' */ typedef struct Ipmip_sysvar_foreach_cbinfo { Ip_u32 baselen; void *opaque; Ipmip_sysvar_foreach_t cb_func; Ipmip_proc_t *proc; } Ipmip_sysvar_foreach_cbinfo_t; typedef struct Ipmip_sysvar_foreach_cbinfo_ext { Ip_u32 baselen; void *opaque; void *ctx; Ipmip_sysvar_foreach_ext_t cb_func; Ipmip_proc_t *proc; } Ipmip_sysvar_foreach_cbinfo_ext_t; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ const char *ipmip_sysvar_mode_desc[] = { "disabled", "optional", "required" }; const Ipmip_sysvar_key_map_t ipmip_sysvar_bool_ops[] = { { 1, "enable" }, { 1, "enabled" }, { 1, "true" }, { 1, "on" }, { 1, "yes" }, { 0, "disable" }, { 0, "disabled" }, { 0, "false" }, { 0, "off" }, { 0, "no" }, { 0, 0 } }; const Ipmip_sysvar_key_map_t ipmip_sysvar_tunnel_mask[] = { { IPMIP_TUNNELMASK_GRE, "gre" }, { IPMIP_TUNNELMASK_IP, "ip" }, { IPMIP_TUNNELMASK_INET6, "inet6" }, { IPMIP_TUNNELMASK_INET, "inet" }, { IPMIP_TUNNELMASK_INET_GRE, "inet.gre" }, { IPMIP_TUNNELMASK_INET6_GRE6, "inet6.gre" }, { IPMIP_TUNNELMASK_INET_IPIP, "inet.ipip" }, { IPMIP_TUNNELMASK_INET_IPIP, "inet.ip" }, { IPMIP_TUNNELMASK_INET6_IP6IP6, "inet6.ip6ip6" }, { IPMIP_TUNNELMASK_INET6_IP6IP6, "inet6.ip" }, { IPMIP_TUNNELMASK_INET_MINENC, "inet.minenc" }, { IPMIP_TUNNELMASK_INET_MINENC, "minenc" }, { 0, 0 } }; /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip_sysvar_foreach_parse *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipmip_sysvar_foreach_parse(const char *name, const char *value, int flags, Ipmip_sysvar_foreach_cbinfo_t *data) { Ip_size_t blen = data->baselen; (void) (flags); if (name[blen] == '.') blen++; (*data->cb_func) (data->proc, name, &name[blen], value, data->opaque); return IPCOM_SUCCESS; } IP_STATIC int ipmip_sysvar_foreach_ext_parse(const char *name, const char *value, int flags, Ipmip_sysvar_foreach_cbinfo_ext_t *data) { Ip_size_t blen = data->baselen; (void) (flags); if (name[blen] == '.') blen++; (*data->cb_func) (data->ctx, data->proc, name, &name[blen], value, data->opaque); return IPCOM_SUCCESS; } /* *=========================================================================== * ipmip_sysvar_get *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC char * ipmip_sysvar_get(const char *format, va_list ap) { char *buf = IP_NULL; char *result = IP_NULL; buf = ipmip_util_vstrdup(format, ap); if (buf == IP_NULL) goto done_out; /* Get the sysvar */ result = ipcom_sysvar_get(buf, IP_NULL, IP_NULL); /* Dont allow zero length results */ if (result && ipcom_strlen(result) == 0) { ipcom_free(result); result = IP_NULL; } done_out: if (buf) ipcom_free(buf); return result; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip_sysvar_cmd_str_to_key *=========================================================================== * Description: Converts the string representation in map to the numeric value. * Parameters: map - The int to string map to use. * key - The protocol number. * Returns: The string represenstion. * */ IP_GLOBAL int ipmip_sysvar_cmd_str_to_key(const Ipmip_sysvar_key_map_t *map, const char *str) { int i; if (str) { int ival; /**/ for (i = 0; map[i].str != IP_NULL; i++) if (ipcom_strcasecmp(str, map[i].str) == 0) return map[i].key; /**/ ival = (int)ipcom_strtol(str, IP_NULL, 10); for (i = 0; map[i].str != IP_NULL; i++) if (map[i].key == ival) return ival; } return -1; } /* *=========================================================================== * ipmip_sysvar_set *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipmip_sysvar_set(const char *value, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_util_vstrdup(format, ap); va_end(ap); if(IP_NULL == buf) return; (void)ipcom_sysvar_set(buf, value, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_free(buf); } IP_GLOBAL void ipmip_sysvar_set_ulong(unsigned long value, const char *format, /* args*/ ...) { va_list ap; char *buf; char *vbuf;; va_start(ap, format); buf = ipmip_util_vstrdup(format, ap); va_end(ap); if(IP_NULL == buf) return; /* Create me a value */ vbuf = ipmip_util_strdup("%u", value); (void)ipcom_sysvar_set(buf, vbuf, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_free(buf); ipcom_free(vbuf); } /* *=========================================================================== * ipmip_sysvar_unset *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipmip_sysvar_unset(const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_util_vstrdup(format, ap); va_end(ap); if(IP_NULL == buf) return; ipcom_sysvar_unset(buf); ipcom_free(buf); } /* *=========================================================================== * ipmip_vsysvar *=========================================================================== * Description: Return the configuration system variable value pointer to * by the format string and the provided optional arguments. * The return value is dynamically allocated, and must be * freed by the caller. * Parameters: format - Format string * ap - Optional arguments * Returns: The configuration string value * */ IP_GLOBAL char * ipmip_vsysvar(const char *format, va_list ap) { return ipmip_sysvar_get(format, ap); } /* *=========================================================================== * ipmip_sysvar *=========================================================================== * Description: Return the configuration system variable value pointer to * by the format string and the provided optional arguments. * The return value is dynamically allocated, and must be * freed by the caller. * Parameters: format - Format string * ... - Optional arguments * Returns: The configuration string value * */ IP_GLOBAL char * ipmip_sysvar(const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); return buf; } /* *=========================================================================== * ipmip_sysvar_mode *=========================================================================== * Description: Parse and return a mode value, where mode is either DISABLED, * OPTIONAL or REQUIRED. DISABLED equals integer 0, or 'disable', * 'disabled', 'false' or 'no'. OPTIONAL equals integer 1, or * 'optional' or 'may'. REQUIRED equals 'yes', 'true', integer 2, * 'enable', 'enabled' or 'required' * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: IPMIP4_SYSVAR_MODE_DISABLED, IPMIP4_SYSVAR_MODE_OPTIONAL or * IPMIP4_SYSVAR_MODE_REQUIRED * */ IP_GLOBAL int ipmip_sysvar_mode(int defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { int op_val = -1; static Ipmip_sysvar_key_map_t ops[] = { { IPMIP_SYSVAR_MODE_REQUIRED, "enable" }, { IPMIP_SYSVAR_MODE_REQUIRED, "enabled" }, { IPMIP_SYSVAR_MODE_REQUIRED, "required" }, { IPMIP_SYSVAR_MODE_REQUIRED, "true" }, { IPMIP_SYSVAR_MODE_REQUIRED, "on" }, { IPMIP_SYSVAR_MODE_REQUIRED, "yes" }, { IPMIP_SYSVAR_MODE_OPTIONAL, "optional" }, { IPMIP_SYSVAR_MODE_OPTIONAL, "option" }, { IPMIP_SYSVAR_MODE_OPTIONAL, "may" }, { IPMIP_SYSVAR_MODE_DISABLED, "disable" }, { IPMIP_SYSVAR_MODE_DISABLED, "disabled" }, { IPMIP_SYSVAR_MODE_DISABLED, "false" }, { IPMIP_SYSVAR_MODE_DISABLED, "off" }, { IPMIP_SYSVAR_MODE_DISABLED, "no" }, { 0, 0 } }; /**/ op_val = ipmip_sysvar_cmd_str_to_key(ops, buf); if (op_val != -1) defval = op_val; ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_key *=========================================================================== * Description: Parse a sysvar key and map it to an option * Parameters: defval - Default value * map - Key options * format - Format string * ... - Optional arguments * Returns: -1 on failure; key value otherwise. * */ IP_GLOBAL int ipmip_sysvar_key(int defval, Ipmip_sysvar_key_map_t *map, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /**/ defval = ipmip_sysvar_cmd_str_to_key(map, buf); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_bool *=========================================================================== * Description: Parse and return a boolean value; A boolean value is either * a numerical value, where != 0,enabled, enable, yes or true * equals IP_TRUE, or 0, disabled, disable, no or false which equals * IP_FALSE. If the system variable doesn't exist, the provided * default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration value; IP_TRUE or IP_FALSE. * */ IP_GLOBAL Ip_bool ipmip_sysvar_bool(Ip_bool defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { int op_val = -1; /**/ op_val = ipmip_sysvar_cmd_str_to_key(ipmip_sysvar_bool_ops, buf); if (op_val != -1) defval = op_val; ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_ulong *=========================================================================== * Description: Parse and return an unsigned long value; If the system variable * doesn't exist, the provided default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration integer value * */ IP_GLOBAL unsigned long ipmip_sysvar_ulong(unsigned long defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /* Non zero? */ defval = ipcom_strtoul(buf, IP_NULL, 0); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_u32 *=========================================================================== * Description: Parse and return an u32; If the system variable * doesn't exist, the provided default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration integer value * */ IP_GLOBAL Ip_u32 ipmip_sysvar_u32(Ip_u32 defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /* Non zero? */ defval = (Ip_u32)ipcom_strtoul(buf, IP_NULL, 0); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_ushort *=========================================================================== * Description: Parse and return an unsigned long value; If the system variable * doesn't exist, the provided default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration integer value * */ IP_GLOBAL unsigned short ipmip_sysvar_ushort(unsigned short defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /* Non zero? */ defval = (unsigned short)ipcom_strtoul(buf, IP_NULL, 0); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_long *=========================================================================== * Description: Parse and return a long value; If the system variable * doesn't exist, the provided default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration integer value * */ IP_GLOBAL long ipmip_sysvar_long(long defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /* Non zero? */ defval = ipcom_strtol(buf, IP_NULL, 0); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_long *=========================================================================== * Description: Parse and return a long value; If the system variable * doesn't exist, the provided default value will be returned. * Parameters: defval - The default value. * format - Format string * ... - Optional arguments * Returns: The configuration integer value * */ IP_GLOBAL short ipmip_sysvar_short(short defval, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { /* Non zero? */ defval = (short)ipcom_strtol(buf, IP_NULL, 0); ipcom_free(buf); } return defval; } /* *=========================================================================== * ipmip_sysvar_strlist *=========================================================================== * Description: Parse and return a string array of the format * .. where length * is 1 byte, and string is a zero terminated; the length includes * the zero termination and the length byte; the array is * terminated by a length byte with value 0. The returned data is * dynamically allocated and must be freed by the caller. num * entries is a one byte entry indicating the number of strings * stored in the array. * Parameters: format - Format string * ... - format arguments * Returns: The strlist array * */ IP_GLOBAL Ip_u8 * ipmip_sysvar_strlist(const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { Ip_u8 *dblock = ipmip_util_explode(buf); ipcom_free(buf); if (dblock) { if (*dblock != 0) return dblock; ipcom_free(dblock); } } return IP_NULL; } /* *=========================================================================== * ipmip_sysvar_strarr *=========================================================================== * Description: Parse and return a string array with the last item set as * IP_NULL. * Parameters: format - Format string * ... - format arguments * Returns: The string pointer array * */ IP_GLOBAL char ** ipmip_sysvar_strarr(const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { char **arr = ipmip_util_strarr(buf, IP_NULL); ipcom_free(buf); return arr; } return IP_NULL; } /* *=========================================================================== * ipmip_sysvar_array *=========================================================================== * Description: Parse and return an array of configuration options where each * string will be matched to a configuration value and returned * in a dynamically allocated integer array terminated with the * value 0xffffffff. The integer array must be freed by the caller. * Parameters: ops - Options for parsing the strings * format - Format string * ... - Optional arguments * Returns: The integer array. * */ IP_GLOBAL int * ipmip_sysvar_array(Ipmip_sysvar_key_map_t *ops, const char *format, /* args*/ ...) { va_list ap; char *buf; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Parse the value */ if (buf) { Ip_u8 *dblock = ipmip_util_explode(buf); Ip_u8 nelem; Ip_u8 nsize; Ip_u8 *sptr; int *iarr; int idx; ipcom_free(buf); if (dblock == IP_NULL) return IP_NULL; nelem = *dblock; sptr = dblock + 1; if (nelem == 0) { ipcom_free(dblock); return IP_NULL; } iarr = ipcom_malloc((nelem + 1) * sizeof(int)); if (iarr == IP_NULL) { ipcom_free(dblock); return IP_NULL; } idx = 0; while ((nsize = *sptr) != 0) { int opt_val = ipmip_sysvar_cmd_str_to_key(ops, (char *)(sptr + 1)); if (opt_val != -1) { iarr[idx++] = opt_val; } sptr += nsize; } /* Terminate */ iarr[idx] = -1; ipcom_free(dblock); return iarr; } return IP_NULL; } #ifdef IPMIP_USE_INET /* *=========================================================================== * ipmip_sysvar_inet *=========================================================================== * Description: Read a sysvar variable and convert it to an IPv4 address and * prefix. If plen is specified; it will look for / prefix * indicator, if not available, prefix will be 32. * Parameters: defip - Default value * addr - The addr to store the result in. * plen - Prefix length.[may be NULL] * format - Format string * ... - Arguments. * Returns: IP_TRUE on success; IP_FALSE otherwise * */ IP_GLOBAL Ip_bool ipmip_sysvar_inet(Ip_u32 defip, Ip_u32 *addr, Ip_u32 *plen, const char *format, /* args*/ ...) { char *buf; va_list ap; Ip_bool success = IP_FALSE; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Set default value */ *addr = defip; /* Grab the sysvar */ if (buf) { success = ipmip_util_inet(buf, addr, plen); ipcom_free(buf); } return success; } #endif #ifdef IPMIP_USE_INET6 /* *=========================================================================== * ipmip_sysvar_inet6 *=========================================================================== * Description: Read a sysvar variable and convert it to an IPv6 address and * prefix. If plen is specified; it will look for / prefix * indicator, if not available, prefix will be 32. * Parameters: defip - Default value * addr - The addr to store the result in. * plen - Prefix length.[may be NULL] * format - Format string * ... - Arguments. * Returns: IP_TRUE on success; IP_FALSE otherwise * */ IP_GLOBAL Ip_bool ipmip_sysvar_inet6(const struct Ip_in6_addr *defin6, struct Ip_in6_addr *addr6, Ip_u8 *plen, const char *format, /* args*/ ...) { char *buf; va_list ap; Ip_bool success = IP_FALSE; va_start(ap, format); buf = ipmip_sysvar_get(format, ap); va_end(ap); /* Set default value */ IPMIP_IP6_SET_ADDR(addr6, defin6? defin6 : &ip_in6addr_any); /* Grab the sysvar */ if (buf) { success = ipmip_util_inet6(buf, addr6, plen); ipcom_free(buf); } return success; } #endif /* *=========================================================================== * ipmip_sysvar_foreach *=========================================================================== * Description: Iterate and expand tables in sysvar. * Parameters: cb_func - The sysvar foreach callback * cookie - Opaque data. * format - The format key * ... - Arguments * Returns: * */ IP_GLOBAL void ipmip_sysvar_foreach(Ipmip_proc_t *proc, Ipmip_sysvar_foreach_t cb_func, void *cookie, const char *format, /* args*/ ...) { Ipmip_sysvar_foreach_cbinfo_t data; va_list ap; char *buf; va_start(ap, format); buf = ipmip_util_vstrdup(format, ap); va_end(ap); /* Overflow or error? */ if (buf == IP_NULL) goto done_out; /* Calculate the base length and set up the cb information */ data.baselen = ipcom_strlen(buf); if (buf[data.baselen - 1] == '*') data.baselen--; data.cb_func = cb_func; data.opaque = cookie; data.proc = proc; ipcom_sysvar_for_each(buf, (Ipcom_sysvar_for_each)ipmip_sysvar_foreach_parse, &data); done_out: if (buf) ipcom_free(buf); } /* *=========================================================================== * ipmip_sysvar_foreach *=========================================================================== * Description: Iterate and expand tables in sysvar. * Parameters: cb_func - The sysvar foreach callback * cookie - Opaque data. * format - The format key * ... - Arguments * Returns: * */ IP_GLOBAL void ipmip_sysvar_foreach_ext(struct Ipmip_context *ctx, Ipmip_proc_t *proc, Ipmip_sysvar_foreach_ext_t cb_func, void *cookie, const char *format, /* args*/ ...) { Ipmip_sysvar_foreach_cbinfo_ext_t data; va_list ap; char *buf; va_start(ap, format); buf = ipmip_util_vstrdup(format, ap); va_end(ap); /* Overflow or error? */ if (buf == IP_NULL) goto done_out; /* Calculate the base length and set up the cb information */ data.baselen = ipcom_strlen(buf); if (buf[data.baselen - 1] == '*') data.baselen--; data.cb_func = cb_func; data.opaque = cookie; data.proc = proc; data.ctx = ctx; ipcom_sysvar_for_each(buf, (Ipcom_sysvar_for_each)ipmip_sysvar_foreach_ext_parse, &data); done_out: if (buf) ipcom_free(buf); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */