/******************************************************************************
 * file    include/cmd.h 
 * author  YuLiang
 * version 1.0.0
 * date    09-Oct-2021
 * brief   This file provides all the headers of the command functions.
 
 ******************************************************************************
 * Attention
 *
 * 
© COPYRIGHT(c) 2021 LandPower
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of LandPower nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/
#ifndef _CMD_H_
#define _CMD_H_
/* Includes ------------------------------------------------------------------*/
#include "array.h"
#include "vty.h"
/* Define --------------------------------------------------------------------*/
/* 命令行最大参数个数. */
#define CMD_ARGC_MAX   16
/* rang检查数字最大位数. */
#define DECIMAL_STRLEN_MAX 10
#define INIT_MATCHARR_SIZE 10
#define COMPLETE_BUF_SIZE 256
#define IPV6_ADDR_STR       "0123456789abcdefABCDEF:.%"
#define IPV6_PREFIX_STR     "0123456789abcdefABCDEF:.%/"
#define STATE_START         1
#define STATE_COLON         2
#define STATE_DOUBLE        3
#define STATE_ADDR          4
#define STATE_DOT           5
#define STATE_SLASH         6
#define STATE_MASK          7
/* 命令行返回值. */
#define CMD_SUCCESS              0
#define CMD_WARNING              1
#define CMD_ERR_NO_MATCH         2
#define CMD_ERR_AMBIGUOUS        3
#define CMD_ERR_INCOMPLETE       4
#define CMD_ERR_EXEED_ARGC_MAX   5
#define CMD_ERR_NOTHING_TODO     6
#define CMD_COMPLETE_FULL_MATCH  7
#define CMD_COMPLETE_MATCH       8
#define CMD_COMPLETE_LIST_MATCH  9
#define CMD_SUCCESS_DAEMON      10
#define CONF_BACKUP_EXT ".sav"
#define CL_COPYRIGHT "Copyright 2025-2027 LandPower."
/* Common descriptions. */
#define SHOW_STR "Show running system information\n"
#define IP_STR "IP information\n"
#define IPV6_STR "IPv6 information\n"
#define NO_STR "Negate a command or set its defaults\n"
#define REDIST_STR "Redistribute information from another routing protocol\n"
#define CLEAR_STR "Reset functions\n"
#define RIP_STR "RIP information\n"
#define BGP_STR "BGP information\n"
#define OSPF_STR "OSPF information\n"
#define NEIGHBOR_STR "Specify neighbor router\n"
#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
#define ROUTER_STR "Enable a routing process\n"
#define AS_STR "AS number\n"
#define MBGP_STR "MBGP information\n"
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
#define OUT_STR "Filter outgoing routing updates\n"
#define IN_STR  "Filter incoming routing updates\n"
#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
#define OSPF6_NUMBER_STR "Specify by number\n"
#define INTERFACE_STR "Interface infomation\n"
#define IFNAME_STR "Interface name(e.g. ep0)\n"
#define IP6_STR "IPv6 Information\n"
#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
#define OSPF6_ROUTER_STR "Enable a routing process\n"
#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
#define SECONDS_STR "<1-65535> Seconds\n"
#define ROUTE_STR "Routing Table\n"
#define PREFIX_LIST_STR "Build a prefix list\n"
/* Some macroes */
#define CMD_OPTION(S)       ('[' == (S[0]))
#define CMD_VARIABLE(S)     (((S[0]) >= 'A' && (S[0]) <= 'Z') || ('<' == (S[0])))
#define CMD_VARARG(S)       ('.' ==(S[0]))
#define CMD_RANGE(S)        ('<' == (S[0]))
#define CMD_IPV4(S)         (0 == strcmp((S), "A.B.C.D"))
#define CMD_IPV4_PREFIX(S)  (0 == strcmp((S), "A.B.C.D/M"))
#define CMD_IPV6(S)         (0 == strcmp((S), "X:X::X:X"))
#define CMD_IPV6_PREFIX(S)  (0 == strcmp((S), "X:X::X:X/M"))
#define DEV_INFO_DEFAULT_IP "192.168.0.10"
#define DEV_INFO_DEFAULT_MASK "255.255.255.0"
#define DEV_INFO_DEFAULT_GW "192.168.0.1"
#define SAVE_STA_CFG_BAK_FILE       1
#define SAVE_DEV_CFG_BAK_FILE       2
/* Exported types ------------------------------------------------------------*/
enum
{
    CMD_ATTR_DEPRECATED = 1,
    CMD_ATTR_HIDDEN,
};
/* 匹配结果类型. */
typedef enum
{
    no_match,
    extend_match,
    ipv4_prefix_match,
    ipv4_match,
    ipv6_prefix_match,
    ipv6_match,
    range_match,
    vararg_match,
    partly_match,
    exact_match 
}  MATCH_TYPE_E;
/* 用于定义命令的宏. */
#define CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
    cmd_element_t cmdname = \
    { \
        .string = cmdstr, \
        .func = funcname, \
        .doc = helpstr, \
        .attr = attrs, \
        .daemon = dnum, \
    };
#define CMD_FUNC_DECL(funcname) \
    static int funcname(cmd_element_t *, vty_t *, int, const char *[]);
#define CMD_FUNC_TEXT(funcname) \
    static int funcname \
        (cmd_element_t *self __attribute__ ((unused)), \
        vty_t *vty __attribute__ ((unused)), \
        int argc __attribute__ ((unused)), \
        const char *argv[] __attribute__ ((unused)))
/* CMD for vty command interafce. Little bit hacky ;-). */
#define CMD(funcname, cmdname, cmdstr, helpstr) \
    CMD_FUNC_DECL(funcname) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
    CMD_FUNC_TEXT(funcname)
#define CMD_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
    CMD_FUNC_DECL(funcname) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
    CMD_FUNC_TEXT(funcname)
#define CMD_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
    CMD_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
#define CMD_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
    CMD_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
/* ALIAS macro which define existing command's alias. */
#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
    CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
/* 命令行模式节点宏 */
typedef enum
{
    USERNAME_NODE,      /* Username node. Default mode of vty interface. */
    PASSWORD_NODE,      /* Password node. */
    ENABLE_NODE,        /* Enable node. */
    CONFIG_NODE,        /* Config node. Default mode of config file. */
    PORT_NODE,          /* Port node. */
    COMMON_NODE,        /* Common node. Cmd is common to other node. */
    NODES_COUNT
} NODE_TYPE_E;
/* config节点配置优先级 */
typedef enum
{
    CONFIG_PRI_CSG = 0,
    CONFIG_PRI_DAU,
    CONFIG_PRI_PD,
    CONFIG_PRI_COUNT
} CONFIG_PRI_E;
/* Host configuration variable */
typedef struct{
    uint8_t type_m;                 // 主设备号
    uint8_t type_s;                 // 次设备号
    uint8_t reserved1[2];           // 保留
    uint32_t dev_id;                // 设备ID
    char hostname[FILE_NAME_LEN];   // 设备名 128byte
    uint32_t factory_date;          // 出厂日期.
    uint32_t deployment_date;       // 部署日期.
    uint8_t app_version[32];        // 软件版本
    uint8_t app_compile_time[32];   // 软件编译时间
    uint8_t hardware_version[32];   // 硬件版本
    uint8_t FPGA_version[32];       // fpga版本
    uint32_t ip;                    // 本机 IP.
    uint32_t mask;                  // 本机 MASK.
    uint32_t gw;                    // 本机网关
    uint8_t mac[6];                 // MAC地址.
    uint16_t server_port;           // 服务器端口号.
    uint32_t server_ipv4;           // 服务器 IP.
} device_info_t;
/* Host configuration variable */
typedef struct
{
    char name[FILE_NAME_LEN];       /* Host name of this router. */
    int lines;                      /* System wide terminal lines. */
    char *version;                  /* 版本号. */
    char *compile;                  /* 编译时间. */
    char configfile[FILE_NAME_LEN]; /* config file name of this host */
    char bannerfile[FILE_NAME_LEN]; /* Banner configuration file name. */
} host_t;
/* Structure of command element. */
typedef struct _cmd_element 
{
    const char *string;         /* Command specification by string */
    const char *doc;            /* Documentation of this command */
    array_t *strs;              /* Pointing out each description array */
    unsigned int str_size;      /* Command index count */
    int (*func)(struct _cmd_element*, vty_t*, int, const char *[]);
    int daemon;                 /* Daemon to which this command belong */
    char *config;               /* Configuration string */
    array_t *sub_cfg;           /* Sub configuration string */
    unsigned char attr;         /* Command attributes */
} cmd_element_t;
/* Command description structure. */
typedef struct
{
    char *cmd;                    /* Command string. */
    char *str;                    /* Command's description. */
} desc_t;
/* 用于命令行模式节点注册配置保存函数 */
typedef int cmd_save_config_f(vty_t*);
/* 命令行模式节点结构体 */
typedef struct
{
    uint32_t node;              /* Node index. */
    uint32_t up_node;           /* Upper level node index. */
    uint8_t param_num;          /* Prompt param num. */
    char *prompt;               /* Prompt character at vty interface. */
    cmd_save_config_f *func;    /* Node's configuration write function */
    array_t *cmds;              /* Array of this node's command list. */
    array_t *configs;           /* 配置函数数组. */
} cmd_node_t;
/* Exported macro ------------------------------------------------------------*/
/* Extern global variables ---------------------------------------------------*/
extern host_t host;
extern device_info_t device_info;
extern array_t *cmd_nodes;
extern int8_t is_system_init;
/* Extern functions ----------------------------------------------------------*/
static inline cmd_node_t *cmd_node_get(NODE_TYPE_E ntype)
{    
    return (cmd_node_t *)array_lookup(cmd_nodes, ntype);
}
extern void cmd_init(void);
extern int32_t cmd_execute(vty_t *vty);
extern const char *cmd_prompt(NODE_TYPE_E ntype);
extern array_t *cmd_strs_create(const char *string);
extern void cmd_strs_free(array_t *a);
extern void cmd_sort_node(void);
extern void cmd_install_node(cmd_node_t *node, cmd_save_config_f *func);
extern array_t *cmd_describe_command (array_t *cmd_line, vty_t *vty, int32_t *status);
extern char **cmd_complete_command(array_t *vline, vty_t *vty, int32_t *status);
extern void cmd_install_element(NODE_TYPE_E ntype, cmd_element_t *cmd);
extern int32_t cmd_config_node_config_register(int32_t pri, cmd_save_config_f *func);
extern void vtysh_init(void);
extern char *vtysh_prompt (void);
extern int vtysh_rl_question(void);
extern int vtysh_rl_completion(void);
extern char *vtysh_completion_entry_function(const char *ignore, int invoking_key);
extern void vtysh_config_recovery(void);
extern void vtysh_device_save(void);
extern void vtysh_eth0_save(void);
extern int32_t vtysh_config_save(void);
extern int32_t vtysh_host_addr_set(char *addr, char *mask);
extern int32_t vtysh_gateway_set(char *gateway);
extern void vtysh_shell_init(void);
extern void vtycmd_init(void);
extern void vtycmd_cmd_init(void);
extern bool vtycmd_connect(void);
extern void vtycmd_print(const char *format, va_list va);
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/