aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c85
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
104enum ctattr_expect { 103enum 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
1100ctnetlink_exp_dump_expect(struct sk_buff *skb, 1100ctnetlink_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}
1371static int 1369static 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);