···8989#define NFULNL_COPY_NONE 0x009090#define NFULNL_COPY_META 0x019191#define NFULNL_COPY_PACKET 0x029292-#define NFULNL_COPY_DISABLED 0x039292+/* 0xff is reserved, don't use it for new copy modes. */93939494#define NFULNL_CFG_F_SEQ 0x00019595#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002
+20
include/linux/netfilter/xt_CHECKSUM.h
···11+/* Header file for iptables ipt_CHECKSUM target22+ *33+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>44+ * (C) 2010 Red Hat Inc55+ * Author: Michael S. Tsirkin <mst@redhat.com>66+ *77+ * This software is distributed under GNU GPL v2, 199188+*/99+#ifndef _XT_CHECKSUM_TARGET_H1010+#define _XT_CHECKSUM_TARGET_H1111+1212+#include <linux/types.h>1313+1414+#define XT_CHECKSUM_OP_FILL 0x01 /* fill in checksum in IP header */1515+1616+struct xt_CHECKSUM_info {1717+ __u8 operation; /* bitset of operations */1818+};1919+2020+#endif /* _XT_CHECKSUM_TARGET_H */
···1111struct xt_quota_info {1212 u_int32_t flags;1313 u_int32_t pad;1414+ aligned_u64 quota;14151516 /* Used internally by the kernel */1616- aligned_u64 quota;1717 struct xt_quota_priv *master;1818};1919
+12-2
include/net/ip_vs.h
···632632(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,633633 const union nf_inet_addr *d_addr, __be16 d_port);634634635635+struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,636636+ struct ip_vs_protocol *pp,637637+ const struct ip_vs_iphdr *iph,638638+ unsigned int proto_off,639639+ int inverse);640640+635641extern struct ip_vs_conn *ip_vs_conn_out_get636642(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,637643 const union nf_inet_addr *d_addr, __be16 d_port);644644+645645+struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,646646+ struct ip_vs_protocol *pp,647647+ const struct ip_vs_iphdr *iph,648648+ unsigned int proto_off,649649+ int inverse);638650639651/* put back the conn without restarting its timer */640652static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)···748736749737extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);750738extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);751751-extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,752752- char *o_buf, int o_len, char *n_buf, int n_len);753739extern int ip_vs_app_init(void);754740extern void ip_vs_app_cleanup(void);755741
···27272828 /* Alter the per-proto part of the tuple (depending on2929 maniptype), to give a unique tuple in the given range if3030- possible; return false if not. Per-protocol part of tuple3131- is initialized to the incoming packet. */3232- bool (*unique_tuple)(struct nf_conntrack_tuple *tuple,3030+ possible. Per-protocol part of tuple is initialized to the3131+ incoming packet. */3232+ void (*unique_tuple)(struct nf_conntrack_tuple *tuple,3333 const struct nf_nat_range *range,3434 enum nf_nat_manip_type maniptype,3535 const struct nf_conn *ct);···6363 const union nf_conntrack_man_proto *min,6464 const union nf_conntrack_man_proto *max);65656666-extern bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,6666+extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,6767 const struct nf_nat_range *range,6868 enum nf_nat_manip_type maniptype,6969 const struct nf_conn *ct,
···283283 arp = arp_hdr(skb);284284 do {285285 const struct arpt_entry_target *t;286286- int hdr_len;287286288287 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {289288 e = arpt_next_entry(e);290289 continue;291290 }292291293293- hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +294294- (2 * skb->dev->addr_len);295295- ADD_COUNTER(e->counters, hdr_len, 1);292292+ ADD_COUNTER(e->counters, arp_hdr_len(skb->dev), 1);296293297294 t = arpt_get_target_c(e);298295···710713 struct arpt_entry *iter;711714 unsigned int cpu;712715 unsigned int i;713713- unsigned int curcpu;716716+ unsigned int curcpu = get_cpu();714717715718 /* Instead of clearing (by a previous call to memset())716719 * the counters and using adds, we set the counters···720723 * if new softirq were to run and call ipt_do_table721724 */722725 local_bh_disable();723723- curcpu = smp_processor_id();724724-725726 i = 0;726727 xt_entry_foreach(iter, t->entries[curcpu], t->size) {727728 SET_COUNTER(counters[i], iter->counters.bcnt,728729 iter->counters.pcnt);729730 ++i;730731 }732732+ local_bh_enable();733733+ /* Processing counters from other cpus, we can let bottom half enabled,734734+ * (preemption is disabled)735735+ */731736732737 for_each_possible_cpu(cpu) {733738 if (cpu == curcpu)···743744 }744745 xt_info_wrunlock(cpu);745746 }746746- local_bh_enable();747747+ put_cpu();747748}748749749750static struct xt_counters *alloc_counters(const struct xt_table *table)
+7-5
net/ipv4/netfilter/ip_tables.c
···364364 goto no_match;365365 }366366367367- ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);367367+ ADD_COUNTER(e->counters, skb->len, 1);368368369369 t = ipt_get_target(e);370370 IP_NF_ASSERT(t->u.kernel.target);···884884 struct ipt_entry *iter;885885 unsigned int cpu;886886 unsigned int i;887887- unsigned int curcpu;887887+ unsigned int curcpu = get_cpu();888888889889 /* Instead of clearing (by a previous call to memset())890890 * the counters and using adds, we set the counters···894894 * if new softirq were to run and call ipt_do_table895895 */896896 local_bh_disable();897897- curcpu = smp_processor_id();898898-899897 i = 0;900898 xt_entry_foreach(iter, t->entries[curcpu], t->size) {901899 SET_COUNTER(counters[i], iter->counters.bcnt,902900 iter->counters.pcnt);903901 ++i;904902 }903903+ local_bh_enable();904904+ /* Processing counters from other cpus, we can let bottom half enabled,905905+ * (preemption is disabled)906906+ */905907906908 for_each_possible_cpu(cpu) {907909 if (cpu == curcpu)···917915 }918916 xt_info_wrunlock(cpu);919917 }920920- local_bh_enable();918918+ put_cpu();921919}922920923921static struct xt_counters *alloc_counters(const struct xt_table *table)
···3737MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");38383939/* generate unique tuple ... */4040-static bool4040+static void4141gre_unique_tuple(struct nf_conntrack_tuple *tuple,4242 const struct nf_nat_range *range,4343 enum nf_nat_manip_type maniptype,···5050 /* If there is no master conntrack we are not PPTP,5151 do not change tuples */5252 if (!ct->master)5353- return false;5353+ return;54545555 if (maniptype == IP_NAT_MANIP_SRC)5656 keyptr = &tuple->src.u.gre.key;···68686969 pr_debug("min = %u, range_size = %u\n", min, range_size);70707171- for (i = 0; i < range_size; i++, key++) {7171+ for (i = 0; ; ++key) {7272 *keyptr = htons(min + key % range_size);7373- if (!nf_nat_used_tuple(tuple, ct))7474- return true;7373+ if (++i == range_size || !nf_nat_used_tuple(tuple, ct))7474+ return;7575 }76767777 pr_debug("%p: no NAT mapping\n", ct);7878- return false;7878+ return;7979}80808181/* manipulate a GRE packet according to maniptype */
+5-5
net/ipv4/netfilter/nf_nat_proto_icmp.c
···2727 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);2828}29293030-static bool3030+static void3131icmp_unique_tuple(struct nf_conntrack_tuple *tuple,3232 const struct nf_nat_range *range,3333 enum nf_nat_manip_type maniptype,···4242 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))4343 range_size = 0xFFFF;44444545- for (i = 0; i < range_size; i++, id++) {4545+ for (i = 0; ; ++id) {4646 tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +4747 (id % range_size));4848- if (!nf_nat_used_tuple(tuple, ct))4949- return true;4848+ if (++i == range_size || !nf_nat_used_tuple(tuple, ct))4949+ return;5050 }5151- return false;5151+ return;5252}53535454static bool
···2626 return true;2727}28282929-static bool unknown_unique_tuple(struct nf_conntrack_tuple *tuple,2929+static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple,3030 const struct nf_nat_range *range,3131 enum nf_nat_manip_type maniptype,3232 const struct nf_conn *ct)3333{3434 /* Sorry: we can't help you; if it's not unique, we can't frob3535 anything. */3636- return false;3636+ return;3737}38383939static bool
+7-7
net/ipv6/netfilter/ip6_tables.c
···387387 goto no_match;388388 }389389390390- ADD_COUNTER(e->counters,391391- ntohs(ipv6_hdr(skb)->payload_len) +392392- sizeof(struct ipv6hdr), 1);390390+ ADD_COUNTER(e->counters, skb->len, 1);393391394392 t = ip6t_get_target_c(e);395393 IP_NF_ASSERT(t->u.kernel.target);···897899 struct ip6t_entry *iter;898900 unsigned int cpu;899901 unsigned int i;900900- unsigned int curcpu;902902+ unsigned int curcpu = get_cpu();901903902904 /* Instead of clearing (by a previous call to memset())903905 * the counters and using adds, we set the counters···907909 * if new softirq were to run and call ipt_do_table908910 */909911 local_bh_disable();910910- curcpu = smp_processor_id();911911-912912 i = 0;913913 xt_entry_foreach(iter, t->entries[curcpu], t->size) {914914 SET_COUNTER(counters[i], iter->counters.bcnt,915915 iter->counters.pcnt);916916 ++i;917917 }918918+ local_bh_enable();919919+ /* Processing counters from other cpus, we can let bottom half enabled,920920+ * (preemption is disabled)921921+ */918922919923 for_each_possible_cpu(cpu) {920924 if (cpu == curcpu)···930930 }931931 xt_info_wrunlock(cpu);932932 }933933- local_bh_enable();933933+ put_cpu();934934}935935936936static struct xt_counters *alloc_counters(const struct xt_table *table)
+9
net/ipv6/netfilter/nf_conntrack_reasm.c
···269269 * in the chain of fragments so far. We must know where to put270270 * this fragment, right?271271 */272272+ prev = fq->q.fragments_tail;273273+ if (!prev || NFCT_FRAG6_CB(prev)->offset < offset) {274274+ next = NULL;275275+ goto found;276276+ }272277 prev = NULL;273278 for (next = fq->q.fragments; next != NULL; next = next->next) {274279 if (NFCT_FRAG6_CB(next)->offset >= offset)···281276 prev = next;282277 }283278279279+found:284280 /* We found where to put this one. Check for overlap with285281 * preceding fragment, and, if needed, align things so that286282 * any overlaps are eliminated.···347341348342 /* Insert this fragment in the chain of fragments. */349343 skb->next = next;344344+ if (!next)345345+ fq->q.fragments_tail = skb;350346 if (prev)351347 prev->next = skb;352348 else···472464 head->csum);473465474466 fq->q.fragments = NULL;467467+ fq->q.fragments_tail = NULL;475468476469 /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */477470 fp = skb_shinfo(head)->frag_list;
+35
net/netfilter/Kconfig
···326326327327comment "Xtables targets"328328329329+config NETFILTER_XT_TARGET_CHECKSUM330330+ tristate "CHECKSUM target support"331331+ depends on IP_NF_MANGLE || IP6_NF_MANGLE332332+ depends on NETFILTER_ADVANCED333333+ ---help---334334+ This option adds a `CHECKSUM' target, which can be used in the iptables mangle335335+ table.336336+337337+ You can use this target to compute and fill in the checksum in338338+ a packet that lacks a checksum. This is particularly useful,339339+ if you need to work around old applications such as dhcp clients,340340+ that do not work well with checksum offloads, but don't want to disable341341+ checksum offload in your device.342342+343343+ To compile it as a module, choose M here. If unsure, say N.344344+329345config NETFILTER_XT_TARGET_CLASSIFY330346 tristate '"CLASSIFY" target support'331347 depends on NETFILTER_ADVANCED···663647664648 To compile it as a module, choose M here. If unsure, say N.665649650650+config NETFILTER_XT_MATCH_CPU651651+ tristate '"cpu" match support'652652+ depends on NETFILTER_ADVANCED653653+ help654654+ CPU matching allows you to match packets based on the CPU655655+ currently handling the packet.656656+657657+ To compile it as a module, choose M here. If unsure, say N.658658+666659config NETFILTER_XT_MATCH_DCCP667660 tristate '"dccp" protocol match support'668661 depends on NETFILTER_ADVANCED···750725 with an optional mask.)751726752727 If unsure, say M.728728+729729+config NETFILTER_XT_MATCH_IPVS730730+ tristate '"ipvs" match support'731731+ depends on IP_VS732732+ depends on NETFILTER_ADVANCED733733+ depends on NF_CONNTRACK734734+ help735735+ This option allows you to match against IPVS properties of a packet.736736+737737+ If unsure, say N.753738754739config NETFILTER_XT_MATCH_LENGTH755740 tristate '"length" match support'
···33#44menuconfig IP_VS55 tristate "IP virtual server support"66- depends on NET && INET && NETFILTER66+ depends on NET && INET && NETFILTER && NF_CONNTRACK77 ---help---88 IP Virtual Server support will let you build a high-performance99 virtual server based on cluster of two or more real servers. This···26262727config IP_VS_IPV62828 bool "IPv6 support for IPVS"2929- depends on EXPERIMENTAL && (IPV6 = y || IP_VS = IPV6)2929+ depends on IPV6 = y || IP_VS = IPV63030 ---help---3131 Add IPv6 support to IPVS. This is incomplete and might be dangerous.3232···8787 protocol. Say Y if unsure.88888989config IP_VS_PROTO_AH_ESP9090- bool9191- depends on UNDEFINED9090+ def_bool IP_VS_PROTO_ESP || IP_VS_PROTO_AH92919392config IP_VS_PROTO_ESP9493 bool "ESP load balancing support"9595- select IP_VS_PROTO_AH_ESP9694 ---help---9795 This option enables support for load balancing ESP (Encapsulation9896 Security Payload) transport protocol. Say Y if unsure.999710098config IP_VS_PROTO_AH10199 bool "AH load balancing support"102102- select IP_VS_PROTO_AH_ESP103100 ---help---104101 This option enables support for load balancing AH (Authentication105102 Header) transport protocol. Say Y if unsure.···235238236239config IP_VS_FTP237240 tristate "FTP protocol helper"238238- depends on IP_VS_PROTO_TCP241241+ depends on IP_VS_PROTO_TCP && NF_NAT239242 ---help---240243 FTP is a protocol that transfers IP address and/or port number in241244 the payload. In the virtual server via Network Address Translation,
-43
net/netfilter/ipvs/ip_vs_app.c
···569569};570570#endif571571572572-573573-/*574574- * Replace a segment of data with a new segment575575- */576576-int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,577577- char *o_buf, int o_len, char *n_buf, int n_len)578578-{579579- int diff;580580- int o_offset;581581- int o_left;582582-583583- EnterFunction(9);584584-585585- diff = n_len - o_len;586586- o_offset = o_buf - (char *)skb->data;587587- /* The length of left data after o_buf+o_len in the skb data */588588- o_left = skb->len - (o_offset + o_len);589589-590590- if (diff <= 0) {591591- memmove(o_buf + n_len, o_buf + o_len, o_left);592592- memcpy(o_buf, n_buf, n_len);593593- skb_trim(skb, skb->len + diff);594594- } else if (diff <= skb_tailroom(skb)) {595595- skb_put(skb, diff);596596- memmove(o_buf + n_len, o_buf + o_len, o_left);597597- memcpy(o_buf, n_buf, n_len);598598- } else {599599- if (pskb_expand_head(skb, skb_headroom(skb), diff, pri))600600- return -ENOMEM;601601- skb_put(skb, diff);602602- memmove(skb->data + o_offset + n_len,603603- skb->data + o_offset + o_len, o_left);604604- skb_copy_to_linear_data_offset(skb, o_offset, n_buf, n_len);605605- }606606-607607- /* must update the iph total length here */608608- ip_hdr(skb)->tot_len = htons(skb->len);609609-610610- LeaveFunction(9);611611- return 0;612612-}613613-614614-615572int __init ip_vs_app_init(void)616573{617574 /* we will replace it with proc_net_ipvs_create() soon */
+45
net/netfilter/ipvs/ip_vs_conn.c
···271271 return cp;272272}273273274274+struct ip_vs_conn *275275+ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,276276+ struct ip_vs_protocol *pp,277277+ const struct ip_vs_iphdr *iph,278278+ unsigned int proto_off, int inverse)279279+{280280+ __be16 _ports[2], *pptr;281281+282282+ pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);283283+ if (pptr == NULL)284284+ return NULL;285285+286286+ if (likely(!inverse))287287+ return ip_vs_conn_in_get(af, iph->protocol,288288+ &iph->saddr, pptr[0],289289+ &iph->daddr, pptr[1]);290290+ else291291+ return ip_vs_conn_in_get(af, iph->protocol,292292+ &iph->daddr, pptr[1],293293+ &iph->saddr, pptr[0]);294294+}295295+EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);296296+274297/* Get reference to connection template */275298struct ip_vs_conn *ip_vs_ct_in_get276299(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,···379356 return ret;380357}381358359359+struct ip_vs_conn *360360+ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,361361+ struct ip_vs_protocol *pp,362362+ const struct ip_vs_iphdr *iph,363363+ unsigned int proto_off, int inverse)364364+{365365+ __be16 _ports[2], *pptr;366366+367367+ pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);368368+ if (pptr == NULL)369369+ return NULL;370370+371371+ if (likely(!inverse))372372+ return ip_vs_conn_out_get(af, iph->protocol,373373+ &iph->saddr, pptr[0],374374+ &iph->daddr, pptr[1]);375375+ else376376+ return ip_vs_conn_out_get(af, iph->protocol,377377+ &iph->daddr, pptr[1],378378+ &iph->saddr, pptr[0]);379379+}380380+EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);382381383382/*384383 * Put back the conn and restart its timer with its timeout
-37
net/netfilter/ipvs/ip_vs_core.c
···54545555EXPORT_SYMBOL(register_ip_vs_scheduler);5656EXPORT_SYMBOL(unregister_ip_vs_scheduler);5757-EXPORT_SYMBOL(ip_vs_skb_replace);5857EXPORT_SYMBOL(ip_vs_proto_name);5958EXPORT_SYMBOL(ip_vs_conn_new);6059EXPORT_SYMBOL(ip_vs_conn_in_get);···533534 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);534535535536 return NF_DROP;536536-}537537-538538-539539-/*540540- * It is hooked before NF_IP_PRI_NAT_SRC at the NF_INET_POST_ROUTING541541- * chain, and is used for VS/NAT.542542- * It detects packets for VS/NAT connections and sends the packets543543- * immediately. This can avoid that iptable_nat mangles the packets544544- * for VS/NAT.545545- */546546-static unsigned int ip_vs_post_routing(unsigned int hooknum,547547- struct sk_buff *skb,548548- const struct net_device *in,549549- const struct net_device *out,550550- int (*okfn)(struct sk_buff *))551551-{552552- if (!skb->ipvs_property)553553- return NF_ACCEPT;554554- /* The packet was sent from IPVS, exit this chain */555555- return NF_STOP;556537}557538558539__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)···14781499 .hooknum = NF_INET_FORWARD,14791500 .priority = 99,14801501 },14811481- /* Before the netfilter connection tracking, exit from POST_ROUTING */14821482- {14831483- .hook = ip_vs_post_routing,14841484- .owner = THIS_MODULE,14851485- .pf = PF_INET,14861486- .hooknum = NF_INET_POST_ROUTING,14871487- .priority = NF_IP_PRI_NAT_SRC-1,14881488- },14891502#ifdef CONFIG_IP_VS_IPV614901503 /* After packet filtering, forward packet through VS/DR, VS/TUN,14911504 * or VS/NAT(change destination), so that filtering rules can be···15051534 .pf = PF_INET6,15061535 .hooknum = NF_INET_FORWARD,15071536 .priority = 99,15081508- },15091509- /* Before the netfilter connection tracking, exit from POST_ROUTING */15101510- {15111511- .hook = ip_vs_post_routing,15121512- .owner = THIS_MODULE,15131513- .pf = PF_INET6,15141514- .hooknum = NF_INET_POST_ROUTING,15151515- .priority = NF_IP6_PRI_NAT_SRC-1,15161537 },15171538#endif15181539};
+165-13
net/netfilter/ipvs/ip_vs_ftp.c
···2020 *2121 * Author: Wouter Gadeyne2222 *2323+ *2424+ * Code for ip_vs_expect_related and ip_vs_expect_callback is taken from2525+ * http://www.ssi.bg/~ja/nfct/:2626+ *2727+ * ip_vs_nfct.c: Netfilter connection tracking support for IPVS2828+ *2929+ * Portions Copyright (C) 2001-20023030+ * Antefacto Ltd, 181 Parnell St, Dublin 1, Ireland.3131+ *3232+ * Portions Copyright (C) 2003-20083333+ * Julian Anastasov2334 */24352536#define KMSG_COMPONENT "IPVS"···4332#include <linux/in.h>4433#include <linux/ip.h>4534#include <linux/netfilter.h>3535+#include <net/netfilter/nf_conntrack.h>3636+#include <net/netfilter/nf_conntrack_expect.h>3737+#include <net/netfilter/nf_nat_helper.h>4638#include <linux/gfp.h>4739#include <net/protocol.h>4840#include <net/tcp.h>···5743#define SERVER_STRING "227 Entering Passive Mode ("5844#define CLIENT_STRING "PORT "59454646+#define FMT_TUPLE "%pI4:%u->%pI4:%u/%u"4747+#define ARG_TUPLE(T) &(T)->src.u3.ip, ntohs((T)->src.u.all), \4848+ &(T)->dst.u3.ip, ntohs((T)->dst.u.all), \4949+ (T)->dst.protonum5050+5151+#define FMT_CONN "%pI4:%u->%pI4:%u->%pI4:%u/%u:%u"5252+#define ARG_CONN(C) &((C)->caddr.ip), ntohs((C)->cport), \5353+ &((C)->vaddr.ip), ntohs((C)->vport), \5454+ &((C)->daddr.ip), ntohs((C)->dport), \5555+ (C)->protocol, (C)->state60566157/*6258 * List of ports (up to IP_VS_APP_MAX_PORTS) to be handled by helper···147123 return 1;148124}149125126126+/*127127+ * Called from init_conntrack() as expectfn handler.128128+ */129129+static void130130+ip_vs_expect_callback(struct nf_conn *ct,131131+ struct nf_conntrack_expect *exp)132132+{133133+ struct nf_conntrack_tuple *orig, new_reply;134134+ struct ip_vs_conn *cp;135135+136136+ if (exp->tuple.src.l3num != PF_INET)137137+ return;138138+139139+ /*140140+ * We assume that no NF locks are held before this callback.141141+ * ip_vs_conn_out_get and ip_vs_conn_in_get should match their142142+ * expectations even if they use wildcard values, now we provide the143143+ * actual values from the newly created original conntrack direction.144144+ * The conntrack is confirmed when packet reaches IPVS hooks.145145+ */146146+147147+ /* RS->CLIENT */148148+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;149149+ cp = ip_vs_conn_out_get(exp->tuple.src.l3num, orig->dst.protonum,150150+ &orig->src.u3, orig->src.u.tcp.port,151151+ &orig->dst.u3, orig->dst.u.tcp.port);152152+ if (cp) {153153+ /* Change reply CLIENT->RS to CLIENT->VS */154154+ new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;155155+ IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "156156+ FMT_TUPLE ", found inout cp=" FMT_CONN "\n",157157+ __func__, ct, ct->status,158158+ ARG_TUPLE(orig), ARG_TUPLE(&new_reply),159159+ ARG_CONN(cp));160160+ new_reply.dst.u3 = cp->vaddr;161161+ new_reply.dst.u.tcp.port = cp->vport;162162+ IP_VS_DBG(7, "%s(): ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE163163+ ", inout cp=" FMT_CONN "\n",164164+ __func__, ct,165165+ ARG_TUPLE(orig), ARG_TUPLE(&new_reply),166166+ ARG_CONN(cp));167167+ goto alter;168168+ }169169+170170+ /* CLIENT->VS */171171+ cp = ip_vs_conn_in_get(exp->tuple.src.l3num, orig->dst.protonum,172172+ &orig->src.u3, orig->src.u.tcp.port,173173+ &orig->dst.u3, orig->dst.u.tcp.port);174174+ if (cp) {175175+ /* Change reply VS->CLIENT to RS->CLIENT */176176+ new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;177177+ IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "178178+ FMT_TUPLE ", found outin cp=" FMT_CONN "\n",179179+ __func__, ct, ct->status,180180+ ARG_TUPLE(orig), ARG_TUPLE(&new_reply),181181+ ARG_CONN(cp));182182+ new_reply.src.u3 = cp->daddr;183183+ new_reply.src.u.tcp.port = cp->dport;184184+ IP_VS_DBG(7, "%s(): ct=%p, new tuples=" FMT_TUPLE ", "185185+ FMT_TUPLE ", outin cp=" FMT_CONN "\n",186186+ __func__, ct,187187+ ARG_TUPLE(orig), ARG_TUPLE(&new_reply),188188+ ARG_CONN(cp));189189+ goto alter;190190+ }191191+192192+ IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuple=" FMT_TUPLE193193+ " - unknown expect\n",194194+ __func__, ct, ct->status, ARG_TUPLE(orig));195195+ return;196196+197197+alter:198198+ /* Never alter conntrack for non-NAT conns */199199+ if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ)200200+ nf_conntrack_alter_reply(ct, &new_reply);201201+ ip_vs_conn_put(cp);202202+ return;203203+}204204+205205+/*206206+ * Create NF conntrack expectation with wildcard (optional) source port.207207+ * Then the default callback function will alter the reply and will confirm208208+ * the conntrack entry when the first packet comes.209209+ */210210+static void211211+ip_vs_expect_related(struct sk_buff *skb, struct nf_conn *ct,212212+ struct ip_vs_conn *cp, u_int8_t proto,213213+ const __be16 *port, int from_rs)214214+{215215+ struct nf_conntrack_expect *exp;216216+217217+ BUG_ON(!ct || ct == &nf_conntrack_untracked);218218+219219+ exp = nf_ct_expect_alloc(ct);220220+ if (!exp)221221+ return;222222+223223+ if (from_rs)224224+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,225225+ nf_ct_l3num(ct), &cp->daddr, &cp->caddr,226226+ proto, port, &cp->cport);227227+ else228228+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,229229+ nf_ct_l3num(ct), &cp->caddr, &cp->vaddr,230230+ proto, port, &cp->vport);231231+232232+ exp->expectfn = ip_vs_expect_callback;233233+234234+ IP_VS_DBG(7, "%s(): ct=%p, expect tuple=" FMT_TUPLE "\n",235235+ __func__, ct, ARG_TUPLE(&exp->tuple));236236+ nf_ct_expect_related(exp);237237+ nf_ct_expect_put(exp);238238+}150239151240/*152241 * Look at outgoing ftp packets to catch the response to a PASV command···286149 struct ip_vs_conn *n_cp;287150 char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */288151 unsigned buf_len;289289- int ret;152152+ int ret = 0;153153+ enum ip_conntrack_info ctinfo;154154+ struct nf_conn *ct;290155291156#ifdef CONFIG_IP_VS_IPV6292157 /* This application helper doesn't work with IPv6 yet,···358219359220 buf_len = strlen(buf);360221361361- /*362362- * Calculate required delta-offset to keep TCP happy363363- */364364- *diff = buf_len - (end-start);365365-366366- if (*diff == 0) {367367- /* simply replace it with new passive address */368368- memcpy(start, buf, buf_len);369369- ret = 1;370370- } else {371371- ret = !ip_vs_skb_replace(skb, GFP_ATOMIC, start,372372- end-start, buf, buf_len);222222+ ct = nf_ct_get(skb, &ctinfo);223223+ if (ct && !nf_ct_is_untracked(ct)) {224224+ /* If mangling fails this function will return 0225225+ * which will cause the packet to be dropped.226226+ * Mangling can only fail under memory pressure,227227+ * hopefully it will succeed on the retransmitted228228+ * packet.229229+ */230230+ ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo,231231+ start-data, end-start,232232+ buf, buf_len);233233+ if (ret)234234+ ip_vs_expect_related(skb, ct, n_cp,235235+ IPPROTO_TCP, NULL, 0);373236 }237237+238238+ /*239239+ * Not setting 'diff' is intentional, otherwise the sequence240240+ * would be adjusted twice.241241+ */374242375243 cp->app_data = NULL;376244 ip_vs_tcp_conn_listen(n_cp);···409263 union nf_inet_addr to;410264 __be16 port;411265 struct ip_vs_conn *n_cp;266266+ struct nf_conn *ct;412267413268#ifdef CONFIG_IP_VS_IPV6414269 /* This application helper doesn't work with IPv6 yet,···495348 /* add its controller */496349 ip_vs_control_add(n_cp, cp);497350 }351351+352352+ ct = (struct nf_conn *)skb->nfct;353353+ if (ct && ct != &nf_conntrack_untracked)354354+ ip_vs_expect_related(skb, ct, n_cp,355355+ IPPROTO_TCP, &n_cp->dport, 1);498356499357 /*500358 * Move tunnel to listen state
···2828#include <net/ip6_route.h>2929#include <linux/icmpv6.h>3030#include <linux/netfilter.h>3131+#include <net/netfilter/nf_conntrack.h>3132#include <linux/netfilter_ipv4.h>32333334#include <net/ip_vs.h>···349348}350349#endif351350351351+static void352352+ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)353353+{354354+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;355355+ struct nf_conntrack_tuple new_tuple;356356+357357+ if (ct == NULL || nf_ct_is_untracked(ct) || nf_ct_is_confirmed(ct))358358+ return;359359+360360+ /*361361+ * The connection is not yet in the hashtable, so we update it.362362+ * CIP->VIP will remain the same, so leave the tuple in363363+ * IP_CT_DIR_ORIGINAL untouched. When the reply comes back from the364364+ * real-server we will see RIP->DIP.365365+ */366366+ new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;367367+ new_tuple.src.u3 = cp->daddr;368368+ /*369369+ * This will also take care of UDP and other protocols.370370+ */371371+ new_tuple.src.u.tcp.port = cp->dport;372372+ nf_conntrack_alter_reply(ct, &new_tuple);373373+}374374+352375/*353376 * NAT transmitter (only for outside-to-inside nat forwarding)354377 * Not used for related ICMP···427402 ip_send_check(ip_hdr(skb));428403429404 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");405405+406406+ ip_vs_update_conntrack(skb, cp);430407431408 /* FIXME: when application helper enlarges the packet and the length432409 is larger than the MTU of outgoing device, there will be still···505478 ipv6_hdr(skb)->daddr = cp->daddr.in6;506479507480 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");481481+482482+ ip_vs_update_conntrack(skb, cp);508483509484 /* FIXME: when application helper enlarges the packet and the length510485 is larger than the MTU of outgoing device, there will be still
···2323{2424 unsigned int i;2525 struct nf_ct_ext_type *t;2626+ struct nf_ct_ext *ext = ct->ext;26272728 for (i = 0; i < NF_CT_EXT_NUM; i++) {2828- if (!nf_ct_ext_exist(ct, i))2929+ if (!__nf_ct_ext_exist(ext, i))2930 continue;30313132 rcu_read_lock();···74737574void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)7675{7777- struct nf_ct_ext *new;7676+ struct nf_ct_ext *old, *new;7877 int i, newlen, newoff;7978 struct nf_ct_ext_type *t;80798180 /* Conntrack must not be confirmed to avoid races on reallocation. */8281 NF_CT_ASSERT(!nf_ct_is_confirmed(ct));83828484- if (!ct->ext)8383+ old = ct->ext;8484+ if (!old)8585 return nf_ct_ext_create(&ct->ext, id, gfp);86868787- if (nf_ct_ext_exist(ct, id))8787+ if (__nf_ct_ext_exist(old, id))8888 return NULL;89899090 rcu_read_lock();9191 t = rcu_dereference(nf_ct_ext_types[id]);9292 BUG_ON(t == NULL);93939494- newoff = ALIGN(ct->ext->len, t->align);9494+ newoff = ALIGN(old->len, t->align);9595 newlen = newoff + t->len;9696 rcu_read_unlock();97979898- new = __krealloc(ct->ext, newlen, gfp);9898+ new = __krealloc(old, newlen, gfp);9999 if (!new)100100 return NULL;101101102102- if (new != ct->ext) {102102+ if (new != old) {103103 for (i = 0; i < NF_CT_EXT_NUM; i++) {104104- if (!nf_ct_ext_exist(ct, i))104104+ if (!__nf_ct_ext_exist(old, i))105105 continue;106106107107 rcu_read_lock();108108 t = rcu_dereference(nf_ct_ext_types[i]);109109 if (t && t->move)110110 t->move((void *)new + new->offset[i],111111- (void *)ct->ext + ct->ext->offset[i]);111111+ (void *)old + old->offset[i]);112112 rcu_read_unlock();113113 }114114- call_rcu(&ct->ext->rcu, __nf_ct_ext_free_rcu);114114+ call_rcu(&old->rcu, __nf_ct_ext_free_rcu);115115 ct->ext = new;116116 }117117
+9-1
net/netfilter/nf_conntrack_proto_tcp.c
···585585 * Let's try to use the data from the packet.586586 */587587 sender->td_end = end;588588+ win <<= sender->td_scale;588589 sender->td_maxwin = (win == 0 ? 1 : win);589590 sender->td_maxend = end + sender->td_maxwin;591591+ /*592592+ * We haven't seen traffic in the other direction yet593593+ * but we have to tweak window tracking to pass III594594+ * and IV until that happens.595595+ */596596+ if (receiver->td_maxwin == 0)597597+ receiver->td_end = receiver->td_maxend = sack;590598 }591599 } else if (((state->state == TCP_CONNTRACK_SYN_SENT592600 && dir == IP_CT_DIR_ORIGINAL)···688680 /*689681 * Update receiver data.690682 */691691- if (after(end, sender->td_maxend))683683+ if (receiver->td_maxwin != 0 && after(end, sender->td_maxend))692684 receiver->td_maxwin += end - sender->td_maxend;693685 if (after(sack + win, receiver->td_maxend - 1)) {694686 receiver->td_maxend = sack + win;
+70
net/netfilter/xt_CHECKSUM.c
···11+/* iptables module for the packet checksum mangling22+ *33+ * (C) 2002 by Harald Welte <laforge@netfilter.org>44+ * (C) 2010 Red Hat, Inc.55+ *66+ * Author: Michael S. Tsirkin <mst@redhat.com>77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License version 2 as1010+ * published by the Free Software Foundation.1111+*/1212+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1313+#include <linux/module.h>1414+#include <linux/skbuff.h>1515+1616+#include <linux/netfilter/x_tables.h>1717+#include <linux/netfilter/xt_CHECKSUM.h>1818+1919+MODULE_LICENSE("GPL");2020+MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");2121+MODULE_DESCRIPTION("Xtables: checksum modification");2222+MODULE_ALIAS("ipt_CHECKSUM");2323+MODULE_ALIAS("ip6t_CHECKSUM");2424+2525+static unsigned int2626+checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)2727+{2828+ if (skb->ip_summed == CHECKSUM_PARTIAL)2929+ skb_checksum_help(skb);3030+3131+ return XT_CONTINUE;3232+}3333+3434+static int checksum_tg_check(const struct xt_tgchk_param *par)3535+{3636+ const struct xt_CHECKSUM_info *einfo = par->targinfo;3737+3838+ if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {3939+ pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);4040+ return -EINVAL;4141+ }4242+ if (!einfo->operation) {4343+ pr_info("no CHECKSUM operation enabled\n");4444+ return -EINVAL;4545+ }4646+ return 0;4747+}4848+4949+static struct xt_target checksum_tg_reg __read_mostly = {5050+ .name = "CHECKSUM",5151+ .family = NFPROTO_UNSPEC,5252+ .target = checksum_tg,5353+ .targetsize = sizeof(struct xt_CHECKSUM_info),5454+ .table = "mangle",5555+ .checkentry = checksum_tg_check,5656+ .me = THIS_MODULE,5757+};5858+5959+static int __init checksum_tg_init(void)6060+{6161+ return xt_register_target(&checksum_tg_reg);6262+}6363+6464+static void __exit checksum_tg_exit(void)6565+{6666+ xt_unregister_target(&checksum_tg_reg);6767+}6868+6969+module_init(checksum_tg_init);7070+module_exit(checksum_tg_exit);
···11+/* Kernel module to match running CPU */22+33+/*44+ * Might be used to distribute connections on several daemons, if55+ * RPS (Remote Packet Steering) is enabled or NIC is multiqueue capable,66+ * each RX queue IRQ affined to one CPU (1:1 mapping)77+ *88+ */99+1010+/* (C) 2010 Eric Dumazet1111+ *1212+ * This program is free software; you can redistribute it and/or modify1313+ * it under the terms of the GNU General Public License version 2 as1414+ * published by the Free Software Foundation.1515+ */1616+1717+#include <linux/module.h>1818+#include <linux/skbuff.h>1919+#include <linux/netfilter/xt_cpu.h>2020+#include <linux/netfilter/x_tables.h>2121+2222+MODULE_LICENSE("GPL");2323+MODULE_AUTHOR("Eric Dumazet <eric.dumazet@gmail.com>");2424+MODULE_DESCRIPTION("Xtables: CPU match");2525+2626+static int cpu_mt_check(const struct xt_mtchk_param *par)2727+{2828+ const struct xt_cpu_info *info = par->matchinfo;2929+3030+ if (info->invert & ~1)3131+ return -EINVAL;3232+ return 0;3333+}3434+3535+static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)3636+{3737+ const struct xt_cpu_info *info = par->matchinfo;3838+3939+ return (info->cpu == smp_processor_id()) ^ info->invert;4040+}4141+4242+static struct xt_match cpu_mt_reg __read_mostly = {4343+ .name = "cpu",4444+ .revision = 0,4545+ .family = NFPROTO_UNSPEC,4646+ .checkentry = cpu_mt_check,4747+ .match = cpu_mt,4848+ .matchsize = sizeof(struct xt_cpu_info),4949+ .me = THIS_MODULE,5050+};5151+5252+static int __init cpu_mt_init(void)5353+{5454+ return xt_register_match(&cpu_mt_reg);5555+}5656+5757+static void __exit cpu_mt_exit(void)5858+{5959+ xt_unregister_match(&cpu_mt_reg);6060+}6161+6262+module_init(cpu_mt_init);6363+module_exit(cpu_mt_exit);
+189
net/netfilter/xt_ipvs.c
···11+/*22+ * xt_ipvs - kernel module to match IPVS connection properties33+ *44+ * Author: Hannes Eder <heder@google.com>55+ */66+77+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt88+99+#include <linux/module.h>1010+#include <linux/moduleparam.h>1111+#include <linux/spinlock.h>1212+#include <linux/skbuff.h>1313+#ifdef CONFIG_IP_VS_IPV61414+#include <net/ipv6.h>1515+#endif1616+#include <linux/ip_vs.h>1717+#include <linux/types.h>1818+#include <linux/netfilter/x_tables.h>1919+#include <linux/netfilter/x_tables.h>2020+#include <linux/netfilter/xt_ipvs.h>2121+#include <net/netfilter/nf_conntrack.h>2222+2323+#include <net/ip_vs.h>2424+2525+MODULE_AUTHOR("Hannes Eder <heder@google.com>");2626+MODULE_DESCRIPTION("Xtables: match IPVS connection properties");2727+MODULE_LICENSE("GPL");2828+MODULE_ALIAS("ipt_ipvs");2929+MODULE_ALIAS("ip6t_ipvs");3030+3131+/* borrowed from xt_conntrack */3232+static bool ipvs_mt_addrcmp(const union nf_inet_addr *kaddr,3333+ const union nf_inet_addr *uaddr,3434+ const union nf_inet_addr *umask,3535+ unsigned int l3proto)3636+{3737+ if (l3proto == NFPROTO_IPV4)3838+ return ((kaddr->ip ^ uaddr->ip) & umask->ip) == 0;3939+#ifdef CONFIG_IP_VS_IPV64040+ else if (l3proto == NFPROTO_IPV6)4141+ return ipv6_masked_addr_cmp(&kaddr->in6, &umask->in6,4242+ &uaddr->in6) == 0;4343+#endif4444+ else4545+ return false;4646+}4747+4848+static bool4949+ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)5050+{5151+ const struct xt_ipvs_mtinfo *data = par->matchinfo;5252+ /* ipvs_mt_check ensures that family is only NFPROTO_IPV[46]. */5353+ const u_int8_t family = par->family;5454+ struct ip_vs_iphdr iph;5555+ struct ip_vs_protocol *pp;5656+ struct ip_vs_conn *cp;5757+ bool match = true;5858+5959+ if (data->bitmask == XT_IPVS_IPVS_PROPERTY) {6060+ match = skb->ipvs_property ^6161+ !!(data->invert & XT_IPVS_IPVS_PROPERTY);6262+ goto out;6363+ }6464+6565+ /* other flags than XT_IPVS_IPVS_PROPERTY are set */6666+ if (!skb->ipvs_property) {6767+ match = false;6868+ goto out;6969+ }7070+7171+ ip_vs_fill_iphdr(family, skb_network_header(skb), &iph);7272+7373+ if (data->bitmask & XT_IPVS_PROTO)7474+ if ((iph.protocol == data->l4proto) ^7575+ !(data->invert & XT_IPVS_PROTO)) {7676+ match = false;7777+ goto out;7878+ }7979+8080+ pp = ip_vs_proto_get(iph.protocol);8181+ if (unlikely(!pp)) {8282+ match = false;8383+ goto out;8484+ }8585+8686+ /*8787+ * Check if the packet belongs to an existing entry8888+ */8989+ cp = pp->conn_out_get(family, skb, pp, &iph, iph.len, 1 /* inverse */);9090+ if (unlikely(cp == NULL)) {9191+ match = false;9292+ goto out;9393+ }9494+9595+ /*9696+ * We found a connection, i.e. ct != 0, make sure to call9797+ * __ip_vs_conn_put before returning. In our case jump to out_put_con.9898+ */9999+100100+ if (data->bitmask & XT_IPVS_VPORT)101101+ if ((cp->vport == data->vport) ^102102+ !(data->invert & XT_IPVS_VPORT)) {103103+ match = false;104104+ goto out_put_cp;105105+ }106106+107107+ if (data->bitmask & XT_IPVS_VPORTCTL)108108+ if ((cp->control != NULL &&109109+ cp->control->vport == data->vportctl) ^110110+ !(data->invert & XT_IPVS_VPORTCTL)) {111111+ match = false;112112+ goto out_put_cp;113113+ }114114+115115+ if (data->bitmask & XT_IPVS_DIR) {116116+ enum ip_conntrack_info ctinfo;117117+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);118118+119119+ if (ct == NULL || nf_ct_is_untracked(ct)) {120120+ match = false;121121+ goto out_put_cp;122122+ }123123+124124+ if ((ctinfo >= IP_CT_IS_REPLY) ^125125+ !!(data->invert & XT_IPVS_DIR)) {126126+ match = false;127127+ goto out_put_cp;128128+ }129129+ }130130+131131+ if (data->bitmask & XT_IPVS_METHOD)132132+ if (((cp->flags & IP_VS_CONN_F_FWD_MASK) == data->fwd_method) ^133133+ !(data->invert & XT_IPVS_METHOD)) {134134+ match = false;135135+ goto out_put_cp;136136+ }137137+138138+ if (data->bitmask & XT_IPVS_VADDR) {139139+ if (ipvs_mt_addrcmp(&cp->vaddr, &data->vaddr,140140+ &data->vmask, family) ^141141+ !(data->invert & XT_IPVS_VADDR)) {142142+ match = false;143143+ goto out_put_cp;144144+ }145145+ }146146+147147+out_put_cp:148148+ __ip_vs_conn_put(cp);149149+out:150150+ pr_debug("match=%d\n", match);151151+ return match;152152+}153153+154154+static int ipvs_mt_check(const struct xt_mtchk_param *par)155155+{156156+ if (par->family != NFPROTO_IPV4157157+#ifdef CONFIG_IP_VS_IPV6158158+ && par->family != NFPROTO_IPV6159159+#endif160160+ ) {161161+ pr_info("protocol family %u not supported\n", par->family);162162+ return -EINVAL;163163+ }164164+165165+ return 0;166166+}167167+168168+static struct xt_match xt_ipvs_mt_reg __read_mostly = {169169+ .name = "ipvs",170170+ .revision = 0,171171+ .family = NFPROTO_UNSPEC,172172+ .match = ipvs_mt,173173+ .checkentry = ipvs_mt_check,174174+ .matchsize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),175175+ .me = THIS_MODULE,176176+};177177+178178+static int __init ipvs_mt_init(void)179179+{180180+ return xt_register_match(&xt_ipvs_mt_reg);181181+}182182+183183+static void __exit ipvs_mt_exit(void)184184+{185185+ xt_unregister_match(&xt_ipvs_mt_reg);186186+}187187+188188+module_init(ipvs_mt_init);189189+module_exit(ipvs_mt_exit);
+5-7
net/netfilter/xt_quota.c
···1111#include <linux/netfilter/xt_quota.h>12121313struct xt_quota_priv {1414- uint64_t quota;1414+ spinlock_t lock;1515+ uint64_t quota;1516};16171718MODULE_LICENSE("GPL");···2120MODULE_ALIAS("ipt_quota");2221MODULE_ALIAS("ip6t_quota");23222424-static DEFINE_SPINLOCK(quota_lock);2525-2623static bool2724quota_mt(const struct sk_buff *skb, struct xt_action_param *par)2825{···2829 struct xt_quota_priv *priv = q->master;2930 bool ret = q->flags & XT_QUOTA_INVERT;30313131- spin_lock_bh("a_lock);3232+ spin_lock_bh(&priv->lock);3233 if (priv->quota >= skb->len) {3334 priv->quota -= skb->len;3435 ret = !ret;···3637 /* we do not allow even small packets from now on */3738 priv->quota = 0;3839 }3939- /* Copy quota back to matchinfo so that iptables can display it */4040- q->quota = priv->quota;4141- spin_unlock_bh("a_lock);4040+ spin_unlock_bh(&priv->lock);42414342 return ret;4443}···5255 if (q->master == NULL)5356 return -ENOMEM;54575858+ spin_lock_init(&q->master->lock);5559 q->master->quota = q->quota;5660 return 0;5761}