/* *=========================================================================== * ipnet_netlink_register_ops *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipnet_rtnetlink_register_family_event(int family, int cmd, Ip_size_t maxattr, Ip_size_t min_size, Ipnet_rtnetlink_do_t doit, Ipnet_netlink_dump_t dumpit) { Ipnet_rtnetlink_table_t *table; /**/ if (ipnet->rtnetlink_links[family] == IP_NULL) { ipnet->rtnetlink_links[family] = ipcom_calloc(IP_RTM_NR_MSGTYPES, sizeof(Ipnet_rtnetlink_table_t *)); ip_assert(ipnet->rtnetlink_links[family] != IP_NULL); } ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] == IP_NULL); ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] = ipcom_calloc(1, sizeof(Ipnet_rtnetlink_table_t)); ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] != IP_NULL); table = ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE]; table->nl_cmd = cmd; table->nl_func_table.nl_rta_max = maxattr; table->nl_func_table.nl_size_min = IP_NLMSG_LENGTH(min_size); table->nl_func_table.nl_do = doit; table->nl_func_table.nl_dump = dumpit; }
/* *=========================================================================== * ipnet_pkt_queue_mbc_configure *=========================================================================== * Description: Configures a queue with new parameters. * Parameters: q - A packet queue. * m - The queue parameters. * Returns: 0 = success * <0 = error code */ IP_STATIC int ipnet_pkt_queue_mbc_configure(Ipnet_pkt_queue_mbc *q, struct Ipnet_ifqueue_mbc *m) { Ip_u32 band; if (q->number_of_bands) { IPCOM_LOG0(ERR, "MBC configure: Can only be configured once"); return -IP_ERRNO_EINVAL; } if (m->mbc_bands < 2 || m->mbc_bands > IPNET_IFQ_CONTAINER_MAX_COUNT) { IPCOM_LOG1(ERR, "MBC configure: Number of priority bands must be between 2 and %d", IPNET_IFQ_CONTAINER_MAX_COUNT); return -IP_ERRNO_EINVAL; } if (m->mbc_bands <= m->mbc_default_band) { IPCOM_LOG1(ERR, "MBC configure: invalid default band, must be [0..%d]", m->mbc_bands - 1); return -IP_ERRNO_EINVAL; } q->bands = ipcom_calloc(m->mbc_bands, sizeof(Ipnet_pkt_queue *)); if (q->bands == IP_NULL) { IPCOM_LOG0(CRIT, "MBC configure: out of memory"); return -IP_ERRNO_ENOMEM; } q->number_of_bands = m->mbc_bands; q->default_band = m->mbc_default_band; for (band = 0; band < q->number_of_bands; band++) { int ret; ret = ipnet_pkt_queue_mbc_insert_default_queue(q, band); if (ret < 0) { IPCOM_LOG1(ERR, "MBC configure: Failed to create default queue: %s", ipcom_strerror(-ret)); return ret; } } return 0; }
/* *=========================================================================== * ipcom_create_ifaddrs_entry *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC struct Ip_ifaddrs * ipcom_create_ifaddrs_entry(const char *ifname, struct Ipnet_if_msghdr *ifm, struct Ipnet_ifa_msghdr *ifa, struct Ip_sockaddr **addrs) { /**/ struct Ip_ifaddrs *nifa = ipcom_calloc(1, sizeof(*nifa)); if (nifa == IP_NULL) return IP_NULL; /* Interface name */ nifa->ifa_name = ipcom_strdup(ifname); if(nifa->ifa_name == IP_NULL) goto fail; /* Interface flags */ nifa->ifa_flags = ifm->ifm_flags; /* Interface address */ nifa->ifa_addr = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_addr == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_addr, addrs[IPNET_RTAX_IFA], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA])); nifa->ifa_netmask = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_netmask == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_netmask, addrs[IPNET_RTAX_NETMASK], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA])); if (IP_BIT_ISSET(ifa->ifam_addrs, IPNET_RTA_BRD)) { nifa->ifa_broadaddr = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_broadaddr == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_broadaddr, addrs[IPNET_RTAX_BRD], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_BRD])); } return nifa; fail: ipcom_ifaddrs_free(nifa); return IP_NULL; }
/* *=========================================================================== * ipnet_sock_sockdev_register *=========================================================================== * Description: Registers the IP_AF_SOCKDEV domain. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_sockdev_register(void) { Ipnet_sock_ops *ops; ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the IP_AF_SOCKDEV domain, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } ops->domain = IP_AF_SOCKDEV; ops->type = IP_SOCK_RAW; ops->proto = -1; ops->destroy = ipnet_sockdev_destroy; ops->init = ipnet_sockdev_init; ops->recv = ipnet_sock_pkt_recv; ops->send = ipnet_sockdev_send; return ipnet_sock_register_ops(ops); }
/* *=========================================================================== * ipnet_gre_setup *=========================================================================== * Description: Setup the GRE tunnel. * Parameters: netif - A GRE tunnel interface. * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_gre_setup(Ipnet_netif *netif) { #ifdef IPNET_USE_RFC2890 Ipnet_gre_t *gre; gre = netif->ipcom.pdrv = ipcom_calloc(1, sizeof(Ipnet_gre_t)); if (gre == IP_NULL) goto errout; gre->reassembly_queue = ipcom_pqueue_new((Ipcom_pqueue_cmp_func) ipnet_gre_seq_cmp, ipcom_pqueue_nop_store_index); return 0; errout: ipnet_gre_destroy(netif); IPCOM_LOG0(CRIT, "Failed to create GRE tunnel due to unsifficient memory"); return -IP_ERRNO_ENOMEM; #else IPCOM_UNUSED_ARG(netif); return 0; #endif /* IPNET_USE_RFC2890 */ }
/* *=========================================================================== * ipnet_rtnetlink_parse *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipnet_rtnetlink_parse(int maxattr, struct Ip_rtattr *attr, Ip_size_t attrlen, struct Ip_rtattr ***rtap) { struct Ip_rtattr **rta = IP_NULL; if (maxattr == 0) attrlen = 0; else { rta = ipcom_calloc(sizeof(struct Ip_rtattr *), maxattr + 1); if (!rta) return -IP_ERRNO_ENOMEM; } while (IP_RTA_OK(attr, attrlen)) { Ip_u16 flavor = attr->rta_type; if (flavor) { if (flavor > maxattr) { ipcom_free(rta); return -IP_ERRNO_EINVAL; } rta[flavor-1] = attr; } attr = IP_RTA_NEXT(attr, attrlen); } *rtap = rta; return 0; }
/* *=========================================================================== * ipcom_cmd_ipd *=========================================================================== * Description: * Parameters: * Returns: */ IP_PUBLIC int ipcom_cmd_ipd(int argc, char **argv) { Ipcom_getopt opt; int i, c, msgtype; Ip_err err = IPCOM_SUCCESS; #if IPCOM_VR_MAX > 1 int vr = ipcom_proc_vr_get(); int vr_new = vr; #endif if (argc < 2) { usage: ipcom_fprintf(ip_stderr, "Interpeak daemon (IPD) command, version 1.2"IP_LF "usage: "IP_LF " ipd [-V <vr>] list"IP_LF " ipd [-V <vr>] start <service>"IP_LF " ipd [-V <vr>] kill <service>"IP_LF " ipd [-V <vr>] reconfigure <service>"IP_LF " ipd [-V <vr>] <#> <service>"IP_LF IP_LF); return 0; } ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "V:", &opt)) != -1) { switch(c) { case 'V': #if IPCOM_VR_MAX > 1 vr_new = ipcom_atoi(opt.optarg); #endif break; default: ipcom_printf("ipd: unknown option %c"IP_LF, (char)c); return -1; } } if (opt.optind >= argc) { ipcom_printf("ipd: missing <command> argument"IP_LF); goto usage; } if(ipcom_strcmp(argv[opt.optind], "list") == 0) { #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr_new); #endif ipcom_printf("Services:"IP_LF); for (i = 0; ipcom_ipd_products[i].name != IP_NULL; i++) { if ((argc - (opt.optind + 1)) > 0) { int p; for (p = opt.optind + 1; p < argc; p++) { if (ipcom_strcasecmp(ipcom_ipd_products[i].name, argv[p]) == 0) goto print_service; } continue; } print_service: if (IP_BIT_ISSET(ipcom_ipd_products[i].flags, IPCOM_IPD_FLAG_IPD_START)) { #ifdef IP_PORT_OSE5 if (ipcom_ipd_products[i].start == IP_NULL && ipcom_ipd_isinstalled_ose5(ipcom_ipd_products[i].name) != IPCOM_SUCCESS) continue; #endif err = ipcom_ipd_send(ipcom_ipd_products[i].name, IPCOM_IPD_MSGTYPE_PING); ipcom_printf("%-20s %-s"IP_LF, ipcom_ipd_products[i].name, err == IPCOM_SUCCESS ? "started" : "killed"); } else if (ipcom_ipd_products[i].start) ipcom_printf("%-20s %-s"IP_LF, ipcom_ipd_products[i].name, "started"); } ipcom_printf(IP_LF); #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr); #endif return 0; } if ((argc - opt.optind) < 2) { ipcom_printf("ipd: missing <service> argument"IP_LF); return -1; } for (i = 0; ipcom_cmd_ipd_messages[i].name; i++) if (ipcom_strcmp(argv[opt.optind], ipcom_cmd_ipd_messages[i].name) == 0) { msgtype = ipcom_cmd_ipd_messages[i].msgtype; goto sendmsg; } if (*argv[opt.optind] == '-' && ipcom_isdigit(argv[opt.optind][1])) { /* "UNIX" signal support (using negative numbers) */ msgtype = -ipcom_atoi(argv[opt.optind] + 1); goto sendmsg; } if (ipcom_isdigit(argv[opt.optind][0])) { /* positive numbers */ msgtype = ipcom_atoi(argv[1]); goto sendmsg; } /* unknown command. */ ipcom_printf ("ipd: unknown command '%s'"IP_LF, argv[opt.optind]); return -1; /* send msg */ sendmsg: #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr_new); #endif if ((argc - opt.optind) < 3) err = ipcom_ipd_send(argv[opt.optind+1], msgtype); else { Ipcom_ipd_msg *msg; int sz = ipcom_strlen(argv[opt.optind + 2]) + 1; msg = ipcom_calloc(1, sz + sizeof(*msg)); if (msg != IP_NULL) { msg->msgtype = msgtype; ipcom_memcpy(msg + 1, argv[opt.optind + 2], sz); err = ipcom_ipd_sendmsg(argv[opt.optind+1], msg, sz + sizeof(*msg)); ipcom_free(msg); } } if(err == IPCOM_SUCCESS) ipcom_printf("ipd: %s %s ok"IP_LF, argv[opt.optind], argv[opt.optind+1]); else ipcom_printf("ipd: %s %s failed: %s"IP_LF, argv[opt.optind], argv[opt.optind+1], ipcom_err_string(err)); #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr); #endif return 0; }
/* *=========================================================================== * ipnet_sock_tcp_register *=========================================================================== * Description: Registers the TCP protocol for IPv4 and/or IPv6. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_tcp_register(void) { Ipnet_sock_tcp_ops *ops; int domains[] = { #ifdef IPCOM_USE_INET IP_AF_INET, #endif #ifdef IPCOM_USE_INET6 IP_AF_INET6, #endif }; int protos[] = { 0, IP_IPPROTO_TCP }; Ip_size_t p, d; int ret; for (d = 0; d < sizeof(domains) / sizeof(domains[0]); d++) for (p = 0; p < sizeof(protos) / sizeof(protos[0]); p++) { ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the TCP protocol, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } switch (domains[d]) { #ifdef IPCOM_USE_INET case IP_AF_INET: ipnet_sock_ip4_get_ops(&ops->inet); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: ipnet_sock_ip6_get_ops(&ops->inet); break; #endif default: break; } ops->network_bind = ops->inet.network_bind; ops->inet.network_bind = ipnet_sock_tcp_bind; ops->network_init = ops->inet.sock.init; ops->inet.sock.init = ipnet_sock_tcp_init; ops->network_destroy = ops->inet.sock.destroy; ops->inet.sock.destroy = ipnet_sock_tcp_destroy; ops->network_connect = ops->inet.sock.connect; ops->inet.sock.connect = ipnet_sock_tcp_connect; ops->inet.sock.type = IP_SOCK_STREAM; ops->inet.sock.proto = protos[p]; ops->inet.sock.allow_async_send = IP_TRUE; ops->inet.sock.accept = iptcp_accept; ops->inet.sock.close = iptcp_close; ops->inet.sock.listen = iptcp_listen; ops->inet.sock.usr_recv = ipnet_usr_sock_tcp_recv; ops->inet.sock.pkts_from_iov = ipnet_usr_sock_tcp_pkts_from_iov; ops->inet.sock.send = iptcp_send; ops->inet.sock.shutdown = iptcp_shutdown; ops->inet.sock.getopt = iptcp_getsockopt; ops->inet.sock.setopt = iptcp_setsockopt; ops->inet.sock.ioctl = iptcp_ioctl; ops->inet.sock.hdr_space += IPTCP_TCP_HDR_SIZE; ops->inet.sock.extra_sock_space += sizeof(Iptcp_tcb); ret = ipnet_sock_register_ops(&ops->inet.sock); if (ret < 0) return ret; } return 0; }
/* *=========================================================================== * ipcom_shellalias_remove *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipcom_shellalias_set(char *name, char *cmd) { struct Ipcom_shellalias_alias *alias; if (ipcom_strcmp(name, "alias") == 0 || ipcom_strcmp(name, "unalias") == 0) return -IPCOM_ERR_INVALID_ARG; /* Remove any old references */ ipcom_shellalias_remove(name); /* Allocate a new alias structure */ alias = ipcom_calloc(1, sizeof(*alias)); /* Could we allocate? */ if (alias != IP_NULL) { Ip_err retval; int argc; char **argv = IP_NULL; /* Allocate the name */ alias->name = ipcom_strdup(name); if (alias->name == IP_NULL) goto fail; /* Allocate the command */ alias->cmd = ipcom_strdup(cmd); if (alias->cmd == IP_NULL) goto fail; /* Parse the string */ retval = ipcom_parse_argstr(alias->cmd, (int *)&argc, &argv); switch(retval) { case IPCOM_SUCCESS: break; case IPCOM_ERR_INVALID_ARG: ipcom_printf("Unmatched string delimiters"IP_LF); goto fail; case IPCOM_ERR_FAILED: default: goto fail; } /* Store */ alias->argv = argv; alias->argc = argc; /* Link the alias into the major list */ ipcom_list_insert_first(&ipcom_shellalias_head, &alias->next); /* Success */ return IPCOM_SUCCESS; } /* No memory */ return -IP_ERRNO_ENOMEM; fail: /* Did we manage to allocate the name? */ if (alias->name != IP_NULL) ipcom_free(alias->name); /* Free the stored command */ if (alias->cmd != IP_NULL) ipcom_free(alias->cmd); /* Free the vector */ if (alias->argv != IP_NULL) ipcom_free(alias->argv); /* Free the structure */ ipcom_free(alias); return -IP_ERRNO_ENOMEM; }
/* *=========================================================================== * ipcom_cmd_sockperf *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_cmd_sockperf(int argc, char **argv) { Ipcom_getopt opt; Ipcom_cmd_sockperf_t cmd; int c; struct Ip_addrinfo hints; char *hostname = "0.0.0.0"; char *servname = "7373"; int socktype = IP_SOCK_STREAM; int domain = IP_AF_INET; if (argc < 2) { ipcom_cmd_sockperf_print_usage(); return 0; } ipcom_memset(&cmd, 0, sizeof(cmd)); cmd.buf_len = 8192; cmd.num_buf = 2048; cmd.num_sock = 1; cmd.linger.l_onoff = 1; cmd.linger.l_linger = 3; cmd.sendbuf_size = 32767; cmd.recvbuf_size = 16384; ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "6aeL:l:n:Pp:R:rs:T:tu", &opt)) != -1) { switch(c) { case '6': domain = IP_AF_INET6; hostname = "::"; break; case 'a': cmd.accept = IP_TRUE; break; case 'e': cmd.echo = IP_TRUE; break; case 'L': cmd.linger.l_linger = ipcom_atoi(opt.optarg); break; case 'l': cmd.buf_len = ipcom_atoi(opt.optarg); break; case 'n': cmd.num_buf = ipcom_atoi(opt.optarg); break; case 'P': cmd.testpattern = IP_TRUE; break; case 'p': servname = opt.optarg; break; case 'R': cmd.recvbuf_size = ipcom_atoi(opt.optarg); break; case 'r': cmd.receive = IP_TRUE; break; case 's': cmd.num_sock = ipcom_atoi(opt.optarg); break; case 'T': cmd.sendbuf_size = ipcom_atoi(opt.optarg); break; case 't': cmd.transmit = IP_TRUE; break; case 'u': socktype = IP_SOCK_DGRAM; break; default: ipcom_printf("sockperf: unknown option %c"IP_LF, (char)c); return -1; } } if (cmd.testpattern) { if (cmd.buf_len & 0x7) { ipcom_printf("sockperf: the buffert (set with -l) must be a multiple of 8 when " "using a test pattern"IP_LF); goto cleanup; } if (cmd.transmit) { cmd.send_pattern = ipcom_calloc(cmd.num_sock, sizeof(Ip_u32)); if (cmd.send_pattern == IP_NULL) { ipcom_printf("sockperf: out of memory when allocating send pattern"IP_LF); goto cleanup; } } if (cmd.receive) { cmd.recv_pattern = ipcom_calloc(cmd.num_sock, sizeof(Ip_u32)); if (cmd.recv_pattern == IP_NULL) { ipcom_printf("sockperf: out of memory when allocating receive pattern"IP_LF); goto cleanup; } } } if (opt.optind < argc) hostname = argv[opt.optind]; ipcom_memset(&hints, 0, sizeof(hints)); hints.ai_socktype = socktype; hints.ai_flags = IP_AI_CANONNAME; hints.ai_family = domain; if (ipcom_getaddrinfo(hostname, servname, &hints, &cmd.res) != 0) { ipcom_printf("sockperf: getaddrinfo() failed"IP_LF); goto cleanup; } cmd.buf = ipcom_malloc(cmd.buf_len + 1); if (cmd.buf == IP_NULL) { ipcom_printf("sockperf: Failed to allocate %lu bytes" IP_LF, cmd.buf_len); goto cleanup; } cmd.sock_array = ipcom_malloc(cmd.num_sock * sizeof(int)); if (cmd.sock_array == IP_NULL) { ipcom_printf("sockperf: Failed to allocate %lu bytes for sockets" IP_LF, cmd.num_sock * sizeof(int)); goto cleanup; } if (cmd.accept) ipcom_cmd_sockperf_accept(&cmd); else ipcom_cmd_sockperf_connect(&cmd); cleanup: ipcom_free(cmd.send_pattern); ipcom_free(cmd.recv_pattern); ipcom_free(cmd.sock_array); ipcom_free(cmd.buf); ipcom_freeaddrinfo(cmd.res); return 0; }
/* *=========================================================================== * ipnet_sock_udp_register *=========================================================================== * Description: Registers the UDP protocol for IPv4 and/or IPv6. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_udp_register(void) { Ipnet_sock_udp_ops *ops; int domains[] = { #ifdef IPCOM_USE_INET IP_AF_INET, #endif #ifdef IPCOM_USE_INET6 IP_AF_INET6, #endif }; int protos[] = { 0, IP_IPPROTO_UDP }; Ip_size_t d, p; int ret; for (d = 0; d < sizeof(domains) / sizeof(domains[0]); d++) for (p = 0; p < sizeof(protos) / sizeof(protos[0]); p++) { ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the UDP protocol, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } switch (domains[d]) { #ifdef IPCOM_USE_INET case IP_AF_INET: ipnet_sock_ip4_get_ops(&ops->inet); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: ipnet_sock_ip6_get_ops(&ops->inet); break; #endif default: break; } ops->network_bind = ops->inet.network_bind; ops->inet.network_bind = ipnet_sock_udp_bind; ops->network_init = ops->inet.sock.init; ops->network_connect = ops->inet.sock.connect; ops->inet.sock.init = ipnet_sock_udp_init; ops->inet.sock.connect = ipnet_sock_udp_connect; ops->inet.sock.type = IP_SOCK_DGRAM; ops->inet.sock.proto = protos[p]; ops->inet.sock.allow_async_send = IP_TRUE; ops->inet.sock.usr_recv = ipnet_usr_sock_recvmsg; ops->inet.sock.send = ipnet_sock_udp_send; ops->inet.sock.hdr_space += IPNET_UDP_HDR_SIZE; ret = ipnet_sock_register_ops(&ops->inet.sock); if (ret < 0) return ret; } return 0; }
IP_PUBLIC Ip_err ipcom_sysvar_ext_setv(const Ipcom_sysvar_ext entries[], int flags) { /* !!TODO: make atomic */ int i; int len = 0; int param_len = 0; char *sysvar_name = IP_NULL; char *sysvar_param = IP_NULL; char *conf = IP_NULL; char *last = IP_NULL; char *value = IP_NULL; char *ifparam = IP_NULL; Ip_err err = IPCOM_SUCCESS; sysvar_name = ipcom_calloc(1, sizeof(char) * 256); if (sysvar_name == IP_NULL) return IPCOM_ERR_NO_MEMORY; for (i = 0; ; i++) { /* * The syntax {IP_NULL,IP_NULL,IP_NULL} terminates the configuration * array. Otherwise, <name1> and/or <name2> must be specified. */ if ((entries[i].name1 == IP_NULL) && (entries[i].name2 == IP_NULL)) { err = (entries[i].param == IP_NULL) ? IPCOM_SUCCESS : IPCOM_ERR_INVALID_CONFIG; goto done; } /* * The expected string should contain <ifparam>=<value>. If the * separator is not found, assume the string does not contain * any valid configuration values. */ if (entries[i].param == IP_NULL || ipcom_strchr(entries[i].param, '=') == IP_NULL) continue; len = ipcom_strlen(entries[i].param); if ((len > param_len) || (sysvar_param == IP_NULL)) { if (sysvar_param) ipcom_free(sysvar_param); /* free previously allocated mem */ param_len = len; sysvar_param = ipcom_calloc(1, param_len+1); if (sysvar_param == IP_NULL) { ipcom_free(sysvar_name); return IPCOM_ERR_NO_MEMORY; } } else ipcom_memset(sysvar_param, 0, param_len+1); ipcom_strcpy(sysvar_param, entries[i].param); /* * Expected format: <ifparam1>=<value1>;<ifparam2>=<value2>;... */ conf = ipcom_strtok_r(sysvar_param, IPCOM_IFPARAM_LIST_DELIMITER, &last); if (conf == IP_NULL) { err = IPCOM_ERR_INVALID_CONFIG; goto done; } do { /* Expected format: <ifparam>=<value> */ ifparam = ipcom_strtok_r(conf, IPCOM_IFPARAM_DELIMITER, &value); if ((ifparam == IP_NULL) || (value == IP_NULL)) { err = IPCOM_ERR_INVALID_CONFIG; goto done; } ipcom_memset(sysvar_name, 0, sizeof(sysvar_name)); if (entries[i].name1 != IP_NULL) { ipcom_strcpy(sysvar_name, entries[i].name1); ipcom_strcat(sysvar_name, "."); } ipcom_strcat(sysvar_name, ifparam); if (entries[i].name2 != IP_NULL) { ipcom_strcat(sysvar_name, "."); ipcom_strcat(sysvar_name, entries[i].name2); } err = ipcom_sysvar_set(sysvar_name, value, flags); if (err == IPCOM_ERR_DUPLICATE) err = IPCOM_SUCCESS; else if (err != IPCOM_SUCCESS) goto done; } while (IP_NULL != (conf = ipcom_strtok_r(IP_NULL, IPCOM_IFPARAM_LIST_DELIMITER, &last))); } done: ipcom_free(sysvar_name); if (sysvar_param) ipcom_free(sysvar_param); return err; }