diff options
-rw-r--r-- | include/linux/netfilter/nfnetlink_conntrack.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 85 |
2 files changed, 41 insertions, 47 deletions
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index fb528e0e3bd9..5c55751c78e4 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h | |||
@@ -33,7 +33,6 @@ enum ctattr_type { | |||
33 | CTA_COUNTERS_ORIG, | 33 | CTA_COUNTERS_ORIG, |
34 | CTA_COUNTERS_REPLY, | 34 | CTA_COUNTERS_REPLY, |
35 | CTA_USE, | 35 | CTA_USE, |
36 | CTA_EXPECT, | ||
37 | CTA_ID, | 36 | CTA_ID, |
38 | __CTA_MAX | 37 | __CTA_MAX |
39 | }; | 38 | }; |
@@ -103,10 +102,12 @@ enum ctattr_protonat { | |||
103 | 102 | ||
104 | enum ctattr_expect { | 103 | enum ctattr_expect { |
105 | CTA_EXPECT_UNSPEC, | 104 | CTA_EXPECT_UNSPEC, |
105 | CTA_EXPECT_MASTER, | ||
106 | CTA_EXPECT_TUPLE, | 106 | CTA_EXPECT_TUPLE, |
107 | CTA_EXPECT_MASK, | 107 | CTA_EXPECT_MASK, |
108 | CTA_EXPECT_TIMEOUT, | 108 | CTA_EXPECT_TIMEOUT, |
109 | CTA_EXPECT_ID, | 109 | CTA_EXPECT_ID, |
110 | CTA_EXPECT_HELP_NAME, | ||
110 | __CTA_EXPECT_MAX | 111 | __CTA_EXPECT_MAX |
111 | }; | 112 | }; |
112 | #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) | 113 | #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 53d98974dcf0..f5bda82c2875 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -1100,18 +1100,21 @@ static inline int | |||
1100 | ctnetlink_exp_dump_expect(struct sk_buff *skb, | 1100 | ctnetlink_exp_dump_expect(struct sk_buff *skb, |
1101 | const struct ip_conntrack_expect *exp) | 1101 | const struct ip_conntrack_expect *exp) |
1102 | { | 1102 | { |
1103 | struct ip_conntrack *master = exp->master; | ||
1103 | u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ); | 1104 | u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ); |
1104 | u_int32_t id = htonl(exp->id); | 1105 | u_int32_t id = htonl(exp->id); |
1105 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT); | ||
1106 | 1106 | ||
1107 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) | 1107 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) |
1108 | goto nfattr_failure; | 1108 | goto nfattr_failure; |
1109 | if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) | 1109 | if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) |
1110 | goto nfattr_failure; | 1110 | goto nfattr_failure; |
1111 | if (ctnetlink_exp_dump_tuple(skb, | ||
1112 | &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | ||
1113 | CTA_EXPECT_MASTER) < 0) | ||
1114 | goto nfattr_failure; | ||
1111 | 1115 | ||
1112 | NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout); | 1116 | NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout); |
1113 | NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id); | 1117 | NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id); |
1114 | NFA_NEST_END(skb, nest_parms); | ||
1115 | 1118 | ||
1116 | return 0; | 1119 | return 0; |
1117 | 1120 | ||
@@ -1259,10 +1262,8 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1259 | return 0; | 1262 | return 0; |
1260 | } | 1263 | } |
1261 | 1264 | ||
1262 | if (cda[CTA_TUPLE_ORIG-1]) | 1265 | if (cda[CTA_EXPECT_MASTER-1]) |
1263 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); | 1266 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER); |
1264 | else if (cda[CTA_TUPLE_REPLY-1]) | ||
1265 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY); | ||
1266 | else | 1267 | else |
1267 | return -EINVAL; | 1268 | return -EINVAL; |
1268 | 1269 | ||
@@ -1310,13 +1311,33 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1310 | struct ip_conntrack_helper *h; | 1311 | struct ip_conntrack_helper *h; |
1311 | int err; | 1312 | int err; |
1312 | 1313 | ||
1313 | /* delete by tuple needs either orig or reply tuple */ | 1314 | if (cda[CTA_EXPECT_TUPLE-1]) { |
1314 | if (cda[CTA_TUPLE_ORIG-1]) | 1315 | /* delete a single expect by tuple */ |
1315 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); | 1316 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); |
1316 | else if (cda[CTA_TUPLE_REPLY-1]) | 1317 | if (err < 0) |
1317 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY); | 1318 | return err; |
1318 | else if (cda[CTA_HELP_NAME-1]) { | 1319 | |
1319 | char *name = NFA_DATA(cda[CTA_HELP_NAME-1]); | 1320 | /* bump usage count to 2 */ |
1321 | exp = ip_conntrack_expect_find_get(&tuple); | ||
1322 | if (!exp) | ||
1323 | return -ENOENT; | ||
1324 | |||
1325 | if (cda[CTA_EXPECT_ID-1]) { | ||
1326 | u_int32_t id = | ||
1327 | *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); | ||
1328 | if (exp->id != ntohl(id)) { | ||
1329 | ip_conntrack_expect_put(exp); | ||
1330 | return -ENOENT; | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | /* after list removal, usage count == 1 */ | ||
1335 | ip_conntrack_unexpect_related(exp); | ||
1336 | /* have to put what we 'get' above. | ||
1337 | * after this line usage count == 0 */ | ||
1338 | ip_conntrack_expect_put(exp); | ||
1339 | } else if (cda[CTA_EXPECT_HELP_NAME-1]) { | ||
1340 | char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); | ||
1320 | 1341 | ||
1321 | /* delete all expectations for this helper */ | 1342 | /* delete all expectations for this helper */ |
1322 | write_lock_bh(&ip_conntrack_lock); | 1343 | write_lock_bh(&ip_conntrack_lock); |
@@ -1332,7 +1353,6 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1332 | __ip_ct_expect_unlink_destroy(exp); | 1353 | __ip_ct_expect_unlink_destroy(exp); |
1333 | } | 1354 | } |
1334 | write_unlock(&ip_conntrack_lock); | 1355 | write_unlock(&ip_conntrack_lock); |
1335 | return 0; | ||
1336 | } else { | 1356 | } else { |
1337 | /* This basically means we have to flush everything*/ | 1357 | /* This basically means we have to flush everything*/ |
1338 | write_lock_bh(&ip_conntrack_lock); | 1358 | write_lock_bh(&ip_conntrack_lock); |
@@ -1342,30 +1362,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1342 | __ip_ct_expect_unlink_destroy(exp); | 1362 | __ip_ct_expect_unlink_destroy(exp); |
1343 | } | 1363 | } |
1344 | write_unlock_bh(&ip_conntrack_lock); | 1364 | write_unlock_bh(&ip_conntrack_lock); |
1345 | return 0; | ||
1346 | } | 1365 | } |
1347 | 1366 | ||
1348 | if (err < 0) | ||
1349 | return err; | ||
1350 | |||
1351 | /* bump usage count to 2 */ | ||
1352 | exp = ip_conntrack_expect_find_get(&tuple); | ||
1353 | if (!exp) | ||
1354 | return -ENOENT; | ||
1355 | |||
1356 | if (cda[CTA_EXPECT_ID-1]) { | ||
1357 | u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); | ||
1358 | if (exp->id != ntohl(id)) { | ||
1359 | ip_conntrack_expect_put(exp); | ||
1360 | return -ENOENT; | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | /* after list removal, usage count == 1 */ | ||
1365 | ip_conntrack_unexpect_related(exp); | ||
1366 | /* have to put what we 'get' above. after this line usage count == 0 */ | ||
1367 | ip_conntrack_expect_put(exp); | ||
1368 | |||
1369 | return 0; | 1367 | return 0; |
1370 | } | 1368 | } |
1371 | static int | 1369 | static int |
@@ -1385,21 +1383,14 @@ ctnetlink_create_expect(struct nfattr *cda[]) | |||
1385 | 1383 | ||
1386 | DEBUGP("entered %s\n", __FUNCTION__); | 1384 | DEBUGP("entered %s\n", __FUNCTION__); |
1387 | 1385 | ||
1386 | /* caller guarantees that those three CTA_EXPECT_* exist */ | ||
1388 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); | 1387 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); |
1389 | if (err < 0) | 1388 | if (err < 0) |
1390 | return err; | 1389 | return err; |
1391 | err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK); | 1390 | err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK); |
1392 | if (err < 0) | 1391 | if (err < 0) |
1393 | return err; | 1392 | return err; |
1394 | 1393 | err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER); | |
1395 | if (cda[CTA_TUPLE_ORIG-1]) | ||
1396 | err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_TUPLE_ORIG); | ||
1397 | else if (cda[CTA_TUPLE_REPLY-1]) | ||
1398 | err = ctnetlink_parse_tuple(cda, &master_tuple, | ||
1399 | CTA_TUPLE_REPLY); | ||
1400 | else | ||
1401 | return -EINVAL; | ||
1402 | |||
1403 | if (err < 0) | 1394 | if (err < 0) |
1404 | return err; | 1395 | return err; |
1405 | 1396 | ||
@@ -1444,7 +1435,9 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1444 | 1435 | ||
1445 | DEBUGP("entered %s\n", __FUNCTION__); | 1436 | DEBUGP("entered %s\n", __FUNCTION__); |
1446 | 1437 | ||
1447 | if (!cda[CTA_EXPECT_TUPLE-1] || !cda[CTA_EXPECT_MASK-1]) | 1438 | if (!cda[CTA_EXPECT_TUPLE-1] |
1439 | || !cda[CTA_EXPECT_MASK-1] | ||
1440 | || !cda[CTA_EXPECT_MASTER-1]) | ||
1448 | return -EINVAL; | 1441 | return -EINVAL; |
1449 | 1442 | ||
1450 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); | 1443 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); |