/* * Routing expression related definition and types. * * Copyright (c) 2016 Anders K. Pedersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include #include #include static struct symbol_table *realm_tbl; void realm_table_rt_init(void) { realm_tbl = rt_symbol_table_init("/etc/iproute2/rt_realms"); } void realm_table_rt_exit(void) { rt_symbol_table_free(realm_tbl); } static void realm_type_print(const struct expr *expr, struct output_ctx *octx) { return symbolic_constant_print(realm_tbl, expr, true, octx); } static struct error_record *realm_type_parse(const struct expr *sym, struct expr **res) { return symbolic_constant_parse(sym, realm_tbl, res); } const struct datatype realm_type = { .type = TYPE_REALM, .name = "realm", .desc = "routing realm", .byteorder = BYTEORDER_HOST_ENDIAN, .size = 4 * BITS_PER_BYTE, .basetype = &integer_type, .print = realm_type_print, .parse = realm_type_parse, .flags = DTYPE_F_PREFIX, }; static const struct rt_template rt_templates[] = { [NFT_RT_CLASSID] = RT_TEMPLATE("classid", &realm_type, 4 * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN, false), [NFT_RT_NEXTHOP4] = RT_TEMPLATE("nexthop", &ipaddr_type, 4 * BITS_PER_BYTE, BYTEORDER_BIG_ENDIAN, true), [NFT_RT_NEXTHOP6] = RT_TEMPLATE("nexthop", &ip6addr_type, 16 * BITS_PER_BYTE, BYTEORDER_BIG_ENDIAN, true), [NFT_RT_TCPMSS] = RT_TEMPLATE("mtu", &integer_type, 2 * BITS_PER_BYTE, BYTEORDER_HOST_ENDIAN, false), }; static void rt_expr_print(const struct expr *expr, struct output_ctx *octx) { const char *ip = ""; switch (expr->rt.key) { case NFT_RT_NEXTHOP4: ip = "ip "; break; case NFT_RT_NEXTHOP6: ip = "ip6 "; break; default: break; } nft_print(octx, "rt %s%s", ip, rt_templates[expr->rt.key].token); } static bool rt_expr_cmp(const struct expr *e1, const struct expr *e2) { return e1->rt.key == e2->rt.key; } static void rt_expr_clone(struct expr *new, const struct expr *expr) { new->rt.key = expr->rt.key; } static const struct expr_ops rt_expr_ops = { .type = EXPR_RT, .name = "rt", .print = rt_expr_print, .cmp = rt_expr_cmp, .clone = rt_expr_clone, }; struct expr *rt_expr_alloc(const struct location *loc, enum nft_rt_keys key, bool invalid) { const struct rt_template *tmpl = &rt_templates[key]; struct expr *expr; if (invalid && tmpl->invalid) expr = expr_alloc(loc, &rt_expr_ops, &invalid_type, tmpl->byteorder, 0); else expr = expr_alloc(loc, &rt_expr_ops, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->rt.key = key; return expr; } void rt_expr_update_type(struct proto_ctx *ctx, struct expr *expr) { const struct proto_desc *desc; switch (expr->rt.key) { case NFT_RT_NEXTHOP4: desc = ctx->protocol[PROTO_BASE_NETWORK_HDR].desc; if (desc == &proto_ip) expr->dtype = &ipaddr_type; else if (desc == &proto_ip6) { expr->rt.key++; expr->dtype = &ip6addr_type; } expr->len = expr->dtype->size; break; default: break; } }