ipsec_tunnel.c
来自「FREESWAN VPN源代码包」· C语言 代码 · 共 2,178 行 · 第 1/5 页
C
2,178 行
ixt_e->ixt_ivlen/8); } else#endif /* CONFIG_IPSEC_ALG */ switch(tdbp->tdb_encalg) {#ifdef CONFIG_IPSEC_ENC_3DES case ESP_3DES: des_ede3_cbc_encrypt((des_cblock *)idat, (des_cblock *)idat, ilen, ((struct des_eks *)(tdbp->tdb_key_e))[0].ks, ((struct des_eks *)(tdbp->tdb_key_e))[1].ks, ((struct des_eks *)(tdbp->tdb_key_e))[2].ks, (des_cblock *)iv, 1); break;#endif /* CONFIG_IPSEC_ENC_3DES */ default: spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; }#ifdef CONFIG_IPSEC_ALG if (!ixt_e)#endif /* CONFIG_IPSEC_ALG */ switch(tdbp->tdb_encalg) {#if defined(CONFIG_IPSEC_ENC_3DES)#ifdef CONFIG_IPSEC_ENC_3DES case ESP_3DES:#endif /* CONFIG_IPSEC_ENC_3DES */ /* XXX update IV with the last 8 octets of the encryption */ ((__u32*)(tdbp->tdb_iv))[0] = ((__u32 *)(idat))[(ilen >> 2) - 2]; ((__u32*)(tdbp->tdb_iv))[1] = ((__u32 *)(idat))[(ilen >> 2) - 1]; break;#endif /* defined(CONFIG_IPSEC_ENC_3DES) */ default: spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; }#ifdef CONFIG_IPSEC_ALG if (ixt_a) { ipsec_alg_sa_esp_hash(tdbp, (caddr_t)espp, len - iphlen - authlen, &(dat[len - authlen]), authlen); } else#endif /* CONFIG_IPSEC_ALG */ switch(tdbp->tdb_authalg) {#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: dmp("espp", (char*)espp, len - iphlen - authlen); tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, (caddr_t)espp, len - iphlen - authlen); dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Final(hash, &tctx.md5); dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, hash, AHMD596_ALEN); dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Final(hash, &tctx.md5); dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(&(dat[len - authlen]), hash, authlen); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(*hash)); break;#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; SHA1Update(&tctx.sha1, (caddr_t)espp, len - iphlen - authlen); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(&(dat[len - authlen]), hash, authlen); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(*hash)); break;#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; }#ifdef NET_21 skb->h.raw = (unsigned char*)espp;#endif /* NET_21 */ break;#endif /* !CONFIG_IPSEC_ESP */#ifdef CONFIG_IPSEC_AH case IPPROTO_AH: ahp = (struct ah *)(dat + iphlen); ahp->ah_spi = tdbp->tdb_said.spi; ahp->ah_rpl = htonl(++(tdbp->tdb_replaywin_lastseq)); ahp->ah_rv = 0; ahp->ah_nh = iph->protocol; ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32); iph->protocol = IPPROTO_AH; dmp("ahp", (char*)ahp, sizeof(*ahp)); ipo = *iph; ipo.tos = 0; ipo.frag_off = 0; ipo.ttl = 0; ipo.check = 0; dmp("ipo", (char*)&ipo, sizeof(ipo)); switch(tdbp->tdb_authalg) {#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5 case AH_MD5: tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr)); dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, dat + iphlen + headroom, len - iphlen - headroom); dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Final(hash, &tctx.md5); dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Update(&tctx.md5, hash, AHMD596_ALEN); dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); MD5Final(hash, &tctx.md5); dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(hash)); break;#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx; SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr)); SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data)); SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); SHA1Update(&tctx.sha1, dat + iphlen + headroom, len - iphlen - headroom); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(hash)); break;#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */ default: spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; }#ifdef NET_21 skb->h.raw = (unsigned char*)ahp;#endif /* NET_21 */ break;#endif /* CONFIG_IPSEC_AH */#ifdef CONFIG_IPSEC_IPIP case IPPROTO_IPIP: iph->version = 4; switch(sysctl_ipsec_tos) { case 0:#ifdef NET_21 iph->tos = skb->nh.iph->tos;#else /* NET_21 */ iph->tos = skb->ip_hdr->tos;#endif /* NET_21 */ break; case 1: iph->tos = 0; break; default: }#ifdef NET_21#ifdef NETDEV_23 iph->ttl = sysctl_ip_default_ttl;#else /* NETDEV_23 */ iph->ttl = ip_statistics.IpDefaultTTL;#endif /* NETDEV_23 */#else /* NET_21 */ iph->ttl = 64; /* ip_statistics.IpDefaultTTL; */#endif /* NET_21 */ iph->frag_off = 0; iph->saddr = ((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr; iph->daddr = ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr; iph->protocol = IPPROTO_IPIP; iph->ihl = sizeof(struct iphdr) >> 2 /* 5 */;#ifdef IP_SELECT_IDENT /* XXX use of skb->dst below is a questionable substitute for &rt->u.dst which is only available later-on */#ifdef IP_SELECT_IDENT_NEW ip_select_ident(iph, skb->dst, NULL);#else /* IP_SELECT_IDENT_NEW */ ip_select_ident(iph, skb->dst);#endif /* IP_SELECT_IDENT_NEW */#else /* IP_SELECT_IDENT */ iph->id = htons(ip_id_count++); /* Race condition here? */#endif /* IP_SELECT_IDENT */ newdst = (__u32)iph->daddr; newsrc = (__u32)iph->saddr; #ifdef NET_21 skb->h.ipiph = skb->nh.iph;#endif /* NET_21 */ break;#endif /* !CONFIG_IPSEC_IPIP */#ifdef CONFIG_IPSEC_IPCOMP case IPPROTO_COMP: { unsigned int flags = 0;#ifdef CONFIG_IPSEC_DEBUG unsigned int old_tot_len = ntohs(iph->tot_len);#endif /* CONFIG_IPSEC_DEBUG */ tdbp->tdb_comp_ratio_dbytes += ntohs(iph->tot_len); skb = skb_compress(skb, tdbp, &flags);#ifdef NET_21 iph = skb->nh.iph;#else /* NET_21 */ iph = skb->ip_hdr;#endif /* NET_21 */ tdbp->tdb_comp_ratio_cbytes += ntohs(iph->tot_len);#ifdef CONFIG_IPSEC_DEBUG if (debug_tunnel & DB_TN_CROUT) { if (old_tot_len > ntohs(iph->tot_len)) KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_tunnel_start_xmit: " "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", old_tot_len, ntohs(iph->tot_len), ntohs(((struct ipcomphdr*)(((char*)iph) + ((iph->ihl) << 2)))->ipcomp_cpi), ntohl(tdbp->tdb_said.spi), (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff)); else KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_tunnel_start_xmit: " "packet did not compress (flags = %d).\n", flags); }#endif /* CONFIG_IPSEC_DEBUG */ } break;#endif /* CONFIG_IPSEC_IPCOMP */ default: spin_unlock(&tdb_lock); stats->tx_errors++; goto cleanup; } #ifdef NET_21 skb->nh.raw = skb->data;#else /* NET_21 */ skb->ip_hdr = skb->h.iph = (struct iphdr *) skb->data;#endif /* NET_21 */ iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(tdbp), sa_len ? sa : " (error)"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph); tdbp->ips_life.ipl_bytes.ipl_count += len; tdbp->ips_life.ipl_bytes.ipl_last = len; if(!tdbp->ips_life.ipl_usetime.ipl_count) { tdbp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; } tdbp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; tdbp->ips_life.ipl_packets.ipl_count++; tdbprev = tdbp; tdbp = tdbp->ips_onext;#ifdef CONFIG_IPSEC_ALG ixt_e = NULL; /* invalidate ipsec_alg */ ixt_a = NULL;#endif /* CONFIG_IPSEC_ALG */ } /* end encapsulation loop here XXX */ spin_unlock(&tdb_lock); matcher.sen_ip_src.s_addr = iph->saddr; matcher.sen_ip_dst.s_addr = iph->daddr; matcher.sen_proto = iph->protocol; extract_ports(iph, &matcher); spin_lock(&eroute_lock); er = ipsec_findroute(&matcher); if(er) { outgoing_said = er->er_said; eroute_pid = er->er_pid; er->er_count++; er->er_lasttime = jiffies/HZ; } spin_unlock(&eroute_lock); KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) && /* ((orgdst != newdst) || (orgsrc != newsrc)) */ (orgedst != outgoing_said.dst.s_addr) && outgoing_said.dst.s_addr && er, "klips_debug:ipsec_tunnel_start_xmit: " "We are recursing here.\n"); } while(/*((orgdst != newdst) || (orgsrc != newsrc))*/ (orgedst != outgoing_said.dst.s_addr) && outgoing_said.dst.s_addr && er); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_tunnel_start_xmit: " "After recursive xforms -- head,tailroom: %d,%d\n", skb_headroom(skb), skb_tailroom(skb)); if(saved_header) { if(skb_headroom(skb) < hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", hard_header_len, skb_headroom(skb)); stats->tx_errors++; goto cleanup; } skb_push(skb, hard_header_len); for (i = 0; i < hard_header_len; i++) { skb->data[i] = saved_header[i]; } }#ifdef CONFIG_IPSEC_NAT_TRAVERSAL if (natt_type && natt_head) { struct iphdr *ipp = skb->nh.iph; struct udphdr *udp; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "encapsuling packet into UDP (NAT-Traversal)\n"); iphlen = ipp->ihl << 2; ipp->tot_len = htons(ntohs(ipp->tot_len) + natt_head); if(skb_tailroom(skb) < natt_head) { printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " "tried to skb_put %d, %d available. " "This should never happen, please report.\n", natt_head, skb_tailroom(skb)); stats->tx_errors++; goto cleanup; } skb_put(skb, natt_head); udp = (struct udphdr *)((char *)ipp + iphlen); /* move ESP hdr after UDP hdr */ memmove((void *)((char *)udp + natt_head), (void *)(udp), ntohs(ipp->tot_len) - iphlen - natt_head); /* clear UDP & Non-IKE Markers (if any) */ memset(udp, 0, natt_head); /* fill UDP with usefull informations ;-) */ udp->source = htons(natt_sport); udp->dest = htons(natt_dport); udp->len = htons(ntohs(ipp->tot_len) - iphlen); /* set protocol */ ipp->protocol = IPPROTO_UDP; /* fix IP checksum */ ipp->check = 0; ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); }#endif bypass: KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_tunnel_start_xmit: " "With hard_header, final head,tailroom: %d,%d\n", skb_headroom(skb), skb_tailroom(skb));#ifdef NET_21 /* 2.2 and 2.4 kernels */ /* new route/dst cache code from James Morris */ skb->dev = physdev; /*skb_orphan(skb);*/ if((error = ip_route_output(&rt, skb->nh.iph->daddr, pass ? 0 : skb->nh.iph->saddr, RT_TOS(skb->nh.iph->tos), physdev->iflink /* rgb: should this be 0? */))) { stats->tx_errors++; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n", error, rt->u.dst.dev->name); goto cleanup; } if(dev == rt->u.dst.dev) { ip_rt_put(rt); /* This is recursion, drop it. */ stats->tx_errors++; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", dev->name); goto cleanup; } dst_release(skb->dst); skb->dst = &rt->u.dst; stats->tx_bytes += skb->len; if(skb->len < skb->nh.raw - skb->data) { stats->tx_errors++; printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: " "tried to __skb_pull nh-data=%d, %d available. This should never happen, please report.\n", skb->nh.raw - skb->data, skb->len); goto c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?