root/sbin/ifconfig/parse.h
/*      $NetBSD: parse.h,v 1.9 2019/08/16 10:33:17 msaitoh Exp $        */

#ifndef _IFCONFIG_PARSE_H
#define _IFCONFIG_PARSE_H

#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/queue.h>
#include <prop/proplib.h>
#include <sys/socket.h>

struct match;
struct parser;

extern struct pbranch command_root;

typedef int (*parser_exec_t)(prop_dictionary_t, prop_dictionary_t);
typedef int (*parser_match_t)(const struct parser *, const struct match *,
    struct match *, int, const char *);
typedef int (*parser_init_t)(struct parser *);

struct match {
        prop_dictionary_t       m_env;
        const struct parser     *m_nextparser;
        const struct parser     *m_parser;
        int                     m_argidx;
        parser_exec_t           m_exec;
};

/* method table */
struct parser_methods {
        parser_match_t  pm_match;
        parser_init_t   pm_init;
};

struct parser {
        const struct parser_methods     *p_methods;
        parser_exec_t                   p_exec;
        const char                      *p_name;
        struct parser                   *p_nextparser;
        bool                            p_initialized;
};

struct branch {
        SIMPLEQ_ENTRY(branch)   b_next;
        struct parser   *b_nextparser;
};

struct pbranch {
        struct parser           pb_parser;
        SIMPLEQ_HEAD(, branch)  pb_branches;
        bool                    pb_match_first;
        const struct branch     *pb_brinit;
        size_t                  pb_nbrinit;
};

struct pterm {
        struct parser           pt_parser;
        const char              *pt_key;
};

extern const struct parser_methods paddr_methods;
extern const struct parser_methods pbranch_methods;
extern const struct parser_methods piface_methods;
extern const struct parser_methods pinteger_methods;
extern const struct parser_methods pstr_methods;
extern const struct parser_methods pkw_methods;
extern const struct parser_methods pterm_methods;

#define PTERM_INITIALIZER(__pt, __name, __exec, __key)                  \
{                                                                       \
        .pt_parser = {.p_name = (__name), .p_methods = &pterm_methods,  \
                      .p_exec = (__exec)},                              \
        .pt_key = (__key)                                               \
}

#define PBRANCH_INITIALIZER(__pb, __name, __brs, __nbr, __match_first)  \
{                                                                       \
        .pb_parser = {.p_name = (__name), .p_methods = &pbranch_methods},\
        .pb_branches = SIMPLEQ_HEAD_INITIALIZER((__pb)->pb_branches),   \
        .pb_brinit = (__brs),                                           \
        .pb_nbrinit = (__nbr),                                          \
        .pb_match_first = (__match_first)                               \
}

#define PSTR_INITIALIZER(__ps, __name, __defexec, __defkey, __defnext)  \
    PSTR_INITIALIZER1((__ps), (__name), (__defexec), (__defkey),        \
    true, (__defnext))

#define PSTR_INITIALIZER1(__ps, __name, __defexec, __defkey, __defhexok,\
    __defnext)                                                          \
{                                                                       \
        .ps_parser = {.p_name = (__name), .p_methods = &pstr_methods,   \
                       .p_exec = (__defexec),                           \
                       .p_nextparser = (__defnext)},                    \
        .ps_key = (__defkey),                                           \
        .ps_hexok = (__defhexok)                                        \
}

#define PADDR_INITIALIZER(__pa, __name, __defexec, __addrkey,           \
    __maskkey, __activator, __deactivator, __defnext)           \
{                                                                       \
        .pa_parser = {.p_name = (__name), .p_methods = &paddr_methods,  \
                       .p_exec = (__defexec),                           \
                       .p_nextparser = (__defnext)},                    \
        .pa_addrkey = (__addrkey),                                      \
        .pa_maskkey = (__maskkey),                                      \
        .pa_activator = (__activator),                                  \
        .pa_deactivator = (__deactivator),                              \
}

#define PIFACE_INITIALIZER(__pif, __name, __defexec, __defkey, __defnext)\
{                                                                       \
        .pif_parser = {.p_name = (__name), .p_methods = &piface_methods,\
                       .p_exec = (__defexec),                           \
                       .p_nextparser = (__defnext)},                    \
        .pif_key = (__defkey)                                           \
}

#define PINTEGER_INITIALIZER1(__pi, __name, __min, __max, __base,       \
    __defexec, __defkey, __defnext)                                     \
{                                                                       \
        .pi_parser = {.p_name = (__name), .p_methods = &pinteger_methods,\
                      .p_exec = (__defexec),                            \
                      .p_nextparser = (__defnext),                      \
                      .p_initialized = false},                          \
        .pi_min = (__min),                                              \
        .pi_max = (__max),                                              \
        .pi_base = (__base),                                            \
        .pi_key = (__defkey)                                            \
}

#define PINTEGER_INITIALIZER(__pi, __name, __base, __defexec, __defkey, \
    __defnext)                                                          \
        PINTEGER_INITIALIZER1(__pi, __name, INTMAX_MIN, INTMAX_MAX,     \
            __base, __defexec, __defkey, __defnext)

#define PKW_INITIALIZER(__pk, __name, __defexec, __defkey, __kws, __nkw,\
        __defnext)                                                      \
{                                                                       \
        .pk_parser = {.p_name = (__name),                               \
                      .p_exec = (__defexec),                            \
                      .p_methods = &pkw_methods,                        \
                      .p_initialized = false},                          \
        .pk_keywords = SIMPLEQ_HEAD_INITIALIZER((__pk)->pk_keywords),   \
        .pk_kwinit = (__kws),                                           \
        .pk_nkwinit = (__nkw),                                          \
        .pk_keyinit = (__defkey),                                       \
        .pk_nextinit = (__defnext)                                      \
}

#define IFKW(__word, __flag)                                    \
{                                                               \
        .k_word = (__word), .k_neg = true, .k_type = KW_T_INT,  \
        .k_int = (__flag),                                      \
        .k_negint = -(__flag)                                   \
}

#define KW_T_NONE       0
#define KW_T_OBJ        1
#define KW_T_INT        2
#define KW_T_STR        3
#define KW_T_BOOL       4
#define KW_T_UINT       5

struct kwinst {
        SIMPLEQ_ENTRY(kwinst)   k_next;
        int                     k_type;
        const char              *k_word;
        const char              *k_key;
        const char              *k_act;
        const char              *k_deact;
        const char              *k_altdeact;
        parser_exec_t           k_exec;
        union kwval {
                int64_t         u_sint;
                uint64_t        u_uint;
                const char      *u_str;
                prop_object_t   u_obj;
                bool            u_bool;
        } k_u, k_negu;
#define k_int   k_u.u_sint
#define k_uint  k_u.u_uint
#define k_str   k_u.u_str
#define k_obj   k_u.u_obj
#define k_bool  k_u.u_bool

#define k_negint        k_negu.u_sint
#define k_neguint       k_negu.u_uint
#define k_negstr        k_negu.u_str
#define k_negobj        k_negu.u_obj
#define k_negbool       k_negu.u_bool

        bool                    k_neg;  /* allow negative form, -keyword */
        struct parser           *k_nextparser;
};

struct pkw {
        struct parser           pk_parser;
        const char              *pk_key;
        const char              *pk_keyinit;
        const struct kwinst     *pk_kwinit;
        size_t                  pk_nkwinit;
        SIMPLEQ_HEAD(, kwinst)  pk_keywords;
};

#define pk_nextinit     pk_parser.p_nextparser
#define pk_execinit     pk_parser.p_exec

struct pstr {
        struct parser           ps_parser;
        const char              *ps_key;
        bool                    ps_hexok;
};

struct pinteger {
        struct parser           pi_parser;
        int64_t                 pi_min;
        int64_t                 pi_max;
        int                     pi_base;
        const char              *pi_key;
};

struct intrange {
        SIMPLEQ_ENTRY(intrange) r_next;
        int64_t                 r_bottom;
        int64_t                 r_top;
        struct parser           *r_nextparser;
};

struct pranges {
        struct parser           pr_parser;
        SIMPLEQ_HEAD(, intrange)        pr_ranges;
};

struct paddr_prefix {
        int16_t         pfx_len;
        struct sockaddr pfx_addr;
};

static inline size_t
paddr_prefix_size(const struct paddr_prefix *pfx)
{
        return offsetof(struct paddr_prefix, pfx_addr) + pfx->pfx_addr.sa_len;
}

struct paddr {
        struct parser           pa_parser;
        const char              *pa_addrkey;
        const char              *pa_maskkey;
        const char              *pa_activator;
        const char              *pa_deactivator;
};

struct piface {
        struct parser           pif_parser;
        const char              *pif_key;
};

struct prest {
        struct parser           pr_parser;
};

struct prest *prest_create(const char *);
struct paddr *paddr_create(const char *, parser_exec_t, const char *,
    const char *, struct parser *);
struct pstr *pstr_create(const char *, parser_exec_t, const char *,
    bool, struct parser *);
struct piface *piface_create(const char *, parser_exec_t, const char *,
    struct parser *);
struct pkw *pkw_create(const char *, parser_exec_t,
    const char *, const struct kwinst *, size_t, struct parser *);
struct pranges *pranges_create(const char *, parser_exec_t, const char *,
    const struct intrange *, size_t, struct parser *);
struct pbranch *pbranch_create(const char *, const struct branch *, size_t,
    bool);
int pbranch_addbranch(struct pbranch *, struct parser *);
int pbranch_setbranches(struct pbranch *, const struct branch *, size_t);

int parse(int, char **, const struct parser *, struct match *, size_t *, int *);

int matches_exec(const struct match *, prop_dictionary_t, size_t);
int parser_init(struct parser *);

#endif /* _IFCONFIG_PARSE_H */