]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/vpn.c
ipsec-317.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / vpn.c
1 /*
2 * Copyright (c) 2007 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
25 * All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. Neither the name of the project nor the names of its contributors
36 * may be used to endorse or promote products derived from this software
37 * without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 */
51
52 #include "config.h"
53
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <sys/socket.h>
57 #include <sys/signal.h>
58 #include <sys/stat.h>
59 #include <sys/un.h>
60
61 #include <net/pfkeyv2.h>
62
63 #include <netinet/in.h>
64 #ifndef HAVE_NETINET6_IPSEC
65 #include <netinet/ipsec.h>
66 #else
67 #include <netinet6/ipsec.h>
68 #endif
69
70
71 #include <stdlib.h>
72 #include <stdio.h>
73 #include <string.h>
74 #include <errno.h>
75 #include <netdb.h>
76 #ifdef HAVE_UNISTD_H
77 #include <unistd.h>
78 #endif
79
80 #include "var.h"
81 #include "misc.h"
82 #include "vmbuf.h"
83 #include "plog.h"
84 #include "sockmisc.h"
85 #include "debug.h"
86 #include "handler.h"
87 #include "schedule.h"
88 #include "localconf.h"
89 #include "remoteconf.h"
90 #include "grabmyaddr.h"
91 #include "isakmp_var.h"
92 #include "isakmp.h"
93 #include "oakley.h"
94 #include "pfkey.h"
95 #include "ipsec_doi.h"
96 #include "isakmp_inf.h"
97 #ifdef ENABLE_HYBRID
98 #include "isakmp_cfg.h"
99 #include "isakmp_unity.h"
100 #endif
101 #include "session.h"
102 #include "gcmalloc.h"
103 #include "sainfo.h"
104 #include "ipsec_doi.h"
105 #include "nattraversal.h"
106 #include "fsm.h"
107
108 #include "vpn_control.h"
109 #include "vpn_control_var.h"
110 #include "strnames.h"
111 #include "ike_session.h"
112 #include "ipsecMessageTracer.h"
113
114
115 static int vpn_get_ph2pfs (phase1_handle_t *);
116
117 int
118 vpn_connect(struct bound_addr *srv, int oper)
119 {
120 int error = -1;
121 struct sockaddr_storage *dst;
122 struct remoteconf *rmconf;
123 struct sockaddr_storage *remote = NULL;
124 struct sockaddr_storage *local = NULL;
125 u_int16_t port;
126
127 dst = racoon_calloc(1, sizeof(struct sockaddr_storage)); // this should come from the bound_addr parameter
128 if (dst == NULL)
129 goto out;
130 ((struct sockaddr_in *)(dst))->sin_len = sizeof(struct sockaddr_in);
131 ((struct sockaddr_in *)(dst))->sin_family = AF_INET;
132 ((struct sockaddr_in *)(dst))->sin_port = PORT_ISAKMP;
133 ((struct sockaddr_in *)(dst))->sin_addr.s_addr = srv->address;
134
135 /* find appropreate configuration */
136 rmconf = getrmconf(dst);
137 if (rmconf == NULL) {
138 plog(ASL_LEVEL_ERR,
139 "no configuration found "
140 "for %s\n", saddrwop2str((struct sockaddr *)dst));
141 goto out1;
142 }
143
144 /*
145 * Find the source address
146 */
147 if (rmconf->forced_local != NULL) {
148 if ((local = dupsaddr(rmconf->forced_local)) == NULL) {
149 plog(ASL_LEVEL_ERR, "failed to duplicate local address\n");
150 goto out1;
151 }
152 } else if ((local = getlocaladdr((struct sockaddr *)dst)) == NULL) {
153 plog(ASL_LEVEL_ERR, "cannot get local address\n");
154 goto out1;
155 }
156
157 if (srv->nat64_prefix.length > 0) {
158 memset(dst, 0, sizeof(*dst));
159 ((struct sockaddr_in6 *)(dst))->sin6_len = sizeof(struct sockaddr_in6);
160 ((struct sockaddr_in6 *)(dst))->sin6_family = AF_INET6;
161 ((struct sockaddr_in6 *)(dst))->sin6_port = PORT_ISAKMP;
162 nw_nat64_synthesize_v6(&srv->nat64_prefix, (struct in_addr *)&srv->address, &((struct sockaddr_in6 *)(dst))->sin6_addr);
163 }
164
165 /* get remote IP address and port number. */
166 if ((remote = dupsaddr(dst)) == NULL) {
167 plog(ASL_LEVEL_ERR,
168 "failed to duplicate address\n");
169 goto out1;
170 }
171
172 switch (remote->ss_family) {
173 case AF_INET:
174 ((struct sockaddr_in *)remote)->sin_port =
175 ((struct sockaddr_in *)rmconf->remote)->sin_port;
176 break;
177 #ifdef INET6
178 case AF_INET6:
179 ((struct sockaddr_in6 *)remote)->sin6_port =
180 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
181 break;
182 #endif
183 default:
184 plog(ASL_LEVEL_ERR,
185 "invalid family: %d\n",
186 remote->ss_family);
187 goto out1;
188 break;
189 }
190
191 port = ntohs(getmyaddrsport(local));
192 if (set_port(local, port) == NULL)
193 goto out1;
194
195 plog(ASL_LEVEL_NOTICE,
196 "accept a request to establish IKE-SA: "
197 "%s\n", saddrwop2str((struct sockaddr *)remote));
198
199 IPSECLOGASLMSG("IPSec connecting to server %s\n",
200 saddrwop2str((struct sockaddr *)remote));
201 if (ikev1_ph1begin_i(NULL, rmconf, remote, local, oper, &srv->nat64_prefix) < 0)
202 goto out1;
203 error = 0;
204
205 out1:
206 if (dst != NULL)
207 racoon_free(dst);
208 if (local != NULL)
209 racoon_free(local);
210 if (remote != NULL)
211 racoon_free(remote);
212 out:
213
214 return error;
215 }
216
217 int
218 vpn_disconnect(struct bound_addr *srv, const char *reason)
219 {
220 union { // Wcast-align fix - force alignment
221 struct sockaddr_storage ss;
222 struct sockaddr_in saddr;
223 } u;
224
225 bzero(&u.saddr, sizeof(u.saddr));
226 u.saddr.sin_len = sizeof(u.saddr);
227 u.saddr.sin_addr.s_addr = srv->address;
228 u.saddr.sin_port = 0;
229 u.saddr.sin_family = AF_INET;
230
231 IPSECLOGASLMSG("IPSec disconnecting from server %s\n",
232 saddrwop2str((struct sockaddr *)&u.ss));
233
234 ike_sessions_stopped_by_controller(&u.ss,
235 0,
236 reason);
237 if (ike_session_purgephXbydstaddrwop(&u.ss) > 0) {
238 return 0;
239 } else {
240 return -1;
241 }
242 }
243
244 int
245 vpn_start_ph2(struct bound_addr *addr, struct vpnctl_cmd_start_ph2 *pkt, size_t pkt_len)
246 {
247 struct vpnctl_sa_selector *selector_ptr;
248 struct vpnctl_algo *algo_ptr, *next_algo;
249 int i, j, defklen;
250 struct sainfoalg *new_algo;
251 struct sainfo *new_sainfo = NULL, *check;
252 u_int16_t class, algorithm, keylen;
253 phase1_handle_t *ph1;
254 struct sockaddr_in saddr;
255
256 struct id {
257 u_int8_t type; /* ID Type */
258 u_int8_t proto_id; /* Protocol ID */
259 u_int16_t port; /* Port */
260 u_int32_t addr; /* IPv4 address */
261 u_int32_t mask;
262 } *id_ptr;
263
264 /* verify ph1 exists */
265 bzero(&saddr, sizeof(saddr));
266 saddr.sin_len = sizeof(saddr);
267 saddr.sin_addr.s_addr = addr->address;
268 saddr.sin_port = 0;
269 saddr.sin_family = AF_INET;
270 ph1 = ike_session_getph1bydstaddrwop(NULL, ALIGNED_CAST(struct sockaddr_storage *)(&saddr));
271 if (ph1 == NULL) {
272 plog(ASL_LEVEL_ERR,
273 "Cannot start Phase 2 - no Phase 1 found.\n");
274 return -1;
275 }
276 if (!FSM_STATE_IS_ESTABLISHED(ph1->status)) {
277 plog(ASL_LEVEL_ERR,
278 "Cannot start Phase 2 - Phase 1 not established.\n");
279 return -1;
280 }
281
282 selector_ptr = (struct vpnctl_sa_selector *)(pkt + 1);
283 size_t total_selector_len = (sizeof(struct vpnctl_sa_selector) * ntohs(pkt->selector_count));
284 if (pkt_len < (sizeof(struct vpnctl_cmd_start_ph2) + total_selector_len)) {
285 plog(ASL_LEVEL_ERR, "invalid length for vpn ph2 selector - len=%ld - expected %ld\n", pkt_len, (sizeof(struct vpnctl_cmd_start_ph2) + total_selector_len));
286 return -1;
287 }
288
289 algo_ptr = (struct vpnctl_algo *)(selector_ptr + ntohs(pkt->selector_count));
290 size_t total_algo_len = (sizeof(struct vpnctl_algo) * ntohs(pkt->algo_count));
291 if (pkt_len < (sizeof(struct vpnctl_cmd_start_ph2) + total_selector_len + total_algo_len)) {
292 plog(ASL_LEVEL_ERR, "invalid length for vpn ph2 algo - len=%ld - expected %ld\n", pkt_len, (sizeof(struct vpnctl_cmd_start_ph2) + total_selector_len + total_algo_len));
293 return -1;
294 }
295
296 for (i = 0; i < ntohs(pkt->selector_count); i++, selector_ptr++) {
297 new_sainfo = create_sainfo();
298 if (new_sainfo == NULL) {
299 plog(ASL_LEVEL_ERR,
300 "Unable to allocate sainfo struct.\n");
301 goto fail;
302 }
303
304 if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
305 new_sainfo->idsrc = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
306 else
307 new_sainfo->idsrc = vmalloc(sizeof(struct id));
308 if (new_sainfo->idsrc == NULL) {
309 plog(ASL_LEVEL_ERR,
310 "Unable to allocate id struct.\n");
311 goto fail;
312 }
313 if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
314 new_sainfo->iddst = vmalloc(sizeof(struct id) - sizeof(u_int32_t));
315 else
316 new_sainfo->iddst = vmalloc(sizeof(struct id));
317 if (new_sainfo->iddst == NULL) {
318 plog(ASL_LEVEL_ERR,
319 "Unable to allocate id struct.\n");
320 goto fail;
321 }
322
323 id_ptr = ALIGNED_CAST(struct id *)new_sainfo->idsrc->v;
324 if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF)
325 id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
326 else {
327 id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
328 id_ptr->mask = selector_ptr->src_tunnel_mask;
329 }
330 id_ptr->addr = selector_ptr->src_tunnel_address;
331 id_ptr->port = selector_ptr->src_tunnel_port;
332 id_ptr->proto_id = selector_ptr->ul_protocol;
333
334 id_ptr = ALIGNED_CAST(struct id *)new_sainfo->iddst->v;
335 if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF)
336 id_ptr->type = IPSECDOI_ID_IPV4_ADDR;
337 else {
338 id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
339 id_ptr->mask = selector_ptr->dst_tunnel_mask;
340 }
341 id_ptr->addr = selector_ptr->dst_tunnel_address;
342 id_ptr->port = selector_ptr->dst_tunnel_port;
343 id_ptr->proto_id = selector_ptr->ul_protocol;
344
345 new_sainfo->dynamic = addr->address;
346 new_sainfo->lifetime = ntohl(pkt->lifetime);
347
348 if (ntohs(pkt->pfs_group) != 0) {
349 new_sainfo->pfs_group = algtype2doi(algclass_isakmp_dh, ntohs(pkt->pfs_group));
350 if (new_sainfo->pfs_group == -1) {
351 plog(ASL_LEVEL_ERR, "Invalid dh group specified\n");
352 goto fail;
353 }
354 }
355 for (j = 0, next_algo = algo_ptr; j < ntohs(pkt->algo_count); j++, next_algo++) {
356
357 new_algo = newsainfoalg();
358 if (new_algo == NULL) {
359 plog(ASL_LEVEL_ERR,
360 "Failed to allocate algorithm structure\n");
361 goto fail;
362 }
363
364 class = ntohs(next_algo->algo_class);
365 algorithm = ntohs(next_algo->algo);
366 keylen = ntohs(next_algo->key_len);
367
368 new_algo->alg = algtype2doi(class, algorithm);
369 if (new_algo->alg == -1) {
370 plog(ASL_LEVEL_ERR, "Algorithm mismatched\n");
371 racoon_free(new_algo);
372 goto fail;
373 }
374
375 defklen = default_keylen(class, algorithm);
376 if (defklen == 0) {
377 if (keylen) {
378 plog(ASL_LEVEL_ERR, "keylen not allowed\n");
379 racoon_free(new_algo);
380 goto fail;
381 }
382 } else {
383 if (keylen && check_keylen(class, algorithm, keylen) < 0) {
384 plog(ASL_LEVEL_ERR, "invalid keylen %d\n", keylen);
385 racoon_free(new_algo);
386 goto fail;
387 }
388 }
389
390 if (keylen)
391 new_algo->encklen = keylen;
392 else
393 new_algo->encklen = defklen;
394
395 /* check if it's supported algorithm by kernel */
396 if (!(class == algclass_ipsec_auth && algorithm == algtype_non_auth)
397 && pk_checkalg(class, algorithm, new_algo->encklen)) {
398 int a = algclass2doi(class);
399 int b = new_algo->alg;
400 if (a == IPSECDOI_ATTR_AUTH)
401 a = IPSECDOI_PROTO_IPSEC_AH;
402 plog(ASL_LEVEL_ERR,
403 "Algorithm %s not supported by the kernel (missing module?)\n", s_ipsecdoi_trns(a, b));
404 racoon_free(new_algo);
405 goto fail;
406 }
407 inssainfoalg(&new_sainfo->algs[class], new_algo);
408 }
409
410 if (new_sainfo->algs[algclass_ipsec_enc] == 0) {
411 plog(ASL_LEVEL_ERR,
412 "No encryption algorithm at %s\n", sainfo2str(new_sainfo));
413 goto fail;
414 }
415 if (new_sainfo->algs[algclass_ipsec_auth] == 0) {
416 plog(ASL_LEVEL_ERR,
417 "No authentication algorithm at %s\n", sainfo2str(new_sainfo));
418 goto fail;
419 }
420 if (new_sainfo->algs[algclass_ipsec_comp] == 0) {
421 plog(ASL_LEVEL_ERR,
422 "No compression algorithm at %s\n", sainfo2str(new_sainfo));
423 goto fail;
424 }
425
426 /* duplicate check */
427 check = getsainfo(new_sainfo->idsrc, new_sainfo->iddst, new_sainfo->id_i, 0);
428 if (check && (!check->idsrc && !new_sainfo->idsrc)) {
429 plog(ASL_LEVEL_ERR, "Duplicated sainfo: %s\n", sainfo2str(new_sainfo));
430 goto fail;
431 }
432 //plog(ASL_LEVEL_DEBUG, "create sainfo: %s\n", sainfo2str(new_sainfo));
433 inssainfo(new_sainfo);
434 new_sainfo = NULL;
435 }
436
437 return 0;
438
439 fail:
440 if (new_sainfo)
441 release_sainfo(new_sainfo);
442 flushsainfo_dynamic((u_int32_t)addr->address);
443 return -1;
444 }
445
446 static int
447 vpn_get_ph2pfs(phase1_handle_t *ph1)
448 {
449 }
450
451
452 int
453 vpn_get_config(phase1_handle_t *iph1, struct vpnctl_status_phase_change **msg, size_t *msg_size)
454 {
455
456 struct vpnctl_modecfg_params *params;
457 struct myaddrs *myaddr;
458 u_int16_t ifname_len, msize;
459 u_int8_t *cptr;
460
461 *msg = NULL;
462 msize = 0;
463
464 /*if (((struct sockaddr_in *)iph1->local)->sin_family != AF_INET) {
465 plog(ASL_LEVEL_ERR,
466 "IPv6 not supported for mode config.\n");
467 return -1;
468 }*/
469
470 if (iph1->mode_cfg->attr_list == NULL)
471 return 1; /* haven't received configuration yet */
472
473 myaddr = find_myaddr((struct sockaddr *)iph1->local, 0);
474 if (myaddr == NULL) {
475 plog(ASL_LEVEL_ERR,
476 "Unable to find address structure.\n");
477 return -1;
478 }
479
480 msize = sizeof(struct vpnctl_status_phase_change)
481 + sizeof(struct vpnctl_modecfg_params);
482 msize += iph1->mode_cfg->attr_list->l;
483
484 *msg = racoon_calloc(1, msize);
485 if (*msg == NULL) {
486 plog(ASL_LEVEL_ERR,
487 "Failed to allocate space for message.\n");
488 return -1;
489 }
490
491 (*msg)->hdr.flags = htons(VPNCTL_FLAG_MODECFG_USED);
492 params = (struct vpnctl_modecfg_params *)(*msg + 1);
493 if (((struct sockaddr_in *)iph1->local)->sin_family == AF_INET) {
494 params->outer_local_addr = ((struct sockaddr_in *)iph1->local)->sin_addr.s_addr;
495 }
496 params->outer_remote_port = htons(0);
497 params->outer_local_port = htons(0);
498 ifname_len = strlen(myaddr->ifname);
499 memset(&params->ifname, 0, IFNAMSIZ);
500 memcpy(&params->ifname, myaddr->ifname, ifname_len < IFNAMSIZ ? ifname_len : IFNAMSIZ-1);
501 cptr = (u_int8_t *)(params + 1);
502 memcpy(cptr, iph1->mode_cfg->attr_list->v, iph1->mode_cfg->attr_list->l);
503 *msg_size = msize;
504
505 IPSECLOGASLMSG("IPSec Network Configuration established.\n");
506
507 return 0;
508 }
509
510 int
511 vpn_xauth_reply(u_int32_t address, void *attr_list, size_t attr_len)
512 {
513
514 struct isakmp_pl_attr *reply;
515 void* attr_ptr;
516 vchar_t *payload = NULL;
517 phase1_handle_t *iph1;
518 struct sockaddr_in saddr;
519 int error = -1;
520 int tlen = attr_len;
521 struct isakmp_data *attr;
522 char *dataptr = (char *)attr_list;
523
524 /* find ph1 */
525 bzero(&saddr, sizeof(saddr));
526 saddr.sin_len = sizeof(saddr);
527 saddr.sin_addr.s_addr = address;
528 saddr.sin_port = 0;
529 saddr.sin_family = AF_INET;
530 iph1 = ike_session_getph1bydstaddrwop(NULL, ALIGNED_CAST(struct sockaddr_storage *)(&saddr));
531 if (iph1 == NULL) {
532 plog(ASL_LEVEL_ERR,
533 "Cannot reply to xauth request - no ph1 found.\n");
534 goto end;
535 }
536
537 if (iph1->xauth_awaiting_userinput == 0) {
538 plog(ASL_LEVEL_ERR, "Received xauth reply data with no xauth reply pending \n");
539 goto end;
540 }
541
542 /* validate attr lengths */
543 while (tlen > 0)
544 {
545 int tlv;
546
547 attr = (struct isakmp_data *)dataptr;
548 tlv = (attr->type & htons(0x8000)) == 0;
549
550 if (tlv) {
551 tlen -= ntohs(attr->lorv);
552 dataptr += ntohs(attr->lorv);
553 }
554 tlen -= sizeof(u_int32_t);
555 dataptr += sizeof(u_int32_t);
556 }
557 if (tlen != 0) {
558 plog(ASL_LEVEL_ERR, "Invalid auth info received from VPN Control socket.\n");
559 goto end;
560 }
561
562 payload = vmalloc(sizeof(struct isakmp_pl_attr) + attr_len);
563 if (payload == NULL) {
564 plog(ASL_LEVEL_ERR, "Cannot allocate memory for xauth reply\n");
565 goto end;
566 }
567 memset(payload->v, 0, sizeof(reply));
568
569 reply = (struct isakmp_pl_attr *)payload->v;
570 reply->h.len = htons(payload->l);
571 reply->type = ISAKMP_CFG_REPLY;
572 reply->id = iph1->pended_xauth_id; /* network byte order */
573 iph1->xauth_awaiting_userinput = 0; /* no longer waiting */
574 attr_ptr = reply + 1;
575 memcpy(attr_ptr, attr_list, attr_len);
576
577 plog(ASL_LEVEL_DEBUG,
578 "Sending MODE_CFG REPLY\n");
579 error = isakmp_cfg_send(iph1, payload,
580 ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, iph1->xauth_awaiting_userinput_msg);
581 VPTRINIT(iph1->xauth_awaiting_userinput_msg);
582 ike_session_stop_xauth_timer(iph1);
583
584 IPSECLOGASLMSG("IPSec Extended Authentication sent.\n");
585
586 end:
587 if (payload)
588 vfree(payload);
589 return error;
590 }
591
592 int
593 vpn_assert(struct sockaddr_storage *src_addr, struct sockaddr_storage *dst_addr)
594 {
595 if (ike_session_assert(src_addr, dst_addr)) {
596 plog(ASL_LEVEL_ERR,
597 "Cannot assert - no matching session.\n");
598 return -1;
599 }
600
601 return 0;
602 }
603