indigo_error_t ind_cxn_cfg_stage(cJSON *config) { indigo_error_t err; int i; err = ind_cfg_parse_loglevel(config, "logging.connection", OFCONNECTIONMANAGER_CONFIG_LOG_BITS_DEFAULT, &staged_config.log_flags); if (err != INDIGO_ERROR_NONE) { return err; } /* Not supporting setting log options yet */ err = ind_cfg_lookup_int(config, "keepalive_period_ms", &staged_config.keepalive_period_ms); if (err == INDIGO_ERROR_NONE) { if (staged_config.keepalive_period_ms <= 0) { AIM_LOG_ERROR("'keepalive_period_ms' must be greater than 0"); return INDIGO_ERROR_PARAM; } } else if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: Could not parse 'keepalive_period_ms'"); return err; } else if (err == INDIGO_ERROR_NOT_FOUND) { AIM_LOG_ERROR("Config: Mising required key 'keepalive_period_ms'"); return err; } err = parse_controllers(config); if (err != INDIGO_ERROR_NONE) { return err; } for (i = 0; i < staged_config.num_controllers; i++) { /* @FIXME local? listen? priority? */ staged_config.controllers[i].config.periodic_echo_ms = staged_config.keepalive_period_ms; staged_config.controllers[i].config.reset_echo_count = 3; /* @FIXME */ } return INDIGO_ERROR_NONE; }
indigo_error_t ind_cxn_cfg_stage(cJSON *config) { indigo_error_t err; err = ind_cfg_parse_loglevel(config, "logging.connection", OFCONNECTIONMANAGER_CONFIG_LOG_BITS_DEFAULT, &staged_config.log_flags); if (err != INDIGO_ERROR_NONE) { return err; } /* Not supporting setting log options yet */ err = ind_cfg_lookup_int(config, "keepalive_period_ms", &staged_config.keepalive_period_ms); if (err == INDIGO_ERROR_NONE) { if (staged_config.keepalive_period_ms <= 0) { AIM_LOG_ERROR("'keepalive_period_ms' must be greater than 0"); return INDIGO_ERROR_PARAM; } } else if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: Could not parse 'keepalive_period_ms'"); return err; } else if (err == INDIGO_ERROR_NOT_FOUND) { AIM_LOG_ERROR("Config: Missing required key 'keepalive_period_ms'"); return err; } err = parse_controllers(config); if (err != INDIGO_ERROR_NONE) { return err; } /* verify TLS parameters */ /* * for now, we should be able to accept: * - TLS config with switch cert and key specified, * cipher_list and CA cert optional * - if cipher_list is specified, it should be valid * - if CA cert is specified, it should be consistent with switch cert * - TLS config with parameters specified, but * CA cert, switch cert and switch priv key files not present */ { cJSON *node = cJSON_GetObjectItem(config, "tls"); if (node) { if (node->type != cJSON_Object) { AIM_LOG_ERROR("Config: expected tls to be an object"); return INDIGO_ERROR_PARAM; } err = parse_tls_config(node); if (err != INDIGO_ERROR_NONE) { AIM_LOG_ERROR("Config: error parsing TLS config: %s", indigo_strerror(err)); return err; } } else { AIM_LOG_VERBOSE("Config: TLS config not found, continuing"); } } staged_config.valid = true; return INDIGO_ERROR_NONE; }
/* Parse a controller string like "tcp:127.0.0.1:6633". */ static indigo_error_t parse_controller(struct controller *controller, cJSON *root) { indigo_cxn_params_tcp_over_ipv4_t *proto; char *proto_str, *ip; int port; int listen; int prio; indigo_error_t err; err = ind_cfg_lookup_string(root, "ip_addr", &ip); if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'ip_addr' must be a string"); } else if (err == INDIGO_ERROR_NOT_FOUND) { AIM_LOG_ERROR("Config: Missing 'ip_addr' in controller spec"); } return err; } err = ind_cfg_lookup_string(root, "protocol", &proto_str); if (err == INDIGO_ERROR_NOT_FOUND) { /* Allow default protocol value */ proto_str = "tcp"; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'protocol' must be a string"); } return err; } /* @TODO support more protocol types */ if (strcmp(proto_str, "tcp")) { AIM_LOG_ERROR("Config: Invalid controller protocol: %s", proto_str); return INDIGO_ERROR_PARAM; } err = ind_cfg_lookup_int(root, "port", &port); if (err == INDIGO_ERROR_NOT_FOUND) { /* Allow default protocol value */ port = 6633; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'port' must be an integer"); } return err; } if (port < 0 || port >= 0xffff) { AIM_LOG_ERROR("Config: Invalid controller port: %d", port); return INDIGO_ERROR_PARAM; } err = ind_cfg_lookup_bool(root, "listen", &listen); if (err == INDIGO_ERROR_NOT_FOUND) { listen = 0; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'listen' must be a boolean"); } return err; } err = ind_cfg_lookup_int(root, "priority", &prio); if (err == INDIGO_ERROR_NOT_FOUND) { prio = 0; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'priority' must be an integer"); } return err; } /* TODO validate IP */ proto = &controller->proto.tcp_over_ipv4; proto->protocol = INDIGO_CXN_PROTO_TCP_OVER_IPV4; strncpy(proto->controller_ip, ip, sizeof(proto->controller_ip)); proto->controller_port = port; controller->config.listen = listen; controller->config.cxn_priority = prio; controller->config.local = 0; controller->config.version = OFCONNECTIONMANAGER_CONFIG_OF_VERSION; return INDIGO_ERROR_NONE; }
/* Parse a controller string like "tcp:127.0.0.1:6633". */ static indigo_error_t parse_controller(struct controller *controller, cJSON *root) { indigo_cxn_protocol_t proto; indigo_cxn_params_tcp_over_ipv4_t *params4; indigo_cxn_params_tcp_over_ipv6_t *params6; indigo_cxn_params_unix_t *params_unix; char *proto_str = NULL, *ip = NULL, *unix_path = NULL; int port; int listen; int local; int prio; indigo_error_t err; err = ind_cfg_lookup_string(root, "protocol", &proto_str); if (err == INDIGO_ERROR_NOT_FOUND) { /* Allow default protocol value */ proto_str = "tcp"; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'protocol' must be a string"); } return err; } if (strcmp(proto_str, "tcp") == 0) { proto = INDIGO_CXN_PROTO_TCP_OVER_IPV4; } else if (strcmp(proto_str, "tcp6") == 0) { proto = INDIGO_CXN_PROTO_TCP_OVER_IPV6; } else if (strcmp(proto_str, "tls") == 0) { proto = INDIGO_CXN_PROTO_TLS_OVER_IPV4; } else if (strcmp(proto_str, "tls6") == 0) { proto = INDIGO_CXN_PROTO_TLS_OVER_IPV6; } else if (strcmp(proto_str, "unix") == 0) { proto = INDIGO_CXN_PROTO_UNIX; } else { AIM_LOG_ERROR("Config: Invalid controller protocol: %s", proto_str); return INDIGO_ERROR_PARAM; } switch(proto) { case INDIGO_CXN_PROTO_TCP_OVER_IPV4: /* fall-through */ case INDIGO_CXN_PROTO_TCP_OVER_IPV6: /* fall-through */ case INDIGO_CXN_PROTO_TLS_OVER_IPV4: /* fall-through */ case INDIGO_CXN_PROTO_TLS_OVER_IPV6: err = ind_cfg_lookup_string(root, "ip_addr", &ip); if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'ip_addr' must be a string"); } else if (err == INDIGO_ERROR_NOT_FOUND) { AIM_LOG_ERROR("Config: Missing 'ip_addr' in controller spec"); } return err; } /* * WARNING: no validity checks for IP address. * Instead, they are performed by the cli front-end. */ err = ind_cfg_lookup_int(root, "port", &port); if (err == INDIGO_ERROR_NOT_FOUND) { /* Allow default protocol value */ port = 6633; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'port' must be an integer"); } return err; } if (port < 0 || port >= 0xffff) { AIM_LOG_ERROR("Config: Invalid controller port: %d", port); return INDIGO_ERROR_PARAM; } break; case INDIGO_CXN_PROTO_UNIX: err = ind_cfg_lookup_string(root, "unix_path", &unix_path); if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'unix_path' must be a string"); } else if (err == INDIGO_ERROR_NOT_FOUND) { AIM_LOG_ERROR("Config: Missing 'unix_path' in controller spec"); } return err; } break; default: AIM_DIE("Config: No handling for protocol %d", proto); } err = ind_cfg_lookup_bool(root, "listen", &listen); if (err == INDIGO_ERROR_NOT_FOUND) { listen = 0; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'listen' must be a boolean"); } return err; } err = ind_cfg_lookup_bool(root, "local", &local); if (err == INDIGO_ERROR_NOT_FOUND) { local = 0; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'local' must be a boolean"); } return err; } err = ind_cfg_lookup_int(root, "priority", &prio); if (err == INDIGO_ERROR_NOT_FOUND) { prio = 0; } else if (err < 0) { if (err == INDIGO_ERROR_PARAM) { AIM_LOG_ERROR("Config: 'priority' must be an integer"); } return err; } /* populate 'controller' struct */ switch (proto) { case INDIGO_CXN_PROTO_TCP_OVER_IPV4: /* fall-through */ case INDIGO_CXN_PROTO_TLS_OVER_IPV4: params4 = &controller->proto.tcp_over_ipv4; params4->protocol = proto; strncpy(params4->controller_ip, ip, sizeof(params4->controller_ip)); params4->controller_port = port; break; case INDIGO_CXN_PROTO_TCP_OVER_IPV6: /* fall-through */ case INDIGO_CXN_PROTO_TLS_OVER_IPV6: params6 = &controller->proto.tcp_over_ipv6; params6->protocol = proto; strncpy(params6->controller_ip, ip, sizeof(params6->controller_ip)); params6->controller_port = port; break; case INDIGO_CXN_PROTO_UNIX: params_unix = &controller->proto.unx; params_unix->protocol = proto; strncpy(params_unix->unix_path, unix_path, INDIGO_CXN_UNIX_PATH_LEN); break; default: AIM_DIE("Config: No handling for protocol %d", proto); } controller->config.listen = listen; controller->config.cxn_priority = prio; controller->config.local = local; controller->config.version = OFCONNECTIONMANAGER_CONFIG_OF_VERSION; if (!local) { controller->config.periodic_echo_ms = staged_config.keepalive_period_ms; controller->config.reset_echo_count = 3; } else { controller->config.periodic_echo_ms = 0; controller->config.reset_echo_count = 0; } return INDIGO_ERROR_NONE; }