]>
Commit | Line | Data |
---|---|---|
997358a6 MW |
1 | /* |
2 | * RFC2367 PF_KEYv2 Key management API message parser | |
3 | * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | * for more details. | |
14 | * | |
15 | * RCSID $Id: pfkey_v2_build.c,v 1.4 2005/04/07 19:43:52 as Exp $ | |
16 | */ | |
17 | ||
18 | /* | |
19 | * Template from klips/net/ipsec/ipsec/ipsec_parser.c. | |
20 | */ | |
21 | ||
22 | char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.4 2005/04/07 19:43:52 as Exp $"; | |
23 | ||
24 | /* | |
25 | * Some ugly stuff to allow consistent debugging code for use in the | |
26 | * kernel and in user space | |
27 | */ | |
28 | ||
29 | #ifdef __KERNEL__ | |
30 | ||
31 | # include <linux/kernel.h> /* for printk */ | |
32 | ||
33 | # include "freeswan/ipsec_kversion.h" /* for malloc switch */ | |
34 | # ifdef MALLOC_SLAB | |
35 | # include <linux/slab.h> /* kmalloc() */ | |
36 | # else /* MALLOC_SLAB */ | |
37 | # include <linux/malloc.h> /* kmalloc() */ | |
38 | # endif /* MALLOC_SLAB */ | |
39 | # include <linux/errno.h> /* error codes */ | |
40 | # include <linux/types.h> /* size_t */ | |
41 | # include <linux/interrupt.h> /* mark_bh */ | |
42 | ||
43 | # include <linux/netdevice.h> /* struct device, and other headers */ | |
44 | # include <linux/etherdevice.h> /* eth_type_trans */ | |
45 | # include <linux/ip.h> /* struct iphdr */ | |
46 | # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | |
47 | # include <linux/ipv6.h> /* struct ipv6hdr */ | |
48 | # endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | |
49 | ||
50 | # define MALLOC(size) kmalloc(size, GFP_ATOMIC) | |
51 | # define FREE(obj) kfree(obj) | |
52 | # include <freeswan.h> | |
53 | #else /* __KERNEL__ */ | |
54 | ||
55 | # include <sys/types.h> | |
56 | # include <linux/types.h> | |
57 | # include <linux/errno.h> | |
58 | # include <malloc.h> | |
59 | # include <string.h> /* memset */ | |
60 | ||
61 | # include <freeswan.h> | |
62 | unsigned int pfkey_lib_debug = 0; | |
63 | ||
64 | void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1); | |
65 | ||
66 | /* #define PLUTO */ | |
67 | ||
68 | #define DEBUGGING(args...) if(pfkey_lib_debug) { \ | |
69 | if(pfkey_debug_func != NULL) { \ | |
70 | (*pfkey_debug_func)("pfkey_lib_debug:" args); \ | |
71 | } else { \ | |
72 | printf("pfkey_lib_debug:" args); \ | |
73 | } } | |
74 | # define MALLOC(size) malloc(size) | |
75 | # define FREE(obj) free(obj) | |
76 | #endif /* __KERNEL__ */ | |
77 | ||
78 | #include <pfkeyv2.h> | |
79 | #include <pfkey.h> | |
80 | ||
81 | #ifdef __KERNEL__ | |
82 | ||
83 | #include "freeswan/radij.h" /* rd_nodes */ | |
84 | #include "freeswan/ipsec_encap.h" /* sockaddr_encap */ | |
85 | ||
86 | # define DEBUGGING(args...) \ | |
87 | KLIPS_PRINT(debug_pfkey, "klips_debug:" args) | |
88 | #endif /* __KERNEL__ */ | |
89 | ||
90 | #include "freeswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ | |
91 | ||
92 | #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) | |
93 | ||
94 | void | |
95 | pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) | |
96 | { | |
97 | int i; | |
98 | ||
99 | for (i = 0; i != SADB_EXT_MAX + 1; i++) { | |
100 | extensions[i] = NULL; | |
101 | } | |
102 | } | |
103 | ||
104 | void | |
105 | pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]) | |
106 | { | |
107 | int i; | |
108 | ||
109 | if (!extensions) { | |
110 | return; | |
111 | } | |
112 | ||
113 | if (extensions[0]) { | |
114 | memset(extensions[0], 0, sizeof(struct sadb_msg)); | |
115 | FREE(extensions[0]); | |
116 | extensions[0] = NULL; | |
117 | } | |
118 | ||
119 | for (i = 1; i != SADB_EXT_MAX + 1; i++) { | |
120 | if(extensions[i]) { | |
121 | memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); | |
122 | FREE(extensions[i]); | |
123 | extensions[i] = NULL; | |
124 | } | |
125 | } | |
126 | } | |
127 | ||
128 | void | |
129 | pfkey_msg_free(struct sadb_msg **pfkey_msg) | |
130 | { | |
131 | if (*pfkey_msg) { | |
132 | memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); | |
133 | FREE(*pfkey_msg); | |
134 | *pfkey_msg = NULL; | |
135 | } | |
136 | } | |
137 | ||
138 | /* Default extension builders taken from the KLIPS code */ | |
139 | ||
140 | int | |
141 | pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext, | |
142 | uint8_t msg_type, | |
143 | uint8_t satype, | |
144 | uint8_t msg_errno, | |
145 | uint32_t seq, | |
146 | uint32_t pid) | |
147 | { | |
148 | int error = 0; | |
149 | struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; | |
150 | ||
151 | DEBUGGING( | |
152 | "pfkey_msg_hdr_build:\n"); | |
153 | DEBUGGING( | |
154 | "pfkey_msg_hdr_build: " | |
155 | "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", | |
156 | &pfkey_ext, | |
157 | pfkey_ext, | |
158 | *pfkey_ext); | |
159 | /* sanity checks... */ | |
160 | if (pfkey_msg) { | |
161 | DEBUGGING( | |
162 | "pfkey_msg_hdr_build: " | |
163 | "why is pfkey_msg already pointing to something?\n"); | |
164 | SENDERR(EINVAL); | |
165 | } | |
166 | ||
167 | if (!msg_type) { | |
168 | DEBUGGING( | |
169 | "pfkey_msg_hdr_build: " | |
170 | "msg type not set, must be non-zero..\n"); | |
171 | SENDERR(EINVAL); | |
172 | } | |
173 | ||
174 | if (msg_type > SADB_MAX) { | |
175 | DEBUGGING( | |
176 | "pfkey_msg_hdr_build: " | |
177 | "msg type too large:%d.\n", | |
178 | msg_type); | |
179 | SENDERR(EINVAL); | |
180 | } | |
181 | ||
182 | if (satype > SADB_SATYPE_MAX) { | |
183 | DEBUGGING( | |
184 | "pfkey_msg_hdr_build: " | |
185 | "satype %d > max %d\n", | |
186 | satype, SADB_SATYPE_MAX); | |
187 | SENDERR(EINVAL); | |
188 | } | |
189 | ||
190 | pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg)); | |
191 | *pfkey_ext = (struct sadb_ext*)pfkey_msg; | |
192 | ||
193 | if (pfkey_msg == NULL) { | |
194 | DEBUGGING( | |
195 | "pfkey_msg_hdr_build: " | |
196 | "memory allocation failed\n"); | |
197 | SENDERR(ENOMEM); | |
198 | } | |
199 | memset(pfkey_msg, 0, sizeof(struct sadb_msg)); | |
200 | ||
201 | pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; | |
202 | ||
203 | pfkey_msg->sadb_msg_type = msg_type; | |
204 | pfkey_msg->sadb_msg_satype = satype; | |
205 | ||
206 | pfkey_msg->sadb_msg_version = PF_KEY_V2; | |
207 | pfkey_msg->sadb_msg_errno = msg_errno; | |
208 | pfkey_msg->sadb_msg_reserved = 0; | |
209 | pfkey_msg->sadb_msg_seq = seq; | |
210 | pfkey_msg->sadb_msg_pid = pid; | |
211 | DEBUGGING( | |
212 | "pfkey_msg_hdr_build: " | |
213 | "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", | |
214 | &pfkey_ext, | |
215 | pfkey_ext, | |
216 | *pfkey_ext); | |
217 | errlab: | |
218 | return error; | |
219 | } | |
220 | ||
221 | int | |
222 | pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, | |
223 | uint16_t exttype, | |
224 | uint32_t spi, | |
225 | uint8_t replay_window, | |
226 | uint8_t sa_state, | |
227 | uint8_t auth, | |
228 | uint8_t encrypt, | |
229 | uint32_t flags, | |
230 | uint32_t/*IPsecSAref_t*/ ref) | |
231 | { | |
232 | int error = 0; | |
233 | struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext; | |
234 | ||
235 | DEBUGGING( | |
236 | "pfkey_sa_build: " | |
237 | "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", | |
238 | ntohl(spi), /* in network order */ | |
239 | replay_window, | |
240 | sa_state, | |
241 | auth, | |
242 | encrypt, | |
243 | flags); | |
244 | /* sanity checks... */ | |
245 | if (pfkey_sa) { | |
246 | DEBUGGING( | |
247 | "pfkey_sa_build: " | |
248 | "why is pfkey_sa already pointing to something?\n"); | |
249 | SENDERR(EINVAL); | |
250 | } | |
251 | ||
252 | if (exttype != SADB_EXT_SA | |
253 | && exttype != SADB_X_EXT_SA2) { | |
254 | DEBUGGING( | |
255 | "pfkey_sa_build: " | |
256 | "invalid exttype=%d.\n", | |
257 | exttype); | |
258 | SENDERR(EINVAL); | |
259 | } | |
260 | ||
261 | if (replay_window > 64) { | |
262 | DEBUGGING( | |
263 | "pfkey_sa_build: " | |
264 | "replay window size: %d -- must be 0 <= size <= 64\n", | |
265 | replay_window); | |
266 | SENDERR(EINVAL); | |
267 | } | |
268 | ||
269 | if (auth > SADB_AALG_MAX) { | |
270 | DEBUGGING( | |
271 | "pfkey_sa_build: " | |
272 | "auth=%d > SADB_AALG_MAX=%d.\n", | |
273 | auth, | |
274 | SADB_AALG_MAX); | |
275 | SENDERR(EINVAL); | |
276 | } | |
277 | ||
278 | if (encrypt > SADB_EALG_MAX) { | |
279 | DEBUGGING( | |
280 | "pfkey_sa_build: " | |
281 | "encrypt=%d > SADB_EALG_MAX=%d.\n", | |
282 | encrypt, | |
283 | SADB_EALG_MAX); | |
284 | SENDERR(EINVAL); | |
285 | } | |
286 | ||
287 | if (sa_state > SADB_SASTATE_MAX) { | |
288 | DEBUGGING( | |
289 | "pfkey_sa_build: " | |
290 | "sa_state=%d exceeds MAX=%d.\n", | |
291 | sa_state, | |
292 | SADB_SASTATE_MAX); | |
293 | SENDERR(EINVAL); | |
294 | } | |
295 | ||
296 | if (sa_state == SADB_SASTATE_DEAD) { | |
297 | DEBUGGING( | |
298 | "pfkey_sa_build: " | |
299 | "sa_state=%d is DEAD=%d is not allowed.\n", | |
300 | sa_state, | |
301 | SADB_SASTATE_DEAD); | |
302 | SENDERR(EINVAL); | |
303 | } | |
304 | ||
305 | if ((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { | |
306 | DEBUGGING( | |
307 | "pfkey_sa_build: " | |
308 | "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", | |
309 | ref, | |
310 | IPSEC_SAREF_NULL, | |
311 | IPSEC_SA_REF_TABLE_NUM_ENTRIES); | |
312 | SENDERR(EINVAL); | |
313 | } | |
314 | ||
315 | pfkey_sa = (struct sadb_sa*)MALLOC(sizeof(struct sadb_sa)); | |
316 | *pfkey_ext = (struct sadb_ext*)pfkey_sa; | |
317 | ||
318 | if (pfkey_sa == NULL) { | |
319 | DEBUGGING( | |
320 | "pfkey_sa_build: " | |
321 | "memory allocation failed\n"); | |
322 | SENDERR(ENOMEM); | |
323 | } | |
324 | memset(pfkey_sa, 0, sizeof(struct sadb_sa)); | |
325 | ||
326 | pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; | |
327 | pfkey_sa->sadb_sa_exttype = exttype; | |
328 | pfkey_sa->sadb_sa_spi = spi; | |
329 | pfkey_sa->sadb_sa_replay = replay_window; | |
330 | pfkey_sa->sadb_sa_state = sa_state; | |
331 | pfkey_sa->sadb_sa_auth = auth; | |
332 | pfkey_sa->sadb_sa_encrypt = encrypt; | |
333 | pfkey_sa->sadb_sa_flags = flags; | |
334 | pfkey_sa->sadb_x_sa_ref = ref; | |
335 | ||
336 | errlab: | |
337 | return error; | |
338 | } | |
339 | ||
340 | int | |
341 | pfkey_sa_build(struct sadb_ext ** pfkey_ext, | |
342 | uint16_t exttype, | |
343 | uint32_t spi, | |
344 | uint8_t replay_window, | |
345 | uint8_t sa_state, | |
346 | uint8_t auth, | |
347 | uint8_t encrypt, | |
348 | uint32_t flags) | |
349 | { | |
350 | return pfkey_sa_ref_build(pfkey_ext, | |
351 | exttype, | |
352 | spi, | |
353 | replay_window, | |
354 | sa_state, | |
355 | auth, | |
356 | encrypt, | |
357 | flags, | |
358 | IPSEC_SAREF_NULL); | |
359 | } | |
360 | ||
361 | int | |
362 | pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, | |
363 | uint16_t exttype, | |
364 | uint32_t allocations, | |
365 | uint64_t bytes, | |
366 | uint64_t addtime, | |
367 | uint64_t usetime, | |
368 | uint32_t packets) | |
369 | { | |
370 | int error = 0; | |
371 | struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; | |
372 | ||
373 | DEBUGGING( | |
374 | "pfkey_lifetime_build:\n"); | |
375 | /* sanity checks... */ | |
376 | if (pfkey_lifetime) { | |
377 | DEBUGGING( | |
378 | "pfkey_lifetime_build: " | |
379 | "why is pfkey_lifetime already pointing to something?\n"); | |
380 | SENDERR(EINVAL); | |
381 | } | |
382 | ||
383 | if (exttype != SADB_EXT_LIFETIME_CURRENT | |
384 | && exttype != SADB_EXT_LIFETIME_HARD | |
385 | && exttype != SADB_EXT_LIFETIME_SOFT) { | |
386 | DEBUGGING( | |
387 | "pfkey_lifetime_build: " | |
388 | "invalid exttype=%d.\n", | |
389 | exttype); | |
390 | SENDERR(EINVAL); | |
391 | } | |
392 | ||
393 | pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime)); | |
394 | *pfkey_ext = (struct sadb_ext*)pfkey_lifetime; | |
395 | ||
396 | if (pfkey_lifetime == NULL) { | |
397 | DEBUGGING( | |
398 | "pfkey_lifetime_build: " | |
399 | "memory allocation failed\n"); | |
400 | SENDERR(ENOMEM); | |
401 | } | |
402 | memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); | |
403 | ||
404 | pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; | |
405 | pfkey_lifetime->sadb_lifetime_exttype = exttype; | |
406 | pfkey_lifetime->sadb_lifetime_allocations = allocations; | |
407 | pfkey_lifetime->sadb_lifetime_bytes = bytes; | |
408 | pfkey_lifetime->sadb_lifetime_addtime = addtime; | |
409 | pfkey_lifetime->sadb_lifetime_usetime = usetime; | |
410 | pfkey_lifetime->sadb_x_lifetime_packets = packets; | |
411 | ||
412 | errlab: | |
413 | return error; | |
414 | } | |
415 | ||
416 | int | |
417 | pfkey_address_build(struct sadb_ext** pfkey_ext, | |
418 | uint16_t exttype, | |
419 | uint8_t proto, | |
420 | uint8_t prefixlen, | |
421 | struct sockaddr* address) | |
422 | { | |
423 | int error = 0; | |
424 | int saddr_len = 0; | |
425 | char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/]; | |
426 | struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; | |
427 | ||
428 | DEBUGGING( | |
429 | "pfkey_address_build: " | |
430 | "exttype=%d proto=%d prefixlen=%d\n", | |
431 | exttype, | |
432 | proto, | |
433 | prefixlen); | |
434 | /* sanity checks... */ | |
435 | if (pfkey_address) { | |
436 | DEBUGGING( | |
437 | "pfkey_address_build: " | |
438 | "why is pfkey_address already pointing to something?\n"); | |
439 | SENDERR(EINVAL); | |
440 | } | |
441 | ||
442 | if (!address) { | |
443 | DEBUGGING("pfkey_address_build: " | |
444 | "address is NULL\n"); | |
445 | SENDERR(EINVAL); | |
446 | } | |
447 | ||
448 | switch(exttype) { | |
449 | case SADB_EXT_ADDRESS_SRC: | |
450 | case SADB_EXT_ADDRESS_DST: | |
451 | case SADB_EXT_ADDRESS_PROXY: | |
452 | case SADB_X_EXT_ADDRESS_DST2: | |
453 | case SADB_X_EXT_ADDRESS_SRC_FLOW: | |
454 | case SADB_X_EXT_ADDRESS_DST_FLOW: | |
455 | case SADB_X_EXT_ADDRESS_SRC_MASK: | |
456 | case SADB_X_EXT_ADDRESS_DST_MASK: | |
457 | #ifdef NAT_TRAVERSAL | |
458 | case SADB_X_EXT_NAT_T_OA: | |
459 | #endif | |
460 | break; | |
461 | default: | |
462 | DEBUGGING( | |
463 | "pfkey_address_build: " | |
464 | "unrecognised ext_type=%d.\n", | |
465 | exttype); | |
466 | SENDERR(EINVAL); | |
467 | } | |
468 | ||
469 | switch (address->sa_family) { | |
470 | case AF_INET: | |
471 | DEBUGGING( | |
472 | "pfkey_address_build: " | |
473 | "found address family AF_INET.\n"); | |
474 | saddr_len = sizeof(struct sockaddr_in); | |
475 | sprintf(ipaddr_txt, "%d.%d.%d.%d:%d" | |
476 | , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 0) & 0xFF | |
477 | , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 8) & 0xFF | |
478 | , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF | |
479 | , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF | |
480 | , ntohs(((struct sockaddr_in*)address)->sin_port)); | |
481 | break; | |
482 | case AF_INET6: | |
483 | DEBUGGING( | |
484 | "pfkey_address_build: " | |
485 | "found address family AF_INET6.\n"); | |
486 | saddr_len = sizeof(struct sockaddr_in6); | |
487 | sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x" | |
488 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0]) | |
489 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1]) | |
490 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2]) | |
491 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3]) | |
492 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4]) | |
493 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5]) | |
494 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6]) | |
495 | , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7]) | |
496 | , ntohs(((struct sockaddr_in6*)address)->sin6_port)); | |
497 | break; | |
498 | default: | |
499 | DEBUGGING( | |
500 | "pfkey_address_build: " | |
501 | "address->sa_family=%d not supported.\n", | |
502 | address->sa_family); | |
503 | SENDERR(EPFNOSUPPORT); | |
504 | } | |
505 | ||
506 | DEBUGGING( | |
507 | "pfkey_address_build: " | |
508 | "found address=%s.\n", | |
509 | ipaddr_txt); | |
510 | if (prefixlen != 0) { | |
511 | DEBUGGING( | |
512 | "pfkey_address_build: " | |
513 | "address prefixes not supported yet.\n"); | |
514 | SENDERR(EAFNOSUPPORT); /* not supported yet */ | |
515 | } | |
516 | ||
517 | pfkey_address = (struct sadb_address*) | |
518 | MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); | |
519 | *pfkey_ext = (struct sadb_ext*)pfkey_address; | |
520 | ||
521 | if (pfkey_address == NULL) { | |
522 | DEBUGGING( | |
523 | "pfkey_lifetime_build: " | |
524 | "memory allocation failed\n"); | |
525 | SENDERR(ENOMEM); | |
526 | } | |
527 | memset(pfkey_address, | |
528 | 0, | |
529 | ALIGN_N(sizeof(struct sadb_address) + saddr_len, | |
530 | IPSEC_PFKEYv2_ALIGN)); | |
531 | ||
532 | pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len, | |
533 | IPSEC_PFKEYv2_ALIGN); | |
534 | ||
535 | pfkey_address->sadb_address_exttype = exttype; | |
536 | pfkey_address->sadb_address_proto = proto; | |
537 | pfkey_address->sadb_address_prefixlen = prefixlen; | |
538 | pfkey_address->sadb_address_reserved = 0; | |
539 | ||
540 | memcpy((char*)pfkey_address + sizeof(struct sadb_address), | |
541 | address, | |
542 | saddr_len); | |
543 | ||
544 | #if 0 | |
545 | for (i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) { | |
546 | pfkey_address_s_ska.sin_zero[i] = 0; | |
547 | } | |
548 | #endif | |
549 | DEBUGGING( | |
550 | "pfkey_address_build: " | |
551 | "successful.\n"); | |
552 | ||
553 | errlab: | |
554 | return error; | |
555 | } | |
556 | ||
557 | int | |
558 | pfkey_key_build(struct sadb_ext** pfkey_ext, | |
559 | uint16_t exttype, | |
560 | uint16_t key_bits, | |
561 | char* key) | |
562 | { | |
563 | int error = 0; | |
564 | struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; | |
565 | ||
566 | DEBUGGING( | |
567 | "pfkey_key_build:\n"); | |
568 | /* sanity checks... */ | |
569 | if (pfkey_key) { | |
570 | DEBUGGING( | |
571 | "pfkey_key_build: " | |
572 | "why is pfkey_key already pointing to something?\n"); | |
573 | SENDERR(EINVAL); | |
574 | } | |
575 | ||
576 | if (!key_bits) { | |
577 | DEBUGGING( | |
578 | "pfkey_key_build: " | |
579 | "key_bits is zero, it must be non-zero.\n"); | |
580 | SENDERR(EINVAL); | |
581 | } | |
582 | ||
583 | if ( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { | |
584 | DEBUGGING( | |
585 | "pfkey_key_build: " | |
586 | "unsupported extension type=%d.\n", | |
587 | exttype); | |
588 | SENDERR(EINVAL); | |
589 | } | |
590 | ||
591 | pfkey_key = (struct sadb_key*) | |
592 | MALLOC(sizeof(struct sadb_key) + | |
593 | DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); | |
594 | *pfkey_ext = (struct sadb_ext*)pfkey_key; | |
595 | ||
596 | if (pfkey_key == NULL) { | |
597 | DEBUGGING( | |
598 | "pfkey_key_build: " | |
599 | "memory allocation failed\n"); | |
600 | SENDERR(ENOMEM); | |
601 | } | |
602 | memset(pfkey_key, | |
603 | 0, | |
604 | sizeof(struct sadb_key) + | |
605 | DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); | |
606 | ||
607 | pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, | |
608 | 64); | |
609 | pfkey_key->sadb_key_exttype = exttype; | |
610 | pfkey_key->sadb_key_bits = key_bits; | |
611 | pfkey_key->sadb_key_reserved = 0; | |
612 | memcpy((char*)pfkey_key + sizeof(struct sadb_key), | |
613 | key, | |
614 | DIVUP(key_bits, 8)); | |
615 | ||
616 | errlab: | |
617 | return error; | |
618 | } | |
619 | ||
620 | int | |
621 | pfkey_ident_build(struct sadb_ext** pfkey_ext, | |
622 | uint16_t exttype, | |
623 | uint16_t ident_type, | |
624 | uint64_t ident_id, | |
625 | uint8_t ident_len, | |
626 | char* ident_string) | |
627 | { | |
628 | int error = 0; | |
629 | struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; | |
630 | int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); | |
631 | ||
632 | DEBUGGING( | |
633 | "pfkey_ident_build:\n"); | |
634 | /* sanity checks... */ | |
635 | if (pfkey_ident) { | |
636 | DEBUGGING( | |
637 | "pfkey_ident_build: " | |
638 | "why is pfkey_ident already pointing to something?\n"); | |
639 | SENDERR(EINVAL); | |
640 | } | |
641 | ||
642 | if ( !((exttype == SADB_EXT_IDENTITY_SRC) || | |
643 | (exttype == SADB_EXT_IDENTITY_DST))) { | |
644 | DEBUGGING( | |
645 | "pfkey_ident_build: " | |
646 | "unsupported extension type=%d.\n", | |
647 | exttype); | |
648 | SENDERR(EINVAL); | |
649 | } | |
650 | ||
651 | if (ident_type == SADB_IDENTTYPE_RESERVED) { | |
652 | DEBUGGING( | |
653 | "pfkey_ident_build: " | |
654 | "ident_type must be non-zero.\n"); | |
655 | SENDERR(EINVAL); | |
656 | } | |
657 | ||
658 | if (ident_type > SADB_IDENTTYPE_MAX) { | |
659 | DEBUGGING( | |
660 | "pfkey_ident_build: " | |
661 | "identtype=%d out of range.\n", | |
662 | ident_type); | |
663 | SENDERR(EINVAL); | |
664 | } | |
665 | ||
666 | if ((ident_type == SADB_IDENTTYPE_PREFIX || | |
667 | ident_type == SADB_IDENTTYPE_FQDN) && | |
668 | !ident_string) { | |
669 | DEBUGGING( | |
670 | "pfkey_ident_build: " | |
671 | "string required to allocate size of extension.\n"); | |
672 | SENDERR(EINVAL); | |
673 | } | |
674 | ||
675 | #if 0 | |
676 | if (ident_type == SADB_IDENTTYPE_USERFQDN) { | |
677 | } | |
678 | #endif | |
679 | ||
680 | pfkey_ident = (struct sadb_ident*) | |
681 | MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN); | |
682 | *pfkey_ext = (struct sadb_ext*)pfkey_ident; | |
683 | ||
684 | if (pfkey_ident == NULL) { | |
685 | DEBUGGING( | |
686 | "pfkey_ident_build: " | |
687 | "memory allocation failed\n"); | |
688 | SENDERR(ENOMEM); | |
689 | } | |
690 | memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); | |
691 | ||
692 | pfkey_ident->sadb_ident_len = ident_len; | |
693 | pfkey_ident->sadb_ident_exttype = exttype; | |
694 | pfkey_ident->sadb_ident_type = ident_type; | |
695 | pfkey_ident->sadb_ident_reserved = 0; | |
696 | pfkey_ident->sadb_ident_id = ident_id; | |
697 | memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), | |
698 | ident_string, | |
699 | data_len); | |
700 | ||
701 | errlab: | |
702 | return error; | |
703 | } | |
704 | ||
705 | int | |
706 | pfkey_sens_build(struct sadb_ext** pfkey_ext, | |
707 | uint32_t dpd, | |
708 | uint8_t sens_level, | |
709 | uint8_t sens_len, | |
710 | uint64_t* sens_bitmap, | |
711 | uint8_t integ_level, | |
712 | uint8_t integ_len, | |
713 | uint64_t* integ_bitmap) | |
714 | { | |
715 | int error = 0; | |
716 | struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; | |
717 | int i; | |
718 | uint64_t* bitmap; | |
719 | ||
720 | DEBUGGING( | |
721 | "pfkey_sens_build:\n"); | |
722 | /* sanity checks... */ | |
723 | if (pfkey_sens) { | |
724 | DEBUGGING( | |
725 | "pfkey_sens_build: " | |
726 | "why is pfkey_sens already pointing to something?\n"); | |
727 | SENDERR(EINVAL); | |
728 | } | |
729 | ||
730 | DEBUGGING( | |
731 | "pfkey_sens_build: " | |
732 | "Sorry, I can't build exttype=%d yet.\n", | |
733 | (*pfkey_ext)->sadb_ext_type); | |
734 | SENDERR(EINVAL); /* don't process these yet */ | |
735 | ||
736 | pfkey_sens = (struct sadb_sens*) | |
737 | MALLOC(sizeof(struct sadb_sens) + | |
738 | (sens_len + integ_len) * sizeof(uint64_t)); | |
739 | *pfkey_ext = (struct sadb_ext*)pfkey_sens; | |
740 | ||
741 | if (pfkey_sens == NULL) { | |
742 | DEBUGGING( | |
743 | "pfkey_sens_build: " | |
744 | "memory allocation failed\n"); | |
745 | SENDERR(ENOMEM); | |
746 | } | |
747 | memset(pfkey_sens, | |
748 | 0, | |
749 | sizeof(struct sadb_sens) + | |
750 | (sens_len + integ_len) * sizeof(uint64_t)); | |
751 | ||
752 | pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + | |
753 | (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; | |
754 | pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; | |
755 | pfkey_sens->sadb_sens_dpd = dpd; | |
756 | pfkey_sens->sadb_sens_sens_level = sens_level; | |
757 | pfkey_sens->sadb_sens_sens_len = sens_len; | |
758 | pfkey_sens->sadb_sens_integ_level = integ_level; | |
759 | pfkey_sens->sadb_sens_integ_len = integ_len; | |
760 | pfkey_sens->sadb_sens_reserved = 0; | |
761 | ||
762 | bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); | |
763 | for (i = 0; i < sens_len; i++) { | |
764 | *bitmap = sens_bitmap[i]; | |
765 | bitmap++; | |
766 | } | |
767 | for (i = 0; i < integ_len; i++) { | |
768 | *bitmap = integ_bitmap[i]; | |
769 | bitmap++; | |
770 | } | |
771 | ||
772 | errlab: | |
773 | return error; | |
774 | } | |
775 | ||
776 | int | |
777 | pfkey_prop_build(struct sadb_ext** pfkey_ext, | |
778 | uint8_t replay, | |
779 | unsigned int comb_num, | |
780 | struct sadb_comb* comb) | |
781 | { | |
782 | int error = 0; | |
783 | int i; | |
784 | struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; | |
785 | struct sadb_comb *combp; | |
786 | ||
787 | DEBUGGING( | |
788 | "pfkey_prop_build:\n"); | |
789 | /* sanity checks... */ | |
790 | if (pfkey_prop) { | |
791 | DEBUGGING( | |
792 | "pfkey_prop_build: " | |
793 | "why is pfkey_prop already pointing to something?\n"); | |
794 | SENDERR(EINVAL); | |
795 | } | |
796 | ||
797 | pfkey_prop = (struct sadb_prop*) | |
798 | MALLOC(sizeof(struct sadb_prop) + | |
799 | comb_num * sizeof(struct sadb_comb)); | |
800 | ||
801 | *pfkey_ext = (struct sadb_ext*)pfkey_prop; | |
802 | ||
803 | if (pfkey_prop == NULL) { | |
804 | DEBUGGING( | |
805 | "pfkey_prop_build: " | |
806 | "memory allocation failed\n"); | |
807 | SENDERR(ENOMEM); | |
808 | } | |
809 | memset(pfkey_prop, | |
810 | 0, | |
811 | sizeof(struct sadb_prop) + | |
812 | comb_num * sizeof(struct sadb_comb)); | |
813 | ||
814 | pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + | |
815 | comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; | |
816 | ||
817 | pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; | |
818 | pfkey_prop->sadb_prop_replay = replay; | |
819 | ||
820 | for (i=0; i<3; i++) { | |
821 | pfkey_prop->sadb_prop_reserved[i] = 0; | |
822 | } | |
823 | ||
824 | combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop)); | |
825 | for (i = 0; i < comb_num; i++) { | |
826 | memcpy (combp, &(comb[i]), sizeof(struct sadb_comb)); | |
827 | combp++; | |
828 | } | |
829 | ||
830 | #if 0 | |
831 | uint8_t sadb_comb_auth; | |
832 | uint8_t sadb_comb_encrypt; | |
833 | uint16_t sadb_comb_flags; | |
834 | uint16_t sadb_comb_auth_minbits; | |
835 | uint16_t sadb_comb_auth_maxbits; | |
836 | uint16_t sadb_comb_encrypt_minbits; | |
837 | uint16_t sadb_comb_encrypt_maxbits; | |
838 | uint32_t sadb_comb_reserved; | |
839 | uint32_t sadb_comb_soft_allocations; | |
840 | uint32_t sadb_comb_hard_allocations; | |
841 | uint64_t sadb_comb_soft_bytes; | |
842 | uint64_t sadb_comb_hard_bytes; | |
843 | uint64_t sadb_comb_soft_addtime; | |
844 | uint64_t sadb_comb_hard_addtime; | |
845 | uint64_t sadb_comb_soft_usetime; | |
846 | uint64_t sadb_comb_hard_usetime; | |
847 | uint32_t sadb_comb_soft_packets; | |
848 | uint32_t sadb_comb_hard_packets; | |
849 | #endif | |
850 | errlab: | |
851 | return error; | |
852 | } | |
853 | ||
854 | int | |
855 | pfkey_supported_build(struct sadb_ext** pfkey_ext, | |
856 | uint16_t exttype, | |
857 | unsigned int alg_num, | |
858 | struct sadb_alg* alg) | |
859 | { | |
860 | int error = 0; | |
861 | unsigned int i; | |
862 | struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; | |
863 | struct sadb_alg *pfkey_alg; | |
864 | ||
865 | /* sanity checks... */ | |
866 | if (pfkey_supported) { | |
867 | DEBUGGING( | |
868 | "pfkey_supported_build: " | |
869 | "why is pfkey_supported already pointing to something?\n"); | |
870 | SENDERR(EINVAL); | |
871 | } | |
872 | ||
873 | if ( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { | |
874 | DEBUGGING( | |
875 | "pfkey_supported_build: " | |
876 | "unsupported extension type=%d.\n", | |
877 | exttype); | |
878 | SENDERR(EINVAL); | |
879 | } | |
880 | ||
881 | pfkey_supported = (struct sadb_supported*) | |
882 | MALLOC(sizeof(struct sadb_supported) + | |
883 | alg_num * sizeof(struct sadb_alg)); | |
884 | ||
885 | *pfkey_ext = (struct sadb_ext*)pfkey_supported; | |
886 | ||
887 | if (pfkey_supported == NULL) { | |
888 | DEBUGGING( | |
889 | "pfkey_supported_build: " | |
890 | "memory allocation failed\n"); | |
891 | SENDERR(ENOMEM); | |
892 | } | |
893 | memset(pfkey_supported, | |
894 | 0, | |
895 | sizeof(struct sadb_supported) + | |
896 | alg_num * | |
897 | sizeof(struct sadb_alg)); | |
898 | ||
899 | pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + | |
900 | alg_num * | |
901 | sizeof(struct sadb_alg)) / | |
902 | IPSEC_PFKEYv2_ALIGN; | |
903 | pfkey_supported->sadb_supported_exttype = exttype; | |
904 | pfkey_supported->sadb_supported_reserved = 0; | |
905 | ||
906 | pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported)); | |
907 | for(i = 0; i < alg_num; i++) { | |
908 | memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); | |
909 | pfkey_alg->sadb_alg_reserved = 0; | |
910 | pfkey_alg++; | |
911 | } | |
912 | ||
913 | #if 0 | |
914 | DEBUGGING( | |
915 | "pfkey_supported_build: " | |
916 | "Sorry, I can't build exttype=%d yet.\n", | |
917 | (*pfkey_ext)->sadb_ext_type); | |
918 | SENDERR(EINVAL); /* don't process these yet */ | |
919 | ||
920 | uint8_t sadb_alg_id; | |
921 | uint8_t sadb_alg_ivlen; | |
922 | uint16_t sadb_alg_minbits; | |
923 | uint16_t sadb_alg_maxbits; | |
924 | uint16_t sadb_alg_reserved; | |
925 | #endif | |
926 | errlab: | |
927 | return error; | |
928 | } | |
929 | ||
930 | int | |
931 | pfkey_spirange_build(struct sadb_ext** pfkey_ext, | |
932 | uint16_t exttype, | |
933 | uint32_t min, /* in network order */ | |
934 | uint32_t max) /* in network order */ | |
935 | { | |
936 | int error = 0; | |
937 | struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; | |
938 | ||
939 | /* sanity checks... */ | |
940 | if (pfkey_spirange) { | |
941 | DEBUGGING( | |
942 | "pfkey_spirange_build: " | |
943 | "why is pfkey_spirange already pointing to something?\n"); | |
944 | SENDERR(EINVAL); | |
945 | } | |
946 | ||
947 | if (ntohl(max) < ntohl(min)) { | |
948 | DEBUGGING( | |
949 | "pfkey_spirange_build: " | |
950 | "minspi=%08x must be < maxspi=%08x.\n", | |
951 | ntohl(min), | |
952 | ntohl(max)); | |
953 | SENDERR(EINVAL); | |
954 | } | |
955 | ||
956 | if (ntohl(min) <= 255) { | |
957 | DEBUGGING( | |
958 | "pfkey_spirange_build: " | |
959 | "minspi=%08x must be > 255.\n", | |
960 | ntohl(min)); | |
961 | SENDERR(EEXIST); | |
962 | } | |
963 | ||
964 | pfkey_spirange = (struct sadb_spirange*) | |
965 | MALLOC(sizeof(struct sadb_spirange)); | |
966 | *pfkey_ext = (struct sadb_ext*)pfkey_spirange; | |
967 | ||
968 | if (pfkey_spirange == NULL) { | |
969 | DEBUGGING( | |
970 | "pfkey_spirange_build: " | |
971 | "memory allocation failed\n"); | |
972 | SENDERR(ENOMEM); | |
973 | } | |
974 | memset(pfkey_spirange, | |
975 | 0, | |
976 | sizeof(struct sadb_spirange)); | |
977 | ||
978 | pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; | |
979 | ||
980 | pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; | |
981 | pfkey_spirange->sadb_spirange_min = min; | |
982 | pfkey_spirange->sadb_spirange_max = max; | |
983 | pfkey_spirange->sadb_spirange_reserved = 0; | |
984 | errlab: | |
985 | return error; | |
986 | } | |
987 | ||
988 | int | |
989 | pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext) | |
990 | { | |
991 | int error = 0; | |
992 | struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; | |
993 | ||
994 | /* sanity checks... */ | |
995 | if (pfkey_x_kmprivate) { | |
996 | DEBUGGING( | |
997 | "pfkey_x_kmprivate_build: " | |
998 | "why is pfkey_x_kmprivate already pointing to something?\n"); | |
999 | SENDERR(EINVAL); | |
1000 | } | |
1001 | ||
1002 | pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; | |
1003 | ||
1004 | DEBUGGING( | |
1005 | "pfkey_x_kmprivate_build: " | |
1006 | "Sorry, I can't build exttype=%d yet.\n", | |
1007 | (*pfkey_ext)->sadb_ext_type); | |
1008 | SENDERR(EINVAL); /* don't process these yet */ | |
1009 | ||
1010 | pfkey_x_kmprivate = (struct sadb_x_kmprivate*) | |
1011 | MALLOC(sizeof(struct sadb_x_kmprivate)); | |
1012 | *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate; | |
1013 | ||
1014 | if (pfkey_x_kmprivate == NULL) { | |
1015 | DEBUGGING( | |
1016 | "pfkey_x_kmprivate_build: " | |
1017 | "memory allocation failed\n"); | |
1018 | SENDERR(ENOMEM); | |
1019 | } | |
1020 | memset(pfkey_x_kmprivate, | |
1021 | 0, | |
1022 | sizeof(struct sadb_x_kmprivate)); | |
1023 | ||
1024 | pfkey_x_kmprivate->sadb_x_kmprivate_len = | |
1025 | sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; | |
1026 | ||
1027 | pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE; | |
1028 | pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; | |
1029 | errlab: | |
1030 | return error; | |
1031 | } | |
1032 | ||
1033 | int | |
1034 | pfkey_x_satype_build(struct sadb_ext** pfkey_ext, | |
1035 | uint8_t satype) | |
1036 | { | |
1037 | int error = 0; | |
1038 | int i; | |
1039 | struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; | |
1040 | ||
1041 | DEBUGGING( | |
1042 | "pfkey_x_satype_build:\n"); | |
1043 | /* sanity checks... */ | |
1044 | if (pfkey_x_satype) { | |
1045 | DEBUGGING( | |
1046 | "pfkey_x_satype_build: " | |
1047 | "why is pfkey_x_satype already pointing to something?\n"); | |
1048 | SENDERR(EINVAL); | |
1049 | } | |
1050 | ||
1051 | if (!satype) { | |
1052 | DEBUGGING( | |
1053 | "pfkey_x_satype_build: " | |
1054 | "SA type not set, must be non-zero.\n"); | |
1055 | SENDERR(EINVAL); | |
1056 | } | |
1057 | ||
1058 | if (satype > SADB_SATYPE_MAX) { | |
1059 | DEBUGGING( | |
1060 | "pfkey_x_satype_build: " | |
1061 | "satype %d > max %d\n", | |
1062 | satype, SADB_SATYPE_MAX); | |
1063 | SENDERR(EINVAL); | |
1064 | } | |
1065 | ||
1066 | pfkey_x_satype = (struct sadb_x_satype*) | |
1067 | MALLOC(sizeof(struct sadb_x_satype)); | |
1068 | ||
1069 | *pfkey_ext = (struct sadb_ext*)pfkey_x_satype; | |
1070 | ||
1071 | if (pfkey_x_satype == NULL) { | |
1072 | DEBUGGING( | |
1073 | "pfkey_x_satype_build: " | |
1074 | "memory allocation failed\n"); | |
1075 | SENDERR(ENOMEM); | |
1076 | } | |
1077 | memset(pfkey_x_satype, | |
1078 | 0, | |
1079 | sizeof(struct sadb_x_satype)); | |
1080 | ||
1081 | pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; | |
1082 | ||
1083 | pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2; | |
1084 | pfkey_x_satype->sadb_x_satype_satype = satype; | |
1085 | for (i=0; i<3; i++) { | |
1086 | pfkey_x_satype->sadb_x_satype_reserved[i] = 0; | |
1087 | } | |
1088 | ||
1089 | errlab: | |
1090 | return error; | |
1091 | } | |
1092 | ||
1093 | int | |
1094 | pfkey_x_debug_build(struct sadb_ext** pfkey_ext, | |
1095 | uint32_t tunnel, | |
1096 | uint32_t netlink, | |
1097 | uint32_t xform, | |
1098 | uint32_t eroute, | |
1099 | uint32_t spi, | |
1100 | uint32_t radij, | |
1101 | uint32_t esp, | |
1102 | uint32_t ah, | |
1103 | uint32_t rcv, | |
1104 | uint32_t pfkey, | |
1105 | uint32_t ipcomp, | |
1106 | uint32_t verbose) | |
1107 | { | |
1108 | int error = 0; | |
1109 | int i; | |
1110 | struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; | |
1111 | ||
1112 | DEBUGGING( | |
1113 | "pfkey_x_debug_build:\n"); | |
1114 | /* sanity checks... */ | |
1115 | if (pfkey_x_debug) { | |
1116 | DEBUGGING( | |
1117 | "pfkey_x_debug_build: " | |
1118 | "why is pfkey_x_debug already pointing to something?\n"); | |
1119 | SENDERR(EINVAL); | |
1120 | } | |
1121 | ||
1122 | DEBUGGING( | |
1123 | "pfkey_x_debug_build: " | |
1124 | "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", | |
1125 | tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); | |
1126 | ||
1127 | pfkey_x_debug = (struct sadb_x_debug*) | |
1128 | MALLOC(sizeof(struct sadb_x_debug)); | |
1129 | *pfkey_ext = (struct sadb_ext*)pfkey_x_debug; | |
1130 | ||
1131 | if (pfkey_x_debug == NULL) { | |
1132 | DEBUGGING( | |
1133 | "pfkey_x_debug_build: " | |
1134 | "memory allocation failed\n"); | |
1135 | SENDERR(ENOMEM); | |
1136 | } | |
1137 | #if 0 | |
1138 | memset(pfkey_x_debug, | |
1139 | 0, | |
1140 | sizeof(struct sadb_x_debug)); | |
1141 | #endif | |
1142 | ||
1143 | pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; | |
1144 | pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG; | |
1145 | ||
1146 | pfkey_x_debug->sadb_x_debug_tunnel = tunnel; | |
1147 | pfkey_x_debug->sadb_x_debug_netlink = netlink; | |
1148 | pfkey_x_debug->sadb_x_debug_xform = xform; | |
1149 | pfkey_x_debug->sadb_x_debug_eroute = eroute; | |
1150 | pfkey_x_debug->sadb_x_debug_spi = spi; | |
1151 | pfkey_x_debug->sadb_x_debug_radij = radij; | |
1152 | pfkey_x_debug->sadb_x_debug_esp = esp; | |
1153 | pfkey_x_debug->sadb_x_debug_ah = ah; | |
1154 | pfkey_x_debug->sadb_x_debug_rcv = rcv; | |
1155 | pfkey_x_debug->sadb_x_debug_pfkey = pfkey; | |
1156 | pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; | |
1157 | pfkey_x_debug->sadb_x_debug_verbose = verbose; | |
1158 | ||
1159 | for (i=0; i<4; i++) { | |
1160 | pfkey_x_debug->sadb_x_debug_reserved[i] = 0; | |
1161 | } | |
1162 | ||
1163 | errlab: | |
1164 | return error; | |
1165 | } | |
1166 | ||
1167 | #ifdef NAT_TRAVERSAL | |
1168 | int | |
1169 | pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext, | |
1170 | uint8_t type) | |
1171 | { | |
1172 | int error = 0; | |
1173 | int i; | |
1174 | struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; | |
1175 | ||
1176 | DEBUGGING( | |
1177 | "pfkey_x_nat_t_type_build:\n"); | |
1178 | /* sanity checks... */ | |
1179 | if (pfkey_x_nat_t_type) { | |
1180 | DEBUGGING( | |
1181 | "pfkey_x_nat_t_type_build: " | |
1182 | "why is pfkey_x_nat_t_type already pointing to something?\n"); | |
1183 | SENDERR(EINVAL); | |
1184 | } | |
1185 | ||
1186 | DEBUGGING( | |
1187 | "pfkey_x_nat_t_type_build: " | |
1188 | "type=%d\n", type); | |
1189 | ||
1190 | pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) | |
1191 | MALLOC(sizeof(struct sadb_x_nat_t_type)); | |
1192 | ||
1193 | *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type; | |
1194 | if (pfkey_x_nat_t_type == NULL) { | |
1195 | DEBUGGING( | |
1196 | "pfkey_x_nat_t_type_build: " | |
1197 | "memory allocation failed\n"); | |
1198 | SENDERR(ENOMEM); | |
1199 | } | |
1200 | ||
1201 | pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; | |
1202 | pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; | |
1203 | pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; | |
1204 | for (i=0; i<3; i++) { | |
1205 | pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; | |
1206 | } | |
1207 | ||
1208 | errlab: | |
1209 | return error; | |
1210 | } | |
1211 | int | |
1212 | pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext, | |
1213 | uint16_t exttype, | |
1214 | uint16_t port) | |
1215 | { | |
1216 | int error = 0; | |
1217 | struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; | |
1218 | ||
1219 | DEBUGGING( | |
1220 | "pfkey_x_nat_t_port_build:\n"); | |
1221 | /* sanity checks... */ | |
1222 | if (pfkey_x_nat_t_port) { | |
1223 | DEBUGGING( | |
1224 | "pfkey_x_nat_t_port_build: " | |
1225 | "why is pfkey_x_nat_t_port already pointing to something?\n"); | |
1226 | SENDERR(EINVAL); | |
1227 | } | |
1228 | ||
1229 | switch (exttype) { | |
1230 | case SADB_X_EXT_NAT_T_SPORT: | |
1231 | case SADB_X_EXT_NAT_T_DPORT: | |
1232 | break; | |
1233 | default: | |
1234 | DEBUGGING( | |
1235 | "pfkey_nat_t_port_build: " | |
1236 | "unrecognised ext_type=%d.\n", | |
1237 | exttype); | |
1238 | SENDERR(EINVAL); | |
1239 | } | |
1240 | ||
1241 | DEBUGGING( | |
1242 | "pfkey_x_nat_t_port_build: " | |
1243 | "ext=%d, port=%d\n", exttype, port); | |
1244 | ||
1245 | pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) | |
1246 | MALLOC(sizeof(struct sadb_x_nat_t_port)); | |
1247 | *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port; | |
1248 | ||
1249 | if (pfkey_x_nat_t_port == NULL) { | |
1250 | DEBUGGING( | |
1251 | "pfkey_x_nat_t_port_build: " | |
1252 | "memory allocation failed\n"); | |
1253 | SENDERR(ENOMEM); | |
1254 | } | |
1255 | ||
1256 | pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; | |
1257 | pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; | |
1258 | pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; | |
1259 | pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; | |
1260 | ||
1261 | errlab: | |
1262 | return error; | |
1263 | } | |
1264 | #endif | |
1265 | ||
1266 | int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, | |
1267 | uint8_t protocol) | |
1268 | { | |
1269 | int error = 0; | |
1270 | struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; | |
1271 | DEBUGGING("pfkey_x_protocol_build: protocol=%u\n", protocol); | |
1272 | /* sanity checks... */ | |
1273 | if (p != 0) { | |
1274 | DEBUGGING("pfkey_x_protocol_build: bogus protocol pointer\n"); | |
1275 | SENDERR(EINVAL); | |
1276 | } | |
1277 | if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { | |
1278 | DEBUGGING("pfkey_build: memory allocation failed\n"); | |
1279 | SENDERR(ENOMEM); | |
1280 | } | |
1281 | *pfkey_ext = (struct sadb_ext *)p; | |
1282 | p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t); | |
1283 | p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL; | |
1284 | p->sadb_protocol_proto = protocol; | |
1285 | p->sadb_protocol_flags = 0; | |
1286 | p->sadb_protocol_reserved2 = 0; | |
1287 | errlab: | |
1288 | return error; | |
1289 | } | |
1290 | ||
1291 | ||
1292 | #if I_DONT_THINK_THIS_WILL_BE_USEFUL | |
1293 | int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*) | |
1294 | = | |
1295 | { | |
1296 | NULL, /* pfkey_msg_build, */ | |
1297 | pfkey_sa_build, | |
1298 | pfkey_lifetime_build, | |
1299 | pfkey_lifetime_build, | |
1300 | pfkey_lifetime_build, | |
1301 | pfkey_address_build, | |
1302 | pfkey_address_build, | |
1303 | pfkey_address_build, | |
1304 | pfkey_key_build, | |
1305 | pfkey_key_build, | |
1306 | pfkey_ident_build, | |
1307 | pfkey_ident_build, | |
1308 | pfkey_sens_build, | |
1309 | pfkey_prop_build, | |
1310 | pfkey_supported_build, | |
1311 | pfkey_supported_build, | |
1312 | pfkey_spirange_build, | |
1313 | pfkey_x_kmprivate_build, | |
1314 | pfkey_x_satype_build, | |
1315 | pfkey_sa_build, | |
1316 | pfkey_address_build, | |
1317 | pfkey_address_build, | |
1318 | pfkey_address_build, | |
1319 | pfkey_address_build, | |
1320 | pfkey_address_build, | |
1321 | pfkey_x_ext_debug_build | |
1322 | }; | |
1323 | #endif | |
1324 | ||
1325 | int | |
1326 | pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) | |
1327 | { | |
1328 | int error = 0; | |
1329 | unsigned ext; | |
1330 | unsigned total_size; | |
1331 | struct sadb_ext *pfkey_ext; | |
1332 | int extensions_seen = 0; | |
1333 | struct sadb_ext *extensions_check[SADB_EXT_MAX + 1]; | |
1334 | ||
1335 | if (!extensions[0]) { | |
1336 | DEBUGGING( | |
1337 | "pfkey_msg_build: " | |
1338 | "extensions[0] must be specified (struct sadb_msg).\n"); | |
1339 | SENDERR(EINVAL); | |
1340 | } | |
1341 | ||
1342 | total_size = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; | |
1343 | for (ext = 1; ext <= SADB_EXT_MAX; ext++) { | |
1344 | if(extensions[ext]) { | |
1345 | total_size += (extensions[ext])->sadb_ext_len; | |
1346 | } | |
1347 | } | |
1348 | ||
1349 | if (!(*pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN))) { | |
1350 | DEBUGGING( | |
1351 | "pfkey_msg_build: " | |
1352 | "memory allocation failed\n"); | |
1353 | SENDERR(ENOMEM); | |
1354 | } | |
1355 | ||
1356 | DEBUGGING( | |
1357 | "pfkey_msg_build: " | |
1358 | "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n", | |
1359 | *pfkey_msg, | |
1360 | (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN), | |
1361 | &(extensions[0])); | |
1362 | memcpy(*pfkey_msg, | |
1363 | extensions[0], | |
1364 | sizeof(struct sadb_msg)); | |
1365 | (*pfkey_msg)->sadb_msg_len = total_size; | |
1366 | (*pfkey_msg)->sadb_msg_reserved = 0; | |
1367 | extensions_seen = 1 ; | |
1368 | ||
1369 | pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); | |
1370 | ||
1371 | for (ext = 1; ext <= SADB_EXT_MAX; ext++) { | |
1372 | /* copy from extension[ext] to buffer */ | |
1373 | if (extensions[ext]) { | |
1374 | /* Is this type of extension permitted for this type of message? */ | |
1375 | if (!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] & | |
1376 | 1<<ext)) { | |
1377 | DEBUGGING( | |
1378 | "pfkey_msg_build: " | |
1379 | "ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n", | |
1380 | ext, | |
1381 | extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], | |
1382 | 1<<ext); | |
1383 | SENDERR(EINVAL); | |
1384 | } | |
1385 | DEBUGGING( | |
1386 | "pfkey_msg_build: " | |
1387 | "copying %lu bytes from extensions[%u]=0p%p to=0p%p\n", | |
1388 | (unsigned long)(extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN), | |
1389 | ext, | |
1390 | extensions[ext], | |
1391 | pfkey_ext); | |
1392 | memcpy(pfkey_ext, | |
1393 | extensions[ext], | |
1394 | (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); | |
1395 | { | |
1396 | char *pfkey_ext_c = (char *)pfkey_ext; | |
1397 | ||
1398 | pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; | |
1399 | pfkey_ext = (struct sadb_ext *)pfkey_ext_c; | |
1400 | } | |
1401 | /* Mark that we have seen this extension and remember the header location */ | |
1402 | extensions_seen |= ( 1 << ext ); | |
1403 | } | |
1404 | } | |
1405 | ||
1406 | /* check required extensions */ | |
1407 | DEBUGGING( | |
1408 | "pfkey_msg_build: " | |
1409 | "extensions permitted=%08x, seen=%08x, required=%08x.\n", | |
1410 | extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type], | |
1411 | extensions_seen, | |
1412 | extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]); | |
1413 | ||
1414 | if ((extensions_seen & | |
1415 | extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) != | |
1416 | extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) { | |
1417 | DEBUGGING( | |
1418 | "pfkey_msg_build: " | |
1419 | "required extensions missing:%08x.\n", | |
1420 | extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] - | |
1421 | (extensions_seen & | |
1422 | extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) ); | |
1423 | SENDERR(EINVAL); | |
1424 | } | |
1425 | ||
1426 | error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir); | |
1427 | if (error) { | |
1428 | DEBUGGING( | |
1429 | "pfkey_msg_build: " | |
1430 | "Trouble parsing newly built pfkey message, error=%d.\n", | |
1431 | error); | |
1432 | SENDERR(-error); | |
1433 | } | |
1434 | ||
1435 | errlab: | |
1436 | ||
1437 | return error; | |
1438 | } |