📄 ipsec_tunnel.c
字号:
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; //是64#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; } /* end encapsulation loop here XXX */ spin_unlock(&tdb_lock); //此地址就是IPIP的地址 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"); //非bundle的大循环是为了处理存在端点完全相同的不同策略的情况(管理员误配?) //是为了容错 } 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; } //把MAC头加回去 skb_push(skb, hard_header_len); for (i = 0; i < hard_header_len; i++) { skb->data[i] = saved_header[i]; } } 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 cleanup; } //???????????????????????????????????????? __skb_pull(skb, skb->nh.raw - skb->data);//ipip.c要求的#ifdef SKB_RESET_NFCT nf_conntrack_put(skb->nfct); skb->nfct = NULL;#ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0;#endif /* CONFIG_NETFILTER_DEBUG */#endif /* SKB_RESET_NFCT */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "...done, calling ip_send() on device:%s\n", skb->dev ? skb->dev->name : "NULL"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, skb->nh.iph);#ifdef NETDEV_23 /* 2.4 kernels */ { int err; err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ipsec_tunnel_xmit2); if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { if(net_ratelimit()) printk(KERN_ERR "klips_error:ipsec_tunnel_start_xmit: " "ip_send() failed, err=%d\n", -err); stats->tx_errors++; stats->tx_aborted_errors++; skb = NULL; goto cleanup; } }#else /* NETDEV_23 */ /* 2.2 kernels */ ip_send(skb);#endif /* NETDEV_23 */#else /* NET_21 */ /* 2.0 kernels */ skb->arp = 1; /* ISDN/ASYNC PPP from Matjaz Godec. */ /* skb->protocol = htons(ETH_P_IP); */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "...done, calling dev_queue_xmit() or ip_fragment().\n"); IP_SEND(skb, physdev);#endif /* NET_21 */ stats->tx_packets++; skb = NULL; cleanup:#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) netif_wake_queue(dev);#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ dev->tbusy = 0;#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ if(saved_header) { kfree(saved_header); } if(skb) { dev_kfree_skb(skb, FREE_WRITE); } if(oskb) { dev_kfree_skb(oskb, FREE_WRITE); } if (tdb.tdb_ident_s.data) { kfree(tdb.tdb_ident_s.data); } if (tdb.tdb_ident_d.data) { kfree(tdb.tdb_ident_d.data); } return 0;}DEBUG_NO_STATIC struct net_device_stats *ipsec_tunnel_get_stats(struct device *dev){ return &(((struct ipsecpriv *)(dev->priv))->mystats);}/* * Revectored calls. * For each of these calls, a field exists in our private structure. */DEBUG_NO_STATIC intipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len){ struct ipsecpriv *prv = dev->priv; struct device *tmp; int ret; struct net_device_stats *stats; /* This device's statistics */ if(skb == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no skb...\n"); return -ENODATA; } if(dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no device...\n"); return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "skb->dev=%s dev=%s.\n", skb->dev ? skb->dev->name : "NULL", dev->name); if(prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no private space associated with dev=%s\n", dev->name ? dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if(prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no physical device associated with dev=%s\n", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } /* check if we have to send a IPv6 packet. It might be a Router Solicitation, where the building of the packet happens in reverse order: 1. ll hdr, 2. IPv6 hdr, 3. ICMPv6 hdr -> skb->nh.raw is still uninitialized when this function is called!! If this is no IPv6 packet, we can print debugging messages, otherwise we skip all debugging messages and just build the ll header */ if(type != ETH_P_IPV6) { /* execute this only, if we don't have to build the header for a IPv6 packet */ if(!prv->hard_header) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "physical device has been detached, packet dropped 0x%p->0x%p len=%d type=%d dev=%s->NULL ", saddr, daddr, len, type, dev->name);#ifdef NET_21 KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(skb->nh.iph->saddr), (__u32)ntohl(skb->nh.iph->daddr) );#else /* NET_21 */ KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(skb->ip_hdr->saddr), (__u32)ntohl(skb->ip_hdr->daddr) );#endif /* NET_21 */ stats->tx_dropped++; return -ENODEV; } #define da ((struct device *)(prv->dev))->dev_addr KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "Revectored 0x%p->0x%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -