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
:
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
]));
90 switch (priv
->result
) {
91 case NFT_FIB_RESULT_OIF
:
92 if (priv
->flags
& NFTA_FIB_F_OIF
)
96 case NFT_FIB_RESULT_OIFNAME
:
97 if (priv
->flags
& NFTA_FIB_F_OIF
)
101 case NFT_FIB_RESULT_ADDRTYPE
:
108 err
= nft_parse_register_store(ctx
, tb
[NFTA_FIB_DREG
], &priv
->dreg
,
109 NULL
, NFT_DATA_VALUE
, len
);
115 EXPORT_SYMBOL_GPL(nft_fib_init
);
117 int nft_fib_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
119 const struct nft_fib
*priv
= nft_expr_priv(expr
);
121 if (nft_dump_register(skb
, NFTA_FIB_DREG
, priv
->dreg
))
124 if (nla_put_be32(skb
, NFTA_FIB_RESULT
, htonl(priv
->result
)))
127 if (nla_put_be32(skb
, NFTA_FIB_FLAGS
, htonl(priv
->flags
)))
132 EXPORT_SYMBOL_GPL(nft_fib_dump
);
134 void nft_fib_store_result(void *reg
, const struct nft_fib
*priv
,
135 const struct net_device
*dev
)
140 switch (priv
->result
) {
141 case NFT_FIB_RESULT_OIF
:
142 index
= dev
? dev
->ifindex
: 0;
143 *dreg
= (priv
->flags
& NFTA_FIB_F_PRESENT
) ? !!index
: index
;
145 case NFT_FIB_RESULT_OIFNAME
:
146 if (priv
->flags
& NFTA_FIB_F_PRESENT
)
149 strncpy(reg
, dev
? dev
->name
: "", IFNAMSIZ
);
157 EXPORT_SYMBOL_GPL(nft_fib_store_result
);
159 MODULE_LICENSE("GPL");
160 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");