aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-08-24 01:48:31 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:08:34 -0400
commit41a49cc3c02ace59d4dddae91ea211c330970ee3 (patch)
treebca262bd2d32f1cf7473b5360052ff3103845e23
parent4e81bb8336a0ac50289d4d4c7a55e559b994ee8f (diff)
[XFRM]: Add sorting interface for state and template.
Under two transformation policies it is required to merge them. This is a platform to sort state for outbound and templates for inbound respectively. It will be used when Mobile IPv6 and IPsec are used at the same time. Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/xfrm.h20
-rw-r--r--net/xfrm/xfrm_policy.c16
-rw-r--r--net/xfrm/xfrm_state.c38
3 files changed, 72 insertions, 2 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4655ca25f808..d341603e4ba8 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -254,6 +254,8 @@ struct xfrm_state_afinfo {
254 struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto, 254 struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto,
255 xfrm_address_t *daddr, xfrm_address_t *saddr, 255 xfrm_address_t *daddr, xfrm_address_t *saddr,
256 int create); 256 int create);
257 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
258 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
257}; 259};
258 260
259extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); 261extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -1002,6 +1004,24 @@ extern int xfrm_state_add(struct xfrm_state *x);
1002extern int xfrm_state_update(struct xfrm_state *x); 1004extern int xfrm_state_update(struct xfrm_state *x);
1003extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); 1005extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
1004extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); 1006extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
1007#ifdef CONFIG_XFRM_SUB_POLICY
1008extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1009 int n, unsigned short family);
1010extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1011 int n, unsigned short family);
1012#else
1013static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
1014 int n, unsigned short family)
1015{
1016 return -ENOSYS;
1017}
1018
1019static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
1020 int n, unsigned short family)
1021{
1022 return -ENOSYS;
1023}
1024#endif
1005extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); 1025extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
1006extern int xfrm_state_delete(struct xfrm_state *x); 1026extern int xfrm_state_delete(struct xfrm_state *x);
1007extern void xfrm_state_flush(u8 proto); 1027extern void xfrm_state_flush(u8 proto);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 96de6c76ed57..1732159ffd01 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -861,6 +861,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
861 struct xfrm_state **xfrm, 861 struct xfrm_state **xfrm,
862 unsigned short family) 862 unsigned short family)
863{ 863{
864 struct xfrm_state *tp[XFRM_MAX_DEPTH];
865 struct xfrm_state **tpp = (npols > 1) ? tp : xfrm;
864 int cnx = 0; 866 int cnx = 0;
865 int error; 867 int error;
866 int ret; 868 int ret;
@@ -871,7 +873,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
871 error = -ENOBUFS; 873 error = -ENOBUFS;
872 goto fail; 874 goto fail;
873 } 875 }
874 ret = xfrm_tmpl_resolve_one(pols[i], fl, &xfrm[cnx], family); 876
877 ret = xfrm_tmpl_resolve_one(pols[i], fl, &tpp[cnx], family);
875 if (ret < 0) { 878 if (ret < 0) {
876 error = ret; 879 error = ret;
877 goto fail; 880 goto fail;
@@ -879,11 +882,15 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
879 cnx += ret; 882 cnx += ret;
880 } 883 }
881 884
885 /* found states are sorted for outbound processing */
886 if (npols > 1)
887 xfrm_state_sort(xfrm, tpp, cnx, family);
888
882 return cnx; 889 return cnx;
883 890
884 fail: 891 fail:
885 for (cnx--; cnx>=0; cnx--) 892 for (cnx--; cnx>=0; cnx--)
886 xfrm_state_put(xfrm[cnx]); 893 xfrm_state_put(tpp[cnx]);
887 return error; 894 return error;
888 895
889} 896}
@@ -1280,6 +1287,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1280 struct sec_path *sp; 1287 struct sec_path *sp;
1281 static struct sec_path dummy; 1288 static struct sec_path dummy;
1282 struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; 1289 struct xfrm_tmpl *tp[XFRM_MAX_DEPTH];
1290 struct xfrm_tmpl *stp[XFRM_MAX_DEPTH];
1283 struct xfrm_tmpl **tpp = tp; 1291 struct xfrm_tmpl **tpp = tp;
1284 int ti = 0; 1292 int ti = 0;
1285 int i, k; 1293 int i, k;
@@ -1297,6 +1305,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1297 tpp[ti++] = &pols[pi]->xfrm_vec[i]; 1305 tpp[ti++] = &pols[pi]->xfrm_vec[i];
1298 } 1306 }
1299 xfrm_nr = ti; 1307 xfrm_nr = ti;
1308 if (npols > 1) {
1309 xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
1310 tpp = stp;
1311 }
1300 1312
1301 /* For each tunnel xfrm, find the first matching tmpl. 1313 /* For each tunnel xfrm, find the first matching tmpl.
1302 * For each tmpl before that, find corresponding xfrm. 1314 * For each tmpl before that, find corresponding xfrm.
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a26ef6952c30..622e92a08d0b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -728,6 +728,44 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
728} 728}
729EXPORT_SYMBOL(xfrm_find_acq); 729EXPORT_SYMBOL(xfrm_find_acq);
730 730
731#ifdef CONFIG_XFRM_SUB_POLICY
732int
733xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
734 unsigned short family)
735{
736 int err = 0;
737 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
738 if (!afinfo)
739 return -EAFNOSUPPORT;
740
741 spin_lock_bh(&xfrm_state_lock);
742 if (afinfo->tmpl_sort)
743 err = afinfo->tmpl_sort(dst, src, n);
744 spin_unlock_bh(&xfrm_state_lock);
745 xfrm_state_put_afinfo(afinfo);
746 return err;
747}
748EXPORT_SYMBOL(xfrm_tmpl_sort);
749
750int
751xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
752 unsigned short family)
753{
754 int err = 0;
755 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
756 if (!afinfo)
757 return -EAFNOSUPPORT;
758
759 spin_lock_bh(&xfrm_state_lock);
760 if (afinfo->state_sort)
761 err = afinfo->state_sort(dst, src, n);
762 spin_unlock_bh(&xfrm_state_lock);
763 xfrm_state_put_afinfo(afinfo);
764 return err;
765}
766EXPORT_SYMBOL(xfrm_state_sort);
767#endif
768
731/* Silly enough, but I'm lazy to build resolution list */ 769/* Silly enough, but I'm lazy to build resolution list */
732 770
733static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) 771static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)