📄 beet-interfamily-and-sleep-loopback-2.6.19.7.patch
字号:
diff -urN a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c--- a/net/ipv4/xfrm4_mode_beet.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/xfrm4_mode_beet.c 2007-05-25 14:44:51.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>@@ -14,100 +15,172 @@ #include <linux/skbuff.h> #include <linux/stringify.h> #include <net/dst.h>+#include <net/dsfield.h> #include <net/ip.h>+#include <net/inet_ecn.h> #include <net/xfrm.h> -/* Add encapsulation header.- *- * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.- * The following fields in it shall be filled in by x->type->output:- * tot_len- * check- *- * On exit, skb->h will be set to the start of the payload to be processed- * by x->type->output and skb->nh will be set to the top IP header.- */ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) {- struct iphdr *iph, *top_iph = NULL;- int hdrlen, optlen;-- iph = skb->nh.iph;- skb->h.ipiph = iph;-- hdrlen = 0;- optlen = iph->ihl * 4 - sizeof(*iph);- if (unlikely(optlen))- hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);-- skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);- top_iph = skb->nh.iph;- hdrlen = iph->ihl * 4 - optlen;- skb->h.raw += hdrlen;-- memmove(top_iph, iph, 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 = top_iph->protocol;+ struct dst_entry *dst = skb->dst;+ int hdrlen;+ struct iphdr *iphv4, *top_iphv4;+ struct ipv6hdr *iphv6, *top_iphv6;++ if (skb->nh.iph->version == 4) {+ + int optlen;++ /* 4-4 */++ 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;+ memmove(top_iphv4, iphv4, 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;+ }+ + top_iphv4->saddr = x->props.saddr.a4;+ top_iphv4->daddr = x->id.daddr.a4;+ + skb->protocol = htons(ETH_P_IP);++ } else if (skb->nh.iph->version == 6) {+ + u8 protocol;+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);++ /* Inner = 6, Outer = 4 : changing the external IP hdr+ * to the outer addresses+ */++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;+ skb_push(skb, hdrlen);+ iphv6 = skb->nh.ipv6h;+ + skb->nh.raw = skb->data;+ top_iphv6 = skb->nh.ipv6h;++ protocol = iphv6->nexthdr;+ skb->nh.raw = skb_pull(skb, delta);+ top_iphv4 = skb->nh.iph;+ skb->h.raw = skb->data + hdrlen;+ top_iphv4->ihl = (sizeof(struct iphdr) >> 2);+ top_iphv4->version = 4;+ top_iphv4->id = 0;+ top_iphv4->frag_off = htons(IP_DF);+ top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);+ top_iphv4->saddr = x->props.saddr.a4;+ top_iphv4->daddr = x->id.daddr.a4;+ skb->h.raw += top_iphv4->ihl*4;+ top_iphv4->protocol = protocol;+ + skb->protocol = htons(ETH_P_IP);+ } else + BUG_ON(1);+ + return 0; - top_iph->protocol = IPPROTO_BEETPH;- top_iph->ihl = sizeof(struct iphdr) / 4;- }-- top_iph->saddr = x->props.saddr.a4;- top_iph->daddr = x->id.daddr.a4; - return 0; } static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) { struct iphdr *iph = skb->nh.iph;+ int hops = skb->nh.iph->ttl; int phlen = 0; int optlen = 0;+ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr);+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); __u8 ph_nexthdr = 0, protocol = 0; int err = -EINVAL; protocol = iph->protocol; - if (unlikely(iph->protocol == IPPROTO_BEETPH)) {- struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);-- if (!pskb_may_pull(skb, sizeof(*ph)))- goto out;+ if (x->sel.family == AF_INET6) {+ /* Here, the inner family is 6, therefore I have to+ * substitute the IPhdr by enlarging it */+ if (skb_tailroom(skb) < delta){+ if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC))+ goto out;+ }+ skb->nh.raw -= delta;+ } else if (x->sel.family == AF_INET) {+ if (unlikely(iph->protocol == IPPROTO_BEETPH)) {+ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);++ 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;++ ph_nexthdr = ph->nexthdr;+ }+ } else+ BUG_ON(1); - 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;-- ph_nexthdr = ph->nexthdr;- }-- skb_push(skb, sizeof(*iph) - phlen + optlen);+ size += (optlen - phlen);+ skb_push(skb, size); memmove(skb->data, skb->nh.raw, sizeof(*iph)); skb->nh.raw = skb->data; - iph = skb->nh.iph;- iph->ihl = (sizeof(*iph) + optlen) / 4;- iph->tot_len = htons(skb->len);- iph->daddr = x->sel.daddr.a4;- iph->saddr = x->sel.saddr.a4;- if (ph_nexthdr)- iph->protocol = ph_nexthdr;- else- iph->protocol = protocol;- iph->check = 0;- iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);+ if (x->sel.family == AF_INET) {+ iph = skb->nh.iph;+ iph->ihl = (sizeof(*iph) + optlen) / 4;+ iph->tot_len = htons(skb->len);+ iph->daddr = x->sel.daddr.a4;+ iph->saddr = x->sel.saddr.a4;+ if (ph_nexthdr)+ iph->protocol = ph_nexthdr;+ else+ iph->protocol = protocol;+ iph->check = 0;+ iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);+ } else if (x->sel.family == AF_INET6) {+ struct ipv6hdr *ip6h = skb->nh.ipv6h;+ memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));+ ip6h->version = 6;+ ip6h->priority = 0;+ ip6h->nexthdr = protocol;+ ip6h->hop_limit = hops;+ 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);+ skb->protocol = htons(ETH_P_IPV6);+ } err = 0; out: return err;diff -urN a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c--- a/net/ipv4/xfrm4_policy.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/xfrm4_policy.c 2007-05-25 14:44:51.000000000 +0300@@ -15,6 +15,7 @@ static struct dst_ops xfrm4_dst_ops; static struct xfrm_policy_afinfo xfrm4_policy_afinfo;+static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu); static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) {@@ -72,17 +73,20 @@ struct dst_entry *dst, *dst_prev; struct rtable *rt0 = (struct rtable*)(*dst_p); struct rtable *rt = rt0;- u32 remote = fl->fl4_dst;- u32 local = fl->fl4_src; struct flowi fl_tunnel = { .nl_u = { .ip4_u = {- .saddr = local,- .daddr = remote,+ .saddr = fl->fl4_src,+ .daddr = fl->fl4_dst, .tos = fl->fl4_tos } } };+ union {+ struct in6_addr *in6;+ struct in_addr *in;+ } remote, local;+ unsigned short outer_family6 = 0; int i; int err; int header_len = 0;@@ -94,7 +98,7 @@ for (i = 0; i < nx; i++) { struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops); struct xfrm_dst *xdst;- int tunnel = 0;+ unsigned short outer_family = 0; if (unlikely(dst1 == NULL)) { err = -ENOBUFS;@@ -117,20 +121,41 @@ dst1->next = dst_prev; dst_prev = dst1; if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {- remote = xfrm[i]->id.daddr.a4;- local = xfrm[i]->props.saddr.a4;- tunnel = 1;+ outer_family = xfrm[i]->props.family;+ if(outer_family == AF_INET){+ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4;+ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4;+ } else if (outer_family == AF_INET6){+ outer_family6 = 1;+ remote.in6 = (struct in6_addr*)xfrm[i]->id.daddr.a6;+ local.in6 = (struct in6_addr*)xfrm[i]->props.saddr.a6; + } else+ BUG_ON(1); } header_len += xfrm[i]->props.header_len; trailer_len += xfrm[i]->props.trailer_len; - if (tunnel) {- fl_tunnel.fl4_src = local;- fl_tunnel.fl4_dst = remote;+ if (outer_family) {+ switch (outer_family) {+ default:+ case AF_INET:+ fl_tunnel.fl4_src = local.in->s_addr;+ fl_tunnel.fl4_dst = remote.in->s_addr;+ break;+ case AF_INET6:+ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);+ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);+ break;+ } err = xfrm_dst_lookup((struct xfrm_dst **)&rt,- &fl_tunnel, AF_INET);+ &fl_tunnel, outer_family); if (err) goto error;+ /* Without this, the atomic inc below segfaults */+ if (outer_family == AF_INET6) {+ rt->peer = NULL;+ rt_bind_peer(rt,1);+ } } else dst_hold(&rt->u.dst); }@@ -181,6 +206,12 @@ } xfrm_init_pmtu(dst);+ if (outer_family6) {+ /* The worst case */+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);+ u32 mtu = dst_mtu(dst);+ xfrm4_update_pmtu(dst, mtu - delta);+ } return 0; error:diff -urN a/net/ipv4/esp4.c b/net/ipv4/esp4.c--- a/net/ipv4/esp4.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/esp4.c 2007-05-25 14:44:51.000000000 +0300@@ -402,6 +402,8 @@ x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; if (x->props.mode == XFRM_MODE_TUNNEL) x->props.header_len += sizeof(struct iphdr);+ else if (x->props.mode == XFRM_MODE_BEET)+ x->props.header_len += IPV4_BEET_PHMAXLEN; if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; diff -urN a/net/ipv4/ipip.c b/net/ipv4/ipip.c--- a/net/ipv4/ipip.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/ipip.c 2007-05-25 14:44:51.000000000 +0300@@ -870,7 +870,7 @@ printk(banner); - if (xfrm4_tunnel_register(&ipip_handler)) {+ if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { printk(KERN_INFO "ipip init: can't register tunnel\n"); return -EAGAIN; }@@ -892,7 +892,7 @@ err2: free_netdev(ipip_fb_tunnel_dev); err1:- xfrm4_tunnel_deregister(&ipip_handler);+ xfrm4_tunnel_deregister(&ipip_handler, AF_INET); goto out; } @@ -912,7 +912,7 @@ static void __exit ipip_fini(void) {- if (xfrm4_tunnel_deregister(&ipip_handler))+ if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) printk(KERN_INFO "ipip close: can't deregister tunnel\n"); rtnl_lock();diff -urN a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c--- a/net/ipv4/xfrm4_output.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/xfrm4_output.c 2007-05-25 14:44:51.000000000 +0300@@ -66,7 +66,7 @@ if (err) goto error; - err = x->mode->output(x, skb);+ err = x->mode->output(x, skb); if (err) goto error; diff -urN a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c--- a/net/ipv4/xfrm4_tunnel.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/xfrm4_tunnel.c 2007-05-25 14:44:51.000000000 +0300@@ -13,7 +13,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) { struct iphdr *iph;- + iph = skb->nh.iph; iph->tot_len = htons(skb->len); ip_send_check(iph);@@ -28,7 +28,7 @@ static int ipip_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)@@ -64,24 +64,45 @@ .priority = 2, }; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+static struct xfrm_tunnel xfrm64_tunnel_handler = {+ .handler = xfrm4_rcv,+ .err_handler = xfrm_tunnel_err,+ .priority = 2,+};+#endif+ static int __init ipip_init(void) { if (xfrm_register_type(&ipip_type, AF_INET) < 0) { printk(KERN_INFO "ipip init: can't add xfrm type\n"); return -EAGAIN; }- if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -