aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_conntrack_tcp.h5
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h4
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c45
3 files changed, 53 insertions, 1 deletions
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h
index 007af4c2770b..22ce29995f13 100644
--- a/include/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/linux/netfilter/nf_conntrack_tcp.h
@@ -30,6 +30,11 @@ enum tcp_conntrack {
30/* Be liberal in window checking */ 30/* Be liberal in window checking */
31#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08 31#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08
32 32
33struct nf_ct_tcp_flags {
34 u_int8_t flags;
35 u_int8_t mask;
36};
37
33#ifdef __KERNEL__ 38#ifdef __KERNEL__
34 39
35struct ip_ct_tcp_state { 40struct ip_ct_tcp_state {
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index b5883ccee295..d7c35039721e 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -83,6 +83,10 @@ enum ctattr_protoinfo {
83enum ctattr_protoinfo_tcp { 83enum ctattr_protoinfo_tcp {
84 CTA_PROTOINFO_TCP_UNSPEC, 84 CTA_PROTOINFO_TCP_UNSPEC,
85 CTA_PROTOINFO_TCP_STATE, 85 CTA_PROTOINFO_TCP_STATE,
86 CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
87 CTA_PROTOINFO_TCP_WSCALE_REPLY,
88 CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
89 CTA_PROTOINFO_TCP_FLAGS_REPLY,
86 __CTA_PROTOINFO_TCP_MAX 90 __CTA_PROTOINFO_TCP_MAX
87}; 91};
88#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) 92#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index a1363626bccc..8439768f9d1c 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1101,11 +1101,26 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
1101 const struct nf_conn *ct) 1101 const struct nf_conn *ct)
1102{ 1102{
1103 struct nfattr *nest_parms; 1103 struct nfattr *nest_parms;
1104 struct nf_ct_tcp_flags tmp = {};
1104 1105
1105 read_lock_bh(&tcp_lock); 1106 read_lock_bh(&tcp_lock);
1106 nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP); 1107 nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
1107 NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t), 1108 NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
1108 &ct->proto.tcp.state); 1109 &ct->proto.tcp.state);
1110
1111 NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
1112 &ct->proto.tcp.seen[0].td_scale);
1113
1114 NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
1115 &ct->proto.tcp.seen[1].td_scale);
1116
1117 tmp.flags = ct->proto.tcp.seen[0].flags;
1118 NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
1119 sizeof(struct nf_ct_tcp_flags), &tmp);
1120
1121 tmp.flags = ct->proto.tcp.seen[1].flags;
1122 NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
1123 sizeof(struct nf_ct_tcp_flags), &tmp);
1109 read_unlock_bh(&tcp_lock); 1124 read_unlock_bh(&tcp_lock);
1110 1125
1111 NFA_NEST_END(skb, nest_parms); 1126 NFA_NEST_END(skb, nest_parms);
@@ -1118,7 +1133,11 @@ nfattr_failure:
1118} 1133}
1119 1134
1120static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = { 1135static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
1121 [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t), 1136 [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
1137 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] = sizeof(u_int8_t),
1138 [CTA_PROTOINFO_TCP_WSCALE_REPLY-1] = sizeof(u_int8_t),
1139 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1] = sizeof(struct nf_ct_tcp_flags),
1140 [CTA_PROTOINFO_TCP_FLAGS_REPLY-1] = sizeof(struct nf_ct_tcp_flags)
1122}; 1141};
1123 1142
1124static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct) 1143static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
@@ -1142,6 +1161,30 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
1142 write_lock_bh(&tcp_lock); 1161 write_lock_bh(&tcp_lock);
1143 ct->proto.tcp.state = 1162 ct->proto.tcp.state =
1144 *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]); 1163 *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
1164
1165 if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]) {
1166 struct nf_ct_tcp_flags *attr =
1167 NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]);
1168 ct->proto.tcp.seen[0].flags &= ~attr->mask;
1169 ct->proto.tcp.seen[0].flags |= attr->flags & attr->mask;
1170 }
1171
1172 if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]) {
1173 struct nf_ct_tcp_flags *attr =
1174 NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]);
1175 ct->proto.tcp.seen[1].flags &= ~attr->mask;
1176 ct->proto.tcp.seen[1].flags |= attr->flags & attr->mask;
1177 }
1178
1179 if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] &&
1180 tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1] &&
1181 ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
1182 ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
1183 ct->proto.tcp.seen[0].td_scale = *(u_int8_t *)
1184 NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]);
1185 ct->proto.tcp.seen[1].td_scale = *(u_int8_t *)
1186 NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]);
1187 }
1145 write_unlock_bh(&tcp_lock); 1188 write_unlock_bh(&tcp_lock);
1146 1189
1147 return 0; 1190 return 0;