diff options
-rw-r--r-- | include/linux/netfilter/nf_conntrack_tcp.h | 5 | ||||
-rw-r--r-- | include/linux/netfilter/nfnetlink_conntrack.h | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 45 |
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 | ||
33 | struct nf_ct_tcp_flags { | ||
34 | u_int8_t flags; | ||
35 | u_int8_t mask; | ||
36 | }; | ||
37 | |||
33 | #ifdef __KERNEL__ | 38 | #ifdef __KERNEL__ |
34 | 39 | ||
35 | struct ip_ct_tcp_state { | 40 | struct 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 { | |||
83 | enum ctattr_protoinfo_tcp { | 83 | enum 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 | ||
1120 | static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = { | 1135 | static 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 | ||
1124 | static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct) | 1143 | static 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; |