···91919292void nf_ct_remove_expectations(struct nf_conn *ct);9393void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);9494-void nf_ct_remove_userspace_expectations(void);95949695/* Allocate space for an expectation: this is mandatory before calling9796 nf_ct_expect_related. You will have to call put afterwards. */
-1
include/net/netfilter/nf_conntrack_tuple.h
···12121313#include <linux/netfilter/x_tables.h>1414#include <linux/netfilter/nf_conntrack_tuple_common.h>1515-#include <linux/netfilter_ipv4/nf_nat.h>1615#include <linux/list_nulls.h>17161817/* A `tuple' is a structure containing the information to uniquely
+4-6
include/net/netfilter/nf_nat.h
···11#ifndef _NF_NAT_H22#define _NF_NAT_H33#include <linux/netfilter_ipv4.h>44-#include <linux/netfilter_ipv4/nf_nat.h>44+#include <linux/netfilter/nf_nat.h>55#include <net/netfilter/nf_conntrack_tuple.h>6677-#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 1688-97enum nf_nat_manip_type {1010- IP_NAT_MANIP_SRC,1111- IP_NAT_MANIP_DST88+ NF_NAT_MANIP_SRC,99+ NF_NAT_MANIP_DST1210};13111412/* SRC manip occurs POST_ROUTING or LOCAL_IN */···50525153/* Set up the info structure to map into this range. */5254extern unsigned int nf_nat_setup_info(struct nf_conn *ct,5353- const struct nf_nat_range *range,5555+ const struct nf_nat_ipv4_range *range,5456 enum nf_nat_manip_type maniptype);55575658/* Is this tuple already taken? (not by us)*/
+1-1
include/net/netfilter/nf_nat_core.h
···2020static inline int nf_nat_initialized(struct nf_conn *ct,2121 enum nf_nat_manip_type manip)2222{2323- if (manip == IP_NAT_MANIP_SRC)2323+ if (manip == NF_NAT_MANIP_SRC)2424 return ct->status & IPS_SRC_NAT_DONE;2525 else2626 return ct->status & IPS_DST_NAT_DONE;
+5-12
include/net/netfilter/nf_nat_protocol.h
···44#include <net/netfilter/nf_nat.h>55#include <linux/netfilter/nfnetlink_conntrack.h>6677-struct nf_nat_range;77+struct nf_nat_ipv4_range;8899struct nf_nat_protocol {1010 /* Protocol number. */1111 unsigned int protonum;1212-1313- struct module *me;14121513 /* Translate a packet to the target according to manip type.1614 Return true if succeeded. */···2830 possible. Per-protocol part of tuple is initialized to the2931 incoming packet. */3032 void (*unique_tuple)(struct nf_conntrack_tuple *tuple,3131- const struct nf_nat_range *range,3333+ const struct nf_nat_ipv4_range *range,3234 enum nf_nat_manip_type maniptype,3335 const struct nf_conn *ct);34363535- int (*range_to_nlattr)(struct sk_buff *skb,3636- const struct nf_nat_range *range);3737-3837 int (*nlattr_to_range)(struct nlattr *tb[],3939- struct nf_nat_range *range);3838+ struct nf_nat_ipv4_range *range);4039};41404241/* Protocol registration. */···5661 const union nf_conntrack_man_proto *max);57625863extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,5959- const struct nf_nat_range *range,6464+ const struct nf_nat_ipv4_range *range,6065 enum nf_nat_manip_type maniptype,6166 const struct nf_conn *ct,6267 u_int16_t *rover);63686464-extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,6565- const struct nf_nat_range *range);6669extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],6767- struct nf_nat_range *range);7070+ struct nf_nat_ipv4_range *range);68716972#endif /*_NF_NAT_PROTO_H*/
+1
net/ipv4/fib_rules.c
···67676868 return err;6969}7070+EXPORT_SYMBOL_GPL(fib_lookup);70717172static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,7273 int flags, struct fib_lookup_arg *arg)
···82828383 To compile it as a module, choose M here. If unsure, say N.84848585+config IP_NF_MATCH_RPFILTER8686+ tristate '"rpfilter" reverse path filter match support'8787+ depends on NETFILTER_ADVANCED8888+ ---help---8989+ This option allows you to match packets whose replies would9090+ go out via the interface the packet came in.9191+9292+ To compile it as a module, choose M here. If unsure, say N.9393+ The module will be called ipt_rpfilter.9494+8595config IP_NF_MATCH_TTL8696 tristate '"ttl" match support'8797 depends on NETFILTER_ADVANCED
···125125126126 To compile it as a module, choose M here. If unsure, say N.127127128128+config IP6_NF_MATCH_RPFILTER129129+ tristate '"rpfilter" reverse path filter match support'130130+ depends on NETFILTER_ADVANCED131131+ ---help---132132+ This option allows you to match packets whose replies would133133+ go out via the interface the packet came in.134134+135135+ To compile it as a module, choose M here. If unsure, say N.136136+ The module will be called ip6t_rpfilter.137137+128138config IP6_NF_MATCH_RT129139 tristate '"rt" Routing header match support'130140 depends on NETFILTER_ADVANCED
···11+/*22+ * Copyright (c) 2011 Florian Westphal <fw@strlen.de>33+ *44+ * This program is free software; you can redistribute it and/or modify55+ * it under the terms of the GNU General Public License version 2 as66+ * published by the Free Software Foundation.77+ */88+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt99+#include <linux/module.h>1010+#include <linux/skbuff.h>1111+#include <linux/netdevice.h>1212+#include <linux/route.h>1313+#include <net/ip6_fib.h>1414+#include <net/ip6_route.h>1515+1616+#include <linux/netfilter/xt_rpfilter.h>1717+#include <linux/netfilter/x_tables.h>1818+1919+MODULE_LICENSE("GPL");2020+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");2121+MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match");2222+2323+static bool rpfilter_addr_unicast(const struct in6_addr *addr)2424+{2525+ int addr_type = ipv6_addr_type(addr);2626+ return addr_type & IPV6_ADDR_UNICAST;2727+}2828+2929+static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,3030+ const struct net_device *dev, u8 flags)3131+{3232+ struct rt6_info *rt;3333+ struct ipv6hdr *iph = ipv6_hdr(skb);3434+ bool ret = false;3535+ struct flowi6 fl6 = {3636+ .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,3737+ .flowi6_proto = iph->nexthdr,3838+ .daddr = iph->saddr,3939+ };4040+ int lookup_flags;4141+4242+ if (rpfilter_addr_unicast(&iph->daddr)) {4343+ memcpy(&fl6.saddr, &iph->daddr, sizeof(struct in6_addr));4444+ lookup_flags = RT6_LOOKUP_F_HAS_SADDR;4545+ } else {4646+ lookup_flags = 0;4747+ }4848+4949+ fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;5050+ if ((flags & XT_RPFILTER_LOOSE) == 0) {5151+ fl6.flowi6_oif = dev->ifindex;5252+ lookup_flags |= RT6_LOOKUP_F_IFACE;5353+ }5454+5555+ rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags);5656+ if (rt->dst.error)5757+ goto out;5858+5959+ if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST))6060+ goto out;6161+6262+ if (rt->rt6i_flags & RTF_LOCAL) {6363+ ret = flags & XT_RPFILTER_ACCEPT_LOCAL;6464+ goto out;6565+ }6666+6767+ if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))6868+ ret = true;6969+ out:7070+ dst_release(&rt->dst);7171+ return ret;7272+}7373+7474+static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)7575+{7676+ const struct xt_rpfilter_info *info = par->matchinfo;7777+ int saddrtype;7878+ struct ipv6hdr *iph;7979+ bool invert = info->flags & XT_RPFILTER_INVERT;8080+8181+ if (par->in->flags & IFF_LOOPBACK)8282+ return true ^ invert;8383+8484+ iph = ipv6_hdr(skb);8585+ saddrtype = ipv6_addr_type(&iph->saddr);8686+ if (unlikely(saddrtype == IPV6_ADDR_ANY))8787+ return true ^ invert; /* not routable: forward path will drop it */8888+8989+ return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert;9090+}9191+9292+static int rpfilter_check(const struct xt_mtchk_param *par)9393+{9494+ const struct xt_rpfilter_info *info = par->matchinfo;9595+ unsigned int options = ~XT_RPFILTER_OPTION_MASK;9696+9797+ if (info->flags & options) {9898+ pr_info("unknown options encountered");9999+ return -EINVAL;100100+ }101101+102102+ if (strcmp(par->table, "mangle") != 0 &&103103+ strcmp(par->table, "raw") != 0) {104104+ pr_info("match only valid in the \'raw\' "105105+ "or \'mangle\' tables, not \'%s\'.\n", par->table);106106+ return -EINVAL;107107+ }108108+109109+ return 0;110110+}111111+112112+static struct xt_match rpfilter_mt_reg __read_mostly = {113113+ .name = "rpfilter",114114+ .family = NFPROTO_IPV6,115115+ .checkentry = rpfilter_check,116116+ .match = rpfilter_mt,117117+ .matchsize = sizeof(struct xt_rpfilter_info),118118+ .hooks = (1 << NF_INET_PRE_ROUTING),119119+ .me = THIS_MODULE120120+};121121+122122+static int __init rpfilter_mt_init(void)123123+{124124+ return xt_register_match(&rpfilter_mt_reg);125125+}126126+127127+static void __exit rpfilter_mt_exit(void)128128+{129129+ xt_unregister_match(&rpfilter_mt_reg);130130+}131131+132132+module_init(rpfilter_mt_init);133133+module_exit(rpfilter_mt_exit);
+7
net/ipv6/route.c
···658658659659}660660661661+struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6,662662+ int flags)663663+{664664+ return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);665665+}666666+EXPORT_SYMBOL_GPL(ip6_route_lookup);667667+661668struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,662669 const struct in6_addr *saddr, int oif, int strict)663670{
+18
net/netfilter/Kconfig
···44config NETFILTER_NETLINK55 tristate6677+config NETFILTER_NETLINK_ACCT88+tristate "Netfilter NFACCT over NFNETLINK interface"99+ depends on NETFILTER_ADVANCED1010+ select NETFILTER_NETLINK1111+ help1212+ If this option is enabled, the kernel will include support1313+ for extended accounting via NFNETLINK.1414+715config NETFILTER_NETLINK_QUEUE816 tristate "Netfilter NFQUEUE over NFNETLINK interface"917 depends on NETFILTER_ADVANCED···884876 Multiport matching allows you to match TCP or UDP packets based on885877 a series of source or destination ports: normally a rule can only886878 match a single range of ports.879879+880880+ To compile it as a module, choose M here. If unsure, say N.881881+882882+config NETFILTER_XT_MATCH_NFACCT883883+ tristate '"nfacct" match support'884884+ default m if NETFILTER_ADVANCED=n885885+ select NETFILTER_NETLINK_ACCT886886+ help887887+ This option allows you to use the extended accounting through888888+ nfnetlink_acct.887889888890 To compile it as a module, choose M here. If unsure, say N.889891
···232232 If you want to compile it in kernel, say Y. To compile it as a233233 module, choose M here. If unsure, say N.234234235235+comment 'IPVS SH scheduler'236236+237237+config IP_VS_SH_TAB_BITS238238+ int "IPVS source hashing table size (the Nth power of 2)"239239+ range 4 20240240+ default 8241241+ ---help---242242+ The source hashing scheduler maps source IPs to destinations243243+ stored in a hash table. This table is tiled by each destination244244+ until all slots in the table are filled. When using weights to245245+ allow destinations to receive more connections, the table is246246+ tiled an amount proportional to the weights specified. The table247247+ needs to be large enough to effectively fit all the destinations248248+ multiplied by their respective weights.249249+235250comment 'IPVS application helper'236251237252config IP_VS_FTP
+17-1
net/netfilter/ipvs/ip_vs_sh.c
···3030 * server is dead or overloaded, the load balancer can bypass the cache3131 * server and send requests to the original server directly.3232 *3333+ * The weight destination attribute can be used to control the3434+ * distribution of connections to the destinations in servernode. The3535+ * greater the weight, the more connections the destination3636+ * will receive.3737+ *3338 */34393540#define KMSG_COMPONENT "IPVS"···10499 struct ip_vs_sh_bucket *b;105100 struct list_head *p;106101 struct ip_vs_dest *dest;102102+ int d_count;107103108104 b = tbl;109105 p = &svc->destinations;106106+ d_count = 0;110107 for (i=0; i<IP_VS_SH_TAB_SIZE; i++) {111108 if (list_empty(p)) {112109 b->dest = NULL;···120113 atomic_inc(&dest->refcnt);121114 b->dest = dest;122115123123- p = p->next;116116+ IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n",117117+ i, IP_VS_DBG_ADDR(svc->af, &dest->addr),118118+ atomic_read(&dest->weight));119119+120120+ /* Don't move to next dest until filling weight */121121+ if (++d_count >= atomic_read(&dest->weight)) {122122+ p = p->next;123123+ d_count = 0;124124+ }125125+124126 }125127 b++;126128 }
+2-2
net/netfilter/nf_conntrack_acct.c
···4646 return 0;47474848 return seq_printf(s, "packets=%llu bytes=%llu ",4949- (unsigned long long)acct[dir].packets,5050- (unsigned long long)acct[dir].bytes);4949+ (unsigned long long)atomic64_read(&acct[dir].packets),5050+ (unsigned long long)atomic64_read(&acct[dir].bytes));5151};5252EXPORT_SYMBOL_GPL(seq_print_acct);5353
···11+/*22+ * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org>33+ * (C) 2011 Intra2net AG <http://www.intra2net.com>44+ *55+ * This program is free software; you can redistribute it and/or modify66+ * it under the terms of the GNU General Public License version 2 as77+ * published by the Free Software Foundation (or any later at your option).88+ */99+#include <linux/init.h>1010+#include <linux/module.h>1111+#include <linux/kernel.h>1212+#include <linux/skbuff.h>1313+#include <linux/netlink.h>1414+#include <linux/rculist.h>1515+#include <linux/slab.h>1616+#include <linux/types.h>1717+#include <linux/errno.h>1818+#include <net/netlink.h>1919+#include <net/sock.h>2020+#include <asm/atomic.h>2121+2222+#include <linux/netfilter.h>2323+#include <linux/netfilter/nfnetlink.h>2424+#include <linux/netfilter/nfnetlink_acct.h>2525+2626+MODULE_LICENSE("GPL");2727+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");2828+MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure");2929+3030+static LIST_HEAD(nfnl_acct_list);3131+3232+struct nf_acct {3333+ atomic64_t pkts;3434+ atomic64_t bytes;3535+ struct list_head head;3636+ atomic_t refcnt;3737+ char name[NFACCT_NAME_MAX];3838+ struct rcu_head rcu_head;3939+};4040+4141+static int4242+nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,4343+ const struct nlmsghdr *nlh, const struct nlattr * const tb[])4444+{4545+ struct nf_acct *nfacct, *matching = NULL;4646+ char *acct_name;4747+4848+ if (!tb[NFACCT_NAME])4949+ return -EINVAL;5050+5151+ acct_name = nla_data(tb[NFACCT_NAME]);5252+5353+ list_for_each_entry(nfacct, &nfnl_acct_list, head) {5454+ if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)5555+ continue;5656+5757+ if (nlh->nlmsg_flags & NLM_F_EXCL)5858+ return -EEXIST;5959+6060+ matching = nfacct;6161+ break;6262+ }6363+6464+ if (matching) {6565+ if (nlh->nlmsg_flags & NLM_F_REPLACE) {6666+ /* reset counters if you request a replacement. */6767+ atomic64_set(&matching->pkts, 0);6868+ atomic64_set(&matching->bytes, 0);6969+ return 0;7070+ }7171+ return -EBUSY;7272+ }7373+7474+ nfacct = kzalloc(sizeof(struct nf_acct), GFP_KERNEL);7575+ if (nfacct == NULL)7676+ return -ENOMEM;7777+7878+ strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);7979+8080+ if (tb[NFACCT_BYTES]) {8181+ atomic64_set(&nfacct->bytes,8282+ be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES])));8383+ }8484+ if (tb[NFACCT_PKTS]) {8585+ atomic64_set(&nfacct->pkts,8686+ be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS])));8787+ }8888+ atomic_set(&nfacct->refcnt, 1);8989+ list_add_tail_rcu(&nfacct->head, &nfnl_acct_list);9090+ return 0;9191+}9292+9393+static int9494+nfnl_acct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,9595+ int event, struct nf_acct *acct)9696+{9797+ struct nlmsghdr *nlh;9898+ struct nfgenmsg *nfmsg;9999+ unsigned int flags = pid ? NLM_F_MULTI : 0;100100+ u64 pkts, bytes;101101+102102+ event |= NFNL_SUBSYS_ACCT << 8;103103+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);104104+ if (nlh == NULL)105105+ goto nlmsg_failure;106106+107107+ nfmsg = nlmsg_data(nlh);108108+ nfmsg->nfgen_family = AF_UNSPEC;109109+ nfmsg->version = NFNETLINK_V0;110110+ nfmsg->res_id = 0;111111+112112+ NLA_PUT_STRING(skb, NFACCT_NAME, acct->name);113113+114114+ if (type == NFNL_MSG_ACCT_GET_CTRZERO) {115115+ pkts = atomic64_xchg(&acct->pkts, 0);116116+ bytes = atomic64_xchg(&acct->bytes, 0);117117+ } else {118118+ pkts = atomic64_read(&acct->pkts);119119+ bytes = atomic64_read(&acct->bytes);120120+ }121121+ NLA_PUT_BE64(skb, NFACCT_PKTS, cpu_to_be64(pkts));122122+ NLA_PUT_BE64(skb, NFACCT_BYTES, cpu_to_be64(bytes));123123+ NLA_PUT_BE32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt)));124124+125125+ nlmsg_end(skb, nlh);126126+ return skb->len;127127+128128+nlmsg_failure:129129+nla_put_failure:130130+ nlmsg_cancel(skb, nlh);131131+ return -1;132132+}133133+134134+static int135135+nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)136136+{137137+ struct nf_acct *cur, *last;138138+139139+ if (cb->args[2])140140+ return 0;141141+142142+ last = (struct nf_acct *)cb->args[1];143143+ if (cb->args[1])144144+ cb->args[1] = 0;145145+146146+ rcu_read_lock();147147+ list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {148148+ if (last && cur != last)149149+ continue;150150+151151+ if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).pid,152152+ cb->nlh->nlmsg_seq,153153+ NFNL_MSG_TYPE(cb->nlh->nlmsg_type),154154+ NFNL_MSG_ACCT_NEW, cur) < 0) {155155+ cb->args[1] = (unsigned long)cur;156156+ break;157157+ }158158+ }159159+ if (!cb->args[1])160160+ cb->args[2] = 1;161161+ rcu_read_unlock();162162+ return skb->len;163163+}164164+165165+static int166166+nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,167167+ const struct nlmsghdr *nlh, const struct nlattr * const tb[])168168+{169169+ int ret = 0;170170+ struct nf_acct *cur;171171+ char *acct_name;172172+173173+ if (nlh->nlmsg_flags & NLM_F_DUMP) {174174+ return netlink_dump_start(nfnl, skb, nlh, nfnl_acct_dump,175175+ NULL, 0);176176+ }177177+178178+ if (!tb[NFACCT_NAME])179179+ return -EINVAL;180180+ acct_name = nla_data(tb[NFACCT_NAME]);181181+182182+ list_for_each_entry(cur, &nfnl_acct_list, head) {183183+ struct sk_buff *skb2;184184+185185+ if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)186186+ continue;187187+188188+ skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);189189+ if (skb2 == NULL)190190+ break;191191+192192+ ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).pid,193193+ nlh->nlmsg_seq,194194+ NFNL_MSG_TYPE(nlh->nlmsg_type),195195+ NFNL_MSG_ACCT_NEW, cur);196196+ if (ret <= 0)197197+ kfree_skb(skb2);198198+199199+ break;200200+ }201201+ return ret;202202+}203203+204204+/* try to delete object, fail if it is still in use. */205205+static int nfnl_acct_try_del(struct nf_acct *cur)206206+{207207+ int ret = 0;208208+209209+ /* we want to avoid races with nfnl_acct_find_get. */210210+ if (atomic_dec_and_test(&cur->refcnt)) {211211+ /* We are protected by nfnl mutex. */212212+ list_del_rcu(&cur->head);213213+ kfree_rcu(cur, rcu_head);214214+ } else {215215+ /* still in use, restore reference counter. */216216+ atomic_inc(&cur->refcnt);217217+ ret = -EBUSY;218218+ }219219+ return ret;220220+}221221+222222+static int223223+nfnl_acct_del(struct sock *nfnl, struct sk_buff *skb,224224+ const struct nlmsghdr *nlh, const struct nlattr * const tb[])225225+{226226+ char *acct_name;227227+ struct nf_acct *cur;228228+ int ret = -ENOENT;229229+230230+ if (!tb[NFACCT_NAME]) {231231+ list_for_each_entry(cur, &nfnl_acct_list, head)232232+ nfnl_acct_try_del(cur);233233+234234+ return 0;235235+ }236236+ acct_name = nla_data(tb[NFACCT_NAME]);237237+238238+ list_for_each_entry(cur, &nfnl_acct_list, head) {239239+ if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0)240240+ continue;241241+242242+ ret = nfnl_acct_try_del(cur);243243+ if (ret < 0)244244+ return ret;245245+246246+ break;247247+ }248248+ return ret;249249+}250250+251251+static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {252252+ [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 },253253+ [NFACCT_BYTES] = { .type = NLA_U64 },254254+ [NFACCT_PKTS] = { .type = NLA_U64 },255255+};256256+257257+static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {258258+ [NFNL_MSG_ACCT_NEW] = { .call = nfnl_acct_new,259259+ .attr_count = NFACCT_MAX,260260+ .policy = nfnl_acct_policy },261261+ [NFNL_MSG_ACCT_GET] = { .call = nfnl_acct_get,262262+ .attr_count = NFACCT_MAX,263263+ .policy = nfnl_acct_policy },264264+ [NFNL_MSG_ACCT_GET_CTRZERO] = { .call = nfnl_acct_get,265265+ .attr_count = NFACCT_MAX,266266+ .policy = nfnl_acct_policy },267267+ [NFNL_MSG_ACCT_DEL] = { .call = nfnl_acct_del,268268+ .attr_count = NFACCT_MAX,269269+ .policy = nfnl_acct_policy },270270+};271271+272272+static const struct nfnetlink_subsystem nfnl_acct_subsys = {273273+ .name = "acct",274274+ .subsys_id = NFNL_SUBSYS_ACCT,275275+ .cb_count = NFNL_MSG_ACCT_MAX,276276+ .cb = nfnl_acct_cb,277277+};278278+279279+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT);280280+281281+struct nf_acct *nfnl_acct_find_get(const char *acct_name)282282+{283283+ struct nf_acct *cur, *acct = NULL;284284+285285+ rcu_read_lock();286286+ list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {287287+ if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)288288+ continue;289289+290290+ if (!try_module_get(THIS_MODULE))291291+ goto err;292292+293293+ if (!atomic_inc_not_zero(&cur->refcnt)) {294294+ module_put(THIS_MODULE);295295+ goto err;296296+ }297297+298298+ acct = cur;299299+ break;300300+ }301301+err:302302+ rcu_read_unlock();303303+ return acct;304304+}305305+EXPORT_SYMBOL_GPL(nfnl_acct_find_get);306306+307307+void nfnl_acct_put(struct nf_acct *acct)308308+{309309+ atomic_dec(&acct->refcnt);310310+ module_put(THIS_MODULE);311311+}312312+EXPORT_SYMBOL_GPL(nfnl_acct_put);313313+314314+void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct)315315+{316316+ atomic64_inc(&nfacct->pkts);317317+ atomic64_add(skb->len, &nfacct->bytes);318318+}319319+EXPORT_SYMBOL_GPL(nfnl_acct_update);320320+321321+static int __init nfnl_acct_init(void)322322+{323323+ int ret;324324+325325+ pr_info("nfnl_acct: registering with nfnetlink.\n");326326+ ret = nfnetlink_subsys_register(&nfnl_acct_subsys);327327+ if (ret < 0) {328328+ pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");329329+ goto err_out;330330+ }331331+ return 0;332332+err_out:333333+ return ret;334334+}335335+336336+static void __exit nfnl_acct_exit(void)337337+{338338+ struct nf_acct *cur, *tmp;339339+340340+ pr_info("nfnl_acct: unregistering from nfnetlink.\n");341341+ nfnetlink_subsys_unregister(&nfnl_acct_subsys);342342+343343+ list_for_each_entry_safe(cur, tmp, &nfnl_acct_list, head) {344344+ list_del_rcu(&cur->head);345345+ /* We are sure that our objects have no clients at this point,346346+ * it's safe to release them all without checking refcnt. */347347+ kfree_rcu(cur, rcu_head);348348+ }349349+}350350+351351+module_init(nfnl_acct_init);352352+module_exit(nfnl_acct_exit);
+5-3
net/netfilter/xt_CT.c
···6262 int ret = 0;6363 u8 proto;64646565- if (info->flags & ~XT_CT_NOTRACK)6666- return -EINVAL;6565+ if (info->flags & ~(XT_CT_NOTRACK | XT_CT_USERSPACE_HELPER))6666+ return -EOPNOTSUPP;67676868 if (info->flags & XT_CT_NOTRACK) {6969 ct = nf_ct_untracked_get();···9292 GFP_KERNEL))9393 goto err3;94949595- if (info->helper[0]) {9595+ if (info->flags & XT_CT_USERSPACE_HELPER) {9696+ __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);9797+ } else if (info->helper[0]) {9698 ret = -ENOENT;9799 proto = xt_ct_find_proto(par);98100 if (!proto) {
+16-16
net/netfilter/xt_connbytes.c
···4040 case XT_CONNBYTES_PKTS:4141 switch (sinfo->direction) {4242 case XT_CONNBYTES_DIR_ORIGINAL:4343- what = counters[IP_CT_DIR_ORIGINAL].packets;4343+ what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);4444 break;4545 case XT_CONNBYTES_DIR_REPLY:4646- what = counters[IP_CT_DIR_REPLY].packets;4646+ what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);4747 break;4848 case XT_CONNBYTES_DIR_BOTH:4949- what = counters[IP_CT_DIR_ORIGINAL].packets;5050- what += counters[IP_CT_DIR_REPLY].packets;4949+ what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);5050+ what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);5151 break;5252 }5353 break;5454 case XT_CONNBYTES_BYTES:5555 switch (sinfo->direction) {5656 case XT_CONNBYTES_DIR_ORIGINAL:5757- what = counters[IP_CT_DIR_ORIGINAL].bytes;5757+ what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);5858 break;5959 case XT_CONNBYTES_DIR_REPLY:6060- what = counters[IP_CT_DIR_REPLY].bytes;6060+ what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);6161 break;6262 case XT_CONNBYTES_DIR_BOTH:6363- what = counters[IP_CT_DIR_ORIGINAL].bytes;6464- what += counters[IP_CT_DIR_REPLY].bytes;6363+ what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);6464+ what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);6565 break;6666 }6767 break;6868 case XT_CONNBYTES_AVGPKT:6969 switch (sinfo->direction) {7070 case XT_CONNBYTES_DIR_ORIGINAL:7171- bytes = counters[IP_CT_DIR_ORIGINAL].bytes;7272- pkts = counters[IP_CT_DIR_ORIGINAL].packets;7171+ bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);7272+ pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);7373 break;7474 case XT_CONNBYTES_DIR_REPLY:7575- bytes = counters[IP_CT_DIR_REPLY].bytes;7676- pkts = counters[IP_CT_DIR_REPLY].packets;7575+ bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);7676+ pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);7777 break;7878 case XT_CONNBYTES_DIR_BOTH:7979- bytes = counters[IP_CT_DIR_ORIGINAL].bytes +8080- counters[IP_CT_DIR_REPLY].bytes;8181- pkts = counters[IP_CT_DIR_ORIGINAL].packets +8282- counters[IP_CT_DIR_REPLY].packets;7979+ bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +8080+ atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);8181+ pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +8282+ atomic64_read(&counters[IP_CT_DIR_REPLY].packets);8383 break;8484 }8585 if (pkts != 0)
+76
net/netfilter/xt_nfacct.c
···11+/*22+ * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org>33+ * (C) 2011 Intra2net AG <http://www.intra2net.com>44+ *55+ * This program is free software; you can redistribute it and/or modify66+ * it under the terms of the GNU General Public License version 2 (or any77+ * later at your option) as published by the Free Software Foundation.88+ */99+#include <linux/module.h>1010+#include <linux/skbuff.h>1111+1212+#include <linux/netfilter/x_tables.h>1313+#include <linux/netfilter/nfnetlink_acct.h>1414+#include <linux/netfilter/xt_nfacct.h>1515+1616+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");1717+MODULE_DESCRIPTION("Xtables: match for the extended accounting infrastructure");1818+MODULE_LICENSE("GPL");1919+MODULE_ALIAS("ipt_nfacct");2020+MODULE_ALIAS("ip6t_nfacct");2121+2222+static bool nfacct_mt(const struct sk_buff *skb, struct xt_action_param *par)2323+{2424+ const struct xt_nfacct_match_info *info = par->targinfo;2525+2626+ nfnl_acct_update(skb, info->nfacct);2727+2828+ return true;2929+}3030+3131+static int3232+nfacct_mt_checkentry(const struct xt_mtchk_param *par)3333+{3434+ struct xt_nfacct_match_info *info = par->matchinfo;3535+ struct nf_acct *nfacct;3636+3737+ nfacct = nfnl_acct_find_get(info->name);3838+ if (nfacct == NULL) {3939+ pr_info("xt_nfacct: accounting object with name `%s' "4040+ "does not exists\n", info->name);4141+ return -ENOENT;4242+ }4343+ info->nfacct = nfacct;4444+ return 0;4545+}4646+4747+static void4848+nfacct_mt_destroy(const struct xt_mtdtor_param *par)4949+{5050+ const struct xt_nfacct_match_info *info = par->matchinfo;5151+5252+ nfnl_acct_put(info->nfacct);5353+}5454+5555+static struct xt_match nfacct_mt_reg __read_mostly = {5656+ .name = "nfacct",5757+ .family = NFPROTO_UNSPEC,5858+ .checkentry = nfacct_mt_checkentry,5959+ .match = nfacct_mt,6060+ .destroy = nfacct_mt_destroy,6161+ .matchsize = sizeof(struct xt_nfacct_match_info),6262+ .me = THIS_MODULE,6363+};6464+6565+static int __init nfacct_mt_init(void)6666+{6767+ return xt_register_match(&nfacct_mt_reg);6868+}6969+7070+static void __exit nfacct_mt_exit(void)7171+{7272+ xt_unregister_match(&nfacct_mt_reg);7373+}7474+7575+module_init(nfacct_mt_init);7676+module_exit(nfacct_mt_exit);