]>
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/mcache.h>
43 #include <sys/domain.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/errno.h>
48 #include <sys/kernel.h>
49 #include <sys/syslog.h>
52 #include <net/route.h>
53 #include <libkern/zlib.h>
54 #include <kern/cpu_number.h>
55 #include <kern/locks.h>
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip.h>
61 #include <netinet/ip_var.h>
62 #include <netinet/ip_ecn.h>
63 #include <netinet/kpi_ipfilter_var.h>
66 #include <netinet/ip6.h>
67 #include <netinet6/ip6_var.h>
69 #include <netinet6/ipcomp.h>
71 #include <netinet6/ipcomp6.h>
74 #include <netinet6/ipsec.h>
76 #include <netinet6/ipsec6.h>
78 #include <netkey/key.h>
79 #include <netkey/keydb.h>
81 #include <net/net_osdep.h>
87 ipcomp4_input(struct mbuf
*m
, int off
)
91 struct ipcomp
*ipcomp
;
92 const struct ipcomp_algorithm
*algo
;
93 u_int16_t cpi
; /* host order */
98 struct secasvar
*sav
= NULL
;
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 IPSEC_STAT_INCREMENT(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 IPSEC_STAT_INCREMENT(ipsecstat
.in_inval
);
115 ipcomp
= mtod(md
, struct ipcomp
*);
117 /* Expect 32-bit aligned data pointer on strict-align platforms */
118 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
120 ip
= mtod(m
, struct ip
*);
121 nxt
= ipcomp
->comp_nxt
;
123 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
125 hlen
= ip
->ip_hl
<< 2;
128 cpi
= ntohs(ipcomp
->comp_cpi
);
130 if (cpi
>= IPCOMP_CPI_NEGOTIATE_MIN
) {
131 sav
= key_allocsa(AF_INET
, (caddr_t
)&ip
->ip_src
,
132 (caddr_t
)&ip
->ip_dst
, IPPROTO_IPCOMP
, htonl(cpi
));
134 && (sav
->state
== SADB_SASTATE_MATURE
135 || sav
->state
== SADB_SASTATE_DYING
)) {
136 cpi
= sav
->alg_enc
; /*XXX*/
137 /* other parameters to look at? */
140 algo
= ipcomp_algorithm_lookup(cpi
);
142 ipseclog((LOG_WARNING
, "IPv4 IPComp input: unknown cpi %u\n",
144 IPSEC_STAT_INCREMENT(ipsecstat
.in_nosa
);
148 /* chop ipcomp header */
150 md
->m_data
+= sizeof(struct ipcomp
);
151 md
->m_len
-= sizeof(struct ipcomp
);
152 m
->m_pkthdr
.len
-= sizeof(struct ipcomp
);
154 ip
->ip_len
-= sizeof(struct ipcomp
);
156 ip
->ip_len
= htons(ntohs(ip
->ip_len
) - sizeof(struct ipcomp
));
159 olen
= m
->m_pkthdr
.len
;
160 newlen
= m
->m_pkthdr
.len
- off
;
161 error
= (*algo
->decompress
)(m
, m
->m_next
, &newlen
);
163 if (error
== EINVAL
) {
164 IPSEC_STAT_INCREMENT(ipsecstat
.in_inval
);
165 } else if (error
== ENOBUFS
) {
166 IPSEC_STAT_INCREMENT(ipsecstat
.in_nomem
);
171 IPSEC_STAT_INCREMENT(ipsecstat
.in_comphist
[cpi
]);
174 * returning decompressed packet onto icmp is meaningless.
175 * mark it decrypted to prevent icmp from attaching original packet.
177 m
->m_flags
|= M_DECRYPTED
;
179 m
->m_pkthdr
.len
= off
+ newlen
;
180 ip
= mtod(m
, struct ip
*);
186 len
= ntohs(ip
->ip_len
);
189 * be careful about underflow. also, do not assign exact value
190 * as ip_len is manipulated differently on *BSDs.
192 len
+= m
->m_pkthdr
.len
;
195 /* packet too big after decompress */
196 IPSEC_STAT_INCREMENT(ipsecstat
.in_inval
);
200 ip
->ip_len
= len
& 0xffff;
202 ip
->ip_len
= htons(len
& 0xffff);
208 key_sa_recordxfer(sav
, m
);
209 if (ipsec_addhist(m
, IPPROTO_IPCOMP
, (u_int32_t
)cpi
) != 0) {
210 IPSEC_STAT_INCREMENT(ipsecstat
.in_nomem
);
213 key_freesav(sav
, KEY_SADB_UNLOCKED
);
217 if (nxt
!= IPPROTO_DONE
) {
218 if ((ip_protox
[nxt
]->pr_flags
& PR_LASTHDR
) != 0 &&
219 ipsec4_in_reject(m
, NULL
)) {
220 IPSEC_STAT_INCREMENT(ipsecstat
.in_polvio
);
224 DTRACE_IP6(receive
, struct mbuf
*, m
, struct inpcb
*, NULL
,
225 struct ip
*, ip
, struct ifnet
*, m
->m_pkthdr
.rcvif
,
226 struct ip
*, ip
, struct ip6_hdr
*, NULL
);
228 ip_proto_dispatch_in(m
, off
, nxt
, 0);
234 IPSEC_STAT_INCREMENT(ipsecstat
.in_success
);
239 key_freesav(sav
, KEY_SADB_UNLOCKED
);
250 ipcomp6_input(struct mbuf
**mp
, int *offp
, int proto
)
252 #pragma unused(proto)
256 struct ipcomp
*ipcomp
;
257 const struct ipcomp_algorithm
*algo
;
258 u_int16_t cpi
; /* host order */
262 struct secasvar
*sav
= NULL
;
268 md
= m_pulldown(m
, off
, sizeof(*ipcomp
), NULL
);
270 m
= NULL
; /*already freed*/
271 ipseclog((LOG_DEBUG
, "IPv6 IPComp input: assumption failed "
272 "(pulldown failure)\n"));
273 IPSEC_STAT_INCREMENT(ipsec6stat
.in_inval
);
276 ipcomp
= mtod(md
, struct ipcomp
*);
278 /* Expect 32-bit aligned data pointer on strict-align platforms */
279 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
281 ip6
= mtod(m
, struct ip6_hdr
*);
282 nxt
= ipcomp
->comp_nxt
;
284 cpi
= ntohs(ipcomp
->comp_cpi
);
286 if (cpi
>= IPCOMP_CPI_NEGOTIATE_MIN
) {
287 sav
= key_allocsa(AF_INET6
, (caddr_t
)&ip6
->ip6_src
,
288 (caddr_t
)&ip6
->ip6_dst
, IPPROTO_IPCOMP
, htonl(cpi
));
290 && (sav
->state
== SADB_SASTATE_MATURE
291 || sav
->state
== SADB_SASTATE_DYING
)) {
292 cpi
= sav
->alg_enc
; /*XXX*/
293 /* other parameters to look at? */
296 algo
= ipcomp_algorithm_lookup(cpi
);
298 ipseclog((LOG_WARNING
, "IPv6 IPComp input: unknown cpi %u; "
299 "dropping the packet for simplicity\n", cpi
));
300 IPSEC_STAT_INCREMENT(ipsec6stat
.in_nosa
);
304 /* chop ipcomp header */
306 md
->m_data
+= sizeof(struct ipcomp
);
307 md
->m_len
-= sizeof(struct ipcomp
);
308 m
->m_pkthdr
.len
-= sizeof(struct ipcomp
);
310 newlen
= m
->m_pkthdr
.len
- off
;
311 error
= (*algo
->decompress
)(m
, md
, &newlen
);
313 if (error
== EINVAL
) {
314 IPSEC_STAT_INCREMENT(ipsec6stat
.in_inval
);
315 } else if (error
== ENOBUFS
) {
316 IPSEC_STAT_INCREMENT(ipsec6stat
.in_nomem
);
321 IPSEC_STAT_INCREMENT(ipsec6stat
.in_comphist
[cpi
]);
322 m
->m_pkthdr
.len
= off
+ newlen
;
325 * returning decompressed packet onto icmp is meaningless.
326 * mark it decrypted to prevent icmp from attaching original packet.
328 m
->m_flags
|= M_DECRYPTED
;
330 /* update next header field */
331 prvnxtp
= ip6_get_prevhdr(m
, off
);
335 * no need to adjust payload length, as all the IPv6 protocols
336 * look at m->m_pkthdr.len
340 key_sa_recordxfer(sav
, m
);
341 if (ipsec_addhist(m
, IPPROTO_IPCOMP
, (u_int32_t
)cpi
) != 0) {
342 IPSEC_STAT_INCREMENT(ipsec6stat
.in_nomem
);
345 key_freesav(sav
, KEY_SADB_UNLOCKED
);
350 IPSEC_STAT_INCREMENT(ipsec6stat
.in_success
);
358 key_freesav(sav
, KEY_SADB_UNLOCKED
);