aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_conntrack_netlink.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 206491488f4e..65a7ebcf86f6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1235,32 +1235,50 @@ nfattr_failure:
1235 return NOTIFY_DONE; 1235 return NOTIFY_DONE;
1236} 1236}
1237#endif 1237#endif
1238static int ctnetlink_exp_done(struct netlink_callback *cb)
1239{
1240 if (cb->args[0])
1241 nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[0]);
1242 return 0;
1243}
1238 1244
1239static int 1245static int
1240ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) 1246ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1241{ 1247{
1242 struct nf_conntrack_expect *exp = NULL; 1248 struct nf_conntrack_expect *exp, *last;
1243 struct list_head *i; 1249 struct list_head *i;
1244 u_int32_t *id = (u_int32_t *) &cb->args[0];
1245 struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); 1250 struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
1246 u_int8_t l3proto = nfmsg->nfgen_family; 1251 u_int8_t l3proto = nfmsg->nfgen_family;
1247 1252
1248 read_lock_bh(&nf_conntrack_lock); 1253 read_lock_bh(&nf_conntrack_lock);
1254 last = (struct nf_conntrack_expect *)cb->args[0];
1255restart:
1249 list_for_each_prev(i, &nf_ct_expect_list) { 1256 list_for_each_prev(i, &nf_ct_expect_list) {
1250 exp = (struct nf_conntrack_expect *) i; 1257 exp = (struct nf_conntrack_expect *) i;
1251 if (l3proto && exp->tuple.src.l3num != l3proto) 1258 if (l3proto && exp->tuple.src.l3num != l3proto)
1252 continue; 1259 continue;
1253 if (exp->id <= *id) 1260 if (cb->args[0]) {
1254 continue; 1261 if (exp != last)
1262 continue;
1263 cb->args[0] = 0;
1264 }
1255 if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid, 1265 if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
1256 cb->nlh->nlmsg_seq, 1266 cb->nlh->nlmsg_seq,
1257 IPCTNL_MSG_EXP_NEW, 1267 IPCTNL_MSG_EXP_NEW,
1258 1, exp) < 0) 1268 1, exp) < 0) {
1269 atomic_inc(&exp->use);
1270 cb->args[0] = (unsigned long)exp;
1259 goto out; 1271 goto out;
1260 *id = exp->id; 1272 }
1273 }
1274 if (cb->args[0]) {
1275 cb->args[0] = 0;
1276 goto restart;
1261 } 1277 }
1262out: 1278out:
1263 read_unlock_bh(&nf_conntrack_lock); 1279 read_unlock_bh(&nf_conntrack_lock);
1280 if (last)
1281 nf_ct_expect_put(last);
1264 1282
1265 return skb->len; 1283 return skb->len;
1266} 1284}
@@ -1287,7 +1305,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1287 if (nlh->nlmsg_flags & NLM_F_DUMP) { 1305 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1288 return netlink_dump_start(ctnl, skb, nlh, 1306 return netlink_dump_start(ctnl, skb, nlh,
1289 ctnetlink_exp_dump_table, 1307 ctnetlink_exp_dump_table,
1290 ctnetlink_done); 1308 ctnetlink_exp_done);
1291 } 1309 }
1292 1310
1293 if (cda[CTA_EXPECT_MASTER-1]) 1311 if (cda[CTA_EXPECT_MASTER-1])