📄 beet-interfamily-and-sleep-loopback-2.6.19.7.patch
字号:
- printk(KERN_INFO "ipip init: can't add xfrm handler\n");++ if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {+ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n");+ xfrm_unregister_type(&ipip_type, AF_INET);+ return -EAGAIN;+ }+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+ if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {+ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n");+ xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); xfrm_unregister_type(&ipip_type, AF_INET); return -EAGAIN; }+#endif return 0; } static void __exit ipip_fini(void) {- if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))- printk(KERN_INFO "ipip close: can't remove xfrm handler\n");+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+ if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))+ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n");+#endif+ if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))+ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n"); if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) printk(KERN_INFO "ipip close: can't remove xfrm type\n"); }diff -urN a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c--- a/net/ipv4/tcp_ipv4.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/tcp_ipv4.c 2007-05-25 14:44:51.000000000 +0300@@ -179,7 +179,7 @@ tmp = ip_route_connect(&rt, nexthop, inet->saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_TCP,- inet->sport, usin->sin_port, sk);+ inet->sport, usin->sin_port, sk, 1); if (tmp < 0) return tmp; diff -urN a/net/ipv4/udp.c b/net/ipv4/udp.c--- a/net/ipv4/udp.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/udp.c 2007-05-25 14:44:51.000000000 +0300@@ -630,7 +630,7 @@ { .sport = inet->sport, .dport = dport } } }; security_sk_classify_flow(sk, &fl);- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));+ err = ip_route_output_flow(&rt, &fl, sk, 1); if (err) goto out; diff -urN a/net/ipv4/route.c b/net/ipv4/route.c--- a/net/ipv4/route.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/route.c 2007-05-25 14:44:51.000000000 +0300@@ -108,6 +108,7 @@ #ifdef CONFIG_SYSCTL #include <linux/sysctl.h> #endif+#include <linux/xfrm.h> #define RT_FL_TOS(oldflp) \ ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))diff -urN a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c--- a/net/ipv4/af_inet.c 2007-05-25 14:44:51.000000000 +0300+++ b/net/ipv4/af_inet.c 2007-05-25 14:44:51.000000000 +0300@@ -1006,7 +1006,7 @@ RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, sk->sk_protocol,- inet->sport, inet->dport, sk);+ inet->sport, inet->dport, sk, 0); if (err) return err; diff -urN a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c--- a/net/ipv4/xfrm4_input.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv4/xfrm4_input.c 2007-05-25 14:44:52.000000000 +0300@@ -106,7 +106,7 @@ if (x->mode->input(x, skb)) goto drop; - if (x->props.mode == XFRM_MODE_TUNNEL) {+ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { decaps = 1; break; }@@ -136,10 +136,8 @@ nf_reset(skb); if (decaps) {- if (!(skb->dev->flags&IFF_LOOPBACK)) {- dst_release(skb->dst);- skb->dst = NULL;- }+ dst_release(skb->dst);+ skb->dst = NULL; netif_rx(skb); return 0; } else {diff -urN a/net/ipv4/raw.c b/net/ipv4/raw.c--- a/net/ipv4/raw.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv4/raw.c 2007-05-25 14:44:52.000000000 +0300@@ -489,7 +489,7 @@ } security_sk_classify_flow(sk, &fl);- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));+ err = ip_route_output_flow(&rt, &fl, sk, 1); } if (err) goto done;diff -urN a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c--- a/net/ipv4/tunnel4.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv4/tunnel4.c 2007-05-25 14:44:52.000000000 +0300@@ -14,9 +14,10 @@ #include <net/xfrm.h> static struct xfrm_tunnel *tunnel4_handlers;+static struct xfrm_tunnel *tunnel64_handlers; static DEFINE_MUTEX(tunnel4_mutex); -int xfrm4_tunnel_register(struct xfrm_tunnel *handler)+int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) { struct xfrm_tunnel **pprev; int ret = -EEXIST;@@ -24,7 +25,8 @@ mutex_lock(&tunnel4_mutex); - for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {+ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;+ *pprev; pprev = &(*pprev)->next) { if ((*pprev)->priority > priority) break; if ((*pprev)->priority == priority)@@ -44,14 +46,15 @@ EXPORT_SYMBOL(xfrm4_tunnel_register); -int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) { struct xfrm_tunnel **pprev; int ret = -ENOENT; mutex_lock(&tunnel4_mutex); - for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {+ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;+ *pprev; pprev = &(*pprev)->next) { if (*pprev == handler) { *pprev = handler->next; ret = 0;@@ -86,6 +89,26 @@ return 0; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+static int tunnel64_rcv(struct sk_buff *skb)+{+ struct xfrm_tunnel *handler;++ if (!pskb_may_pull(skb, sizeof(struct iphdr)))+ goto drop;++ for (handler = tunnel64_handlers; handler; handler = handler->next)+ if (!handler->handler(skb))+ return 0;++ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);++drop:+ kfree_skb(skb);+ return 0;+}+#endif+ static void tunnel4_err(struct sk_buff *skb, u32 info) { struct xfrm_tunnel *handler;@@ -101,17 +124,36 @@ .no_policy = 1, }; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+static struct net_protocol tunnel64_protocol = {+ .handler = tunnel64_rcv,+ .err_handler = tunnel4_err,+ .no_policy = 1,+};+#endif+ static int __init tunnel4_init(void) { if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { printk(KERN_ERR "tunnel4 init: can't add protocol\n"); return -EAGAIN; }+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+ if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {+ printk(KERN_ERR "tunnel64 init: can't add protocol\n");+ inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);+ return -EAGAIN;+ }+#endif return 0; } static void __exit tunnel4_fini(void) {+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)+ if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))+ printk(KERN_ERR "tunnel64 close: can't remove protocol\n");+#endif if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); }diff -urN a/net/ipv4/datagram.c b/net/ipv4/datagram.c--- a/net/ipv4/datagram.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv4/datagram.c 2007-05-25 14:44:52.000000000 +0300@@ -49,7 +49,7 @@ err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, sk->sk_protocol,- inet->sport, usin->sin_port, sk);+ inet->sport, usin->sin_port, sk, 1); if (err) return err; if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {diff -urN a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c--- a/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 14:44:52.000000000 +0300@@ -66,6 +66,8 @@ top_iph->daddr = x->id.daddr.a4; top_iph->protocol = IPPROTO_IPIP; + skb->protocol = htons(ETH_P_IP);+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); return 0; }diff -urN a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c--- a/net/ipv6/xfrm6_policy.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv6/xfrm6_policy.c 2007-05-25 14:44:52.000000000 +0300@@ -24,6 +24,7 @@ static struct dst_ops xfrm6_dst_ops; static struct xfrm_policy_afinfo xfrm6_policy_afinfo;+static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu); static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl) {@@ -89,7 +90,7 @@ static inline struct in6_addr* __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr) {- return (x->type->remote_addr) ?+ return (x->type && x->type->remote_addr) ? (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) : (struct in6_addr*)&x->id.daddr; }@@ -97,7 +98,7 @@ static inline struct in6_addr* __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr) {- return (x->type->local_addr) ?+ return (x->type && x->type->local_addr) ? (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) : (struct in6_addr*)&x->props.saddr; }@@ -105,7 +106,7 @@ 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,16 +132,19 @@ struct dst_entry *dst, *dst_prev; struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); struct rt6_info *rt = rt0;- struct in6_addr *remote = &fl->fl6_dst;- struct in6_addr *local = &fl->fl6_src;+ unsigned short outer_family = 0, beet = 0; struct flowi fl_tunnel = { .nl_u = { .ip6_u = {- .saddr = *local,- .daddr = *remote+ .saddr = fl->fl6_src,+ .daddr = fl->fl6_dst } } };+ union {+ struct in6_addr *in6;+ struct in_addr *in;+ } remote, local; int i; int err = 0; int header_len = 0;@@ -153,8 +157,7 @@ for (i = 0; i < nx; i++) { struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops); struct xfrm_dst *xdst;- int tunnel = 0;-+ if (unlikely(dst1 == NULL)) { err = -ENOBUFS; dst_release(&rt->u.dst);@@ -178,18 +181,39 @@ dst1->next = dst_prev; dst_prev = dst1; if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {- remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);- local = __xfrm6_bundle_addr_local(xfrm[i], local);- tunnel = 1;+ outer_family = xfrm[i]->props.family;+ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);+ if (outer_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 (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 {+ BUG_ON(1);+ } }+ __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); trailer_len += xfrm[i]->props.trailer_len; - if (tunnel) {- ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);- ipv6_addr_copy(&fl_tunnel.fl6_src, local);+ if (outer_family) {+ switch (outer_family) {+ default:+ case AF_INET6:+ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);+ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);+ break;+ case AF_INET:+ fl_tunnel.fl4_dst = remote.in->s_addr;+ fl_tunnel.fl4_src = local.in->s_addr;+ fl_tunnel.fl4_tos = 0;+ fl_tunnel.fl4_fwmark = 0;+ fl_tunnel.fl4_scope = 0;+ break;+ } err = xfrm_dst_lookup((struct xfrm_dst **) &rt,- &fl_tunnel, AF_INET6);+ &fl_tunnel, outer_family); if (err) goto error; } else@@ -241,6 +265,13 @@ } xfrm_init_pmtu(dst);++ if (beet && outer_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_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c--- a/net/ipv6/xfrm6_mode_beet.c 2007-05-25 14:44:52.000000000 +0300+++ b/net/ipv6/xfrm6_mode_beet.c 2007-05-25 14:44:52.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>@@ -16,6 +17,7 @@ #include <net/dsfield.h> #include <net/dst.h> #include <net/inet_ecn.h>+#include <net/ip.h> #include <net/ipv6.h> #include <net/xfrm.h> @@ -31,39 +33,166 @@ * its absence, that of the top IP header. The value of skb->data will always * point to the top IP header. */+/* 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 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -