#ifndef HICNLIGHT_CONFIG_COMMAND #define HICNLIGHT_CONFIG_COMMAND /** * @file command.h * @brief Commands. */ #include // offsetof #include #include /* Update sscanf accordingly in parse_cmd.c */ #define MAX_PARAMETERS 10 #define MAX_SCANF_PARAM_LEN 100 typedef int (*parser_hook_t)(void *arg); typedef enum { TYPENAME_UNDEFINED, TYPENAME_INT, TYPENAME_UINT, TYPENAME_STR, TYPENAME_SYMBOLIC_OR_ID, TYPENAME_INTERFACE_NAME, TYPENAME_IP_ADDRESS, TYPENAME_IP_PREFIX, TYPENAME_ON_OFF, TYPENAME_ENUM, TYPENAME_POLICY_STATE, } parser_typename_t; typedef struct { parser_typename_t name; union { struct { size_t max_size; } str; struct { int min; int max; } sint; struct { int min; int max; } uint; struct { int (*from_str)(const char *str); } enum_; struct { policy_tag_t tag; } policy_state; }; } parser_type_t; typedef struct { const char *name; const char *help; parser_type_t type; size_t offset; /* * quick hack to let the functions update two or more parameters, like for * IP_ADDRESS or IP_PREFIX types */ size_t offset2; size_t offset3; } command_parameter_t; typedef struct { hc_action_t action; hc_object_type_t object; unsigned nparams; command_parameter_t parameters[MAX_PARAMETERS]; parser_hook_t post_hook; } command_parser_t; #define TYPE_STRN(N) \ (parser_type_t) { \ .name = TYPENAME_STR, \ .str = { \ .max_size = N, \ }, \ } #define TYPE_FMT_STRN(N) "%s" #define TYPE_INT(MIN, MAX) \ (parser_type_t) { \ .name = TYPENAME_INT, \ .sint = { \ .min = (MIN), \ .max = (MAX), \ }, \ } #define TYPE_FMT_INT "%d" #define TYPE_UINT(min, max) \ (parser_type_t) { \ .name = TYPENAME_UINT, \ .uint = { \ .min = min, \ .max = max, \ }, \ } #define TYPE_FMT_UINT "%u" #define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) #define TYPE_FMT_SYMBOLIC_OR_ID "%s" #define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) #define TYPE_FMT_INTERFACE_NAME "%s" #define TYPE_IP_ADDRESS \ (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } #define TYPE_FMT_IP_ADDRESS "%s" #define TYPE_IP_PREFIX \ (parser_type_t) { .name = TYPENAME_IP_PREFIX, } #define TYPE_FMT_IP_PREFIX "%s" #define TYPE_ON_OFF \ (parser_type_t) { .name = TYPENAME_ON_OFF, } #define TYPE_FMT_ON_OFF "%s" #define TYPE_ENUM(x) \ (parser_type_t) { \ .name = TYPENAME_ENUM, \ .enum_ = { \ .from_str = (int (*)(const char *))x##_from_str, \ }, \ } /* We need to allocate room for the intermediate string */ #define TYPE_FMT_ENUM "%s" #define TYPE_POLICY_STATE(TAG) \ (parser_type_t) { \ .name = TYPENAME_POLICY_STATE, \ .policy_state = { \ .tag = TAG, \ }, \ } /* We need to allocate room for the intermediate string */ #define TYPE_FMT_POLICY_STATE "%s" /** * \brief Register a protocol * \param protocol Pointer to a protocol_t structure describing the protocol to * register \return None */ void command_register(const command_parser_t *command); /** * \brief Search a registered protocol in the library according to its name * \param[in] action The action of the command. * \param[in] object The object of the command. * \param[in] nparams The number of parameters expected in the command. * \return A pointer to the corresponding command if any, NULL othewise */ const command_parser_t *command_search(hc_action_t action, hc_object_type_t object, unsigned nparams); /** * @brief List the commands associated with the specified object and/or action. * Use OBJECT_UNDEFINED and ACTION_UNDEFINED to list all the available objects. * Use ACTION_UNDEFINED to list all the actions associated to the specified * object. * * @param object The action of the command * @param action The object of the command */ void command_list(hc_object_type_t object, hc_action_t action); #define COMMAND_REGISTER(MOD) \ static void __init_##MOD(void) __attribute__((constructor)); \ static void __init_##MOD(void) { command_register(&MOD); } #endif /* HICNLIGHT_CONFIG_COMMAND */