Hi: This patch adds the ability to delete policies by index and getting policy info by selector. Previously get_policy_info can't really be used without doing a dump. It also fixes the missing verify_dir check in get_policy. Cheers, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/include/net/xfrm.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/xfrm.h,v retrieving revision 1.2 diff -u -r1.2 xfrm.h --- kernel-source-2.5/include/net/xfrm.h 2 Jun 2003 10:55:50 -0000 1.2 +++ kernel-source-2.5/include/net/xfrm.h 7 Jun 2003 08:05:07 -0000 @@ -790,7 +790,8 @@ struct xfrm_policy *xfrm_policy_alloc(int gfp); extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel); +struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, + int delete); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); void xfrm_policy_flush(void); u32 xfrm_get_acqseq(void); Index: kernel-source-2.5/net/netsyms.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/netsyms.c,v retrieving revision 1.1.1.10 diff -u -r1.1.1.10 netsyms.c --- kernel-source-2.5/net/netsyms.c 27 May 2003 08:38:41 -0000 1.1.1.10 +++ kernel-source-2.5/net/netsyms.c 7 Jun 2003 08:05:27 -0000 @@ -337,7 +337,7 @@ EXPORT_SYMBOL(xfrm_alloc_spi); EXPORT_SYMBOL(xfrm_state_flush); EXPORT_SYMBOL(xfrm_policy_kill); -EXPORT_SYMBOL(xfrm_policy_delete); +EXPORT_SYMBOL(xfrm_policy_bysel); EXPORT_SYMBOL(xfrm_policy_insert); EXPORT_SYMBOL(xfrm_policy_walk); EXPORT_SYMBOL(xfrm_policy_flush); Index: kernel-source-2.5/net/key/af_key.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/key/af_key.c,v retrieving revision 1.3 diff -u -r1.3 af_key.c --- kernel-source-2.5/net/key/af_key.c 27 May 2003 09:34:08 -0000 1.3 +++ kernel-source-2.5/net/key/af_key.c 7 Jun 2003 08:05:50 -0000 @@ -1990,7 +1990,7 @@ if (sel.dport) sel.dport_mask = ~0; - xp = xfrm_policy_delete(pol->sadb_x_policy_dir-1, &sel); + xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1); if (xp == NULL) return -ENOENT; Index: kernel-source-2.5/net/xfrm/xfrm_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v retrieving revision 1.4 diff -u -r1.4 xfrm_policy.c --- kernel-source-2.5/net/xfrm/xfrm_policy.c 2 Jun 2003 10:55:50 -0000 1.4 +++ kernel-source-2.5/net/xfrm/xfrm_policy.c 7 Jun 2003 08:04:33 -0000 @@ -287,19 +287,25 @@ return 0; } -struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel) +struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, + int delete) { struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) { - *p = pol->next; + if (delete) + *p = pol->next; break; } } - if (pol) - atomic_inc(&flow_cache_genid); + if (pol) { + if (delete) + atomic_inc(&flow_cache_genid); + else + xfrm_pol_hold(pol); + } write_unlock_bh(&xfrm_policy_lock); return pol; } Index: kernel-source-2.5/net/xfrm/xfrm_user.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_user.c,v retrieving revision 1.2 diff -u -r1.2 xfrm_user.c --- kernel-source-2.5/net/xfrm/xfrm_user.c 1 Jun 2003 00:11:12 -0000 1.2 +++ kernel-source-2.5/net/xfrm/xfrm_user.c 7 Jun 2003 08:10:59 -0000 @@ -656,26 +656,6 @@ return 0; } -static int xfrm_del_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) -{ - struct xfrm_policy *xp; - struct xfrm_userpolicy_id *p; - int err; - - p = NLMSG_DATA(nlh); - - err = verify_policy_dir(p->dir); - if (err) - return err; - - xp = xfrm_policy_delete(p->dir, &p->sel); - if (xp == NULL) - return -ENOENT; - xfrm_policy_kill(xp); - xfrm_pol_put(xp); - return 0; -} - static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) { struct xfrm_dump_info *sp = ptr; @@ -774,20 +754,36 @@ { struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; - struct sk_buff *resp_skb; int err; + int delete; p = NLMSG_DATA(nlh); - xp = xfrm_policy_byid(p->dir, p->index, 0); + delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; + + err = verify_policy_dir(p->dir); + if (err) + return err; + + if (p->index) + xp = xfrm_policy_byid(p->dir, p->index, delete); + else + xp = xfrm_policy_bysel(p->dir, &p->sel, delete); if (xp == NULL) return -ENOENT; - resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq); - if (IS_ERR(resp_skb)) { - err = PTR_ERR(resp_skb); - } else { - err = netlink_unicast(xfrm_nl, resp_skb, - NETLINK_CB(skb).pid, MSG_DONTWAIT); + if (delete) + xfrm_policy_kill(xp); + else { + struct sk_buff *resp_skb; + + resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq); + if (IS_ERR(resp_skb)) { + err = PTR_ERR(resp_skb); + } else { + err = netlink_unicast(xfrm_nl, resp_skb, + NETLINK_CB(skb).pid, + MSG_DONTWAIT); + } } xfrm_pol_put(xp); @@ -819,7 +815,7 @@ .dump = xfrm_dump_sa, }, { .doit = xfrm_add_policy }, - { .doit = xfrm_del_policy }, + { .doit = xfrm_get_policy }, { .doit = xfrm_get_policy, .dump = xfrm_dump_policy,