?? simple-beet-and-interfamily-2.6.17.9-v1.patch
字號:
+ * section 3.1.2+ */+ if (!x->props.mode)+ skb->ip_summed = CHECKSUM_UNNECESSARY;+ }++ iph->protocol = nexthdr[1];+ pskb_trim(skb, skb->len - alen - padlen - 2);+ memcpy(workbuf, skb->nh.raw, iph->ihl*4);+ skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);+ skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;+ memcpy(skb->nh.raw, workbuf, iph->ihl*4);+ skb->nh.iph->tot_len = htons(skb->len);++ return 0;++out:+ return -EINVAL;+}++static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)+{+ struct esp_data *esp = x->data;+ u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);++ if (x->props.mode) {+ mtu = ALIGN(mtu + 2, blksize);+ } else {+ /* The worst case. */+ mtu = ALIGN(mtu + 2, 4) + blksize - 4;+ }+ if (esp->conf.padlen)+ mtu = ALIGN(mtu, esp->conf.padlen);++ return mtu + x->props.header_len + esp->auth.icv_trunc_len;+}++static void esp4_err(struct sk_buff *skb, u32 info)+{+ struct iphdr *iph = (struct iphdr*)skb->data;+ struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));+ struct xfrm_state *x;++ if (skb->h.icmph->type != ICMP_DEST_UNREACH ||+ skb->h.icmph->code != ICMP_FRAG_NEEDED)+ return;++ x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);+ if (!x)+ return;+ NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",+ ntohl(esph->spi), ntohl(iph->daddr));+ xfrm_state_put(x);+}++static void esp_destroy(struct xfrm_state *x)+{+ struct esp_data *esp = x->data;++ if (!esp)+ return;++ crypto_free_tfm(esp->conf.tfm);+ esp->conf.tfm = NULL;+ kfree(esp->conf.ivec);+ esp->conf.ivec = NULL;+ crypto_free_tfm(esp->auth.tfm);+ esp->auth.tfm = NULL;+ kfree(esp->auth.work_icv);+ esp->auth.work_icv = NULL;+ kfree(esp);+}++static int esp_init_state(struct xfrm_state *x)+{+ struct esp_data *esp = NULL;++ /* null auth and encryption can have zero length keys */+ if (x->aalg) {+ if (x->aalg->alg_key_len > 512)+ goto error;+ }+ if (x->ealg == NULL)+ goto error;++ esp = kmalloc(sizeof(*esp), GFP_KERNEL);+ if (esp == NULL)+ return -ENOMEM;++ memset(esp, 0, sizeof(*esp));++ if (x->aalg) {+ struct xfrm_algo_desc *aalg_desc;++ esp->auth.key = x->aalg->alg_key;+ esp->auth.key_len = (x->aalg->alg_key_len+7)/8;+ esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);+ if (esp->auth.tfm == NULL)+ goto error;+ esp->auth.icv = esp_hmac_digest;++ aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);+ BUG_ON(!aalg_desc);++ if (aalg_desc->uinfo.auth.icv_fullbits/8 !=+ crypto_tfm_alg_digestsize(esp->auth.tfm)) {+ NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",+ x->aalg->alg_name,+ crypto_tfm_alg_digestsize(esp->auth.tfm),+ aalg_desc->uinfo.auth.icv_fullbits/8);+ goto error;+ }++ esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;+ esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;++ esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);+ if (!esp->auth.work_icv)+ goto error;+ }+ esp->conf.key = x->ealg->alg_key;+ esp->conf.key_len = (x->ealg->alg_key_len+7)/8;+ if (x->props.ealgo == SADB_EALG_NULL)+ esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);+ else+ esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);+ if (esp->conf.tfm == NULL)+ goto error;+ esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);+ esp->conf.padlen = 0;+ if (esp->conf.ivlen) {+ esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);+ if (unlikely(esp->conf.ivec == NULL))+ goto error;+ get_random_bytes(esp->conf.ivec, esp->conf.ivlen);+ }+ if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))+ goto error;+ x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;+ if (x->props.mode)+ x->props.header_len += sizeof(struct iphdr);+ if (x->encap) {+ struct xfrm_encap_tmpl *encap = x->encap;++ switch (encap->encap_type) {+ default:+ goto error;+ case UDP_ENCAP_ESPINUDP:+ x->props.header_len += sizeof(struct udphdr);+ break;+ case UDP_ENCAP_ESPINUDP_NON_IKE:+ x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32);+ break;+ }+ }+ x->data = esp;+ x->props.trailer_len = esp4_get_max_size(x, 0) - x->props.header_len;+ return 0;++error:+ x->data = esp;+ esp_destroy(x);+ x->data = NULL;+ return -EINVAL;+}++static struct xfrm_type esp_type =+{+ .description = "ESP4",+ .owner = THIS_MODULE,+ .proto = IPPROTO_ESP,+ .init_state = esp_init_state,+ .destructor = esp_destroy,+ .get_max_size = esp4_get_max_size,+ .input = esp_input,+ .output = esp_output+};++static struct net_protocol esp4_protocol = {+ .handler = xfrm4_rcv,+ .err_handler = esp4_err,+ .no_policy = 1,+};++static int __init esp4_init(void)+{+ if (xfrm_register_type(&esp_type, AF_INET) < 0) {+ printk(KERN_INFO "ip esp init: can't add xfrm type\n");+ return -EAGAIN;+ }+ if (inet_add_protocol(&esp4_protocol, IPPROTO_ESP) < 0) {+ printk(KERN_INFO "ip esp init: can't add protocol\n");+ xfrm_unregister_type(&esp_type, AF_INET);+ return -EAGAIN;+ }+ return 0;+}++static void __exit esp4_fini(void)+{+ if (inet_del_protocol(&esp4_protocol, IPPROTO_ESP) < 0)+ printk(KERN_INFO "ip esp close: can't remove protocol\n");+ if (xfrm_unregister_type(&esp_type, AF_INET) < 0)+ printk(KERN_INFO "ip esp close: can't remove xfrm type\n");+}++module_init(esp4_init);+module_exit(esp4_fini);+MODULE_LICENSE("GPL");diff -urN linux-2.6.17.9/net/ipv4/ipcomp.c linux-2.6.17.9.hipl/net/ipv4/ipcomp.c--- linux-2.6.17.9/net/ipv4/ipcomp.c 2006-08-18 19:26:24.000000000 +0300+++ linux-2.6.17.9.hipl/net/ipv4/ipcomp.c 2006-12-18 15:01:03.000000000 +0200@@ -194,7 +194,7 @@ return 0; out_ok:- if (x->props.mode)+ if (x->props.mode == XFRM_MODE_TUNNEL) ip_send_check(iph); return 0; }@@ -234,7 +234,7 @@ t->id.daddr.a4 = x->id.daddr.a4; memcpy(&t->sel, &x->sel, sizeof(t->sel)); t->props.family = AF_INET;- t->props.mode = 1;+ t->props.mode = x->props.mode; t->props.saddr.a4 = x->props.saddr.a4; t->props.flags = x->props.flags; @@ -434,8 +434,10 @@ memset(ipcd, 0, sizeof(*ipcd)); x->props.header_len = 0;- 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; mutex_lock(&ipcomp_resource_mutex); if (!ipcomp_alloc_scratches())@@ -446,7 +448,7 @@ goto error; mutex_unlock(&ipcomp_resource_mutex); - if (x->props.mode) {+ if (x->props.mode == XFRM_MODE_TUNNEL) { err = ipcomp_tunnel_attach(x); if (err) goto error_tunnel;diff -urN linux-2.6.17.9/net/ipv4/xfrm4_input.c linux-2.6.17.9.hipl/net/ipv4/xfrm4_input.c--- linux-2.6.17.9/net/ipv4/xfrm4_input.c 2006-08-18 19:26:24.000000000 +0300+++ linux-2.6.17.9.hipl/net/ipv4/xfrm4_input.c 2006-12-18 15:01:04.000000000 +0200@@ -115,16 +115,29 @@ iph = skb->nh.iph; - if (x->props.mode) {- if (iph->protocol != IPPROTO_IPIP)- goto drop;- if (!pskb_may_pull(skb, sizeof(struct iphdr)))- goto drop;- if (skb_cloned(skb) &&- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))- goto drop;- if (x->props.flags & XFRM_STATE_DECAP_DSCP)- ipv4_copy_dscp(iph, skb->h.ipiph);+ if (x->props.mode == XFRM_MODE_TUNNEL) {+ if (x->sel.family == AF_INET) {+ if (iph->protocol != IPPROTO_IPIP)+ goto drop;+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))+ goto drop;+ if (skb_cloned(skb) &&+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))+ goto drop;+ if (x->props.flags & XFRM_STATE_DECAP_DSCP)+ ipv4_copy_dscp(iph, skb->h.ipiph);+ } else if (x->sel.family == AF_INET6) {+ /* Inner = 6, Outer = 4 */+ if (skb->nh.iph->protocol != IPPROTO_IPV6)+ goto drop;++ if (skb_cloned(skb) &&+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))+ goto drop;+ skb->protocol = htons(ETH_P_IPV6);+ } else+ BUG_ON(1);+ if (!(x->props.flags & XFRM_STATE_NOECN)) ipip_ecn_decapsulate(skb); skb->mac.raw = memmove(skb->data - skb->mac_len,@@ -133,6 +146,84 @@ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); decaps = 1; break;+ } else if (x->props.mode == XFRM_MODE_BEET) {+ 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))+ return -EINVAL; //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 drop;+ phlen = ph->hdrlen * 8;+ optlen = phlen - ph->padlen - sizeof(*ph);++ if (optlen < 0 || optlen & 3 || optlen > 250)+ goto drop;+ if (!pskb_may_pull(skb, phlen))+ goto drop;++ ph_nexthdr = ph->nexthdr;+ }+ } else+ BUG_ON(1);+++ if (skb_cloned(skb) &&+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))+ goto drop;++ 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);+ }+ decaps = 1;+ break; } if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) < 0)diff -urN linux-2.6.17.9/net/ipv4/xfrm4_output.c linux-2.6.17.9.hipl/net/ipv4/xfrm4_output.c--- linux-2.6.17.9/net/ipv4/xfrm4_output.c 2006-08-18 19:26:24.000000000 +0300+++ linux-2.6.17.9.hipl/net/ipv4/xfrm4_output.c 2006-12-18 15:01:04.000000000 +0200@@ -32,45 +32,131 @@ */ static void xfrm4_encap(struct sk_buff *skb) {- struct dst_entry *dst = skb->dst;- struct xfrm_state *x = dst->xfrm;- struct iphdr *iph, *top_iph;- int flags;-- iph = skb->nh.iph;- skb->h.ipiph = iph;-- skb->nh.raw = skb_push(skb, x->props.header_len);- top_iph = skb->nh.iph;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -