]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/isakmp_frag.c
1 /* $Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp $ */
4 * Copyright (C) 2004 Emmanuel Dreyfus
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/queue.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
42 #include <openssl/md5.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
54 # include <sys/time.h>
73 #include "isakmp_var.h"
76 #include "isakmp_frag.h"
80 isakmp_sendfrags(iph1
, buf
)
81 struct ph1handle
*iph1
;
85 struct isakmp_frag
*fraghdr
;
93 unsigned int fragnum
= 0;
98 * Catch the exchange type for later: the fragments and the
99 * fragmented packet must have the same exchange type.
101 hdr
= (struct isakmp
*)buf
->v
;
105 * We want to send a a packet smaller than ISAKMP_FRAG_MAXLEN
106 * First compute the maximum data length that will fit in it
108 max_datalen
= ISAKMP_FRAG_MAXLEN
-
109 (sizeof(*hdr
) + sizeof(*fraghdr
) + sizeof(trailer
));
117 if (len
> max_datalen
)
118 datalen
= max_datalen
;
122 fraglen
= sizeof(*hdr
)
126 if ((frag
= vmalloc(fraglen
)) == NULL
) {
127 plog(LLV_ERROR
, LOCATION
, NULL
,
128 "Cannot allocate memory\n");
132 set_isakmp_header1(frag
, iph1
, ISAKMP_NPTYPE_FRAG
);
133 hdr
= (struct isakmp
*)frag
->v
;
136 fraghdr
= (struct isakmp_frag
*)(hdr
+ 1);
137 fraghdr
->unknown0
= htons(0);
138 fraghdr
->len
= htons(fraglen
- sizeof(*hdr
));
139 fraghdr
->unknown1
= htons(1);
140 fraghdr
->index
= fragnum
;
142 fraghdr
->flags
= ISAKMP_FRAG_LAST
;
146 data
= (caddr_t
)(fraghdr
+ 1);
147 memcpy(data
, sdata
, datalen
);
149 if (isakmp_send(iph1
, frag
) < 0) {
150 plog(LLV_ERROR
, LOCATION
, NULL
, "isakmp_send failed\n");
164 vendorid_frag_cap(gen
)
165 struct isakmp_gen
*gen
;
169 hp
= (int *)(gen
+ 1);
171 return ntohl(hp
[MD5_DIGEST_LENGTH
/ sizeof(*hp
)]);
175 isakmp_frag_extract(iph1
, msg
)
176 struct ph1handle
*iph1
;
179 struct isakmp
*isakmp
;
180 struct isakmp_frag
*frag
;
181 struct isakmp_frag_item
*item
;
188 if (msg
->l
< sizeof(*isakmp
) + sizeof(*frag
)) {
189 plog(LLV_ERROR
, LOCATION
, NULL
, "Message too short\n");
193 isakmp
= (struct isakmp
*)msg
->v
;
194 frag
= (struct isakmp_frag
*)(isakmp
+ 1);
197 * frag->len is the frag payload data plus the frag payload header,
198 * whose size is sizeof(*frag)
200 if (msg
->l
< sizeof(*isakmp
) + ntohs(frag
->len
)) {
201 plog(LLV_ERROR
, LOCATION
, NULL
, "Fragment too short\n");
205 if ((buf
= vmalloc(ntohs(frag
->len
) - sizeof(*frag
))) == NULL
) {
206 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
210 if ((item
= racoon_malloc(sizeof(*item
))) == NULL
) {
211 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
216 data
= (char *)(frag
+ 1);
217 memcpy(buf
->v
, data
, buf
->l
);
219 item
->frag_num
= frag
->index
;
220 item
->frag_last
= (frag
->flags
& ISAKMP_FRAG_LAST
);
221 item
->frag_next
= NULL
;
222 item
->frag_packet
= buf
;
224 /* Look for the last frag while inserting the new item in the chain */
226 last_frag
= item
->frag_num
;
228 if (iph1
->frag_chain
== NULL
) {
229 iph1
->frag_chain
= item
;
231 struct isakmp_frag_item
*current
;
233 current
= iph1
->frag_chain
;
234 while (current
->frag_next
) {
235 if (current
->frag_last
)
236 last_frag
= item
->frag_num
;
237 current
= current
->frag_next
;
239 current
->frag_next
= item
;
242 /* If we saw the last frag, check if the chain is complete */
243 if (last_frag
!= 0) {
244 for (i
= 1; i
<= last_frag
; i
++) {
245 item
= iph1
->frag_chain
;
247 if (item
->frag_num
== i
)
249 item
= item
->frag_next
;
250 } while (item
!= NULL
);
252 if (item
== NULL
) /* Not found */
256 if (item
!= NULL
) /* It is complete */
264 isakmp_frag_reassembly(iph1
)
265 struct ph1handle
*iph1
;
267 struct isakmp_frag_item
*item
;
274 if ((item
= iph1
->frag_chain
) == NULL
) {
275 plog(LLV_ERROR
, LOCATION
, NULL
, "No fragment to reassemble\n");
281 len
+= item
->frag_packet
->l
;
282 item
= item
->frag_next
;
283 } while (item
!= NULL
);
285 if ((buf
= vmalloc(len
)) == NULL
) {
286 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
291 for (i
= 1; i
<= frag_count
; i
++) {
292 item
= iph1
->frag_chain
;
294 if (item
->frag_num
== i
)
296 item
= item
->frag_next
;
297 } while (item
!= NULL
);
300 plog(LLV_ERROR
, LOCATION
, NULL
,
301 "Missing fragment #%d\n", i
);
306 memcpy(data
, item
->frag_packet
->v
, item
->frag_packet
->l
);
307 data
+= item
->frag_packet
->l
;
311 item
= iph1
->frag_chain
;
313 struct isakmp_frag_item
*next_item
;
315 next_item
= item
->frag_next
;
317 vfree(item
->frag_packet
);
321 } while (item
!= NULL
);
323 iph1
->frag_chain
= NULL
;
329 isakmp_frag_addcap(buf
, cap
)
336 /* If the capability has not been added, add room now */
338 if (len
== MD5_DIGEST_LENGTH
) {
339 if ((buf
= vrealloc(buf
, len
+ sizeof(cap
))) == NULL
) {
340 plog(LLV_ERROR
, LOCATION
, NULL
,
341 "Cannot allocate memory\n");
344 capp
= (int *)(buf
->v
+ len
);
348 capp
= (int *)(buf
->v
+ MD5_DIGEST_LENGTH
);