enum ipsec_rcv_value ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) { unsigned int flags = 0; struct ipsec_sa *ipsp = irs->ipsp; struct sk_buff *skb; skb = irs->skb; ipsec_xmit_dmp("ipcomp", skb_transport_header(skb), skb->len); if (ipsp == NULL) return IPSEC_RCV_SAIDNOTFOUND; if (sysctl_ipsec_inbound_policy_check && ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != (ntohl(irs->said.spi) & 0x0000ffff)) && (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ ))) { char sa2[SATOT_BUF]; size_t sa_len2 = 0; sa_len2 = KLIPS_SATOT(debug_rcv, &ipsp->ips_said, 0, sa2, sizeof(sa2)); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", irs->sa_len ? irs->sa : " (error)", sa_len2 ? sa2 : " (error)", ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), (__u32)ntohl(irs->said.spi), (__u32)ntohl((ipsp->ips_said.spi)), (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff)); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_SAIDNOTFOUND; } if (lsw_ip_hdr_version(irs) == 6) ipsp->ips_comp_ratio_cbytes += ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else ipsp->ips_comp_ratio_cbytes += ntohs(lsw_ip4_hdr(irs)->tot_len); irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; #ifdef CONFIG_KLIPS_OCF if (irs->ipsp->ocf_in_use) return ipsec_ocf_rcv(irs); #endif skb = skb_decompress(skb, ipsp, &flags); if (!skb || flags) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "skb_decompress() returned error flags=%x, dropped.\n", flags); if (irs->stats) { if (flags) irs->stats->rx_errors++; else irs->stats->rx_dropped++; } return IPSEC_RCV_IPCOMPFAILED; } /* make sure we update the pointer */ irs->skb = skb; irs->iph = (void *) ip_hdr(skb); if (lsw_ip_hdr_version(irs) == 6) ipsp->ips_comp_ratio_dbytes += ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else ipsp->ips_comp_ratio_dbytes += ntohs(lsw_ip4_hdr(irs)->tot_len); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", irs->sa_len ? irs->sa : " (error)", (__u32)ntohl(irs->said.spi), ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, irs->next_header); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->iph); return IPSEC_RCV_OK; }
enum ipsec_rcv_value ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) { unsigned int flags = 0; struct ipsec_sa *ipsp = irs->ipsp; struct sk_buff *skb; skb=irs->skb; ipsec_xmit_dmp("ipcomp", skb->data, skb->len); if(ipsp == NULL) { return IPSEC_RCV_SAIDNOTFOUND; } #if 0 /* we want to check that this wasn't the first SA on the list, because * we don't support bare IPCOMP, for unexplained reasons. MCR */ if (ipsp->ips_onext != NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n", irs->sa_len ? irs->sa : " (error)"); if(irs->stats) { irs->stats->rx_dropped++; } return IPSEC_RCV_IPCOMPALONE; } #endif if(sysctl_ipsec_inbound_policy_check && ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != ntohl(irs->said.spi)) && (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ ))) { char sa2[SATOT_BUF]; size_t sa_len2 = 0; sa_len2 = satot(&ipsp->ips_said, 0, sa2, sizeof(sa2)); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", irs->sa_len ? irs->sa : " (error)", ipsp != NULL ? (sa_len2 ? sa2 : " (error)") : "NULL", ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), (__u32)ntohl(irs->said.spi), ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0); if(irs->stats) { irs->stats->rx_dropped++; } return IPSEC_RCV_SAIDNOTFOUND; } ipsp->ips_comp_ratio_cbytes += ntohs(irs->ipp->tot_len); irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; skb = skb_decompress(skb, ipsp, &flags); if (!skb || flags) { spin_unlock(&tdb_lock); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "skb_decompress() returned error flags=%x, dropped.\n", flags); if (irs->stats) { if (flags) irs->stats->rx_errors++; else irs->stats->rx_dropped++; } return IPSEC_RCV_IPCOMPFAILED; } /* make sure we update the pointer */ irs->skb = skb; #ifdef NET_21 irs->ipp = skb->nh.iph; #else /* NET_21 */ irs->ipp = skb->ip_hdr; #endif /* NET_21 */ ipsp->ips_comp_ratio_dbytes += ntohs(irs->ipp->tot_len); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", irs->sa_len ? irs->sa : " (error)", (__u32)ntohl(irs->said.spi), ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, irs->next_header); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->ipp); return IPSEC_RCV_OK; }