📄 ipsec_rcv.c
字号:
struct udp_opt *tp = &us->udp; struct iphdr *ip = (struct iphdr *)skb->nh.iph; struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl); __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); __u32 *udpdata32 = (__u32 *)udpdata; irs.natt_sport = ntohs(udp->source); irs.natt_dport = ntohs(udp->dest); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", tp->esp_in_udp); KLIPS_IP_PRINT(debug_rcv, ip); if (udpdata < skb->tail) { unsigned int len = skb->tail - udpdata; if ((len==1) && (udpdata[0]==0xff)) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " /* not IPv6 compliant message */ "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr)); goto rcvleave; } else if ( (tp->encap_type == ESPINUDP_WITH_NON_IKE) && (len > (2*sizeof(__u32) + sizeof(struct esphdr))) && (udpdata32[0]==0) && (udpdata32[1]==0) ) { /* ESP Packet with Non-IKE header */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ESPinUDP pkt with Non-IKE - spi=0x%x\n", ntohl(udpdata32[2])); irs.natt_type = ESPINUDP_WITH_NON_IKE; irs.natt_len = sizeof(struct udphdr)+(2*sizeof(__u32)); } else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) && (len > sizeof(struct esphdr)) && (udpdata32[0]!=0) ) { /* ESP Packet without Non-ESP header */ irs.natt_type = ESPINUDP_WITH_NON_ESP; irs.natt_len = sizeof(struct udphdr); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ESPinUDP pkt without Non-ESP - spi=0x%x\n", ntohl(udpdata32[0])); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "IKE packet - not handled here\n"); KLIPS_DEC_USE; return -1; } } else { KLIPS_DEC_USE; return -1; }#endif /* NAT-T not supported on 2.6. */#else /* NET_26 */#ifndef UDP_OPT_IN_SOCK struct udp_opt { __u32 esp_in_udp; }; struct udp_opt *tp = (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp);#else struct udp_opt *tp = &(skb->sk->tp_pinfo.af_udp);#endif struct iphdr *ip = (struct iphdr *)skb->nh.iph; struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl); __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); __u32 *udpdata32 = (__u32 *)udpdata; irs.natt_sport = ntohs(udp->source); irs.natt_dport = ntohs(udp->dest); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", tp->esp_in_udp); KLIPS_IP_PRINT(debug_rcv, ip); if (udpdata < skb->tail) { unsigned int len = skb->tail - udpdata; if ((len==1) && (udpdata[0]==0xff)) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " /* not IPv6 compliant message */ "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr)); goto rcvleave; } else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) && (len > (2*sizeof(__u32) + sizeof(struct esphdr))) && (udpdata32[0]==0) && (udpdata32[1]==0) ) { /* ESP Packet with Non-IKE header */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ESPinUDP pkt with Non-IKE - spi=0x%x\n", ntohl(udpdata32[2])); irs.natt_type = ESPINUDP_WITH_NON_IKE; irs.natt_len = sizeof(struct udphdr)+(2*sizeof(__u32)); } else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) && (len > sizeof(struct esphdr)) && (udpdata32[0]!=0) ) { /* ESP Packet without Non-ESP header */ irs.natt_type = ESPINUDP_WITH_NON_ESP; irs.natt_len = sizeof(struct udphdr); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ESPinUDP pkt without Non-ESP - spi=0x%x\n", ntohl(udpdata32[0])); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "IKE packet - not handled here\n"); KLIPS_INC_USE; return -1; } } else { KLIPS_DEC_USE; return -1; }#endif /* NET_26 */ }#endif /* NAT_T */#ifdef IPH_is_SKB_PULLED /* In Linux 2.4.4, the IP header has been skb_pull()ed before the packet is passed to us. So we'll skb_push() to get back to it. */ if (skb->data == skb->h.raw) { skb_push(skb, skb->h.raw - skb->nh.raw); }#endif /* IPH_is_SKB_PULLED */ /* dev->hard_header_len is unreliable and should not be used */ irs.hard_header_len = skb->mac.raw ? (skb->data - skb->mac.raw) : 0; if((irs.hard_header_len < 0) || (irs.hard_header_len > skb_headroom(skb))) irs.hard_header_len = 0;#ifdef NET_21 /* if skb was cloned (most likely due to a packet sniffer such as tcpdump being momentarily attached to the interface), make a copy of our own to modify */ if(skb_cloned(skb)) { /* include any mac header while copying.. */ if(skb_headroom(skb) < irs.hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_rcv: " "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", irs.hard_header_len, skb_headroom(skb)); goto rcvleave; } skb_push(skb, irs.hard_header_len); if#ifdef SKB_COW_NEW (skb_cow(skb, skb_headroom(skb)) != 0)#else /* SKB_COW_NEW */ ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)#endif /* SKB_COW_NEW */ { goto rcvleave; } if(skb->len < irs.hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_rcv: " "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", irs.hard_header_len, skb->len); goto rcvleave; } skb_pull(skb, irs.hard_header_len); }#endif /* NET_21 */#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)) { if (skb_linearize(skb, GFP_ATOMIC) != 0) { goto rcvleave; } }#endif /* IP_FRAGMENT_LINEARIZE */#ifdef CONFIG_IPSEC_NAT_TRAVERSAL if (irs.natt_len) { /** * Now, we are sure packet is ESPinUDP. 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 = (struct iphdr *)skb->data; 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; } memmove(skb->data + irs.natt_len, skb->data, irs.iphlen); skb_pull(skb, irs.natt_len); /* update nh.iph */ ipp = skb->nh.iph = (struct iphdr *)skb->data; /* modify protocol */ ipp->protocol = IPPROTO_ESP; skb->sk = NULL; KLIPS_IP_PRINT(debug_rcv, skb->nh.iph); }#endif ipp = skb->nh.iph; 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); /* begin decapsulating loop here */ /* The spinlock is to prevent any other process from accessing or deleting the ipsec_sa hash table or any of the ipsec_sa s while we are using and updating them. This is not optimal, but was relatively straightforward at the time. A better way to do it has been planned for more than a year, to lock the hash table and put reference counts on each ipsec_sa instead. This is not likely to happen in KLIPS1 unless a volunteer contributes it, but will be designed into KLIPS2. */ spin_lock(&tdb_lock); /* 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; do { int decap_stat; struct xform_functions *proto_funcs; switch(irs.ipp->protocol) { case IPPROTO_ESP: proto_funcs = esp_xform_funcs; break; #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: proto_funcs = ah_xform_funcs; break;#endif /* !CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: proto_funcs = ipcomp_xform_funcs; break;#endif /* !CONFIG_KLIPS_IPCOMP */ default: if(irs.stats) { irs.stats->rx_errors++; } decap_stat = IPSEC_RCV_BADPROTO; goto rcvleave; } decap_stat = ipsec_rcv_decap_once(&irs, proto_funcs); if(decap_stat != IPSEC_RCV_OK) { spin_unlock(&tdb_lock); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: decap_once failed: %d\n", decap_stat); goto rcvleave; } /* end decapsulation loop here */ } while( (irs.ipp->protocol == IPPROTO_ESP ) || (irs.ipp->protocol == IPPROTO_AH )#ifdef CONFIG_KLIPS_IPCOMP || (irs.ipp->protocol == IPPROTO_COMP)#endif /* CONFIG_KLIPS_IPCOMP */ ); /* set up for decap loop */ ipp =irs.ipp; ipsp =irs.ipsp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -