Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 729 lines 20 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#include <linux/kernel.h> 3#include <linux/init.h> 4#include <linux/module.h> 5#include <linux/seqlock.h> 6#include <linux/netlink.h> 7#include <linux/netfilter.h> 8#include <linux/netfilter/nf_tables.h> 9#include <net/netfilter/nf_tables.h> 10#include <net/dst_metadata.h> 11#include <net/ip_tunnels.h> 12#include <net/vxlan.h> 13#include <net/erspan.h> 14#include <net/geneve.h> 15 16struct nft_tunnel { 17 enum nft_tunnel_keys key:8; 18 u8 dreg; 19 enum nft_tunnel_mode mode:8; 20 u8 len; 21}; 22 23static void nft_tunnel_get_eval(const struct nft_expr *expr, 24 struct nft_regs *regs, 25 const struct nft_pktinfo *pkt) 26{ 27 const struct nft_tunnel *priv = nft_expr_priv(expr); 28 u32 *dest = &regs->data[priv->dreg]; 29 struct ip_tunnel_info *tun_info; 30 31 tun_info = skb_tunnel_info(pkt->skb); 32 33 switch (priv->key) { 34 case NFT_TUNNEL_PATH: 35 if (!tun_info) { 36 nft_reg_store8(dest, false); 37 return; 38 } 39 if (priv->mode == NFT_TUNNEL_MODE_NONE || 40 (priv->mode == NFT_TUNNEL_MODE_RX && 41 !(tun_info->mode & IP_TUNNEL_INFO_TX)) || 42 (priv->mode == NFT_TUNNEL_MODE_TX && 43 (tun_info->mode & IP_TUNNEL_INFO_TX))) 44 nft_reg_store8(dest, true); 45 else 46 nft_reg_store8(dest, false); 47 break; 48 case NFT_TUNNEL_ID: 49 if (!tun_info) { 50 regs->verdict.code = NFT_BREAK; 51 return; 52 } 53 if (priv->mode == NFT_TUNNEL_MODE_NONE || 54 (priv->mode == NFT_TUNNEL_MODE_RX && 55 !(tun_info->mode & IP_TUNNEL_INFO_TX)) || 56 (priv->mode == NFT_TUNNEL_MODE_TX && 57 (tun_info->mode & IP_TUNNEL_INFO_TX))) 58 *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id)); 59 else 60 regs->verdict.code = NFT_BREAK; 61 break; 62 default: 63 WARN_ON(1); 64 regs->verdict.code = NFT_BREAK; 65 } 66} 67 68static const struct nla_policy nft_tunnel_policy[NFTA_TUNNEL_MAX + 1] = { 69 [NFTA_TUNNEL_KEY] = NLA_POLICY_MAX(NLA_BE32, 255), 70 [NFTA_TUNNEL_DREG] = NLA_POLICY_MAX(NLA_BE32, NFT_REG32_MAX), 71 [NFTA_TUNNEL_MODE] = NLA_POLICY_MAX(NLA_BE32, NFT_TUNNEL_MODE_MAX), 72}; 73 74static int nft_tunnel_get_init(const struct nft_ctx *ctx, 75 const struct nft_expr *expr, 76 const struct nlattr * const tb[]) 77{ 78 struct nft_tunnel *priv = nft_expr_priv(expr); 79 u32 len; 80 81 if (!tb[NFTA_TUNNEL_KEY] || 82 !tb[NFTA_TUNNEL_DREG]) 83 return -EINVAL; 84 85 priv->key = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY])); 86 switch (priv->key) { 87 case NFT_TUNNEL_PATH: 88 len = sizeof(u8); 89 break; 90 case NFT_TUNNEL_ID: 91 len = sizeof(u32); 92 break; 93 default: 94 return -EOPNOTSUPP; 95 } 96 97 if (tb[NFTA_TUNNEL_MODE]) { 98 priv->mode = ntohl(nla_get_be32(tb[NFTA_TUNNEL_MODE])); 99 if (priv->mode > NFT_TUNNEL_MODE_MAX) 100 return -EOPNOTSUPP; 101 } else { 102 priv->mode = NFT_TUNNEL_MODE_NONE; 103 } 104 105 priv->len = len; 106 return nft_parse_register_store(ctx, tb[NFTA_TUNNEL_DREG], &priv->dreg, 107 NULL, NFT_DATA_VALUE, len); 108} 109 110static int nft_tunnel_get_dump(struct sk_buff *skb, 111 const struct nft_expr *expr, bool reset) 112{ 113 const struct nft_tunnel *priv = nft_expr_priv(expr); 114 115 if (nla_put_be32(skb, NFTA_TUNNEL_KEY, htonl(priv->key))) 116 goto nla_put_failure; 117 if (nft_dump_register(skb, NFTA_TUNNEL_DREG, priv->dreg)) 118 goto nla_put_failure; 119 if (nla_put_be32(skb, NFTA_TUNNEL_MODE, htonl(priv->mode))) 120 goto nla_put_failure; 121 return 0; 122 123nla_put_failure: 124 return -1; 125} 126 127static struct nft_expr_type nft_tunnel_type; 128static const struct nft_expr_ops nft_tunnel_get_ops = { 129 .type = &nft_tunnel_type, 130 .size = NFT_EXPR_SIZE(sizeof(struct nft_tunnel)), 131 .eval = nft_tunnel_get_eval, 132 .init = nft_tunnel_get_init, 133 .dump = nft_tunnel_get_dump, 134}; 135 136static struct nft_expr_type nft_tunnel_type __read_mostly = { 137 .name = "tunnel", 138 .family = NFPROTO_NETDEV, 139 .ops = &nft_tunnel_get_ops, 140 .policy = nft_tunnel_policy, 141 .maxattr = NFTA_TUNNEL_MAX, 142 .owner = THIS_MODULE, 143}; 144 145struct nft_tunnel_opts { 146 union { 147 struct vxlan_metadata vxlan; 148 struct erspan_metadata erspan; 149 u8 data[IP_TUNNEL_OPTS_MAX]; 150 } u; 151 IP_TUNNEL_DECLARE_FLAGS(flags); 152 u32 len; 153}; 154 155struct nft_tunnel_obj { 156 struct metadata_dst *md; 157 struct nft_tunnel_opts opts; 158}; 159 160static const struct nla_policy nft_tunnel_ip_policy[NFTA_TUNNEL_KEY_IP_MAX + 1] = { 161 [NFTA_TUNNEL_KEY_IP_SRC] = { .type = NLA_U32 }, 162 [NFTA_TUNNEL_KEY_IP_DST] = { .type = NLA_U32 }, 163}; 164 165static int nft_tunnel_obj_ip_init(const struct nft_ctx *ctx, 166 const struct nlattr *attr, 167 struct ip_tunnel_info *info) 168{ 169 struct nlattr *tb[NFTA_TUNNEL_KEY_IP_MAX + 1]; 170 int err; 171 172 err = nla_parse_nested_deprecated(tb, NFTA_TUNNEL_KEY_IP_MAX, attr, 173 nft_tunnel_ip_policy, NULL); 174 if (err < 0) 175 return err; 176 177 if (!tb[NFTA_TUNNEL_KEY_IP_DST]) 178 return -EINVAL; 179 180 if (tb[NFTA_TUNNEL_KEY_IP_SRC]) 181 info->key.u.ipv4.src = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP_SRC]); 182 if (tb[NFTA_TUNNEL_KEY_IP_DST]) 183 info->key.u.ipv4.dst = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP_DST]); 184 185 return 0; 186} 187 188static const struct nla_policy nft_tunnel_ip6_policy[NFTA_TUNNEL_KEY_IP6_MAX + 1] = { 189 [NFTA_TUNNEL_KEY_IP6_SRC] = { .len = sizeof(struct in6_addr), }, 190 [NFTA_TUNNEL_KEY_IP6_DST] = { .len = sizeof(struct in6_addr), }, 191 [NFTA_TUNNEL_KEY_IP6_FLOWLABEL] = { .type = NLA_U32, } 192}; 193 194static int nft_tunnel_obj_ip6_init(const struct nft_ctx *ctx, 195 const struct nlattr *attr, 196 struct ip_tunnel_info *info) 197{ 198 struct nlattr *tb[NFTA_TUNNEL_KEY_IP6_MAX + 1]; 199 int err; 200 201 err = nla_parse_nested_deprecated(tb, NFTA_TUNNEL_KEY_IP6_MAX, attr, 202 nft_tunnel_ip6_policy, NULL); 203 if (err < 0) 204 return err; 205 206 if (!tb[NFTA_TUNNEL_KEY_IP6_DST]) 207 return -EINVAL; 208 209 if (tb[NFTA_TUNNEL_KEY_IP6_SRC]) { 210 memcpy(&info->key.u.ipv6.src, 211 nla_data(tb[NFTA_TUNNEL_KEY_IP6_SRC]), 212 sizeof(struct in6_addr)); 213 } 214 if (tb[NFTA_TUNNEL_KEY_IP6_DST]) { 215 memcpy(&info->key.u.ipv6.dst, 216 nla_data(tb[NFTA_TUNNEL_KEY_IP6_DST]), 217 sizeof(struct in6_addr)); 218 } 219 if (tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL]) 220 info->key.label = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL]); 221 222 info->mode |= IP_TUNNEL_INFO_IPV6; 223 224 return 0; 225} 226 227static const struct nla_policy nft_tunnel_opts_vxlan_policy[NFTA_TUNNEL_KEY_VXLAN_MAX + 1] = { 228 [NFTA_TUNNEL_KEY_VXLAN_GBP] = { .type = NLA_U32 }, 229}; 230 231static int nft_tunnel_obj_vxlan_init(const struct nlattr *attr, 232 struct nft_tunnel_opts *opts) 233{ 234 struct nlattr *tb[NFTA_TUNNEL_KEY_VXLAN_MAX + 1]; 235 int err; 236 237 err = nla_parse_nested_deprecated(tb, NFTA_TUNNEL_KEY_VXLAN_MAX, attr, 238 nft_tunnel_opts_vxlan_policy, NULL); 239 if (err < 0) 240 return err; 241 242 if (!tb[NFTA_TUNNEL_KEY_VXLAN_GBP]) 243 return -EINVAL; 244 245 opts->u.vxlan.gbp = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_VXLAN_GBP])); 246 247 opts->len = sizeof(struct vxlan_metadata); 248 ip_tunnel_flags_zero(opts->flags); 249 __set_bit(IP_TUNNEL_VXLAN_OPT_BIT, opts->flags); 250 251 return 0; 252} 253 254static const struct nla_policy nft_tunnel_opts_erspan_policy[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = { 255 [NFTA_TUNNEL_KEY_ERSPAN_VERSION] = { .type = NLA_U32 }, 256 [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX] = { .type = NLA_U32 }, 257 [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 }, 258 [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID] = { .type = NLA_U8 }, 259}; 260 261static int nft_tunnel_obj_erspan_init(const struct nlattr *attr, 262 struct nft_tunnel_opts *opts) 263{ 264 struct nlattr *tb[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1]; 265 uint8_t hwid, dir; 266 int err, version; 267 268 err = nla_parse_nested_deprecated(tb, NFTA_TUNNEL_KEY_ERSPAN_MAX, 269 attr, nft_tunnel_opts_erspan_policy, 270 NULL); 271 if (err < 0) 272 return err; 273 274 if (!tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]) 275 return -EINVAL; 276 277 version = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION])); 278 switch (version) { 279 case ERSPAN_VERSION: 280 if (!tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]) 281 return -EINVAL; 282 283 opts->u.erspan.u.index = 284 nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]); 285 break; 286 case ERSPAN_VERSION2: 287 if (!tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] || 288 !tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]) 289 return -EINVAL; 290 291 hwid = nla_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]); 292 dir = nla_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]); 293 294 set_hwid(&opts->u.erspan.u.md2, hwid); 295 opts->u.erspan.u.md2.dir = dir; 296 break; 297 default: 298 return -EOPNOTSUPP; 299 } 300 opts->u.erspan.version = version; 301 302 opts->len = sizeof(struct erspan_metadata); 303 ip_tunnel_flags_zero(opts->flags); 304 __set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, opts->flags); 305 306 return 0; 307} 308 309static const struct nla_policy nft_tunnel_opts_geneve_policy[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = { 310 [NFTA_TUNNEL_KEY_GENEVE_CLASS] = { .type = NLA_U16 }, 311 [NFTA_TUNNEL_KEY_GENEVE_TYPE] = { .type = NLA_U8 }, 312 [NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 }, 313}; 314 315static int nft_tunnel_obj_geneve_init(const struct nlattr *attr, 316 struct nft_tunnel_opts *opts) 317{ 318 struct geneve_opt *opt = (struct geneve_opt *)(opts->u.data + opts->len); 319 struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1]; 320 int err, data_len; 321 322 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_GENEVE_MAX, attr, 323 nft_tunnel_opts_geneve_policy, NULL); 324 if (err < 0) 325 return err; 326 327 if (!tb[NFTA_TUNNEL_KEY_GENEVE_CLASS] || 328 !tb[NFTA_TUNNEL_KEY_GENEVE_TYPE] || 329 !tb[NFTA_TUNNEL_KEY_GENEVE_DATA]) 330 return -EINVAL; 331 332 attr = tb[NFTA_TUNNEL_KEY_GENEVE_DATA]; 333 data_len = nla_len(attr); 334 if (data_len % 4) 335 return -EINVAL; 336 337 opts->len += sizeof(*opt) + data_len; 338 if (opts->len > IP_TUNNEL_OPTS_MAX) 339 return -EINVAL; 340 341 memcpy(opt->opt_data, nla_data(attr), data_len); 342 opt->length = data_len / 4; 343 opt->opt_class = nla_get_be16(tb[NFTA_TUNNEL_KEY_GENEVE_CLASS]); 344 opt->type = nla_get_u8(tb[NFTA_TUNNEL_KEY_GENEVE_TYPE]); 345 ip_tunnel_flags_zero(opts->flags); 346 __set_bit(IP_TUNNEL_GENEVE_OPT_BIT, opts->flags); 347 348 return 0; 349} 350 351static const struct nla_policy nft_tunnel_opts_policy[NFTA_TUNNEL_KEY_OPTS_MAX + 1] = { 352 [NFTA_TUNNEL_KEY_OPTS_UNSPEC] = { 353 .strict_start_type = NFTA_TUNNEL_KEY_OPTS_GENEVE }, 354 [NFTA_TUNNEL_KEY_OPTS_VXLAN] = { .type = NLA_NESTED, }, 355 [NFTA_TUNNEL_KEY_OPTS_ERSPAN] = { .type = NLA_NESTED, }, 356 [NFTA_TUNNEL_KEY_OPTS_GENEVE] = { .type = NLA_NESTED, }, 357}; 358 359static int nft_tunnel_obj_opts_init(const struct nft_ctx *ctx, 360 const struct nlattr *attr, 361 struct ip_tunnel_info *info, 362 struct nft_tunnel_opts *opts) 363{ 364 struct nlattr *nla; 365 int err, rem; 366 u32 type = 0; 367 368 err = nla_validate_nested_deprecated(attr, NFTA_TUNNEL_KEY_OPTS_MAX, 369 nft_tunnel_opts_policy, NULL); 370 if (err < 0) 371 return err; 372 373 nla_for_each_attr(nla, nla_data(attr), nla_len(attr), rem) { 374 switch (nla_type(nla)) { 375 case NFTA_TUNNEL_KEY_OPTS_VXLAN: 376 if (type) 377 return -EINVAL; 378 err = nft_tunnel_obj_vxlan_init(nla, opts); 379 if (err) 380 return err; 381 type = IP_TUNNEL_VXLAN_OPT_BIT; 382 break; 383 case NFTA_TUNNEL_KEY_OPTS_ERSPAN: 384 if (type) 385 return -EINVAL; 386 err = nft_tunnel_obj_erspan_init(nla, opts); 387 if (err) 388 return err; 389 type = IP_TUNNEL_ERSPAN_OPT_BIT; 390 break; 391 case NFTA_TUNNEL_KEY_OPTS_GENEVE: 392 if (type && type != IP_TUNNEL_GENEVE_OPT_BIT) 393 return -EINVAL; 394 err = nft_tunnel_obj_geneve_init(nla, opts); 395 if (err) 396 return err; 397 type = IP_TUNNEL_GENEVE_OPT_BIT; 398 break; 399 default: 400 return -EOPNOTSUPP; 401 } 402 } 403 404 return err; 405} 406 407static const struct nla_policy nft_tunnel_key_policy[NFTA_TUNNEL_KEY_MAX + 1] = { 408 [NFTA_TUNNEL_KEY_IP] = { .type = NLA_NESTED, }, 409 [NFTA_TUNNEL_KEY_IP6] = { .type = NLA_NESTED, }, 410 [NFTA_TUNNEL_KEY_ID] = { .type = NLA_U32, }, 411 [NFTA_TUNNEL_KEY_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NFT_TUNNEL_F_MASK), 412 [NFTA_TUNNEL_KEY_TOS] = { .type = NLA_U8, }, 413 [NFTA_TUNNEL_KEY_TTL] = { .type = NLA_U8, }, 414 [NFTA_TUNNEL_KEY_SPORT] = { .type = NLA_U16, }, 415 [NFTA_TUNNEL_KEY_DPORT] = { .type = NLA_U16, }, 416 [NFTA_TUNNEL_KEY_OPTS] = { .type = NLA_NESTED, }, 417}; 418 419static int nft_tunnel_obj_init(const struct nft_ctx *ctx, 420 const struct nlattr * const tb[], 421 struct nft_object *obj) 422{ 423 struct nft_tunnel_obj *priv = nft_obj_data(obj); 424 struct ip_tunnel_info info; 425 struct metadata_dst *md; 426 int err; 427 428 if (!tb[NFTA_TUNNEL_KEY_ID]) 429 return -EINVAL; 430 431 memset(&info, 0, sizeof(info)); 432 info.mode = IP_TUNNEL_INFO_TX; 433 info.key.tun_id = key32_to_tunnel_id(nla_get_be32(tb[NFTA_TUNNEL_KEY_ID])); 434 __set_bit(IP_TUNNEL_KEY_BIT, info.key.tun_flags); 435 __set_bit(IP_TUNNEL_CSUM_BIT, info.key.tun_flags); 436 __set_bit(IP_TUNNEL_NOCACHE_BIT, info.key.tun_flags); 437 438 if (tb[NFTA_TUNNEL_KEY_IP]) { 439 err = nft_tunnel_obj_ip_init(ctx, tb[NFTA_TUNNEL_KEY_IP], &info); 440 if (err < 0) 441 return err; 442 } else if (tb[NFTA_TUNNEL_KEY_IP6]) { 443 err = nft_tunnel_obj_ip6_init(ctx, tb[NFTA_TUNNEL_KEY_IP6], &info); 444 if (err < 0) 445 return err; 446 } else { 447 return -EINVAL; 448 } 449 450 if (tb[NFTA_TUNNEL_KEY_SPORT]) { 451 info.key.tp_src = nla_get_be16(tb[NFTA_TUNNEL_KEY_SPORT]); 452 } 453 if (tb[NFTA_TUNNEL_KEY_DPORT]) { 454 info.key.tp_dst = nla_get_be16(tb[NFTA_TUNNEL_KEY_DPORT]); 455 } 456 457 if (tb[NFTA_TUNNEL_KEY_FLAGS]) { 458 u32 tun_flags; 459 460 tun_flags = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_FLAGS])); 461 if (tun_flags & ~NFT_TUNNEL_F_MASK) 462 return -EOPNOTSUPP; 463 464 if (tun_flags & NFT_TUNNEL_F_ZERO_CSUM_TX) 465 __clear_bit(IP_TUNNEL_CSUM_BIT, info.key.tun_flags); 466 if (tun_flags & NFT_TUNNEL_F_DONT_FRAGMENT) 467 __set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, 468 info.key.tun_flags); 469 if (tun_flags & NFT_TUNNEL_F_SEQ_NUMBER) 470 __set_bit(IP_TUNNEL_SEQ_BIT, info.key.tun_flags); 471 } 472 if (tb[NFTA_TUNNEL_KEY_TOS]) 473 info.key.tos = nla_get_u8(tb[NFTA_TUNNEL_KEY_TOS]); 474 info.key.ttl = nla_get_u8_default(tb[NFTA_TUNNEL_KEY_TTL], U8_MAX); 475 476 if (tb[NFTA_TUNNEL_KEY_OPTS]) { 477 err = nft_tunnel_obj_opts_init(ctx, tb[NFTA_TUNNEL_KEY_OPTS], 478 &info, &priv->opts); 479 if (err < 0) 480 return err; 481 } 482 483 md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, 484 GFP_KERNEL_ACCOUNT); 485 if (!md) 486 return -ENOMEM; 487 488 memcpy(&md->u.tun_info, &info, sizeof(info)); 489#ifdef CONFIG_DST_CACHE 490 err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL_ACCOUNT); 491 if (err < 0) { 492 metadata_dst_free(md); 493 return err; 494 } 495#endif 496 ip_tunnel_info_opts_set(&md->u.tun_info, &priv->opts.u, priv->opts.len, 497 priv->opts.flags); 498 priv->md = md; 499 500 return 0; 501} 502 503static inline void nft_tunnel_obj_eval(struct nft_object *obj, 504 struct nft_regs *regs, 505 const struct nft_pktinfo *pkt) 506{ 507 struct nft_tunnel_obj *priv = nft_obj_data(obj); 508 struct sk_buff *skb = pkt->skb; 509 510 skb_dst_drop(skb); 511 dst_hold((struct dst_entry *) priv->md); 512 skb_dst_set(skb, (struct dst_entry *) priv->md); 513} 514 515static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info) 516{ 517 struct nlattr *nest; 518 519 if (info->mode & IP_TUNNEL_INFO_IPV6) { 520 nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_IP6); 521 if (!nest) 522 return -1; 523 524 if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, 525 &info->key.u.ipv6.src) < 0 || 526 nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, 527 &info->key.u.ipv6.dst) < 0 || 528 nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, 529 info->key.label)) { 530 nla_nest_cancel(skb, nest); 531 return -1; 532 } 533 534 nla_nest_end(skb, nest); 535 } else { 536 nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_IP); 537 if (!nest) 538 return -1; 539 540 if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, 541 info->key.u.ipv4.src) < 0 || 542 nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, 543 info->key.u.ipv4.dst) < 0) { 544 nla_nest_cancel(skb, nest); 545 return -1; 546 } 547 548 nla_nest_end(skb, nest); 549 } 550 551 return 0; 552} 553 554static int nft_tunnel_opts_dump(struct sk_buff *skb, 555 struct nft_tunnel_obj *priv) 556{ 557 struct nft_tunnel_opts *opts = &priv->opts; 558 struct nlattr *nest, *inner; 559 560 nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS); 561 if (!nest) 562 return -1; 563 564 if (test_bit(IP_TUNNEL_VXLAN_OPT_BIT, opts->flags)) { 565 inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_VXLAN); 566 if (!inner) 567 goto failure; 568 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP, 569 htonl(opts->u.vxlan.gbp))) 570 goto inner_failure; 571 nla_nest_end(skb, inner); 572 } else if (test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, opts->flags)) { 573 inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_ERSPAN); 574 if (!inner) 575 goto failure; 576 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_VERSION, 577 htonl(opts->u.erspan.version))) 578 goto inner_failure; 579 switch (opts->u.erspan.version) { 580 case ERSPAN_VERSION: 581 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX, 582 opts->u.erspan.u.index)) 583 goto inner_failure; 584 break; 585 case ERSPAN_VERSION2: 586 if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID, 587 get_hwid(&opts->u.erspan.u.md2)) || 588 nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR, 589 opts->u.erspan.u.md2.dir)) 590 goto inner_failure; 591 break; 592 } 593 nla_nest_end(skb, inner); 594 } else if (test_bit(IP_TUNNEL_GENEVE_OPT_BIT, opts->flags)) { 595 struct geneve_opt *opt; 596 int offset = 0; 597 598 while (opts->len > offset) { 599 inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_GENEVE); 600 if (!inner) 601 goto failure; 602 opt = (struct geneve_opt *)(opts->u.data + offset); 603 if (nla_put_be16(skb, NFTA_TUNNEL_KEY_GENEVE_CLASS, 604 opt->opt_class) || 605 nla_put_u8(skb, NFTA_TUNNEL_KEY_GENEVE_TYPE, 606 opt->type) || 607 nla_put(skb, NFTA_TUNNEL_KEY_GENEVE_DATA, 608 opt->length * 4, opt->opt_data)) 609 goto inner_failure; 610 offset += sizeof(*opt) + opt->length * 4; 611 nla_nest_end(skb, inner); 612 } 613 } 614 nla_nest_end(skb, nest); 615 return 0; 616 617inner_failure: 618 nla_nest_cancel(skb, inner); 619failure: 620 nla_nest_cancel(skb, nest); 621 return -1; 622} 623 624static int nft_tunnel_ports_dump(struct sk_buff *skb, 625 struct ip_tunnel_info *info) 626{ 627 if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, info->key.tp_src) < 0 || 628 nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, info->key.tp_dst) < 0) 629 return -1; 630 631 return 0; 632} 633 634static int nft_tunnel_flags_dump(struct sk_buff *skb, 635 struct ip_tunnel_info *info) 636{ 637 u32 flags = 0; 638 639 if (test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, info->key.tun_flags)) 640 flags |= NFT_TUNNEL_F_DONT_FRAGMENT; 641 if (!test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags)) 642 flags |= NFT_TUNNEL_F_ZERO_CSUM_TX; 643 if (test_bit(IP_TUNNEL_SEQ_BIT, info->key.tun_flags)) 644 flags |= NFT_TUNNEL_F_SEQ_NUMBER; 645 646 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_FLAGS, htonl(flags)) < 0) 647 return -1; 648 649 return 0; 650} 651 652static int nft_tunnel_obj_dump(struct sk_buff *skb, 653 struct nft_object *obj, bool reset) 654{ 655 struct nft_tunnel_obj *priv = nft_obj_data(obj); 656 struct ip_tunnel_info *info = &priv->md->u.tun_info; 657 658 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ID, 659 tunnel_id_to_key32(info->key.tun_id)) || 660 nft_tunnel_ip_dump(skb, info) < 0 || 661 nft_tunnel_ports_dump(skb, info) < 0 || 662 nft_tunnel_flags_dump(skb, info) < 0 || 663 nla_put_u8(skb, NFTA_TUNNEL_KEY_TOS, info->key.tos) || 664 nla_put_u8(skb, NFTA_TUNNEL_KEY_TTL, info->key.ttl) || 665 nft_tunnel_opts_dump(skb, priv) < 0) 666 goto nla_put_failure; 667 668 return 0; 669 670nla_put_failure: 671 return -1; 672} 673 674static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx, 675 struct nft_object *obj) 676{ 677 struct nft_tunnel_obj *priv = nft_obj_data(obj); 678 679 metadata_dst_free(priv->md); 680} 681 682static struct nft_object_type nft_tunnel_obj_type; 683static const struct nft_object_ops nft_tunnel_obj_ops = { 684 .type = &nft_tunnel_obj_type, 685 .size = sizeof(struct nft_tunnel_obj), 686 .eval = nft_tunnel_obj_eval, 687 .init = nft_tunnel_obj_init, 688 .destroy = nft_tunnel_obj_destroy, 689 .dump = nft_tunnel_obj_dump, 690}; 691 692static struct nft_object_type nft_tunnel_obj_type __read_mostly = { 693 .type = NFT_OBJECT_TUNNEL, 694 .family = NFPROTO_NETDEV, 695 .ops = &nft_tunnel_obj_ops, 696 .maxattr = NFTA_TUNNEL_KEY_MAX, 697 .policy = nft_tunnel_key_policy, 698 .owner = THIS_MODULE, 699}; 700 701static int __init nft_tunnel_module_init(void) 702{ 703 int err; 704 705 err = nft_register_expr(&nft_tunnel_type); 706 if (err < 0) 707 return err; 708 709 err = nft_register_obj(&nft_tunnel_obj_type); 710 if (err < 0) 711 nft_unregister_expr(&nft_tunnel_type); 712 713 return err; 714} 715 716static void __exit nft_tunnel_module_exit(void) 717{ 718 nft_unregister_obj(&nft_tunnel_obj_type); 719 nft_unregister_expr(&nft_tunnel_type); 720} 721 722module_init(nft_tunnel_module_init); 723module_exit(nft_tunnel_module_exit); 724 725MODULE_LICENSE("GPL"); 726MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 727MODULE_ALIAS_NFT_EXPR("tunnel"); 728MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL); 729MODULE_DESCRIPTION("nftables tunnel expression support");