📄 ipsec_rcv.c
字号:
return skb;}#endifintipsec_rcv(struct sk_buff *skb#ifndef PROTO_HANDLER_SINGLE_PARM unsigned short xlen#endif /* PROTO_HANDLER_SINGLE_PARM */ ){#ifdef CONFIG_KLIPS_DEBUG struct net_device *dev = skb->dev;#endif /* CONFIG_KLIPS_DEBUG */ unsigned char protoc; struct net_device_stats *stats = NULL; /* This device's statistics */ struct net_device *ipsecdev = NULL, *prvdev; struct ipsecpriv *prv; struct ipsec_rcv_state nirs, *irs = &nirs; struct iphdr *ipp; char name[9]; int i; /* Don't unlink in the middle of a turnaround */ KLIPS_INC_USE; memset(&nirs, 0, sizeof(struct ipsec_rcv_state)); if (skb == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "NULL skb passed in.\n"); goto rcvleave; } if (skb->data == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "NULL skb->data passed in, packet is bogus, dropping.\n"); goto rcvleave; }#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) { /* NET_26 NAT-T is handled by seperate function */ struct sk_buff *nskb; int udp_decap_ret = 0; nskb = ipsec_rcv_natt_decap(skb, irs, &udp_decap_ret); if(nskb == NULL) { /* return with non-zero, because UDP.c code * need to send it upstream. */ if(skb && udp_decap_ret == 0) { ipsec_kfree_skb(skb); } KLIPS_DEC_USE; return(udp_decap_ret); } skb = nskb; }#endif /* NAT_T */ /* dev->hard_header_len is unreliable and should not be used */ irs->hard_header_len = skb->mac.raw ? (skb->nh.raw - skb->mac.raw) : 0; if((irs->hard_header_len < 0) || (irs->hard_header_len > skb_headroom(skb))) irs->hard_header_len = 0; skb = ipsec_rcv_unclone(skb, irs); if(skb == NULL) { goto rcvleave; }#if IP_FRAGMENT_LINEARIZE /* In Linux 2.4.4, we may have to reassemble fragments. They are not assembled automatically to save TCP from having to copy twice. */ if (skb_is_nonlinear(skb)) {#ifdef HAVE_NEW_SKB_LINEARIZE if (skb_linearize_cow(skb) != 0)#else if (skb_linearize(skb, GFP_ATOMIC) != 0) #endif { goto rcvleave; } }#endif /* IP_FRAGMENT_LINEARIZE */#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) if (irs->natt_len) { /** * Now, we are sure packet is ESPinUDP, and we have a private * copy that has been linearized, remove natt_len bytes * from packet and modify protocol to ESP. */ if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph) && ((unsigned char *)skb->nh.iph > (unsigned char *)skb->head)) { unsigned int _len = (unsigned char *)skb->data - (unsigned char *)skb->nh.iph; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n", _len); skb_push(skb, _len); } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "removing %d bytes from ESPinUDP packet\n", irs->natt_len); ipp = skb->nh.iph; irs->iphlen = ipp->ihl << 2; ipp->tot_len = htons(ntohs(ipp->tot_len) - irs->natt_len); if (skb->len < irs->iphlen + irs->natt_len) { printk(KERN_WARNING "klips_error:ipsec_rcv: " "ESPinUDP packet is too small (%d < %d+%d). " "This should never happen, please report.\n", (int)(skb->len), irs->iphlen, irs->natt_len); goto rcvleave; } /* advance payload pointer to point past the UDP header */ skb->h.raw = skb->h.raw + irs->natt_len; /* modify protocol */ ipp->protocol = IPPROTO_ESP; skb->sk = NULL; KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); }#endif ipp = skb->nh.iph; { struct in_addr ipsaddr; struct in_addr ipdaddr; ipsaddr.s_addr = ipp->saddr; addrtoa(ipsaddr, 0, irs->ipsaddr_txt , sizeof(irs->ipsaddr_txt)); ipdaddr.s_addr = ipp->daddr; addrtoa(ipdaddr, 0, irs->ipdaddr_txt , sizeof(irs->ipdaddr_txt)); } irs->iphlen = ipp->ihl << 2; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "<<< Info -- "); KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ", skb->dev->name ? skb->dev->name : "NULL"); KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ", dev->name ? dev->name : "NULL"); KLIPS_PRINTMORE(debug_rcv, "\n"); KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)), "klips_debug:ipsec_rcv: " "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n", skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL", dev ? (dev->name ? dev->name : "NULL") : "NULL"); protoc = ipp->protocol;#ifndef NET_21 if((!protocol) || (protocol->protocol != protoc)) { KLIPS_PRINT(debug_rcv & DB_RX_IPSA, "klips_debug:ipsec_rcv: " "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n"); }#endif /* !NET_21 */ if( (protoc != IPPROTO_AH) &&#ifdef CONFIG_KLIPS_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER (protoc != IPPROTO_COMP) &&#endif /* CONFIG_KLIPS_IPCOMP */ (protoc != IPPROTO_ESP) ) { KLIPS_PRINT(debug_rcv & DB_RX_IPSA, "klips_debug:ipsec_rcv: Why the hell is someone " "passing me a non-ipsec protocol = %d packet? -- dropped.\n", protoc); goto rcvleave; } if(skb->dev) { for(i = 0; i < IPSEC_NUM_IF; i++) { sprintf(name, IPSEC_DEV_FORMAT, i); if(!strcmp(name, skb->dev->name)) { prv = (struct ipsecpriv *)(skb->dev->priv); if(prv) { stats = (struct net_device_stats *) &(prv->mystats); } ipsecdev = skb->dev; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n"); break; } if((ipsecdev = __ipsec_dev_get(name)) == NULL) { KLIPS_PRINT(debug_rcv, "klips_error:ipsec_rcv: " "device %s does not exist\n", name); } prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL; prvdev = prv ? (struct net_device *)(prv->dev) : NULL;#if 0 KLIPS_PRINT(debug_rcv && prvdev, "klips_debug:ipsec_rcv: " "physical device for device %s is %s\n", name, prvdev->name);#endif if(prvdev && skb->dev && !strcmp(prvdev->name, skb->dev->name)) { stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL; skb->dev = ipsecdev; KLIPS_PRINT(debug_rcv && prvdev, "klips_debug:ipsec_rcv: " "assigning packet ownership to virtual device %s from physical device %s.\n", name, prvdev->name); if(stats) { stats->rx_packets++; } break; } } } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "device supplied with skb is NULL\n"); } if(stats == NULL) { KLIPS_PRINT((debug_rcv), "klips_error:ipsec_rcv: " "packet received from physical I/F (%s) not connected to ipsec I/F. Cannot record stats. May not have SA for decoding. Is IPSEC traffic expected on this I/F? Check routing.\n", skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL"); } KLIPS_IP_PRINT(debug_rcv, ipp); /* set up for decap loop */ irs->stats= stats; irs->ipp = ipp; irs->ipsp = NULL; irs->ilen = 0; irs->authlen=0; irs->authfuncs=NULL; irs->skb = skb; ipsec_rcv_decap(irs); KLIPS_DEC_USE; return(0); rcvleave: if(skb) { ipsec_kfree_skb(skb); } KLIPS_DEC_USE; return(0);}#ifdef NET_26/* * this entry point is not a protocol entry point, so the entry * is a bit different. * * skb->iph->tot_len has been byte-swapped, and reduced by the size of * the IP header (and options). * * skb->h.raw has been pulled up the ESP header. * * skb->iph->protocol = 50 IPPROTO_ESP; * */int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type){ struct ipsec_rcv_state nirs, *irs = &nirs; struct iphdr *ipp; /* Don't unlink in the middle of a turnaround */ KLIPS_INC_USE; memset(irs, 0, sizeof(*irs)); /* XXX fudge it so that all nat-t stuff comes from ipsec0 */ /* eventually, the SA itself will determine which device * it comes from */ { skb->dev = ipsec_get_device(0); } /* set up for decap loop */ irs->hard_header_len = skb->dev->hard_header_len; skb = ipsec_rcv_unclone(skb, irs);#if IP_FRAGMENT_LINEARIZE /* In Linux 2.4.4, we may have to reassemble fragments. They are not assembled automatically to save TCP from having to copy twice. */ if (skb_is_nonlinear(skb)) {#ifdef HAVE_NEW_SKB_LINEARIZE if (skb_linearize_cow(skb) != 0) #else if (skb_linearize(skb, GFP_ATOMIC) != 0) #endif { goto rcvleave; } }#endif /* IP_FRAGMENT_LINEARIZE */ ipp = skb->nh.iph; { struct in_addr ipsaddr; struct in_addr ipdaddr; ipsaddr.s_addr = ipp->saddr; addrtoa(ipsaddr, 0, irs->ipsaddr_txt , sizeof(irs->ipsaddr_txt)); ipdaddr.s_addr = ipp->daddr; addrtoa(ipdaddr, 0, irs->ipdaddr_txt , sizeof(irs->ipdaddr_txt)); } irs->iphlen = ipp->ihl << 2; KLIPS_IP_PRINT(debug_rcv, ipp); irs->stats= NULL; irs->ipp = ipp; irs->ipsp = NULL; irs->ilen = 0; irs->authlen=0; irs->authfuncs=NULL; irs->skb = skb;#ifdef CONFIG_IPSEC_NAT_TRAVERSAL switch(encap_type) { case UDP_ENCAP_ESPINUDP: irs->natt_type = ESPINUDP_WITH_NON_ESP; break; case UDP_ENCAP_ESPINUDP_NON_IKE: irs->natt_type = ESPINUDP_WITH_NON_IKE; break; default: if(printk_ratelimit()) { printk(KERN_INFO "KLIPS received unknown UDP-ESP encap type %u\n", encap_type); } return -1; }#endif ipsec_rcv_decap(irs); KLIPS_DEC_USE; return 0;rcvleave: if(skb) { ipsec_kfree_skb(skb); } KLIPS_DEC_USE; return 0;}#endif/* * $Log: ipsec_rcv.c,v $ * Revision 1.171.2.9 2006/07/30 02:09:33 paul * Author: Bart Trojanowski <bart@xelerance.com> * This fixes a NATT+ESP bug in rcv path. * * We only want to test NATT policy on the ESP packet. Doing so on the * bundled SA breaks because the next layer does not know anything about * NATT. * * Fix just puts an if(proto == IPPROTO_ESP) around the NATT policy check. * * Revision 1.171.2.8 2006/07/29 05:03:04 paul * Added check for new version of skb_linearize that only takes 1 argument, * for 2.6.18+ kernels. * * Revision 1.171.2.7 2006/04/20 16:33:07 mcr * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it. * Fix in-kernel module compilation. Sub-makefiles do not work. * * Revision 1.171.2.6 2005/12/07 06:07:04 paul * comment out KLIPS_DEC_USE in ipsec_rcv_decap. Likely an artifact from * refactoring. http://bugs.xelerance.com/view.php?id=454 * * Revision 1.171.2.5 2005/10/21 02:22:29 mcr * pull up of another try at 2.4.x kernel fix * * Revision 1.171.2.4 2005/10/21 01:39:56 mcr * nat-t fix is 2.4/2.6 specific * * Revision 1.178 2005/10/21 02:19:34 mcr * on 2.4 systems, we have to fix up the length as well. * * Revision 1.177 2005/10/21 00:18:31 mcr * nat-t fix is 2.4 specific. * * Revision 1.176 2005/10/20 21:06:11 mcr * possible fix for nat-t problem on 2.4 kernels. * * Revision 1.175 2005/10/13 02:49:24 mcr * tested UDP-encapsulated ESP packets that were not actually ESP, * (but IKE) were being eaten. * * Revision 1.174 2005/10/13 01:25:22 mcr * UDP-encapsulated ESP packets that were not actually ESP, * (but IKE) were being eaten. * * Revision 1.173 2005/08/31 23:26:11 mcr * fixes for 2.6.13 * * Revision 1.172 2005/08/05 08:44:54 mcr * ipsec_kern24.h (compat code for 2.4) must be include * explicitely now. * * Revision 1.171 2005/07/08 23:56:06 ken * #ifdef * * Revision 1.170 2005/07/08 23:50:05 ken * Don't attempt to decapsulate if NAT-T isn't available in the code * * Revision 1.169 2005/06/06 00:27:31 mcr * fix for making tcpdump (packet capture) work correctly for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -