1 // SPDX-License-Identifier: GPL-2.0-only
4 * Generic part shared by ipv4 and ipv6 backends.
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/netlink.h>
11 #include <linux/netfilter.h>
12 #include <linux/netfilter/nf_tables.h>
13 #include <net/netfilter/nf_tables_core.h>
14 #include <net/netfilter/nf_tables.h>
15 #include <net/netfilter/nft_fib.h>
17 const struct nla_policy nft_fib_policy
[NFTA_FIB_MAX
+ 1] = {
18 [NFTA_FIB_DREG
] = { .type
= NLA_U32
},
19 [NFTA_FIB_RESULT
] = { .type
= NLA_U32
},
20 [NFTA_FIB_FLAGS
] = { .type
= NLA_U32
},
22 EXPORT_SYMBOL(nft_fib_policy
);
24 #define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
25 NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
28 int nft_fib_validate(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
29 const struct nft_data
**data
)
31 const struct nft_fib
*priv
= nft_expr_priv(expr
);
34 switch (priv
->result
) {
35 case NFT_FIB_RESULT_OIF
: /* fallthrough */
36 case NFT_FIB_RESULT_OIFNAME
:
37 hooks
= (1 << NF_INET_PRE_ROUTING
);
39 case NFT_FIB_RESULT_ADDRTYPE
:
40 if (priv
->flags
& NFTA_FIB_F_IIF
)
41 hooks
= (1 << NF_INET_PRE_ROUTING
) |
42 (1 << NF_INET_LOCAL_IN
) |
43 (1 << NF_INET_FORWARD
);
44 else if (priv
->flags
& NFTA_FIB_F_OIF
)
45 hooks
= (1 << NF_INET_LOCAL_OUT
) |
46 (1 << NF_INET_POST_ROUTING
) |
47 (1 << NF_INET_FORWARD
);
49 hooks
= (1 << NF_INET_LOCAL_IN
) |
50 (1 << NF_INET_LOCAL_OUT
) |
51 (1 << NF_INET_FORWARD
) |
52 (1 << NF_INET_PRE_ROUTING
) |
53 (1 << NF_INET_POST_ROUTING
);
60 return nft_chain_validate_hooks(ctx
->chain
, hooks
);
62 EXPORT_SYMBOL_GPL(nft_fib_validate
);
64 int nft_fib_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
65 const struct nlattr
* const tb
[])
67 struct nft_fib
*priv
= nft_expr_priv(expr
);
71 if (!tb
[NFTA_FIB_DREG
] || !tb
[NFTA_FIB_RESULT
] || !tb
[NFTA_FIB_FLAGS
])
74 priv
->flags
= ntohl(nla_get_be32(tb
[NFTA_FIB_FLAGS
]));
76 if (priv
->flags
== 0 || (priv
->flags
& ~NFTA_FIB_F_ALL
))
79 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) ==
80 (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
))
82 if ((priv
->flags
& (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
)) ==
83 (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
))
85 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) == 0)
88 priv
->result
= ntohl(nla_get_be32(tb
[NFTA_FIB_RESULT
]));
89 priv
->dreg
= nft_parse_register(tb
[NFTA_FIB_DREG
]);
91 switch (priv
->result
) {
92 case NFT_FIB_RESULT_OIF
:
93 if (priv
->flags
& NFTA_FIB_F_OIF
)
97 case NFT_FIB_RESULT_OIFNAME
:
98 if (priv
->flags
& NFTA_FIB_F_OIF
)
102 case NFT_FIB_RESULT_ADDRTYPE
:
109 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
110 NFT_DATA_VALUE
, len
);
116 EXPORT_SYMBOL_GPL(nft_fib_init
);
118 int nft_fib_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
120 const struct nft_fib
*priv
= nft_expr_priv(expr
);
122 if (nft_dump_register(skb
, NFTA_FIB_DREG
, priv
->dreg
))
125 if (nla_put_be32(skb
, NFTA_FIB_RESULT
, htonl(priv
->result
)))
128 if (nla_put_be32(skb
, NFTA_FIB_FLAGS
, htonl(priv
->flags
)))
133 EXPORT_SYMBOL_GPL(nft_fib_dump
);
135 void nft_fib_store_result(void *reg
, const struct nft_fib
*priv
,
136 const struct net_device
*dev
)
141 switch (priv
->result
) {
142 case NFT_FIB_RESULT_OIF
:
143 index
= dev
? dev
->ifindex
: 0;
144 *dreg
= (priv
->flags
& NFTA_FIB_F_PRESENT
) ? !!index
: index
;
146 case NFT_FIB_RESULT_OIFNAME
:
147 if (priv
->flags
& NFTA_FIB_F_PRESENT
)
150 strncpy(reg
, dev
? dev
->name
: "", IFNAMSIZ
);
158 EXPORT_SYMBOL_GPL(nft_fib_store_result
);
160 MODULE_LICENSE("GPL");
161 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");