Blame view
net/netfilter/nft_rt.c
4.43 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
2fa841938 netfilter: nf_tab... |
2 3 |
/* * Copyright (c) 2016 Anders K. Pedersen <akp@cohaesio.com> |
2fa841938 netfilter: nf_tab... |
4 5 6 |
*/ #include <linux/kernel.h> |
2fa841938 netfilter: nf_tab... |
7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <net/dst.h> #include <net/ip6_route.h> #include <net/route.h> #include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables_core.h> struct nft_rt { enum nft_rt_keys key:8; enum nft_registers dreg:8; }; |
6b5dc98e8 netfilter: rt: ad... |
20 21 22 23 |
static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst) { u32 minlen = sizeof(struct ipv6hdr), mtu = dst_mtu(skbdst); const struct sk_buff *skb = pkt->skb; |
3f87c08c6 netfilter: move r... |
24 |
struct dst_entry *dst = NULL; |
6b5dc98e8 netfilter: rt: ad... |
25 26 27 28 29 30 31 |
struct flowi fl; memset(&fl, 0, sizeof(fl)); switch (nft_pf(pkt)) { case NFPROTO_IPV4: fl.u.ip4.daddr = ip_hdr(skb)->saddr; |
1aff64715 netfilter: rt: ac... |
32 |
minlen = sizeof(struct iphdr) + sizeof(struct tcphdr); |
6b5dc98e8 netfilter: rt: ad... |
33 34 35 |
break; case NFPROTO_IPV6: fl.u.ip6.daddr = ipv6_hdr(skb)->saddr; |
1aff64715 netfilter: rt: ac... |
36 |
minlen = sizeof(struct ipv6hdr) + sizeof(struct tcphdr); |
6b5dc98e8 netfilter: rt: ad... |
37 38 |
break; } |
3f87c08c6 netfilter: move r... |
39 40 41 42 |
nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt)); if (dst) { mtu = min(mtu, dst_mtu(dst)); dst_release(dst); |
6b5dc98e8 netfilter: rt: ad... |
43 44 45 46 47 48 49 |
} if (mtu <= minlen || mtu > 0xffff) return TCP_MSS_DEFAULT; return mtu - minlen; } |
10870dd89 netfilter: nf_tab... |
50 51 52 |
void nft_rt_get_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) |
2fa841938 netfilter: nf_tab... |
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
{ const struct nft_rt *priv = nft_expr_priv(expr); const struct sk_buff *skb = pkt->skb; u32 *dest = ®s->data[priv->dreg]; const struct dst_entry *dst; dst = skb_dst(skb); if (!dst) goto err; switch (priv->key) { #ifdef CONFIG_IP_ROUTE_CLASSID case NFT_RT_CLASSID: *dest = dst->tclassid; break; #endif case NFT_RT_NEXTHOP4: |
0e5a1c7eb netfilter: nf_tab... |
70 |
if (nft_pf(pkt) != NFPROTO_IPV4) |
2fa841938 netfilter: nf_tab... |
71 |
goto err; |
5fd02ebe6 netfilter: fix a ... |
72 73 |
*dest = (__force u32)rt_nexthop((const struct rtable *)dst, ip_hdr(skb)->daddr); |
2fa841938 netfilter: nf_tab... |
74 75 |
break; case NFT_RT_NEXTHOP6: |
0e5a1c7eb netfilter: nf_tab... |
76 |
if (nft_pf(pkt) != NFPROTO_IPV6) |
2fa841938 netfilter: nf_tab... |
77 78 79 80 81 82 |
goto err; memcpy(dest, rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr), sizeof(struct in6_addr)); break; |
6b5dc98e8 netfilter: rt: ad... |
83 84 85 |
case NFT_RT_TCPMSS: nft_reg_store16(dest, get_tcpmss(pkt, dst)); break; |
02b408fae netfilter: nf_tab... |
86 87 88 89 90 |
#ifdef CONFIG_XFRM case NFT_RT_XFRM: nft_reg_store8(dest, !!dst->xfrm); break; #endif |
2fa841938 netfilter: nf_tab... |
91 92 93 94 95 96 97 98 99 |
default: WARN_ON(1); goto err; } return; err: regs->verdict.code = NFT_BREAK; } |
5fd02ebe6 netfilter: fix a ... |
100 |
static const struct nla_policy nft_rt_policy[NFTA_RT_MAX + 1] = { |
2fa841938 netfilter: nf_tab... |
101 102 103 |
[NFTA_RT_DREG] = { .type = NLA_U32 }, [NFTA_RT_KEY] = { .type = NLA_U32 }, }; |
cad439445 netfilter: nft_rt... |
104 105 106 |
static int nft_rt_get_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) |
2fa841938 netfilter: nf_tab... |
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
{ struct nft_rt *priv = nft_expr_priv(expr); unsigned int len; if (tb[NFTA_RT_KEY] == NULL || tb[NFTA_RT_DREG] == NULL) return -EINVAL; priv->key = ntohl(nla_get_be32(tb[NFTA_RT_KEY])); switch (priv->key) { #ifdef CONFIG_IP_ROUTE_CLASSID case NFT_RT_CLASSID: #endif case NFT_RT_NEXTHOP4: len = sizeof(u32); break; case NFT_RT_NEXTHOP6: len = sizeof(struct in6_addr); break; |
6b5dc98e8 netfilter: rt: ad... |
126 127 128 |
case NFT_RT_TCPMSS: len = sizeof(u16); break; |
02b408fae netfilter: nf_tab... |
129 130 131 132 133 |
#ifdef CONFIG_XFRM case NFT_RT_XFRM: len = sizeof(u8); break; #endif |
2fa841938 netfilter: nf_tab... |
134 135 136 137 138 139 140 141 |
default: return -EOPNOTSUPP; } priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]); return nft_validate_register_store(ctx, priv->dreg, NULL, NFT_DATA_VALUE, len); } |
cad439445 netfilter: nft_rt... |
142 143 |
static int nft_rt_get_dump(struct sk_buff *skb, const struct nft_expr *expr) |
2fa841938 netfilter: nf_tab... |
144 145 146 147 148 149 150 151 152 153 154 155 |
{ const struct nft_rt *priv = nft_expr_priv(expr); if (nla_put_be32(skb, NFTA_RT_KEY, htonl(priv->key))) goto nla_put_failure; if (nft_dump_register(skb, NFTA_RT_DREG, priv->dreg)) goto nla_put_failure; return 0; nla_put_failure: return -1; } |
6b5dc98e8 netfilter: rt: ad... |
156 157 158 159 160 161 162 163 164 165 |
static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) { const struct nft_rt *priv = nft_expr_priv(expr); unsigned int hooks; switch (priv->key) { case NFT_RT_NEXTHOP4: case NFT_RT_NEXTHOP6: case NFT_RT_CLASSID: |
02b408fae netfilter: nf_tab... |
166 |
case NFT_RT_XFRM: |
6b5dc98e8 netfilter: rt: ad... |
167 168 169 170 171 172 173 174 175 176 177 178 |
return 0; case NFT_RT_TCPMSS: hooks = (1 << NF_INET_FORWARD) | (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_POST_ROUTING); break; default: return -EINVAL; } return nft_chain_validate_hooks(ctx->chain, hooks); } |
2fa841938 netfilter: nf_tab... |
179 180 181 182 183 184 |
static const struct nft_expr_ops nft_rt_get_ops = { .type = &nft_rt_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_rt)), .eval = nft_rt_get_eval, .init = nft_rt_get_init, .dump = nft_rt_get_dump, |
6b5dc98e8 netfilter: rt: ad... |
185 |
.validate = nft_rt_validate, |
2fa841938 netfilter: nf_tab... |
186 |
}; |
ae1bc6a9f netfilter: nf_tab... |
187 |
struct nft_expr_type nft_rt_type __read_mostly = { |
2fa841938 netfilter: nf_tab... |
188 189 190 191 192 193 |
.name = "rt", .ops = &nft_rt_get_ops, .policy = nft_rt_policy, .maxattr = NFTA_RT_MAX, .owner = THIS_MODULE, }; |