/* * FIB expression. * * Copyright (c) Red Hat GmbH. Author: Florian Westphal * * 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 static const char *fib_result[NFT_FIB_RESULT_MAX + 1] = { [NFT_FIB_RESULT_OIF] = "oif", [NFT_FIB_RESULT_OIFNAME] = "oifname", [NFT_FIB_RESULT_ADDRTYPE] = "type", }; static const struct symbol_table addrtype_tbl = { .base = BASE_DECIMAL, .symbols = { SYMBOL("unspec", RTN_UNSPEC), SYMBOL("unicast", RTN_UNICAST), SYMBOL("local", RTN_LOCAL), SYMBOL("broadcast", RTN_BROADCAST), SYMBOL("anycast", RTN_ANYCAST), SYMBOL("multicast", RTN_MULTICAST), SYMBOL("blackhole", RTN_BLACKHOLE), SYMBOL("unreachable", RTN_UNREACHABLE), SYMBOL("prohibit", RTN_PROHIBIT), SYMBOL_LIST_END } }; const struct datatype fib_addr_type = { .type = TYPE_FIB_ADDR, .name = "fib_addrtype", .desc = "fib address type", .byteorder = BYTEORDER_HOST_ENDIAN, .size = 4 * BITS_PER_BYTE, .basetype = &integer_type, .sym_tbl = &addrtype_tbl, }; static const char *fib_result_str(enum nft_fib_result result) { if (result <= NFT_FIB_RESULT_MAX) return fib_result[result]; return "unknown"; } static void __fib_expr_print_f(unsigned int *flags, unsigned int f, const char *s, struct output_ctx *octx) { if ((*flags & f) == 0) return; nft_print(octx, "%s", s); *flags &= ~f; if (*flags) nft_print(octx, " . "); } static void fib_expr_print(const struct expr *expr, struct output_ctx *octx) { unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT; nft_print(octx, "fib "); __fib_expr_print_f(&flags, NFTA_FIB_F_SADDR, "saddr", octx); __fib_expr_print_f(&flags, NFTA_FIB_F_DADDR, "daddr", octx); __fib_expr_print_f(&flags, NFTA_FIB_F_MARK, "mark", octx); __fib_expr_print_f(&flags, NFTA_FIB_F_IIF, "iif", octx); __fib_expr_print_f(&flags, NFTA_FIB_F_OIF, "oif", octx); if (flags) nft_print(octx, "0x%x", flags); nft_print(octx, " %s", fib_result_str(expr->fib.result)); } static bool fib_expr_cmp(const struct expr *e1, const struct expr *e2) { return e1->fib.result == e2->fib.result && e1->fib.flags == e2->fib.flags; } static void fib_expr_clone(struct expr *new, const struct expr *expr) { new->fib.result = expr->fib.result; new->fib.flags= expr->fib.flags; } static const struct expr_ops fib_expr_ops = { .type = EXPR_FIB, .name = "fib", .print = fib_expr_print, .cmp = fib_expr_cmp, .clone = fib_expr_clone, }; struct expr *fib_expr_alloc(const struct location *loc, unsigned int flags, unsigned int result) { const struct datatype *type; unsigned int len = 4 * BITS_PER_BYTE; struct expr *expr; switch (result) { case NFT_FIB_RESULT_OIF: type = &ifindex_type; break; case NFT_FIB_RESULT_OIFNAME: type = &string_type; len = IFNAMSIZ * BITS_PER_BYTE; break; case NFT_FIB_RESULT_ADDRTYPE: type = &fib_addr_type; break; default: BUG("Unknown result %d\n", result); } if (flags & NFTA_FIB_F_PRESENT) type = &boolean_type; expr = expr_alloc(loc, &fib_expr_ops, type, BYTEORDER_HOST_ENDIAN, len); expr->fib.result = result; expr->fib.flags = flags; return expr; }