📄 ipsec_xmit.c
字号:
, "klips_xmit: invalid nat-t type %d" , ixs->natt_type); bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE; goto cleanup; break; } ixs->tailroom += ixs->natt_head; }#endif break;#endif /* !CONFIG_KLIPS_ESP */#ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: ixs->headroom += sizeof(struct iphdr); break;#endif /* !CONFIG_KLIPS_IPIP */ case IPPROTO_COMP:#ifdef CONFIG_KLIPS_IPCOMP /* We can't predict how much the packet will shrink without doing the actual compression. We could do it here, if we were the first encapsulation in the chain. That might save us a skb_copy_expand, since we might fit into the existing skb then. However, this would be a bit unclean (and this hack has bit us once), so we better not do it. After all, the skb_copy_expand is cheap in comparison to the actual compression. At least we know the packet will not grow. */ break;#endif /* CONFIG_KLIPS_IPCOMP */ default: ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_BADPROTO; goto cleanup; } ixs->ipsp = ixs->ipsp->ips_onext; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "Required head,tailroom: %d,%d\n", ixs->headroom, ixs->tailroom); ixs->max_headroom += ixs->headroom; ixs->max_tailroom += ixs->tailroom; ixs->pyldsz += (ixs->headroom + ixs->tailroom); } ixs->ipsp = ixs->ipsq; /* restore the head of the ipsec_sa chain */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb), ixs->max_headroom, ixs->max_tailroom); ixs->tot_headroom += ixs->max_headroom; ixs->tot_tailroom += ixs->max_tailroom; ixs->mtudiff = ixs->cur_mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n", ixs->cur_mtu, ixs->physmtu, ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len)); if(ixs->mtudiff > 0) { int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_info:ipsec_xmit_encap_bundle: " "dev %s mtu of %d decreased by %d to %d\n", ixs->dev ? ixs->dev->name : "ifX", ixs->cur_mtu, ixs->cur_mtu - newmtu, newmtu); ixs->cur_mtu = newmtu; /* this would seem to adjust the MTU of the route as well */#if 0 ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */#endif /* 0 */ } /* If the sender is doing PMTU discovery, and the packet doesn't fit within ixs->prv->mtu, notify him (unless it was an ICMP packet, or it was not the zero-offset packet) and send it anyways. Note: buggy firewall configuration may prevent the ICMP packet from getting back. */ if(sysctl_ipsec_icmp && ixs->cur_mtu < ntohs(ixs->iph->tot_len) && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) { int notify = ixs->iph->protocol != IPPROTO_ICMP && (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0; #ifdef IPSEC_obey_DF KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "fragmentation needed and DF set; %sdropping packet\n", notify ? "sending ICMP and " : ""); if (notify) ICMP_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, ixs->cur_mtu, ixs->physdev); ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_CANNOTFRAG; goto cleanup;#else /* IPSEC_obey_DF */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "fragmentation needed and DF set; %spassing packet\n", notify ? "sending ICMP and " : ""); if (notify) ICMP_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, ixs->cur_mtu, ixs->physdev);#endif /* IPSEC_obey_DF */ } #ifdef MSS_HACK /* * If this is a transport mode TCP packet with * SYN set, determine an effective MSS based on * AH/ESP overheads determined above. */ if (ixs->iph->protocol == IPPROTO_TCP && ixs->outgoing_said.proto != IPPROTO_IPIP) { struct tcphdr *tcph = ixs->skb->h.th; if (tcph->syn && !tcph->ack) { if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->cur_mtu)) { printk(KERN_WARNING "klips_warning:ipsec_xmit_encap_bundle: " "ipsec_adjust_mss() failed\n"); ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_MSSERR; goto cleanup; } } }#endif /* MSS_HACK */#ifdef CONFIG_IPSEC_NAT_TRAVERSAL if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) { /** * NAT-Traversal and Transport Mode: * we need to correct TCP/UDP checksum * * If we've got NAT-OA, we can fix checksum without recalculation. * If we don't we can zero udp checksum. */ __u32 natt_oa = ixs->ipsp->ips_natt_oa ? ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0; __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph; __u16 data_len = pkt_len - (ixs->iph->ihl << 2); switch (ixs->iph->protocol) { case IPPROTO_TCP: if (data_len >= sizeof(struct tcphdr)) { struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); if (natt_oa) { __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: " "fix TCP checksum using NAT-OA\n"); tcp->check = csum_fold( csum_partial((unsigned char *)buff, sizeof(buff), tcp->check^0xffff)); } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: do not recalc TCP checksum\n"); } } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: can't fix TCP checksum\n"); } break; case IPPROTO_UDP: if (data_len >= sizeof(struct udphdr)) { struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl); if (udp->check == 0) { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: UDP checksum already 0\n"); } else if (natt_oa) { __u32 buff[2] = { ~ixs->iph->daddr, natt_oa }; KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: " "fix UDP checksum using NAT-OA\n"); udp->check = csum_fold( csum_partial((unsigned char *)buff, sizeof(buff), udp->check^0xffff)); } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: zero UDP checksum\n"); udp->check = 0; } } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: can't fix UDP checksum\n"); } break; default: KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: " "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n"); break; } }#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */ if(!ixs->hard_header_stripped && ixs->hard_header_len>0) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "allocating %d bytes for hardheader.\n", ixs->hard_header_len); if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: " "Failed, tried to allocate %d bytes for temp hard_header.\n", ixs->hard_header_len); ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ERRMEMALLOC; goto cleanup; } { int i; for (i = 0; i < ixs->hard_header_len; i++) { ixs->saved_header[i] = ixs->skb->data[i]; } } if(ixs->skb->len < ixs->hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: " "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", ixs->hard_header_len, (int)(ixs->skb->len)); ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR; goto cleanup; } skb_pull(ixs->skb, ixs->hard_header_len); ixs->hard_header_stripped = 1; /* ixs->iph = (struct iphdr *) (ixs->skb->data); */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "head,tailroom: %d,%d after hard_header stripped.\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph); } else { KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "hard header already stripped.\n"); } ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15; if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && (skb_tailroom(ixs->skb) >= ixs->max_tailroom)#ifndef NET_21 && ixs->skb->free#endif /* !NET_21 */ ) { KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "data fits in existing skb\n"); } else { struct sk_buff* tskb; if(!ixs->oskb) { ixs->oskb = ixs->skb; } tskb = skb_copy_expand(ixs->skb, /* The need for 2 * link layer length here remains unexplained...RGB */ ixs->max_headroom + 2 * ixs->ll_headroom, ixs->max_tailroom, GFP_ATOMIC); if(tskb && ixs->skb->sk) { skb_set_owner_w(tskb, ixs->skb->sk); } if(ixs->skb != ixs->oskb) { ipsec_kfree_skb(ixs->skb); } ixs->skb = tskb; if (!ixs->skb) { printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: " "Failed, tried to allocate %d head and %d tailroom\n", ixs->max_headroom, ixs->max_tailroom); ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ERRSKBALLOC; goto cleanup; } KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_bundle: " "head,tailroom: %d,%d after allocation\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); } if(debug_tunnel & DB_TN_ENCAP) { ipsec_print_ip(ixs->iph); } /* * Apply grouped transforms to packet */ while (ixs->ipsp) { enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK; encap_stat = ipsec_xmit_encap_once(ixs); if(debug_tunnel & DB_TN_ENCAP) { ipsec_print_ip(ixs->iph); } if(encap_stat != IPSEC_XMIT_OK) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n", encap_stat); bundle_stat = IPSEC_XMIT_ENCAPFAIL; goto cleanup; } } /* we are done with this SA */ ipsec_sa_put(ixs->ipsp); /* end encapsulation loop here XXX */ cleanup: spin_unlock(&tdb_lock); return bundle_stat;}/* * $Log: ipsec_xmit.c,v $ * Revision 1.20.2.6 2006/07/07 22:09:49 paul * From: Bart Trojanowski <bart@xelerance.com> * Removing a left over '#else' that split another '#if/#endif' block in two. * * Revision 1.20.2.5 2006/07/07 15:43:17 paul * From: Bart Trojanowski <bart@xelerance.com> * improved protocol detection in ipsec_print_ip() -- a debug aid. * * Revision 1.20.2.4 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.20.2.3 2005/11/29 21:52:57 ken * Fix for #518 MTU issues * * Revision 1.20.2.2 2005/11/27 21:41:03 paul * Pull down TTL fixes from head. this fixes "Unknown symbol sysctl_ip_default_ttl"in for klips as module. * * Revision 1.20.2.1 2005/08/27 23:40:00 paul * recommited HAVE_SOCK_SECURITY fixes for linux 2.6.13 * * Revision 1.20 2005/07/12 15:39:27 paul * include asm/uaccess.h for VERIFY_WRITE * * Revision 1.19 2005/05/24 01:02:35 mcr * some refactoring/simplification of situation where alg * is not found. * * Revision 1.18 2005/05/23 23:52:33 mcr * adjust comments, add additional debugging. * * Revision 1.17 2005/05/23 22:57:23 mcr * removed explicit 3DES support. * * Revision 1.16 2005/05/21 03:29:15 mcr * fixed warning about unused zeroes if AH is off. * * Revision 1.15 2005/05/20 16:47:59 mcr * include asm/checksum.h to get ip_fast_csum macro. * * Revision 1.14 2005/05/11 01:43:03 mcr * removed "poor-man"s OOP in favour of proper C structures. * * Revision 1.13 2005/04/29 05:10:22 mcr * removed from extraenous includes to make unit testing easier. * * Revision 1.12 2005/04/15 01:28:34 mcr * use ipsec_dmp_block. * * Revision 1.11 2005/01/26 00:50:35 mcr * adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT, * and make sure that NAT_TRAVERSAL is set as well to match * userspace compiles of code. * * Revision 1.10 2004/09/13 17:55:21 ken * MD5* -> osMD5* * * Revision 1.9 2004/07/10 19:11:18 mcr * CONFIG_IPSEC -> CONFIG_KLIPS. * * Revision 1.8 2004/04/06 02:49:26 mcr * pullup of algo code from alg-branch. * * Revision 1.7 2004/02/03 03:13:41 mcr * mark invalid encapsulation states. * * Revision 1.6.2.1 2003/12/22 15:25:52 jjo * Merged algo-0.8.1-rc11-test1 into alg-branch * * Revision 1.6 2003/12/10 01:14:27 mcr * NAT-traversal patches to KLIPS. * * Revision 1.5 2003/10/31 02:27:55 mcr * pulled up port-selector patches and sa_id elimination. * * Revision 1.4.4.2 2003/10/29 01:37:39 mcr * when creating %hold from %trap, only make the %hold as * specific as the %trap was - so if the protocol and ports * were wildcards, then the %hold will be too. * * Revision 1.4.4.1 2003/09/21 13:59:56 mcr * pre-liminary X.509 patch - does not yet pass tests. * * Revision 1.4 2003/06/20 02:28:10 mcr * misstype of variable name, not detected by module build. * * Revision 1.3 2003/06/20 01:42:21 mcr * added counters to measure how many ACQUIREs we send to pluto, * and how many are successfully sent. * * Revision 1.2 2003/04/03 17:38:35 rgb * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}. * Normalised coding style. * Simplified logic and reduced duplication of code. * * Revision 1.1 2003/02/12 19:31:23 rgb * Refactored from ipsec_tunnel.c * * Local Variables: * c-file-style: "linux" * End: * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -