📄 hipmod-sleep-beet-and-interfamily-all-in-one.patch
字号:
diff -urN a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c--- a/net/ipv4/xfrm4_input.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/xfrm4_input.c 2007-05-25 12:21:11.000000000 +0300@@ -13,6 +13,7 @@ #include <linux/string.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h>+#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> @@ -23,6 +24,15 @@ EXPORT_SYMBOL(xfrm4_rcv); +static inline void ipip_ecn_decapsulate(struct sk_buff *skb)+{+ struct iphdr *outer_iph = skb->nh.iph;+ struct iphdr *inner_iph = skb->h.ipiph;++ if (INET_ECN_is_ce(outer_iph->tos))+ IP_ECN_set_ce(inner_iph);+}+ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) { switch (nexthdr) {@@ -103,11 +113,11 @@ xfrm_vec[xfrm_nr++] = x; - if (x->mode->input(x, skb))+ if (x->mode->input(x, skb)) goto drop;-+ if (x->props.mode) {- decaps = 1;+ decaps = 1; break; } diff -urN a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c--- a/net/ipv4/xfrm4_output.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/xfrm4_output.c 2007-05-25 12:21:11.000000000 +0300@@ -14,10 +14,12 @@ #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/netfilter_ipv4.h>+#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/icmp.h> + static int xfrm4_tunnel_check_size(struct sk_buff *skb) { int mtu, ret = 0;@@ -54,7 +56,7 @@ goto error_nolock; } - if (x->props.mode) {+ if (x->props.mode == XFRM_MODE_TUNNEL) { err = xfrm4_tunnel_check_size(skb); if (err) goto error_nolock;@@ -66,7 +68,7 @@ if (err) goto error; - err = x->mode->output(skb);+ err = x->mode->output(skb); if (err) goto error; @@ -85,6 +87,7 @@ } dst = skb->dst; x = dst->xfrm;+ } while (x && !x->props.mode); IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;diff -urN a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c--- a/net/ipv4/xfrm4_tunnel.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/xfrm4_tunnel.c 2007-05-25 12:21:11.000000000 +0300@@ -28,13 +28,20 @@ static int ipip_init_state(struct xfrm_state *x) {- if (!x->props.mode)- return -EINVAL;- if (x->encap) return -EINVAL; - x->props.header_len = sizeof(struct iphdr);+ switch (x->props.mode) {+ case XFRM_MODE_TRANSPORT:+ return -EINVAL;+ default:+ case XFRM_MODE_TUNNEL:+ x->props.header_len = sizeof(struct iphdr);+ break;+ case XFRM_MODE_BEET:+ x->props.header_len += IPV4_BEET_PHMAXLEN;+ break;+ } return 0; }diff -urN a/net/ipv4/route.c b/net/ipv4/route.c--- a/net/ipv4/route.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/route.c 2007-05-25 12:21:11.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)))@@ -2631,7 +2632,7 @@ int ip_route_output_key(struct rtable **rp, struct flowi *flp) {- return ip_route_output_flow(rp, flp, NULL, 0);+ return ip_route_output_flow(rp, flp, NULL, XFRM_LOOKUP_SLEEP); } static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,diff -urN a/net/ipv4/ah4.c b/net/ipv4/ah4.c--- a/net/ipv4/ah4.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/ah4.c 2007-05-25 12:21:11.000000000 +0300@@ -253,8 +253,10 @@ goto error; x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len);- if (x->props.mode)+ 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; x->data = ahp; return 0;diff -urN a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c--- a/net/ipv4/xfrm4_policy.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/xfrm4_policy.c 2007-05-25 12:21:11.000000000 +0300@@ -16,6 +16,8 @@ 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) { return __ip_route_output_key((struct rtable**)dst, fl);@@ -53,17 +55,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_dst,+ .daddr = fl->fl4_src, .tos = fl->fl4_tos } } };+ union {+ struct in6_addr *in6;+ struct in_addr *in;+ } remote, local;+ unsigned short outer_family = 0, beet = 0; int i; int err; int header_len = 0;@@ -75,7 +80,6 @@ for (i = 0; i < nx; i++) { struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops); struct xfrm_dst *xdst;- int tunnel = 0; if (unlikely(dst1 == NULL)) { err = -ENOBUFS;@@ -96,21 +100,45 @@ dst1->next = dst_prev; dst_prev = dst1;- if (xfrm[i]->props.mode) {- remote = xfrm[i]->id.daddr.a4;- local = xfrm[i]->props.saddr.a4;- tunnel = 1;++ if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL || xfrm[i]->props.mode == XFRM_MODE_BEET) {+ outer_family = xfrm[i]->props.family;+ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);++ if(outer_family == AF_INET6){+ remote.in6 = (struct in6_addr*)&xfrm[i]->id.daddr;+ local.in6 = (struct in6_addr*)&xfrm[i]->props.saddr;+ } else if(outer_family == AF_INET){+ remote.in = (struct in_addr*)&xfrm[i]->id.daddr;+ local.in = (struct in_addr*)&xfrm[i]->props.saddr;+ } 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) {+ case AF_INET:+ fl_tunnel.fl4_dst = remote.in->s_addr;+ fl_tunnel.fl4_src = local.in->s_addr;+ break;+ case AF_INET6:+ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);+ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);+ break;+ default:+ BUG_ON(1);+ } 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); }@@ -160,6 +188,11 @@ } xfrm_init_pmtu(dst);+ if (beet && outer_family == AF_INET6) {+ 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/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c--- a/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 12:21:11.000000000 +0300+++ b/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 12:21:11.000000000 +0300@@ -33,7 +33,7 @@ * 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_tunnel_output(struct sk_buff *skb)+ static int xfrm4_tunnel_output(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm;@@ -98,6 +98,182 @@ return err; } +/* jk: this should be moved to the beet module! */+static int xfrm4_beet_output(struct sk_buff *skb)+{+ struct dst_entry *dst = skb->dst;+ struct xfrm_state *x = dst->xfrm;+ 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;+ + } 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;+ + } else + BUG_ON(1);+ + return 0;+}+++/* jk: this should be moved to the beet module! */+static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)+{+ int err = -EINVAL;+ int phlen = 0;+ int optlen = 0;+ __u8 ph_nexthdr = 0;+ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr);+ int proto = skb->nh.iph->protocol;+ int hops = skb->nh.iph->ttl;+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);+ + 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; //Just returning from here.+ }++ skb->nh.raw -= delta;+ } else if (x->sel.family == AF_INET) {+ // We need to extract the PH+ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->nh.iph + 1);++ if (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;++ ph_nexthdr = ph->nexthdr;+ }+ } else+ BUG_ON(1);++ 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);+ skb->nh.raw = skb->data;++ if (x->sel.family == AF_INET) {+ struct iphdr *iph = skb->nh.iph;++ if (unlikely(phlen)) {+ skb_pull(skb, phlen - optlen);+ 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 = proto;+ ip_send_check(iph);+ } 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 = proto;+ 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;+}+ static struct xfrm_mode xfrm4_tunnel_mode = { .input = xfrm4_tunnel_input, .output = xfrm4_tunnel_output,@@ -105,8 +281,19 @@ .encap = XFRM_MODE_TUNNEL, }; +/* jk: this should be moved to the beet module! */+static struct xfrm_mode xfrm4_beet_mode = {+ .input = xfrm4_beet_input,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -