2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
6 * Generic part shared by ipv4 and ipv6 backends.
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <net/netfilter/nf_tables_core.h>
16 #include <net/netfilter/nf_tables.h>
17 #include <net/netfilter/nft_fib.h>
19 const struct nla_policy nft_fib_policy
[NFTA_FIB_MAX
+ 1] = {
20 [NFTA_FIB_DREG
] = { .type
= NLA_U32
},
21 [NFTA_FIB_RESULT
] = { .type
= NLA_U32
},
22 [NFTA_FIB_FLAGS
] = { .type
= NLA_U32
},
24 EXPORT_SYMBOL(nft_fib_policy
);
26 #define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
27 NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
30 int nft_fib_validate(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
31 const struct nft_data
**data
)
33 const struct nft_fib
*priv
= nft_expr_priv(expr
);
36 switch (priv
->result
) {
37 case NFT_FIB_RESULT_OIF
: /* fallthrough */
38 case NFT_FIB_RESULT_OIFNAME
:
39 hooks
= (1 << NF_INET_PRE_ROUTING
);
41 case NFT_FIB_RESULT_ADDRTYPE
:
42 if (priv
->flags
& NFTA_FIB_F_IIF
)
43 hooks
= (1 << NF_INET_PRE_ROUTING
) |
44 (1 << NF_INET_LOCAL_IN
) |
45 (1 << NF_INET_FORWARD
);
46 else if (priv
->flags
& NFTA_FIB_F_OIF
)
47 hooks
= (1 << NF_INET_LOCAL_OUT
) |
48 (1 << NF_INET_POST_ROUTING
) |
49 (1 << NF_INET_FORWARD
);
51 hooks
= (1 << NF_INET_LOCAL_IN
) |
52 (1 << NF_INET_LOCAL_OUT
) |
53 (1 << NF_INET_FORWARD
) |
54 (1 << NF_INET_PRE_ROUTING
) |
55 (1 << NF_INET_POST_ROUTING
);
62 return nft_chain_validate_hooks(ctx
->chain
, hooks
);
64 EXPORT_SYMBOL_GPL(nft_fib_validate
);
66 int nft_fib_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
67 const struct nlattr
* const tb
[])
69 struct nft_fib
*priv
= nft_expr_priv(expr
);
73 if (!tb
[NFTA_FIB_DREG
] || !tb
[NFTA_FIB_RESULT
] || !tb
[NFTA_FIB_FLAGS
])
76 priv
->flags
= ntohl(nla_get_be32(tb
[NFTA_FIB_FLAGS
]));
78 if (priv
->flags
== 0 || (priv
->flags
& ~NFTA_FIB_F_ALL
))
81 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) ==
82 (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
))
84 if ((priv
->flags
& (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
)) ==
85 (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
))
87 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) == 0)
90 priv
->result
= ntohl(nla_get_be32(tb
[NFTA_FIB_RESULT
]));
91 priv
->dreg
= nft_parse_register(tb
[NFTA_FIB_DREG
]);
93 switch (priv
->result
) {
94 case NFT_FIB_RESULT_OIF
:
95 if (priv
->flags
& NFTA_FIB_F_OIF
)
99 case NFT_FIB_RESULT_OIFNAME
:
100 if (priv
->flags
& NFTA_FIB_F_OIF
)
104 case NFT_FIB_RESULT_ADDRTYPE
:
111 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
112 NFT_DATA_VALUE
, len
);
118 EXPORT_SYMBOL_GPL(nft_fib_init
);
120 int nft_fib_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
122 const struct nft_fib
*priv
= nft_expr_priv(expr
);
124 if (nft_dump_register(skb
, NFTA_FIB_DREG
, priv
->dreg
))
127 if (nla_put_be32(skb
, NFTA_FIB_RESULT
, htonl(priv
->result
)))
130 if (nla_put_be32(skb
, NFTA_FIB_FLAGS
, htonl(priv
->flags
)))
135 EXPORT_SYMBOL_GPL(nft_fib_dump
);
137 void nft_fib_store_result(void *reg
, const struct nft_fib
*priv
,
138 const struct nft_pktinfo
*pkt
, int index
)
140 struct net_device
*dev
;
143 switch (priv
->result
) {
144 case NFT_FIB_RESULT_OIF
:
145 *dreg
= (priv
->flags
& NFTA_FIB_F_PRESENT
) ? !!index
: index
;
147 case NFT_FIB_RESULT_OIFNAME
:
148 dev
= dev_get_by_index_rcu(nft_net(pkt
), index
);
149 if (priv
->flags
& NFTA_FIB_F_PRESENT
)
152 strncpy(reg
, dev
? dev
->name
: "", IFNAMSIZ
);
160 EXPORT_SYMBOL_GPL(nft_fib_store_result
);
162 MODULE_LICENSE("GPL");
163 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");