?? beet-interfamily-2.6.22.6.patch
字號(hào):
+ unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr);+ optptr[2] -= 4;+ memset(&optptr[optptr[2]-1], 0, 4);+ }+ if (opt->ts) {+ unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr);+ if (opt->ts_needtime) {+ optptr[2] -= 4;+ memset(&optptr[optptr[2]-1], 0, 4);+ if ((optptr[3]&0xF) == IPOPT_TS_PRESPEC)+ optptr[2] -= 4;+ }+ if (opt->ts_needaddr) {+ optptr[2] -= 4;+ memset(&optptr[optptr[2]-1], 0, 4);+ }+ }+}++static struct ip_options *ip_options_get_alloc(const int optlen)+{+ struct ip_options *opt = kmalloc(sizeof(*opt) + ((optlen + 3) & ~3),+ GFP_KERNEL);+ if (opt)+ memset(opt, 0, sizeof(*opt));+ return opt;+}++static int ip_options_get_finish(struct ip_options **optp,+ struct ip_options *opt, int optlen)+{+ while (optlen & 3)+ opt->__data[optlen++] = IPOPT_END;+ opt->optlen = optlen;+ opt->is_data = 1;+ if (optlen && ip_options_compile(opt, NULL)) {+ kfree(opt);+ return -EINVAL;+ }+ kfree(*optp);+ *optp = opt;+ return 0;+}++int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen)+{+ struct ip_options *opt = ip_options_get_alloc(optlen);++ if (!opt)+ return -ENOMEM;+ if (optlen && copy_from_user(opt->__data, data, optlen)) {+ kfree(opt);+ return -EFAULT;+ }+ return ip_options_get_finish(optp, opt, optlen);+}++int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)+{+ struct ip_options *opt = ip_options_get_alloc(optlen);++ if (!opt)+ return -ENOMEM;+ if (optlen)+ memcpy(opt->__data, data, optlen);+ return ip_options_get_finish(optp, opt, optlen);+}++void ip_forward_options(struct sk_buff *skb)+{+ struct ip_options * opt = &(IPCB(skb)->opt);+ unsigned char * optptr;+ struct rtable *rt = (struct rtable*)skb->dst;+ unsigned char *raw = skb_network_header(skb);++ if (opt->rr_needaddr) {+ optptr = (unsigned char *)raw + opt->rr;+ ip_rt_get_source(&optptr[optptr[2]-5], rt);+ opt->is_changed = 1;+ }+ if (opt->srr_is_hit) {+ int srrptr, srrspace;++ optptr = raw + opt->srr;++ for ( srrptr=optptr[2], srrspace = optptr[1];+ srrptr <= srrspace;+ srrptr += 4+ ) {+ if (srrptr + 3 > srrspace)+ break;+ if (memcmp(&rt->rt_dst, &optptr[srrptr-1], 4) == 0)+ break;+ }+ if (srrptr + 3 <= srrspace) {+ opt->is_changed = 1;+ ip_rt_get_source(&optptr[srrptr-1], rt);+ ip_hdr(skb)->daddr = rt->rt_dst;+ optptr[2] = srrptr+4;+ } else if (net_ratelimit())+ printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");+ if (opt->ts_needaddr) {+ optptr = raw + opt->ts;+ ip_rt_get_source(&optptr[optptr[2]-9], rt);+ opt->is_changed = 1;+ }+ }+ if (opt->is_changed) {+ opt->is_changed = 0;+ ip_send_check(ip_hdr(skb));+ }+}++int ip_options_rcv_srr(struct sk_buff *skb)+{+ struct ip_options *opt = &(IPCB(skb)->opt);+ int srrspace, srrptr;+ __be32 nexthop;+ struct iphdr *iph = ip_hdr(skb);+ unsigned char *optptr = skb_network_header(skb) + opt->srr;+ struct rtable *rt = (struct rtable*)skb->dst;+ struct rtable *rt2;+ int err;++ if (!opt->srr)+ return 0;++ if (skb->pkt_type != PACKET_HOST)+ return -EINVAL;+ if (rt->rt_type == RTN_UNICAST) {+ if (!opt->is_strictroute)+ return 0;+ icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24));+ return -EINVAL;+ }+ if (rt->rt_type != RTN_LOCAL)+ return -EINVAL;++ for (srrptr=optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {+ if (srrptr + 3 > srrspace) {+ icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24));+ return -EINVAL;+ }+ memcpy(&nexthop, &optptr[srrptr-1], 4);++ rt = (struct rtable*)skb->dst;+ skb->dst = NULL;+ err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);+ rt2 = (struct rtable*)skb->dst;+ if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {+ ip_rt_put(rt2);+ skb->dst = &rt->u.dst;+ return -EINVAL;+ }+ ip_rt_put(rt);+ if (rt2->rt_type != RTN_LOCAL)+ break;+ /* Superfast 8) loopback forward */+ memcpy(&iph->daddr, &optptr[srrptr-1], 4);+ opt->is_changed = 1;+ }+ if (srrptr <= srrspace) {+ opt->srr_is_hit = 1;+ opt->is_changed = 1;+ }+ return 0;+}diff -urN linux-2.6.22.6/net/ipv4/xfrm4_input.c linux-2.6.22.6-beet/net/ipv4/xfrm4_input.c--- linux-2.6.22.6/net/ipv4/xfrm4_input.c 2007-08-31 09:21:01.000000000 +0300+++ linux-2.6.22.6-beet/net/ipv4/xfrm4_input.c 2007-09-11 22:38:08.000000000 +0300@@ -108,7 +108,9 @@ 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 &&+ x->sel.family != AF_INET)) { decaps = 1; break; }diff -urN linux-2.6.22.6/net/ipv4/xfrm4_input.c.orig linux-2.6.22.6-beet/net/ipv4/xfrm4_input.c.orig--- linux-2.6.22.6/net/ipv4/xfrm4_input.c.orig 1970-01-01 02:00:00.000000000 +0200+++ linux-2.6.22.6-beet/net/ipv4/xfrm4_input.c.orig 2007-08-31 09:21:01.000000000 +0300@@ -0,0 +1,169 @@+/*+ * xfrm4_input.c+ *+ * Changes:+ * YOSHIFUJI Hideaki @USAGI+ * Split up af-specific portion+ * Derek Atkins <derek@ihtfp.com>+ * Add Encapsulation support+ *+ */++#include <linux/module.h>+#include <linux/string.h>+#include <linux/netfilter.h>+#include <linux/netfilter_ipv4.h>+#include <net/ip.h>+#include <net/xfrm.h>++int xfrm4_rcv(struct sk_buff *skb)+{+ return xfrm4_rcv_encap(skb, 0);+}++EXPORT_SYMBOL(xfrm4_rcv);++static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)+{+ switch (nexthdr) {+ case IPPROTO_IPIP:+ case IPPROTO_IPV6:+ *spi = ip_hdr(skb)->saddr;+ *seq = 0;+ return 0;+ }++ return xfrm_parse_spi(skb, nexthdr, spi, seq);+}++#ifdef CONFIG_NETFILTER+static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)+{+ if (skb->dst == NULL) {+ const struct iphdr *iph = ip_hdr(skb);++ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,+ skb->dev))+ goto drop;+ }+ return dst_input(skb);+drop:+ kfree_skb(skb);+ return NET_RX_DROP;+}+#endif++int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)+{+ __be32 spi, seq;+ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];+ struct xfrm_state *x;+ int xfrm_nr = 0;+ int decaps = 0;+ int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);++ if (err != 0)+ goto drop;++ do {+ const struct iphdr *iph = ip_hdr(skb);++ if (xfrm_nr == XFRM_MAX_DEPTH)+ goto drop;++ x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,+ iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);+ if (x == NULL)+ goto drop;++ spin_lock(&x->lock);+ if (unlikely(x->km.state != XFRM_STATE_VALID))+ goto drop_unlock;++ if ((x->encap ? x->encap->encap_type : 0) != encap_type)+ goto drop_unlock;++ if (x->props.replay_window && xfrm_replay_check(x, seq))+ goto drop_unlock;++ if (xfrm_state_check_expire(x))+ goto drop_unlock;++ if (x->type->input(x, skb))+ goto drop_unlock;++ /* only the first xfrm gets the encap type */+ encap_type = 0;++ if (x->props.replay_window)+ xfrm_replay_advance(x, seq);++ x->curlft.bytes += skb->len;+ x->curlft.packets++;++ spin_unlock(&x->lock);++ xfrm_vec[xfrm_nr++] = x;++ if (x->mode->input(x, skb))+ goto drop;++ if (x->props.mode == XFRM_MODE_TUNNEL) {+ decaps = 1;+ break;+ }++ err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);+ if (err < 0)+ goto drop;+ } while (!err);++ /* Allocate new secpath or COW existing one. */++ if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {+ struct sec_path *sp;+ sp = secpath_dup(skb->sp);+ if (!sp)+ goto drop;+ if (skb->sp)+ secpath_put(skb->sp);+ skb->sp = sp;+ }+ if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)+ goto drop;++ memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,+ xfrm_nr * sizeof(xfrm_vec[0]));+ skb->sp->len += xfrm_nr;++ nf_reset(skb);++ if (decaps) {+ dst_release(skb->dst);+ skb->dst = NULL;+ netif_rx(skb);+ return 0;+ } else {+#ifdef CONFIG_NETFILTER+ __skb_push(skb, skb->data - skb_network_header(skb));+ ip_hdr(skb)->tot_len = htons(skb->len);+ ip_send_check(ip_hdr(skb));++ NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,+ xfrm4_rcv_encap_finish);+ return 0;+#else+ return -ip_hdr(skb)->protocol;+#endif+ }++drop_unlock:+ spin_unlock(&x->lock);+ xfrm_state_put(x);+drop:+ while (--xfrm_nr >= 0)+ xfrm_state_put(xfrm_vec[xfrm_nr]);++ kfree_skb(skb);+ return 0;+}diff -urN linux-2.6.22.6/net/ipv4/xfrm4_mode_beet.c linux-2.6.22.6-beet/net/ipv4/xfrm4_mode_beet.c--- linux-2.6.22.6/net/ipv4/xfrm4_mode_beet.c 2007-08-31 09:21:01.000000000 +0300+++ linux-2.6.22.6-beet/net/ipv4/xfrm4_mode_beet.c 2007-09-11 22:38:08.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/dst.h> #include <net/ip.h> #include <net/xfrm.h>+#include <net/inet_ecn.h> /* Add encapsulation header. *@@ -24,92 +26,177 @@ * 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.+ * On exit, skb->transport_header will be set to the start of the+ * payload to be processed by x->type->output and skb->network_header+ * 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;- int hdrlen, optlen;-- iph = ip_hdr(skb);- skb->transport_header = skb->network_header;-- hdrlen = 0;- optlen = iph->ihl * 4 - sizeof(*iph);- if (unlikely(optlen))- hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);-- skb_push(skb, x->props.header_len - IPV4_BEET_PHMAXLEN + hdrlen);- skb_reset_network_header(skb);- top_iph = ip_hdr(skb);- skb->transport_header += sizeof(*iph) - hdrlen;-- memmove(top_iph, iph, sizeof(*iph));- if (unlikely(optlen)) {- struct ip_beet_phdr *ph;-- BUG_ON(optlen < 0);-- ph = (struct ip_beet_phdr *)skb_transport_header(skb);- ph->padlen = 4 - (optlen & 4);- ph->hdrlen = optlen / 8;- ph->nexthdr = top_iph->protocol;- if (ph->padlen)- memset(ph + 1, IPOPT_NOP, ph->padlen);-- top_iph->protocol = IPPROTO_BEETPH;- top_iph->ihl = sizeof(struct iphdr) / 4;+ struct dst_entry *dst = skb->dst;+ struct iphdr *iphv4, *top_iphv4;+ int hdrlen;++ if (ip_hdr(skb)->version == 4) {+ int optlen;++ /* 4-4 */+ iphv4 = ip_hdr(skb);+ skb->transport_header = skb->network_header;++ hdrlen = 0;+ optlen = iphv4->ihl * 4 - sizeof(*iphv4);+ if (unlikely(optlen))+ hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);++ skb_push(skb, x->props.header_len - IPV4_BEET_PHMAXLEN + hdrlen);+ skb_reset_network_header(skb);+ top_iphv4 = ip_hdr(skb);+ skb->transport_header += sizeof(*iphv4) - hdrlen;++ memmove(top_iphv4, iphv4, sizeof(*iphv4));+ if (unlikely(optlen)) {+ struct ip_beet_phdr *ph;++ BUG_ON(optlen < 0);++ ph = (struct ip_beet_phdr *)skb_transport_header(skb);+ ph->padlen = 4 - (optlen & 4);+ ph->hdrlen = optlen / 8;+ ph->nexthdr = iphv4->protocol;+ if (ph->padlen)+ memset(ph + 1, IPOPT_NOP, ph->padlen);++ top_iphv4->protocol = IPPROTO_BEETPH;+ top_iphv4->ihl = 5;+ }++ top_iphv4->saddr = x->props.saddr.a4;+ top_iphv4->daddr = x->id.daddr.a4;+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)+ } else if (ip_hdr(skb)->version == 6) {+ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);+ u8 protocol = ipv6_hdr(skb)->nexthdr;++ skb_set_transport_header(skb, sizeof(struct ipv6hdr));++ /* Inner = 6, Outer = 4 : changing the external IP hdr+ * to the outer addresses+ */+ hdrlen = x->props.header_len;++ skb_pull(skb, delta);+ skb_push(skb, hdrlen);++ skb_reset_network_header(skb);+ top_iphv4 = ip_hdr(skb);+ top_iphv4->ihl = 5;+ 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->protocol = protocol;++ top_iphv4->saddr = x->props.saddr.a4;+ top_iphv4->daddr = x->id.daddr.a4;+ IPCB(skb)->flags = 0;+#endif } - top_iph->saddr = x->props.saddr.a4;- top_iph->daddr = x->id.daddr.a4;-+ skb->protocol = htons(ETH_P_IP);+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); return 0; } static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb);+ int hops = iph->ttl; int phlen = 0; int optlen = 0;- u8 ph_nexthdr = 0;+ __u8 protocol = 0; int err = -EINVAL; - if (unlikely(iph->protocol == IPPROTO_BEETPH)) {- struct ip_beet_phdr *ph;+ protocol = iph->protocol;+ if (x->sel.family == AF_INET) {+ if (unlikely(protocol == IPPROTO_BEETPH)) {+ struct ip_beet_phdr *ph;++ if (!pskb_may_pull(skb, sizeof(*ph)))+ goto out;++ ph = (struct ip_beet_phdr *)(ipip_hdr(skb) + 1);++ phlen = sizeof(*ph) + ph->padlen;+ optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);+ if (optlen < 0 || optlen & 3 || optlen > 250)+ goto out;++ if (!pskb_may_pull(skb, phlen + optlen))+ goto out;++ protocol = ph->nexthdr;+ }++ skb_push(skb, sizeof(*iph) - phlen);+ skb_reset_network_header(skb);+ memmove(skb_network_header(skb), iph, sizeof(*iph));++ iph = ip_hdr(skb);+ iph->ihl = (sizeof(*iph) + optlen) / 4;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -