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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter/IPVS updates for net-next:

1) Add .release_ops to properly unroll .select_ops, use it from nft_compat.
After this change, we can remove list of extensions too to simplify this
codebase.

2) Update amanda conntrack helper to support v3.4, from Florian Tham.

3) Get rid of the obsolete BUGPRINT macro in ebtables, from
Florian Westphal.

4) Merge IPv4 and IPv6 masquerading infrastructure into one single module.
From Florian Westphal.

5) Patchset to remove nf_nat_l3proto structure to get rid of
indirections, from Florian Westphal.

6) Skip unnecessary conntrack timeout updates in case the value is
still the same, also from Florian Westphal.

7) Remove unnecessary 'fall through' comments in empty switch cases,
from Li RongQing.

8) Fix lookup to fixed size hashtable sets on big endian with 32-bit keys.

9) Incorrect logic to deactivate path of fixed size hashtable sets,
element was being tested to self.

10) Remove nft_hash_key(), the bitmap set is always selected for 16-bit
keys.

11) Use boolean whenever possible in IPVS codebase, from Andrea Claudi.

12) Enter close state in conntrack if RST matches exact sequence number,
from Florian Westphal.

13) Initialize dst_cache in tunnel extension, from wenxu.

14) Pass protocol as u16 to xt_check_match and xt_check_target, from
Li RongQing.

15) SCTP header is granted to be in a linear area from IPVS NAT handler,
from Xin Long.

16) Don't steal packets coming from slave VRF device from the
ip_sabotage_in() path, from David Ahern.

17) Fix unsafe update of basechain stats, from Li RongQing.

18) Make sure CONNTRACK_LOCKS is power of 2 to let compiler optimize
modulo operation as bitwise AND, from Li RongQing.

19) Use device_attribute instead of internal definition in the IDLETIMER
target, from Sami Tolvanen.

20) Merge redir, masq and IPv4/IPv6 NAT chain types, from Florian Westphal.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+1747 -2419
+2 -2
include/linux/netfilter/x_tables.h
··· 289 289 290 290 int xt_check_proc_name(const char *name, unsigned int size); 291 291 292 - int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, 292 + int xt_check_match(struct xt_mtchk_param *, unsigned int size, u16 proto, 293 293 bool inv_proto); 294 - int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, 294 + int xt_check_target(struct xt_tgchk_param *, unsigned int size, u16 proto, 295 295 bool inv_proto); 296 296 297 297 int xt_match_to_user(const struct xt_entry_match *m,
+5 -5
include/net/netfilter/nf_conntrack.h
··· 190 190 191 191 void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 192 192 const struct sk_buff *skb, 193 - unsigned long extra_jiffies, int do_acct); 193 + u32 extra_jiffies, bool do_acct); 194 194 195 195 /* Refresh conntrack for this many jiffies and do accounting */ 196 196 static inline void nf_ct_refresh_acct(struct nf_conn *ct, 197 197 enum ip_conntrack_info ctinfo, 198 198 const struct sk_buff *skb, 199 - unsigned long extra_jiffies) 199 + u32 extra_jiffies) 200 200 { 201 - __nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1); 201 + __nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, true); 202 202 } 203 203 204 204 /* Refresh conntrack for this many jiffies */ 205 205 static inline void nf_ct_refresh(struct nf_conn *ct, 206 206 const struct sk_buff *skb, 207 - unsigned long extra_jiffies) 207 + u32 extra_jiffies) 208 208 { 209 - __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0); 209 + __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, false); 210 210 } 211 211 212 212 /* kill conntrack and do accounting */
+41 -4
include/net/netfilter/nf_nat.h
··· 31 31 /* The structure embedded in the conntrack structure. */ 32 32 struct nf_conn_nat { 33 33 union nf_conntrack_nat_help help; 34 - #if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \ 35 - IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6) 34 + #if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE) 36 35 int masq_index; 37 36 #endif 38 37 }; ··· 60 61 struct nf_conn_nat *nat, 61 62 const struct net_device *out) 62 63 { 63 - #if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \ 64 - IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6) 64 + #if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE) 65 65 return nat && nat->masq_index && hooknum == NF_INET_POST_ROUTING && 66 66 CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL && 67 67 nat->masq_index != out->ifindex; ··· 73 75 const struct nf_hook_ops *nat_ops, unsigned int ops_count); 74 76 void nf_nat_unregister_fn(struct net *net, const struct nf_hook_ops *ops, 75 77 unsigned int ops_count); 78 + 79 + unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 80 + unsigned int hooknum, struct sk_buff *skb); 81 + 82 + unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct, 83 + enum nf_nat_manip_type mtype, 84 + enum ip_conntrack_dir dir); 85 + void nf_nat_csum_recalc(struct sk_buff *skb, 86 + u8 nfproto, u8 proto, void *data, __sum16 *check, 87 + int datalen, int oldlen); 88 + 89 + int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct, 90 + enum ip_conntrack_info ctinfo, 91 + unsigned int hooknum); 92 + 93 + int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, 94 + enum ip_conntrack_info ctinfo, 95 + unsigned int hooknum, unsigned int hdrlen); 96 + 97 + int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops); 98 + void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops); 99 + 100 + int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops); 101 + void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops); 102 + 103 + unsigned int 104 + nf_nat_inet_fn(void *priv, struct sk_buff *skb, 105 + const struct nf_hook_state *state); 106 + 107 + int nf_xfrm_me_harder(struct net *n, struct sk_buff *s, unsigned int family); 108 + 109 + static inline int nf_nat_initialized(struct nf_conn *ct, 110 + enum nf_nat_manip_type manip) 111 + { 112 + if (manip == NF_NAT_MANIP_SRC) 113 + return ct->status & IPS_SRC_NAT_DONE; 114 + else 115 + return ct->status & IPS_DST_NAT_DONE; 116 + } 76 117 #endif
-29
include/net/netfilter/nf_nat_core.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _NF_NAT_CORE_H 3 - #define _NF_NAT_CORE_H 4 - #include <linux/list.h> 5 - #include <net/netfilter/nf_conntrack.h> 6 - #include <net/netfilter/nf_nat.h> 7 - 8 - /* This header used to share core functionality between the standalone 9 - NAT module, and the compatibility layer's use of NAT for masquerading. */ 10 - 11 - unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 12 - unsigned int hooknum, struct sk_buff *skb); 13 - 14 - unsigned int 15 - nf_nat_inet_fn(void *priv, struct sk_buff *skb, 16 - const struct nf_hook_state *state); 17 - 18 - int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family); 19 - 20 - static inline int nf_nat_initialized(struct nf_conn *ct, 21 - enum nf_nat_manip_type manip) 22 - { 23 - if (manip == NF_NAT_MANIP_SRC) 24 - return ct->status & IPS_SRC_NAT_DONE; 25 - else 26 - return ct->status & IPS_DST_NAT_DONE; 27 - } 28 - 29 - #endif /* _NF_NAT_CORE_H */
-50
include/net/netfilter/nf_nat_l3proto.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _NF_NAT_L3PROTO_H 3 - #define _NF_NAT_L3PROTO_H 4 - 5 - struct nf_nat_l3proto { 6 - u8 l3proto; 7 - 8 - bool (*manip_pkt)(struct sk_buff *skb, 9 - unsigned int iphdroff, 10 - const struct nf_conntrack_tuple *target, 11 - enum nf_nat_manip_type maniptype); 12 - 13 - void (*csum_update)(struct sk_buff *skb, unsigned int iphdroff, 14 - __sum16 *check, 15 - const struct nf_conntrack_tuple *t, 16 - enum nf_nat_manip_type maniptype); 17 - 18 - void (*csum_recalc)(struct sk_buff *skb, u8 proto, 19 - void *data, __sum16 *check, 20 - int datalen, int oldlen); 21 - 22 - void (*decode_session)(struct sk_buff *skb, 23 - const struct nf_conn *ct, 24 - enum ip_conntrack_dir dir, 25 - unsigned long statusbit, 26 - struct flowi *fl); 27 - 28 - int (*nlattr_to_range)(struct nlattr *tb[], 29 - struct nf_nat_range2 *range); 30 - }; 31 - 32 - int nf_nat_l3proto_register(const struct nf_nat_l3proto *); 33 - void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *); 34 - const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto); 35 - 36 - int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct, 37 - enum ip_conntrack_info ctinfo, 38 - unsigned int hooknum); 39 - 40 - int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, 41 - enum ip_conntrack_info ctinfo, 42 - unsigned int hooknum, unsigned int hdrlen); 43 - 44 - int nf_nat_l3proto_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops); 45 - void nf_nat_l3proto_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops); 46 - 47 - int nf_nat_l3proto_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops); 48 - void nf_nat_l3proto_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops); 49 - 50 - #endif /* _NF_NAT_L3PROTO_H */
-16
include/net/netfilter/nf_nat_l4proto.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* Header for use in defining a given protocol. */ 3 - #ifndef _NF_NAT_L4PROTO_H 4 - #define _NF_NAT_L4PROTO_H 5 - #include <net/netfilter/nf_nat.h> 6 - #include <linux/netfilter/nfnetlink_conntrack.h> 7 - 8 - struct nf_nat_l3proto; 9 - 10 - /* Translate a packet to the target according to manip type. Return on success. */ 11 - bool nf_nat_l4proto_manip_pkt(struct sk_buff *skb, 12 - const struct nf_nat_l3proto *l3proto, 13 - unsigned int iphdroff, unsigned int hdroff, 14 - const struct nf_conntrack_tuple *tuple, 15 - enum nf_nat_manip_type maniptype); 16 - #endif /*_NF_NAT_L4PROTO_H*/
+3
include/net/netfilter/nf_tables.h
··· 690 690 gcb->elems[gcb->head.cnt++] = elem; 691 691 } 692 692 693 + struct nft_expr_ops; 693 694 /** 694 695 * struct nft_expr_type - nf_tables expression type 695 696 * 696 697 * @select_ops: function to select nft_expr_ops 698 + * @release_ops: release nft_expr_ops 697 699 * @ops: default ops, used when no select_ops functions is present 698 700 * @list: used internally 699 701 * @name: Identifier ··· 708 706 struct nft_expr_type { 709 707 const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, 710 708 const struct nlattr * const tb[]); 709 + void (*release_ops)(const struct nft_expr_ops *ops); 711 710 const struct nft_expr_ops *ops; 712 711 struct list_head list; 713 712 const char *name;
-22
include/net/netfilter/nft_masq.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _NFT_MASQ_H_ 3 - #define _NFT_MASQ_H_ 4 - 5 - struct nft_masq { 6 - u32 flags; 7 - enum nft_registers sreg_proto_min:8; 8 - enum nft_registers sreg_proto_max:8; 9 - }; 10 - 11 - extern const struct nla_policy nft_masq_policy[]; 12 - 13 - int nft_masq_init(const struct nft_ctx *ctx, 14 - const struct nft_expr *expr, 15 - const struct nlattr * const tb[]); 16 - 17 - int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr); 18 - 19 - int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, 20 - const struct nft_data **data); 21 - 22 - #endif /* _NFT_MASQ_H_ */
-22
include/net/netfilter/nft_redir.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _NFT_REDIR_H_ 3 - #define _NFT_REDIR_H_ 4 - 5 - struct nft_redir { 6 - enum nft_registers sreg_proto_min:8; 7 - enum nft_registers sreg_proto_max:8; 8 - u16 flags; 9 - }; 10 - 11 - extern const struct nla_policy nft_redir_policy[]; 12 - 13 - int nft_redir_init(const struct nft_ctx *ctx, 14 - const struct nft_expr *expr, 15 - const struct nlattr * const tb[]); 16 - 17 - int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr); 18 - 19 - int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, 20 - const struct nft_data **data); 21 - 22 - #endif /* _NFT_REDIR_H_ */
+2 -1
net/bridge/br_netfilter_hooks.c
··· 831 831 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); 832 832 833 833 if (nf_bridge && !nf_bridge->in_prerouting && 834 - !netif_is_l3_master(skb->dev)) { 834 + !netif_is_l3_master(skb->dev) && 835 + !netif_is_l3_slave(skb->dev)) { 835 836 state->okfn(state->net, state->sk, skb); 836 837 return NF_STOLEN; 837 838 }
+42 -95
net/bridge/netfilter/ebtables.c
··· 31 31 /* needed for logical [in,out]-dev filtering */ 32 32 #include "../br_private.h" 33 33 34 - #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ 35 - "report to author: "format, ## args) 36 - /* #define BUGPRINT(format, args...) */ 37 - 38 34 /* Each cpu has its own set of counters, so there is no need for write_lock in 39 35 * the softirq 40 36 * For reading or updating the counters, the user context needs to ··· 381 385 par->match = match; 382 386 par->matchinfo = m->data; 383 387 ret = xt_check_match(par, m->match_size, 384 - e->ethproto, e->invflags & EBT_IPROTO); 388 + ntohs(e->ethproto), e->invflags & EBT_IPROTO); 385 389 if (ret < 0) { 386 390 module_put(match->me); 387 391 return ret; ··· 418 422 par->target = watcher; 419 423 par->targinfo = w->data; 420 424 ret = xt_check_target(par, w->watcher_size, 421 - e->ethproto, e->invflags & EBT_IPROTO); 425 + ntohs(e->ethproto), e->invflags & EBT_IPROTO); 422 426 if (ret < 0) { 423 427 module_put(watcher->me); 424 428 return ret; ··· 462 466 /* we make userspace set this right, 463 467 * so there is no misunderstanding 464 468 */ 465 - BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set " 466 - "in distinguisher\n"); 467 469 return -EINVAL; 468 470 } 469 471 if (i != NF_BR_NUMHOOKS) ··· 479 485 offset += e->next_offset; 480 486 } 481 487 } 482 - if (offset != limit) { 483 - BUGPRINT("entries_size too small\n"); 488 + if (offset != limit) 484 489 return -EINVAL; 485 - } 486 490 487 491 /* check if all valid hooks have a chain */ 488 492 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 489 493 if (!newinfo->hook_entry[i] && 490 - (valid_hooks & (1 << i))) { 491 - BUGPRINT("Valid hook without chain\n"); 494 + (valid_hooks & (1 << i))) 492 495 return -EINVAL; 493 - } 494 496 } 495 497 return 0; 496 498 } ··· 513 523 /* this checks if the previous chain has as many entries 514 524 * as it said it has 515 525 */ 516 - if (*n != *cnt) { 517 - BUGPRINT("nentries does not equal the nr of entries " 518 - "in the chain\n"); 526 + if (*n != *cnt) 519 527 return -EINVAL; 520 - } 528 + 521 529 if (((struct ebt_entries *)e)->policy != EBT_DROP && 522 530 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) { 523 531 /* only RETURN from udc */ 524 532 if (i != NF_BR_NUMHOOKS || 525 - ((struct ebt_entries *)e)->policy != EBT_RETURN) { 526 - BUGPRINT("bad policy\n"); 533 + ((struct ebt_entries *)e)->policy != EBT_RETURN) 527 534 return -EINVAL; 528 - } 529 535 } 530 536 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */ 531 537 (*udc_cnt)++; 532 - if (((struct ebt_entries *)e)->counter_offset != *totalcnt) { 533 - BUGPRINT("counter_offset != totalcnt"); 538 + if (((struct ebt_entries *)e)->counter_offset != *totalcnt) 534 539 return -EINVAL; 535 - } 536 540 *n = ((struct ebt_entries *)e)->nentries; 537 541 *cnt = 0; 538 542 return 0; ··· 534 550 /* a plain old entry, heh */ 535 551 if (sizeof(struct ebt_entry) > e->watchers_offset || 536 552 e->watchers_offset > e->target_offset || 537 - e->target_offset >= e->next_offset) { 538 - BUGPRINT("entry offsets not in right order\n"); 553 + e->target_offset >= e->next_offset) 539 554 return -EINVAL; 540 - } 555 + 541 556 /* this is not checked anywhere else */ 542 - if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) { 543 - BUGPRINT("target size too small\n"); 557 + if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) 544 558 return -EINVAL; 545 - } 559 + 546 560 (*cnt)++; 547 561 (*totalcnt)++; 548 562 return 0; ··· 660 678 if (e->bitmask == 0) 661 679 return 0; 662 680 663 - if (e->bitmask & ~EBT_F_MASK) { 664 - BUGPRINT("Unknown flag for bitmask\n"); 681 + if (e->bitmask & ~EBT_F_MASK) 665 682 return -EINVAL; 666 - } 667 - if (e->invflags & ~EBT_INV_MASK) { 668 - BUGPRINT("Unknown flag for inv bitmask\n"); 683 + 684 + if (e->invflags & ~EBT_INV_MASK) 669 685 return -EINVAL; 670 - } 671 - if ((e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3)) { 672 - BUGPRINT("NOPROTO & 802_3 not allowed\n"); 686 + 687 + if ((e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3)) 673 688 return -EINVAL; 674 - } 689 + 675 690 /* what hook do we belong to? */ 676 691 for (i = 0; i < NF_BR_NUMHOOKS; i++) { 677 692 if (!newinfo->hook_entry[i]) ··· 727 748 t->u.target = target; 728 749 if (t->u.target == &ebt_standard_target) { 729 750 if (gap < sizeof(struct ebt_standard_target)) { 730 - BUGPRINT("Standard target size too big\n"); 731 751 ret = -EFAULT; 732 752 goto cleanup_watchers; 733 753 } 734 754 if (((struct ebt_standard_target *)t)->verdict < 735 755 -NUM_STANDARD_TARGETS) { 736 - BUGPRINT("Invalid standard target\n"); 737 756 ret = -EFAULT; 738 757 goto cleanup_watchers; 739 758 } ··· 744 767 tgpar.target = target; 745 768 tgpar.targinfo = t->data; 746 769 ret = xt_check_target(&tgpar, t->target_size, 747 - e->ethproto, e->invflags & EBT_IPROTO); 770 + ntohs(e->ethproto), e->invflags & EBT_IPROTO); 748 771 if (ret < 0) { 749 772 module_put(target->me); 750 773 goto cleanup_watchers; ··· 790 813 if (strcmp(t->u.name, EBT_STANDARD_TARGET)) 791 814 goto letscontinue; 792 815 if (e->target_offset + sizeof(struct ebt_standard_target) > 793 - e->next_offset) { 794 - BUGPRINT("Standard target size too big\n"); 816 + e->next_offset) 795 817 return -1; 796 - } 818 + 797 819 verdict = ((struct ebt_standard_target *)t)->verdict; 798 820 if (verdict >= 0) { /* jump to another chain */ 799 821 struct ebt_entries *hlp2 = ··· 801 825 if (hlp2 == cl_s[i].cs.chaininfo) 802 826 break; 803 827 /* bad destination or loop */ 804 - if (i == udc_cnt) { 805 - BUGPRINT("bad destination\n"); 828 + if (i == udc_cnt) 806 829 return -1; 807 - } 808 - if (cl_s[i].cs.n) { 809 - BUGPRINT("loop\n"); 830 + 831 + if (cl_s[i].cs.n) 810 832 return -1; 811 - } 833 + 812 834 if (cl_s[i].hookmask & (1 << hooknr)) 813 835 goto letscontinue; 814 836 /* this can't be 0, so the loop test is correct */ ··· 839 865 i = 0; 840 866 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i]) 841 867 i++; 842 - if (i == NF_BR_NUMHOOKS) { 843 - BUGPRINT("No valid hooks specified\n"); 868 + if (i == NF_BR_NUMHOOKS) 844 869 return -EINVAL; 845 - } 846 - if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) { 847 - BUGPRINT("Chains don't start at beginning\n"); 870 + 871 + if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) 848 872 return -EINVAL; 849 - } 873 + 850 874 /* make sure chains are ordered after each other in same order 851 875 * as their corresponding hooks 852 876 */ 853 877 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) { 854 878 if (!newinfo->hook_entry[j]) 855 879 continue; 856 - if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) { 857 - BUGPRINT("Hook order must be followed\n"); 880 + if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) 858 881 return -EINVAL; 859 - } 882 + 860 883 i = j; 861 884 } 862 885 ··· 871 900 if (ret != 0) 872 901 return ret; 873 902 874 - if (i != j) { 875 - BUGPRINT("nentries does not equal the nr of entries in the " 876 - "(last) chain\n"); 903 + if (i != j) 877 904 return -EINVAL; 878 - } 879 - if (k != newinfo->nentries) { 880 - BUGPRINT("Total nentries is wrong\n"); 905 + 906 + if (k != newinfo->nentries) 881 907 return -EINVAL; 882 - } 883 908 884 909 /* get the location of the udc, put them in an array 885 910 * while we're at it, allocate the chainstack ··· 909 942 ebt_get_udc_positions, newinfo, &i, cl_s); 910 943 /* sanity check */ 911 944 if (i != udc_cnt) { 912 - BUGPRINT("i != udc_cnt\n"); 913 945 vfree(cl_s); 914 946 return -EFAULT; 915 947 } ··· 1008 1042 goto free_unlock; 1009 1043 1010 1044 if (repl->num_counters && repl->num_counters != t->private->nentries) { 1011 - BUGPRINT("Wrong nr. of counters requested\n"); 1012 1045 ret = -EINVAL; 1013 1046 goto free_unlock; 1014 1047 } ··· 1083 1118 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1084 1119 return -EFAULT; 1085 1120 1086 - if (len != sizeof(tmp) + tmp.entries_size) { 1087 - BUGPRINT("Wrong len argument\n"); 1121 + if (len != sizeof(tmp) + tmp.entries_size) 1088 1122 return -EINVAL; 1089 - } 1090 1123 1091 - if (tmp.entries_size == 0) { 1092 - BUGPRINT("Entries_size never zero\n"); 1124 + if (tmp.entries_size == 0) 1093 1125 return -EINVAL; 1094 - } 1126 + 1095 1127 /* overflow check */ 1096 1128 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / 1097 1129 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) ··· 1115 1153 } 1116 1154 if (copy_from_user( 1117 1155 newinfo->entries, tmp.entries, tmp.entries_size) != 0) { 1118 - BUGPRINT("Couldn't copy entries from userspace\n"); 1119 1156 ret = -EFAULT; 1120 1157 goto free_entries; 1121 1158 } ··· 1155 1194 1156 1195 if (input_table == NULL || (repl = input_table->table) == NULL || 1157 1196 repl->entries == NULL || repl->entries_size == 0 || 1158 - repl->counters != NULL || input_table->private != NULL) { 1159 - BUGPRINT("Bad table data for ebt_register_table!!!\n"); 1197 + repl->counters != NULL || input_table->private != NULL) 1160 1198 return -EINVAL; 1161 - } 1162 1199 1163 1200 /* Don't add one table to multiple lists. */ 1164 1201 table = kmemdup(input_table, sizeof(struct ebt_table), GFP_KERNEL); ··· 1194 1235 ((char *)repl->hook_entry[i] - repl->entries); 1195 1236 } 1196 1237 ret = translate_table(net, repl->name, newinfo); 1197 - if (ret != 0) { 1198 - BUGPRINT("Translate_table failed\n"); 1238 + if (ret != 0) 1199 1239 goto free_chainstack; 1200 - } 1201 1240 1202 1241 if (table->check && table->check(newinfo, table->valid_hooks)) { 1203 - BUGPRINT("The table doesn't like its own initial data, lol\n"); 1204 1242 ret = -EINVAL; 1205 1243 goto free_chainstack; 1206 1244 } ··· 1208 1252 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { 1209 1253 if (strcmp(t->name, table->name) == 0) { 1210 1254 ret = -EEXIST; 1211 - BUGPRINT("Table name already exists\n"); 1212 1255 goto free_unlock; 1213 1256 } 1214 1257 } ··· 1275 1320 goto free_tmp; 1276 1321 1277 1322 if (num_counters != t->private->nentries) { 1278 - BUGPRINT("Wrong nr of counters\n"); 1279 1323 ret = -EINVAL; 1280 1324 goto unlock_mutex; 1281 1325 } ··· 1401 1447 if (num_counters == 0) 1402 1448 return 0; 1403 1449 1404 - if (num_counters != nentries) { 1405 - BUGPRINT("Num_counters wrong\n"); 1450 + if (num_counters != nentries) 1406 1451 return -EINVAL; 1407 - } 1408 1452 1409 1453 counterstmp = vmalloc(array_size(nentries, sizeof(*counterstmp))); 1410 1454 if (!counterstmp) ··· 1448 1496 (tmp.num_counters ? nentries * sizeof(struct ebt_counter) : 0)) 1449 1497 return -EINVAL; 1450 1498 1451 - if (tmp.nentries != nentries) { 1452 - BUGPRINT("Nentries wrong\n"); 1499 + if (tmp.nentries != nentries) 1453 1500 return -EINVAL; 1454 - } 1455 1501 1456 - if (tmp.entries_size != entries_size) { 1457 - BUGPRINT("Wrong size\n"); 1502 + if (tmp.entries_size != entries_size) 1458 1503 return -EINVAL; 1459 - } 1460 1504 1461 1505 ret = copy_counters_to_user(t, oldcounters, tmp.counters, 1462 1506 tmp.num_counters, nentries); ··· 1524 1576 } 1525 1577 mutex_unlock(&ebt_mutex); 1526 1578 if (copy_to_user(user, &tmp, *len) != 0) { 1527 - BUGPRINT("c2u Didn't work\n"); 1528 1579 ret = -EFAULT; 1529 1580 break; 1530 1581 }
+3 -47
net/ipv4/netfilter/Kconfig
··· 94 94 tristate "IPv4 packet rejection" 95 95 default m if NETFILTER_ADVANCED=n 96 96 97 - config NF_NAT_IPV4 98 - tristate "IPv4 NAT" 99 - depends on NF_CONNTRACK 100 - default m if NETFILTER_ADVANCED=n 101 - select NF_NAT 102 - help 103 - The IPv4 NAT option allows masquerading, port forwarding and other 104 - forms of full Network Address Port Translation. This can be 105 - controlled by iptables or nft. 106 - 107 - if NF_NAT_IPV4 108 - 109 - config NF_NAT_MASQUERADE_IPV4 110 - bool 111 - 112 - if NF_TABLES 113 - config NFT_CHAIN_NAT_IPV4 114 - depends on NF_TABLES_IPV4 115 - tristate "IPv4 nf_tables nat chain support" 116 - help 117 - This option enables the "nat" chain for IPv4 in nf_tables. This 118 - chain type is used to perform Network Address Translation (NAT) 119 - packet transformations such as the source, destination address and 120 - source and destination ports. 121 - 122 - config NFT_MASQ_IPV4 123 - tristate "IPv4 masquerading support for nf_tables" 124 - depends on NF_TABLES_IPV4 125 - depends on NFT_MASQ 126 - select NF_NAT_MASQUERADE_IPV4 127 - help 128 - This is the expression that provides IPv4 masquerading support for 129 - nf_tables. 130 - 131 - config NFT_REDIR_IPV4 132 - tristate "IPv4 redirect support for nf_tables" 133 - depends on NF_TABLES_IPV4 134 - depends on NFT_REDIR 135 - select NF_NAT_REDIRECT 136 - help 137 - This is the expression that provides IPv4 redirect support for 138 - nf_tables. 139 - endif # NF_TABLES 140 - 97 + if NF_NAT 141 98 config NF_NAT_SNMP_BASIC 142 99 tristate "Basic SNMP-ALG support" 143 100 depends on NF_CONNTRACK_SNMP ··· 123 166 depends on NF_CONNTRACK 124 167 default NF_CONNTRACK_H323 125 168 126 - endif # NF_NAT_IPV4 169 + endif # NF_NAT 127 170 128 171 config IP_NF_IPTABLES 129 172 tristate "IP tables support (required for filtering/masq/NAT)" ··· 220 263 depends on NF_CONNTRACK 221 264 default m if NETFILTER_ADVANCED=n 222 265 select NF_NAT 223 - select NF_NAT_IPV4 224 266 select NETFILTER_XT_NAT 225 267 help 226 268 This enables the `nat' table in iptables. This allows masquerading, ··· 232 276 233 277 config IP_NF_TARGET_MASQUERADE 234 278 tristate "MASQUERADE target support" 235 - select NF_NAT_MASQUERADE_IPV4 279 + select NF_NAT_MASQUERADE 236 280 default m if NETFILTER_ADVANCED=n 237 281 help 238 282 Masquerading is a special case of NAT: all outgoing connections are
-7
net/ipv4/netfilter/Makefile
··· 3 3 # Makefile for the netfilter modules on top of IPv4. 4 4 # 5 5 6 - nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o 7 - nf_nat_ipv4-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o 8 - obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o 9 - 10 6 # defrag 11 7 obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o 12 8 ··· 25 29 obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o 26 30 27 31 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o 28 - obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o 29 32 obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o 30 33 obj-$(CONFIG_NFT_FIB_IPV4) += nft_fib_ipv4.o 31 - obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o 32 - obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redir_ipv4.o 33 34 obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o 34 35 35 36 # flow table support
+3 -5
net/ipv4/netfilter/iptable_nat.c
··· 15 15 #include <net/ip.h> 16 16 17 17 #include <net/netfilter/nf_nat.h> 18 - #include <net/netfilter/nf_nat_core.h> 19 - #include <net/netfilter/nf_nat_l3proto.h> 20 18 21 19 static int __net_init iptable_nat_table_init(struct net *net); 22 20 ··· 68 70 int i, ret; 69 71 70 72 for (i = 0; i < ARRAY_SIZE(nf_nat_ipv4_ops); i++) { 71 - ret = nf_nat_l3proto_ipv4_register_fn(net, &nf_nat_ipv4_ops[i]); 73 + ret = nf_nat_ipv4_register_fn(net, &nf_nat_ipv4_ops[i]); 72 74 if (ret) { 73 75 while (i) 74 - nf_nat_l3proto_ipv4_unregister_fn(net, &nf_nat_ipv4_ops[--i]); 76 + nf_nat_ipv4_unregister_fn(net, &nf_nat_ipv4_ops[--i]); 75 77 76 78 return ret; 77 79 } ··· 85 87 int i; 86 88 87 89 for (i = 0; i < ARRAY_SIZE(nf_nat_ipv4_ops); i++) 88 - nf_nat_l3proto_ipv4_unregister_fn(net, &nf_nat_ipv4_ops[i]); 90 + nf_nat_ipv4_unregister_fn(net, &nf_nat_ipv4_ops[i]); 89 91 } 90 92 91 93 static int __net_init iptable_nat_table_init(struct net *net)
-388
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
··· 1 - /* 2 - * (C) 1999-2001 Paul `Rusty' Russell 3 - * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 4 - * (C) 2011 Patrick McHardy <kaber@trash.net> 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - */ 10 - 11 - #include <linux/types.h> 12 - #include <linux/module.h> 13 - #include <linux/skbuff.h> 14 - #include <linux/ip.h> 15 - #include <linux/icmp.h> 16 - #include <linux/netfilter.h> 17 - #include <linux/netfilter_ipv4.h> 18 - #include <net/secure_seq.h> 19 - #include <net/checksum.h> 20 - #include <net/route.h> 21 - #include <net/ip.h> 22 - 23 - #include <net/netfilter/nf_conntrack_core.h> 24 - #include <net/netfilter/nf_conntrack.h> 25 - #include <net/netfilter/nf_nat_core.h> 26 - #include <net/netfilter/nf_nat_l3proto.h> 27 - #include <net/netfilter/nf_nat_l4proto.h> 28 - 29 - static const struct nf_nat_l3proto nf_nat_l3proto_ipv4; 30 - 31 - #ifdef CONFIG_XFRM 32 - static void nf_nat_ipv4_decode_session(struct sk_buff *skb, 33 - const struct nf_conn *ct, 34 - enum ip_conntrack_dir dir, 35 - unsigned long statusbit, 36 - struct flowi *fl) 37 - { 38 - const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; 39 - struct flowi4 *fl4 = &fl->u.ip4; 40 - 41 - if (ct->status & statusbit) { 42 - fl4->daddr = t->dst.u3.ip; 43 - if (t->dst.protonum == IPPROTO_TCP || 44 - t->dst.protonum == IPPROTO_UDP || 45 - t->dst.protonum == IPPROTO_UDPLITE || 46 - t->dst.protonum == IPPROTO_DCCP || 47 - t->dst.protonum == IPPROTO_SCTP) 48 - fl4->fl4_dport = t->dst.u.all; 49 - } 50 - 51 - statusbit ^= IPS_NAT_MASK; 52 - 53 - if (ct->status & statusbit) { 54 - fl4->saddr = t->src.u3.ip; 55 - if (t->dst.protonum == IPPROTO_TCP || 56 - t->dst.protonum == IPPROTO_UDP || 57 - t->dst.protonum == IPPROTO_UDPLITE || 58 - t->dst.protonum == IPPROTO_DCCP || 59 - t->dst.protonum == IPPROTO_SCTP) 60 - fl4->fl4_sport = t->src.u.all; 61 - } 62 - } 63 - #endif /* CONFIG_XFRM */ 64 - 65 - static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, 66 - unsigned int iphdroff, 67 - const struct nf_conntrack_tuple *target, 68 - enum nf_nat_manip_type maniptype) 69 - { 70 - struct iphdr *iph; 71 - unsigned int hdroff; 72 - 73 - if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) 74 - return false; 75 - 76 - iph = (void *)skb->data + iphdroff; 77 - hdroff = iphdroff + iph->ihl * 4; 78 - 79 - if (!nf_nat_l4proto_manip_pkt(skb, &nf_nat_l3proto_ipv4, iphdroff, 80 - hdroff, target, maniptype)) 81 - return false; 82 - iph = (void *)skb->data + iphdroff; 83 - 84 - if (maniptype == NF_NAT_MANIP_SRC) { 85 - csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); 86 - iph->saddr = target->src.u3.ip; 87 - } else { 88 - csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); 89 - iph->daddr = target->dst.u3.ip; 90 - } 91 - return true; 92 - } 93 - 94 - static void nf_nat_ipv4_csum_update(struct sk_buff *skb, 95 - unsigned int iphdroff, __sum16 *check, 96 - const struct nf_conntrack_tuple *t, 97 - enum nf_nat_manip_type maniptype) 98 - { 99 - struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); 100 - __be32 oldip, newip; 101 - 102 - if (maniptype == NF_NAT_MANIP_SRC) { 103 - oldip = iph->saddr; 104 - newip = t->src.u3.ip; 105 - } else { 106 - oldip = iph->daddr; 107 - newip = t->dst.u3.ip; 108 - } 109 - inet_proto_csum_replace4(check, skb, oldip, newip, true); 110 - } 111 - 112 - static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, 113 - u8 proto, void *data, __sum16 *check, 114 - int datalen, int oldlen) 115 - { 116 - if (skb->ip_summed != CHECKSUM_PARTIAL) { 117 - const struct iphdr *iph = ip_hdr(skb); 118 - 119 - skb->ip_summed = CHECKSUM_PARTIAL; 120 - skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 121 - ip_hdrlen(skb); 122 - skb->csum_offset = (void *)check - data; 123 - *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, 124 - proto, 0); 125 - } else 126 - inet_proto_csum_replace2(check, skb, 127 - htons(oldlen), htons(datalen), true); 128 - } 129 - 130 - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 131 - static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], 132 - struct nf_nat_range2 *range) 133 - { 134 - if (tb[CTA_NAT_V4_MINIP]) { 135 - range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]); 136 - range->flags |= NF_NAT_RANGE_MAP_IPS; 137 - } 138 - 139 - if (tb[CTA_NAT_V4_MAXIP]) 140 - range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]); 141 - else 142 - range->max_addr.ip = range->min_addr.ip; 143 - 144 - return 0; 145 - } 146 - #endif 147 - 148 - static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { 149 - .l3proto = NFPROTO_IPV4, 150 - .manip_pkt = nf_nat_ipv4_manip_pkt, 151 - .csum_update = nf_nat_ipv4_csum_update, 152 - .csum_recalc = nf_nat_ipv4_csum_recalc, 153 - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 154 - .nlattr_to_range = nf_nat_ipv4_nlattr_to_range, 155 - #endif 156 - #ifdef CONFIG_XFRM 157 - .decode_session = nf_nat_ipv4_decode_session, 158 - #endif 159 - }; 160 - 161 - int nf_nat_icmp_reply_translation(struct sk_buff *skb, 162 - struct nf_conn *ct, 163 - enum ip_conntrack_info ctinfo, 164 - unsigned int hooknum) 165 - { 166 - struct { 167 - struct icmphdr icmp; 168 - struct iphdr ip; 169 - } *inside; 170 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 171 - enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 172 - unsigned int hdrlen = ip_hdrlen(skb); 173 - struct nf_conntrack_tuple target; 174 - unsigned long statusbit; 175 - 176 - WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 177 - 178 - if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 179 - return 0; 180 - if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) 181 - return 0; 182 - 183 - inside = (void *)skb->data + hdrlen; 184 - if (inside->icmp.type == ICMP_REDIRECT) { 185 - if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 186 - return 0; 187 - if (ct->status & IPS_NAT_MASK) 188 - return 0; 189 - } 190 - 191 - if (manip == NF_NAT_MANIP_SRC) 192 - statusbit = IPS_SRC_NAT; 193 - else 194 - statusbit = IPS_DST_NAT; 195 - 196 - /* Invert if this is reply direction */ 197 - if (dir == IP_CT_DIR_REPLY) 198 - statusbit ^= IPS_NAT_MASK; 199 - 200 - if (!(ct->status & statusbit)) 201 - return 1; 202 - 203 - if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp), 204 - &ct->tuplehash[!dir].tuple, !manip)) 205 - return 0; 206 - 207 - if (skb->ip_summed != CHECKSUM_PARTIAL) { 208 - /* Reloading "inside" here since manip_pkt may reallocate */ 209 - inside = (void *)skb->data + hdrlen; 210 - inside->icmp.checksum = 0; 211 - inside->icmp.checksum = 212 - csum_fold(skb_checksum(skb, hdrlen, 213 - skb->len - hdrlen, 0)); 214 - } 215 - 216 - /* Change outer to look like the reply to an incoming packet */ 217 - nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 218 - target.dst.protonum = IPPROTO_ICMP; 219 - if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip)) 220 - return 0; 221 - 222 - return 1; 223 - } 224 - EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); 225 - 226 - static unsigned int 227 - nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, 228 - const struct nf_hook_state *state) 229 - { 230 - struct nf_conn *ct; 231 - enum ip_conntrack_info ctinfo; 232 - 233 - ct = nf_ct_get(skb, &ctinfo); 234 - if (!ct) 235 - return NF_ACCEPT; 236 - 237 - if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 238 - if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { 239 - if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 240 - state->hook)) 241 - return NF_DROP; 242 - else 243 - return NF_ACCEPT; 244 - } 245 - } 246 - 247 - return nf_nat_inet_fn(priv, skb, state); 248 - } 249 - 250 - static unsigned int 251 - nf_nat_ipv4_in(void *priv, struct sk_buff *skb, 252 - const struct nf_hook_state *state) 253 - { 254 - unsigned int ret; 255 - __be32 daddr = ip_hdr(skb)->daddr; 256 - 257 - ret = nf_nat_ipv4_fn(priv, skb, state); 258 - if (ret != NF_DROP && ret != NF_STOLEN && 259 - daddr != ip_hdr(skb)->daddr) 260 - skb_dst_drop(skb); 261 - 262 - return ret; 263 - } 264 - 265 - static unsigned int 266 - nf_nat_ipv4_out(void *priv, struct sk_buff *skb, 267 - const struct nf_hook_state *state) 268 - { 269 - #ifdef CONFIG_XFRM 270 - const struct nf_conn *ct; 271 - enum ip_conntrack_info ctinfo; 272 - int err; 273 - #endif 274 - unsigned int ret; 275 - 276 - ret = nf_nat_ipv4_fn(priv, skb, state); 277 - #ifdef CONFIG_XFRM 278 - if (ret != NF_DROP && ret != NF_STOLEN && 279 - !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 280 - (ct = nf_ct_get(skb, &ctinfo)) != NULL) { 281 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 282 - 283 - if ((ct->tuplehash[dir].tuple.src.u3.ip != 284 - ct->tuplehash[!dir].tuple.dst.u3.ip) || 285 - (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 286 - ct->tuplehash[dir].tuple.src.u.all != 287 - ct->tuplehash[!dir].tuple.dst.u.all)) { 288 - err = nf_xfrm_me_harder(state->net, skb, AF_INET); 289 - if (err < 0) 290 - ret = NF_DROP_ERR(err); 291 - } 292 - } 293 - #endif 294 - return ret; 295 - } 296 - 297 - static unsigned int 298 - nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, 299 - const struct nf_hook_state *state) 300 - { 301 - const struct nf_conn *ct; 302 - enum ip_conntrack_info ctinfo; 303 - unsigned int ret; 304 - int err; 305 - 306 - ret = nf_nat_ipv4_fn(priv, skb, state); 307 - if (ret != NF_DROP && ret != NF_STOLEN && 308 - (ct = nf_ct_get(skb, &ctinfo)) != NULL) { 309 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 310 - 311 - if (ct->tuplehash[dir].tuple.dst.u3.ip != 312 - ct->tuplehash[!dir].tuple.src.u3.ip) { 313 - err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); 314 - if (err < 0) 315 - ret = NF_DROP_ERR(err); 316 - } 317 - #ifdef CONFIG_XFRM 318 - else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 319 - ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 320 - ct->tuplehash[dir].tuple.dst.u.all != 321 - ct->tuplehash[!dir].tuple.src.u.all) { 322 - err = nf_xfrm_me_harder(state->net, skb, AF_INET); 323 - if (err < 0) 324 - ret = NF_DROP_ERR(err); 325 - } 326 - #endif 327 - } 328 - return ret; 329 - } 330 - 331 - static const struct nf_hook_ops nf_nat_ipv4_ops[] = { 332 - /* Before packet filtering, change destination */ 333 - { 334 - .hook = nf_nat_ipv4_in, 335 - .pf = NFPROTO_IPV4, 336 - .hooknum = NF_INET_PRE_ROUTING, 337 - .priority = NF_IP_PRI_NAT_DST, 338 - }, 339 - /* After packet filtering, change source */ 340 - { 341 - .hook = nf_nat_ipv4_out, 342 - .pf = NFPROTO_IPV4, 343 - .hooknum = NF_INET_POST_ROUTING, 344 - .priority = NF_IP_PRI_NAT_SRC, 345 - }, 346 - /* Before packet filtering, change destination */ 347 - { 348 - .hook = nf_nat_ipv4_local_fn, 349 - .pf = NFPROTO_IPV4, 350 - .hooknum = NF_INET_LOCAL_OUT, 351 - .priority = NF_IP_PRI_NAT_DST, 352 - }, 353 - /* After packet filtering, change source */ 354 - { 355 - .hook = nf_nat_ipv4_fn, 356 - .pf = NFPROTO_IPV4, 357 - .hooknum = NF_INET_LOCAL_IN, 358 - .priority = NF_IP_PRI_NAT_SRC, 359 - }, 360 - }; 361 - 362 - int nf_nat_l3proto_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops) 363 - { 364 - return nf_nat_register_fn(net, ops, nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 365 - } 366 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_ipv4_register_fn); 367 - 368 - void nf_nat_l3proto_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 369 - { 370 - nf_nat_unregister_fn(net, ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 371 - } 372 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_ipv4_unregister_fn); 373 - 374 - static int __init nf_nat_l3proto_ipv4_init(void) 375 - { 376 - return nf_nat_l3proto_register(&nf_nat_l3proto_ipv4); 377 - } 378 - 379 - static void __exit nf_nat_l3proto_ipv4_exit(void) 380 - { 381 - nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv4); 382 - } 383 - 384 - MODULE_LICENSE("GPL"); 385 - MODULE_ALIAS("nf-nat-" __stringify(AF_INET)); 386 - 387 - module_init(nf_nat_l3proto_ipv4_init); 388 - module_exit(nf_nat_l3proto_ipv4_exit);
+187 -21
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c net/netfilter/nf_nat_masquerade.c
··· 1 - /* (C) 1999-2001 Paul `Rusty' Russell 2 - * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 1 + // SPDX-License-Identifier: GPL-2.0 8 2 9 3 #include <linux/types.h> 10 4 #include <linux/atomic.h> 11 5 #include <linux/inetdevice.h> 12 - #include <linux/ip.h> 13 - #include <linux/timer.h> 14 6 #include <linux/netfilter.h> 15 - #include <net/protocol.h> 16 - #include <net/ip.h> 17 - #include <net/checksum.h> 18 - #include <net/route.h> 19 7 #include <linux/netfilter_ipv4.h> 20 - #include <linux/netfilter/x_tables.h> 21 - #include <net/netfilter/nf_nat.h> 8 + #include <linux/netfilter_ipv6.h> 9 + 22 10 #include <net/netfilter/ipv4/nf_nat_masquerade.h> 11 + #include <net/netfilter/ipv6/nf_nat_masquerade.h> 12 + 13 + static DEFINE_MUTEX(masq_mutex); 14 + static unsigned int masq_refcnt __read_mostly; 23 15 24 16 unsigned int 25 17 nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, ··· 70 78 71 79 if (!nat) 72 80 return 0; 73 - if (nf_ct_l3num(i) != NFPROTO_IPV4) 74 - return 0; 75 81 return nat->masq_index == (int)(long)ifindex; 76 82 } 77 83 ··· 85 95 * conntracks which were associated with that device, 86 96 * and forget them. 87 97 */ 88 - WARN_ON(dev->ifindex == 0); 89 98 90 99 nf_ct_iterate_cleanup_net(net, device_cmp, 91 100 (void *)(long)dev->ifindex, 0, 0); ··· 136 147 .notifier_call = masq_inet_event, 137 148 }; 138 149 139 - static int masq_refcnt; 140 - static DEFINE_MUTEX(masq_mutex); 141 - 142 150 int nf_nat_masquerade_ipv4_register_notifier(void) 143 151 { 144 152 int ret = 0; ··· 180 194 mutex_unlock(&masq_mutex); 181 195 } 182 196 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_unregister_notifier); 197 + 198 + #if IS_ENABLED(CONFIG_IPV6) 199 + static atomic_t v6_worker_count __read_mostly; 200 + 201 + static int 202 + nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev, 203 + const struct in6_addr *daddr, unsigned int srcprefs, 204 + struct in6_addr *saddr) 205 + { 206 + #ifdef CONFIG_IPV6_MODULE 207 + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); 208 + 209 + if (!v6_ops) 210 + return -EHOSTUNREACH; 211 + 212 + return v6_ops->dev_get_saddr(net, dev, daddr, srcprefs, saddr); 213 + #else 214 + return ipv6_dev_get_saddr(net, dev, daddr, srcprefs, saddr); 215 + #endif 216 + } 217 + 218 + unsigned int 219 + nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, 220 + const struct net_device *out) 221 + { 222 + enum ip_conntrack_info ctinfo; 223 + struct nf_conn_nat *nat; 224 + struct in6_addr src; 225 + struct nf_conn *ct; 226 + struct nf_nat_range2 newrange; 227 + 228 + ct = nf_ct_get(skb, &ctinfo); 229 + WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 230 + ctinfo == IP_CT_RELATED_REPLY))); 231 + 232 + if (nat_ipv6_dev_get_saddr(nf_ct_net(ct), out, 233 + &ipv6_hdr(skb)->daddr, 0, &src) < 0) 234 + return NF_DROP; 235 + 236 + nat = nf_ct_nat_ext_add(ct); 237 + if (nat) 238 + nat->masq_index = out->ifindex; 239 + 240 + newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; 241 + newrange.min_addr.in6 = src; 242 + newrange.max_addr.in6 = src; 243 + newrange.min_proto = range->min_proto; 244 + newrange.max_proto = range->max_proto; 245 + 246 + return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); 247 + } 248 + EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6); 249 + 250 + struct masq_dev_work { 251 + struct work_struct work; 252 + struct net *net; 253 + struct in6_addr addr; 254 + int ifindex; 255 + }; 256 + 257 + static int inet6_cmp(struct nf_conn *ct, void *work) 258 + { 259 + struct masq_dev_work *w = (struct masq_dev_work *)work; 260 + struct nf_conntrack_tuple *tuple; 261 + 262 + if (!device_cmp(ct, (void *)(long)w->ifindex)) 263 + return 0; 264 + 265 + tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; 266 + 267 + return ipv6_addr_equal(&w->addr, &tuple->dst.u3.in6); 268 + } 269 + 270 + static void iterate_cleanup_work(struct work_struct *work) 271 + { 272 + struct masq_dev_work *w; 273 + 274 + w = container_of(work, struct masq_dev_work, work); 275 + 276 + nf_ct_iterate_cleanup_net(w->net, inet6_cmp, (void *)w, 0, 0); 277 + 278 + put_net(w->net); 279 + kfree(w); 280 + atomic_dec(&v6_worker_count); 281 + module_put(THIS_MODULE); 282 + } 283 + 284 + /* atomic notifier; can't call nf_ct_iterate_cleanup_net (it can sleep). 285 + * 286 + * Defer it to the system workqueue. 287 + * 288 + * As we can have 'a lot' of inet_events (depending on amount of ipv6 289 + * addresses being deleted), we also need to limit work item queue. 290 + */ 291 + static int masq_inet6_event(struct notifier_block *this, 292 + unsigned long event, void *ptr) 293 + { 294 + struct inet6_ifaddr *ifa = ptr; 295 + const struct net_device *dev; 296 + struct masq_dev_work *w; 297 + struct net *net; 298 + 299 + if (event != NETDEV_DOWN || atomic_read(&v6_worker_count) >= 16) 300 + return NOTIFY_DONE; 301 + 302 + dev = ifa->idev->dev; 303 + net = maybe_get_net(dev_net(dev)); 304 + if (!net) 305 + return NOTIFY_DONE; 306 + 307 + if (!try_module_get(THIS_MODULE)) 308 + goto err_module; 309 + 310 + w = kmalloc(sizeof(*w), GFP_ATOMIC); 311 + if (w) { 312 + atomic_inc(&v6_worker_count); 313 + 314 + INIT_WORK(&w->work, iterate_cleanup_work); 315 + w->ifindex = dev->ifindex; 316 + w->net = net; 317 + w->addr = ifa->addr; 318 + schedule_work(&w->work); 319 + 320 + return NOTIFY_DONE; 321 + } 322 + 323 + module_put(THIS_MODULE); 324 + err_module: 325 + put_net(net); 326 + return NOTIFY_DONE; 327 + } 328 + 329 + static struct notifier_block masq_inet6_notifier = { 330 + .notifier_call = masq_inet6_event, 331 + }; 332 + 333 + int nf_nat_masquerade_ipv6_register_notifier(void) 334 + { 335 + int ret = 0; 336 + 337 + mutex_lock(&masq_mutex); 338 + /* check if the notifier is already set */ 339 + if (++masq_refcnt > 1) 340 + goto out_unlock; 341 + 342 + ret = register_netdevice_notifier(&masq_dev_notifier); 343 + if (ret) 344 + goto err_dec; 345 + 346 + ret = register_inet6addr_notifier(&masq_inet6_notifier); 347 + if (ret) 348 + goto err_unregister; 349 + 350 + mutex_unlock(&masq_mutex); 351 + return ret; 352 + 353 + err_unregister: 354 + unregister_netdevice_notifier(&masq_dev_notifier); 355 + err_dec: 356 + masq_refcnt--; 357 + out_unlock: 358 + mutex_unlock(&masq_mutex); 359 + return ret; 360 + } 361 + EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier); 362 + 363 + void nf_nat_masquerade_ipv6_unregister_notifier(void) 364 + { 365 + mutex_lock(&masq_mutex); 366 + /* check if the notifier still has clients */ 367 + if (--masq_refcnt > 0) 368 + goto out_unlock; 369 + 370 + unregister_inet6addr_notifier(&masq_inet6_notifier); 371 + unregister_netdevice_notifier(&masq_dev_notifier); 372 + out_unlock: 373 + mutex_unlock(&masq_mutex); 374 + } 375 + EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier); 376 + #endif
-87
net/ipv4/netfilter/nft_chain_nat_ipv4.c
··· 1 - /* 2 - * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 3 - * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org> 4 - * Copyright (c) 2012 Intel Corporation 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - * 10 - * Development of this code funded by Astaro AG (http://www.astaro.com/) 11 - */ 12 - 13 - #include <linux/module.h> 14 - #include <linux/init.h> 15 - #include <linux/list.h> 16 - #include <linux/skbuff.h> 17 - #include <linux/ip.h> 18 - #include <linux/netfilter.h> 19 - #include <linux/netfilter_ipv4.h> 20 - #include <linux/netfilter/nf_tables.h> 21 - #include <net/netfilter/nf_conntrack.h> 22 - #include <net/netfilter/nf_nat.h> 23 - #include <net/netfilter/nf_nat_core.h> 24 - #include <net/netfilter/nf_tables.h> 25 - #include <net/netfilter/nf_tables_ipv4.h> 26 - #include <net/netfilter/nf_nat_l3proto.h> 27 - #include <net/ip.h> 28 - 29 - static unsigned int nft_nat_do_chain(void *priv, 30 - struct sk_buff *skb, 31 - const struct nf_hook_state *state) 32 - { 33 - struct nft_pktinfo pkt; 34 - 35 - nft_set_pktinfo(&pkt, skb, state); 36 - nft_set_pktinfo_ipv4(&pkt, skb); 37 - 38 - return nft_do_chain(&pkt, priv); 39 - } 40 - 41 - static int nft_nat_ipv4_reg(struct net *net, const struct nf_hook_ops *ops) 42 - { 43 - return nf_nat_l3proto_ipv4_register_fn(net, ops); 44 - } 45 - 46 - static void nft_nat_ipv4_unreg(struct net *net, const struct nf_hook_ops *ops) 47 - { 48 - nf_nat_l3proto_ipv4_unregister_fn(net, ops); 49 - } 50 - 51 - static const struct nft_chain_type nft_chain_nat_ipv4 = { 52 - .name = "nat", 53 - .type = NFT_CHAIN_T_NAT, 54 - .family = NFPROTO_IPV4, 55 - .owner = THIS_MODULE, 56 - .hook_mask = (1 << NF_INET_PRE_ROUTING) | 57 - (1 << NF_INET_POST_ROUTING) | 58 - (1 << NF_INET_LOCAL_OUT) | 59 - (1 << NF_INET_LOCAL_IN), 60 - .hooks = { 61 - [NF_INET_PRE_ROUTING] = nft_nat_do_chain, 62 - [NF_INET_POST_ROUTING] = nft_nat_do_chain, 63 - [NF_INET_LOCAL_OUT] = nft_nat_do_chain, 64 - [NF_INET_LOCAL_IN] = nft_nat_do_chain, 65 - }, 66 - .ops_register = nft_nat_ipv4_reg, 67 - .ops_unregister = nft_nat_ipv4_unreg, 68 - }; 69 - 70 - static int __init nft_chain_nat_init(void) 71 - { 72 - nft_register_chain_type(&nft_chain_nat_ipv4); 73 - 74 - return 0; 75 - } 76 - 77 - static void __exit nft_chain_nat_exit(void) 78 - { 79 - nft_unregister_chain_type(&nft_chain_nat_ipv4); 80 - } 81 - 82 - module_init(nft_chain_nat_init); 83 - module_exit(nft_chain_nat_exit); 84 - 85 - MODULE_LICENSE("GPL"); 86 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 87 - MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat");
-90
net/ipv4/netfilter/nft_masq_ipv4.c
··· 1 - /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - 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.h> 16 - #include <net/netfilter/nft_masq.h> 17 - #include <net/netfilter/ipv4/nf_nat_masquerade.h> 18 - 19 - static void nft_masq_ipv4_eval(const struct nft_expr *expr, 20 - struct nft_regs *regs, 21 - const struct nft_pktinfo *pkt) 22 - { 23 - struct nft_masq *priv = nft_expr_priv(expr); 24 - struct nf_nat_range2 range; 25 - 26 - memset(&range, 0, sizeof(range)); 27 - range.flags = priv->flags; 28 - if (priv->sreg_proto_min) { 29 - range.min_proto.all = (__force __be16)nft_reg_load16( 30 - &regs->data[priv->sreg_proto_min]); 31 - range.max_proto.all = (__force __be16)nft_reg_load16( 32 - &regs->data[priv->sreg_proto_max]); 33 - } 34 - regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt), 35 - &range, nft_out(pkt)); 36 - } 37 - 38 - static void 39 - nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 40 - { 41 - nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 42 - } 43 - 44 - static struct nft_expr_type nft_masq_ipv4_type; 45 - static const struct nft_expr_ops nft_masq_ipv4_ops = { 46 - .type = &nft_masq_ipv4_type, 47 - .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 48 - .eval = nft_masq_ipv4_eval, 49 - .init = nft_masq_init, 50 - .destroy = nft_masq_ipv4_destroy, 51 - .dump = nft_masq_dump, 52 - .validate = nft_masq_validate, 53 - }; 54 - 55 - static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { 56 - .family = NFPROTO_IPV4, 57 - .name = "masq", 58 - .ops = &nft_masq_ipv4_ops, 59 - .policy = nft_masq_policy, 60 - .maxattr = NFTA_MASQ_MAX, 61 - .owner = THIS_MODULE, 62 - }; 63 - 64 - static int __init nft_masq_ipv4_module_init(void) 65 - { 66 - int ret; 67 - 68 - ret = nft_register_expr(&nft_masq_ipv4_type); 69 - if (ret < 0) 70 - return ret; 71 - 72 - ret = nf_nat_masquerade_ipv4_register_notifier(); 73 - if (ret) 74 - nft_unregister_expr(&nft_masq_ipv4_type); 75 - 76 - return ret; 77 - } 78 - 79 - static void __exit nft_masq_ipv4_module_exit(void) 80 - { 81 - nft_unregister_expr(&nft_masq_ipv4_type); 82 - nf_nat_masquerade_ipv4_unregister_notifier(); 83 - } 84 - 85 - module_init(nft_masq_ipv4_module_init); 86 - module_exit(nft_masq_ipv4_module_exit); 87 - 88 - MODULE_LICENSE("GPL"); 89 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org"); 90 - MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
-82
net/ipv4/netfilter/nft_redir_ipv4.c
··· 1 - /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - 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.h> 16 - #include <net/netfilter/nf_nat.h> 17 - #include <net/netfilter/nf_nat_redirect.h> 18 - #include <net/netfilter/nft_redir.h> 19 - 20 - static void nft_redir_ipv4_eval(const struct nft_expr *expr, 21 - struct nft_regs *regs, 22 - const struct nft_pktinfo *pkt) 23 - { 24 - struct nft_redir *priv = nft_expr_priv(expr); 25 - struct nf_nat_ipv4_multi_range_compat mr; 26 - 27 - memset(&mr, 0, sizeof(mr)); 28 - if (priv->sreg_proto_min) { 29 - mr.range[0].min.all = (__force __be16)nft_reg_load16( 30 - &regs->data[priv->sreg_proto_min]); 31 - mr.range[0].max.all = (__force __be16)nft_reg_load16( 32 - &regs->data[priv->sreg_proto_max]); 33 - mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 34 - } 35 - 36 - mr.range[0].flags |= priv->flags; 37 - 38 - regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt)); 39 - } 40 - 41 - static void 42 - nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 43 - { 44 - nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 45 - } 46 - 47 - static struct nft_expr_type nft_redir_ipv4_type; 48 - static const struct nft_expr_ops nft_redir_ipv4_ops = { 49 - .type = &nft_redir_ipv4_type, 50 - .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 51 - .eval = nft_redir_ipv4_eval, 52 - .init = nft_redir_init, 53 - .destroy = nft_redir_ipv4_destroy, 54 - .dump = nft_redir_dump, 55 - .validate = nft_redir_validate, 56 - }; 57 - 58 - static struct nft_expr_type nft_redir_ipv4_type __read_mostly = { 59 - .family = NFPROTO_IPV4, 60 - .name = "redir", 61 - .ops = &nft_redir_ipv4_ops, 62 - .policy = nft_redir_policy, 63 - .maxattr = NFTA_REDIR_MAX, 64 - .owner = THIS_MODULE, 65 - }; 66 - 67 - static int __init nft_redir_ipv4_module_init(void) 68 - { 69 - return nft_register_expr(&nft_redir_ipv4_type); 70 - } 71 - 72 - static void __exit nft_redir_ipv4_module_exit(void) 73 - { 74 - nft_unregister_expr(&nft_redir_ipv4_type); 75 - } 76 - 77 - module_init(nft_redir_ipv4_module_init); 78 - module_exit(nft_redir_ipv4_module_exit); 79 - 80 - MODULE_LICENSE("GPL"); 81 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 82 - MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
+1 -47
net/ipv6/netfilter/Kconfig
··· 31 31 fields such as the source, destination, flowlabel, hop-limit and 32 32 the packet mark. 33 33 34 - if NF_NAT_IPV6 35 - 36 - config NFT_CHAIN_NAT_IPV6 37 - tristate "IPv6 nf_tables nat chain support" 38 - help 39 - This option enables the "nat" chain for IPv6 in nf_tables. This 40 - chain type is used to perform Network Address Translation (NAT) 41 - packet transformations such as the source, destination address and 42 - source and destination ports. 43 - 44 - config NFT_MASQ_IPV6 45 - tristate "IPv6 masquerade support for nf_tables" 46 - depends on NFT_MASQ 47 - select NF_NAT_MASQUERADE_IPV6 48 - help 49 - This is the expression that provides IPv4 masquerading support for 50 - nf_tables. 51 - 52 - config NFT_REDIR_IPV6 53 - tristate "IPv6 redirect support for nf_tables" 54 - depends on NFT_REDIR 55 - select NF_NAT_REDIRECT 56 - help 57 - This is the expression that provides IPv4 redirect support for 58 - nf_tables. 59 - 60 - endif # NF_NAT_IPV6 61 - 62 34 config NFT_REJECT_IPV6 63 35 select NF_REJECT_IPV6 64 36 default NFT_REJECT ··· 77 105 tristate "IPv6 packet logging" 78 106 default m if NETFILTER_ADVANCED=n 79 107 select NF_LOG_COMMON 80 - 81 - config NF_NAT_IPV6 82 - tristate "IPv6 NAT" 83 - depends on NF_CONNTRACK 84 - depends on NETFILTER_ADVANCED 85 - select NF_NAT 86 - help 87 - The IPv6 NAT option allows masquerading, port forwarding and other 88 - forms of full Network Address Port Translation. This can be 89 - controlled by iptables or nft. 90 - 91 - if NF_NAT_IPV6 92 - 93 - config NF_NAT_MASQUERADE_IPV6 94 - bool 95 - 96 - endif # NF_NAT_IPV6 97 108 98 109 config IP6_NF_IPTABLES 99 110 tristate "IP6 tables support (required for filtering)" ··· 266 311 depends on NF_CONNTRACK 267 312 depends on NETFILTER_ADVANCED 268 313 select NF_NAT 269 - select NF_NAT_IPV6 270 314 select NETFILTER_XT_NAT 271 315 help 272 316 This enables the `nat' table in ip6tables. This allows masquerading, ··· 278 324 279 325 config IP6_NF_TARGET_MASQUERADE 280 326 tristate "MASQUERADE target support" 281 - select NF_NAT_MASQUERADE_IPV6 327 + select NF_NAT_MASQUERADE 282 328 help 283 329 Masquerading is a special case of NAT: all outgoing connections are 284 330 changed to seem to come from a particular interface's address, and
-7
net/ipv6/netfilter/Makefile
··· 11 11 obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 12 12 obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o 13 13 14 - nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o 15 - nf_nat_ipv6-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o 16 - obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o 17 - 18 14 # defrag 19 15 nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o 20 16 obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o ··· 28 32 29 33 # nf_tables 30 34 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o 31 - obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o 32 35 obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o 33 - obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o 34 - obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redir_ipv6.o 35 36 obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o 36 37 obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o 37 38
+3 -5
net/ipv6/netfilter/ip6table_nat.c
··· 17 17 #include <net/ipv6.h> 18 18 19 19 #include <net/netfilter/nf_nat.h> 20 - #include <net/netfilter/nf_nat_core.h> 21 - #include <net/netfilter/nf_nat_l3proto.h> 22 20 23 21 static int __net_init ip6table_nat_table_init(struct net *net); 24 22 ··· 70 72 int i, ret; 71 73 72 74 for (i = 0; i < ARRAY_SIZE(nf_nat_ipv6_ops); i++) { 73 - ret = nf_nat_l3proto_ipv6_register_fn(net, &nf_nat_ipv6_ops[i]); 75 + ret = nf_nat_ipv6_register_fn(net, &nf_nat_ipv6_ops[i]); 74 76 if (ret) { 75 77 while (i) 76 - nf_nat_l3proto_ipv6_unregister_fn(net, &nf_nat_ipv6_ops[--i]); 78 + nf_nat_ipv6_unregister_fn(net, &nf_nat_ipv6_ops[--i]); 77 79 78 80 return ret; 79 81 } ··· 87 89 int i; 88 90 89 91 for (i = 0; i < ARRAY_SIZE(nf_nat_ipv6_ops); i++) 90 - nf_nat_l3proto_ipv6_unregister_fn(net, &nf_nat_ipv6_ops[i]); 92 + nf_nat_ipv6_unregister_fn(net, &nf_nat_ipv6_ops[i]); 91 93 } 92 94 93 95 static int __net_init ip6table_nat_table_init(struct net *net)
-427
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
··· 1 - /* 2 - * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - * 8 - * Development of IPv6 NAT funded by Astaro. 9 - */ 10 - #include <linux/types.h> 11 - #include <linux/module.h> 12 - #include <linux/skbuff.h> 13 - #include <linux/ipv6.h> 14 - #include <linux/netfilter.h> 15 - #include <linux/netfilter_ipv6.h> 16 - #include <net/secure_seq.h> 17 - #include <net/checksum.h> 18 - #include <net/ip6_checksum.h> 19 - #include <net/ip6_route.h> 20 - #include <net/xfrm.h> 21 - #include <net/ipv6.h> 22 - 23 - #include <net/netfilter/nf_conntrack_core.h> 24 - #include <net/netfilter/nf_conntrack.h> 25 - #include <net/netfilter/nf_nat_core.h> 26 - #include <net/netfilter/nf_nat_l3proto.h> 27 - #include <net/netfilter/nf_nat_l4proto.h> 28 - 29 - static const struct nf_nat_l3proto nf_nat_l3proto_ipv6; 30 - 31 - #ifdef CONFIG_XFRM 32 - static void nf_nat_ipv6_decode_session(struct sk_buff *skb, 33 - const struct nf_conn *ct, 34 - enum ip_conntrack_dir dir, 35 - unsigned long statusbit, 36 - struct flowi *fl) 37 - { 38 - const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; 39 - struct flowi6 *fl6 = &fl->u.ip6; 40 - 41 - if (ct->status & statusbit) { 42 - fl6->daddr = t->dst.u3.in6; 43 - if (t->dst.protonum == IPPROTO_TCP || 44 - t->dst.protonum == IPPROTO_UDP || 45 - t->dst.protonum == IPPROTO_UDPLITE || 46 - t->dst.protonum == IPPROTO_DCCP || 47 - t->dst.protonum == IPPROTO_SCTP) 48 - fl6->fl6_dport = t->dst.u.all; 49 - } 50 - 51 - statusbit ^= IPS_NAT_MASK; 52 - 53 - if (ct->status & statusbit) { 54 - fl6->saddr = t->src.u3.in6; 55 - if (t->dst.protonum == IPPROTO_TCP || 56 - t->dst.protonum == IPPROTO_UDP || 57 - t->dst.protonum == IPPROTO_UDPLITE || 58 - t->dst.protonum == IPPROTO_DCCP || 59 - t->dst.protonum == IPPROTO_SCTP) 60 - fl6->fl6_sport = t->src.u.all; 61 - } 62 - } 63 - #endif 64 - 65 - static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, 66 - unsigned int iphdroff, 67 - const struct nf_conntrack_tuple *target, 68 - enum nf_nat_manip_type maniptype) 69 - { 70 - struct ipv6hdr *ipv6h; 71 - __be16 frag_off; 72 - int hdroff; 73 - u8 nexthdr; 74 - 75 - if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h))) 76 - return false; 77 - 78 - ipv6h = (void *)skb->data + iphdroff; 79 - nexthdr = ipv6h->nexthdr; 80 - hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h), 81 - &nexthdr, &frag_off); 82 - if (hdroff < 0) 83 - goto manip_addr; 84 - 85 - if ((frag_off & htons(~0x7)) == 0 && 86 - !nf_nat_l4proto_manip_pkt(skb, &nf_nat_l3proto_ipv6, iphdroff, hdroff, 87 - target, maniptype)) 88 - return false; 89 - 90 - /* must reload, offset might have changed */ 91 - ipv6h = (void *)skb->data + iphdroff; 92 - 93 - manip_addr: 94 - if (maniptype == NF_NAT_MANIP_SRC) 95 - ipv6h->saddr = target->src.u3.in6; 96 - else 97 - ipv6h->daddr = target->dst.u3.in6; 98 - 99 - return true; 100 - } 101 - 102 - static void nf_nat_ipv6_csum_update(struct sk_buff *skb, 103 - unsigned int iphdroff, __sum16 *check, 104 - const struct nf_conntrack_tuple *t, 105 - enum nf_nat_manip_type maniptype) 106 - { 107 - const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff); 108 - const struct in6_addr *oldip, *newip; 109 - 110 - if (maniptype == NF_NAT_MANIP_SRC) { 111 - oldip = &ipv6h->saddr; 112 - newip = &t->src.u3.in6; 113 - } else { 114 - oldip = &ipv6h->daddr; 115 - newip = &t->dst.u3.in6; 116 - } 117 - inet_proto_csum_replace16(check, skb, oldip->s6_addr32, 118 - newip->s6_addr32, true); 119 - } 120 - 121 - static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, 122 - u8 proto, void *data, __sum16 *check, 123 - int datalen, int oldlen) 124 - { 125 - if (skb->ip_summed != CHECKSUM_PARTIAL) { 126 - const struct ipv6hdr *ipv6h = ipv6_hdr(skb); 127 - 128 - skb->ip_summed = CHECKSUM_PARTIAL; 129 - skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 130 - (data - (void *)skb->data); 131 - skb->csum_offset = (void *)check - data; 132 - *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 133 - datalen, proto, 0); 134 - } else 135 - inet_proto_csum_replace2(check, skb, 136 - htons(oldlen), htons(datalen), true); 137 - } 138 - 139 - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 140 - static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], 141 - struct nf_nat_range2 *range) 142 - { 143 - if (tb[CTA_NAT_V6_MINIP]) { 144 - nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP], 145 - sizeof(struct in6_addr)); 146 - range->flags |= NF_NAT_RANGE_MAP_IPS; 147 - } 148 - 149 - if (tb[CTA_NAT_V6_MAXIP]) 150 - nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP], 151 - sizeof(struct in6_addr)); 152 - else 153 - range->max_addr = range->min_addr; 154 - 155 - return 0; 156 - } 157 - #endif 158 - 159 - static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { 160 - .l3proto = NFPROTO_IPV6, 161 - .manip_pkt = nf_nat_ipv6_manip_pkt, 162 - .csum_update = nf_nat_ipv6_csum_update, 163 - .csum_recalc = nf_nat_ipv6_csum_recalc, 164 - #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 165 - .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, 166 - #endif 167 - #ifdef CONFIG_XFRM 168 - .decode_session = nf_nat_ipv6_decode_session, 169 - #endif 170 - }; 171 - 172 - int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, 173 - struct nf_conn *ct, 174 - enum ip_conntrack_info ctinfo, 175 - unsigned int hooknum, 176 - unsigned int hdrlen) 177 - { 178 - struct { 179 - struct icmp6hdr icmp6; 180 - struct ipv6hdr ip6; 181 - } *inside; 182 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 183 - enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 184 - struct nf_conntrack_tuple target; 185 - unsigned long statusbit; 186 - 187 - WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 188 - 189 - if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 190 - return 0; 191 - if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) 192 - return 0; 193 - 194 - inside = (void *)skb->data + hdrlen; 195 - if (inside->icmp6.icmp6_type == NDISC_REDIRECT) { 196 - if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 197 - return 0; 198 - if (ct->status & IPS_NAT_MASK) 199 - return 0; 200 - } 201 - 202 - if (manip == NF_NAT_MANIP_SRC) 203 - statusbit = IPS_SRC_NAT; 204 - else 205 - statusbit = IPS_DST_NAT; 206 - 207 - /* Invert if this is reply direction */ 208 - if (dir == IP_CT_DIR_REPLY) 209 - statusbit ^= IPS_NAT_MASK; 210 - 211 - if (!(ct->status & statusbit)) 212 - return 1; 213 - 214 - if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6), 215 - &ct->tuplehash[!dir].tuple, !manip)) 216 - return 0; 217 - 218 - if (skb->ip_summed != CHECKSUM_PARTIAL) { 219 - struct ipv6hdr *ipv6h = ipv6_hdr(skb); 220 - inside = (void *)skb->data + hdrlen; 221 - inside->icmp6.icmp6_cksum = 0; 222 - inside->icmp6.icmp6_cksum = 223 - csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 224 - skb->len - hdrlen, IPPROTO_ICMPV6, 225 - skb_checksum(skb, hdrlen, 226 - skb->len - hdrlen, 0)); 227 - } 228 - 229 - nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 230 - target.dst.protonum = IPPROTO_ICMPV6; 231 - if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip)) 232 - return 0; 233 - 234 - return 1; 235 - } 236 - EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation); 237 - 238 - static unsigned int 239 - nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, 240 - const struct nf_hook_state *state) 241 - { 242 - struct nf_conn *ct; 243 - enum ip_conntrack_info ctinfo; 244 - __be16 frag_off; 245 - int hdrlen; 246 - u8 nexthdr; 247 - 248 - ct = nf_ct_get(skb, &ctinfo); 249 - /* Can't track? It's not due to stress, or conntrack would 250 - * have dropped it. Hence it's the user's responsibilty to 251 - * packet filter it out, or implement conntrack/NAT for that 252 - * protocol. 8) --RR 253 - */ 254 - if (!ct) 255 - return NF_ACCEPT; 256 - 257 - if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 258 - nexthdr = ipv6_hdr(skb)->nexthdr; 259 - hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), 260 - &nexthdr, &frag_off); 261 - 262 - if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) { 263 - if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo, 264 - state->hook, 265 - hdrlen)) 266 - return NF_DROP; 267 - else 268 - return NF_ACCEPT; 269 - } 270 - } 271 - 272 - return nf_nat_inet_fn(priv, skb, state); 273 - } 274 - 275 - static unsigned int 276 - nf_nat_ipv6_in(void *priv, struct sk_buff *skb, 277 - const struct nf_hook_state *state) 278 - { 279 - unsigned int ret; 280 - struct in6_addr daddr = ipv6_hdr(skb)->daddr; 281 - 282 - ret = nf_nat_ipv6_fn(priv, skb, state); 283 - if (ret != NF_DROP && ret != NF_STOLEN && 284 - ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr)) 285 - skb_dst_drop(skb); 286 - 287 - return ret; 288 - } 289 - 290 - static unsigned int 291 - nf_nat_ipv6_out(void *priv, struct sk_buff *skb, 292 - const struct nf_hook_state *state) 293 - { 294 - #ifdef CONFIG_XFRM 295 - const struct nf_conn *ct; 296 - enum ip_conntrack_info ctinfo; 297 - int err; 298 - #endif 299 - unsigned int ret; 300 - 301 - ret = nf_nat_ipv6_fn(priv, skb, state); 302 - #ifdef CONFIG_XFRM 303 - if (ret != NF_DROP && ret != NF_STOLEN && 304 - !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 305 - (ct = nf_ct_get(skb, &ctinfo)) != NULL) { 306 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 307 - 308 - if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, 309 - &ct->tuplehash[!dir].tuple.dst.u3) || 310 - (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 311 - ct->tuplehash[dir].tuple.src.u.all != 312 - ct->tuplehash[!dir].tuple.dst.u.all)) { 313 - err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 314 - if (err < 0) 315 - ret = NF_DROP_ERR(err); 316 - } 317 - } 318 - #endif 319 - return ret; 320 - } 321 - 322 - static int nat_route_me_harder(struct net *net, struct sk_buff *skb) 323 - { 324 - #ifdef CONFIG_IPV6_MODULE 325 - const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); 326 - 327 - if (!v6_ops) 328 - return -EHOSTUNREACH; 329 - 330 - return v6_ops->route_me_harder(net, skb); 331 - #else 332 - return ip6_route_me_harder(net, skb); 333 - #endif 334 - } 335 - 336 - static unsigned int 337 - nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, 338 - const struct nf_hook_state *state) 339 - { 340 - const struct nf_conn *ct; 341 - enum ip_conntrack_info ctinfo; 342 - unsigned int ret; 343 - int err; 344 - 345 - ret = nf_nat_ipv6_fn(priv, skb, state); 346 - if (ret != NF_DROP && ret != NF_STOLEN && 347 - (ct = nf_ct_get(skb, &ctinfo)) != NULL) { 348 - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 349 - 350 - if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, 351 - &ct->tuplehash[!dir].tuple.src.u3)) { 352 - err = nat_route_me_harder(state->net, skb); 353 - if (err < 0) 354 - ret = NF_DROP_ERR(err); 355 - } 356 - #ifdef CONFIG_XFRM 357 - else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 358 - ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 359 - ct->tuplehash[dir].tuple.dst.u.all != 360 - ct->tuplehash[!dir].tuple.src.u.all) { 361 - err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 362 - if (err < 0) 363 - ret = NF_DROP_ERR(err); 364 - } 365 - #endif 366 - } 367 - return ret; 368 - } 369 - 370 - static const struct nf_hook_ops nf_nat_ipv6_ops[] = { 371 - /* Before packet filtering, change destination */ 372 - { 373 - .hook = nf_nat_ipv6_in, 374 - .pf = NFPROTO_IPV6, 375 - .hooknum = NF_INET_PRE_ROUTING, 376 - .priority = NF_IP6_PRI_NAT_DST, 377 - }, 378 - /* After packet filtering, change source */ 379 - { 380 - .hook = nf_nat_ipv6_out, 381 - .pf = NFPROTO_IPV6, 382 - .hooknum = NF_INET_POST_ROUTING, 383 - .priority = NF_IP6_PRI_NAT_SRC, 384 - }, 385 - /* Before packet filtering, change destination */ 386 - { 387 - .hook = nf_nat_ipv6_local_fn, 388 - .pf = NFPROTO_IPV6, 389 - .hooknum = NF_INET_LOCAL_OUT, 390 - .priority = NF_IP6_PRI_NAT_DST, 391 - }, 392 - /* After packet filtering, change source */ 393 - { 394 - .hook = nf_nat_ipv6_fn, 395 - .pf = NFPROTO_IPV6, 396 - .hooknum = NF_INET_LOCAL_IN, 397 - .priority = NF_IP6_PRI_NAT_SRC, 398 - }, 399 - }; 400 - 401 - int nf_nat_l3proto_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops) 402 - { 403 - return nf_nat_register_fn(net, ops, nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 404 - } 405 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_ipv6_register_fn); 406 - 407 - void nf_nat_l3proto_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 408 - { 409 - nf_nat_unregister_fn(net, ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 410 - } 411 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_ipv6_unregister_fn); 412 - 413 - static int __init nf_nat_l3proto_ipv6_init(void) 414 - { 415 - return nf_nat_l3proto_register(&nf_nat_l3proto_ipv6); 416 - } 417 - 418 - static void __exit nf_nat_l3proto_ipv6_exit(void) 419 - { 420 - nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv6); 421 - } 422 - 423 - MODULE_LICENSE("GPL"); 424 - MODULE_ALIAS("nf-nat-" __stringify(AF_INET6)); 425 - 426 - module_init(nf_nat_l3proto_ipv6_init); 427 - module_exit(nf_nat_l3proto_ipv6_exit);
-240
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
··· 1 - /* 2 - * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - * 8 - * Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6 9 - * NAT funded by Astaro. 10 - */ 11 - 12 - #include <linux/kernel.h> 13 - #include <linux/atomic.h> 14 - #include <linux/netdevice.h> 15 - #include <linux/ipv6.h> 16 - #include <linux/netfilter.h> 17 - #include <linux/netfilter_ipv6.h> 18 - #include <net/netfilter/nf_nat.h> 19 - #include <net/addrconf.h> 20 - #include <net/ipv6.h> 21 - #include <net/netfilter/ipv6/nf_nat_masquerade.h> 22 - 23 - #define MAX_WORK_COUNT 16 24 - 25 - static atomic_t v6_worker_count; 26 - 27 - static int 28 - nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev, 29 - const struct in6_addr *daddr, unsigned int srcprefs, 30 - struct in6_addr *saddr) 31 - { 32 - #ifdef CONFIG_IPV6_MODULE 33 - const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); 34 - 35 - if (!v6_ops) 36 - return -EHOSTUNREACH; 37 - 38 - return v6_ops->dev_get_saddr(net, dev, daddr, srcprefs, saddr); 39 - #else 40 - return ipv6_dev_get_saddr(net, dev, daddr, srcprefs, saddr); 41 - #endif 42 - } 43 - 44 - unsigned int 45 - nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, 46 - const struct net_device *out) 47 - { 48 - enum ip_conntrack_info ctinfo; 49 - struct nf_conn_nat *nat; 50 - struct in6_addr src; 51 - struct nf_conn *ct; 52 - struct nf_nat_range2 newrange; 53 - 54 - ct = nf_ct_get(skb, &ctinfo); 55 - WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 56 - ctinfo == IP_CT_RELATED_REPLY))); 57 - 58 - if (nat_ipv6_dev_get_saddr(nf_ct_net(ct), out, 59 - &ipv6_hdr(skb)->daddr, 0, &src) < 0) 60 - return NF_DROP; 61 - 62 - nat = nf_ct_nat_ext_add(ct); 63 - if (nat) 64 - nat->masq_index = out->ifindex; 65 - 66 - newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; 67 - newrange.min_addr.in6 = src; 68 - newrange.max_addr.in6 = src; 69 - newrange.min_proto = range->min_proto; 70 - newrange.max_proto = range->max_proto; 71 - 72 - return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); 73 - } 74 - EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6); 75 - 76 - static int device_cmp(struct nf_conn *ct, void *ifindex) 77 - { 78 - const struct nf_conn_nat *nat = nfct_nat(ct); 79 - 80 - if (!nat) 81 - return 0; 82 - if (nf_ct_l3num(ct) != NFPROTO_IPV6) 83 - return 0; 84 - return nat->masq_index == (int)(long)ifindex; 85 - } 86 - 87 - static int masq_device_event(struct notifier_block *this, 88 - unsigned long event, void *ptr) 89 - { 90 - const struct net_device *dev = netdev_notifier_info_to_dev(ptr); 91 - struct net *net = dev_net(dev); 92 - 93 - if (event == NETDEV_DOWN) 94 - nf_ct_iterate_cleanup_net(net, device_cmp, 95 - (void *)(long)dev->ifindex, 0, 0); 96 - 97 - return NOTIFY_DONE; 98 - } 99 - 100 - static struct notifier_block masq_dev_notifier = { 101 - .notifier_call = masq_device_event, 102 - }; 103 - 104 - struct masq_dev_work { 105 - struct work_struct work; 106 - struct net *net; 107 - struct in6_addr addr; 108 - int ifindex; 109 - }; 110 - 111 - static int inet_cmp(struct nf_conn *ct, void *work) 112 - { 113 - struct masq_dev_work *w = (struct masq_dev_work *)work; 114 - struct nf_conntrack_tuple *tuple; 115 - 116 - if (!device_cmp(ct, (void *)(long)w->ifindex)) 117 - return 0; 118 - 119 - tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; 120 - 121 - return ipv6_addr_equal(&w->addr, &tuple->dst.u3.in6); 122 - } 123 - 124 - static void iterate_cleanup_work(struct work_struct *work) 125 - { 126 - struct masq_dev_work *w; 127 - 128 - w = container_of(work, struct masq_dev_work, work); 129 - 130 - nf_ct_iterate_cleanup_net(w->net, inet_cmp, (void *)w, 0, 0); 131 - 132 - put_net(w->net); 133 - kfree(w); 134 - atomic_dec(&v6_worker_count); 135 - module_put(THIS_MODULE); 136 - } 137 - 138 - /* ipv6 inet notifier is an atomic notifier, i.e. we cannot 139 - * schedule. 140 - * 141 - * Unfortunately, nf_ct_iterate_cleanup_net can run for a long 142 - * time if there are lots of conntracks and the system 143 - * handles high softirq load, so it frequently calls cond_resched 144 - * while iterating the conntrack table. 145 - * 146 - * So we defer nf_ct_iterate_cleanup_net walk to the system workqueue. 147 - * 148 - * As we can have 'a lot' of inet_events (depending on amount 149 - * of ipv6 addresses being deleted), we also need to add an upper 150 - * limit to the number of queued work items. 151 - */ 152 - static int masq_inet6_event(struct notifier_block *this, 153 - unsigned long event, void *ptr) 154 - { 155 - struct inet6_ifaddr *ifa = ptr; 156 - const struct net_device *dev; 157 - struct masq_dev_work *w; 158 - struct net *net; 159 - 160 - if (event != NETDEV_DOWN || 161 - atomic_read(&v6_worker_count) >= MAX_WORK_COUNT) 162 - return NOTIFY_DONE; 163 - 164 - dev = ifa->idev->dev; 165 - net = maybe_get_net(dev_net(dev)); 166 - if (!net) 167 - return NOTIFY_DONE; 168 - 169 - if (!try_module_get(THIS_MODULE)) 170 - goto err_module; 171 - 172 - w = kmalloc(sizeof(*w), GFP_ATOMIC); 173 - if (w) { 174 - atomic_inc(&v6_worker_count); 175 - 176 - INIT_WORK(&w->work, iterate_cleanup_work); 177 - w->ifindex = dev->ifindex; 178 - w->net = net; 179 - w->addr = ifa->addr; 180 - schedule_work(&w->work); 181 - 182 - return NOTIFY_DONE; 183 - } 184 - 185 - module_put(THIS_MODULE); 186 - err_module: 187 - put_net(net); 188 - return NOTIFY_DONE; 189 - } 190 - 191 - static struct notifier_block masq_inet6_notifier = { 192 - .notifier_call = masq_inet6_event, 193 - }; 194 - 195 - static int masq_refcnt; 196 - static DEFINE_MUTEX(masq_mutex); 197 - 198 - int nf_nat_masquerade_ipv6_register_notifier(void) 199 - { 200 - int ret = 0; 201 - 202 - mutex_lock(&masq_mutex); 203 - /* check if the notifier is already set */ 204 - if (++masq_refcnt > 1) 205 - goto out_unlock; 206 - 207 - ret = register_netdevice_notifier(&masq_dev_notifier); 208 - if (ret) 209 - goto err_dec; 210 - 211 - ret = register_inet6addr_notifier(&masq_inet6_notifier); 212 - if (ret) 213 - goto err_unregister; 214 - 215 - mutex_unlock(&masq_mutex); 216 - return ret; 217 - 218 - err_unregister: 219 - unregister_netdevice_notifier(&masq_dev_notifier); 220 - err_dec: 221 - masq_refcnt--; 222 - out_unlock: 223 - mutex_unlock(&masq_mutex); 224 - return ret; 225 - } 226 - EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier); 227 - 228 - void nf_nat_masquerade_ipv6_unregister_notifier(void) 229 - { 230 - mutex_lock(&masq_mutex); 231 - /* check if the notifier still has clients */ 232 - if (--masq_refcnt > 0) 233 - goto out_unlock; 234 - 235 - unregister_inet6addr_notifier(&masq_inet6_notifier); 236 - unregister_netdevice_notifier(&masq_dev_notifier); 237 - out_unlock: 238 - mutex_unlock(&masq_mutex); 239 - } 240 - EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);
-85
net/ipv6/netfilter/nft_chain_nat_ipv6.c
··· 1 - /* 2 - * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 3 - * Copyright (c) 2012 Intel Corporation 4 - * 5 - * This program is free software; you can redistribute it and/or modify it 6 - * under the terms and conditions of the GNU General Public License, 7 - * version 2, as published by the Free Software Foundation. 8 - * 9 - */ 10 - 11 - #include <linux/module.h> 12 - #include <linux/init.h> 13 - #include <linux/list.h> 14 - #include <linux/skbuff.h> 15 - #include <linux/ip.h> 16 - #include <linux/netfilter.h> 17 - #include <linux/netfilter_ipv6.h> 18 - #include <linux/netfilter/nf_tables.h> 19 - #include <net/netfilter/nf_conntrack.h> 20 - #include <net/netfilter/nf_nat.h> 21 - #include <net/netfilter/nf_nat_core.h> 22 - #include <net/netfilter/nf_tables.h> 23 - #include <net/netfilter/nf_tables_ipv6.h> 24 - #include <net/netfilter/nf_nat_l3proto.h> 25 - #include <net/ipv6.h> 26 - 27 - static unsigned int nft_nat_do_chain(void *priv, 28 - struct sk_buff *skb, 29 - const struct nf_hook_state *state) 30 - { 31 - struct nft_pktinfo pkt; 32 - 33 - nft_set_pktinfo(&pkt, skb, state); 34 - nft_set_pktinfo_ipv6(&pkt, skb); 35 - 36 - return nft_do_chain(&pkt, priv); 37 - } 38 - 39 - static int nft_nat_ipv6_reg(struct net *net, const struct nf_hook_ops *ops) 40 - { 41 - return nf_nat_l3proto_ipv6_register_fn(net, ops); 42 - } 43 - 44 - static void nft_nat_ipv6_unreg(struct net *net, const struct nf_hook_ops *ops) 45 - { 46 - nf_nat_l3proto_ipv6_unregister_fn(net, ops); 47 - } 48 - 49 - static const struct nft_chain_type nft_chain_nat_ipv6 = { 50 - .name = "nat", 51 - .type = NFT_CHAIN_T_NAT, 52 - .family = NFPROTO_IPV6, 53 - .owner = THIS_MODULE, 54 - .hook_mask = (1 << NF_INET_PRE_ROUTING) | 55 - (1 << NF_INET_POST_ROUTING) | 56 - (1 << NF_INET_LOCAL_OUT) | 57 - (1 << NF_INET_LOCAL_IN), 58 - .hooks = { 59 - [NF_INET_PRE_ROUTING] = nft_nat_do_chain, 60 - [NF_INET_POST_ROUTING] = nft_nat_do_chain, 61 - [NF_INET_LOCAL_OUT] = nft_nat_do_chain, 62 - [NF_INET_LOCAL_IN] = nft_nat_do_chain, 63 - }, 64 - .ops_register = nft_nat_ipv6_reg, 65 - .ops_unregister = nft_nat_ipv6_unreg, 66 - }; 67 - 68 - static int __init nft_chain_nat_ipv6_init(void) 69 - { 70 - nft_register_chain_type(&nft_chain_nat_ipv6); 71 - 72 - return 0; 73 - } 74 - 75 - static void __exit nft_chain_nat_ipv6_exit(void) 76 - { 77 - nft_unregister_chain_type(&nft_chain_nat_ipv6); 78 - } 79 - 80 - module_init(nft_chain_nat_ipv6_init); 81 - module_exit(nft_chain_nat_ipv6_exit); 82 - 83 - MODULE_LICENSE("GPL"); 84 - MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>"); 85 - MODULE_ALIAS_NFT_CHAIN(AF_INET6, "nat");
-91
net/ipv6/netfilter/nft_masq_ipv6.c
··· 1 - /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - 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.h> 16 - #include <net/netfilter/nf_nat.h> 17 - #include <net/netfilter/nft_masq.h> 18 - #include <net/netfilter/ipv6/nf_nat_masquerade.h> 19 - 20 - static void nft_masq_ipv6_eval(const struct nft_expr *expr, 21 - struct nft_regs *regs, 22 - const struct nft_pktinfo *pkt) 23 - { 24 - struct nft_masq *priv = nft_expr_priv(expr); 25 - struct nf_nat_range2 range; 26 - 27 - memset(&range, 0, sizeof(range)); 28 - range.flags = priv->flags; 29 - if (priv->sreg_proto_min) { 30 - range.min_proto.all = (__force __be16)nft_reg_load16( 31 - &regs->data[priv->sreg_proto_min]); 32 - range.max_proto.all = (__force __be16)nft_reg_load16( 33 - &regs->data[priv->sreg_proto_max]); 34 - } 35 - regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, 36 - nft_out(pkt)); 37 - } 38 - 39 - static void 40 - nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 41 - { 42 - nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 43 - } 44 - 45 - static struct nft_expr_type nft_masq_ipv6_type; 46 - static const struct nft_expr_ops nft_masq_ipv6_ops = { 47 - .type = &nft_masq_ipv6_type, 48 - .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 49 - .eval = nft_masq_ipv6_eval, 50 - .init = nft_masq_init, 51 - .destroy = nft_masq_ipv6_destroy, 52 - .dump = nft_masq_dump, 53 - .validate = nft_masq_validate, 54 - }; 55 - 56 - static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { 57 - .family = NFPROTO_IPV6, 58 - .name = "masq", 59 - .ops = &nft_masq_ipv6_ops, 60 - .policy = nft_masq_policy, 61 - .maxattr = NFTA_MASQ_MAX, 62 - .owner = THIS_MODULE, 63 - }; 64 - 65 - static int __init nft_masq_ipv6_module_init(void) 66 - { 67 - int ret; 68 - 69 - ret = nft_register_expr(&nft_masq_ipv6_type); 70 - if (ret < 0) 71 - return ret; 72 - 73 - ret = nf_nat_masquerade_ipv6_register_notifier(); 74 - if (ret) 75 - nft_unregister_expr(&nft_masq_ipv6_type); 76 - 77 - return ret; 78 - } 79 - 80 - static void __exit nft_masq_ipv6_module_exit(void) 81 - { 82 - nft_unregister_expr(&nft_masq_ipv6_type); 83 - nf_nat_masquerade_ipv6_unregister_notifier(); 84 - } 85 - 86 - module_init(nft_masq_ipv6_module_init); 87 - module_exit(nft_masq_ipv6_module_exit); 88 - 89 - MODULE_LICENSE("GPL"); 90 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 91 - MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");
-83
net/ipv6/netfilter/nft_redir_ipv6.c
··· 1 - /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - 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.h> 16 - #include <net/netfilter/nf_nat.h> 17 - #include <net/netfilter/nft_redir.h> 18 - #include <net/netfilter/nf_nat_redirect.h> 19 - 20 - static void nft_redir_ipv6_eval(const struct nft_expr *expr, 21 - struct nft_regs *regs, 22 - const struct nft_pktinfo *pkt) 23 - { 24 - struct nft_redir *priv = nft_expr_priv(expr); 25 - struct nf_nat_range2 range; 26 - 27 - memset(&range, 0, sizeof(range)); 28 - if (priv->sreg_proto_min) { 29 - range.min_proto.all = (__force __be16)nft_reg_load16( 30 - &regs->data[priv->sreg_proto_min]); 31 - range.max_proto.all = (__force __be16)nft_reg_load16( 32 - &regs->data[priv->sreg_proto_max]); 33 - range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 34 - } 35 - 36 - range.flags |= priv->flags; 37 - 38 - regs->verdict.code = 39 - nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt)); 40 - } 41 - 42 - static void 43 - nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 44 - { 45 - nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 46 - } 47 - 48 - static struct nft_expr_type nft_redir_ipv6_type; 49 - static const struct nft_expr_ops nft_redir_ipv6_ops = { 50 - .type = &nft_redir_ipv6_type, 51 - .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 52 - .eval = nft_redir_ipv6_eval, 53 - .init = nft_redir_init, 54 - .destroy = nft_redir_ipv6_destroy, 55 - .dump = nft_redir_dump, 56 - .validate = nft_redir_validate, 57 - }; 58 - 59 - static struct nft_expr_type nft_redir_ipv6_type __read_mostly = { 60 - .family = NFPROTO_IPV6, 61 - .name = "redir", 62 - .ops = &nft_redir_ipv6_ops, 63 - .policy = nft_redir_policy, 64 - .maxattr = NFTA_REDIR_MAX, 65 - .owner = THIS_MODULE, 66 - }; 67 - 68 - static int __init nft_redir_ipv6_module_init(void) 69 - { 70 - return nft_register_expr(&nft_redir_ipv6_type); 71 - } 72 - 73 - static void __exit nft_redir_ipv6_module_exit(void) 74 - { 75 - nft_unregister_expr(&nft_redir_ipv6_type); 76 - } 77 - 78 - module_init(nft_redir_ipv6_module_init); 79 - module_exit(nft_redir_ipv6_module_exit); 80 - 81 - MODULE_LICENSE("GPL"); 82 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 83 - MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
+13 -1
net/netfilter/Kconfig
··· 396 396 the enqueued via NFNETLINK. 397 397 398 398 config NF_NAT 399 - tristate 399 + tristate "Network Address Translation support" 400 + depends on NF_CONNTRACK 401 + default m if NETFILTER_ADVANCED=n 402 + help 403 + The NAT option allows masquerading, port forwarding and other 404 + forms of full Network Address Port Translation. This can be 405 + controlled by iptables, ip6tables or nft. 400 406 401 407 config NF_NAT_NEEDED 402 408 bool ··· 435 429 default NF_NAT && NF_CONNTRACK_TFTP 436 430 437 431 config NF_NAT_REDIRECT 432 + bool 433 + 434 + config NF_NAT_MASQUERADE 438 435 bool 439 436 440 437 config NETFILTER_SYNPROXY ··· 532 523 config NFT_MASQ 533 524 depends on NF_CONNTRACK 534 525 depends on NF_NAT 526 + select NF_NAT_MASQUERADE 535 527 tristate "Netfilter nf_tables masquerade support" 536 528 help 537 529 This option adds the "masquerade" expression that you can use ··· 542 532 depends on NF_CONNTRACK 543 533 depends on NF_NAT 544 534 tristate "Netfilter nf_tables redirect support" 535 + select NF_NAT_REDIRECT 545 536 help 546 537 This options adds the "redirect" expression that you can use 547 538 to perform NAT in the redirect flavour. ··· 550 539 config NFT_NAT 551 540 depends on NF_CONNTRACK 552 541 select NF_NAT 542 + depends on NF_TABLES_IPV4 || NF_TABLES_IPV6 553 543 tristate "Netfilter nf_tables nat module" 554 544 help 555 545 This option adds the "nat" expression that you can use to perform
+3
net/netfilter/Makefile
··· 56 56 57 57 obj-$(CONFIG_NF_NAT) += nf_nat.o 58 58 nf_nat-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o 59 + nf_nat-$(CONFIG_NF_NAT_MASQUERADE) += nf_nat_masquerade.o 59 60 60 61 # NAT helpers 61 62 obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o ··· 109 108 obj-$(CONFIG_NFT_OSF) += nft_osf.o 110 109 obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o 111 110 obj-$(CONFIG_NFT_XFRM) += nft_xfrm.o 111 + 112 + obj-$(CONFIG_NFT_NAT) += nft_chain_nat.o 112 113 113 114 # nf_tables netdev 114 115 obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
+6 -6
net/netfilter/ipvs/ip_vs_ctl.c
··· 3086 3086 3087 3087 static int ip_vs_genl_parse_service(struct netns_ipvs *ipvs, 3088 3088 struct ip_vs_service_user_kern *usvc, 3089 - struct nlattr *nla, int full_entry, 3089 + struct nlattr *nla, bool full_entry, 3090 3090 struct ip_vs_service **ret_svc) 3091 3091 { 3092 3092 struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1]; ··· 3173 3173 struct ip_vs_service *svc; 3174 3174 int ret; 3175 3175 3176 - ret = ip_vs_genl_parse_service(ipvs, &usvc, nla, 0, &svc); 3176 + ret = ip_vs_genl_parse_service(ipvs, &usvc, nla, false, &svc); 3177 3177 return ret ? ERR_PTR(ret) : svc; 3178 3178 } 3179 3179 ··· 3283 3283 } 3284 3284 3285 3285 static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest, 3286 - struct nlattr *nla, int full_entry) 3286 + struct nlattr *nla, bool full_entry) 3287 3287 { 3288 3288 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; 3289 3289 struct nlattr *nla_addr, *nla_port; ··· 3545 3545 3546 3546 static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) 3547 3547 { 3548 + bool need_full_svc = false, need_full_dest = false; 3548 3549 struct ip_vs_service *svc = NULL; 3549 3550 struct ip_vs_service_user_kern usvc; 3550 3551 struct ip_vs_dest_user_kern udest; 3551 3552 int ret = 0, cmd; 3552 - int need_full_svc = 0, need_full_dest = 0; 3553 3553 struct net *net = sock_net(skb->sk); 3554 3554 struct netns_ipvs *ipvs = net_ipvs(net); 3555 3555 ··· 3573 3573 * received a valid one. We need a full service specification when 3574 3574 * adding / editing a service. Only identifying members otherwise. */ 3575 3575 if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE) 3576 - need_full_svc = 1; 3576 + need_full_svc = true; 3577 3577 3578 3578 ret = ip_vs_genl_parse_service(ipvs, &usvc, 3579 3579 info->attrs[IPVS_CMD_ATTR_SERVICE], ··· 3593 3593 if (cmd == IPVS_CMD_NEW_DEST || cmd == IPVS_CMD_SET_DEST || 3594 3594 cmd == IPVS_CMD_DEL_DEST) { 3595 3595 if (cmd != IPVS_CMD_DEL_DEST) 3596 - need_full_dest = 1; 3596 + need_full_dest = true; 3597 3597 3598 3598 ret = ip_vs_genl_parse_dest(&udest, 3599 3599 info->attrs[IPVS_CMD_ATTR_DEST],
+2 -2
net/netfilter/ipvs/ip_vs_ftp.c
··· 124 124 } 125 125 s = data + plen; 126 126 if (skip) { 127 - int found = 0; 127 + bool found = false; 128 128 129 129 for (;; s++) { 130 130 if (s == data_limit) ··· 136 136 if (!ext && isdigit(*s)) 137 137 break; 138 138 if (*s == skip) 139 - found = 1; 139 + found = true; 140 140 } else if (*s != skip) { 141 141 break; 142 142 }
+2 -5
net/netfilter/ipvs/ip_vs_proto_sctp.c
··· 186 186 sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) 187 187 { 188 188 unsigned int sctphoff; 189 - struct sctphdr *sh, _sctph; 189 + struct sctphdr *sh; 190 190 __le32 cmp, val; 191 191 192 192 #ifdef CONFIG_IP_VS_IPV6 ··· 196 196 #endif 197 197 sctphoff = ip_hdrlen(skb); 198 198 199 - sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph); 200 - if (sh == NULL) 201 - return 0; 202 - 199 + sh = (struct sctphdr *)(skb->data + sctphoff); 203 200 cmp = sh->checksum; 204 201 val = sctp_compute_cksum(skb, sctphoff); 205 202
+4 -4
net/netfilter/ipvs/ip_vs_proto_tcp.c
··· 153 153 { 154 154 struct tcphdr *tcph; 155 155 unsigned int tcphoff = iph->len; 156 + bool payload_csum = false; 156 157 int oldlen; 157 - int payload_csum = 0; 158 158 159 159 #ifdef CONFIG_IP_VS_IPV6 160 160 if (cp->af == AF_INET6 && iph->fragoffs) ··· 180 180 if (ret == 1) 181 181 oldlen = skb->len - tcphoff; 182 182 else 183 - payload_csum = 1; 183 + payload_csum = true; 184 184 } 185 185 186 186 tcph = (void *)skb_network_header(skb) + tcphoff; ··· 231 231 { 232 232 struct tcphdr *tcph; 233 233 unsigned int tcphoff = iph->len; 234 + bool payload_csum = false; 234 235 int oldlen; 235 - int payload_csum = 0; 236 236 237 237 #ifdef CONFIG_IP_VS_IPV6 238 238 if (cp->af == AF_INET6 && iph->fragoffs) ··· 261 261 if (ret == 1) 262 262 oldlen = skb->len - tcphoff; 263 263 else 264 - payload_csum = 1; 264 + payload_csum = true; 265 265 } 266 266 267 267 tcph = (void *)skb_network_header(skb) + tcphoff;
+4 -4
net/netfilter/ipvs/ip_vs_proto_udp.c
··· 143 143 { 144 144 struct udphdr *udph; 145 145 unsigned int udphoff = iph->len; 146 + bool payload_csum = false; 146 147 int oldlen; 147 - int payload_csum = 0; 148 148 149 149 #ifdef CONFIG_IP_VS_IPV6 150 150 if (cp->af == AF_INET6 && iph->fragoffs) ··· 172 172 if (ret == 1) 173 173 oldlen = skb->len - udphoff; 174 174 else 175 - payload_csum = 1; 175 + payload_csum = true; 176 176 } 177 177 178 178 udph = (void *)skb_network_header(skb) + udphoff; ··· 226 226 { 227 227 struct udphdr *udph; 228 228 unsigned int udphoff = iph->len; 229 + bool payload_csum = false; 229 230 int oldlen; 230 - int payload_csum = 0; 231 231 232 232 #ifdef CONFIG_IP_VS_IPV6 233 233 if (cp->af == AF_INET6 && iph->fragoffs) ··· 256 256 if (ret == 1) 257 257 oldlen = skb->len - udphoff; 258 258 else 259 - payload_csum = 1; 259 + payload_csum = true; 260 260 } 261 261 262 262 udph = (void *)skb_network_header(skb) + udphoff;
+2 -2
net/netfilter/ipvs/ip_vs_xmit.c
··· 126 126 { 127 127 struct flowi4 fl4; 128 128 struct rtable *rt; 129 - int loop = 0; 129 + bool loop = false; 130 130 131 131 memset(&fl4, 0, sizeof(fl4)); 132 132 fl4.daddr = daddr; ··· 149 149 ip_rt_put(rt); 150 150 *saddr = fl4.saddr; 151 151 flowi4_update_output(&fl4, 0, 0, daddr, fl4.saddr); 152 - loop++; 152 + loop = true; 153 153 goto retry; 154 154 } 155 155 *saddr = fl4.saddr;
+7 -2
net/netfilter/nf_conntrack_amanda.c
··· 54 54 SEARCH_DATA, 55 55 SEARCH_MESG, 56 56 SEARCH_INDEX, 57 + SEARCH_STATE, 57 58 }; 58 59 59 60 static struct { ··· 80 79 }, 81 80 [SEARCH_INDEX] = { 82 81 .string = "INDEX ", 82 + .len = 6, 83 + }, 84 + [SEARCH_STATE] = { 85 + .string = "STATE ", 83 86 .len = 6, 84 87 }, 85 88 }; ··· 129 124 goto out; 130 125 stop += start; 131 126 132 - for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { 127 + for (i = SEARCH_DATA; i <= SEARCH_STATE; i++) { 133 128 off = skb_find_text(skb, start, stop, search[i].ts); 134 129 if (off == UINT_MAX) 135 130 continue; ··· 173 168 } 174 169 175 170 static const struct nf_conntrack_expect_policy amanda_exp_policy = { 176 - .max_expected = 3, 171 + .max_expected = 4, 177 172 .timeout = 180, 178 173 }; 179 174
+5 -6
net/netfilter/nf_conntrack_core.c
··· 51 51 #include <net/netfilter/nf_conntrack_labels.h> 52 52 #include <net/netfilter/nf_conntrack_synproxy.h> 53 53 #include <net/netfilter/nf_nat.h> 54 - #include <net/netfilter/nf_nat_core.h> 55 54 #include <net/netfilter/nf_nat_helper.h> 56 55 #include <net/netns/hash.h> 57 56 #include <net/ip.h> ··· 1751 1752 void __nf_ct_refresh_acct(struct nf_conn *ct, 1752 1753 enum ip_conntrack_info ctinfo, 1753 1754 const struct sk_buff *skb, 1754 - unsigned long extra_jiffies, 1755 - int do_acct) 1755 + u32 extra_jiffies, 1756 + bool do_acct) 1756 1757 { 1757 - WARN_ON(!skb); 1758 - 1759 1758 /* Only update if this is not a fixed timeout */ 1760 1759 if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) 1761 1760 goto acct; ··· 1762 1765 if (nf_ct_is_confirmed(ct)) 1763 1766 extra_jiffies += nfct_time_stamp; 1764 1767 1765 - ct->timeout = extra_jiffies; 1768 + if (ct->timeout != extra_jiffies) 1769 + ct->timeout = extra_jiffies; 1766 1770 acct: 1767 1771 if (do_acct) 1768 1772 nf_ct_acct_update(ct, ctinfo, skb->len); ··· 2480 2482 int cpu; 2481 2483 2482 2484 BUILD_BUG_ON(IP_CT_UNTRACKED == IP_CT_NUMBER); 2485 + BUILD_BUG_ON_NOT_POWER_OF_2(CONNTRACK_LOCKS); 2483 2486 atomic_set(&net->ct.count, 0); 2484 2487 2485 2488 net->ct.pcpu_lists = alloc_percpu(struct ct_pcpu);
+1 -1
net/netfilter/nf_conntrack_netlink.c
··· 46 46 #include <net/netfilter/nf_conntrack_labels.h> 47 47 #include <net/netfilter/nf_conntrack_synproxy.h> 48 48 #ifdef CONFIG_NF_NAT_NEEDED 49 - #include <net/netfilter/nf_nat_core.h> 49 + #include <net/netfilter/nf_nat.h> 50 50 #include <net/netfilter/nf_nat_helper.h> 51 51 #endif 52 52
+40 -10
net/netfilter/nf_conntrack_proto_tcp.c
··· 828 828 return true; 829 829 } 830 830 831 + static bool nf_conntrack_tcp_established(const struct nf_conn *ct) 832 + { 833 + return ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED && 834 + test_bit(IPS_ASSURED_BIT, &ct->status); 835 + } 836 + 831 837 /* Returns verdict for packet, or -1 for invalid. */ 832 838 int nf_conntrack_tcp_packet(struct nf_conn *ct, 833 839 struct sk_buff *skb, ··· 1036 1030 new_state = TCP_CONNTRACK_ESTABLISHED; 1037 1031 break; 1038 1032 case TCP_CONNTRACK_CLOSE: 1039 - if (index == TCP_RST_SET 1040 - && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) 1041 - && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) { 1042 - /* Invalid RST */ 1043 - spin_unlock_bh(&ct->lock); 1044 - nf_ct_l4proto_log_invalid(skb, ct, "invalid rst"); 1045 - return -NF_ACCEPT; 1033 + if (index != TCP_RST_SET) 1034 + break; 1035 + 1036 + if (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) { 1037 + u32 seq = ntohl(th->seq); 1038 + 1039 + if (before(seq, ct->proto.tcp.seen[!dir].td_maxack)) { 1040 + /* Invalid RST */ 1041 + spin_unlock_bh(&ct->lock); 1042 + nf_ct_l4proto_log_invalid(skb, ct, "invalid rst"); 1043 + return -NF_ACCEPT; 1044 + } 1045 + 1046 + if (!nf_conntrack_tcp_established(ct) || 1047 + seq == ct->proto.tcp.seen[!dir].td_maxack) 1048 + break; 1049 + 1050 + /* Check if rst is part of train, such as 1051 + * foo:80 > bar:4379: P, 235946583:235946602(19) ack 42 1052 + * foo:80 > bar:4379: R, 235946602:235946602(0) ack 42 1053 + */ 1054 + if (ct->proto.tcp.last_index == TCP_ACK_SET && 1055 + ct->proto.tcp.last_dir == dir && 1056 + seq == ct->proto.tcp.last_end) 1057 + break; 1058 + 1059 + /* ... RST sequence number doesn't match exactly, keep 1060 + * established state to allow a possible challenge ACK. 1061 + */ 1062 + new_state = old_state; 1046 1063 } 1047 - if (index == TCP_RST_SET 1048 - && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) 1064 + if (((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) 1049 1065 && ct->proto.tcp.last_index == TCP_SYN_SET) 1050 1066 || (!test_bit(IPS_ASSURED_BIT, &ct->status) 1051 1067 && ct->proto.tcp.last_index == TCP_ACK_SET)) ··· 1083 1055 * segments we ignored. */ 1084 1056 goto in_window; 1085 1057 } 1086 - /* Just fall through */ 1058 + break; 1087 1059 default: 1088 1060 /* Keep compilers happy. */ 1089 1061 break; ··· 1118 1090 if (ct->proto.tcp.retrans >= tn->tcp_max_retrans && 1119 1091 timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) 1120 1092 timeout = timeouts[TCP_CONNTRACK_RETRANS]; 1093 + else if (unlikely(index == TCP_RST_SET)) 1094 + timeout = timeouts[TCP_CONNTRACK_CLOSE]; 1121 1095 else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) & 1122 1096 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && 1123 1097 timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
+122 -74
net/netfilter/nf_nat_core.c
··· 22 22 #include <net/netfilter/nf_conntrack.h> 23 23 #include <net/netfilter/nf_conntrack_core.h> 24 24 #include <net/netfilter/nf_nat.h> 25 - #include <net/netfilter/nf_nat_l3proto.h> 26 - #include <net/netfilter/nf_nat_core.h> 27 25 #include <net/netfilter/nf_nat_helper.h> 28 26 #include <net/netfilter/nf_conntrack_helper.h> 29 27 #include <net/netfilter/nf_conntrack_seqadj.h> ··· 33 35 static spinlock_t nf_nat_locks[CONNTRACK_LOCKS]; 34 36 35 37 static DEFINE_MUTEX(nf_nat_proto_mutex); 36 - static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO] 37 - __read_mostly; 38 38 static unsigned int nat_net_id __read_mostly; 39 39 40 40 static struct hlist_head *nf_nat_bysource __read_mostly; ··· 54 58 struct nf_nat_hooks_net nat_proto_net[NFPROTO_NUMPROTO]; 55 59 }; 56 60 57 - inline const struct nf_nat_l3proto * 58 - __nf_nat_l3proto_find(u8 family) 61 + #ifdef CONFIG_XFRM 62 + static void nf_nat_ipv4_decode_session(struct sk_buff *skb, 63 + const struct nf_conn *ct, 64 + enum ip_conntrack_dir dir, 65 + unsigned long statusbit, 66 + struct flowi *fl) 59 67 { 60 - return rcu_dereference(nf_nat_l3protos[family]); 68 + const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; 69 + struct flowi4 *fl4 = &fl->u.ip4; 70 + 71 + if (ct->status & statusbit) { 72 + fl4->daddr = t->dst.u3.ip; 73 + if (t->dst.protonum == IPPROTO_TCP || 74 + t->dst.protonum == IPPROTO_UDP || 75 + t->dst.protonum == IPPROTO_UDPLITE || 76 + t->dst.protonum == IPPROTO_DCCP || 77 + t->dst.protonum == IPPROTO_SCTP) 78 + fl4->fl4_dport = t->dst.u.all; 79 + } 80 + 81 + statusbit ^= IPS_NAT_MASK; 82 + 83 + if (ct->status & statusbit) { 84 + fl4->saddr = t->src.u3.ip; 85 + if (t->dst.protonum == IPPROTO_TCP || 86 + t->dst.protonum == IPPROTO_UDP || 87 + t->dst.protonum == IPPROTO_UDPLITE || 88 + t->dst.protonum == IPPROTO_DCCP || 89 + t->dst.protonum == IPPROTO_SCTP) 90 + fl4->fl4_sport = t->src.u.all; 91 + } 61 92 } 62 93 63 - #ifdef CONFIG_XFRM 94 + static void nf_nat_ipv6_decode_session(struct sk_buff *skb, 95 + const struct nf_conn *ct, 96 + enum ip_conntrack_dir dir, 97 + unsigned long statusbit, 98 + struct flowi *fl) 99 + { 100 + #if IS_ENABLED(CONFIG_IPV6) 101 + const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; 102 + struct flowi6 *fl6 = &fl->u.ip6; 103 + 104 + if (ct->status & statusbit) { 105 + fl6->daddr = t->dst.u3.in6; 106 + if (t->dst.protonum == IPPROTO_TCP || 107 + t->dst.protonum == IPPROTO_UDP || 108 + t->dst.protonum == IPPROTO_UDPLITE || 109 + t->dst.protonum == IPPROTO_DCCP || 110 + t->dst.protonum == IPPROTO_SCTP) 111 + fl6->fl6_dport = t->dst.u.all; 112 + } 113 + 114 + statusbit ^= IPS_NAT_MASK; 115 + 116 + if (ct->status & statusbit) { 117 + fl6->saddr = t->src.u3.in6; 118 + if (t->dst.protonum == IPPROTO_TCP || 119 + t->dst.protonum == IPPROTO_UDP || 120 + t->dst.protonum == IPPROTO_UDPLITE || 121 + t->dst.protonum == IPPROTO_DCCP || 122 + t->dst.protonum == IPPROTO_SCTP) 123 + fl6->fl6_sport = t->src.u.all; 124 + } 125 + #endif 126 + } 127 + 64 128 static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl) 65 129 { 66 - const struct nf_nat_l3proto *l3proto; 67 130 const struct nf_conn *ct; 68 131 enum ip_conntrack_info ctinfo; 69 132 enum ip_conntrack_dir dir; ··· 134 79 return; 135 80 136 81 family = nf_ct_l3num(ct); 137 - l3proto = __nf_nat_l3proto_find(family); 138 - if (l3proto == NULL) 139 - return; 140 - 141 82 dir = CTINFO2DIR(ctinfo); 142 83 if (dir == IP_CT_DIR_ORIGINAL) 143 84 statusbit = IPS_DST_NAT; 144 85 else 145 86 statusbit = IPS_SRC_NAT; 146 87 147 - l3proto->decode_session(skb, ct, dir, statusbit, fl); 88 + switch (family) { 89 + case NFPROTO_IPV4: 90 + nf_nat_ipv4_decode_session(skb, ct, dir, statusbit, fl); 91 + return; 92 + case NFPROTO_IPV6: 93 + nf_nat_ipv6_decode_session(skb, ct, dir, statusbit, fl); 94 + return; 95 + } 148 96 } 149 97 150 98 int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family) ··· 240 182 __be16 port; 241 183 242 184 switch (tuple->dst.protonum) { 243 - case IPPROTO_ICMP: /* fallthrough */ 185 + case IPPROTO_ICMP: 244 186 case IPPROTO_ICMPV6: 245 187 return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) && 246 188 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id); ··· 689 631 } 690 632 EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding); 691 633 692 - static unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct, 693 - enum nf_nat_manip_type mtype, 694 - enum ip_conntrack_dir dir) 695 - { 696 - const struct nf_nat_l3proto *l3proto; 697 - struct nf_conntrack_tuple target; 698 - 699 - /* We are aiming to look like inverse of other direction. */ 700 - nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 701 - 702 - l3proto = __nf_nat_l3proto_find(target.src.l3num); 703 - if (!l3proto->manip_pkt(skb, 0, &target, mtype)) 704 - return NF_DROP; 705 - 706 - return NF_ACCEPT; 707 - } 708 - 709 634 /* Do packet manipulations according to nf_nat_setup_info. */ 710 635 unsigned int nf_nat_packet(struct nf_conn *ct, 711 636 enum ip_conntrack_info ctinfo, ··· 839 798 return 0; 840 799 } 841 800 842 - static void nf_nat_l3proto_clean(u8 l3proto) 843 - { 844 - struct nf_nat_proto_clean clean = { 845 - .l3proto = l3proto, 846 - }; 847 - 848 - nf_ct_iterate_destroy(nf_nat_proto_remove, &clean); 849 - } 850 - 851 - int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto) 852 - { 853 - RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto); 854 - return 0; 855 - } 856 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_register); 857 - 858 - void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *l3proto) 859 - { 860 - mutex_lock(&nf_nat_proto_mutex); 861 - RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], NULL); 862 - mutex_unlock(&nf_nat_proto_mutex); 863 - synchronize_rcu(); 864 - 865 - nf_nat_l3proto_clean(l3proto->l3proto); 866 - } 867 - EXPORT_SYMBOL_GPL(nf_nat_l3proto_unregister); 868 - 869 801 /* No one using conntrack by the time this called. */ 870 802 static void nf_nat_cleanup_conntrack(struct nf_conn *ct) 871 803 { ··· 901 887 [CTA_NAT_PROTO] = { .type = NLA_NESTED }, 902 888 }; 903 889 890 + static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], 891 + struct nf_nat_range2 *range) 892 + { 893 + if (tb[CTA_NAT_V4_MINIP]) { 894 + range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]); 895 + range->flags |= NF_NAT_RANGE_MAP_IPS; 896 + } 897 + 898 + if (tb[CTA_NAT_V4_MAXIP]) 899 + range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]); 900 + else 901 + range->max_addr.ip = range->min_addr.ip; 902 + 903 + return 0; 904 + } 905 + 906 + static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], 907 + struct nf_nat_range2 *range) 908 + { 909 + if (tb[CTA_NAT_V6_MINIP]) { 910 + nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP], 911 + sizeof(struct in6_addr)); 912 + range->flags |= NF_NAT_RANGE_MAP_IPS; 913 + } 914 + 915 + if (tb[CTA_NAT_V6_MAXIP]) 916 + nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP], 917 + sizeof(struct in6_addr)); 918 + else 919 + range->max_addr = range->min_addr; 920 + 921 + return 0; 922 + } 923 + 904 924 static int 905 925 nfnetlink_parse_nat(const struct nlattr *nat, 906 - const struct nf_conn *ct, struct nf_nat_range2 *range, 907 - const struct nf_nat_l3proto *l3proto) 926 + const struct nf_conn *ct, struct nf_nat_range2 *range) 908 927 { 909 928 struct nlattr *tb[CTA_NAT_MAX+1]; 910 929 int err; ··· 948 901 if (err < 0) 949 902 return err; 950 903 951 - err = l3proto->nlattr_to_range(tb, range); 952 - if (err < 0) 904 + switch (nf_ct_l3num(ct)) { 905 + case NFPROTO_IPV4: 906 + err = nf_nat_ipv4_nlattr_to_range(tb, range); 907 + break; 908 + case NFPROTO_IPV6: 909 + err = nf_nat_ipv6_nlattr_to_range(tb, range); 910 + break; 911 + default: 912 + err = -EPROTONOSUPPORT; 913 + break; 914 + } 915 + 916 + if (err) 953 917 return err; 954 918 955 919 if (!tb[CTA_NAT_PROTO]) ··· 976 918 const struct nlattr *attr) 977 919 { 978 920 struct nf_nat_range2 range; 979 - const struct nf_nat_l3proto *l3proto; 980 921 int err; 981 922 982 923 /* Should not happen, restricted to creating new conntracks ··· 984 927 if (WARN_ON_ONCE(nf_nat_initialized(ct, manip))) 985 928 return -EEXIST; 986 929 987 - /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to 988 - * attach the null binding, otherwise this may oops. 989 - */ 990 - l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); 991 - if (l3proto == NULL) 992 - return -EAGAIN; 993 - 994 930 /* No NAT information has been passed, allocate the null-binding */ 995 931 if (attr == NULL) 996 932 return __nf_nat_alloc_null_binding(ct, manip) == NF_DROP ? -ENOMEM : 0; 997 933 998 - err = nfnetlink_parse_nat(attr, ct, &range, l3proto); 934 + err = nfnetlink_parse_nat(attr, ct, &range); 999 935 if (err < 0) 1000 936 return err; 1001 937 ··· 1085 1035 mutex_unlock(&nf_nat_proto_mutex); 1086 1036 return ret; 1087 1037 } 1088 - EXPORT_SYMBOL_GPL(nf_nat_register_fn); 1089 1038 1090 1039 void nf_nat_unregister_fn(struct net *net, const struct nf_hook_ops *ops, 1091 1040 unsigned int ops_count) ··· 1133 1084 unlock: 1134 1085 mutex_unlock(&nf_nat_proto_mutex); 1135 1086 } 1136 - EXPORT_SYMBOL_GPL(nf_nat_unregister_fn); 1137 1087 1138 1088 static struct pernet_operations nat_net_ops = { 1139 1089 .id = &nat_net_id,
+4 -11
net/netfilter/nf_nat_helper.c
··· 22 22 #include <net/netfilter/nf_conntrack_expect.h> 23 23 #include <net/netfilter/nf_conntrack_seqadj.h> 24 24 #include <net/netfilter/nf_nat.h> 25 - #include <net/netfilter/nf_nat_l3proto.h> 26 - #include <net/netfilter/nf_nat_l4proto.h> 27 - #include <net/netfilter/nf_nat_core.h> 28 25 #include <net/netfilter/nf_nat_helper.h> 29 26 30 27 /* Frobs data inside this packet, which is linear. */ ··· 95 98 const char *rep_buffer, 96 99 unsigned int rep_len, bool adjust) 97 100 { 98 - const struct nf_nat_l3proto *l3proto; 99 101 struct tcphdr *tcph; 100 102 int oldlen, datalen; 101 103 ··· 114 118 115 119 datalen = skb->len - protoff; 116 120 117 - l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); 118 - l3proto->csum_recalc(skb, IPPROTO_TCP, tcph, &tcph->check, 119 - datalen, oldlen); 121 + nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP, 122 + tcph, &tcph->check, datalen, oldlen); 120 123 121 124 if (adjust && rep_len != match_len) 122 125 nf_ct_seqadj_set(ct, ctinfo, tcph->seq, ··· 145 150 const char *rep_buffer, 146 151 unsigned int rep_len) 147 152 { 148 - const struct nf_nat_l3proto *l3proto; 149 153 struct udphdr *udph; 150 154 int datalen, oldlen; 151 155 ··· 170 176 if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) 171 177 return true; 172 178 173 - l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); 174 - l3proto->csum_recalc(skb, IPPROTO_UDP, udph, &udph->check, 175 - datalen, oldlen); 179 + nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP, 180 + udph, &udph->check, datalen, oldlen); 176 181 177 182 return true; 178 183 }
+712 -32
net/netfilter/nf_nat_proto.c
··· 20 20 21 21 #include <linux/netfilter.h> 22 22 #include <net/netfilter/nf_nat.h> 23 - #include <net/netfilter/nf_nat_core.h> 24 - #include <net/netfilter/nf_nat_l3proto.h> 25 - #include <net/netfilter/nf_nat_l4proto.h> 23 + 24 + #include <linux/ipv6.h> 25 + #include <linux/netfilter_ipv6.h> 26 + #include <net/checksum.h> 27 + #include <net/ip6_checksum.h> 28 + #include <net/ip6_route.h> 29 + #include <net/xfrm.h> 30 + #include <net/ipv6.h> 31 + 32 + #include <net/netfilter/nf_conntrack_core.h> 33 + #include <net/netfilter/nf_conntrack.h> 34 + #include <linux/netfilter/nfnetlink_conntrack.h> 35 + 36 + static void nf_csum_update(struct sk_buff *skb, 37 + unsigned int iphdroff, __sum16 *check, 38 + const struct nf_conntrack_tuple *t, 39 + enum nf_nat_manip_type maniptype); 26 40 27 41 static void 28 42 __udp_manip_pkt(struct sk_buff *skb, 29 - const struct nf_nat_l3proto *l3proto, 30 43 unsigned int iphdroff, struct udphdr *hdr, 31 44 const struct nf_conntrack_tuple *tuple, 32 45 enum nf_nat_manip_type maniptype, bool do_csum) ··· 56 43 portptr = &hdr->dest; 57 44 } 58 45 if (do_csum) { 59 - l3proto->csum_update(skb, iphdroff, &hdr->check, 60 - tuple, maniptype); 46 + nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype); 61 47 inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 62 48 false); 63 49 if (!hdr->check) ··· 66 54 } 67 55 68 56 static bool udp_manip_pkt(struct sk_buff *skb, 69 - const struct nf_nat_l3proto *l3proto, 70 57 unsigned int iphdroff, unsigned int hdroff, 71 58 const struct nf_conntrack_tuple *tuple, 72 59 enum nf_nat_manip_type maniptype) ··· 79 68 hdr = (struct udphdr *)(skb->data + hdroff); 80 69 do_csum = hdr->check || skb->ip_summed == CHECKSUM_PARTIAL; 81 70 82 - __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, do_csum); 71 + __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, do_csum); 83 72 return true; 84 73 } 85 74 86 75 static bool udplite_manip_pkt(struct sk_buff *skb, 87 - const struct nf_nat_l3proto *l3proto, 88 76 unsigned int iphdroff, unsigned int hdroff, 89 77 const struct nf_conntrack_tuple *tuple, 90 78 enum nf_nat_manip_type maniptype) ··· 95 85 return false; 96 86 97 87 hdr = (struct udphdr *)(skb->data + hdroff); 98 - __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, true); 88 + __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, true); 99 89 #endif 100 90 return true; 101 91 } 102 92 103 93 static bool 104 94 sctp_manip_pkt(struct sk_buff *skb, 105 - const struct nf_nat_l3proto *l3proto, 106 95 unsigned int iphdroff, unsigned int hdroff, 107 96 const struct nf_conntrack_tuple *tuple, 108 97 enum nf_nat_manip_type maniptype) ··· 144 135 145 136 static bool 146 137 tcp_manip_pkt(struct sk_buff *skb, 147 - const struct nf_nat_l3proto *l3proto, 148 138 unsigned int iphdroff, unsigned int hdroff, 149 139 const struct nf_conntrack_tuple *tuple, 150 140 enum nf_nat_manip_type maniptype) ··· 179 171 if (hdrsize < sizeof(*hdr)) 180 172 return true; 181 173 182 - l3proto->csum_update(skb, iphdroff, &hdr->check, tuple, maniptype); 174 + nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype); 183 175 inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, false); 184 176 return true; 185 177 } 186 178 187 179 static bool 188 180 dccp_manip_pkt(struct sk_buff *skb, 189 - const struct nf_nat_l3proto *l3proto, 190 181 unsigned int iphdroff, unsigned int hdroff, 191 182 const struct nf_conntrack_tuple *tuple, 192 183 enum nf_nat_manip_type maniptype) ··· 217 210 if (hdrsize < sizeof(*hdr)) 218 211 return true; 219 212 220 - l3proto->csum_update(skb, iphdroff, &hdr->dccph_checksum, 221 - tuple, maniptype); 213 + nf_csum_update(skb, iphdroff, &hdr->dccph_checksum, tuple, maniptype); 222 214 inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport, 223 215 false); 224 216 #endif ··· 226 220 227 221 static bool 228 222 icmp_manip_pkt(struct sk_buff *skb, 229 - const struct nf_nat_l3proto *l3proto, 230 223 unsigned int iphdroff, unsigned int hdroff, 231 224 const struct nf_conntrack_tuple *tuple, 232 225 enum nf_nat_manip_type maniptype) ··· 244 239 245 240 static bool 246 241 icmpv6_manip_pkt(struct sk_buff *skb, 247 - const struct nf_nat_l3proto *l3proto, 248 242 unsigned int iphdroff, unsigned int hdroff, 249 243 const struct nf_conntrack_tuple *tuple, 250 244 enum nf_nat_manip_type maniptype) ··· 254 250 return false; 255 251 256 252 hdr = (struct icmp6hdr *)(skb->data + hdroff); 257 - l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, 258 - tuple, maniptype); 253 + nf_csum_update(skb, iphdroff, &hdr->icmp6_cksum, tuple, maniptype); 259 254 if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST || 260 255 hdr->icmp6_type == ICMPV6_ECHO_REPLY) { 261 256 inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, ··· 268 265 /* manipulate a GRE packet according to maniptype */ 269 266 static bool 270 267 gre_manip_pkt(struct sk_buff *skb, 271 - const struct nf_nat_l3proto *l3proto, 272 268 unsigned int iphdroff, unsigned int hdroff, 273 269 const struct nf_conntrack_tuple *tuple, 274 270 enum nf_nat_manip_type maniptype) ··· 306 304 return true; 307 305 } 308 306 309 - bool nf_nat_l4proto_manip_pkt(struct sk_buff *skb, 310 - const struct nf_nat_l3proto *l3proto, 307 + static bool l4proto_manip_pkt(struct sk_buff *skb, 311 308 unsigned int iphdroff, unsigned int hdroff, 312 309 const struct nf_conntrack_tuple *tuple, 313 310 enum nf_nat_manip_type maniptype) 314 311 { 315 312 switch (tuple->dst.protonum) { 316 313 case IPPROTO_TCP: 317 - return tcp_manip_pkt(skb, l3proto, iphdroff, hdroff, 314 + return tcp_manip_pkt(skb, iphdroff, hdroff, 318 315 tuple, maniptype); 319 316 case IPPROTO_UDP: 320 - return udp_manip_pkt(skb, l3proto, iphdroff, hdroff, 317 + return udp_manip_pkt(skb, iphdroff, hdroff, 321 318 tuple, maniptype); 322 319 case IPPROTO_UDPLITE: 323 - return udplite_manip_pkt(skb, l3proto, iphdroff, hdroff, 320 + return udplite_manip_pkt(skb, iphdroff, hdroff, 324 321 tuple, maniptype); 325 322 case IPPROTO_SCTP: 326 - return sctp_manip_pkt(skb, l3proto, iphdroff, hdroff, 323 + return sctp_manip_pkt(skb, iphdroff, hdroff, 327 324 tuple, maniptype); 328 325 case IPPROTO_ICMP: 329 - return icmp_manip_pkt(skb, l3proto, iphdroff, hdroff, 326 + return icmp_manip_pkt(skb, iphdroff, hdroff, 330 327 tuple, maniptype); 331 328 case IPPROTO_ICMPV6: 332 - return icmpv6_manip_pkt(skb, l3proto, iphdroff, hdroff, 329 + return icmpv6_manip_pkt(skb, iphdroff, hdroff, 333 330 tuple, maniptype); 334 331 case IPPROTO_DCCP: 335 - return dccp_manip_pkt(skb, l3proto, iphdroff, hdroff, 332 + return dccp_manip_pkt(skb, iphdroff, hdroff, 336 333 tuple, maniptype); 337 334 case IPPROTO_GRE: 338 - return gre_manip_pkt(skb, l3proto, iphdroff, hdroff, 335 + return gre_manip_pkt(skb, iphdroff, hdroff, 339 336 tuple, maniptype); 340 337 } 341 338 342 339 /* If we don't know protocol -- no error, pass it unmodified. */ 343 340 return true; 344 341 } 345 - EXPORT_SYMBOL_GPL(nf_nat_l4proto_manip_pkt); 342 + 343 + static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, 344 + unsigned int iphdroff, 345 + const struct nf_conntrack_tuple *target, 346 + enum nf_nat_manip_type maniptype) 347 + { 348 + struct iphdr *iph; 349 + unsigned int hdroff; 350 + 351 + if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) 352 + return false; 353 + 354 + iph = (void *)skb->data + iphdroff; 355 + hdroff = iphdroff + iph->ihl * 4; 356 + 357 + if (!l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype)) 358 + return false; 359 + iph = (void *)skb->data + iphdroff; 360 + 361 + if (maniptype == NF_NAT_MANIP_SRC) { 362 + csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); 363 + iph->saddr = target->src.u3.ip; 364 + } else { 365 + csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); 366 + iph->daddr = target->dst.u3.ip; 367 + } 368 + return true; 369 + } 370 + 371 + static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, 372 + unsigned int iphdroff, 373 + const struct nf_conntrack_tuple *target, 374 + enum nf_nat_manip_type maniptype) 375 + { 376 + #if IS_ENABLED(CONFIG_IPV6) 377 + struct ipv6hdr *ipv6h; 378 + __be16 frag_off; 379 + int hdroff; 380 + u8 nexthdr; 381 + 382 + if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h))) 383 + return false; 384 + 385 + ipv6h = (void *)skb->data + iphdroff; 386 + nexthdr = ipv6h->nexthdr; 387 + hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h), 388 + &nexthdr, &frag_off); 389 + if (hdroff < 0) 390 + goto manip_addr; 391 + 392 + if ((frag_off & htons(~0x7)) == 0 && 393 + !l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype)) 394 + return false; 395 + 396 + /* must reload, offset might have changed */ 397 + ipv6h = (void *)skb->data + iphdroff; 398 + 399 + manip_addr: 400 + if (maniptype == NF_NAT_MANIP_SRC) 401 + ipv6h->saddr = target->src.u3.in6; 402 + else 403 + ipv6h->daddr = target->dst.u3.in6; 404 + 405 + #endif 406 + return true; 407 + } 408 + 409 + unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct, 410 + enum nf_nat_manip_type mtype, 411 + enum ip_conntrack_dir dir) 412 + { 413 + struct nf_conntrack_tuple target; 414 + 415 + /* We are aiming to look like inverse of other direction. */ 416 + nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 417 + 418 + switch (target.src.l3num) { 419 + case NFPROTO_IPV6: 420 + if (nf_nat_ipv6_manip_pkt(skb, 0, &target, mtype)) 421 + return NF_ACCEPT; 422 + break; 423 + case NFPROTO_IPV4: 424 + if (nf_nat_ipv4_manip_pkt(skb, 0, &target, mtype)) 425 + return NF_ACCEPT; 426 + break; 427 + default: 428 + WARN_ON_ONCE(1); 429 + break; 430 + } 431 + 432 + return NF_DROP; 433 + } 434 + 435 + static void nf_nat_ipv4_csum_update(struct sk_buff *skb, 436 + unsigned int iphdroff, __sum16 *check, 437 + const struct nf_conntrack_tuple *t, 438 + enum nf_nat_manip_type maniptype) 439 + { 440 + struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); 441 + __be32 oldip, newip; 442 + 443 + if (maniptype == NF_NAT_MANIP_SRC) { 444 + oldip = iph->saddr; 445 + newip = t->src.u3.ip; 446 + } else { 447 + oldip = iph->daddr; 448 + newip = t->dst.u3.ip; 449 + } 450 + inet_proto_csum_replace4(check, skb, oldip, newip, true); 451 + } 452 + 453 + static void nf_nat_ipv6_csum_update(struct sk_buff *skb, 454 + unsigned int iphdroff, __sum16 *check, 455 + const struct nf_conntrack_tuple *t, 456 + enum nf_nat_manip_type maniptype) 457 + { 458 + #if IS_ENABLED(CONFIG_IPV6) 459 + const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff); 460 + const struct in6_addr *oldip, *newip; 461 + 462 + if (maniptype == NF_NAT_MANIP_SRC) { 463 + oldip = &ipv6h->saddr; 464 + newip = &t->src.u3.in6; 465 + } else { 466 + oldip = &ipv6h->daddr; 467 + newip = &t->dst.u3.in6; 468 + } 469 + inet_proto_csum_replace16(check, skb, oldip->s6_addr32, 470 + newip->s6_addr32, true); 471 + #endif 472 + } 473 + 474 + static void nf_csum_update(struct sk_buff *skb, 475 + unsigned int iphdroff, __sum16 *check, 476 + const struct nf_conntrack_tuple *t, 477 + enum nf_nat_manip_type maniptype) 478 + { 479 + switch (t->src.l3num) { 480 + case NFPROTO_IPV4: 481 + nf_nat_ipv4_csum_update(skb, iphdroff, check, t, maniptype); 482 + return; 483 + case NFPROTO_IPV6: 484 + nf_nat_ipv6_csum_update(skb, iphdroff, check, t, maniptype); 485 + return; 486 + } 487 + } 488 + 489 + static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, 490 + u8 proto, void *data, __sum16 *check, 491 + int datalen, int oldlen) 492 + { 493 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 494 + const struct iphdr *iph = ip_hdr(skb); 495 + 496 + skb->ip_summed = CHECKSUM_PARTIAL; 497 + skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 498 + ip_hdrlen(skb); 499 + skb->csum_offset = (void *)check - data; 500 + *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, 501 + proto, 0); 502 + } else { 503 + inet_proto_csum_replace2(check, skb, 504 + htons(oldlen), htons(datalen), true); 505 + } 506 + } 507 + 508 + #if IS_ENABLED(CONFIG_IPV6) 509 + static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, 510 + u8 proto, void *data, __sum16 *check, 511 + int datalen, int oldlen) 512 + { 513 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 514 + const struct ipv6hdr *ipv6h = ipv6_hdr(skb); 515 + 516 + skb->ip_summed = CHECKSUM_PARTIAL; 517 + skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 518 + (data - (void *)skb->data); 519 + skb->csum_offset = (void *)check - data; 520 + *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 521 + datalen, proto, 0); 522 + } else { 523 + inet_proto_csum_replace2(check, skb, 524 + htons(oldlen), htons(datalen), true); 525 + } 526 + } 527 + #endif 528 + 529 + void nf_nat_csum_recalc(struct sk_buff *skb, 530 + u8 nfproto, u8 proto, void *data, __sum16 *check, 531 + int datalen, int oldlen) 532 + { 533 + switch (nfproto) { 534 + case NFPROTO_IPV4: 535 + nf_nat_ipv4_csum_recalc(skb, proto, data, check, 536 + datalen, oldlen); 537 + return; 538 + #if IS_ENABLED(CONFIG_IPV6) 539 + case NFPROTO_IPV6: 540 + nf_nat_ipv6_csum_recalc(skb, proto, data, check, 541 + datalen, oldlen); 542 + return; 543 + #endif 544 + } 545 + 546 + WARN_ON_ONCE(1); 547 + } 548 + 549 + int nf_nat_icmp_reply_translation(struct sk_buff *skb, 550 + struct nf_conn *ct, 551 + enum ip_conntrack_info ctinfo, 552 + unsigned int hooknum) 553 + { 554 + struct { 555 + struct icmphdr icmp; 556 + struct iphdr ip; 557 + } *inside; 558 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 559 + enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 560 + unsigned int hdrlen = ip_hdrlen(skb); 561 + struct nf_conntrack_tuple target; 562 + unsigned long statusbit; 563 + 564 + WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 565 + 566 + if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 567 + return 0; 568 + if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) 569 + return 0; 570 + 571 + inside = (void *)skb->data + hdrlen; 572 + if (inside->icmp.type == ICMP_REDIRECT) { 573 + if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 574 + return 0; 575 + if (ct->status & IPS_NAT_MASK) 576 + return 0; 577 + } 578 + 579 + if (manip == NF_NAT_MANIP_SRC) 580 + statusbit = IPS_SRC_NAT; 581 + else 582 + statusbit = IPS_DST_NAT; 583 + 584 + /* Invert if this is reply direction */ 585 + if (dir == IP_CT_DIR_REPLY) 586 + statusbit ^= IPS_NAT_MASK; 587 + 588 + if (!(ct->status & statusbit)) 589 + return 1; 590 + 591 + if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp), 592 + &ct->tuplehash[!dir].tuple, !manip)) 593 + return 0; 594 + 595 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 596 + /* Reloading "inside" here since manip_pkt may reallocate */ 597 + inside = (void *)skb->data + hdrlen; 598 + inside->icmp.checksum = 0; 599 + inside->icmp.checksum = 600 + csum_fold(skb_checksum(skb, hdrlen, 601 + skb->len - hdrlen, 0)); 602 + } 603 + 604 + /* Change outer to look like the reply to an incoming packet */ 605 + nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 606 + target.dst.protonum = IPPROTO_ICMP; 607 + if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip)) 608 + return 0; 609 + 610 + return 1; 611 + } 612 + EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); 613 + 614 + static unsigned int 615 + nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, 616 + const struct nf_hook_state *state) 617 + { 618 + struct nf_conn *ct; 619 + enum ip_conntrack_info ctinfo; 620 + 621 + ct = nf_ct_get(skb, &ctinfo); 622 + if (!ct) 623 + return NF_ACCEPT; 624 + 625 + if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 626 + if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { 627 + if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 628 + state->hook)) 629 + return NF_DROP; 630 + else 631 + return NF_ACCEPT; 632 + } 633 + } 634 + 635 + return nf_nat_inet_fn(priv, skb, state); 636 + } 637 + 638 + static unsigned int 639 + nf_nat_ipv4_in(void *priv, struct sk_buff *skb, 640 + const struct nf_hook_state *state) 641 + { 642 + unsigned int ret; 643 + __be32 daddr = ip_hdr(skb)->daddr; 644 + 645 + ret = nf_nat_ipv4_fn(priv, skb, state); 646 + if (ret == NF_ACCEPT && daddr != ip_hdr(skb)->daddr) 647 + skb_dst_drop(skb); 648 + 649 + return ret; 650 + } 651 + 652 + static unsigned int 653 + nf_nat_ipv4_out(void *priv, struct sk_buff *skb, 654 + const struct nf_hook_state *state) 655 + { 656 + #ifdef CONFIG_XFRM 657 + const struct nf_conn *ct; 658 + enum ip_conntrack_info ctinfo; 659 + int err; 660 + #endif 661 + unsigned int ret; 662 + 663 + ret = nf_nat_ipv4_fn(priv, skb, state); 664 + #ifdef CONFIG_XFRM 665 + if (ret != NF_ACCEPT) 666 + return ret; 667 + 668 + if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) 669 + return ret; 670 + 671 + ct = nf_ct_get(skb, &ctinfo); 672 + if (ct) { 673 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 674 + 675 + if (ct->tuplehash[dir].tuple.src.u3.ip != 676 + ct->tuplehash[!dir].tuple.dst.u3.ip || 677 + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 678 + ct->tuplehash[dir].tuple.src.u.all != 679 + ct->tuplehash[!dir].tuple.dst.u.all)) { 680 + err = nf_xfrm_me_harder(state->net, skb, AF_INET); 681 + if (err < 0) 682 + ret = NF_DROP_ERR(err); 683 + } 684 + } 685 + #endif 686 + return ret; 687 + } 688 + 689 + static unsigned int 690 + nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, 691 + const struct nf_hook_state *state) 692 + { 693 + const struct nf_conn *ct; 694 + enum ip_conntrack_info ctinfo; 695 + unsigned int ret; 696 + int err; 697 + 698 + ret = nf_nat_ipv4_fn(priv, skb, state); 699 + if (ret != NF_ACCEPT) 700 + return ret; 701 + 702 + ct = nf_ct_get(skb, &ctinfo); 703 + if (ct) { 704 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 705 + 706 + if (ct->tuplehash[dir].tuple.dst.u3.ip != 707 + ct->tuplehash[!dir].tuple.src.u3.ip) { 708 + err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); 709 + if (err < 0) 710 + ret = NF_DROP_ERR(err); 711 + } 712 + #ifdef CONFIG_XFRM 713 + else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 714 + ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 715 + ct->tuplehash[dir].tuple.dst.u.all != 716 + ct->tuplehash[!dir].tuple.src.u.all) { 717 + err = nf_xfrm_me_harder(state->net, skb, AF_INET); 718 + if (err < 0) 719 + ret = NF_DROP_ERR(err); 720 + } 721 + #endif 722 + } 723 + return ret; 724 + } 725 + 726 + static const struct nf_hook_ops nf_nat_ipv4_ops[] = { 727 + /* Before packet filtering, change destination */ 728 + { 729 + .hook = nf_nat_ipv4_in, 730 + .pf = NFPROTO_IPV4, 731 + .hooknum = NF_INET_PRE_ROUTING, 732 + .priority = NF_IP_PRI_NAT_DST, 733 + }, 734 + /* After packet filtering, change source */ 735 + { 736 + .hook = nf_nat_ipv4_out, 737 + .pf = NFPROTO_IPV4, 738 + .hooknum = NF_INET_POST_ROUTING, 739 + .priority = NF_IP_PRI_NAT_SRC, 740 + }, 741 + /* Before packet filtering, change destination */ 742 + { 743 + .hook = nf_nat_ipv4_local_fn, 744 + .pf = NFPROTO_IPV4, 745 + .hooknum = NF_INET_LOCAL_OUT, 746 + .priority = NF_IP_PRI_NAT_DST, 747 + }, 748 + /* After packet filtering, change source */ 749 + { 750 + .hook = nf_nat_ipv4_fn, 751 + .pf = NFPROTO_IPV4, 752 + .hooknum = NF_INET_LOCAL_IN, 753 + .priority = NF_IP_PRI_NAT_SRC, 754 + }, 755 + }; 756 + 757 + int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops) 758 + { 759 + return nf_nat_register_fn(net, ops, nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 760 + } 761 + EXPORT_SYMBOL_GPL(nf_nat_ipv4_register_fn); 762 + 763 + void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 764 + { 765 + nf_nat_unregister_fn(net, ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 766 + } 767 + EXPORT_SYMBOL_GPL(nf_nat_ipv4_unregister_fn); 768 + 769 + #if IS_ENABLED(CONFIG_IPV6) 770 + int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, 771 + struct nf_conn *ct, 772 + enum ip_conntrack_info ctinfo, 773 + unsigned int hooknum, 774 + unsigned int hdrlen) 775 + { 776 + struct { 777 + struct icmp6hdr icmp6; 778 + struct ipv6hdr ip6; 779 + } *inside; 780 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 781 + enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 782 + struct nf_conntrack_tuple target; 783 + unsigned long statusbit; 784 + 785 + WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 786 + 787 + if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 788 + return 0; 789 + if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) 790 + return 0; 791 + 792 + inside = (void *)skb->data + hdrlen; 793 + if (inside->icmp6.icmp6_type == NDISC_REDIRECT) { 794 + if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 795 + return 0; 796 + if (ct->status & IPS_NAT_MASK) 797 + return 0; 798 + } 799 + 800 + if (manip == NF_NAT_MANIP_SRC) 801 + statusbit = IPS_SRC_NAT; 802 + else 803 + statusbit = IPS_DST_NAT; 804 + 805 + /* Invert if this is reply direction */ 806 + if (dir == IP_CT_DIR_REPLY) 807 + statusbit ^= IPS_NAT_MASK; 808 + 809 + if (!(ct->status & statusbit)) 810 + return 1; 811 + 812 + if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6), 813 + &ct->tuplehash[!dir].tuple, !manip)) 814 + return 0; 815 + 816 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 817 + struct ipv6hdr *ipv6h = ipv6_hdr(skb); 818 + 819 + inside = (void *)skb->data + hdrlen; 820 + inside->icmp6.icmp6_cksum = 0; 821 + inside->icmp6.icmp6_cksum = 822 + csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 823 + skb->len - hdrlen, IPPROTO_ICMPV6, 824 + skb_checksum(skb, hdrlen, 825 + skb->len - hdrlen, 0)); 826 + } 827 + 828 + nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 829 + target.dst.protonum = IPPROTO_ICMPV6; 830 + if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip)) 831 + return 0; 832 + 833 + return 1; 834 + } 835 + EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation); 836 + 837 + static unsigned int 838 + nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, 839 + const struct nf_hook_state *state) 840 + { 841 + struct nf_conn *ct; 842 + enum ip_conntrack_info ctinfo; 843 + __be16 frag_off; 844 + int hdrlen; 845 + u8 nexthdr; 846 + 847 + ct = nf_ct_get(skb, &ctinfo); 848 + /* Can't track? It's not due to stress, or conntrack would 849 + * have dropped it. Hence it's the user's responsibilty to 850 + * packet filter it out, or implement conntrack/NAT for that 851 + * protocol. 8) --RR 852 + */ 853 + if (!ct) 854 + return NF_ACCEPT; 855 + 856 + if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 857 + nexthdr = ipv6_hdr(skb)->nexthdr; 858 + hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), 859 + &nexthdr, &frag_off); 860 + 861 + if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) { 862 + if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo, 863 + state->hook, 864 + hdrlen)) 865 + return NF_DROP; 866 + else 867 + return NF_ACCEPT; 868 + } 869 + } 870 + 871 + return nf_nat_inet_fn(priv, skb, state); 872 + } 873 + 874 + static unsigned int 875 + nf_nat_ipv6_in(void *priv, struct sk_buff *skb, 876 + const struct nf_hook_state *state) 877 + { 878 + unsigned int ret; 879 + struct in6_addr daddr = ipv6_hdr(skb)->daddr; 880 + 881 + ret = nf_nat_ipv6_fn(priv, skb, state); 882 + if (ret != NF_DROP && ret != NF_STOLEN && 883 + ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr)) 884 + skb_dst_drop(skb); 885 + 886 + return ret; 887 + } 888 + 889 + static unsigned int 890 + nf_nat_ipv6_out(void *priv, struct sk_buff *skb, 891 + const struct nf_hook_state *state) 892 + { 893 + #ifdef CONFIG_XFRM 894 + const struct nf_conn *ct; 895 + enum ip_conntrack_info ctinfo; 896 + int err; 897 + #endif 898 + unsigned int ret; 899 + 900 + ret = nf_nat_ipv6_fn(priv, skb, state); 901 + #ifdef CONFIG_XFRM 902 + if (ret != NF_ACCEPT) 903 + return ret; 904 + 905 + if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) 906 + return ret; 907 + ct = nf_ct_get(skb, &ctinfo); 908 + if (ct) { 909 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 910 + 911 + if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, 912 + &ct->tuplehash[!dir].tuple.dst.u3) || 913 + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 914 + ct->tuplehash[dir].tuple.src.u.all != 915 + ct->tuplehash[!dir].tuple.dst.u.all)) { 916 + err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 917 + if (err < 0) 918 + ret = NF_DROP_ERR(err); 919 + } 920 + } 921 + #endif 922 + 923 + return ret; 924 + } 925 + 926 + static int nat_route_me_harder(struct net *net, struct sk_buff *skb) 927 + { 928 + #ifdef CONFIG_IPV6_MODULE 929 + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); 930 + 931 + if (!v6_ops) 932 + return -EHOSTUNREACH; 933 + 934 + return v6_ops->route_me_harder(net, skb); 935 + #else 936 + return ip6_route_me_harder(net, skb); 937 + #endif 938 + } 939 + 940 + static unsigned int 941 + nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, 942 + const struct nf_hook_state *state) 943 + { 944 + const struct nf_conn *ct; 945 + enum ip_conntrack_info ctinfo; 946 + unsigned int ret; 947 + int err; 948 + 949 + ret = nf_nat_ipv6_fn(priv, skb, state); 950 + if (ret != NF_ACCEPT) 951 + return ret; 952 + 953 + ct = nf_ct_get(skb, &ctinfo); 954 + if (ct) { 955 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 956 + 957 + if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, 958 + &ct->tuplehash[!dir].tuple.src.u3)) { 959 + err = nat_route_me_harder(state->net, skb); 960 + if (err < 0) 961 + ret = NF_DROP_ERR(err); 962 + } 963 + #ifdef CONFIG_XFRM 964 + else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 965 + ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 966 + ct->tuplehash[dir].tuple.dst.u.all != 967 + ct->tuplehash[!dir].tuple.src.u.all) { 968 + err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 969 + if (err < 0) 970 + ret = NF_DROP_ERR(err); 971 + } 972 + #endif 973 + } 974 + 975 + return ret; 976 + } 977 + 978 + static const struct nf_hook_ops nf_nat_ipv6_ops[] = { 979 + /* Before packet filtering, change destination */ 980 + { 981 + .hook = nf_nat_ipv6_in, 982 + .pf = NFPROTO_IPV6, 983 + .hooknum = NF_INET_PRE_ROUTING, 984 + .priority = NF_IP6_PRI_NAT_DST, 985 + }, 986 + /* After packet filtering, change source */ 987 + { 988 + .hook = nf_nat_ipv6_out, 989 + .pf = NFPROTO_IPV6, 990 + .hooknum = NF_INET_POST_ROUTING, 991 + .priority = NF_IP6_PRI_NAT_SRC, 992 + }, 993 + /* Before packet filtering, change destination */ 994 + { 995 + .hook = nf_nat_ipv6_local_fn, 996 + .pf = NFPROTO_IPV6, 997 + .hooknum = NF_INET_LOCAL_OUT, 998 + .priority = NF_IP6_PRI_NAT_DST, 999 + }, 1000 + /* After packet filtering, change source */ 1001 + { 1002 + .hook = nf_nat_ipv6_fn, 1003 + .pf = NFPROTO_IPV6, 1004 + .hooknum = NF_INET_LOCAL_IN, 1005 + .priority = NF_IP6_PRI_NAT_SRC, 1006 + }, 1007 + }; 1008 + 1009 + int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops) 1010 + { 1011 + return nf_nat_register_fn(net, ops, nf_nat_ipv6_ops, 1012 + ARRAY_SIZE(nf_nat_ipv6_ops)); 1013 + } 1014 + EXPORT_SYMBOL_GPL(nf_nat_ipv6_register_fn); 1015 + 1016 + void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 1017 + { 1018 + nf_nat_unregister_fn(net, ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 1019 + } 1020 + EXPORT_SYMBOL_GPL(nf_nat_ipv6_unregister_fn); 1021 + #endif /* CONFIG_IPV6 */
+6 -1
net/netfilter/nf_tables_api.c
··· 2172 2172 { 2173 2173 struct nft_expr_info info; 2174 2174 struct nft_expr *expr; 2175 + struct module *owner; 2175 2176 int err; 2176 2177 2177 2178 err = nf_tables_expr_parse(ctx, nla, &info); ··· 2192 2191 err3: 2193 2192 kfree(expr); 2194 2193 err2: 2195 - module_put(info.ops->type->owner); 2194 + owner = info.ops->type->owner; 2195 + if (info.ops->type->release_ops) 2196 + info.ops->type->release_ops(info.ops); 2197 + 2198 + module_put(owner); 2196 2199 err1: 2197 2200 return ERR_PTR(err); 2198 2201 }
+8 -7
net/netfilter/nf_tables_core.c
··· 98 98 const struct nft_pktinfo *pkt) 99 99 { 100 100 struct nft_base_chain *base_chain; 101 + struct nft_stats __percpu *pstats; 101 102 struct nft_stats *stats; 102 103 103 104 base_chain = nft_base_chain(chain); 104 - if (!rcu_access_pointer(base_chain->stats)) 105 - return; 106 105 107 - local_bh_disable(); 108 - stats = this_cpu_ptr(rcu_dereference(base_chain->stats)); 109 - if (stats) { 106 + rcu_read_lock(); 107 + pstats = READ_ONCE(base_chain->stats); 108 + if (pstats) { 109 + local_bh_disable(); 110 + stats = this_cpu_ptr(pstats); 110 111 u64_stats_update_begin(&stats->syncp); 111 112 stats->pkts++; 112 113 stats->bytes += pkt->skb->len; 113 114 u64_stats_update_end(&stats->syncp); 115 + local_bh_enable(); 114 116 } 115 - local_bh_enable(); 117 + rcu_read_unlock(); 116 118 } 117 119 118 120 struct nft_jumpstack { ··· 223 221 chain = regs.verdict.chain; 224 222 goto do_chain; 225 223 case NFT_CONTINUE: 226 - /* fall through */ 227 224 case NFT_RETURN: 228 225 nft_trace_packet(&info, chain, rule, 229 226 NFT_TRACETYPE_RETURN);
+108
net/netfilter/nft_chain_nat.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/module.h> 4 + #include <linux/netfilter/nf_tables.h> 5 + #include <net/netfilter/nf_nat.h> 6 + #include <net/netfilter/nf_tables.h> 7 + #include <net/netfilter/nf_tables_ipv4.h> 8 + #include <net/netfilter/nf_tables_ipv6.h> 9 + 10 + static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb, 11 + const struct nf_hook_state *state) 12 + { 13 + struct nft_pktinfo pkt; 14 + 15 + nft_set_pktinfo(&pkt, skb, state); 16 + 17 + switch (state->pf) { 18 + #ifdef CONFIG_NF_TABLES_IPV4 19 + case NFPROTO_IPV4: 20 + nft_set_pktinfo_ipv4(&pkt, skb); 21 + break; 22 + #endif 23 + #ifdef CONFIG_NF_TABLES_IPV6 24 + case NFPROTO_IPV6: 25 + nft_set_pktinfo_ipv6(&pkt, skb); 26 + break; 27 + #endif 28 + default: 29 + break; 30 + } 31 + 32 + return nft_do_chain(&pkt, priv); 33 + } 34 + 35 + #ifdef CONFIG_NF_TABLES_IPV4 36 + static const struct nft_chain_type nft_chain_nat_ipv4 = { 37 + .name = "nat", 38 + .type = NFT_CHAIN_T_NAT, 39 + .family = NFPROTO_IPV4, 40 + .owner = THIS_MODULE, 41 + .hook_mask = (1 << NF_INET_PRE_ROUTING) | 42 + (1 << NF_INET_POST_ROUTING) | 43 + (1 << NF_INET_LOCAL_OUT) | 44 + (1 << NF_INET_LOCAL_IN), 45 + .hooks = { 46 + [NF_INET_PRE_ROUTING] = nft_nat_do_chain, 47 + [NF_INET_POST_ROUTING] = nft_nat_do_chain, 48 + [NF_INET_LOCAL_OUT] = nft_nat_do_chain, 49 + [NF_INET_LOCAL_IN] = nft_nat_do_chain, 50 + }, 51 + .ops_register = nf_nat_ipv4_register_fn, 52 + .ops_unregister = nf_nat_ipv4_unregister_fn, 53 + }; 54 + #endif 55 + 56 + #ifdef CONFIG_NF_TABLES_IPV6 57 + static const struct nft_chain_type nft_chain_nat_ipv6 = { 58 + .name = "nat", 59 + .type = NFT_CHAIN_T_NAT, 60 + .family = NFPROTO_IPV6, 61 + .owner = THIS_MODULE, 62 + .hook_mask = (1 << NF_INET_PRE_ROUTING) | 63 + (1 << NF_INET_POST_ROUTING) | 64 + (1 << NF_INET_LOCAL_OUT) | 65 + (1 << NF_INET_LOCAL_IN), 66 + .hooks = { 67 + [NF_INET_PRE_ROUTING] = nft_nat_do_chain, 68 + [NF_INET_POST_ROUTING] = nft_nat_do_chain, 69 + [NF_INET_LOCAL_OUT] = nft_nat_do_chain, 70 + [NF_INET_LOCAL_IN] = nft_nat_do_chain, 71 + }, 72 + .ops_register = nf_nat_ipv6_register_fn, 73 + .ops_unregister = nf_nat_ipv6_unregister_fn, 74 + }; 75 + #endif 76 + 77 + static int __init nft_chain_nat_init(void) 78 + { 79 + #ifdef CONFIG_NF_TABLES_IPV6 80 + nft_register_chain_type(&nft_chain_nat_ipv6); 81 + #endif 82 + #ifdef CONFIG_NF_TABLES_IPV4 83 + nft_register_chain_type(&nft_chain_nat_ipv4); 84 + #endif 85 + 86 + return 0; 87 + } 88 + 89 + static void __exit nft_chain_nat_exit(void) 90 + { 91 + #ifdef CONFIG_NF_TABLES_IPV4 92 + nft_unregister_chain_type(&nft_chain_nat_ipv4); 93 + #endif 94 + #ifdef CONFIG_NF_TABLES_IPV6 95 + nft_unregister_chain_type(&nft_chain_nat_ipv6); 96 + #endif 97 + } 98 + 99 + module_init(nft_chain_nat_init); 100 + module_exit(nft_chain_nat_exit); 101 + 102 + MODULE_LICENSE("GPL"); 103 + #ifdef CONFIG_NF_TABLES_IPV4 104 + MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat"); 105 + #endif 106 + #ifdef CONFIG_NF_TABLES_IPV6 107 + MODULE_ALIAS_NFT_CHAIN(AF_INET6, "nat"); 108 + #endif
+55 -226
net/netfilter/nft_compat.c
··· 22 22 #include <linux/netfilter_bridge/ebtables.h> 23 23 #include <linux/netfilter_arp/arp_tables.h> 24 24 #include <net/netfilter/nf_tables.h> 25 - #include <net/netns/generic.h> 26 - 27 - struct nft_xt { 28 - struct list_head head; 29 - struct nft_expr_ops ops; 30 - refcount_t refcnt; 31 - 32 - /* used only when transaction mutex is locked */ 33 - unsigned int listcnt; 34 - 35 - /* Unlike other expressions, ops doesn't have static storage duration. 36 - * nft core assumes they do. We use kfree_rcu so that nft core can 37 - * can check expr->ops->size even after nft_compat->destroy() frees 38 - * the nft_xt struct that holds the ops structure. 39 - */ 40 - struct rcu_head rcu_head; 41 - }; 42 25 43 26 /* Used for matches where *info is larger than X byte */ 44 27 #define NFT_MATCH_LARGE_THRESH 192 ··· 29 46 struct nft_xt_match_priv { 30 47 void *info; 31 48 }; 32 - 33 - struct nft_compat_net { 34 - struct list_head nft_target_list; 35 - struct list_head nft_match_list; 36 - }; 37 - 38 - static unsigned int nft_compat_net_id __read_mostly; 39 - static struct nft_expr_type nft_match_type; 40 - static struct nft_expr_type nft_target_type; 41 - 42 - static struct nft_compat_net *nft_compat_pernet(struct net *net) 43 - { 44 - return net_generic(net, nft_compat_net_id); 45 - } 46 - 47 - static void nft_xt_get(struct nft_xt *xt) 48 - { 49 - /* refcount_inc() warns on 0 -> 1 transition, but we can't 50 - * init the reference count to 1 in .select_ops -- we can't 51 - * undo such an increase when another expression inside the same 52 - * rule fails afterwards. 53 - */ 54 - if (xt->listcnt == 0) 55 - refcount_set(&xt->refcnt, 1); 56 - else 57 - refcount_inc(&xt->refcnt); 58 - 59 - xt->listcnt++; 60 - } 61 - 62 - static bool nft_xt_put(struct nft_xt *xt) 63 - { 64 - if (refcount_dec_and_test(&xt->refcnt)) { 65 - WARN_ON_ONCE(!list_empty(&xt->head)); 66 - kfree_rcu(xt, rcu_head); 67 - return true; 68 - } 69 - 70 - return false; 71 - } 72 49 73 50 static int nft_compat_chain_validate_dependency(const struct nft_ctx *ctx, 74 51 const char *tablename) ··· 224 281 struct xt_target *target = expr->ops->data; 225 282 struct xt_tgchk_param par; 226 283 size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO])); 227 - struct nft_xt *nft_xt; 228 284 u16 proto = 0; 229 285 bool inv = false; 230 286 union nft_entry e = {}; ··· 247 305 if (!target->target) 248 306 return -EINVAL; 249 307 250 - nft_xt = container_of(expr->ops, struct nft_xt, ops); 251 - nft_xt_get(nft_xt); 252 308 return 0; 253 309 } 254 310 ··· 265 325 if (par.target->destroy != NULL) 266 326 par.target->destroy(&par); 267 327 268 - if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops))) 269 - module_put(me); 328 + module_put(me); 329 + kfree(expr->ops); 270 330 } 271 331 272 332 static int nft_extension_dump_info(struct sk_buff *skb, int attr, ··· 439 499 struct xt_match *match = expr->ops->data; 440 500 struct xt_mtchk_param par; 441 501 size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO])); 442 - struct nft_xt *nft_xt; 443 502 u16 proto = 0; 444 503 bool inv = false; 445 504 union nft_entry e = {}; ··· 454 515 455 516 nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv); 456 517 457 - ret = xt_check_match(&par, size, proto, inv); 458 - if (ret < 0) 459 - return ret; 460 - 461 - nft_xt = container_of(expr->ops, struct nft_xt, ops); 462 - nft_xt_get(nft_xt); 463 - return 0; 518 + return xt_check_match(&par, size, proto, inv); 464 519 } 465 520 466 521 static int ··· 497 564 if (par.match->destroy != NULL) 498 565 par.match->destroy(&par); 499 566 500 - if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops))) 501 - module_put(me); 567 + module_put(me); 568 + kfree(expr->ops); 502 569 } 503 570 504 571 static void 505 572 nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 506 573 { 507 574 __nft_match_destroy(ctx, expr, nft_expr_priv(expr)); 508 - } 509 - 510 - static void nft_compat_deactivate(const struct nft_ctx *ctx, 511 - const struct nft_expr *expr, 512 - enum nft_trans_phase phase) 513 - { 514 - struct nft_xt *xt = container_of(expr->ops, struct nft_xt, ops); 515 - 516 - if (phase == NFT_TRANS_ABORT || phase == NFT_TRANS_COMMIT) { 517 - if (--xt->listcnt == 0) 518 - list_del_init(&xt->head); 519 - } 520 575 } 521 576 522 577 static void ··· 701 780 .cb = nfnl_nft_compat_cb, 702 781 }; 703 782 704 - static bool nft_match_cmp(const struct xt_match *match, 705 - const char *name, u32 rev, u32 family) 706 - { 707 - return strcmp(match->name, name) == 0 && match->revision == rev && 708 - (match->family == NFPROTO_UNSPEC || match->family == family); 709 - } 783 + static struct nft_expr_type nft_match_type; 710 784 711 785 static const struct nft_expr_ops * 712 786 nft_match_select_ops(const struct nft_ctx *ctx, 713 787 const struct nlattr * const tb[]) 714 788 { 715 - struct nft_compat_net *cn; 716 - struct nft_xt *nft_match; 789 + struct nft_expr_ops *ops; 717 790 struct xt_match *match; 718 791 unsigned int matchsize; 719 792 char *mt_name; ··· 723 808 rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); 724 809 family = ctx->family; 725 810 726 - cn = nft_compat_pernet(ctx->net); 727 - 728 - /* Re-use the existing match if it's already loaded. */ 729 - list_for_each_entry(nft_match, &cn->nft_match_list, head) { 730 - struct xt_match *match = nft_match->ops.data; 731 - 732 - if (nft_match_cmp(match, mt_name, rev, family)) 733 - return &nft_match->ops; 734 - } 735 - 736 811 match = xt_request_find_match(family, mt_name, rev); 737 812 if (IS_ERR(match)) 738 813 return ERR_PTR(-ENOENT); ··· 732 827 goto err; 733 828 } 734 829 735 - /* This is the first time we use this match, allocate operations */ 736 - nft_match = kzalloc(sizeof(struct nft_xt), GFP_KERNEL); 737 - if (nft_match == NULL) { 830 + ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); 831 + if (!ops) { 738 832 err = -ENOMEM; 739 833 goto err; 740 834 } 741 835 742 - refcount_set(&nft_match->refcnt, 0); 743 - nft_match->ops.type = &nft_match_type; 744 - nft_match->ops.eval = nft_match_eval; 745 - nft_match->ops.init = nft_match_init; 746 - nft_match->ops.destroy = nft_match_destroy; 747 - nft_match->ops.deactivate = nft_compat_deactivate; 748 - nft_match->ops.dump = nft_match_dump; 749 - nft_match->ops.validate = nft_match_validate; 750 - nft_match->ops.data = match; 836 + ops->type = &nft_match_type; 837 + ops->eval = nft_match_eval; 838 + ops->init = nft_match_init; 839 + ops->destroy = nft_match_destroy; 840 + ops->dump = nft_match_dump; 841 + ops->validate = nft_match_validate; 842 + ops->data = match; 751 843 752 844 matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize)); 753 845 if (matchsize > NFT_MATCH_LARGE_THRESH) { 754 846 matchsize = NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv)); 755 847 756 - nft_match->ops.eval = nft_match_large_eval; 757 - nft_match->ops.init = nft_match_large_init; 758 - nft_match->ops.destroy = nft_match_large_destroy; 759 - nft_match->ops.dump = nft_match_large_dump; 848 + ops->eval = nft_match_large_eval; 849 + ops->init = nft_match_large_init; 850 + ops->destroy = nft_match_large_destroy; 851 + ops->dump = nft_match_large_dump; 760 852 } 761 853 762 - nft_match->ops.size = matchsize; 854 + ops->size = matchsize; 763 855 764 - nft_match->listcnt = 0; 765 - list_add(&nft_match->head, &cn->nft_match_list); 766 - 767 - return &nft_match->ops; 856 + return ops; 768 857 err: 769 858 module_put(match->me); 770 859 return ERR_PTR(err); 771 860 } 772 861 862 + static void nft_match_release_ops(const struct nft_expr_ops *ops) 863 + { 864 + struct xt_match *match = ops->data; 865 + 866 + module_put(match->me); 867 + kfree(ops); 868 + } 869 + 773 870 static struct nft_expr_type nft_match_type __read_mostly = { 774 871 .name = "match", 775 872 .select_ops = nft_match_select_ops, 873 + .release_ops = nft_match_release_ops, 776 874 .policy = nft_match_policy, 777 875 .maxattr = NFTA_MATCH_MAX, 778 876 .owner = THIS_MODULE, 779 877 }; 780 878 781 - static bool nft_target_cmp(const struct xt_target *tg, 782 - const char *name, u32 rev, u32 family) 783 - { 784 - return strcmp(tg->name, name) == 0 && tg->revision == rev && 785 - (tg->family == NFPROTO_UNSPEC || tg->family == family); 786 - } 879 + static struct nft_expr_type nft_target_type; 787 880 788 881 static const struct nft_expr_ops * 789 882 nft_target_select_ops(const struct nft_ctx *ctx, 790 883 const struct nlattr * const tb[]) 791 884 { 792 - struct nft_compat_net *cn; 793 - struct nft_xt *nft_target; 885 + struct nft_expr_ops *ops; 794 886 struct xt_target *target; 795 887 char *tg_name; 796 888 u32 rev, family; ··· 807 905 strcmp(tg_name, "standard") == 0) 808 906 return ERR_PTR(-EINVAL); 809 907 810 - cn = nft_compat_pernet(ctx->net); 811 - /* Re-use the existing target if it's already loaded. */ 812 - list_for_each_entry(nft_target, &cn->nft_target_list, head) { 813 - struct xt_target *target = nft_target->ops.data; 814 - 815 - if (!target->target) 816 - continue; 817 - 818 - if (nft_target_cmp(target, tg_name, rev, family)) 819 - return &nft_target->ops; 820 - } 821 - 822 908 target = xt_request_find_target(family, tg_name, rev); 823 909 if (IS_ERR(target)) 824 910 return ERR_PTR(-ENOENT); ··· 821 931 goto err; 822 932 } 823 933 824 - /* This is the first time we use this target, allocate operations */ 825 - nft_target = kzalloc(sizeof(struct nft_xt), GFP_KERNEL); 826 - if (nft_target == NULL) { 934 + ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); 935 + if (!ops) { 827 936 err = -ENOMEM; 828 937 goto err; 829 938 } 830 939 831 - refcount_set(&nft_target->refcnt, 0); 832 - nft_target->ops.type = &nft_target_type; 833 - nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); 834 - nft_target->ops.init = nft_target_init; 835 - nft_target->ops.destroy = nft_target_destroy; 836 - nft_target->ops.deactivate = nft_compat_deactivate; 837 - nft_target->ops.dump = nft_target_dump; 838 - nft_target->ops.validate = nft_target_validate; 839 - nft_target->ops.data = target; 940 + ops->type = &nft_target_type; 941 + ops->size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); 942 + ops->init = nft_target_init; 943 + ops->destroy = nft_target_destroy; 944 + ops->dump = nft_target_dump; 945 + ops->validate = nft_target_validate; 946 + ops->data = target; 840 947 841 948 if (family == NFPROTO_BRIDGE) 842 - nft_target->ops.eval = nft_target_eval_bridge; 949 + ops->eval = nft_target_eval_bridge; 843 950 else 844 - nft_target->ops.eval = nft_target_eval_xt; 951 + ops->eval = nft_target_eval_xt; 845 952 846 - nft_target->listcnt = 0; 847 - list_add(&nft_target->head, &cn->nft_target_list); 848 - 849 - return &nft_target->ops; 953 + return ops; 850 954 err: 851 955 module_put(target->me); 852 956 return ERR_PTR(err); 853 957 } 854 958 959 + static void nft_target_release_ops(const struct nft_expr_ops *ops) 960 + { 961 + struct xt_target *target = ops->data; 962 + 963 + module_put(target->me); 964 + kfree(ops); 965 + } 966 + 855 967 static struct nft_expr_type nft_target_type __read_mostly = { 856 968 .name = "target", 857 969 .select_ops = nft_target_select_ops, 970 + .release_ops = nft_target_release_ops, 858 971 .policy = nft_target_policy, 859 972 .maxattr = NFTA_TARGET_MAX, 860 973 .owner = THIS_MODULE, 861 - }; 862 - 863 - static int __net_init nft_compat_init_net(struct net *net) 864 - { 865 - struct nft_compat_net *cn = nft_compat_pernet(net); 866 - 867 - INIT_LIST_HEAD(&cn->nft_target_list); 868 - INIT_LIST_HEAD(&cn->nft_match_list); 869 - 870 - return 0; 871 - } 872 - 873 - static void __net_exit nft_compat_exit_net(struct net *net) 874 - { 875 - struct nft_compat_net *cn = nft_compat_pernet(net); 876 - struct nft_xt *xt, *next; 877 - 878 - if (list_empty(&cn->nft_match_list) && 879 - list_empty(&cn->nft_target_list)) 880 - return; 881 - 882 - /* If there was an error that caused nft_xt expr to not be initialized 883 - * fully and noone else requested the same expression later, the lists 884 - * contain 0-refcount entries that still hold module reference. 885 - * 886 - * Clean them here. 887 - */ 888 - mutex_lock(&net->nft.commit_mutex); 889 - list_for_each_entry_safe(xt, next, &cn->nft_target_list, head) { 890 - struct xt_target *target = xt->ops.data; 891 - 892 - list_del_init(&xt->head); 893 - 894 - if (refcount_read(&xt->refcnt)) 895 - continue; 896 - module_put(target->me); 897 - kfree(xt); 898 - } 899 - 900 - list_for_each_entry_safe(xt, next, &cn->nft_match_list, head) { 901 - struct xt_match *match = xt->ops.data; 902 - 903 - list_del_init(&xt->head); 904 - 905 - if (refcount_read(&xt->refcnt)) 906 - continue; 907 - module_put(match->me); 908 - kfree(xt); 909 - } 910 - mutex_unlock(&net->nft.commit_mutex); 911 - } 912 - 913 - static struct pernet_operations nft_compat_net_ops = { 914 - .init = nft_compat_init_net, 915 - .exit = nft_compat_exit_net, 916 - .id = &nft_compat_net_id, 917 - .size = sizeof(struct nft_compat_net), 918 974 }; 919 975 920 976 static int __init nft_compat_module_init(void) 921 977 { 922 978 int ret; 923 979 924 - ret = register_pernet_subsys(&nft_compat_net_ops); 925 - if (ret < 0) 926 - goto err_target; 927 - 928 980 ret = nft_register_expr(&nft_match_type); 929 981 if (ret < 0) 930 - goto err_pernet; 982 + return ret; 931 983 932 984 ret = nft_register_expr(&nft_target_type); 933 985 if (ret < 0) ··· 886 1054 nft_unregister_expr(&nft_target_type); 887 1055 err_match: 888 1056 nft_unregister_expr(&nft_match_type); 889 - err_pernet: 890 - unregister_pernet_subsys(&nft_compat_net_ops); 891 1057 return ret; 892 1058 } 893 1059 ··· 894 1064 nfnetlink_subsys_unregister(&nfnl_compat_subsys); 895 1065 nft_unregister_expr(&nft_target_type); 896 1066 nft_unregister_expr(&nft_match_type); 897 - unregister_pernet_subsys(&nft_compat_net_ops); 898 1067 } 899 1068 900 1069 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
+167 -13
net/netfilter/nft_masq.c
··· 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_tables.h> 16 16 #include <net/netfilter/nf_nat.h> 17 - #include <net/netfilter/nft_masq.h> 17 + #include <net/netfilter/ipv4/nf_nat_masquerade.h> 18 + #include <net/netfilter/ipv6/nf_nat_masquerade.h> 18 19 19 - const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { 20 + struct nft_masq { 21 + u32 flags; 22 + enum nft_registers sreg_proto_min:8; 23 + enum nft_registers sreg_proto_max:8; 24 + }; 25 + 26 + static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = { 20 27 [NFTA_MASQ_FLAGS] = { .type = NLA_U32 }, 21 28 [NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 }, 22 29 [NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 }, 23 30 }; 24 - EXPORT_SYMBOL_GPL(nft_masq_policy); 25 31 26 - int nft_masq_validate(const struct nft_ctx *ctx, 27 - const struct nft_expr *expr, 28 - const struct nft_data **data) 32 + static int nft_masq_validate(const struct nft_ctx *ctx, 33 + const struct nft_expr *expr, 34 + const struct nft_data **data) 29 35 { 30 36 int err; 31 37 ··· 42 36 return nft_chain_validate_hooks(ctx->chain, 43 37 (1 << NF_INET_POST_ROUTING)); 44 38 } 45 - EXPORT_SYMBOL_GPL(nft_masq_validate); 46 39 47 - int nft_masq_init(const struct nft_ctx *ctx, 48 - const struct nft_expr *expr, 49 - const struct nlattr * const tb[]) 40 + static int nft_masq_init(const struct nft_ctx *ctx, 41 + const struct nft_expr *expr, 42 + const struct nlattr * const tb[]) 50 43 { 51 44 u32 plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); 52 45 struct nft_masq *priv = nft_expr_priv(expr); ··· 80 75 81 76 return nf_ct_netns_get(ctx->net, ctx->family); 82 77 } 83 - EXPORT_SYMBOL_GPL(nft_masq_init); 84 78 85 - int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr) 79 + static int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr) 86 80 { 87 81 const struct nft_masq *priv = nft_expr_priv(expr); 88 82 ··· 102 98 nla_put_failure: 103 99 return -1; 104 100 } 105 - EXPORT_SYMBOL_GPL(nft_masq_dump); 101 + 102 + static void nft_masq_ipv4_eval(const struct nft_expr *expr, 103 + struct nft_regs *regs, 104 + const struct nft_pktinfo *pkt) 105 + { 106 + struct nft_masq *priv = nft_expr_priv(expr); 107 + struct nf_nat_range2 range; 108 + 109 + memset(&range, 0, sizeof(range)); 110 + range.flags = priv->flags; 111 + if (priv->sreg_proto_min) { 112 + range.min_proto.all = (__force __be16)nft_reg_load16( 113 + &regs->data[priv->sreg_proto_min]); 114 + range.max_proto.all = (__force __be16)nft_reg_load16( 115 + &regs->data[priv->sreg_proto_max]); 116 + } 117 + regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt), 118 + &range, nft_out(pkt)); 119 + } 120 + 121 + static void 122 + nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 123 + { 124 + nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 125 + } 126 + 127 + static struct nft_expr_type nft_masq_ipv4_type; 128 + static const struct nft_expr_ops nft_masq_ipv4_ops = { 129 + .type = &nft_masq_ipv4_type, 130 + .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 131 + .eval = nft_masq_ipv4_eval, 132 + .init = nft_masq_init, 133 + .destroy = nft_masq_ipv4_destroy, 134 + .dump = nft_masq_dump, 135 + .validate = nft_masq_validate, 136 + }; 137 + 138 + static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { 139 + .family = NFPROTO_IPV4, 140 + .name = "masq", 141 + .ops = &nft_masq_ipv4_ops, 142 + .policy = nft_masq_policy, 143 + .maxattr = NFTA_MASQ_MAX, 144 + .owner = THIS_MODULE, 145 + }; 146 + 147 + #ifdef CONFIG_NF_TABLES_IPV6 148 + static void nft_masq_ipv6_eval(const struct nft_expr *expr, 149 + struct nft_regs *regs, 150 + const struct nft_pktinfo *pkt) 151 + { 152 + struct nft_masq *priv = nft_expr_priv(expr); 153 + struct nf_nat_range2 range; 154 + 155 + memset(&range, 0, sizeof(range)); 156 + range.flags = priv->flags; 157 + if (priv->sreg_proto_min) { 158 + range.min_proto.all = (__force __be16)nft_reg_load16( 159 + &regs->data[priv->sreg_proto_min]); 160 + range.max_proto.all = (__force __be16)nft_reg_load16( 161 + &regs->data[priv->sreg_proto_max]); 162 + } 163 + regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, 164 + nft_out(pkt)); 165 + } 166 + 167 + static void 168 + nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 169 + { 170 + nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 171 + } 172 + 173 + static struct nft_expr_type nft_masq_ipv6_type; 174 + static const struct nft_expr_ops nft_masq_ipv6_ops = { 175 + .type = &nft_masq_ipv6_type, 176 + .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 177 + .eval = nft_masq_ipv6_eval, 178 + .init = nft_masq_init, 179 + .destroy = nft_masq_ipv6_destroy, 180 + .dump = nft_masq_dump, 181 + .validate = nft_masq_validate, 182 + }; 183 + 184 + static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { 185 + .family = NFPROTO_IPV6, 186 + .name = "masq", 187 + .ops = &nft_masq_ipv6_ops, 188 + .policy = nft_masq_policy, 189 + .maxattr = NFTA_MASQ_MAX, 190 + .owner = THIS_MODULE, 191 + }; 192 + 193 + static int __init nft_masq_module_init_ipv6(void) 194 + { 195 + int ret = nft_register_expr(&nft_masq_ipv6_type); 196 + 197 + if (ret) 198 + return ret; 199 + 200 + ret = nf_nat_masquerade_ipv6_register_notifier(); 201 + if (ret < 0) 202 + nft_unregister_expr(&nft_masq_ipv6_type); 203 + 204 + return ret; 205 + } 206 + 207 + static void nft_masq_module_exit_ipv6(void) 208 + { 209 + nft_unregister_expr(&nft_masq_ipv6_type); 210 + nf_nat_masquerade_ipv6_unregister_notifier(); 211 + } 212 + #else 213 + static inline int nft_masq_module_init_ipv6(void) { return 0; } 214 + static inline void nft_masq_module_exit_ipv6(void) {} 215 + #endif 216 + 217 + static int __init nft_masq_module_init(void) 218 + { 219 + int ret; 220 + 221 + ret = nft_masq_module_init_ipv6(); 222 + if (ret < 0) 223 + return ret; 224 + 225 + ret = nft_register_expr(&nft_masq_ipv4_type); 226 + if (ret < 0) { 227 + nft_masq_module_exit_ipv6(); 228 + return ret; 229 + } 230 + 231 + ret = nf_nat_masquerade_ipv4_register_notifier(); 232 + if (ret < 0) { 233 + nft_masq_module_exit_ipv6(); 234 + nft_unregister_expr(&nft_masq_ipv4_type); 235 + return ret; 236 + } 237 + 238 + return ret; 239 + } 240 + 241 + static void __exit nft_masq_module_exit(void) 242 + { 243 + nft_masq_module_exit_ipv6(); 244 + nft_unregister_expr(&nft_masq_ipv4_type); 245 + nf_nat_masquerade_ipv4_unregister_notifier(); 246 + } 247 + 248 + module_init(nft_masq_module_init); 249 + module_exit(nft_masq_module_exit); 106 250 107 251 MODULE_LICENSE("GPL"); 108 252 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 253 + MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq"); 254 + MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
-2
net/netfilter/nft_nat.c
··· 21 21 #include <linux/netfilter/nf_tables.h> 22 22 #include <net/netfilter/nf_conntrack.h> 23 23 #include <net/netfilter/nf_nat.h> 24 - #include <net/netfilter/nf_nat_core.h> 25 24 #include <net/netfilter/nf_tables.h> 26 - #include <net/netfilter/nf_nat_l3proto.h> 27 25 #include <net/ip.h> 28 26 29 27 struct nft_nat {
+142 -12
net/netfilter/nft_redir.c
··· 13 13 #include <linux/netfilter.h> 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_nat.h> 16 + #include <net/netfilter/nf_nat_redirect.h> 16 17 #include <net/netfilter/nf_tables.h> 17 - #include <net/netfilter/nft_redir.h> 18 18 19 - const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = { 19 + struct nft_redir { 20 + enum nft_registers sreg_proto_min:8; 21 + enum nft_registers sreg_proto_max:8; 22 + u16 flags; 23 + }; 24 + 25 + static const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = { 20 26 [NFTA_REDIR_REG_PROTO_MIN] = { .type = NLA_U32 }, 21 27 [NFTA_REDIR_REG_PROTO_MAX] = { .type = NLA_U32 }, 22 28 [NFTA_REDIR_FLAGS] = { .type = NLA_U32 }, 23 29 }; 24 - EXPORT_SYMBOL_GPL(nft_redir_policy); 25 30 26 - int nft_redir_validate(const struct nft_ctx *ctx, 27 - const struct nft_expr *expr, 28 - const struct nft_data **data) 31 + static int nft_redir_validate(const struct nft_ctx *ctx, 32 + const struct nft_expr *expr, 33 + const struct nft_data **data) 29 34 { 30 35 int err; 31 36 ··· 42 37 (1 << NF_INET_PRE_ROUTING) | 43 38 (1 << NF_INET_LOCAL_OUT)); 44 39 } 45 - EXPORT_SYMBOL_GPL(nft_redir_validate); 46 40 47 - int nft_redir_init(const struct nft_ctx *ctx, 48 - const struct nft_expr *expr, 49 - const struct nlattr * const tb[]) 41 + static int nft_redir_init(const struct nft_ctx *ctx, 42 + const struct nft_expr *expr, 43 + const struct nlattr * const tb[]) 50 44 { 51 45 struct nft_redir *priv = nft_expr_priv(expr); 52 46 unsigned int plen; ··· 81 77 82 78 return nf_ct_netns_get(ctx->net, ctx->family); 83 79 } 84 - EXPORT_SYMBOL_GPL(nft_redir_init); 85 80 86 81 int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr) 87 82 { ··· 104 101 nla_put_failure: 105 102 return -1; 106 103 } 107 - EXPORT_SYMBOL_GPL(nft_redir_dump); 104 + 105 + static void nft_redir_ipv4_eval(const struct nft_expr *expr, 106 + struct nft_regs *regs, 107 + const struct nft_pktinfo *pkt) 108 + { 109 + struct nft_redir *priv = nft_expr_priv(expr); 110 + struct nf_nat_ipv4_multi_range_compat mr; 111 + 112 + memset(&mr, 0, sizeof(mr)); 113 + if (priv->sreg_proto_min) { 114 + mr.range[0].min.all = (__force __be16)nft_reg_load16( 115 + &regs->data[priv->sreg_proto_min]); 116 + mr.range[0].max.all = (__force __be16)nft_reg_load16( 117 + &regs->data[priv->sreg_proto_max]); 118 + mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 119 + } 120 + 121 + mr.range[0].flags |= priv->flags; 122 + 123 + regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt)); 124 + } 125 + 126 + static void 127 + nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 128 + { 129 + nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 130 + } 131 + 132 + static struct nft_expr_type nft_redir_ipv4_type; 133 + static const struct nft_expr_ops nft_redir_ipv4_ops = { 134 + .type = &nft_redir_ipv4_type, 135 + .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 136 + .eval = nft_redir_ipv4_eval, 137 + .init = nft_redir_init, 138 + .destroy = nft_redir_ipv4_destroy, 139 + .dump = nft_redir_dump, 140 + .validate = nft_redir_validate, 141 + }; 142 + 143 + static struct nft_expr_type nft_redir_ipv4_type __read_mostly = { 144 + .family = NFPROTO_IPV4, 145 + .name = "redir", 146 + .ops = &nft_redir_ipv4_ops, 147 + .policy = nft_redir_policy, 148 + .maxattr = NFTA_REDIR_MAX, 149 + .owner = THIS_MODULE, 150 + }; 151 + 152 + #ifdef CONFIG_NF_TABLES_IPV6 153 + static void nft_redir_ipv6_eval(const struct nft_expr *expr, 154 + struct nft_regs *regs, 155 + const struct nft_pktinfo *pkt) 156 + { 157 + struct nft_redir *priv = nft_expr_priv(expr); 158 + struct nf_nat_range2 range; 159 + 160 + memset(&range, 0, sizeof(range)); 161 + if (priv->sreg_proto_min) { 162 + range.min_proto.all = (__force __be16)nft_reg_load16( 163 + &regs->data[priv->sreg_proto_min]); 164 + range.max_proto.all = (__force __be16)nft_reg_load16( 165 + &regs->data[priv->sreg_proto_max]); 166 + range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 167 + } 168 + 169 + range.flags |= priv->flags; 170 + 171 + regs->verdict.code = 172 + nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt)); 173 + } 174 + 175 + static void 176 + nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 177 + { 178 + nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 179 + } 180 + 181 + static struct nft_expr_type nft_redir_ipv6_type; 182 + static const struct nft_expr_ops nft_redir_ipv6_ops = { 183 + .type = &nft_redir_ipv6_type, 184 + .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 185 + .eval = nft_redir_ipv6_eval, 186 + .init = nft_redir_init, 187 + .destroy = nft_redir_ipv6_destroy, 188 + .dump = nft_redir_dump, 189 + .validate = nft_redir_validate, 190 + }; 191 + 192 + static struct nft_expr_type nft_redir_ipv6_type __read_mostly = { 193 + .family = NFPROTO_IPV6, 194 + .name = "redir", 195 + .ops = &nft_redir_ipv6_ops, 196 + .policy = nft_redir_policy, 197 + .maxattr = NFTA_REDIR_MAX, 198 + .owner = THIS_MODULE, 199 + }; 200 + #endif 201 + 202 + static int __init nft_redir_module_init(void) 203 + { 204 + int ret = nft_register_expr(&nft_redir_ipv4_type); 205 + 206 + if (ret) 207 + return ret; 208 + 209 + #ifdef CONFIG_NF_TABLES_IPV6 210 + ret = nft_register_expr(&nft_redir_ipv6_type); 211 + if (ret) { 212 + nft_unregister_expr(&nft_redir_ipv4_type); 213 + return ret; 214 + } 215 + #endif 216 + 217 + return ret; 218 + } 219 + 220 + static void __exit nft_redir_module_exit(void) 221 + { 222 + nft_unregister_expr(&nft_redir_ipv4_type); 223 + #ifdef CONFIG_NF_TABLES_IPV6 224 + nft_unregister_expr(&nft_redir_ipv6_type); 225 + #endif 226 + } 227 + 228 + module_init(nft_redir_module_init); 229 + module_exit(nft_redir_module_exit); 108 230 109 231 MODULE_LICENSE("GPL"); 110 232 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 233 + MODULE_ALIAS_NFT_AF_EXPR(AF_INET4, "redir"); 234 + MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
+22 -16
net/netfilter/nft_set_hash.c
··· 442 442 return ERR_PTR(-ENOENT); 443 443 } 444 444 445 - /* nft_hash_select_ops() makes sure key size can be either 2 or 4 bytes . */ 446 - static inline u32 nft_hash_key(const u32 *key, u32 klen) 447 - { 448 - if (klen == 4) 449 - return *key; 450 - 451 - return *(u16 *)key; 452 - } 453 - 454 445 static bool nft_hash_lookup_fast(const struct net *net, 455 446 const struct nft_set *set, 456 447 const u32 *key, const struct nft_set_ext **ext) ··· 451 460 const struct nft_hash_elem *he; 452 461 u32 hash, k1, k2; 453 462 454 - k1 = nft_hash_key(key, set->klen); 463 + k1 = *key; 455 464 hash = jhash_1word(k1, priv->seed); 456 465 hash = reciprocal_scale(hash, priv->buckets); 457 466 hlist_for_each_entry_rcu(he, &priv->table[hash], node) { 458 - k2 = nft_hash_key(nft_set_ext_key(&he->ext)->data, set->klen); 467 + k2 = *(u32 *)nft_set_ext_key(&he->ext)->data; 459 468 if (k1 == k2 && 460 469 nft_set_elem_active(&he->ext, genmask)) { 461 470 *ext = &he->ext; ··· 463 472 } 464 473 } 465 474 return false; 475 + } 476 + 477 + static u32 nft_jhash(const struct nft_set *set, const struct nft_hash *priv, 478 + const struct nft_set_ext *ext) 479 + { 480 + const struct nft_data *key = nft_set_ext_key(ext); 481 + u32 hash, k1; 482 + 483 + if (set->klen == 4) { 484 + k1 = *(u32 *)key; 485 + hash = jhash_1word(k1, priv->seed); 486 + } else { 487 + hash = jhash(key, set->klen, priv->seed); 488 + } 489 + hash = reciprocal_scale(hash, priv->buckets); 490 + 491 + return hash; 466 492 } 467 493 468 494 static int nft_hash_insert(const struct net *net, const struct nft_set *set, ··· 491 483 u8 genmask = nft_genmask_next(net); 492 484 u32 hash; 493 485 494 - hash = jhash(nft_set_ext_key(&this->ext), set->klen, priv->seed); 495 - hash = reciprocal_scale(hash, priv->buckets); 486 + hash = nft_jhash(set, priv, &this->ext); 496 487 hlist_for_each_entry(he, &priv->table[hash], node) { 497 488 if (!memcmp(nft_set_ext_key(&this->ext), 498 489 nft_set_ext_key(&he->ext), set->klen) && ··· 530 523 u8 genmask = nft_genmask_next(net); 531 524 u32 hash; 532 525 533 - hash = jhash(nft_set_ext_key(&this->ext), set->klen, priv->seed); 534 - hash = reciprocal_scale(hash, priv->buckets); 526 + hash = nft_jhash(set, priv, &this->ext); 535 527 hlist_for_each_entry(he, &priv->table[hash], node) { 536 - if (!memcmp(nft_set_ext_key(&this->ext), &elem->key.val, 528 + if (!memcmp(nft_set_ext_key(&he->ext), &elem->key.val, 537 529 set->klen) && 538 530 nft_set_elem_active(&he->ext, genmask)) { 539 531 nft_set_elem_change_active(net, set, &he->ext);
+7
net/netfilter/nft_tunnel.c
··· 406 406 return -ENOMEM; 407 407 408 408 memcpy(&md->u.tun_info, &info, sizeof(info)); 409 + #ifdef CONFIG_DST_CACHE 410 + err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL); 411 + if (err < 0) { 412 + metadata_dst_free(md); 413 + return err; 414 + } 415 + #endif 409 416 ip_tunnel_info_opts_set(&md->u.tun_info, &priv->opts.u, priv->opts.len, 410 417 priv->opts.flags); 411 418 priv->md = md;
+2 -2
net/netfilter/x_tables.c
··· 461 461 EXPORT_SYMBOL(xt_check_proc_name); 462 462 463 463 int xt_check_match(struct xt_mtchk_param *par, 464 - unsigned int size, u_int8_t proto, bool inv_proto) 464 + unsigned int size, u16 proto, bool inv_proto) 465 465 { 466 466 int ret; 467 467 ··· 984 984 EXPORT_SYMBOL(xt_find_jump_offset); 985 985 986 986 int xt_check_target(struct xt_tgchk_param *par, 987 - unsigned int size, u_int8_t proto, bool inv_proto) 987 + unsigned int size, u16 proto, bool inv_proto) 988 988 { 989 989 int ret; 990 990
+4 -10
net/netfilter/xt_IDLETIMER.c
··· 41 41 #include <linux/workqueue.h> 42 42 #include <linux/sysfs.h> 43 43 44 - struct idletimer_tg_attr { 45 - struct attribute attr; 46 - ssize_t (*show)(struct kobject *kobj, 47 - struct attribute *attr, char *buf); 48 - }; 49 - 50 44 struct idletimer_tg { 51 45 struct list_head entry; 52 46 struct timer_list timer; 53 47 struct work_struct work; 54 48 55 49 struct kobject *kobj; 56 - struct idletimer_tg_attr attr; 50 + struct device_attribute attr; 57 51 58 52 unsigned int refcnt; 59 53 }; ··· 70 76 return NULL; 71 77 } 72 78 73 - static ssize_t idletimer_tg_show(struct kobject *kobj, struct attribute *attr, 74 - char *buf) 79 + static ssize_t idletimer_tg_show(struct device *dev, 80 + struct device_attribute *attr, char *buf) 75 81 { 76 82 struct idletimer_tg *timer; 77 83 unsigned long expires = 0; 78 84 79 85 mutex_lock(&list_mutex); 80 86 81 - timer = __idletimer_tg_find_by_label(attr->name); 87 + timer = __idletimer_tg_find_by_label(attr->attr.name); 82 88 if (timer) 83 89 expires = timer->timer.expires; 84 90
+1 -1
net/netfilter/xt_nat.c
··· 14 14 #include <linux/skbuff.h> 15 15 #include <linux/netfilter.h> 16 16 #include <linux/netfilter/x_tables.h> 17 - #include <net/netfilter/nf_nat_core.h> 17 + #include <net/netfilter/nf_nat.h> 18 18 19 19 static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) 20 20 {
-2
net/openvswitch/Kconfig
··· 8 8 depends on !NF_CONNTRACK || \ 9 9 (NF_CONNTRACK && ((!NF_DEFRAG_IPV6 || NF_DEFRAG_IPV6) && \ 10 10 (!NF_NAT || NF_NAT) && \ 11 - (!NF_NAT_IPV4 || NF_NAT_IPV4) && \ 12 - (!NF_NAT_IPV6 || NF_NAT_IPV6) && \ 13 11 (!NETFILTER_CONNCOUNT || NETFILTER_CONNCOUNT))) 14 12 select LIBCRC32C 15 13 select MPLS
+5 -7
net/openvswitch/conntrack.c
··· 29 29 #include <net/ipv6_frag.h> 30 30 31 31 #ifdef CONFIG_NF_NAT_NEEDED 32 - #include <linux/netfilter/nf_nat.h> 33 - #include <net/netfilter/nf_nat_core.h> 34 - #include <net/netfilter/nf_nat_l3proto.h> 32 + #include <net/netfilter/nf_nat.h> 35 33 #endif 36 34 37 35 #include "datapath.h" ··· 743 745 switch (ctinfo) { 744 746 case IP_CT_RELATED: 745 747 case IP_CT_RELATED_REPLY: 746 - if (IS_ENABLED(CONFIG_NF_NAT_IPV4) && 748 + if (IS_ENABLED(CONFIG_NF_NAT) && 747 749 skb->protocol == htons(ETH_P_IP) && 748 750 ip_hdr(skb)->protocol == IPPROTO_ICMP) { 749 751 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 750 752 hooknum)) 751 753 err = NF_DROP; 752 754 goto push; 753 - } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) && 755 + } else if (IS_ENABLED(CONFIG_IPV6) && 754 756 skb->protocol == htons(ETH_P_IPV6)) { 755 757 __be16 frag_off; 756 758 u8 nexthdr = ipv6_hdr(skb)->nexthdr; ··· 1671 1673 } 1672 1674 1673 1675 if (info->range.flags & NF_NAT_RANGE_MAP_IPS) { 1674 - if (IS_ENABLED(CONFIG_NF_NAT_IPV4) && 1676 + if (IS_ENABLED(CONFIG_NF_NAT) && 1675 1677 info->family == NFPROTO_IPV4) { 1676 1678 if (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MIN, 1677 1679 info->range.min_addr.ip) || ··· 1680 1682 (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MAX, 1681 1683 info->range.max_addr.ip)))) 1682 1684 return false; 1683 - } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) && 1685 + } else if (IS_ENABLED(CONFIG_IPV6) && 1684 1686 info->family == NFPROTO_IPV6) { 1685 1687 if (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MIN, 1686 1688 &info->range.min_addr.in6) ||
+1 -2
tools/testing/selftests/net/config
··· 17 17 CONFIG_NETFILTER=y 18 18 CONFIG_NETFILTER_ADVANCED=y 19 19 CONFIG_NF_CONNTRACK=m 20 - CONFIG_NF_NAT_IPV6=m 21 - CONFIG_NF_NAT_IPV4=m 20 + CONFIG_NF_NAT=m 22 21 CONFIG_IP6_NF_IPTABLES=m 23 22 CONFIG_IP_NF_IPTABLES=m 24 23 CONFIG_IP6_NF_NAT=m