1 /* $NetBSD: isakmp_frag.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */
3 /* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp */
6 * Copyright (C) 2004 Emmanuel Dreyfus
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/queue.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
44 #include <openssl/md5.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
56 # include <sys/time.h>
75 #include "isakmp_var.h"
78 #include "isakmp_frag.h"
82 isakmp_sendfrags(iph1
, buf
)
83 struct ph1handle
*iph1
;
87 struct isakmp_frag
*fraghdr
;
95 unsigned int fragnum
= 0;
100 * Catch the exchange type for later: the fragments and the
101 * fragmented packet must have the same exchange type.
103 hdr
= (struct isakmp
*)buf
->v
;
107 * We want to send a a packet smaller than ISAKMP_FRAG_MAXLEN
108 * First compute the maximum data length that will fit in it
110 max_datalen
= ISAKMP_FRAG_MAXLEN
-
111 (sizeof(*hdr
) + sizeof(*fraghdr
) + sizeof(trailer
));
119 if (len
> max_datalen
)
120 datalen
= max_datalen
;
124 fraglen
= sizeof(*hdr
)
128 if ((frag
= vmalloc(fraglen
)) == NULL
) {
129 plog(LLV_ERROR
, LOCATION
, NULL
,
130 "Cannot allocate memory\n");
134 set_isakmp_header1(frag
, iph1
, ISAKMP_NPTYPE_FRAG
);
135 hdr
= (struct isakmp
*)frag
->v
;
138 fraghdr
= (struct isakmp_frag
*)(hdr
+ 1);
139 fraghdr
->unknown0
= htons(0);
140 fraghdr
->len
= htons(fraglen
- sizeof(*hdr
));
141 fraghdr
->unknown1
= htons(1);
142 fraghdr
->index
= fragnum
;
144 fraghdr
->flags
= ISAKMP_FRAG_LAST
;
148 data
= (caddr_t
)(fraghdr
+ 1);
149 memcpy(data
, sdata
, datalen
);
151 if (isakmp_send(iph1
, frag
) < 0) {
152 plog(LLV_ERROR
, LOCATION
, NULL
, "isakmp_send failed\n");
166 vendorid_frag_cap(gen
)
167 struct isakmp_gen
*gen
;
171 hp
= (int *)(gen
+ 1);
173 return ntohl(hp
[MD5_DIGEST_LENGTH
/ sizeof(*hp
)]);
177 isakmp_frag_extract(iph1
, msg
)
178 struct ph1handle
*iph1
;
181 struct isakmp
*isakmp
;
182 struct isakmp_frag
*frag
;
183 struct isakmp_frag_item
*item
;
190 if (msg
->l
< sizeof(*isakmp
) + sizeof(*frag
)) {
191 plog(LLV_ERROR
, LOCATION
, NULL
, "Message too short\n");
195 isakmp
= (struct isakmp
*)msg
->v
;
196 frag
= (struct isakmp_frag
*)(isakmp
+ 1);
199 * frag->len is the frag payload data plus the frag payload header,
200 * whose size is sizeof(*frag)
202 if (msg
->l
< sizeof(*isakmp
) + ntohs(frag
->len
) ||
203 ntohs(frag
->len
) < sizeof(*frag
) + 1) {
204 plog(LLV_ERROR
, LOCATION
, NULL
, "Fragment too short\n");
208 if ((buf
= vmalloc(ntohs(frag
->len
) - sizeof(*frag
))) == NULL
) {
209 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
213 if ((item
= racoon_malloc(sizeof(*item
))) == NULL
) {
214 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
219 data
= (char *)(frag
+ 1);
220 memcpy(buf
->v
, data
, buf
->l
);
222 item
->frag_num
= frag
->index
;
223 item
->frag_last
= (frag
->flags
& ISAKMP_FRAG_LAST
);
224 item
->frag_next
= NULL
;
225 item
->frag_packet
= buf
;
227 /* Look for the last frag while inserting the new item in the chain */
229 last_frag
= item
->frag_num
;
231 if (iph1
->frag_chain
== NULL
) {
232 iph1
->frag_chain
= item
;
234 struct isakmp_frag_item
*current
;
236 current
= iph1
->frag_chain
;
237 while (current
->frag_next
) {
238 if (current
->frag_last
)
239 last_frag
= item
->frag_num
;
240 current
= current
->frag_next
;
242 current
->frag_next
= item
;
245 /* If we saw the last frag, check if the chain is complete */
246 if (last_frag
!= 0) {
247 for (i
= 1; i
<= last_frag
; i
++) {
248 item
= iph1
->frag_chain
;
250 if (item
->frag_num
== i
)
252 item
= item
->frag_next
;
253 } while (item
!= NULL
);
255 if (item
== NULL
) /* Not found */
259 if (item
!= NULL
) /* It is complete */
267 isakmp_frag_reassembly(iph1
)
268 struct ph1handle
*iph1
;
270 struct isakmp_frag_item
*item
;
277 if ((item
= iph1
->frag_chain
) == NULL
) {
278 plog(LLV_ERROR
, LOCATION
, NULL
, "No fragment to reassemble\n");
284 len
+= item
->frag_packet
->l
;
285 item
= item
->frag_next
;
286 } while (item
!= NULL
);
288 if ((buf
= vmalloc(len
)) == NULL
) {
289 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot allocate memory\n");
294 for (i
= 1; i
<= frag_count
; i
++) {
295 item
= iph1
->frag_chain
;
297 if (item
->frag_num
== i
)
299 item
= item
->frag_next
;
300 } while (item
!= NULL
);
303 plog(LLV_ERROR
, LOCATION
, NULL
,
304 "Missing fragment #%d\n", i
);
309 memcpy(data
, item
->frag_packet
->v
, item
->frag_packet
->l
);
310 data
+= item
->frag_packet
->l
;
314 item
= iph1
->frag_chain
;
316 struct isakmp_frag_item
*next_item
;
318 next_item
= item
->frag_next
;
320 vfree(item
->frag_packet
);
324 } while (item
!= NULL
);
326 iph1
->frag_chain
= NULL
;
332 isakmp_frag_addcap(buf
, cap
)
339 /* If the capability has not been added, add room now */
341 if (len
== MD5_DIGEST_LENGTH
) {
342 if ((buf
= vrealloc(buf
, len
+ sizeof(cap
))) == NULL
) {
343 plog(LLV_ERROR
, LOCATION
, NULL
,
344 "Cannot allocate memory\n");
347 capp
= (int *)(buf
->v
+ len
);
351 capp
= (int *)(buf
->v
+ MD5_DIGEST_LENGTH
);