beet-interfamily-sleep-loopback-2.6.21.3.patch
来自「HIP:Host Identity Protocol」· PATCH 代码 · 共 840 行 · 第 1/2 页
PATCH
840 行
static inline void __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x) {- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)+ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) *nflen += x->props.header_len; else *len += x->props.header_len;@@ -114,7 +115,7 @@ static inline void __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x) {- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)+ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) *nflen -= x->props.header_len; else *len -= x->props.header_len;@@ -131,6 +132,7 @@ struct dst_entry *dst, *dst_prev; struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); struct rt6_info *rt = rt0;+ unsigned short encap_family = 0, beet = 0; struct flowi fl_tunnel = { .nl_u = { .ip6_u = {@@ -139,6 +141,10 @@ } } };+ union {+ struct in6_addr *in6;+ struct in_addr *in;+ } remote, local; int i; int err = 0; int header_len = 0;@@ -175,20 +181,35 @@ dst1->next = dst_prev; dst_prev = dst1; + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {+ encap_family = xfrm[i]->props.family;+ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);+ if (encap_family == AF_INET6) {+ remote.in6 = __xfrm6_bundle_addr_remote(xfrm[i], remote.in6);+ local.in6 = __xfrm6_bundle_addr_local(xfrm[i], local.in6);+ } else if (encap_family == AF_INET) {+ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4;+ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4;+ } else {+ BUG_ON(1);+ }+ }+ __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); trailer_len += xfrm[i]->props.trailer_len; if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||+ xfrm[i]->props.mode == XFRM_MODE_BEET || xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {- unsigned short encap_family = xfrm[i]->props.family; switch(encap_family) { case AF_INET: fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;+ fl_tunnel.fl4_tos = 0;+ fl_tunnel.fl4_scope = 0; break; case AF_INET6: ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));- ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_local(xfrm[i], &fl->fl6_src)); break; default:@@ -259,6 +280,13 @@ } xfrm_init_pmtu(dst);++ if (beet && encap_family == AF_INET) {+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);+ u32 mtu = dst_mtu(dst);+ xfrm6_update_pmtu(dst, mtu + delta);+ }+ return 0; error:diff -urN a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c--- a/net/ipv6/xfrm6_tunnel.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/ipv6/xfrm6_tunnel.c 2007-05-25 16:36:44.000000000 +0300@@ -307,7 +307,7 @@ static int xfrm6_tunnel_init_state(struct xfrm_state *x) {- if (x->props.mode != XFRM_MODE_TUNNEL)+ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET) return -EINVAL; if (x->encap)diff -urN a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c--- a/net/ipv6/xfrm6_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/ipv6/xfrm6_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300@@ -80,6 +80,7 @@ top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);+ skb->protocol = htons(ETH_P_IPV6); return 0; } diff -urN a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c--- a/net/ipv6/xfrm6_mode_beet.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/ipv6/xfrm6_mode_beet.c 2007-05-25 16:36:44.000000000 +0300@@ -6,6 +6,7 @@ * Herbert Xu <herbert@gondor.apana.org.au> * Abhinav Pathak <abhinav.pathak@hiit.fi> * Jeff Ahrenholz <ahrenholz@gmail.com>+ * Joakim Koskela <jookos@gmail.com> */ #include <linux/init.h>@@ -33,37 +34,154 @@ */ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) {- struct ipv6hdr *iph, *top_iph;- u8 *prevhdr;- int hdr_len;-- skb_push(skb, x->props.header_len);- iph = skb->nh.ipv6h;-- hdr_len = ip6_find_1stfragopt(skb, &prevhdr);- skb->nh.raw = prevhdr - x->props.header_len;- skb->h.raw = skb->data + hdr_len;- memmove(skb->data, iph, hdr_len); - skb->nh.raw = skb->data;- top_iph = skb->nh.ipv6h;- skb->nh.raw = &top_iph->nexthdr;- skb->h.ipv6h = top_iph + 1;-- ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);- ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);+ struct dst_entry *dst = skb->dst;+ int hdrlen;+ struct iphdr *iphv4, *top_iphv4;+ struct ipv6hdr *iphv6, *top_iphv6;+ + if (skb->nh.iph->version == 6) {+ + u8 *prevhdr;+ int hdr_len;++ /* 6-6 */++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;+ skb_push(skb, hdrlen);+ iphv6 = skb->nh.ipv6h;++ hdr_len = ip6_find_1stfragopt(skb, &prevhdr);+ skb->nh.raw = prevhdr - hdrlen;+ skb->h.raw = skb->data + hdr_len;+ memmove(skb->data, iphv6, hdr_len);+ + skb->nh.raw = skb->data;+ top_iphv6 = skb->nh.ipv6h;+ skb->nh.raw = &top_iphv6->nexthdr;+ skb->h.ipv6h = top_iphv6 + 1;+ ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr *)&x->props.saddr);+ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr);++ skb->protocol = htons(ETH_P_IPV6);+ + } else if (skb->nh.iph->version == 4) {++ int flags;+ int optlen;+ int dsfield;+ u8 protocol;+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);++ /* Inner = 4, Outer = 6*/++ iphv4 = skb->nh.iph;+ skb->h.ipiph = iphv4;++ hdrlen = x->props.header_len;++ optlen = iphv4->ihl * 4 - sizeof(*iphv4);+ + if (!optlen) {+ hdrlen -= IPV4_BEET_PHMAXLEN;+ } else {+ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));+ hdrlen -= optlen & 4;+ }++ skb->nh.raw = skb_push(skb, hdrlen);+ + top_iphv4 = skb->nh.iph;+ hdrlen = iphv4->ihl * 4 - optlen;+ skb->h.raw += hdrlen; + if (unlikely(optlen)) {+ struct ip_beet_phdr *ph;+ + BUG_ON(optlen < 0);+ + ph = (struct ip_beet_phdr *)skb->h.raw;+ ph->padlen = 4 - (optlen & 4);+ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;+ ph->nexthdr = iphv4->protocol;+ top_iphv4->protocol = IPPROTO_BEETPH;+ top_iphv4->ihl = sizeof(struct iphdr) / 4;+ }+ + if (unlikely(optlen))+ protocol = top_iphv4->protocol;+ else+ protocol = iphv4->protocol;+ + if (skb_headroom(skb) <= 2*delta){+ if (pskb_expand_head(skb, delta,0, GFP_ATOMIC))+ return -ENOMEM;+ }+ + skb->nh.raw = skb_push(skb, delta);++ top_iphv6 = skb->nh.ipv6h;+ skb->h.ipv6h = top_iphv6 + 1;+ /* DS disclosed */+ top_iphv6->version = 6;+ top_iphv6->priority = 0;+ top_iphv6->flow_lbl[0] = 0;+ top_iphv6->flow_lbl[1] = 0;+ top_iphv6->flow_lbl[2] = 0;+ dsfield = ipv6_get_dsfield(top_iphv6);+ dsfield = INET_ECN_encapsulate(dsfield, dsfield);+ flags = x->props.flags;+ if (flags & XFRM_STATE_NOECN)+ dsfield &= ~INET_ECN_MASK;+ ipv6_change_dsfield(top_iphv6, 0, dsfield);++ top_iphv6->nexthdr = protocol;+ top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);+ top_iphv6->payload_len = htons(skb->len - sizeof(struct ipv6hdr));+ ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr *)&x->props.saddr);+ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr);+ skb->nh.raw = &top_iphv6->nexthdr;++ skb->protocol = htons(ETH_P_IPV6);+ } else+ BUG_ON(1); return 0; } static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) {- struct ipv6hdr *ip6h;- int size = sizeof(struct ipv6hdr);+ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw);+ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr);+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);+ __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit;+ __u8 ph_nexthdr = 0;+ int phlen = 0;+ int optlen = 0;+ int err = -EINVAL; - if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))- goto out;+ if (x->sel.family == AF_INET) {+ /* Inner = IPv4, therefore the IPhdr must be shrunk */+ /* Inner = 4, Outer = 6 */+ if (unlikely(proto == IPPROTO_BEETPH)) {+ if (!pskb_may_pull(skb, sizeof(*ph)))+ goto out;+ phlen = ph->hdrlen * 8;+ optlen = phlen - ph->padlen - sizeof(*ph);++ if (optlen < 0 || optlen & 3 || optlen > 250)+ goto out;+ if (!pskb_may_pull(skb, phlen))+ goto out;++ proto = ph_nexthdr = ph->nexthdr;+ }+ skb->nh.raw += delta;+ }+ + if (skb_cloned(skb) &&+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))+ goto out; skb_push(skb, size); memmove(skb->data, skb->nh.raw, size);@@ -71,11 +189,36 @@ skb->mac.raw = memmove(skb->data - skb->mac_len, skb->mac.raw, skb->mac_len);-- ip6h = skb->nh.ipv6h;- ip6h->payload_len = htons(skb->len - size);- ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);- ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);+ if (unlikely(phlen)) {+ skb_pull(skb, phlen - optlen);+ skb->nh.raw = skb->data;+ }+ if (x->sel.family == AF_INET6) {+ struct ipv6hdr *ip6h = skb->nh.ipv6h;+ ip6h->payload_len = htons(skb->len - size);+ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);+ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);+ } else if (x->sel.family == AF_INET) {+ struct iphdr *iph = skb->nh.iph;+ iph->ihl = (sizeof(*iph) + optlen) / 4;+ iph->version = 4;+ iph->tos = 0;+ iph->id = 0;+ iph->frag_off = 0;+ iph->ttl = hops;+ iph->protocol = proto;+ iph->daddr = x->sel.daddr.a4;+ iph->saddr = x->sel.saddr.a4;+ iph->tot_len = htons(skb->len);+ ip_send_check(iph);+ skb->protocol = htons(ETH_P_IP);+ if (unlikely(!optlen)) {+ skb->h.raw = skb->nh.raw;+ }+ dst_release(skb->dst);+ skb->dst = NULL;+ } else+ BUG_ON(1); err = 0; out: return err;diff -urN a/net/ipv6/esp6.c b/net/ipv6/esp6.c--- a/net/ipv6/esp6.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/ipv6/esp6.c 2007-05-25 16:36:44.000000000 +0300@@ -242,7 +242,7 @@ struct esp_data *esp = x->data; u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); - if (x->props.mode == XFRM_MODE_TUNNEL) {+ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */@@ -365,6 +365,8 @@ x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; if (x->props.mode == XFRM_MODE_TUNNEL) x->props.header_len += sizeof(struct ipv6hdr);+ else if (x->props.mode == XFRM_MODE_BEET)+ x->props.header_len += IPV4_BEET_PHMAXLEN; x->data = esp; return 0; diff -urN a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c--- a/net/ipv6/xfrm6_input.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/ipv6/xfrm6_input.c 2007-05-25 16:36:44.000000000 +0300@@ -73,7 +73,7 @@ if (x->mode->input(x, skb)) goto drop; - if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */+ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { /* XXX */ decaps = 1; break; }diff -urN a/net/dccp/ipv6.c b/net/dccp/ipv6.c--- a/net/dccp/ipv6.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/dccp/ipv6.c 2007-05-25 16:36:44.000000000 +0300@@ -156,7 +156,7 @@ goto out; } - err = xfrm_lookup(&dst, &fl, sk, 0);+ err = xfrm_lookup(&dst, &fl, sk, 1); if (err < 0) { sk->sk_err_soft = -err; goto out;diff -urN a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c--- a/net/xfrm/xfrm_policy.c 2007-05-25 16:36:44.000000000 +0300+++ b/net/xfrm/xfrm_policy.c 2007-05-25 16:36:44.000000000 +0300@@ -1224,7 +1224,7 @@ xfrm_address_t *local = saddr; struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; - if (tmpl->mode == XFRM_MODE_TUNNEL) {+ if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == XFRM_MODE_BEET) { remote = &tmpl->id.daddr; local = &tmpl->saddr; family = tmpl->encap_family;diff -urN a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c--- a/net/xfrm/xfrm_state.c 2007-05-25 16:36:45.000000000 +0300+++ b/net/xfrm/xfrm_state.c 2007-05-25 16:36:45.000000000 +0300@@ -558,7 +558,7 @@ selector. */ if (x->km.state == XFRM_STATE_VALID) {- if (!xfrm_selector_match(&x->sel, fl, family) ||+ if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || !security_xfrm_state_pol_flow_match(x, pol, fl)) continue; if (!best ||@@ -570,7 +570,7 @@ acquire_in_progress = 1; } else if (x->km.state == XFRM_STATE_ERROR || x->km.state == XFRM_STATE_EXPIRED) {- if (xfrm_selector_match(&x->sel, fl, family) &&+ if (xfrm_selector_match(&x->sel, fl, x->sel.family) && security_xfrm_state_pol_flow_match(x, pol, fl)) error = -ESRCH; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?