diff options
author | Patrick McHardy <kaber@trash.net> | 2007-07-08 01:35:21 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:18:01 -0400 |
commit | 31f15875c5ad98a13b528aaf19c839e22b43dc9a (patch) | |
tree | 3ede173710f42917ed228a2494af3b891a7ff4cf /net | |
parent | 5d08ad440feae11b8d6e7599147a8a20ac60f99a (diff) |
[NETFILTER]: nf_conntrack_helper/nf_conntrack_netlink: convert to expectation hash
Convert from the global expectation list to the hash table.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 21 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 79 |
2 files changed, 58 insertions, 42 deletions
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index fdabf823f8cd..cc8ae7404ac4 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -114,22 +114,25 @@ EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); | |||
114 | 114 | ||
115 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | 115 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) |
116 | { | 116 | { |
117 | unsigned int i; | ||
118 | struct nf_conntrack_tuple_hash *h; | 117 | struct nf_conntrack_tuple_hash *h; |
119 | struct nf_conntrack_expect *exp, *tmp; | 118 | struct nf_conntrack_expect *exp; |
120 | struct hlist_node *n; | 119 | struct hlist_node *n, *next; |
120 | unsigned int i; | ||
121 | 121 | ||
122 | /* Need write lock here, to delete helper. */ | 122 | /* Need write lock here, to delete helper. */ |
123 | write_lock_bh(&nf_conntrack_lock); | 123 | write_lock_bh(&nf_conntrack_lock); |
124 | list_del(&me->list); | 124 | list_del(&me->list); |
125 | 125 | ||
126 | /* Get rid of expectations */ | 126 | /* Get rid of expectations */ |
127 | list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { | 127 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
128 | struct nf_conn_help *help = nfct_help(exp->master); | 128 | hlist_for_each_entry_safe(exp, n, next, |
129 | if ((help->helper == me || exp->helper == me) && | 129 | &nf_ct_expect_hash[i], hnode) { |
130 | del_timer(&exp->timeout)) { | 130 | struct nf_conn_help *help = nfct_help(exp->master); |
131 | nf_ct_unlink_expect(exp); | 131 | if ((help->helper == me || exp->helper == me) && |
132 | nf_ct_expect_put(exp); | 132 | del_timer(&exp->timeout)) { |
133 | nf_ct_unlink_expect(exp); | ||
134 | nf_ct_expect_put(exp); | ||
135 | } | ||
133 | } | 136 | } |
134 | } | 137 | } |
135 | 138 | ||
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 65a7ebcf86f6..60af9b6b9e00 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1237,8 +1237,8 @@ nfattr_failure: | |||
1237 | #endif | 1237 | #endif |
1238 | static int ctnetlink_exp_done(struct netlink_callback *cb) | 1238 | static int ctnetlink_exp_done(struct netlink_callback *cb) |
1239 | { | 1239 | { |
1240 | if (cb->args[0]) | 1240 | if (cb->args[1]) |
1241 | nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[0]); | 1241 | nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]); |
1242 | return 0; | 1242 | return 0; |
1243 | } | 1243 | } |
1244 | 1244 | ||
@@ -1246,35 +1246,37 @@ static int | |||
1246 | ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | 1246 | ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) |
1247 | { | 1247 | { |
1248 | struct nf_conntrack_expect *exp, *last; | 1248 | struct nf_conntrack_expect *exp, *last; |
1249 | struct list_head *i; | ||
1250 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); | 1249 | struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); |
1250 | struct hlist_node *n; | ||
1251 | u_int8_t l3proto = nfmsg->nfgen_family; | 1251 | u_int8_t l3proto = nfmsg->nfgen_family; |
1252 | 1252 | ||
1253 | read_lock_bh(&nf_conntrack_lock); | 1253 | read_lock_bh(&nf_conntrack_lock); |
1254 | last = (struct nf_conntrack_expect *)cb->args[0]; | 1254 | last = (struct nf_conntrack_expect *)cb->args[1]; |
1255 | for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { | ||
1255 | restart: | 1256 | restart: |
1256 | list_for_each_prev(i, &nf_ct_expect_list) { | 1257 | hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]], |
1257 | exp = (struct nf_conntrack_expect *) i; | 1258 | hnode) { |
1258 | if (l3proto && exp->tuple.src.l3num != l3proto) | 1259 | if (l3proto && exp->tuple.src.l3num != l3proto) |
1259 | continue; | ||
1260 | if (cb->args[0]) { | ||
1261 | if (exp != last) | ||
1262 | continue; | 1260 | continue; |
1263 | cb->args[0] = 0; | 1261 | if (cb->args[1]) { |
1262 | if (exp != last) | ||
1263 | continue; | ||
1264 | cb->args[1] = 0; | ||
1265 | } | ||
1266 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, | ||
1267 | cb->nlh->nlmsg_seq, | ||
1268 | IPCTNL_MSG_EXP_NEW, | ||
1269 | 1, exp) < 0) { | ||
1270 | atomic_inc(&exp->use); | ||
1271 | cb->args[1] = (unsigned long)exp; | ||
1272 | goto out; | ||
1273 | } | ||
1264 | } | 1274 | } |
1265 | if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, | 1275 | if (cb->args[1]) { |
1266 | cb->nlh->nlmsg_seq, | 1276 | cb->args[1] = 0; |
1267 | IPCTNL_MSG_EXP_NEW, | 1277 | goto restart; |
1268 | 1, exp) < 0) { | ||
1269 | atomic_inc(&exp->use); | ||
1270 | cb->args[0] = (unsigned long)exp; | ||
1271 | goto out; | ||
1272 | } | 1278 | } |
1273 | } | 1279 | } |
1274 | if (cb->args[0]) { | ||
1275 | cb->args[0] = 0; | ||
1276 | goto restart; | ||
1277 | } | ||
1278 | out: | 1280 | out: |
1279 | read_unlock_bh(&nf_conntrack_lock); | 1281 | read_unlock_bh(&nf_conntrack_lock); |
1280 | if (last) | 1282 | if (last) |
@@ -1354,11 +1356,13 @@ static int | |||
1354 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | 1356 | ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, |
1355 | struct nlmsghdr *nlh, struct nfattr *cda[]) | 1357 | struct nlmsghdr *nlh, struct nfattr *cda[]) |
1356 | { | 1358 | { |
1357 | struct nf_conntrack_expect *exp, *tmp; | 1359 | struct nf_conntrack_expect *exp; |
1358 | struct nf_conntrack_tuple tuple; | 1360 | struct nf_conntrack_tuple tuple; |
1359 | struct nf_conntrack_helper *h; | 1361 | struct nf_conntrack_helper *h; |
1360 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); | 1362 | struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); |
1363 | struct hlist_node *n, *next; | ||
1361 | u_int8_t u3 = nfmsg->nfgen_family; | 1364 | u_int8_t u3 = nfmsg->nfgen_family; |
1365 | unsigned int i; | ||
1362 | int err; | 1366 | int err; |
1363 | 1367 | ||
1364 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) | 1368 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) |
@@ -1390,6 +1394,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1390 | nf_ct_expect_put(exp); | 1394 | nf_ct_expect_put(exp); |
1391 | } else if (cda[CTA_EXPECT_HELP_NAME-1]) { | 1395 | } else if (cda[CTA_EXPECT_HELP_NAME-1]) { |
1392 | char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); | 1396 | char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]); |
1397 | struct nf_conn_help *m_help; | ||
1393 | 1398 | ||
1394 | /* delete all expectations for this helper */ | 1399 | /* delete all expectations for this helper */ |
1395 | write_lock_bh(&nf_conntrack_lock); | 1400 | write_lock_bh(&nf_conntrack_lock); |
@@ -1398,22 +1403,30 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1398 | write_unlock_bh(&nf_conntrack_lock); | 1403 | write_unlock_bh(&nf_conntrack_lock); |
1399 | return -EINVAL; | 1404 | return -EINVAL; |
1400 | } | 1405 | } |
1401 | list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { | 1406 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
1402 | struct nf_conn_help *m_help = nfct_help(exp->master); | 1407 | hlist_for_each_entry_safe(exp, n, next, |
1403 | if (m_help->helper == h | 1408 | &nf_ct_expect_hash[i], |
1404 | && del_timer(&exp->timeout)) { | 1409 | hnode) { |
1405 | nf_ct_unlink_expect(exp); | 1410 | m_help = nfct_help(exp->master); |
1406 | nf_ct_expect_put(exp); | 1411 | if (m_help->helper == h |
1412 | && del_timer(&exp->timeout)) { | ||
1413 | nf_ct_unlink_expect(exp); | ||
1414 | nf_ct_expect_put(exp); | ||
1415 | } | ||
1407 | } | 1416 | } |
1408 | } | 1417 | } |
1409 | write_unlock_bh(&nf_conntrack_lock); | 1418 | write_unlock_bh(&nf_conntrack_lock); |
1410 | } else { | 1419 | } else { |
1411 | /* This basically means we have to flush everything*/ | 1420 | /* This basically means we have to flush everything*/ |
1412 | write_lock_bh(&nf_conntrack_lock); | 1421 | write_lock_bh(&nf_conntrack_lock); |
1413 | list_for_each_entry_safe(exp, tmp, &nf_ct_expect_list, list) { | 1422 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
1414 | if (del_timer(&exp->timeout)) { | 1423 | hlist_for_each_entry_safe(exp, n, next, |
1415 | nf_ct_unlink_expect(exp); | 1424 | &nf_ct_expect_hash[i], |
1416 | nf_ct_expect_put(exp); | 1425 | hnode) { |
1426 | if (del_timer(&exp->timeout)) { | ||
1427 | nf_ct_unlink_expect(exp); | ||
1428 | nf_ct_expect_put(exp); | ||
1429 | } | ||
1417 | } | 1430 | } |
1418 | } | 1431 | } |
1419 | write_unlock_bh(&nf_conntrack_lock); | 1432 | write_unlock_bh(&nf_conntrack_lock); |