diff options
32 files changed, 699 insertions, 440 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 576d7f0bed5d..615b20b58545 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* IP Virtual Server |
2 | * IP Virtual Server | 2 | * data structure and functionality definitions |
3 | * data structure and functionality definitions | ||
4 | */ | 3 | */ |
5 | 4 | ||
6 | #ifndef _NET_IP_VS_H | 5 | #ifndef _NET_IP_VS_H |
@@ -12,7 +11,7 @@ | |||
12 | 11 | ||
13 | #include <linux/list.h> /* for struct list_head */ | 12 | #include <linux/list.h> /* for struct list_head */ |
14 | #include <linux/spinlock.h> /* for struct rwlock_t */ | 13 | #include <linux/spinlock.h> /* for struct rwlock_t */ |
15 | #include <linux/atomic.h> /* for struct atomic_t */ | 14 | #include <linux/atomic.h> /* for struct atomic_t */ |
16 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
17 | #include <linux/timer.h> | 16 | #include <linux/timer.h> |
18 | #include <linux/bug.h> | 17 | #include <linux/bug.h> |
@@ -30,15 +29,13 @@ | |||
30 | #endif | 29 | #endif |
31 | #include <net/net_namespace.h> /* Netw namespace */ | 30 | #include <net/net_namespace.h> /* Netw namespace */ |
32 | 31 | ||
33 | /* | 32 | /* Generic access of ipvs struct */ |
34 | * Generic access of ipvs struct | ||
35 | */ | ||
36 | static inline struct netns_ipvs *net_ipvs(struct net* net) | 33 | static inline struct netns_ipvs *net_ipvs(struct net* net) |
37 | { | 34 | { |
38 | return net->ipvs; | 35 | return net->ipvs; |
39 | } | 36 | } |
40 | /* | 37 | |
41 | * Get net ptr from skb in traffic cases | 38 | /* Get net ptr from skb in traffic cases |
42 | * use skb_sknet when call is from userland (ioctl or netlink) | 39 | * use skb_sknet when call is from userland (ioctl or netlink) |
43 | */ | 40 | */ |
44 | static inline struct net *skb_net(const struct sk_buff *skb) | 41 | static inline struct net *skb_net(const struct sk_buff *skb) |
@@ -90,8 +87,8 @@ static inline struct net *skb_sknet(const struct sk_buff *skb) | |||
90 | return &init_net; | 87 | return &init_net; |
91 | #endif | 88 | #endif |
92 | } | 89 | } |
93 | /* | 90 | |
94 | * This one needed for single_open_net since net is stored directly in | 91 | /* This one needed for single_open_net since net is stored directly in |
95 | * private not as a struct i.e. seq_file_net can't be used. | 92 | * private not as a struct i.e. seq_file_net can't be used. |
96 | */ | 93 | */ |
97 | static inline struct net *seq_file_single_net(struct seq_file *seq) | 94 | static inline struct net *seq_file_single_net(struct seq_file *seq) |
@@ -108,7 +105,7 @@ extern int ip_vs_conn_tab_size; | |||
108 | 105 | ||
109 | struct ip_vs_iphdr { | 106 | struct ip_vs_iphdr { |
110 | __u32 len; /* IPv4 simply where L4 starts | 107 | __u32 len; /* IPv4 simply where L4 starts |
111 | IPv6 where L4 Transport Header starts */ | 108 | * IPv6 where L4 Transport Header starts */ |
112 | __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ | 109 | __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ |
113 | __s16 protocol; | 110 | __s16 protocol; |
114 | __s32 flags; | 111 | __s32 flags; |
@@ -304,16 +301,11 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len, | |||
304 | #define LeaveFunction(level) do {} while (0) | 301 | #define LeaveFunction(level) do {} while (0) |
305 | #endif | 302 | #endif |
306 | 303 | ||
307 | 304 | /* The port number of FTP service (in network order). */ | |
308 | /* | ||
309 | * The port number of FTP service (in network order). | ||
310 | */ | ||
311 | #define FTPPORT cpu_to_be16(21) | 305 | #define FTPPORT cpu_to_be16(21) |
312 | #define FTPDATA cpu_to_be16(20) | 306 | #define FTPDATA cpu_to_be16(20) |
313 | 307 | ||
314 | /* | 308 | /* TCP State Values */ |
315 | * TCP State Values | ||
316 | */ | ||
317 | enum { | 309 | enum { |
318 | IP_VS_TCP_S_NONE = 0, | 310 | IP_VS_TCP_S_NONE = 0, |
319 | IP_VS_TCP_S_ESTABLISHED, | 311 | IP_VS_TCP_S_ESTABLISHED, |
@@ -329,25 +321,19 @@ enum { | |||
329 | IP_VS_TCP_S_LAST | 321 | IP_VS_TCP_S_LAST |
330 | }; | 322 | }; |
331 | 323 | ||
332 | /* | 324 | /* UDP State Values */ |
333 | * UDP State Values | ||
334 | */ | ||
335 | enum { | 325 | enum { |
336 | IP_VS_UDP_S_NORMAL, | 326 | IP_VS_UDP_S_NORMAL, |
337 | IP_VS_UDP_S_LAST, | 327 | IP_VS_UDP_S_LAST, |
338 | }; | 328 | }; |
339 | 329 | ||
340 | /* | 330 | /* ICMP State Values */ |
341 | * ICMP State Values | ||
342 | */ | ||
343 | enum { | 331 | enum { |
344 | IP_VS_ICMP_S_NORMAL, | 332 | IP_VS_ICMP_S_NORMAL, |
345 | IP_VS_ICMP_S_LAST, | 333 | IP_VS_ICMP_S_LAST, |
346 | }; | 334 | }; |
347 | 335 | ||
348 | /* | 336 | /* SCTP State Values */ |
349 | * SCTP State Values | ||
350 | */ | ||
351 | enum ip_vs_sctp_states { | 337 | enum ip_vs_sctp_states { |
352 | IP_VS_SCTP_S_NONE, | 338 | IP_VS_SCTP_S_NONE, |
353 | IP_VS_SCTP_S_INIT1, | 339 | IP_VS_SCTP_S_INIT1, |
@@ -366,21 +352,18 @@ enum ip_vs_sctp_states { | |||
366 | IP_VS_SCTP_S_LAST | 352 | IP_VS_SCTP_S_LAST |
367 | }; | 353 | }; |
368 | 354 | ||
369 | /* | 355 | /* Delta sequence info structure |
370 | * Delta sequence info structure | 356 | * Each ip_vs_conn has 2 (output AND input seq. changes). |
371 | * Each ip_vs_conn has 2 (output AND input seq. changes). | 357 | * Only used in the VS/NAT. |
372 | * Only used in the VS/NAT. | ||
373 | */ | 358 | */ |
374 | struct ip_vs_seq { | 359 | struct ip_vs_seq { |
375 | __u32 init_seq; /* Add delta from this seq */ | 360 | __u32 init_seq; /* Add delta from this seq */ |
376 | __u32 delta; /* Delta in sequence numbers */ | 361 | __u32 delta; /* Delta in sequence numbers */ |
377 | __u32 previous_delta; /* Delta in sequence numbers | 362 | __u32 previous_delta; /* Delta in sequence numbers |
378 | before last resized pkt */ | 363 | * before last resized pkt */ |
379 | }; | 364 | }; |
380 | 365 | ||
381 | /* | 366 | /* counters per cpu */ |
382 | * counters per cpu | ||
383 | */ | ||
384 | struct ip_vs_counters { | 367 | struct ip_vs_counters { |
385 | __u32 conns; /* connections scheduled */ | 368 | __u32 conns; /* connections scheduled */ |
386 | __u32 inpkts; /* incoming packets */ | 369 | __u32 inpkts; /* incoming packets */ |
@@ -388,17 +371,13 @@ struct ip_vs_counters { | |||
388 | __u64 inbytes; /* incoming bytes */ | 371 | __u64 inbytes; /* incoming bytes */ |
389 | __u64 outbytes; /* outgoing bytes */ | 372 | __u64 outbytes; /* outgoing bytes */ |
390 | }; | 373 | }; |
391 | /* | 374 | /* Stats per cpu */ |
392 | * Stats per cpu | ||
393 | */ | ||
394 | struct ip_vs_cpu_stats { | 375 | struct ip_vs_cpu_stats { |
395 | struct ip_vs_counters ustats; | 376 | struct ip_vs_counters ustats; |
396 | struct u64_stats_sync syncp; | 377 | struct u64_stats_sync syncp; |
397 | }; | 378 | }; |
398 | 379 | ||
399 | /* | 380 | /* IPVS statistics objects */ |
400 | * IPVS statistics objects | ||
401 | */ | ||
402 | struct ip_vs_estimator { | 381 | struct ip_vs_estimator { |
403 | struct list_head list; | 382 | struct list_head list; |
404 | 383 | ||
@@ -491,9 +470,7 @@ struct ip_vs_protocol { | |||
491 | void (*timeout_change)(struct ip_vs_proto_data *pd, int flags); | 470 | void (*timeout_change)(struct ip_vs_proto_data *pd, int flags); |
492 | }; | 471 | }; |
493 | 472 | ||
494 | /* | 473 | /* protocol data per netns */ |
495 | * protocol data per netns | ||
496 | */ | ||
497 | struct ip_vs_proto_data { | 474 | struct ip_vs_proto_data { |
498 | struct ip_vs_proto_data *next; | 475 | struct ip_vs_proto_data *next; |
499 | struct ip_vs_protocol *pp; | 476 | struct ip_vs_protocol *pp; |
@@ -520,9 +497,7 @@ struct ip_vs_conn_param { | |||
520 | __u8 pe_data_len; | 497 | __u8 pe_data_len; |
521 | }; | 498 | }; |
522 | 499 | ||
523 | /* | 500 | /* IP_VS structure allocated for each dynamically scheduled connection */ |
524 | * IP_VS structure allocated for each dynamically scheduled connection | ||
525 | */ | ||
526 | struct ip_vs_conn { | 501 | struct ip_vs_conn { |
527 | struct hlist_node c_list; /* hashed list heads */ | 502 | struct hlist_node c_list; /* hashed list heads */ |
528 | /* Protocol, addresses and port numbers */ | 503 | /* Protocol, addresses and port numbers */ |
@@ -561,17 +536,18 @@ struct ip_vs_conn { | |||
561 | struct ip_vs_dest *dest; /* real server */ | 536 | struct ip_vs_dest *dest; /* real server */ |
562 | atomic_t in_pkts; /* incoming packet counter */ | 537 | atomic_t in_pkts; /* incoming packet counter */ |
563 | 538 | ||
564 | /* packet transmitter for different forwarding methods. If it | 539 | /* Packet transmitter for different forwarding methods. If it |
565 | mangles the packet, it must return NF_DROP or better NF_STOLEN, | 540 | * mangles the packet, it must return NF_DROP or better NF_STOLEN, |
566 | otherwise this must be changed to a sk_buff **. | 541 | * otherwise this must be changed to a sk_buff **. |
567 | NF_ACCEPT can be returned when destination is local. | 542 | * NF_ACCEPT can be returned when destination is local. |
568 | */ | 543 | */ |
569 | int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp, | 544 | int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp, |
570 | struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); | 545 | struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); |
571 | 546 | ||
572 | /* Note: we can group the following members into a structure, | 547 | /* Note: we can group the following members into a structure, |
573 | in order to save more space, and the following members are | 548 | * in order to save more space, and the following members are |
574 | only used in VS/NAT anyway */ | 549 | * only used in VS/NAT anyway |
550 | */ | ||
575 | struct ip_vs_app *app; /* bound ip_vs_app object */ | 551 | struct ip_vs_app *app; /* bound ip_vs_app object */ |
576 | void *app_data; /* Application private data */ | 552 | void *app_data; /* Application private data */ |
577 | struct ip_vs_seq in_seq; /* incoming seq. struct */ | 553 | struct ip_vs_seq in_seq; /* incoming seq. struct */ |
@@ -584,9 +560,7 @@ struct ip_vs_conn { | |||
584 | struct rcu_head rcu_head; | 560 | struct rcu_head rcu_head; |
585 | }; | 561 | }; |
586 | 562 | ||
587 | /* | 563 | /* To save some memory in conn table when name space is disabled. */ |
588 | * To save some memory in conn table when name space is disabled. | ||
589 | */ | ||
590 | static inline struct net *ip_vs_conn_net(const struct ip_vs_conn *cp) | 564 | static inline struct net *ip_vs_conn_net(const struct ip_vs_conn *cp) |
591 | { | 565 | { |
592 | #ifdef CONFIG_NET_NS | 566 | #ifdef CONFIG_NET_NS |
@@ -595,6 +569,7 @@ static inline struct net *ip_vs_conn_net(const struct ip_vs_conn *cp) | |||
595 | return &init_net; | 569 | return &init_net; |
596 | #endif | 570 | #endif |
597 | } | 571 | } |
572 | |||
598 | static inline void ip_vs_conn_net_set(struct ip_vs_conn *cp, struct net *net) | 573 | static inline void ip_vs_conn_net_set(struct ip_vs_conn *cp, struct net *net) |
599 | { | 574 | { |
600 | #ifdef CONFIG_NET_NS | 575 | #ifdef CONFIG_NET_NS |
@@ -612,13 +587,12 @@ static inline int ip_vs_conn_net_eq(const struct ip_vs_conn *cp, | |||
612 | #endif | 587 | #endif |
613 | } | 588 | } |
614 | 589 | ||
615 | /* | 590 | /* Extended internal versions of struct ip_vs_service_user and ip_vs_dest_user |
616 | * Extended internal versions of struct ip_vs_service_user and | 591 | * for IPv6 support. |
617 | * ip_vs_dest_user for IPv6 support. | ||
618 | * | 592 | * |
619 | * We need these to conveniently pass around service and destination | 593 | * We need these to conveniently pass around service and destination |
620 | * options, but unfortunately, we also need to keep the old definitions to | 594 | * options, but unfortunately, we also need to keep the old definitions to |
621 | * maintain userspace backwards compatibility for the setsockopt interface. | 595 | * maintain userspace backwards compatibility for the setsockopt interface. |
622 | */ | 596 | */ |
623 | struct ip_vs_service_user_kern { | 597 | struct ip_vs_service_user_kern { |
624 | /* virtual service addresses */ | 598 | /* virtual service addresses */ |
@@ -656,8 +630,8 @@ struct ip_vs_dest_user_kern { | |||
656 | 630 | ||
657 | 631 | ||
658 | /* | 632 | /* |
659 | * The information about the virtual service offered to the net | 633 | * The information about the virtual service offered to the net and the |
660 | * and the forwarding entries | 634 | * forwarding entries. |
661 | */ | 635 | */ |
662 | struct ip_vs_service { | 636 | struct ip_vs_service { |
663 | struct hlist_node s_list; /* for normal service table */ | 637 | struct hlist_node s_list; /* for normal service table */ |
@@ -697,9 +671,8 @@ struct ip_vs_dest_dst { | |||
697 | struct rcu_head rcu_head; | 671 | struct rcu_head rcu_head; |
698 | }; | 672 | }; |
699 | 673 | ||
700 | /* | 674 | /* The real server destination forwarding entry with ip address, port number, |
701 | * The real server destination forwarding entry | 675 | * and so on. |
702 | * with ip address, port number, and so on. | ||
703 | */ | 676 | */ |
704 | struct ip_vs_dest { | 677 | struct ip_vs_dest { |
705 | struct list_head n_list; /* for the dests in the service */ | 678 | struct list_head n_list; /* for the dests in the service */ |
@@ -738,10 +711,7 @@ struct ip_vs_dest { | |||
738 | unsigned int in_rs_table:1; /* we are in rs_table */ | 711 | unsigned int in_rs_table:1; /* we are in rs_table */ |
739 | }; | 712 | }; |
740 | 713 | ||
741 | 714 | /* The scheduler object */ | |
742 | /* | ||
743 | * The scheduler object | ||
744 | */ | ||
745 | struct ip_vs_scheduler { | 715 | struct ip_vs_scheduler { |
746 | struct list_head n_list; /* d-linked list head */ | 716 | struct list_head n_list; /* d-linked list head */ |
747 | char *name; /* scheduler name */ | 717 | char *name; /* scheduler name */ |
@@ -781,9 +751,7 @@ struct ip_vs_pe { | |||
781 | int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf); | 751 | int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf); |
782 | }; | 752 | }; |
783 | 753 | ||
784 | /* | 754 | /* The application module object (a.k.a. app incarnation) */ |
785 | * The application module object (a.k.a. app incarnation) | ||
786 | */ | ||
787 | struct ip_vs_app { | 755 | struct ip_vs_app { |
788 | struct list_head a_list; /* member in app list */ | 756 | struct list_head a_list; /* member in app list */ |
789 | int type; /* IP_VS_APP_TYPE_xxx */ | 757 | int type; /* IP_VS_APP_TYPE_xxx */ |
@@ -799,16 +767,14 @@ struct ip_vs_app { | |||
799 | atomic_t usecnt; /* usage counter */ | 767 | atomic_t usecnt; /* usage counter */ |
800 | struct rcu_head rcu_head; | 768 | struct rcu_head rcu_head; |
801 | 769 | ||
802 | /* | 770 | /* output hook: Process packet in inout direction, diff set for TCP. |
803 | * output hook: Process packet in inout direction, diff set for TCP. | ||
804 | * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok, | 771 | * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok, |
805 | * 2=Mangled but checksum was not updated | 772 | * 2=Mangled but checksum was not updated |
806 | */ | 773 | */ |
807 | int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *, | 774 | int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *, |
808 | struct sk_buff *, int *diff); | 775 | struct sk_buff *, int *diff); |
809 | 776 | ||
810 | /* | 777 | /* input hook: Process packet in outin direction, diff set for TCP. |
811 | * input hook: Process packet in outin direction, diff set for TCP. | ||
812 | * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok, | 778 | * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok, |
813 | * 2=Mangled but checksum was not updated | 779 | * 2=Mangled but checksum was not updated |
814 | */ | 780 | */ |
@@ -867,9 +833,7 @@ struct ipvs_master_sync_state { | |||
867 | struct netns_ipvs { | 833 | struct netns_ipvs { |
868 | int gen; /* Generation */ | 834 | int gen; /* Generation */ |
869 | int enable; /* enable like nf_hooks do */ | 835 | int enable; /* enable like nf_hooks do */ |
870 | /* | 836 | /* Hash table: for real service lookups */ |
871 | * Hash table: for real service lookups | ||
872 | */ | ||
873 | #define IP_VS_RTAB_BITS 4 | 837 | #define IP_VS_RTAB_BITS 4 |
874 | #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS) | 838 | #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS) |
875 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) | 839 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) |
@@ -903,7 +867,7 @@ struct netns_ipvs { | |||
903 | struct list_head sctp_apps[SCTP_APP_TAB_SIZE]; | 867 | struct list_head sctp_apps[SCTP_APP_TAB_SIZE]; |
904 | #endif | 868 | #endif |
905 | /* ip_vs_conn */ | 869 | /* ip_vs_conn */ |
906 | atomic_t conn_count; /* connection counter */ | 870 | atomic_t conn_count; /* connection counter */ |
907 | 871 | ||
908 | /* ip_vs_ctl */ | 872 | /* ip_vs_ctl */ |
909 | struct ip_vs_stats tot_stats; /* Statistics & est. */ | 873 | struct ip_vs_stats tot_stats; /* Statistics & est. */ |
@@ -990,9 +954,9 @@ struct netns_ipvs { | |||
990 | char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | 954 | char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; |
991 | /* net name space ptr */ | 955 | /* net name space ptr */ |
992 | struct net *net; /* Needed by timer routines */ | 956 | struct net *net; /* Needed by timer routines */ |
993 | /* Number of heterogeneous destinations, needed because | 957 | /* Number of heterogeneous destinations, needed becaus heterogeneous |
994 | * heterogeneous are not supported when synchronization is | 958 | * are not supported when synchronization is enabled. |
995 | * enabled */ | 959 | */ |
996 | unsigned int mixed_address_family_dests; | 960 | unsigned int mixed_address_family_dests; |
997 | }; | 961 | }; |
998 | 962 | ||
@@ -1147,9 +1111,8 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs) | |||
1147 | 1111 | ||
1148 | #endif | 1112 | #endif |
1149 | 1113 | ||
1150 | /* | 1114 | /* IPVS core functions |
1151 | * IPVS core functions | 1115 | * (from ip_vs_core.c) |
1152 | * (from ip_vs_core.c) | ||
1153 | */ | 1116 | */ |
1154 | const char *ip_vs_proto_name(unsigned int proto); | 1117 | const char *ip_vs_proto_name(unsigned int proto); |
1155 | void ip_vs_init_hash_table(struct list_head *table, int rows); | 1118 | void ip_vs_init_hash_table(struct list_head *table, int rows); |
@@ -1157,11 +1120,9 @@ void ip_vs_init_hash_table(struct list_head *table, int rows); | |||
1157 | 1120 | ||
1158 | #define IP_VS_APP_TYPE_FTP 1 | 1121 | #define IP_VS_APP_TYPE_FTP 1 |
1159 | 1122 | ||
1160 | /* | 1123 | /* ip_vs_conn handling functions |
1161 | * ip_vs_conn handling functions | 1124 | * (from ip_vs_conn.c) |
1162 | * (from ip_vs_conn.c) | ||
1163 | */ | 1125 | */ |
1164 | |||
1165 | enum { | 1126 | enum { |
1166 | IP_VS_DIR_INPUT = 0, | 1127 | IP_VS_DIR_INPUT = 0, |
1167 | IP_VS_DIR_OUTPUT, | 1128 | IP_VS_DIR_OUTPUT, |
@@ -1292,9 +1253,7 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) | |||
1292 | atomic_inc(&ctl_cp->n_control); | 1253 | atomic_inc(&ctl_cp->n_control); |
1293 | } | 1254 | } |
1294 | 1255 | ||
1295 | /* | 1256 | /* IPVS netns init & cleanup functions */ |
1296 | * IPVS netns init & cleanup functions | ||
1297 | */ | ||
1298 | int ip_vs_estimator_net_init(struct net *net); | 1257 | int ip_vs_estimator_net_init(struct net *net); |
1299 | int ip_vs_control_net_init(struct net *net); | 1258 | int ip_vs_control_net_init(struct net *net); |
1300 | int ip_vs_protocol_net_init(struct net *net); | 1259 | int ip_vs_protocol_net_init(struct net *net); |
@@ -1309,9 +1268,8 @@ void ip_vs_estimator_net_cleanup(struct net *net); | |||
1309 | void ip_vs_sync_net_cleanup(struct net *net); | 1268 | void ip_vs_sync_net_cleanup(struct net *net); |
1310 | void ip_vs_service_net_cleanup(struct net *net); | 1269 | void ip_vs_service_net_cleanup(struct net *net); |
1311 | 1270 | ||
1312 | /* | 1271 | /* IPVS application functions |
1313 | * IPVS application functions | 1272 | * (from ip_vs_app.c) |
1314 | * (from ip_vs_app.c) | ||
1315 | */ | 1273 | */ |
1316 | #define IP_VS_APP_MAX_PORTS 8 | 1274 | #define IP_VS_APP_MAX_PORTS 8 |
1317 | struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app); | 1275 | struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app); |
@@ -1331,9 +1289,7 @@ int unregister_ip_vs_pe(struct ip_vs_pe *pe); | |||
1331 | struct ip_vs_pe *ip_vs_pe_getbyname(const char *name); | 1289 | struct ip_vs_pe *ip_vs_pe_getbyname(const char *name); |
1332 | struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name); | 1290 | struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name); |
1333 | 1291 | ||
1334 | /* | 1292 | /* Use a #define to avoid all of module.h just for these trivial ops */ |
1335 | * Use a #define to avoid all of module.h just for these trivial ops | ||
1336 | */ | ||
1337 | #define ip_vs_pe_get(pe) \ | 1293 | #define ip_vs_pe_get(pe) \ |
1338 | if (pe && pe->module) \ | 1294 | if (pe && pe->module) \ |
1339 | __module_get(pe->module); | 1295 | __module_get(pe->module); |
@@ -1342,9 +1298,7 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name); | |||
1342 | if (pe && pe->module) \ | 1298 | if (pe && pe->module) \ |
1343 | module_put(pe->module); | 1299 | module_put(pe->module); |
1344 | 1300 | ||
1345 | /* | 1301 | /* IPVS protocol functions (from ip_vs_proto.c) */ |
1346 | * IPVS protocol functions (from ip_vs_proto.c) | ||
1347 | */ | ||
1348 | int ip_vs_protocol_init(void); | 1302 | int ip_vs_protocol_init(void); |
1349 | void ip_vs_protocol_cleanup(void); | 1303 | void ip_vs_protocol_cleanup(void); |
1350 | void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags); | 1304 | void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags); |
@@ -1362,9 +1316,8 @@ extern struct ip_vs_protocol ip_vs_protocol_esp; | |||
1362 | extern struct ip_vs_protocol ip_vs_protocol_ah; | 1316 | extern struct ip_vs_protocol ip_vs_protocol_ah; |
1363 | extern struct ip_vs_protocol ip_vs_protocol_sctp; | 1317 | extern struct ip_vs_protocol ip_vs_protocol_sctp; |
1364 | 1318 | ||
1365 | /* | 1319 | /* Registering/unregistering scheduler functions |
1366 | * Registering/unregistering scheduler functions | 1320 | * (from ip_vs_sched.c) |
1367 | * (from ip_vs_sched.c) | ||
1368 | */ | 1321 | */ |
1369 | int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); | 1322 | int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); |
1370 | int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); | 1323 | int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler); |
@@ -1383,10 +1336,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, | |||
1383 | 1336 | ||
1384 | void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); | 1337 | void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); |
1385 | 1338 | ||
1386 | 1339 | /* IPVS control data and functions (from ip_vs_ctl.c) */ | |
1387 | /* | ||
1388 | * IPVS control data and functions (from ip_vs_ctl.c) | ||
1389 | */ | ||
1390 | extern struct ip_vs_stats ip_vs_stats; | 1340 | extern struct ip_vs_stats ip_vs_stats; |
1391 | extern int sysctl_ip_vs_sync_ver; | 1341 | extern int sysctl_ip_vs_sync_ver; |
1392 | 1342 | ||
@@ -1427,26 +1377,21 @@ static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest) | |||
1427 | kfree(dest); | 1377 | kfree(dest); |
1428 | } | 1378 | } |
1429 | 1379 | ||
1430 | /* | 1380 | /* IPVS sync daemon data and function prototypes |
1431 | * IPVS sync daemon data and function prototypes | 1381 | * (from ip_vs_sync.c) |
1432 | * (from ip_vs_sync.c) | ||
1433 | */ | 1382 | */ |
1434 | int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid); | 1383 | int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid); |
1435 | int stop_sync_thread(struct net *net, int state); | 1384 | int stop_sync_thread(struct net *net, int state); |
1436 | void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); | 1385 | void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); |
1437 | 1386 | ||
1438 | /* | 1387 | /* IPVS rate estimator prototypes (from ip_vs_est.c) */ |
1439 | * IPVS rate estimator prototypes (from ip_vs_est.c) | ||
1440 | */ | ||
1441 | void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); | 1388 | void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats); |
1442 | void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); | 1389 | void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats); |
1443 | void ip_vs_zero_estimator(struct ip_vs_stats *stats); | 1390 | void ip_vs_zero_estimator(struct ip_vs_stats *stats); |
1444 | void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | 1391 | void ip_vs_read_estimator(struct ip_vs_stats_user *dst, |
1445 | struct ip_vs_stats *stats); | 1392 | struct ip_vs_stats *stats); |
1446 | 1393 | ||
1447 | /* | 1394 | /* Various IPVS packet transmitters (from ip_vs_xmit.c) */ |
1448 | * Various IPVS packet transmitters (from ip_vs_xmit.c) | ||
1449 | */ | ||
1450 | int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 1395 | int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
1451 | struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); | 1396 | struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); |
1452 | int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 1397 | int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
@@ -1477,12 +1422,10 @@ int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
1477 | #endif | 1422 | #endif |
1478 | 1423 | ||
1479 | #ifdef CONFIG_SYSCTL | 1424 | #ifdef CONFIG_SYSCTL |
1480 | /* | 1425 | /* This is a simple mechanism to ignore packets when |
1481 | * This is a simple mechanism to ignore packets when | 1426 | * we are loaded. Just set ip_vs_drop_rate to 'n' and |
1482 | * we are loaded. Just set ip_vs_drop_rate to 'n' and | 1427 | * we start to drop 1/rate of the packets |
1483 | * we start to drop 1/rate of the packets | ||
1484 | */ | 1428 | */ |
1485 | |||
1486 | static inline int ip_vs_todrop(struct netns_ipvs *ipvs) | 1429 | static inline int ip_vs_todrop(struct netns_ipvs *ipvs) |
1487 | { | 1430 | { |
1488 | if (!ipvs->drop_rate) | 1431 | if (!ipvs->drop_rate) |
@@ -1496,9 +1439,7 @@ static inline int ip_vs_todrop(struct netns_ipvs *ipvs) | |||
1496 | static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; } | 1439 | static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; } |
1497 | #endif | 1440 | #endif |
1498 | 1441 | ||
1499 | /* | 1442 | /* ip_vs_fwd_tag returns the forwarding tag of the connection */ |
1500 | * ip_vs_fwd_tag returns the forwarding tag of the connection | ||
1501 | */ | ||
1502 | #define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK) | 1443 | #define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK) |
1503 | 1444 | ||
1504 | static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) | 1445 | static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) |
@@ -1557,9 +1498,7 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum) | |||
1557 | return csum_partial(diff, sizeof(diff), oldsum); | 1498 | return csum_partial(diff, sizeof(diff), oldsum); |
1558 | } | 1499 | } |
1559 | 1500 | ||
1560 | /* | 1501 | /* Forget current conntrack (unconfirmed) and attach notrack entry */ |
1561 | * Forget current conntrack (unconfirmed) and attach notrack entry | ||
1562 | */ | ||
1563 | static inline void ip_vs_notrack(struct sk_buff *skb) | 1502 | static inline void ip_vs_notrack(struct sk_buff *skb) |
1564 | { | 1503 | { |
1565 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | 1504 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) |
@@ -1576,9 +1515,8 @@ static inline void ip_vs_notrack(struct sk_buff *skb) | |||
1576 | } | 1515 | } |
1577 | 1516 | ||
1578 | #ifdef CONFIG_IP_VS_NFCT | 1517 | #ifdef CONFIG_IP_VS_NFCT |
1579 | /* | 1518 | /* Netfilter connection tracking |
1580 | * Netfilter connection tracking | 1519 | * (from ip_vs_nfct.c) |
1581 | * (from ip_vs_nfct.c) | ||
1582 | */ | 1520 | */ |
1583 | static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs) | 1521 | static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs) |
1584 | { | 1522 | { |
@@ -1617,14 +1555,12 @@ static inline int ip_vs_confirm_conntrack(struct sk_buff *skb) | |||
1617 | static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp) | 1555 | static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp) |
1618 | { | 1556 | { |
1619 | } | 1557 | } |
1620 | /* CONFIG_IP_VS_NFCT */ | 1558 | #endif /* CONFIG_IP_VS_NFCT */ |
1621 | #endif | ||
1622 | 1559 | ||
1623 | static inline int | 1560 | static inline int |
1624 | ip_vs_dest_conn_overhead(struct ip_vs_dest *dest) | 1561 | ip_vs_dest_conn_overhead(struct ip_vs_dest *dest) |
1625 | { | 1562 | { |
1626 | /* | 1563 | /* We think the overhead of processing active connections is 256 |
1627 | * We think the overhead of processing active connections is 256 | ||
1628 | * times higher than that of inactive connections in average. (This | 1564 | * times higher than that of inactive connections in average. (This |
1629 | * 256 times might not be accurate, we will change it later) We | 1565 | * 256 times might not be accurate, we will change it later) We |
1630 | * use the following formula to estimate the overhead now: | 1566 | * use the following formula to estimate the overhead now: |
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h new file mode 100644 index 000000000000..2aa6048a55c1 --- /dev/null +++ b/include/net/netfilter/br_netfilter.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _BR_NETFILTER_H_ | ||
2 | #define _BR_NETFILTER_H_ | ||
3 | |||
4 | void br_netfilter_enable(void); | ||
5 | |||
6 | #endif /* _BR_NETFILTER_H_ */ | ||
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h index f713b5a31d62..e8427193c777 100644 --- a/include/net/netfilter/ipv4/nf_reject.h +++ b/include/net/netfilter/ipv4/nf_reject.h | |||
@@ -1,128 +1,13 @@ | |||
1 | #ifndef _IPV4_NF_REJECT_H | 1 | #ifndef _IPV4_NF_REJECT_H |
2 | #define _IPV4_NF_REJECT_H | 2 | #define _IPV4_NF_REJECT_H |
3 | 3 | ||
4 | #include <net/ip.h> | 4 | #include <net/icmp.h> |
5 | #include <net/tcp.h> | ||
6 | #include <net/route.h> | ||
7 | #include <net/dst.h> | ||
8 | 5 | ||
9 | static inline void nf_send_unreach(struct sk_buff *skb_in, int code) | 6 | static inline void nf_send_unreach(struct sk_buff *skb_in, int code) |
10 | { | 7 | { |
11 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | 8 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); |
12 | } | 9 | } |
13 | 10 | ||
14 | /* Send RST reply */ | 11 | void nf_send_reset(struct sk_buff *oldskb, int hook); |
15 | static void nf_send_reset(struct sk_buff *oldskb, int hook) | ||
16 | { | ||
17 | struct sk_buff *nskb; | ||
18 | const struct iphdr *oiph; | ||
19 | struct iphdr *niph; | ||
20 | const struct tcphdr *oth; | ||
21 | struct tcphdr _otcph, *tcph; | ||
22 | |||
23 | /* IP header checks: fragment. */ | ||
24 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | ||
25 | return; | ||
26 | |||
27 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | ||
28 | sizeof(_otcph), &_otcph); | ||
29 | if (oth == NULL) | ||
30 | return; | ||
31 | |||
32 | /* No RST for RST. */ | ||
33 | if (oth->rst) | ||
34 | return; | ||
35 | |||
36 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
37 | return; | ||
38 | |||
39 | /* Check checksum */ | ||
40 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | ||
41 | return; | ||
42 | oiph = ip_hdr(oldskb); | ||
43 | |||
44 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
45 | LL_MAX_HEADER, GFP_ATOMIC); | ||
46 | if (!nskb) | ||
47 | return; | ||
48 | |||
49 | skb_reserve(nskb, LL_MAX_HEADER); | ||
50 | |||
51 | skb_reset_network_header(nskb); | ||
52 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); | ||
53 | niph->version = 4; | ||
54 | niph->ihl = sizeof(struct iphdr) / 4; | ||
55 | niph->tos = 0; | ||
56 | niph->id = 0; | ||
57 | niph->frag_off = htons(IP_DF); | ||
58 | niph->protocol = IPPROTO_TCP; | ||
59 | niph->check = 0; | ||
60 | niph->saddr = oiph->daddr; | ||
61 | niph->daddr = oiph->saddr; | ||
62 | |||
63 | skb_reset_transport_header(nskb); | ||
64 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | ||
65 | memset(tcph, 0, sizeof(*tcph)); | ||
66 | tcph->source = oth->dest; | ||
67 | tcph->dest = oth->source; | ||
68 | tcph->doff = sizeof(struct tcphdr) / 4; | ||
69 | |||
70 | if (oth->ack) | ||
71 | tcph->seq = oth->ack_seq; | ||
72 | else { | ||
73 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + | ||
74 | oldskb->len - ip_hdrlen(oldskb) - | ||
75 | (oth->doff << 2)); | ||
76 | tcph->ack = 1; | ||
77 | } | ||
78 | |||
79 | tcph->rst = 1; | ||
80 | tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr, | ||
81 | niph->daddr, 0); | ||
82 | nskb->ip_summed = CHECKSUM_PARTIAL; | ||
83 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | ||
84 | nskb->csum_offset = offsetof(struct tcphdr, check); | ||
85 | |||
86 | /* ip_route_me_harder expects skb->dst to be set */ | ||
87 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | ||
88 | |||
89 | nskb->protocol = htons(ETH_P_IP); | ||
90 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) | ||
91 | goto free_nskb; | ||
92 | |||
93 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | ||
94 | |||
95 | /* "Never happens" */ | ||
96 | if (nskb->len > dst_mtu(skb_dst(nskb))) | ||
97 | goto free_nskb; | ||
98 | |||
99 | nf_ct_attach(nskb, oldskb); | ||
100 | |||
101 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | ||
102 | /* If we use ip_local_out for bridged traffic, the MAC source on | ||
103 | * the RST will be ours, instead of the destination's. This confuses | ||
104 | * some routers/firewalls, and they drop the packet. So we need to | ||
105 | * build the eth header using the original destination's MAC as the | ||
106 | * source, and send the RST packet directly. | ||
107 | */ | ||
108 | if (oldskb->nf_bridge) { | ||
109 | struct ethhdr *oeth = eth_hdr(oldskb); | ||
110 | nskb->dev = oldskb->nf_bridge->physindev; | ||
111 | niph->tot_len = htons(nskb->len); | ||
112 | ip_send_check(niph); | ||
113 | if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), | ||
114 | oeth->h_source, oeth->h_dest, nskb->len) < 0) | ||
115 | goto free_nskb; | ||
116 | dev_queue_xmit(nskb); | ||
117 | } else | ||
118 | #endif | ||
119 | ip_local_out(nskb); | ||
120 | |||
121 | return; | ||
122 | |||
123 | free_nskb: | ||
124 | kfree_skb(nskb); | ||
125 | } | ||
126 | |||
127 | 12 | ||
128 | #endif /* _IPV4_NF_REJECT_H */ | 13 | #endif /* _IPV4_NF_REJECT_H */ |
diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h index 36b0da2d55bb..60fa1530006b 100644 --- a/include/net/netfilter/nft_reject.h +++ b/include/net/netfilter/nft_reject.h | |||
@@ -14,12 +14,7 @@ int nft_reject_init(const struct nft_ctx *ctx, | |||
14 | 14 | ||
15 | int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr); | 15 | int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr); |
16 | 16 | ||
17 | void nft_reject_ipv4_eval(const struct nft_expr *expr, | 17 | int nft_reject_icmp_code(u8 code); |
18 | struct nft_data data[NFT_REG_MAX + 1], | 18 | int nft_reject_icmpv6_code(u8 code); |
19 | const struct nft_pktinfo *pkt); | ||
20 | |||
21 | void nft_reject_ipv6_eval(const struct nft_expr *expr, | ||
22 | struct nft_data data[NFT_REG_MAX + 1], | ||
23 | const struct nft_pktinfo *pkt); | ||
24 | 19 | ||
25 | #endif | 20 | #endif |
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index b72ccfeaf865..c26df6787fb0 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h | |||
@@ -749,13 +749,34 @@ enum nft_queue_attributes { | |||
749 | * | 749 | * |
750 | * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable | 750 | * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable |
751 | * @NFT_REJECT_TCP_RST: reject using TCP RST | 751 | * @NFT_REJECT_TCP_RST: reject using TCP RST |
752 | * @NFT_REJECT_ICMPX_UNREACH: abstracted ICMP unreachable for bridge and inet | ||
752 | */ | 753 | */ |
753 | enum nft_reject_types { | 754 | enum nft_reject_types { |
754 | NFT_REJECT_ICMP_UNREACH, | 755 | NFT_REJECT_ICMP_UNREACH, |
755 | NFT_REJECT_TCP_RST, | 756 | NFT_REJECT_TCP_RST, |
757 | NFT_REJECT_ICMPX_UNREACH, | ||
756 | }; | 758 | }; |
757 | 759 | ||
758 | /** | 760 | /** |
761 | * enum nft_reject_code - Generic reject codes for IPv4/IPv6 | ||
762 | * | ||
763 | * @NFT_REJECT_ICMPX_NO_ROUTE: no route to host / network unreachable | ||
764 | * @NFT_REJECT_ICMPX_PORT_UNREACH: port unreachable | ||
765 | * @NFT_REJECT_ICMPX_HOST_UNREACH: host unreachable | ||
766 | * @NFT_REJECT_ICMPX_ADMIN_PROHIBITED: administratively prohibited | ||
767 | * | ||
768 | * These codes are mapped to real ICMP and ICMPv6 codes. | ||
769 | */ | ||
770 | enum nft_reject_inet_code { | ||
771 | NFT_REJECT_ICMPX_NO_ROUTE = 0, | ||
772 | NFT_REJECT_ICMPX_PORT_UNREACH, | ||
773 | NFT_REJECT_ICMPX_HOST_UNREACH, | ||
774 | NFT_REJECT_ICMPX_ADMIN_PROHIBITED, | ||
775 | __NFT_REJECT_ICMPX_MAX | ||
776 | }; | ||
777 | #define NFT_REJECT_ICMPX_MAX (__NFT_REJECT_ICMPX_MAX + 1) | ||
778 | |||
779 | /** | ||
759 | * enum nft_reject_attributes - nf_tables reject expression netlink attributes | 780 | * enum nft_reject_attributes - nf_tables reject expression netlink attributes |
760 | * | 781 | * |
761 | * @NFTA_REJECT_TYPE: packet type to use (NLA_U32: nft_reject_types) | 782 | * @NFTA_REJECT_TYPE: packet type to use (NLA_U32: nft_reject_types) |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 97e43937aaca..fa1270cc5086 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -856,6 +856,11 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops, | |||
856 | return NF_ACCEPT; | 856 | return NF_ACCEPT; |
857 | } | 857 | } |
858 | 858 | ||
859 | void br_netfilter_enable(void) | ||
860 | { | ||
861 | } | ||
862 | EXPORT_SYMBOL_GPL(br_netfilter_enable); | ||
863 | |||
859 | /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because | 864 | /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because |
860 | * br_dev_queue_push_xmit is called afterwards */ | 865 | * br_dev_queue_push_xmit is called afterwards */ |
861 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { | 866 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { |
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 5bcc0d8b31f2..da17a5eab8b4 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c | |||
@@ -34,9 +34,11 @@ static struct nft_af_info nft_af_bridge __read_mostly = { | |||
34 | .owner = THIS_MODULE, | 34 | .owner = THIS_MODULE, |
35 | .nops = 1, | 35 | .nops = 1, |
36 | .hooks = { | 36 | .hooks = { |
37 | [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, | ||
37 | [NF_BR_LOCAL_IN] = nft_do_chain_bridge, | 38 | [NF_BR_LOCAL_IN] = nft_do_chain_bridge, |
38 | [NF_BR_FORWARD] = nft_do_chain_bridge, | 39 | [NF_BR_FORWARD] = nft_do_chain_bridge, |
39 | [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, | 40 | [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, |
41 | [NF_BR_POST_ROUTING] = nft_do_chain_bridge, | ||
40 | }, | 42 | }, |
41 | }; | 43 | }; |
42 | 44 | ||
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index ee3ffe93e14e..a76479535df2 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -14,21 +14,106 @@ | |||
14 | #include <linux/netfilter/nf_tables.h> | 14 | #include <linux/netfilter/nf_tables.h> |
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nft_reject.h> | 16 | #include <net/netfilter/nft_reject.h> |
17 | #include <net/netfilter/ipv4/nf_reject.h> | ||
18 | #include <net/netfilter/ipv6/nf_reject.h> | ||
17 | 19 | ||
18 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 20 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
19 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_data data[NFT_REG_MAX + 1], |
20 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
21 | { | 23 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | ||
25 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
26 | |||
22 | switch (eth_hdr(pkt->skb)->h_proto) { | 27 | switch (eth_hdr(pkt->skb)->h_proto) { |
23 | case htons(ETH_P_IP): | 28 | case htons(ETH_P_IP): |
24 | return nft_reject_ipv4_eval(expr, data, pkt); | 29 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | ||
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
32 | break; | ||
33 | case NFT_REJECT_TCP_RST: | ||
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
35 | break; | ||
36 | case NFT_REJECT_ICMPX_UNREACH: | ||
37 | nf_send_unreach(pkt->skb, | ||
38 | nft_reject_icmp_code(priv->icmp_code)); | ||
39 | break; | ||
40 | } | ||
41 | break; | ||
25 | case htons(ETH_P_IPV6): | 42 | case htons(ETH_P_IPV6): |
26 | return nft_reject_ipv6_eval(expr, data, pkt); | 43 | switch (priv->type) { |
44 | case NFT_REJECT_ICMP_UNREACH: | ||
45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
46 | pkt->ops->hooknum); | ||
47 | break; | ||
48 | case NFT_REJECT_TCP_RST: | ||
49 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
50 | break; | ||
51 | case NFT_REJECT_ICMPX_UNREACH: | ||
52 | nf_send_unreach6(net, pkt->skb, | ||
53 | nft_reject_icmpv6_code(priv->icmp_code), | ||
54 | pkt->ops->hooknum); | ||
55 | break; | ||
56 | } | ||
57 | break; | ||
27 | default: | 58 | default: |
28 | /* No explicit way to reject this protocol, drop it. */ | 59 | /* No explicit way to reject this protocol, drop it. */ |
29 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
30 | break; | 60 | break; |
31 | } | 61 | } |
62 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
63 | } | ||
64 | |||
65 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | ||
66 | const struct nft_expr *expr, | ||
67 | const struct nlattr * const tb[]) | ||
68 | { | ||
69 | struct nft_reject *priv = nft_expr_priv(expr); | ||
70 | int icmp_code; | ||
71 | |||
72 | if (tb[NFTA_REJECT_TYPE] == NULL) | ||
73 | return -EINVAL; | ||
74 | |||
75 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | ||
76 | switch (priv->type) { | ||
77 | case NFT_REJECT_ICMP_UNREACH: | ||
78 | case NFT_REJECT_ICMPX_UNREACH: | ||
79 | if (tb[NFTA_REJECT_ICMP_CODE] == NULL) | ||
80 | return -EINVAL; | ||
81 | |||
82 | icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]); | ||
83 | if (priv->type == NFT_REJECT_ICMPX_UNREACH && | ||
84 | icmp_code > NFT_REJECT_ICMPX_MAX) | ||
85 | return -EINVAL; | ||
86 | |||
87 | priv->icmp_code = icmp_code; | ||
88 | break; | ||
89 | case NFT_REJECT_TCP_RST: | ||
90 | break; | ||
91 | default: | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int nft_reject_bridge_dump(struct sk_buff *skb, | ||
98 | const struct nft_expr *expr) | ||
99 | { | ||
100 | const struct nft_reject *priv = nft_expr_priv(expr); | ||
101 | |||
102 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) | ||
103 | goto nla_put_failure; | ||
104 | |||
105 | switch (priv->type) { | ||
106 | case NFT_REJECT_ICMP_UNREACH: | ||
107 | case NFT_REJECT_ICMPX_UNREACH: | ||
108 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | ||
109 | goto nla_put_failure; | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | |||
115 | nla_put_failure: | ||
116 | return -1; | ||
32 | } | 117 | } |
33 | 118 | ||
34 | static struct nft_expr_type nft_reject_bridge_type; | 119 | static struct nft_expr_type nft_reject_bridge_type; |
@@ -36,8 +121,8 @@ static const struct nft_expr_ops nft_reject_bridge_ops = { | |||
36 | .type = &nft_reject_bridge_type, | 121 | .type = &nft_reject_bridge_type, |
37 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | 122 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), |
38 | .eval = nft_reject_bridge_eval, | 123 | .eval = nft_reject_bridge_eval, |
39 | .init = nft_reject_init, | 124 | .init = nft_reject_bridge_init, |
40 | .dump = nft_reject_dump, | 125 | .dump = nft_reject_bridge_dump, |
41 | }; | 126 | }; |
42 | 127 | ||
43 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | 128 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 28916e47f959..9a423e2c5766 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -572,7 +572,7 @@ static void skb_release_head_state(struct sk_buff *skb) | |||
572 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 572 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
573 | nf_conntrack_put(skb->nfct); | 573 | nf_conntrack_put(skb->nfct); |
574 | #endif | 574 | #endif |
575 | #ifdef CONFIG_BRIDGE_NETFILTER | 575 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
576 | nf_bridge_put(skb->nf_bridge); | 576 | nf_bridge_put(skb->nf_bridge); |
577 | #endif | 577 | #endif |
578 | /* XXX: IS this still necessary? - JHS */ | 578 | /* XXX: IS this still necessary? - JHS */ |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c8fa62476461..e35b71289156 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -516,7 +516,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
516 | 516 | ||
517 | hlen = iph->ihl * 4; | 517 | hlen = iph->ihl * 4; |
518 | mtu = mtu - hlen; /* Size of data space */ | 518 | mtu = mtu - hlen; /* Size of data space */ |
519 | #ifdef CONFIG_BRIDGE_NETFILTER | 519 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
520 | if (skb->nf_bridge) | 520 | if (skb->nf_bridge) |
521 | mtu -= nf_bridge_mtu_reduction(skb); | 521 | mtu -= nf_bridge_mtu_reduction(skb); |
522 | #endif | 522 | #endif |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 345242a79db6..4c019d5c3f57 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -61,8 +61,13 @@ config NFT_CHAIN_ROUTE_IPV4 | |||
61 | fields such as the source, destination, type of service and | 61 | fields such as the source, destination, type of service and |
62 | the packet mark. | 62 | the packet mark. |
63 | 63 | ||
64 | config NF_REJECT_IPV4 | ||
65 | tristate "IPv4 packet rejection" | ||
66 | default m if NETFILTER_ADVANCED=n | ||
67 | |||
64 | config NFT_REJECT_IPV4 | 68 | config NFT_REJECT_IPV4 |
65 | depends on NF_TABLES_IPV4 | 69 | depends on NF_TABLES_IPV4 |
70 | select NF_REJECT_IPV4 | ||
66 | default NFT_REJECT | 71 | default NFT_REJECT |
67 | tristate | 72 | tristate |
68 | 73 | ||
@@ -208,6 +213,7 @@ config IP_NF_FILTER | |||
208 | config IP_NF_TARGET_REJECT | 213 | config IP_NF_TARGET_REJECT |
209 | tristate "REJECT target support" | 214 | tristate "REJECT target support" |
210 | depends on IP_NF_FILTER | 215 | depends on IP_NF_FILTER |
216 | select NF_REJECT_IPV4 | ||
211 | default m if NETFILTER_ADVANCED=n | 217 | default m if NETFILTER_ADVANCED=n |
212 | help | 218 | help |
213 | The REJECT target allows a filtering rule to specify that an ICMP | 219 | The REJECT target allows a filtering rule to specify that an ICMP |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 14488cc5fd2c..f4cef5af0969 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -23,6 +23,9 @@ obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o | |||
23 | obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o | 23 | obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o |
24 | obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o | 24 | obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o |
25 | 25 | ||
26 | # reject | ||
27 | obj-$(CONFIG_NF_REJECT_IPV4) += nf_reject_ipv4.o | ||
28 | |||
26 | # NAT helpers (nf_conntrack) | 29 | # NAT helpers (nf_conntrack) |
27 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o | 30 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o |
28 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o | 31 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 5b6e0df4ccff..8f48f5517e33 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/netfilter/x_tables.h> | 20 | #include <linux/netfilter/x_tables.h> |
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter_ipv4/ip_tables.h> |
22 | #include <linux/netfilter_ipv4/ipt_REJECT.h> | 22 | #include <linux/netfilter_ipv4/ipt_REJECT.h> |
23 | #ifdef CONFIG_BRIDGE_NETFILTER | 23 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
24 | #include <linux/netfilter_bridge.h> | 24 | #include <linux/netfilter_bridge.h> |
25 | #endif | 25 | #endif |
26 | 26 | ||
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 76bd1aef257f..7e5ca6f2d0cd 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
@@ -50,7 +50,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, | |||
50 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | 50 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #ifdef CONFIG_BRIDGE_NETFILTER | 53 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
54 | if (skb->nf_bridge && | 54 | if (skb->nf_bridge && |
55 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | 55 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) |
56 | return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; | 56 | return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; |
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c new file mode 100644 index 000000000000..b023b4eb1a96 --- /dev/null +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 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 | */ | ||
8 | |||
9 | #include <net/ip.h> | ||
10 | #include <net/tcp.h> | ||
11 | #include <net/route.h> | ||
12 | #include <net/dst.h> | ||
13 | #include <linux/netfilter_ipv4.h> | ||
14 | |||
15 | /* Send RST reply */ | ||
16 | void nf_send_reset(struct sk_buff *oldskb, int hook) | ||
17 | { | ||
18 | struct sk_buff *nskb; | ||
19 | const struct iphdr *oiph; | ||
20 | struct iphdr *niph; | ||
21 | const struct tcphdr *oth; | ||
22 | struct tcphdr _otcph, *tcph; | ||
23 | |||
24 | /* IP header checks: fragment. */ | ||
25 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | ||
26 | return; | ||
27 | |||
28 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | ||
29 | sizeof(_otcph), &_otcph); | ||
30 | if (oth == NULL) | ||
31 | return; | ||
32 | |||
33 | /* No RST for RST. */ | ||
34 | if (oth->rst) | ||
35 | return; | ||
36 | |||
37 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
38 | return; | ||
39 | |||
40 | /* Check checksum */ | ||
41 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | ||
42 | return; | ||
43 | oiph = ip_hdr(oldskb); | ||
44 | |||
45 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + | ||
46 | LL_MAX_HEADER, GFP_ATOMIC); | ||
47 | if (!nskb) | ||
48 | return; | ||
49 | |||
50 | skb_reserve(nskb, LL_MAX_HEADER); | ||
51 | |||
52 | skb_reset_network_header(nskb); | ||
53 | niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); | ||
54 | niph->version = 4; | ||
55 | niph->ihl = sizeof(struct iphdr) / 4; | ||
56 | niph->tos = 0; | ||
57 | niph->id = 0; | ||
58 | niph->frag_off = htons(IP_DF); | ||
59 | niph->protocol = IPPROTO_TCP; | ||
60 | niph->check = 0; | ||
61 | niph->saddr = oiph->daddr; | ||
62 | niph->daddr = oiph->saddr; | ||
63 | |||
64 | skb_reset_transport_header(nskb); | ||
65 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | ||
66 | memset(tcph, 0, sizeof(*tcph)); | ||
67 | tcph->source = oth->dest; | ||
68 | tcph->dest = oth->source; | ||
69 | tcph->doff = sizeof(struct tcphdr) / 4; | ||
70 | |||
71 | if (oth->ack) | ||
72 | tcph->seq = oth->ack_seq; | ||
73 | else { | ||
74 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + | ||
75 | oldskb->len - ip_hdrlen(oldskb) - | ||
76 | (oth->doff << 2)); | ||
77 | tcph->ack = 1; | ||
78 | } | ||
79 | |||
80 | tcph->rst = 1; | ||
81 | tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr, | ||
82 | niph->daddr, 0); | ||
83 | nskb->ip_summed = CHECKSUM_PARTIAL; | ||
84 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | ||
85 | nskb->csum_offset = offsetof(struct tcphdr, check); | ||
86 | |||
87 | /* ip_route_me_harder expects skb->dst to be set */ | ||
88 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | ||
89 | |||
90 | nskb->protocol = htons(ETH_P_IP); | ||
91 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) | ||
92 | goto free_nskb; | ||
93 | |||
94 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | ||
95 | |||
96 | /* "Never happens" */ | ||
97 | if (nskb->len > dst_mtu(skb_dst(nskb))) | ||
98 | goto free_nskb; | ||
99 | |||
100 | nf_ct_attach(nskb, oldskb); | ||
101 | |||
102 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | ||
103 | /* If we use ip_local_out for bridged traffic, the MAC source on | ||
104 | * the RST will be ours, instead of the destination's. This confuses | ||
105 | * some routers/firewalls, and they drop the packet. So we need to | ||
106 | * build the eth header using the original destination's MAC as the | ||
107 | * source, and send the RST packet directly. | ||
108 | */ | ||
109 | if (oldskb->nf_bridge) { | ||
110 | struct ethhdr *oeth = eth_hdr(oldskb); | ||
111 | nskb->dev = oldskb->nf_bridge->physindev; | ||
112 | niph->tot_len = htons(nskb->len); | ||
113 | ip_send_check(niph); | ||
114 | if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), | ||
115 | oeth->h_source, oeth->h_dest, nskb->len) < 0) | ||
116 | goto free_nskb; | ||
117 | dev_queue_xmit(nskb); | ||
118 | } else | ||
119 | #endif | ||
120 | ip_local_out(nskb); | ||
121 | |||
122 | return; | ||
123 | |||
124 | free_nskb: | ||
125 | kfree_skb(nskb); | ||
126 | } | ||
127 | EXPORT_SYMBOL_GPL(nf_send_reset); | ||
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c index 6ea1d207b6a5..1c636d6b5b50 100644 --- a/net/ipv4/netfilter/nft_masq_ipv4.c +++ b/net/ipv4/netfilter/nft_masq_ipv4.c | |||
@@ -32,33 +32,12 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, | |||
32 | data[NFT_REG_VERDICT].verdict = verdict; | 32 | data[NFT_REG_VERDICT].verdict = verdict; |
33 | } | 33 | } |
34 | 34 | ||
35 | static int nft_masq_ipv4_init(const struct nft_ctx *ctx, | ||
36 | const struct nft_expr *expr, | ||
37 | const struct nlattr * const tb[]) | ||
38 | { | ||
39 | int err; | ||
40 | |||
41 | err = nft_masq_init(ctx, expr, tb); | ||
42 | if (err < 0) | ||
43 | return err; | ||
44 | |||
45 | nf_nat_masquerade_ipv4_register_notifier(); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void nft_masq_ipv4_destroy(const struct nft_ctx *ctx, | ||
50 | const struct nft_expr *expr) | ||
51 | { | ||
52 | nf_nat_masquerade_ipv4_unregister_notifier(); | ||
53 | } | ||
54 | |||
55 | static struct nft_expr_type nft_masq_ipv4_type; | 35 | static struct nft_expr_type nft_masq_ipv4_type; |
56 | static const struct nft_expr_ops nft_masq_ipv4_ops = { | 36 | static const struct nft_expr_ops nft_masq_ipv4_ops = { |
57 | .type = &nft_masq_ipv4_type, | 37 | .type = &nft_masq_ipv4_type, |
58 | .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), | 38 | .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), |
59 | .eval = nft_masq_ipv4_eval, | 39 | .eval = nft_masq_ipv4_eval, |
60 | .init = nft_masq_ipv4_init, | 40 | .init = nft_masq_init, |
61 | .destroy = nft_masq_ipv4_destroy, | ||
62 | .dump = nft_masq_dump, | 41 | .dump = nft_masq_dump, |
63 | }; | 42 | }; |
64 | 43 | ||
@@ -73,12 +52,21 @@ static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { | |||
73 | 52 | ||
74 | static int __init nft_masq_ipv4_module_init(void) | 53 | static int __init nft_masq_ipv4_module_init(void) |
75 | { | 54 | { |
76 | return nft_register_expr(&nft_masq_ipv4_type); | 55 | int ret; |
56 | |||
57 | ret = nft_register_expr(&nft_masq_ipv4_type); | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | |||
61 | nf_nat_masquerade_ipv4_register_notifier(); | ||
62 | |||
63 | return ret; | ||
77 | } | 64 | } |
78 | 65 | ||
79 | static void __exit nft_masq_ipv4_module_exit(void) | 66 | static void __exit nft_masq_ipv4_module_exit(void) |
80 | { | 67 | { |
81 | nft_unregister_expr(&nft_masq_ipv4_type); | 68 | nft_unregister_expr(&nft_masq_ipv4_type); |
69 | nf_nat_masquerade_ipv4_unregister_notifier(); | ||
82 | } | 70 | } |
83 | 71 | ||
84 | module_init(nft_masq_ipv4_module_init); | 72 | module_init(nft_masq_ipv4_module_init); |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index e79718a382f2..ed33299c56d1 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
17 | #include <linux/netfilter/nf_tables.h> | 17 | #include <linux/netfilter/nf_tables.h> |
18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
19 | #include <net/icmp.h> | ||
20 | #include <net/netfilter/ipv4/nf_reject.h> | 19 | #include <net/netfilter/ipv4/nf_reject.h> |
21 | #include <net/netfilter/nft_reject.h> | 20 | #include <net/netfilter/nft_reject.h> |
22 | 21 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index bb1a40db7be1..6af874fc187f 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -40,8 +40,13 @@ config NFT_CHAIN_ROUTE_IPV6 | |||
40 | fields such as the source, destination, flowlabel, hop-limit and | 40 | fields such as the source, destination, flowlabel, hop-limit and |
41 | the packet mark. | 41 | the packet mark. |
42 | 42 | ||
43 | config NF_REJECT_IPV6 | ||
44 | tristate "IPv6 packet rejection" | ||
45 | default m if NETFILTER_ADVANCED=n | ||
46 | |||
43 | config NFT_REJECT_IPV6 | 47 | config NFT_REJECT_IPV6 |
44 | depends on NF_TABLES_IPV6 | 48 | depends on NF_TABLES_IPV6 |
49 | select NF_REJECT_IPV6 | ||
45 | default NFT_REJECT | 50 | default NFT_REJECT |
46 | tristate | 51 | tristate |
47 | 52 | ||
@@ -208,6 +213,7 @@ config IP6_NF_FILTER | |||
208 | config IP6_NF_TARGET_REJECT | 213 | config IP6_NF_TARGET_REJECT |
209 | tristate "REJECT target support" | 214 | tristate "REJECT target support" |
210 | depends on IP6_NF_FILTER | 215 | depends on IP6_NF_FILTER |
216 | select NF_REJECT_IPV6 | ||
211 | default m if NETFILTER_ADVANCED=n | 217 | default m if NETFILTER_ADVANCED=n |
212 | help | 218 | help |
213 | The REJECT target allows a filtering rule to specify that an ICMPv6 | 219 | The REJECT target allows a filtering rule to specify that an ICMPv6 |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 0f7e5b3f328d..fbb25f01143c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -27,6 +27,9 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | |||
27 | # logging | 27 | # logging |
28 | obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o | 28 | obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o |
29 | 29 | ||
30 | # reject | ||
31 | obj-$(CONFIG_NF_REJECT_IPV6) += nf_reject_ipv6.o | ||
32 | |||
30 | # nf_tables | 33 | # nf_tables |
31 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 34 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
32 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 35 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 7b9a748c6bac..e70382e4dfb5 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -40,7 +40,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | |||
40 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | 40 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | #ifdef CONFIG_BRIDGE_NETFILTER | 43 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
44 | if (skb->nf_bridge && | 44 | if (skb->nf_bridge && |
45 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | 45 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) |
46 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; | 46 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c new file mode 100644 index 000000000000..5f5f0438d74d --- /dev/null +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 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 | */ | ||
8 | #include <net/ipv6.h> | ||
9 | #include <net/ip6_route.h> | ||
10 | #include <net/ip6_fib.h> | ||
11 | #include <net/ip6_checksum.h> | ||
12 | #include <linux/netfilter_ipv6.h> | ||
13 | |||
14 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | ||
15 | { | ||
16 | struct sk_buff *nskb; | ||
17 | struct tcphdr otcph, *tcph; | ||
18 | unsigned int otcplen, hh_len; | ||
19 | int tcphoff, needs_ack; | ||
20 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | ||
21 | struct ipv6hdr *ip6h; | ||
22 | #define DEFAULT_TOS_VALUE 0x0U | ||
23 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
24 | struct dst_entry *dst = NULL; | ||
25 | u8 proto; | ||
26 | __be16 frag_off; | ||
27 | struct flowi6 fl6; | ||
28 | |||
29 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
30 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
31 | pr_debug("addr is not unicast.\n"); | ||
32 | return; | ||
33 | } | ||
34 | |||
35 | proto = oip6h->nexthdr; | ||
36 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); | ||
37 | |||
38 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | ||
39 | pr_debug("Cannot get TCP header.\n"); | ||
40 | return; | ||
41 | } | ||
42 | |||
43 | otcplen = oldskb->len - tcphoff; | ||
44 | |||
45 | /* IP header checks: fragment, too short. */ | ||
46 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | ||
47 | pr_debug("proto(%d) != IPPROTO_TCP, " | ||
48 | "or too short. otcplen = %d\n", | ||
49 | proto, otcplen); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) | ||
54 | BUG(); | ||
55 | |||
56 | /* No RST for RST. */ | ||
57 | if (otcph.rst) { | ||
58 | pr_debug("RST is set\n"); | ||
59 | return; | ||
60 | } | ||
61 | |||
62 | /* Check checksum. */ | ||
63 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { | ||
64 | pr_debug("TCP checksum is invalid\n"); | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | memset(&fl6, 0, sizeof(fl6)); | ||
69 | fl6.flowi6_proto = IPPROTO_TCP; | ||
70 | fl6.saddr = oip6h->daddr; | ||
71 | fl6.daddr = oip6h->saddr; | ||
72 | fl6.fl6_sport = otcph.dest; | ||
73 | fl6.fl6_dport = otcph.source; | ||
74 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
75 | dst = ip6_route_output(net, NULL, &fl6); | ||
76 | if (dst == NULL || dst->error) { | ||
77 | dst_release(dst); | ||
78 | return; | ||
79 | } | ||
80 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
81 | if (IS_ERR(dst)) | ||
82 | return; | ||
83 | |||
84 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
85 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
86 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
87 | GFP_ATOMIC); | ||
88 | |||
89 | if (!nskb) { | ||
90 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
91 | dst_release(dst); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | skb_dst_set(nskb, dst); | ||
96 | |||
97 | skb_reserve(nskb, hh_len + dst->header_len); | ||
98 | |||
99 | skb_put(nskb, sizeof(struct ipv6hdr)); | ||
100 | skb_reset_network_header(nskb); | ||
101 | ip6h = ipv6_hdr(nskb); | ||
102 | ip6_flow_hdr(ip6h, tclass, 0); | ||
103 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | ||
104 | ip6h->nexthdr = IPPROTO_TCP; | ||
105 | ip6h->saddr = oip6h->daddr; | ||
106 | ip6h->daddr = oip6h->saddr; | ||
107 | |||
108 | skb_reset_transport_header(nskb); | ||
109 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | ||
110 | /* Truncate to length (no data) */ | ||
111 | tcph->doff = sizeof(struct tcphdr)/4; | ||
112 | tcph->source = otcph.dest; | ||
113 | tcph->dest = otcph.source; | ||
114 | |||
115 | if (otcph.ack) { | ||
116 | needs_ack = 0; | ||
117 | tcph->seq = otcph.ack_seq; | ||
118 | tcph->ack_seq = 0; | ||
119 | } else { | ||
120 | needs_ack = 1; | ||
121 | tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin | ||
122 | + otcplen - (otcph.doff<<2)); | ||
123 | tcph->seq = 0; | ||
124 | } | ||
125 | |||
126 | /* Reset flags */ | ||
127 | ((u_int8_t *)tcph)[13] = 0; | ||
128 | tcph->rst = 1; | ||
129 | tcph->ack = needs_ack; | ||
130 | tcph->window = 0; | ||
131 | tcph->urg_ptr = 0; | ||
132 | tcph->check = 0; | ||
133 | |||
134 | /* Adjust TCP checksum */ | ||
135 | tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, | ||
136 | &ipv6_hdr(nskb)->daddr, | ||
137 | sizeof(struct tcphdr), IPPROTO_TCP, | ||
138 | csum_partial(tcph, | ||
139 | sizeof(struct tcphdr), 0)); | ||
140 | |||
141 | nf_ct_attach(nskb, oldskb); | ||
142 | |||
143 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | ||
144 | /* If we use ip6_local_out for bridged traffic, the MAC source on | ||
145 | * the RST will be ours, instead of the destination's. This confuses | ||
146 | * some routers/firewalls, and they drop the packet. So we need to | ||
147 | * build the eth header using the original destination's MAC as the | ||
148 | * source, and send the RST packet directly. | ||
149 | */ | ||
150 | if (oldskb->nf_bridge) { | ||
151 | struct ethhdr *oeth = eth_hdr(oldskb); | ||
152 | nskb->dev = oldskb->nf_bridge->physindev; | ||
153 | nskb->protocol = htons(ETH_P_IPV6); | ||
154 | ip6h->payload_len = htons(sizeof(struct tcphdr)); | ||
155 | if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), | ||
156 | oeth->h_source, oeth->h_dest, nskb->len) < 0) | ||
157 | return; | ||
158 | dev_queue_xmit(nskb); | ||
159 | } else | ||
160 | #endif | ||
161 | ip6_local_out(nskb); | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(nf_send_reset6); | ||
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c index 4e51334ef6b7..556262f40761 100644 --- a/net/ipv6/netfilter/nft_masq_ipv6.c +++ b/net/ipv6/netfilter/nft_masq_ipv6.c | |||
@@ -32,33 +32,12 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, | |||
32 | data[NFT_REG_VERDICT].verdict = verdict; | 32 | data[NFT_REG_VERDICT].verdict = verdict; |
33 | } | 33 | } |
34 | 34 | ||
35 | static int nft_masq_ipv6_init(const struct nft_ctx *ctx, | ||
36 | const struct nft_expr *expr, | ||
37 | const struct nlattr * const tb[]) | ||
38 | { | ||
39 | int err; | ||
40 | |||
41 | err = nft_masq_init(ctx, expr, tb); | ||
42 | if (err < 0) | ||
43 | return err; | ||
44 | |||
45 | nf_nat_masquerade_ipv6_register_notifier(); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void nft_masq_ipv6_destroy(const struct nft_ctx *ctx, | ||
50 | const struct nft_expr *expr) | ||
51 | { | ||
52 | nf_nat_masquerade_ipv6_unregister_notifier(); | ||
53 | } | ||
54 | |||
55 | static struct nft_expr_type nft_masq_ipv6_type; | 35 | static struct nft_expr_type nft_masq_ipv6_type; |
56 | static const struct nft_expr_ops nft_masq_ipv6_ops = { | 36 | static const struct nft_expr_ops nft_masq_ipv6_ops = { |
57 | .type = &nft_masq_ipv6_type, | 37 | .type = &nft_masq_ipv6_type, |
58 | .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), | 38 | .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), |
59 | .eval = nft_masq_ipv6_eval, | 39 | .eval = nft_masq_ipv6_eval, |
60 | .init = nft_masq_ipv6_init, | 40 | .init = nft_masq_init, |
61 | .destroy = nft_masq_ipv6_destroy, | ||
62 | .dump = nft_masq_dump, | 41 | .dump = nft_masq_dump, |
63 | }; | 42 | }; |
64 | 43 | ||
@@ -73,12 +52,21 @@ static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { | |||
73 | 52 | ||
74 | static int __init nft_masq_ipv6_module_init(void) | 53 | static int __init nft_masq_ipv6_module_init(void) |
75 | { | 54 | { |
76 | return nft_register_expr(&nft_masq_ipv6_type); | 55 | int ret; |
56 | |||
57 | ret = nft_register_expr(&nft_masq_ipv6_type); | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | |||
61 | nf_nat_masquerade_ipv6_register_notifier(); | ||
62 | |||
63 | return ret; | ||
77 | } | 64 | } |
78 | 65 | ||
79 | static void __exit nft_masq_ipv6_module_exit(void) | 66 | static void __exit nft_masq_ipv6_module_exit(void) |
80 | { | 67 | { |
81 | nft_unregister_expr(&nft_masq_ipv6_type); | 68 | nft_unregister_expr(&nft_masq_ipv6_type); |
69 | nf_nat_masquerade_ipv6_unregister_notifier(); | ||
82 | } | 70 | } |
83 | 71 | ||
84 | module_init(nft_masq_ipv6_module_init); | 72 | module_init(nft_masq_ipv6_module_init); |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index 03cdb69ac9bf..35dd35873442 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -237,7 +237,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
237 | #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) | 237 | #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) |
238 | 238 | ||
239 | if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { | 239 | if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { |
240 | #ifdef CONFIG_BRIDGE_NETFILTER | 240 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
241 | const struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 241 | const struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
242 | 242 | ||
243 | if (!nf_bridge) | 243 | if (!nf_bridge) |
@@ -474,7 +474,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
474 | ip6_netmask(&e.ip, e.cidr); | 474 | ip6_netmask(&e.ip, e.cidr); |
475 | 475 | ||
476 | if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { | 476 | if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { |
477 | #ifdef CONFIG_BRIDGE_NETFILTER | 477 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
478 | const struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 478 | const struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
479 | 479 | ||
480 | if (!nf_bridge) | 480 | if (!nf_bridge) |
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c index eeb8ef4ff1a3..a2233e77cf39 100644 --- a/net/netfilter/nf_log_common.c +++ b/net/netfilter/nf_log_common.c | |||
@@ -158,7 +158,7 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf, | |||
158 | '0' + loginfo->u.log.level, prefix, | 158 | '0' + loginfo->u.log.level, prefix, |
159 | in ? in->name : "", | 159 | in ? in->name : "", |
160 | out ? out->name : ""); | 160 | out ? out->name : ""); |
161 | #ifdef CONFIG_BRIDGE_NETFILTER | 161 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
162 | if (skb->nf_bridge) { | 162 | if (skb->nf_bridge) { |
163 | const struct net_device *physindev; | 163 | const struct net_device *physindev; |
164 | const struct net_device *physoutdev; | 164 | const struct net_device *physoutdev; |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5d24b1fdb593..4c8b68e5fa16 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -52,7 +52,7 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry) | |||
52 | dev_put(entry->indev); | 52 | dev_put(entry->indev); |
53 | if (entry->outdev) | 53 | if (entry->outdev) |
54 | dev_put(entry->outdev); | 54 | dev_put(entry->outdev); |
55 | #ifdef CONFIG_BRIDGE_NETFILTER | 55 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
56 | if (entry->skb->nf_bridge) { | 56 | if (entry->skb->nf_bridge) { |
57 | struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; | 57 | struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; |
58 | 58 | ||
@@ -77,7 +77,7 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry) | |||
77 | dev_hold(entry->indev); | 77 | dev_hold(entry->indev); |
78 | if (entry->outdev) | 78 | if (entry->outdev) |
79 | dev_hold(entry->outdev); | 79 | dev_hold(entry->outdev); |
80 | #ifdef CONFIG_BRIDGE_NETFILTER | 80 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
81 | if (entry->skb->nf_bridge) { | 81 | if (entry->skb->nf_bridge) { |
82 | struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; | 82 | struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; |
83 | struct net_device *physdev; | 83 | struct net_device *physdev; |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 19e79f0d9ad2..556a0dfa4abc 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -4163,6 +4163,7 @@ static void __exit nf_tables_module_exit(void) | |||
4163 | { | 4163 | { |
4164 | unregister_pernet_subsys(&nf_tables_net_ops); | 4164 | unregister_pernet_subsys(&nf_tables_net_ops); |
4165 | nfnetlink_subsys_unregister(&nf_tables_subsys); | 4165 | nfnetlink_subsys_unregister(&nf_tables_subsys); |
4166 | rcu_barrier(); | ||
4166 | nf_tables_core_module_exit(); | 4167 | nf_tables_core_module_exit(); |
4167 | kfree(info); | 4168 | kfree(info); |
4168 | } | 4169 | } |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index a11c5ff2f720..b1e3a0579416 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | #include <linux/atomic.h> | 37 | #include <linux/atomic.h> |
38 | 38 | ||
39 | #ifdef CONFIG_BRIDGE_NETFILTER | 39 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
40 | #include "../bridge/br_private.h" | 40 | #include "../bridge/br_private.h" |
41 | #endif | 41 | #endif |
42 | 42 | ||
@@ -429,7 +429,7 @@ __build_packet_message(struct nfnl_log_net *log, | |||
429 | goto nla_put_failure; | 429 | goto nla_put_failure; |
430 | 430 | ||
431 | if (indev) { | 431 | if (indev) { |
432 | #ifndef CONFIG_BRIDGE_NETFILTER | 432 | #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
433 | if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, | 433 | if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, |
434 | htonl(indev->ifindex))) | 434 | htonl(indev->ifindex))) |
435 | goto nla_put_failure; | 435 | goto nla_put_failure; |
@@ -460,7 +460,7 @@ __build_packet_message(struct nfnl_log_net *log, | |||
460 | } | 460 | } |
461 | 461 | ||
462 | if (outdev) { | 462 | if (outdev) { |
463 | #ifndef CONFIG_BRIDGE_NETFILTER | 463 | #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
464 | if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, | 464 | if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, |
465 | htonl(outdev->ifindex))) | 465 | htonl(outdev->ifindex))) |
466 | goto nla_put_failure; | 466 | goto nla_put_failure; |
@@ -640,7 +640,7 @@ nfulnl_log_packet(struct net *net, | |||
640 | + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) | 640 | + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) |
641 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 641 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
642 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 642 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
643 | #ifdef CONFIG_BRIDGE_NETFILTER | 643 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
644 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 644 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
645 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 645 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
646 | #endif | 646 | #endif |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 108120f216b1..a82077d9f59b 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | #include <linux/atomic.h> | 37 | #include <linux/atomic.h> |
38 | 38 | ||
39 | #ifdef CONFIG_BRIDGE_NETFILTER | 39 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
40 | #include "../bridge/br_private.h" | 40 | #include "../bridge/br_private.h" |
41 | #endif | 41 | #endif |
42 | 42 | ||
@@ -302,7 +302,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
302 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) | 302 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) |
303 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 303 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
304 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 304 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
305 | #ifdef CONFIG_BRIDGE_NETFILTER | 305 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
306 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 306 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
307 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ | 307 | + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
308 | #endif | 308 | #endif |
@@ -380,7 +380,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
380 | 380 | ||
381 | indev = entry->indev; | 381 | indev = entry->indev; |
382 | if (indev) { | 382 | if (indev) { |
383 | #ifndef CONFIG_BRIDGE_NETFILTER | 383 | #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
384 | if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex))) | 384 | if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex))) |
385 | goto nla_put_failure; | 385 | goto nla_put_failure; |
386 | #else | 386 | #else |
@@ -410,7 +410,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
410 | } | 410 | } |
411 | 411 | ||
412 | if (outdev) { | 412 | if (outdev) { |
413 | #ifndef CONFIG_BRIDGE_NETFILTER | 413 | #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
414 | if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) | 414 | if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) |
415 | goto nla_put_failure; | 415 | goto nla_put_failure; |
416 | #else | 416 | #else |
@@ -569,7 +569,7 @@ nf_queue_entry_dup(struct nf_queue_entry *e) | |||
569 | return NULL; | 569 | return NULL; |
570 | } | 570 | } |
571 | 571 | ||
572 | #ifdef CONFIG_BRIDGE_NETFILTER | 572 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
573 | /* When called from bridge netfilter, skb->data must point to MAC header | 573 | /* When called from bridge netfilter, skb->data must point to MAC header |
574 | * before calling skb_gso_segment(). Else, original MAC header is lost | 574 | * before calling skb_gso_segment(). Else, original MAC header is lost |
575 | * and segmented skbs will be sent to wrong destination. | 575 | * and segmented skbs will be sent to wrong destination. |
@@ -763,7 +763,7 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) | |||
763 | if (entry->outdev) | 763 | if (entry->outdev) |
764 | if (entry->outdev->ifindex == ifindex) | 764 | if (entry->outdev->ifindex == ifindex) |
765 | return 1; | 765 | return 1; |
766 | #ifdef CONFIG_BRIDGE_NETFILTER | 766 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
767 | if (entry->skb->nf_bridge) { | 767 | if (entry->skb->nf_bridge) { |
768 | if (entry->skb->nf_bridge->physindev && | 768 | if (entry->skb->nf_bridge->physindev && |
769 | entry->skb->nf_bridge->physindev->ifindex == ifindex) | 769 | entry->skb->nf_bridge->physindev->ifindex == ifindex) |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 1840989092ed..7e2683c8a44a 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -101,26 +101,12 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
101 | 101 | ||
102 | static void target_compat_from_user(struct xt_target *t, void *in, void *out) | 102 | static void target_compat_from_user(struct xt_target *t, void *in, void *out) |
103 | { | 103 | { |
104 | #ifdef CONFIG_COMPAT | 104 | int pad; |
105 | if (t->compat_from_user) { | ||
106 | int pad; | ||
107 | |||
108 | t->compat_from_user(out, in); | ||
109 | pad = XT_ALIGN(t->targetsize) - t->targetsize; | ||
110 | if (pad > 0) | ||
111 | memset(out + t->targetsize, 0, pad); | ||
112 | } else | ||
113 | #endif | ||
114 | memcpy(out, in, XT_ALIGN(t->targetsize)); | ||
115 | } | ||
116 | 105 | ||
117 | static inline int nft_compat_target_offset(struct xt_target *target) | 106 | memcpy(out, in, t->targetsize); |
118 | { | 107 | pad = XT_ALIGN(t->targetsize) - t->targetsize; |
119 | #ifdef CONFIG_COMPAT | 108 | if (pad > 0) |
120 | return xt_compat_target_offset(target); | 109 | memset(out + t->targetsize, 0, pad); |
121 | #else | ||
122 | return 0; | ||
123 | #endif | ||
124 | } | 110 | } |
125 | 111 | ||
126 | static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = { | 112 | static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = { |
@@ -208,34 +194,6 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) | |||
208 | module_put(target->me); | 194 | module_put(target->me); |
209 | } | 195 | } |
210 | 196 | ||
211 | static int | ||
212 | target_dump_info(struct sk_buff *skb, const struct xt_target *t, const void *in) | ||
213 | { | ||
214 | int ret; | ||
215 | |||
216 | #ifdef CONFIG_COMPAT | ||
217 | if (t->compat_to_user) { | ||
218 | mm_segment_t old_fs; | ||
219 | void *out; | ||
220 | |||
221 | out = kmalloc(XT_ALIGN(t->targetsize), GFP_ATOMIC); | ||
222 | if (out == NULL) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | /* We want to reuse existing compat_to_user */ | ||
226 | old_fs = get_fs(); | ||
227 | set_fs(KERNEL_DS); | ||
228 | t->compat_to_user(out, in); | ||
229 | set_fs(old_fs); | ||
230 | ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), out); | ||
231 | kfree(out); | ||
232 | } else | ||
233 | #endif | ||
234 | ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), in); | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) | 197 | static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) |
240 | { | 198 | { |
241 | const struct xt_target *target = expr->ops->data; | 199 | const struct xt_target *target = expr->ops->data; |
@@ -243,7 +201,7 @@ static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
243 | 201 | ||
244 | if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) || | 202 | if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) || |
245 | nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) || | 203 | nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) || |
246 | target_dump_info(skb, target, info)) | 204 | nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info)) |
247 | goto nla_put_failure; | 205 | goto nla_put_failure; |
248 | 206 | ||
249 | return 0; | 207 | return 0; |
@@ -341,17 +299,12 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
341 | 299 | ||
342 | static void match_compat_from_user(struct xt_match *m, void *in, void *out) | 300 | static void match_compat_from_user(struct xt_match *m, void *in, void *out) |
343 | { | 301 | { |
344 | #ifdef CONFIG_COMPAT | 302 | int pad; |
345 | if (m->compat_from_user) { | 303 | |
346 | int pad; | 304 | memcpy(out, in, m->matchsize); |
347 | 305 | pad = XT_ALIGN(m->matchsize) - m->matchsize; | |
348 | m->compat_from_user(out, in); | 306 | if (pad > 0) |
349 | pad = XT_ALIGN(m->matchsize) - m->matchsize; | 307 | memset(out + m->matchsize, 0, pad); |
350 | if (pad > 0) | ||
351 | memset(out + m->matchsize, 0, pad); | ||
352 | } else | ||
353 | #endif | ||
354 | memcpy(out, in, XT_ALIGN(m->matchsize)); | ||
355 | } | 308 | } |
356 | 309 | ||
357 | static int | 310 | static int |
@@ -404,43 +357,6 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) | |||
404 | module_put(match->me); | 357 | module_put(match->me); |
405 | } | 358 | } |
406 | 359 | ||
407 | static int | ||
408 | match_dump_info(struct sk_buff *skb, const struct xt_match *m, const void *in) | ||
409 | { | ||
410 | int ret; | ||
411 | |||
412 | #ifdef CONFIG_COMPAT | ||
413 | if (m->compat_to_user) { | ||
414 | mm_segment_t old_fs; | ||
415 | void *out; | ||
416 | |||
417 | out = kmalloc(XT_ALIGN(m->matchsize), GFP_ATOMIC); | ||
418 | if (out == NULL) | ||
419 | return -ENOMEM; | ||
420 | |||
421 | /* We want to reuse existing compat_to_user */ | ||
422 | old_fs = get_fs(); | ||
423 | set_fs(KERNEL_DS); | ||
424 | m->compat_to_user(out, in); | ||
425 | set_fs(old_fs); | ||
426 | ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), out); | ||
427 | kfree(out); | ||
428 | } else | ||
429 | #endif | ||
430 | ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), in); | ||
431 | |||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | static inline int nft_compat_match_offset(struct xt_match *match) | ||
436 | { | ||
437 | #ifdef CONFIG_COMPAT | ||
438 | return xt_compat_match_offset(match); | ||
439 | #else | ||
440 | return 0; | ||
441 | #endif | ||
442 | } | ||
443 | |||
444 | static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr) | 360 | static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr) |
445 | { | 361 | { |
446 | void *info = nft_expr_priv(expr); | 362 | void *info = nft_expr_priv(expr); |
@@ -448,7 +364,7 @@ static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
448 | 364 | ||
449 | if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) || | 365 | if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) || |
450 | nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) || | 366 | nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) || |
451 | match_dump_info(skb, match, info)) | 367 | nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info)) |
452 | goto nla_put_failure; | 368 | goto nla_put_failure; |
453 | 369 | ||
454 | return 0; | 370 | return 0; |
@@ -643,8 +559,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, | |||
643 | return ERR_PTR(-ENOMEM); | 559 | return ERR_PTR(-ENOMEM); |
644 | 560 | ||
645 | nft_match->ops.type = &nft_match_type; | 561 | nft_match->ops.type = &nft_match_type; |
646 | nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize) + | 562 | nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize)); |
647 | nft_compat_match_offset(match)); | ||
648 | nft_match->ops.eval = nft_match_eval; | 563 | nft_match->ops.eval = nft_match_eval; |
649 | nft_match->ops.init = nft_match_init; | 564 | nft_match->ops.init = nft_match_init; |
650 | nft_match->ops.destroy = nft_match_destroy; | 565 | nft_match->ops.destroy = nft_match_destroy; |
@@ -714,8 +629,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
714 | return ERR_PTR(-ENOMEM); | 629 | return ERR_PTR(-ENOMEM); |
715 | 630 | ||
716 | nft_target->ops.type = &nft_target_type; | 631 | nft_target->ops.type = &nft_target_type; |
717 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize) + | 632 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); |
718 | nft_compat_target_offset(target)); | ||
719 | nft_target->ops.eval = nft_target_eval; | 633 | nft_target->ops.eval = nft_target_eval; |
720 | nft_target->ops.init = nft_target_init; | 634 | nft_target->ops.init = nft_target_init; |
721 | nft_target->ops.destroy = nft_target_destroy; | 635 | nft_target->ops.destroy = nft_target_destroy; |
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index f3448c296446..ec8a456092a7 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/netfilter/nf_tables.h> | 17 | #include <linux/netfilter/nf_tables.h> |
18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
19 | #include <net/netfilter/nft_reject.h> | 19 | #include <net/netfilter/nft_reject.h> |
20 | #include <linux/icmp.h> | ||
21 | #include <linux/icmpv6.h> | ||
20 | 22 | ||
21 | const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { | 23 | const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { |
22 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, | 24 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, |
@@ -70,5 +72,40 @@ nla_put_failure: | |||
70 | } | 72 | } |
71 | EXPORT_SYMBOL_GPL(nft_reject_dump); | 73 | EXPORT_SYMBOL_GPL(nft_reject_dump); |
72 | 74 | ||
75 | static u8 icmp_code_v4[NFT_REJECT_ICMPX_MAX] = { | ||
76 | [NFT_REJECT_ICMPX_NO_ROUTE] = ICMP_NET_UNREACH, | ||
77 | [NFT_REJECT_ICMPX_PORT_UNREACH] = ICMP_PORT_UNREACH, | ||
78 | [NFT_REJECT_ICMPX_HOST_UNREACH] = ICMP_HOST_UNREACH, | ||
79 | [NFT_REJECT_ICMPX_ADMIN_PROHIBITED] = ICMP_PKT_FILTERED, | ||
80 | }; | ||
81 | |||
82 | int nft_reject_icmp_code(u8 code) | ||
83 | { | ||
84 | if (code > NFT_REJECT_ICMPX_MAX) | ||
85 | return -EINVAL; | ||
86 | |||
87 | return icmp_code_v4[code]; | ||
88 | } | ||
89 | |||
90 | EXPORT_SYMBOL_GPL(nft_reject_icmp_code); | ||
91 | |||
92 | |||
93 | static u8 icmp_code_v6[NFT_REJECT_ICMPX_MAX] = { | ||
94 | [NFT_REJECT_ICMPX_NO_ROUTE] = ICMPV6_NOROUTE, | ||
95 | [NFT_REJECT_ICMPX_PORT_UNREACH] = ICMPV6_PORT_UNREACH, | ||
96 | [NFT_REJECT_ICMPX_HOST_UNREACH] = ICMPV6_ADDR_UNREACH, | ||
97 | [NFT_REJECT_ICMPX_ADMIN_PROHIBITED] = ICMPV6_ADM_PROHIBITED, | ||
98 | }; | ||
99 | |||
100 | int nft_reject_icmpv6_code(u8 code) | ||
101 | { | ||
102 | if (code > NFT_REJECT_ICMPX_MAX) | ||
103 | return -EINVAL; | ||
104 | |||
105 | return icmp_code_v6[code]; | ||
106 | } | ||
107 | |||
108 | EXPORT_SYMBOL_GPL(nft_reject_icmpv6_code); | ||
109 | |||
73 | MODULE_LICENSE("GPL"); | 110 | MODULE_LICENSE("GPL"); |
74 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 111 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index b718a52a4654..7b5f9d58680a 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c | |||
@@ -14,17 +14,103 @@ | |||
14 | #include <linux/netfilter/nf_tables.h> | 14 | #include <linux/netfilter/nf_tables.h> |
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nft_reject.h> | 16 | #include <net/netfilter/nft_reject.h> |
17 | #include <net/netfilter/ipv4/nf_reject.h> | ||
18 | #include <net/netfilter/ipv6/nf_reject.h> | ||
17 | 19 | ||
18 | static void nft_reject_inet_eval(const struct nft_expr *expr, | 20 | static void nft_reject_inet_eval(const struct nft_expr *expr, |
19 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_data data[NFT_REG_MAX + 1], |
20 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
21 | { | 23 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | ||
25 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
26 | |||
22 | switch (pkt->ops->pf) { | 27 | switch (pkt->ops->pf) { |
23 | case NFPROTO_IPV4: | 28 | case NFPROTO_IPV4: |
24 | return nft_reject_ipv4_eval(expr, data, pkt); | 29 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | ||
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
32 | break; | ||
33 | case NFT_REJECT_TCP_RST: | ||
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
35 | break; | ||
36 | case NFT_REJECT_ICMPX_UNREACH: | ||
37 | nf_send_unreach(pkt->skb, | ||
38 | nft_reject_icmp_code(priv->icmp_code)); | ||
39 | break; | ||
40 | } | ||
41 | break; | ||
25 | case NFPROTO_IPV6: | 42 | case NFPROTO_IPV6: |
26 | return nft_reject_ipv6_eval(expr, data, pkt); | 43 | switch (priv->type) { |
44 | case NFT_REJECT_ICMP_UNREACH: | ||
45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
46 | pkt->ops->hooknum); | ||
47 | break; | ||
48 | case NFT_REJECT_TCP_RST: | ||
49 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
50 | break; | ||
51 | case NFT_REJECT_ICMPX_UNREACH: | ||
52 | nf_send_unreach6(net, pkt->skb, | ||
53 | nft_reject_icmpv6_code(priv->icmp_code), | ||
54 | pkt->ops->hooknum); | ||
55 | break; | ||
56 | } | ||
57 | break; | ||
58 | } | ||
59 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
60 | } | ||
61 | |||
62 | static int nft_reject_inet_init(const struct nft_ctx *ctx, | ||
63 | const struct nft_expr *expr, | ||
64 | const struct nlattr * const tb[]) | ||
65 | { | ||
66 | struct nft_reject *priv = nft_expr_priv(expr); | ||
67 | int icmp_code; | ||
68 | |||
69 | if (tb[NFTA_REJECT_TYPE] == NULL) | ||
70 | return -EINVAL; | ||
71 | |||
72 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | ||
73 | switch (priv->type) { | ||
74 | case NFT_REJECT_ICMP_UNREACH: | ||
75 | case NFT_REJECT_ICMPX_UNREACH: | ||
76 | if (tb[NFTA_REJECT_ICMP_CODE] == NULL) | ||
77 | return -EINVAL; | ||
78 | |||
79 | icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]); | ||
80 | if (priv->type == NFT_REJECT_ICMPX_UNREACH && | ||
81 | icmp_code > NFT_REJECT_ICMPX_MAX) | ||
82 | return -EINVAL; | ||
83 | |||
84 | priv->icmp_code = icmp_code; | ||
85 | break; | ||
86 | case NFT_REJECT_TCP_RST: | ||
87 | break; | ||
88 | default: | ||
89 | return -EINVAL; | ||
27 | } | 90 | } |
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int nft_reject_inet_dump(struct sk_buff *skb, | ||
95 | const struct nft_expr *expr) | ||
96 | { | ||
97 | const struct nft_reject *priv = nft_expr_priv(expr); | ||
98 | |||
99 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) | ||
100 | goto nla_put_failure; | ||
101 | |||
102 | switch (priv->type) { | ||
103 | case NFT_REJECT_ICMP_UNREACH: | ||
104 | case NFT_REJECT_ICMPX_UNREACH: | ||
105 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | ||
106 | goto nla_put_failure; | ||
107 | break; | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | |||
112 | nla_put_failure: | ||
113 | return -1; | ||
28 | } | 114 | } |
29 | 115 | ||
30 | static struct nft_expr_type nft_reject_inet_type; | 116 | static struct nft_expr_type nft_reject_inet_type; |
@@ -32,8 +118,8 @@ static const struct nft_expr_ops nft_reject_inet_ops = { | |||
32 | .type = &nft_reject_inet_type, | 118 | .type = &nft_reject_inet_type, |
33 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | 119 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), |
34 | .eval = nft_reject_inet_eval, | 120 | .eval = nft_reject_inet_eval, |
35 | .init = nft_reject_init, | 121 | .init = nft_reject_inet_init, |
36 | .dump = nft_reject_dump, | 122 | .dump = nft_reject_inet_dump, |
37 | }; | 123 | }; |
38 | 124 | ||
39 | static struct nft_expr_type nft_reject_inet_type __read_mostly = { | 125 | static struct nft_expr_type nft_reject_inet_type __read_mostly = { |
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index d7ca16b8b8df..f440f57a452f 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/netfilter_bridge.h> | 13 | #include <linux/netfilter_bridge.h> |
14 | #include <linux/netfilter/xt_physdev.h> | 14 | #include <linux/netfilter/xt_physdev.h> |
15 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | #include <net/netfilter/br_netfilter.h> | ||
16 | 17 | ||
17 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
18 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | 19 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); |
@@ -87,6 +88,8 @@ static int physdev_mt_check(const struct xt_mtchk_param *par) | |||
87 | { | 88 | { |
88 | const struct xt_physdev_info *info = par->matchinfo; | 89 | const struct xt_physdev_info *info = par->matchinfo; |
89 | 90 | ||
91 | br_netfilter_enable(); | ||
92 | |||
90 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || | 93 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || |
91 | info->bitmask & ~XT_PHYSDEV_OP_MASK) | 94 | info->bitmask & ~XT_PHYSDEV_OP_MASK) |
92 | return -EINVAL; | 95 | return -EINVAL; |