|
@@ -42,6 +42,7 @@
|
|
#include <net/netfilter/nf_conntrack_tuple.h>
|
|
#include <net/netfilter/nf_conntrack_tuple.h>
|
|
#include <net/netfilter/nf_conntrack_acct.h>
|
|
#include <net/netfilter/nf_conntrack_acct.h>
|
|
#include <net/netfilter/nf_conntrack_zones.h>
|
|
#include <net/netfilter/nf_conntrack_zones.h>
|
|
|
|
+#include <net/netfilter/nf_conntrack_timestamp.h>
|
|
#ifdef CONFIG_NF_NAT_NEEDED
|
|
#ifdef CONFIG_NF_NAT_NEEDED
|
|
#include <net/netfilter/nf_nat_core.h>
|
|
#include <net/netfilter/nf_nat_core.h>
|
|
#include <net/netfilter/nf_nat_protocol.h>
|
|
#include <net/netfilter/nf_nat_protocol.h>
|
|
@@ -230,6 +231,33 @@ nla_put_failure:
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int
|
|
|
|
+ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct)
|
|
|
|
+{
|
|
|
|
+ struct nlattr *nest_count;
|
|
|
|
+ const struct nf_conn_tstamp *tstamp;
|
|
|
|
+
|
|
|
|
+ tstamp = nf_conn_tstamp_find(ct);
|
|
|
|
+ if (!tstamp)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ nest_count = nla_nest_start(skb, CTA_TIMESTAMP | NLA_F_NESTED);
|
|
|
|
+ if (!nest_count)
|
|
|
|
+ goto nla_put_failure;
|
|
|
|
+
|
|
|
|
+ NLA_PUT_BE64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start));
|
|
|
|
+ if (tstamp->stop != 0) {
|
|
|
|
+ NLA_PUT_BE64(skb, CTA_TIMESTAMP_STOP,
|
|
|
|
+ cpu_to_be64(tstamp->stop));
|
|
|
|
+ }
|
|
|
|
+ nla_nest_end(skb, nest_count);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+nla_put_failure:
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
#ifdef CONFIG_NF_CONNTRACK_MARK
|
|
#ifdef CONFIG_NF_CONNTRACK_MARK
|
|
static inline int
|
|
static inline int
|
|
ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
|
|
ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
|
|
@@ -404,6 +432,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
|
|
ctnetlink_dump_timeout(skb, ct) < 0 ||
|
|
ctnetlink_dump_timeout(skb, ct) < 0 ||
|
|
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
|
|
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
|
|
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
|
|
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
|
|
|
|
+ ctnetlink_dump_timestamp(skb, ct) < 0 ||
|
|
ctnetlink_dump_protoinfo(skb, ct) < 0 ||
|
|
ctnetlink_dump_protoinfo(skb, ct) < 0 ||
|
|
ctnetlink_dump_helpinfo(skb, ct) < 0 ||
|
|
ctnetlink_dump_helpinfo(skb, ct) < 0 ||
|
|
ctnetlink_dump_mark(skb, ct) < 0 ||
|
|
ctnetlink_dump_mark(skb, ct) < 0 ||
|
|
@@ -470,6 +499,18 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline size_t
|
|
|
|
+ctnetlink_timestamp_size(const struct nf_conn *ct)
|
|
|
|
+{
|
|
|
|
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
|
|
|
|
+ if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
|
|
|
|
+ return 0;
|
|
|
|
+ return nla_total_size(0) + 2 * nla_total_size(sizeof(uint64_t));
|
|
|
|
+#else
|
|
|
|
+ return 0;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
static inline size_t
|
|
static inline size_t
|
|
ctnetlink_nlmsg_size(const struct nf_conn *ct)
|
|
ctnetlink_nlmsg_size(const struct nf_conn *ct)
|
|
{
|
|
{
|
|
@@ -481,6 +522,7 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct)
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
|
|
+ ctnetlink_counters_size(ct)
|
|
+ ctnetlink_counters_size(ct)
|
|
|
|
+ + ctnetlink_timestamp_size(ct)
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
|
|
+ nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
|
|
+ nla_total_size(0) /* CTA_PROTOINFO */
|
|
+ nla_total_size(0) /* CTA_PROTOINFO */
|
|
+ nla_total_size(0) /* CTA_HELP */
|
|
+ nla_total_size(0) /* CTA_HELP */
|
|
@@ -571,7 +613,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
|
|
|
|
|
|
if (events & (1 << IPCT_DESTROY)) {
|
|
if (events & (1 << IPCT_DESTROY)) {
|
|
if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
|
|
if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
|
|
- ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
|
|
|
|
|
|
+ ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
|
|
|
|
+ ctnetlink_dump_timestamp(skb, ct) < 0)
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
} else {
|
|
} else {
|
|
if (ctnetlink_dump_timeout(skb, ct) < 0)
|
|
if (ctnetlink_dump_timeout(skb, ct) < 0)
|
|
@@ -1360,6 +1403,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
|
|
}
|
|
}
|
|
|
|
|
|
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
|
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
|
|
|
+ nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
|
|
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
|
|
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
|
|
/* we must add conntrack extensions before confirmation. */
|
|
/* we must add conntrack extensions before confirmation. */
|
|
ct->status |= IPS_CONFIRMED;
|
|
ct->status |= IPS_CONFIRMED;
|