Add a table containing all available datatypes and registration/lookup functions.
This will be used to associate a stand-alone set in the kernel with the correct
type without parsing the entire ruleset.
Additionally it would now be possible to remove the global declarations for the
core types. Not done yet though.
Signed-off-by: Patrick McHardy <kaber@trash.net>
TYPE_CT_STATE,
TYPE_CT_DIR,
TYPE_CT_STATUS,
+ __TYPE_MAX
};
+#define TYPE_MAX (__TYPE_MAX - 1)
/**
* enum byteorder
* struct datatype
*
* @type: numeric identifier
- * @name: type name for diagnostics
+ * @name: type name
+ * @desc: type description
* @basetype: basetype for subtypes, determines type compatibilty
* @basefmt: format string for basetype
* @print: function to print a constant of this type
struct datatype {
enum datatypes type;
const char *name;
+ const char *desc;
const struct datatype *basetype;
const char *basefmt;
void (*print)(const struct expr *expr);
const struct symbol_table *sym_tbl;
};
+extern void datatype_register(const struct datatype *dtype);
+extern const struct datatype *datatype_lookup(enum datatypes type);
+extern const struct datatype *datatype_lookup_byname(const char *name);
+
extern struct error_record *symbol_parse(const struct expr *sym,
struct expr **res);
extern void datatype_print(const struct expr *expr);
static const struct datatype ct_state_type = {
.type = TYPE_CT_STATE,
- .name = "conntrack state",
+ .name = "ct_state",
+ .desc = "conntrack state",
.basetype = &bitmask_type,
.sym_tbl = &ct_state_tbl,
};
static const struct datatype ct_dir_type = {
.type = TYPE_CT_DIR,
- .name = "conntrack direction",
+ .name = "ct_dir",
+ .desc = "conntrack direction",
.basetype = &bitmask_type,
.sym_tbl = &ct_dir_tbl,
};
static const struct datatype ct_status_type = {
.type = TYPE_CT_STATUS,
- .name = "conntrack status",
+ .name = "ct_status",
+ .desc = "conntrack status",
.basetype = &bitmask_type,
.sym_tbl = &ct_status_tbl,
};
expr->ct.key = key;
return expr;
}
+
+static void __init ct_init(void)
+{
+ datatype_register(&ct_state_type);
+ datatype_register(&ct_dir_type);
+ datatype_register(&ct_status_type);
+}
#include <gmputil.h>
#include <erec.h>
+static const struct datatype *datatypes[TYPE_MAX + 1] = {
+ [TYPE_VERDICT] = &verdict_type,
+ [TYPE_BITMASK] = &bitmask_type,
+ [TYPE_INTEGER] = &integer_type,
+ [TYPE_STRING] = &string_type,
+ [TYPE_LLADDR] = &lladdr_type,
+ [TYPE_IPADDR] = &ipaddr_type,
+ [TYPE_IP6ADDR] = &ip6addr_type,
+ [TYPE_ETHERTYPE] = ðertype_type,
+ [TYPE_INET_PROTOCOL] = &inet_protocol_type,
+ [TYPE_INET_SERVICE] = &inet_service_type,
+ [TYPE_TIME] = &time_type,
+ [TYPE_MARK] = &mark_type,
+ [TYPE_ARPHRD] = &arphrd_type,
+};
+
+void datatype_register(const struct datatype *dtype)
+{
+ datatypes[dtype->type] = dtype;
+}
+
+const struct datatype *datatype_lookup(enum datatypes type)
+{
+ if (type > TYPE_MAX)
+ return NULL;
+ return datatypes[type];
+}
+
+const struct datatype *datatype_lookup_byname(const char *name)
+{
+ const struct datatype *dtype;
+ enum datatypes type;
+
+ for (type = TYPE_INVALID; type <= TYPE_MAX; type++) {
+ dtype = datatypes[type];
+ if (dtype == NULL)
+ continue;
+ if (!strcmp(dtype->name, name))
+ return dtype;
+ }
+ return NULL;
+}
+
void datatype_print(const struct expr *expr)
{
const struct datatype *dtype = expr->dtype;
return error(&sym->location,
"Can't parse symbolic %s expressions",
- sym->sym_type->name);
+ sym->sym_type->desc);
}
struct error_record *symbolic_constant_parse(const struct expr *sym,
if (s->identifier == NULL)
return error(&sym->location, "Could not parse %s",
- sym->sym_type->name);
+ sym->sym_type->desc);
*res = constant_expr_alloc(&sym->location, sym->sym_type,
tbl->byteorder, tbl->size, &s->value);
const struct datatype invalid_type = {
.type = TYPE_INVALID,
.name = "invalid",
+ .desc = "invalid",
.print = invalid_type_print,
};
const struct datatype verdict_type = {
.type = TYPE_VERDICT,
.name = "verdict",
+ .desc = "netfilter verdict",
.print = verdict_type_print,
};
const struct datatype bitmask_type = {
.type = TYPE_BITMASK,
.name = "bitmask",
+ .desc = "bitmask",
.basetype = &integer_type,
};
if (sym->sym_type != &integer_type)
return NULL;
return error(&sym->location, "Could not parse %s",
- sym->sym_type->name);
+ sym->sym_type->desc);
}
*res = constant_expr_alloc(&sym->location, sym->sym_type,
const struct datatype integer_type = {
.type = TYPE_INTEGER,
.name = "integer",
+ .desc = "integer",
.print = integer_type_print,
.parse = integer_type_parse,
};
const struct datatype string_type = {
.type = TYPE_STRING,
.name = "string",
+ .desc = "string",
.print = string_type_print,
.parse = string_type_parse,
};
const struct datatype lladdr_type = {
.type = TYPE_LLADDR,
- .name = "LL address",
+ .name = "lladdr",
+ .desc = "link layer address",
.basetype = &integer_type,
.print = lladdr_type_print,
.parse = lladdr_type_parse,
const struct datatype ipaddr_type = {
.type = TYPE_IPADDR,
- .name = "IPv4 address",
+ .name = "ipv4_address",
+ .desc = "IPv4 address",
.basetype = &integer_type,
.print = ipaddr_type_print,
.parse = ipaddr_type_parse,
const struct datatype ip6addr_type = {
.type = TYPE_IP6ADDR,
- .name = "IPv6 address",
+ .name = "ipv6_address",
+ .desc = "IPv6 address",
.basetype = &integer_type,
.print = ip6addr_type_print,
.parse = ip6addr_type_parse,
const struct datatype inet_protocol_type = {
.type = TYPE_INET_PROTOCOL,
- .name = "Internet protocol",
+ .name = "inet_protocol",
+ .desc = "Internet protocol",
.basetype = &integer_type,
.print = inet_protocol_type_print,
.parse = inet_protocol_type_parse,
const struct datatype inet_service_type = {
.type = TYPE_INET_SERVICE,
- .name = "internet network service",
+ .name = "inet_service",
+ .desc = "internet network service",
.basetype = &integer_type,
.print = inet_service_type_print,
.parse = inet_service_type_parse,
const struct datatype mark_type = {
.type = TYPE_MARK,
- .name = "packet mark",
+ .name = "mark",
+ .desc = "packet mark",
.basetype = &integer_type,
.basefmt = "0x%.8Zx",
.print = mark_type_print,
const struct datatype time_type = {
.type = TYPE_TIME,
- .name = "relative time",
+ .name = "time",
+ .desc = "relative time",
.basetype = &integer_type,
.print = time_type_print,
};
if (expr_basetype(base)->type != TYPE_INTEGER)
return expr_error(ctx, prefix,
"Prefix expression is undefined for "
- "%s types", base->dtype->name);
+ "%s types", base->dtype->desc);
if (prefix->prefix_len > base->len)
return expr_error(ctx, prefix,
if (expr_basetype(*expr)->type != TYPE_INTEGER)
return expr_binary_error(ctx, *expr, range,
"Range expression is undefined for "
- "%s types", (*expr)->dtype->name);
+ "%s types", (*expr)->dtype->desc);
if (!expr_is_constant(*expr))
return expr_binary_error(ctx, *expr, range,
"Range is not constant");
return expr_binary_error(ctx, left, op,
"Binary operation (%s) is undefined "
"for %s types",
- sym, left->dtype->name);
+ sym, left->dtype->desc);
if (expr_is_constant(left) && !expr_is_singleton(left))
return expr_binary_error(ctx, left, op,
if (i->dtype->basetype->type != TYPE_BITMASK)
return expr_error(ctx, i,
"Basetype of type %s is not bitmask",
- i->dtype->name);
+ i->dtype->desc);
mpz_ior(val, val, i->value);
}
const struct datatype *dtype = expr->dtype;
const char *delim = "";
- printf("%s expression, datatype %s", expr->ops->name, dtype->name);
+ printf("%s expression, datatype %s (%s)",
+ expr->ops->name, dtype->name, dtype->desc);
if (dtype->basetype != NULL) {
printf(" (basetype ");
for (dtype = dtype->basetype; dtype != NULL;
dtype = dtype->basetype) {
- printf("%s%s", delim, dtype->name);
+ printf("%s%s", delim, dtype->desc);
delim = ", ";
}
printf(")");
static const struct datatype mh_type_type = {
.type = TYPE_MH_TYPE,
- .name = "Mobility Header Type",
+ .name = "mh_type",
+ .desc = "Mobility Header Type",
.basetype = &integer_type,
.sym_tbl = &mh_type_tbl,
};
[MHHDR_CHECKSUM] = MH_FIELD("checksum", ip6mh_cksum, &integer_type),
},
};
+
+static void __init exthdr_init(void)
+{
+ datatype_register(&mh_type_type);
+}
static const struct datatype realm_type = {
.type = TYPE_REALM,
- .name = "routing realm",
+ .name = "realm",
+ .desc = "routing realm",
.basetype = &integer_type,
.print = realm_type_print,
.parse = realm_type_parse,
if (rtnl_tc_str2handle(sym->identifier, &handle) < 0)
return error(&sym->location, "Could not parse %s",
- sym->sym_type->name);
+ sym->sym_type->desc);
*res = constant_expr_alloc(&sym->location, sym->sym_type,
BYTEORDER_HOST_ENDIAN,
static const struct datatype tchandle_type = {
.type = TYPE_TC_HANDLE,
- .name = "TC handle",
+ .name = "tc_handle",
+ .desc = "TC handle",
.basetype = &integer_type,
.print = tchandle_type_print,
.parse = tchandle_type_parse,
static const struct datatype ifindex_type = {
.type = TYPE_IFINDEX,
- .name = "interface index",
+ .name = "ifindex",
+ .desc = "interface index",
.basetype = &integer_type,
.print = ifindex_type_print,
.parse = ifindex_type_parse,
const struct datatype arphrd_type = {
.type = TYPE_ARPHRD,
- .name = "hardware type",
+ .name = "arphrd",
+ .desc = "hardware type",
.basetype = &integer_type,
.sym_tbl = &arphrd_tbl,
};
static const struct datatype uid_type = {
.type = TYPE_UID,
- .name = "user ID",
+ .name = "uid",
+ .desc = "user ID",
.basetype = &integer_type,
.print = uid_type_print,
.parse = uid_type_parse,
static const struct datatype gid_type = {
.type = TYPE_GID,
- .name = "group ID",
+ .name = "gid",
+ .desc = "group ID",
.basetype = &integer_type,
.print = gid_type_print,
.parse = gid_type_parse,
stmt->meta.expr = expr;
return stmt;
}
+
+static void __init meta_init(void)
+{
+ datatype_register(&ifindex_type);
+ datatype_register(&realm_type);
+ datatype_register(&tchandle_type);
+ datatype_register(&uid_type);
+ datatype_register(&gid_type);
+}
static const struct datatype icmp_type_type = {
.type = TYPE_ICMP_TYPE,
- .name = "ICMP type",
+ .name = "icmp_type",
+ .desc = "ICMP type",
.basetype = &integer_type,
.sym_tbl = &icmp_type_tbl,
};
static const struct datatype tcp_flag_type = {
.type = TYPE_TCP_FLAG,
- .name = "TCP flag",
+ .name = "tcp_flag",
+ .desc = "TCP flag",
.basetype = &bitmask_type,
.sym_tbl = &tcp_flag_tbl,
};
static const struct datatype arpop_type = {
.type = TYPE_ARPOP,
- .name = "ARP operation",
+ .name = "arp_op",
+ .desc = "ARP operation",
.basetype = &integer_type,
.sym_tbl = &arpop_tbl,
};
const struct datatype ethertype_type = {
.type = TYPE_ETHERTYPE,
- .name = "Ethernet protocol",
+ .name = "ethertype",
+ .desc = "Ethernet protocol",
.basetype = &integer_type,
.sym_tbl = ðertype_tbl,
};
[ETHHDR_TYPE] = ETHHDR_TYPE("type", ether_type),
},
};
+
+static void __init payload_init(void)
+{
+ datatype_register(&icmp_type_type);
+ datatype_register(&tcp_flag_type);
+ datatype_register(&arpop_type);
+ datatype_register(ðertype_type);
+}