aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_conntrack_netlink.c43
1 files changed, 16 insertions, 27 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9307b033c0c9..cc705175765c 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1367,15 +1367,12 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
1367 nf_ct_protonum(ct)); 1367 nf_ct_protonum(ct));
1368 if (helper == NULL) { 1368 if (helper == NULL) {
1369 rcu_read_unlock(); 1369 rcu_read_unlock();
1370 spin_unlock_bh(&nf_conntrack_lock);
1371#ifdef CONFIG_MODULES 1370#ifdef CONFIG_MODULES
1372 if (request_module("nfct-helper-%s", helpname) < 0) { 1371 if (request_module("nfct-helper-%s", helpname) < 0) {
1373 spin_lock_bh(&nf_conntrack_lock);
1374 err = -EOPNOTSUPP; 1372 err = -EOPNOTSUPP;
1375 goto err1; 1373 goto err1;
1376 } 1374 }
1377 1375
1378 spin_lock_bh(&nf_conntrack_lock);
1379 rcu_read_lock(); 1376 rcu_read_lock();
1380 helper = __nf_conntrack_helper_find(helpname, 1377 helper = __nf_conntrack_helper_find(helpname,
1381 nf_ct_l3num(ct), 1378 nf_ct_l3num(ct),
@@ -1469,7 +1466,10 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
1469 tstamp->start = ktime_to_ns(ktime_get_real()); 1466 tstamp->start = ktime_to_ns(ktime_get_real());
1470 1467
1471 add_timer(&ct->timeout); 1468 add_timer(&ct->timeout);
1469 spin_lock_bh(&nf_conntrack_lock);
1472 nf_conntrack_hash_insert(ct); 1470 nf_conntrack_hash_insert(ct);
1471 nf_conntrack_get(&ct->ct_general);
1472 spin_unlock_bh(&nf_conntrack_lock);
1473 rcu_read_unlock(); 1473 rcu_read_unlock();
1474 1474
1475 return ct; 1475 return ct;
@@ -1490,6 +1490,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1490 struct nf_conntrack_tuple otuple, rtuple; 1490 struct nf_conntrack_tuple otuple, rtuple;
1491 struct nf_conntrack_tuple_hash *h = NULL; 1491 struct nf_conntrack_tuple_hash *h = NULL;
1492 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1492 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1493 struct nf_conn *ct;
1493 u_int8_t u3 = nfmsg->nfgen_family; 1494 u_int8_t u3 = nfmsg->nfgen_family;
1494 u16 zone; 1495 u16 zone;
1495 int err; 1496 int err;
@@ -1512,25 +1513,22 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1512 1513
1513 spin_lock_bh(&nf_conntrack_lock); 1514 spin_lock_bh(&nf_conntrack_lock);
1514 if (cda[CTA_TUPLE_ORIG]) 1515 if (cda[CTA_TUPLE_ORIG])
1515 h = __nf_conntrack_find(net, zone, &otuple); 1516 h = nf_conntrack_find_get(net, zone, &otuple);
1516 else if (cda[CTA_TUPLE_REPLY]) 1517 else if (cda[CTA_TUPLE_REPLY])
1517 h = __nf_conntrack_find(net, zone, &rtuple); 1518 h = nf_conntrack_find_get(net, zone, &rtuple);
1519 spin_unlock_bh(&nf_conntrack_lock);
1518 1520
1519 if (h == NULL) { 1521 if (h == NULL) {
1520 err = -ENOENT; 1522 err = -ENOENT;
1521 if (nlh->nlmsg_flags & NLM_F_CREATE) { 1523 if (nlh->nlmsg_flags & NLM_F_CREATE) {
1522 struct nf_conn *ct;
1523 enum ip_conntrack_events events; 1524 enum ip_conntrack_events events;
1524 1525
1525 ct = ctnetlink_create_conntrack(net, zone, cda, &otuple, 1526 ct = ctnetlink_create_conntrack(net, zone, cda, &otuple,
1526 &rtuple, u3); 1527 &rtuple, u3);
1527 if (IS_ERR(ct)) { 1528 if (IS_ERR(ct))
1528 err = PTR_ERR(ct); 1529 return PTR_ERR(ct);
1529 goto out_unlock; 1530
1530 }
1531 err = 0; 1531 err = 0;
1532 nf_conntrack_get(&ct->ct_general);
1533 spin_unlock_bh(&nf_conntrack_lock);
1534 if (test_bit(IPS_EXPECTED_BIT, &ct->status)) 1532 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1535 events = IPCT_RELATED; 1533 events = IPCT_RELATED;
1536 else 1534 else
@@ -1545,23 +1543,19 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1545 ct, NETLINK_CB(skb).pid, 1543 ct, NETLINK_CB(skb).pid,
1546 nlmsg_report(nlh)); 1544 nlmsg_report(nlh));
1547 nf_ct_put(ct); 1545 nf_ct_put(ct);
1548 } else 1546 }
1549 spin_unlock_bh(&nf_conntrack_lock);
1550 1547
1551 return err; 1548 return err;
1552 } 1549 }
1553 /* implicit 'else' */ 1550 /* implicit 'else' */
1554 1551
1555 /* We manipulate the conntrack inside the global conntrack table lock,
1556 * so there's no need to increase the refcount */
1557 err = -EEXIST; 1552 err = -EEXIST;
1553 ct = nf_ct_tuplehash_to_ctrack(h);
1558 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { 1554 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
1559 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 1555 spin_lock_bh(&nf_conntrack_lock);
1560
1561 err = ctnetlink_change_conntrack(ct, cda); 1556 err = ctnetlink_change_conntrack(ct, cda);
1557 spin_unlock_bh(&nf_conntrack_lock);
1562 if (err == 0) { 1558 if (err == 0) {
1563 nf_conntrack_get(&ct->ct_general);
1564 spin_unlock_bh(&nf_conntrack_lock);
1565 nf_conntrack_eventmask_report((1 << IPCT_REPLY) | 1559 nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
1566 (1 << IPCT_ASSURED) | 1560 (1 << IPCT_ASSURED) |
1567 (1 << IPCT_HELPER) | 1561 (1 << IPCT_HELPER) |
@@ -1570,15 +1564,10 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1570 (1 << IPCT_MARK), 1564 (1 << IPCT_MARK),
1571 ct, NETLINK_CB(skb).pid, 1565 ct, NETLINK_CB(skb).pid,
1572 nlmsg_report(nlh)); 1566 nlmsg_report(nlh));
1573 nf_ct_put(ct); 1567 }
1574 } else
1575 spin_unlock_bh(&nf_conntrack_lock);
1576
1577 return err;
1578 } 1568 }
1579 1569
1580out_unlock: 1570 nf_ct_put(ct);
1581 spin_unlock_bh(&nf_conntrack_lock);
1582 return err; 1571 return err;
1583} 1572}
1584 1573