aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-08-23 21:11:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:06:41 -0400
commit1b5c229987dc4d0c92a38fac0cde2aeec08cd775 (patch)
tree5726243af6aa7194f1ed65e0340539e1ee5c6a42 /net
parent99505a843673faeae962a8cde128c7c034ba6b5e (diff)
[XFRM] STATE: Support non-fragment outbound transformation headers.
For originated outbound IPv6 packets which will fragment, ip6_append_data() should know length of extension headers before sending them and the length is carried by dst_entry. IPv6 IPsec headers fragment then transformation was designed to place all headers after fragment header. OTOH Mobile IPv6 extension headers do not fragment then it is a good idea to make dst_entry have non-fragment length to tell it to ip6_append_data(). 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>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/xfrm6_policy.c24
3 files changed, 24 insertions, 3 deletions
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index a5bed741de2c..e517981ceadd 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -135,6 +135,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
135 dst_prev->flags |= DST_HOST; 135 dst_prev->flags |= DST_HOST;
136 dst_prev->lastuse = jiffies; 136 dst_prev->lastuse = jiffies;
137 dst_prev->header_len = header_len; 137 dst_prev->header_len = header_len;
138 dst_prev->nfheader_len = 0;
138 dst_prev->trailer_len = trailer_len; 139 dst_prev->trailer_len = trailer_len;
139 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); 140 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
140 141
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 2a376b7d91b4..258e3e45f5e0 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -971,7 +971,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
971 971
972 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); 972 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
973 973
974 fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0); 974 fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0);
975 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); 975 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
976 976
977 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { 977 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 9328fc88708a..a3f68c8b737e 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -75,6 +75,24 @@ __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
75 (struct in6_addr*)&x->props.saddr; 75 (struct in6_addr*)&x->props.saddr;
76} 76}
77 77
78static inline void
79__xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
80{
81 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
82 *nflen += x->props.header_len;
83 else
84 *len += x->props.header_len;
85}
86
87static inline void
88__xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
89{
90 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
91 *nflen -= x->props.header_len;
92 else
93 *len -= x->props.header_len;
94}
95
78/* Allocate chain of dst_entry's, attach known xfrm's, calculate 96/* Allocate chain of dst_entry's, attach known xfrm's, calculate
79 * all the metrics... Shortly, bundle a bundle. 97 * all the metrics... Shortly, bundle a bundle.
80 */ 98 */
@@ -99,6 +117,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
99 int i; 117 int i;
100 int err = 0; 118 int err = 0;
101 int header_len = 0; 119 int header_len = 0;
120 int nfheader_len = 0;
102 int trailer_len = 0; 121 int trailer_len = 0;
103 122
104 dst = dst_prev = NULL; 123 dst = dst_prev = NULL;
@@ -135,7 +154,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
135 local = __xfrm6_bundle_addr_local(xfrm[i], local); 154 local = __xfrm6_bundle_addr_local(xfrm[i], local);
136 tunnel = 1; 155 tunnel = 1;
137 } 156 }
138 header_len += xfrm[i]->props.header_len; 157 __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
139 trailer_len += xfrm[i]->props.trailer_len; 158 trailer_len += xfrm[i]->props.trailer_len;
140 159
141 if (tunnel) { 160 if (tunnel) {
@@ -170,6 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
170 dst_prev->flags |= DST_HOST; 189 dst_prev->flags |= DST_HOST;
171 dst_prev->lastuse = jiffies; 190 dst_prev->lastuse = jiffies;
172 dst_prev->header_len = header_len; 191 dst_prev->header_len = header_len;
192 dst_prev->nfheader_len = nfheader_len;
173 dst_prev->trailer_len = trailer_len; 193 dst_prev->trailer_len = trailer_len;
174 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); 194 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
175 195
@@ -188,7 +208,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
188 x->u.rt6.rt6i_src = rt0->rt6i_src; 208 x->u.rt6.rt6i_src = rt0->rt6i_src;
189 x->u.rt6.rt6i_idev = rt0->rt6i_idev; 209 x->u.rt6.rt6i_idev = rt0->rt6i_idev;
190 in6_dev_hold(rt0->rt6i_idev); 210 in6_dev_hold(rt0->rt6i_idev);
191 header_len -= x->u.dst.xfrm->props.header_len; 211 __xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm);
192 trailer_len -= x->u.dst.xfrm->props.trailer_len; 212 trailer_len -= x->u.dst.xfrm->props.trailer_len;
193 } 213 }
194 214