]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ipcomp_input.c
   1 /*      $FreeBSD: src/sys/netinet6/ipcomp_input.c,v 1.1.2.2 2001/07/03 11:01:54 ume Exp $       */ 
   2 /*      $KAME: ipcomp_input.c,v 1.25 2001/03/01 09:12:09 itojun Exp $   */ 
   5  * Copyright (C) 1999 WIDE Project. 
   8  * Redistribution and use in source and binary forms, with or without 
   9  * modification, are permitted provided that the following conditions 
  11  * 1. Redistributions of source code must retain the above copyright 
  12  *    notice, this list of conditions and the following disclaimer. 
  13  * 2. Redistributions in binary form must reproduce the above copyright 
  14  *    notice, this list of conditions and the following disclaimer in the 
  15  *    documentation and/or other materials provided with the distribution. 
  16  * 3. Neither the name of the project nor the names of its contributors 
  17  *    may be used to endorse or promote products derived from this software 
  18  *    without specific prior written permission. 
  20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  34  * RFC2393 IP payload compression protocol (IPComp). 
  38 #include <sys/param.h> 
  39 #include <sys/systm.h> 
  40 #include <sys/malloc.h> 
  42 #include <sys/domain.h> 
  43 #include <sys/protosw.h> 
  44 #include <sys/socket.h> 
  45 #include <sys/errno.h> 
  47 #include <sys/kernel.h> 
  48 #include <sys/syslog.h> 
  51 #include <net/route.h> 
  53 #include <kern/cpu_number.h> 
  54 #include <kern/locks.h> 
  56 #include <netinet/in.h> 
  57 #include <netinet/in_systm.h> 
  58 #include <netinet/in_var.h> 
  59 #include <netinet/ip.h> 
  60 #include <netinet/ip_var.h> 
  61 #include <netinet/ip_ecn.h> 
  64 #include <netinet/ip6.h> 
  65 #include <netinet6/ip6_var.h> 
  67 #include <netinet6/ipcomp.h> 
  69 #include <netinet6/ipcomp6.h> 
  72 #include <netinet6/ipsec.h> 
  74 #include <netinet6/ipsec6.h> 
  76 #include <netkey/key.h> 
  77 #include <netkey/keydb.h> 
  79 #include <net/net_osdep.h> 
  83 extern lck_mtx_t 
*sadb_mutex
; 
  85 ipcomp4_input(struct mbuf 
*m
, int off
) 
  89         struct ipcomp 
*ipcomp
; 
  90         const struct ipcomp_algorithm 
*algo
; 
  91         u_int16_t cpi
;  /* host order */ 
  96         struct secasvar 
*sav 
= NULL
; 
  98         lck_mtx_lock(sadb_mutex
); 
 100         if (m
->m_pkthdr
.len 
< off 
+ sizeof(struct ipcomp
)) { 
 101                 ipseclog((LOG_DEBUG
, "IPv4 IPComp input: assumption failed " 
 102                     "(packet too short)\n")); 
 103                 ipsecstat
.in_inval
++; 
 107         md 
= m_pulldown(m
, off
, sizeof(*ipcomp
), NULL
); 
 109                 m 
= NULL
;       /*already freed*/ 
 110                 ipseclog((LOG_DEBUG
, "IPv4 IPComp input: assumption failed " 
 111                     "(pulldown failure)\n")); 
 112                 ipsecstat
.in_inval
++; 
 115         ipcomp 
= mtod(md
, struct ipcomp 
*); 
 116         ip 
= mtod(m
, struct ip 
*); 
 117         nxt 
= ipcomp
->comp_nxt
; 
 119         hlen 
= IP_VHL_HL(ip
->ip_vhl
) << 2; 
 121         hlen 
= ip
->ip_hl 
<< 2; 
 124         cpi 
= ntohs(ipcomp
->comp_cpi
); 
 126         if (cpi 
>= IPCOMP_CPI_NEGOTIATE_MIN
) { 
 127                 sav 
= key_allocsa(AF_INET
, (caddr_t
)&ip
->ip_src
, 
 128                         (caddr_t
)&ip
->ip_dst
, IPPROTO_IPCOMP
, htonl(cpi
)); 
 130                  && (sav
->state 
== SADB_SASTATE_MATURE
 
 131                   || sav
->state 
== SADB_SASTATE_DYING
)) { 
 132                         cpi 
= sav
->alg_enc
;     /*XXX*/ 
 133                         /* other parameters to look at? */ 
 136         algo 
= ipcomp_algorithm_lookup(cpi
); 
 138                 ipseclog((LOG_WARNING
, "IPv4 IPComp input: unknown cpi %u\n", 
 144         /* chop ipcomp header */ 
 146         md
->m_data 
+= sizeof(struct ipcomp
); 
 147         md
->m_len 
-= sizeof(struct ipcomp
); 
 148         m
->m_pkthdr
.len 
-= sizeof(struct ipcomp
); 
 150         ip
->ip_len 
-= sizeof(struct ipcomp
); 
 152         ip
->ip_len 
= htons(ntohs(ip
->ip_len
) - sizeof(struct ipcomp
)); 
 155         olen 
= m
->m_pkthdr
.len
; 
 156         newlen 
= m
->m_pkthdr
.len 
- off
; 
 157         lck_mtx_unlock(sadb_mutex
); 
 158         error 
= (*algo
->decompress
)(m
, m
->m_next
, &newlen
); 
 159         lck_mtx_lock(sadb_mutex
); 
 162                         ipsecstat
.in_inval
++; 
 163                 else if (error 
== ENOBUFS
) 
 164                         ipsecstat
.in_nomem
++; 
 168         ipsecstat
.in_comphist
[cpi
]++; 
 171          * returning decompressed packet onto icmp is meaningless. 
 172          * mark it decrypted to prevent icmp from attaching original packet. 
 174         m
->m_flags 
|= M_DECRYPTED
; 
 176         m
->m_pkthdr
.len 
= off 
+ newlen
; 
 177         ip 
= mtod(m
, struct ip 
*); 
 183         len 
= ntohs(ip
->ip_len
); 
 186          * be careful about underflow.  also, do not assign exact value 
 187          * as ip_len is manipulated differently on *BSDs. 
 189         len 
+= m
->m_pkthdr
.len
; 
 192                 /* packet too big after decompress */ 
 193                 ipsecstat
.in_inval
++; 
 197         ip
->ip_len 
= len 
& 0xffff; 
 199         ip
->ip_len 
= htons(len 
& 0xffff); 
 205                 key_sa_recordxfer(sav
, m
); 
 206                 if (ipsec_addhist(m
, IPPROTO_IPCOMP
, (u_int32_t
)cpi
) != 0) { 
 207                         ipsecstat
.in_nomem
++; 
 214         if (nxt 
!= IPPROTO_DONE
) { 
 215                 if ((ip_protox
[nxt
]->pr_flags 
& PR_LASTHDR
) != 0 && 
 216                     ipsec4_in_reject(m
, NULL
)) { 
 217                         ipsecstat
.in_polvio
++; 
 220                 lck_mtx_unlock(sadb_mutex
); 
 221                 ip_proto_dispatch_in(m
, off
, nxt
, 0); 
 222                 lck_mtx_lock(sadb_mutex
); 
 227         ipsecstat
.in_success
++; 
 228         lck_mtx_unlock(sadb_mutex
); 
 235         lck_mtx_unlock(sadb_mutex
); 
 243 ipcomp6_input(mp
, offp
) 
 250         struct ipcomp 
*ipcomp
; 
 251         const struct ipcomp_algorithm 
*algo
; 
 252         u_int16_t cpi
;  /* host order */ 
 256         struct secasvar 
*sav 
= NULL
; 
 262         lck_mtx_lock(sadb_mutex
); 
 263         md 
= m_pulldown(m
, off
, sizeof(*ipcomp
), NULL
); 
 265                 m 
= NULL
;       /*already freed*/ 
 266                 ipseclog((LOG_DEBUG
, "IPv6 IPComp input: assumption failed " 
 267                     "(pulldown failure)\n")); 
 268                 ipsec6stat
.in_inval
++; 
 271         ipcomp 
= mtod(md
, struct ipcomp 
*); 
 272         ip6 
= mtod(m
, struct ip6_hdr 
*); 
 273         nxt 
= ipcomp
->comp_nxt
; 
 275         cpi 
= ntohs(ipcomp
->comp_cpi
); 
 277         if (cpi 
>= IPCOMP_CPI_NEGOTIATE_MIN
) { 
 278                 sav 
= key_allocsa(AF_INET6
, (caddr_t
)&ip6
->ip6_src
, 
 279                         (caddr_t
)&ip6
->ip6_dst
, IPPROTO_IPCOMP
, htonl(cpi
)); 
 281                  && (sav
->state 
== SADB_SASTATE_MATURE
 
 282                   || sav
->state 
== SADB_SASTATE_DYING
)) { 
 283                         cpi 
= sav
->alg_enc
;     /*XXX*/ 
 284                         /* other parameters to look at? */ 
 287         algo 
= ipcomp_algorithm_lookup(cpi
); 
 289                 ipseclog((LOG_WARNING
, "IPv6 IPComp input: unknown cpi %u; " 
 290                         "dropping the packet for simplicity\n", cpi
)); 
 291                 ipsec6stat
.in_nosa
++; 
 295         /* chop ipcomp header */ 
 297         md
->m_data 
+= sizeof(struct ipcomp
); 
 298         md
->m_len 
-= sizeof(struct ipcomp
); 
 299         m
->m_pkthdr
.len 
-= sizeof(struct ipcomp
); 
 301         newlen 
= m
->m_pkthdr
.len 
- off
; 
 302         lck_mtx_unlock(sadb_mutex
); 
 303         error 
= (*algo
->decompress
)(m
, md
, &newlen
); 
 304         lck_mtx_lock(sadb_mutex
); 
 307                         ipsec6stat
.in_inval
++; 
 308                 else if (error 
== ENOBUFS
) 
 309                         ipsec6stat
.in_nomem
++; 
 313         ipsec6stat
.in_comphist
[cpi
]++; 
 314         m
->m_pkthdr
.len 
= off 
+ newlen
; 
 317          * returning decompressed packet onto icmp is meaningless. 
 318          * mark it decrypted to prevent icmp from attaching original packet. 
 320         m
->m_flags 
|= M_DECRYPTED
; 
 322         /* update next header field */ 
 323         prvnxtp 
= ip6_get_prevhdr(m
, off
); 
 327          * no need to adjust payload length, as all the IPv6 protocols 
 328          * look at m->m_pkthdr.len 
 332                 key_sa_recordxfer(sav
, m
); 
 333                 if (ipsec_addhist(m
, IPPROTO_IPCOMP
, (u_int32_t
)cpi
) != 0) { 
 334                         ipsec6stat
.in_nomem
++; 
 342         ipsec6stat
.in_success
++; 
 343         lck_mtx_unlock(sadb_mutex
); 
 351         lck_mtx_unlock(sadb_mutex
);