2 * Copyright (c) 2008, 2012, 2013 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/queue.h>
35 #include "ike_session.h"
36 #include "isakmp_var.h"
37 #include "isakmp_ident.h"
38 #include "isakmp_agg.h"
39 #include "isakmp_quick.h"
40 #include "isakmp_inf.h"
41 #include "vpn_control_var.h"
47 fsm_set_state(int *var
, int state
)
50 plog(ASL_LEVEL_DEBUG
, "****** state changed to: %s\n", s_isakmp_state(0, 0, state
));
54 //================================
55 // Version Agnostic Events
56 //================================
58 fsm_api_handle_connect (struct sockaddr_storage
*remote
, const int connect_mode
)
65 fsm_api_handle_disconnect (struct sockaddr_storage
*remote
, const char *reason
)
72 fsm_pfkey_handle_acquire (phase2_handle_t
*iph2
)
79 fsm_pfkey_getspi_complete (phase2_handle_t
*iph2
)
85 fsm_isakmp_initial_pkt (vchar_t
*pkt
, struct sockaddr_storage
*local
, struct sockaddr_storage
*remote
)
91 //================================
93 //================================
96 fsm_ikev1_phase1_process_payloads (phase1_handle_t
*iph1
, vchar_t
*msg
)
101 struct timeval start
, end
;
103 gettimeofday(&start
, NULL
);
106 switch (iph1
->status
) {
107 case IKEV1_STATE_PHASE1_ESTABLISHED
:
108 return 0; // ignore - already established
110 case IKEV1_STATE_IDENT_I_MSG1SENT
:
111 error
= ident_i2recv(iph1
, msg
);
114 case IKEV1_STATE_IDENT_I_MSG3SENT
:
115 error
= ident_i4recv(iph1
, msg
);
118 case IKEV1_STATE_IDENT_I_MSG5SENT
:
119 error
= ident_i6recv(iph1
, msg
);
122 case IKEV1_STATE_IDENT_R_START
:
123 error
= ident_r1recv(iph1
, msg
);
125 plog(ASL_LEVEL_ERR
, "failed to pre-process packet.\n");
130 case IKEV1_STATE_IDENT_R_MSG2SENT
:
131 error
= ident_r3recv(iph1
, msg
);
134 case IKEV1_STATE_IDENT_R_MSG4SENT
:
135 error
= ident_r5recv(iph1
, msg
);
138 case IKEV1_STATE_AGG_R_START
:
139 error
= agg_r1recv(iph1
, msg
);
141 plog(ASL_LEVEL_ERR
, "failed to pre-process packet.\n");
146 case IKEV1_STATE_AGG_I_MSG1SENT
:
147 error
= agg_i2recv(iph1
, msg
);
150 case IKEV1_STATE_AGG_R_MSG2SENT
:
151 error
= agg_r3recv(iph1
, msg
);
160 return 0; // ignore error and keep phase 1 handle
162 VPTRINIT(iph1
->sendbuf
);
163 /* turn off schedule */
164 SCHED_KILL(iph1
->scr
);
167 plog(ASL_LEVEL_DEBUG
, "===\n");
168 if ((error
= fsm_ikev1_phase1_send_response(iph1
, msg
))) {
169 plog(ASL_LEVEL_ERR
, "failed to process packet.\n");
174 gettimeofday(&end
, NULL
);
175 syslog(LOG_NOTICE
, "%s(%s): %8.6f",
176 "Phase 1", s_isakmp_state(iph1
->etype
, iph1
->side
, iph1
->status
),
177 timedelta(&start
, &end
));
179 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
))
180 ikev1_phase1_established(iph1
);
185 plog(ASL_LEVEL_ERR
, "Phase 1 negotiation failed.\n");
186 ike_session_unlink_phase1(iph1
);
193 fsm_ikev1_phase1_send_response(phase1_handle_t
*iph1
, vchar_t
*msg
)
198 switch (iph1
->status
) {
199 case IKEV1_STATE_IDENT_I_START
:
200 error
= ident_i1send(iph1
, msg
);
203 case IKEV1_STATE_IDENT_I_MSG2RCVD
:
204 error
= ident_i3send(iph1
, msg
);
207 case IKEV1_STATE_IDENT_I_MSG4RCVD
:
208 error
= ident_i5send(iph1
, msg
);
211 case IKEV1_STATE_IDENT_I_MSG6RCVD
:
212 error
= ident_ifinalize(iph1
, msg
);
215 case IKEV1_STATE_IDENT_R_MSG1RCVD
:
216 error
= ident_r2send(iph1
, msg
);
219 case IKEV1_STATE_IDENT_R_MSG3RCVD
:
220 error
= ident_r4send(iph1
, msg
);
223 case IKEV1_STATE_IDENT_R_MSG5RCVD
:
224 error
= ident_r6send(iph1
, msg
);
227 case IKEV1_STATE_AGG_I_START
:
228 error
= agg_i1send(iph1
, msg
);
231 case IKEV1_STATE_AGG_I_MSG2RCVD
:
232 error
= agg_i3send(iph1
, msg
);
235 case IKEV1_STATE_AGG_R_MSG1RCVD
:
236 error
= agg_r2send(iph1
, msg
);
239 case IKEV1_STATE_AGG_R_MSG3RCVD
:
240 error
= agg_rfinalize(iph1
, msg
);
250 vpncontrol_notify_ike_failed(error
, FROM_LOCAL
, iph1_get_remote_v4_address(iph1
), 0, NULL
);
257 fsm_ikev1_phase2_process_payloads (phase2_handle_t
*iph2
, vchar_t
*msg
)
262 struct timeval start
, end
;
264 gettimeofday(&start
, NULL
);
267 switch (iph2
->status
) {
268 /* ignore a packet */
269 case IKEV1_STATE_PHASE2_ESTABLISHED
:
270 case IKEV1_STATE_QUICK_I_GETSPISENT
:
271 case IKEV1_STATE_QUICK_R_GETSPISENT
:
274 case IKEV1_STATE_QUICK_I_MSG1SENT
:
275 error
= quick_i2recv(iph2
, msg
);
278 case IKEV1_STATE_QUICK_I_MSG3SENT
:
279 error
= quick_i4recv(iph2
, msg
);
282 case IKEV1_STATE_QUICK_R_START
:
283 error
= quick_r1recv(iph2
, msg
);
286 case IKEV1_STATE_QUICK_R_MSG2SENT
:
287 error
= quick_r3recv(iph2
, msg
);
297 plog(ASL_LEVEL_ERR
, "failed to pre-process packet.\n");
298 if (error
== ISAKMP_INTERNAL_ERROR
)
300 isakmp_info_send_n1(iph2
->ph1
, error
, NULL
);
304 /* when using commit bit, status will be reached here. */
305 //if (iph2->status == PHASE2ST_ADDSA) //%%% BUG FIX - wrong place
308 /* free resend buffer */
309 if (iph2
->sendbuf
== NULL
&& iph2
->status
!= IKEV1_STATE_QUICK_R_MSG1RCVD
) {
311 "no buffer found as sendbuf\n");
315 VPTRINIT(iph2
->sendbuf
);
317 /* turn off schedule */
318 SCHED_KILL(iph2
->scr
);
320 /* when using commit bit, will be finished here - no more packets to send */
321 if (iph2
->status
== IKEV1_STATE_QUICK_I_ADDSA
)
324 error
= fsm_ikev1_phase2_send_response(iph2
, msg
);
326 plog(ASL_LEVEL_ERR
, "failed to process packet.\n");
331 gettimeofday(&end
, NULL
);
332 syslog(LOG_NOTICE
, "%s(%s): %8.6f",
334 s_isakmp_state(ISAKMP_ETYPE_QUICK
, iph2
->side
, iph2
->status
),
335 timedelta(&start
, &end
));
341 plog(ASL_LEVEL_ERR
, "Phase 2 negotiation failed.\n");
342 ike_session_unlink_phase2(iph2
);
348 fsm_ikev1_phase2_send_response(phase2_handle_t
*iph2
, vchar_t
*msg
)
353 switch (iph2
->status
) {
354 case IKEV1_STATE_QUICK_R_MSG1RCVD
:
355 error
= quick_rprep(iph2
, msg
);
358 case IKEV1_STATE_QUICK_I_GETSPIDONE
:
359 error
= quick_i1send(iph2
, msg
);
362 case IKEV1_STATE_QUICK_I_MSG2RCVD
:
363 error
= quick_i3send(iph2
, msg
);
366 case IKEV1_STATE_QUICK_R_GETSPIDONE
:
367 error
= quick_r2send(iph2
, msg
);
370 case IKEV1_STATE_QUICK_R_MSG3RCVD
:
371 error
= quick_r4send(iph2
, msg
);
374 case IKEV1_STATE_QUICK_R_COMMIT
:
375 error
= quick_rfinalize(iph2
, msg
);