17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (C) 2001-2003 by Darren Reed
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate *
67c478bd9Sstevel@tonic-gate * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT
77c478bd9Sstevel@tonic-gate * code.
8ab25eeb5Syz *
9ab25eeb5Syz * $Id: ip_ipsec_pxy.c,v 2.20.2.7 2005/07/15 21:56:50 darrenr Exp $
10ab25eeb5Syz *
11*33f2fefdSDarren Reed * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
12ab25eeb5Syz * Use is subject to license terms.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #define IPF_IPSEC_PROXY
167c478bd9Sstevel@tonic-gate
17f4b3ec61Sdh typedef struct ifs_ipsecpxy {
18f4b3ec61Sdh frentry_t ipsecfr;
19f4b3ec61Sdh ipftq_t *ipsecnattqe;
20f4b3ec61Sdh ipftq_t *ipsecstatetqe;
21f4b3ec61Sdh char ipsec_buffer[1500];
22f4b3ec61Sdh int ipsec_proxy_init;
23f4b3ec61Sdh int ipsec_proxy_ttl;
24f4b3ec61Sdh } ifs_ipsecpxy_t;
25f4b3ec61Sdh
26f4b3ec61Sdh int ippr_ipsec_init __P((void **, ipf_stack_t *));
27f4b3ec61Sdh void ippr_ipsec_fini __P((void **, ipf_stack_t *));
28f4b3ec61Sdh int ippr_ipsec_new __P((fr_info_t *, ap_session_t *, nat_t *, void *));
29f4b3ec61Sdh void ippr_ipsec_del __P((ap_session_t *, void *, ipf_stack_t *));
30f4b3ec61Sdh int ippr_ipsec_inout __P((fr_info_t *, ap_session_t *, nat_t *, void *));
31f4b3ec61Sdh int ippr_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *, void *));
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate * IPSec application proxy initialization.
357c478bd9Sstevel@tonic-gate */
ippr_ipsec_init(private,ifs)36f4b3ec61Sdh int ippr_ipsec_init(private, ifs)
37f4b3ec61Sdh void **private;
38f4b3ec61Sdh ipf_stack_t *ifs;
397c478bd9Sstevel@tonic-gate {
40f4b3ec61Sdh ifs_ipsecpxy_t *ifsipsec;
41f4b3ec61Sdh
42f4b3ec61Sdh KMALLOC(ifsipsec, ifs_ipsecpxy_t *);
43f4b3ec61Sdh if (ifsipsec == NULL)
447c478bd9Sstevel@tonic-gate return -1;
45f4b3ec61Sdh
46f4b3ec61Sdh bzero((char *)&ifsipsec->ipsecfr, sizeof(ifsipsec->ipsecfr));
47f4b3ec61Sdh ifsipsec->ipsecfr.fr_ref = 1;
48f4b3ec61Sdh ifsipsec->ipsecfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
49f4b3ec61Sdh MUTEX_INIT(&ifsipsec->ipsecfr.fr_lock, "IPsec proxy rule lock");
50f4b3ec61Sdh ifsipsec->ipsec_proxy_init = 1;
51f4b3ec61Sdh ifsipsec->ipsec_proxy_ttl = 60;
52f4b3ec61Sdh
53f4b3ec61Sdh ifsipsec->ipsecnattqe = fr_addtimeoutqueue(&ifs->ifs_nat_utqe, ifsipsec->ipsec_proxy_ttl, ifs);
54f4b3ec61Sdh if (ifsipsec->ipsecnattqe == NULL) {
55f4b3ec61Sdh MUTEX_DESTROY(&ifsipsec->ipsecfr.fr_lock);
56f4b3ec61Sdh KFREE(ifsipsec);
577c478bd9Sstevel@tonic-gate return -1;
587c478bd9Sstevel@tonic-gate }
59f4b3ec61Sdh ifsipsec->ipsecstatetqe = fr_addtimeoutqueue(&ifs->ifs_ips_utqe, ifsipsec->ipsec_proxy_ttl, ifs);
60f4b3ec61Sdh if (ifsipsec->ipsecstatetqe == NULL) {
61f4b3ec61Sdh if (fr_deletetimeoutqueue(ifsipsec->ipsecnattqe) == 0)
62f4b3ec61Sdh fr_freetimeoutqueue(ifsipsec->ipsecnattqe, ifs);
63f4b3ec61Sdh ifsipsec->ipsecnattqe = NULL;
64f4b3ec61Sdh MUTEX_DESTROY(&ifsipsec->ipsecfr.fr_lock);
65f4b3ec61Sdh KFREE(ifsipsec);
66f4b3ec61Sdh return -1;
67f4b3ec61Sdh }
68f4b3ec61Sdh
69f4b3ec61Sdh ifsipsec->ipsecnattqe->ifq_flags |= IFQF_PROXY;
70f4b3ec61Sdh ifsipsec->ipsecstatetqe->ifq_flags |= IFQF_PROXY;
71f4b3ec61Sdh
72f4b3ec61Sdh ifsipsec->ipsecfr.fr_age[0] = ifsipsec->ipsec_proxy_ttl;
73f4b3ec61Sdh ifsipsec->ipsecfr.fr_age[1] = ifsipsec->ipsec_proxy_ttl;
74ab25eeb5Syz
75f4b3ec61Sdh *private = (void *)ifsipsec;
76ab25eeb5Syz
777c478bd9Sstevel@tonic-gate return 0;
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate
ippr_ipsec_fini(private,ifs)81f4b3ec61Sdh void ippr_ipsec_fini(private, ifs)
82f4b3ec61Sdh void **private;
83f4b3ec61Sdh ipf_stack_t *ifs;
847c478bd9Sstevel@tonic-gate {
85f4b3ec61Sdh ifs_ipsecpxy_t *ifsipsec = *((ifs_ipsecpxy_t **)private);
86f4b3ec61Sdh
87f4b3ec61Sdh if (ifsipsec->ipsecnattqe != NULL) {
88f4b3ec61Sdh if (fr_deletetimeoutqueue(ifsipsec->ipsecnattqe) == 0)
89f4b3ec61Sdh fr_freetimeoutqueue(ifsipsec->ipsecnattqe, ifs);
90ab25eeb5Syz }
91f4b3ec61Sdh ifsipsec->ipsecnattqe = NULL;
92f4b3ec61Sdh if (ifsipsec->ipsecstatetqe != NULL) {
93f4b3ec61Sdh if (fr_deletetimeoutqueue(ifsipsec->ipsecstatetqe) == 0)
94f4b3ec61Sdh fr_freetimeoutqueue(ifsipsec->ipsecstatetqe, ifs);
95ab25eeb5Syz }
96f4b3ec61Sdh ifsipsec->ipsecstatetqe = NULL;
977c478bd9Sstevel@tonic-gate
98f4b3ec61Sdh if (ifsipsec->ipsec_proxy_init == 1) {
99f4b3ec61Sdh MUTEX_DESTROY(&ifsipsec->ipsecfr.fr_lock);
100f4b3ec61Sdh ifsipsec->ipsec_proxy_init = 0;
1017c478bd9Sstevel@tonic-gate }
102f4b3ec61Sdh
103f4b3ec61Sdh KFREE(ifsipsec);
104f4b3ec61Sdh *private = NULL;
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * Setup for a new IPSEC proxy.
1107c478bd9Sstevel@tonic-gate */
ippr_ipsec_new(fin,aps,nat,private)111f4b3ec61Sdh int ippr_ipsec_new(fin, aps, nat, private)
1127c478bd9Sstevel@tonic-gate fr_info_t *fin;
1137c478bd9Sstevel@tonic-gate ap_session_t *aps;
1147c478bd9Sstevel@tonic-gate nat_t *nat;
115f4b3ec61Sdh void *private;
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate ipsec_pxy_t *ipsec;
1187c478bd9Sstevel@tonic-gate fr_info_t fi;
1197c478bd9Sstevel@tonic-gate ipnat_t *ipn;
1207c478bd9Sstevel@tonic-gate char *ptr;
121ab25eeb5Syz int p, off, dlen, ttl;
1227c478bd9Sstevel@tonic-gate mb_t *m;
1237c478bd9Sstevel@tonic-gate ip_t *ip;
124f4b3ec61Sdh ipf_stack_t *ifs = fin->fin_ifs;
125f4b3ec61Sdh ifs_ipsecpxy_t *ifsipsec = (ifs_ipsecpxy_t *)private;
1267c478bd9Sstevel@tonic-gate
127ab25eeb5Syz off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
128f4b3ec61Sdh bzero(ifsipsec->ipsec_buffer, sizeof(ifsipsec->ipsec_buffer));
1297c478bd9Sstevel@tonic-gate ip = fin->fin_ip;
1307c478bd9Sstevel@tonic-gate m = fin->fin_m;
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate dlen = M_LEN(m) - off;
1337c478bd9Sstevel@tonic-gate if (dlen < 16)
1347c478bd9Sstevel@tonic-gate return -1;
135f4b3ec61Sdh COPYDATA(m, off, MIN(sizeof(ifsipsec->ipsec_buffer), dlen),
136f4b3ec61Sdh ifsipsec->ipsec_buffer);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (nat_outlookup(fin, 0, IPPROTO_ESP, nat->nat_inip,
1397c478bd9Sstevel@tonic-gate ip->ip_dst) != NULL)
1407c478bd9Sstevel@tonic-gate return -1;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate aps->aps_psiz = sizeof(*ipsec);
1437c478bd9Sstevel@tonic-gate KMALLOCS(aps->aps_data, ipsec_pxy_t *, sizeof(*ipsec));
1447c478bd9Sstevel@tonic-gate if (aps->aps_data == NULL)
1457c478bd9Sstevel@tonic-gate return -1;
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate ipsec = aps->aps_data;
1487c478bd9Sstevel@tonic-gate bzero((char *)ipsec, sizeof(*ipsec));
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /*
1517c478bd9Sstevel@tonic-gate * Create NAT rule against which the tunnel/transport mapping is
1527c478bd9Sstevel@tonic-gate * created. This is required because the current NAT rule does not
1537c478bd9Sstevel@tonic-gate * describe ESP but UDP instead.
1547c478bd9Sstevel@tonic-gate */
1557c478bd9Sstevel@tonic-gate ipn = &ipsec->ipsc_rule;
156f4b3ec61Sdh ttl = IPF_TTLVAL(ifsipsec->ipsecnattqe->ifq_ttl);
157f4b3ec61Sdh ipn->in_tqehead[0] = fr_addtimeoutqueue(&ifs->ifs_nat_utqe, ttl, ifs);
158f4b3ec61Sdh ipn->in_tqehead[1] = fr_addtimeoutqueue(&ifs->ifs_nat_utqe, ttl, ifs);
1597c478bd9Sstevel@tonic-gate ipn->in_ifps[0] = fin->fin_ifp;
1607c478bd9Sstevel@tonic-gate ipn->in_apr = NULL;
1617c478bd9Sstevel@tonic-gate ipn->in_use = 1;
1627c478bd9Sstevel@tonic-gate ipn->in_hits = 1;
163ab25eeb5Syz ipn->in_nip = ntohl(nat->nat_outip.s_addr);
1647c478bd9Sstevel@tonic-gate ipn->in_ippip = 1;
1657c478bd9Sstevel@tonic-gate ipn->in_inip = nat->nat_inip.s_addr;
1667c478bd9Sstevel@tonic-gate ipn->in_inmsk = 0xffffffff;
1677c478bd9Sstevel@tonic-gate ipn->in_outip = fin->fin_saddr;
1687c478bd9Sstevel@tonic-gate ipn->in_outmsk = nat->nat_outip.s_addr;
1697c478bd9Sstevel@tonic-gate ipn->in_srcip = fin->fin_saddr;
1707c478bd9Sstevel@tonic-gate ipn->in_srcmsk = 0xffffffff;
1717c478bd9Sstevel@tonic-gate ipn->in_redir = NAT_MAP;
1727c478bd9Sstevel@tonic-gate bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
1737c478bd9Sstevel@tonic-gate sizeof(ipn->in_ifnames[0]));
1747c478bd9Sstevel@tonic-gate ipn->in_p = IPPROTO_ESP;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate bcopy((char *)fin, (char *)&fi, sizeof(fi));
1777c478bd9Sstevel@tonic-gate fi.fin_fi.fi_p = IPPROTO_ESP;
178f4b3ec61Sdh fi.fin_fr = &ifsipsec->ipsecfr;
1797c478bd9Sstevel@tonic-gate fi.fin_data[0] = 0;
1807c478bd9Sstevel@tonic-gate fi.fin_data[1] = 0;
1817c478bd9Sstevel@tonic-gate p = ip->ip_p;
1827c478bd9Sstevel@tonic-gate ip->ip_p = IPPROTO_ESP;
183ab25eeb5Syz fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
1847c478bd9Sstevel@tonic-gate fi.fin_flx |= FI_IGNORE;
1857c478bd9Sstevel@tonic-gate
186f4b3ec61Sdh ptr = ifsipsec->ipsec_buffer;
1877c478bd9Sstevel@tonic-gate bcopy(ptr, (char *)ipsec->ipsc_icookie, sizeof(ipsec_cookie_t));
1887c478bd9Sstevel@tonic-gate ptr += sizeof(ipsec_cookie_t);
1897c478bd9Sstevel@tonic-gate bcopy(ptr, (char *)ipsec->ipsc_rcookie, sizeof(ipsec_cookie_t));
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate * The responder cookie should only be non-zero if the initiator
1927c478bd9Sstevel@tonic-gate * cookie is non-zero. Therefore, it is safe to assume(!) that the
1937c478bd9Sstevel@tonic-gate * cookies are both set after copying if the responder is non-zero.
1947c478bd9Sstevel@tonic-gate */
1957c478bd9Sstevel@tonic-gate if ((ipsec->ipsc_rcookie[0]|ipsec->ipsc_rcookie[1]) != 0)
1967c478bd9Sstevel@tonic-gate ipsec->ipsc_rckset = 1;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate ipsec->ipsc_nat = nat_new(&fi, ipn, &ipsec->ipsc_nat,
1997c478bd9Sstevel@tonic-gate NAT_SLAVE|SI_WILDP, NAT_OUTBOUND);
2007c478bd9Sstevel@tonic-gate if (ipsec->ipsc_nat != NULL) {
2017c478bd9Sstevel@tonic-gate (void) nat_proto(&fi, ipsec->ipsc_nat, 0);
2027c478bd9Sstevel@tonic-gate nat_update(&fi, ipsec->ipsc_nat, ipn);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate fi.fin_data[0] = 0;
2057c478bd9Sstevel@tonic-gate fi.fin_data[1] = 0;
2067c478bd9Sstevel@tonic-gate ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state,
2077c478bd9Sstevel@tonic-gate SI_WILDP);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate ip->ip_p = p & 0xff;
2107c478bd9Sstevel@tonic-gate return 0;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * For outgoing IKE packets. refresh timeouts for NAT & state entries, if
2167c478bd9Sstevel@tonic-gate * we can. If they have disappeared, recreate them.
2177c478bd9Sstevel@tonic-gate */
ippr_ipsec_inout(fin,aps,nat,private)218f4b3ec61Sdh int ippr_ipsec_inout(fin, aps, nat, private)
2197c478bd9Sstevel@tonic-gate fr_info_t *fin;
2207c478bd9Sstevel@tonic-gate ap_session_t *aps;
2217c478bd9Sstevel@tonic-gate nat_t *nat;
222f4b3ec61Sdh void *private;
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate ipsec_pxy_t *ipsec;
2257c478bd9Sstevel@tonic-gate fr_info_t fi;
2267c478bd9Sstevel@tonic-gate ip_t *ip;
2277c478bd9Sstevel@tonic-gate int p;
228f4b3ec61Sdh ipf_stack_t *ifs = fin->fin_ifs;
229f4b3ec61Sdh ifs_ipsecpxy_t *ifsipsec = (ifs_ipsecpxy_t *)private;
2307c478bd9Sstevel@tonic-gate
231ab25eeb5Syz if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
232ab25eeb5Syz return 0;
233ab25eeb5Syz
234ab25eeb5Syz if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
235ab25eeb5Syz return 0;
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate ipsec = aps->aps_data;
238ab25eeb5Syz
2397c478bd9Sstevel@tonic-gate if (ipsec != NULL) {
240ab25eeb5Syz ip = fin->fin_ip;
241ab25eeb5Syz p = ip->ip_p;
242ab25eeb5Syz
243ab25eeb5Syz if ((ipsec->ipsc_nat == NULL) || (ipsec->ipsc_state == NULL)) {
244ab25eeb5Syz bcopy((char *)fin, (char *)&fi, sizeof(fi));
245ab25eeb5Syz fi.fin_fi.fi_p = IPPROTO_ESP;
246f4b3ec61Sdh fi.fin_fr = &ifsipsec->ipsecfr;
247ab25eeb5Syz fi.fin_data[0] = 0;
248ab25eeb5Syz fi.fin_data[1] = 0;
249ab25eeb5Syz ip->ip_p = IPPROTO_ESP;
250ab25eeb5Syz fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
251ab25eeb5Syz fi.fin_flx |= FI_IGNORE;
252ab25eeb5Syz }
253ab25eeb5Syz
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate * Update NAT timeout/create NAT if missing.
2567c478bd9Sstevel@tonic-gate */
2577c478bd9Sstevel@tonic-gate if (ipsec->ipsc_nat != NULL)
258f4b3ec61Sdh fr_queueback(&ipsec->ipsc_nat->nat_tqe, ifs);
2597c478bd9Sstevel@tonic-gate else {
2607c478bd9Sstevel@tonic-gate ipsec->ipsc_nat = nat_new(&fi, &ipsec->ipsc_rule,
2617c478bd9Sstevel@tonic-gate &ipsec->ipsc_nat,
2627c478bd9Sstevel@tonic-gate NAT_SLAVE|SI_WILDP,
263ab25eeb5Syz nat->nat_dir);
2647c478bd9Sstevel@tonic-gate if (ipsec->ipsc_nat != NULL) {
2657c478bd9Sstevel@tonic-gate (void) nat_proto(&fi, ipsec->ipsc_nat, 0);
2667c478bd9Sstevel@tonic-gate nat_update(&fi, ipsec->ipsc_nat,
2677c478bd9Sstevel@tonic-gate &ipsec->ipsc_rule);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate /*
2727c478bd9Sstevel@tonic-gate * Update state timeout/create state if missing.
2737c478bd9Sstevel@tonic-gate */
274f4b3ec61Sdh READ_ENTER(&ifs->ifs_ipf_state);
2757c478bd9Sstevel@tonic-gate if (ipsec->ipsc_state != NULL) {
276f4b3ec61Sdh fr_queueback(&ipsec->ipsc_state->is_sti, ifs);
2777c478bd9Sstevel@tonic-gate ipsec->ipsc_state->is_die = nat->nat_age;
278f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ipf_state);
2797c478bd9Sstevel@tonic-gate } else {
280f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ipf_state);
2817c478bd9Sstevel@tonic-gate fi.fin_data[0] = 0;
2827c478bd9Sstevel@tonic-gate fi.fin_data[1] = 0;
2837c478bd9Sstevel@tonic-gate ipsec->ipsc_state = fr_addstate(&fi,
2847c478bd9Sstevel@tonic-gate &ipsec->ipsc_state,
2857c478bd9Sstevel@tonic-gate SI_WILDP);
2867c478bd9Sstevel@tonic-gate }
287ab25eeb5Syz ip->ip_p = p;
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate return 0;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate * This extends the NAT matching to be based on the cookies associated with
2957c478bd9Sstevel@tonic-gate * a session and found at the front of IKE packets. The cookies are always
2967c478bd9Sstevel@tonic-gate * in the same order (not reversed depending on packet flow direction as with
2977c478bd9Sstevel@tonic-gate * UDP/TCP port numbers).
2987c478bd9Sstevel@tonic-gate */
299f4b3ec61Sdh /*ARGSUSED*/
ippr_ipsec_match(fin,aps,nat,private)300f4b3ec61Sdh int ippr_ipsec_match(fin, aps, nat, private)
3017c478bd9Sstevel@tonic-gate fr_info_t *fin;
3027c478bd9Sstevel@tonic-gate ap_session_t *aps;
3037c478bd9Sstevel@tonic-gate nat_t *nat;
304f4b3ec61Sdh void *private;
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate ipsec_pxy_t *ipsec;
3077c478bd9Sstevel@tonic-gate u_32_t cookies[4];
3087c478bd9Sstevel@tonic-gate mb_t *m;
3097c478bd9Sstevel@tonic-gate int off;
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate nat = nat; /* LINT */
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG))
3147c478bd9Sstevel@tonic-gate return -1;
3157c478bd9Sstevel@tonic-gate
316ab25eeb5Syz off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff;
3177c478bd9Sstevel@tonic-gate ipsec = aps->aps_data;
3187c478bd9Sstevel@tonic-gate m = fin->fin_m;
3197c478bd9Sstevel@tonic-gate COPYDATA(m, off, sizeof(cookies), (char *)cookies);
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate if ((cookies[0] != ipsec->ipsc_icookie[0]) ||
3227c478bd9Sstevel@tonic-gate (cookies[1] != ipsec->ipsc_icookie[1]))
3237c478bd9Sstevel@tonic-gate return -1;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate if (ipsec->ipsc_rckset == 0) {
3267c478bd9Sstevel@tonic-gate if ((cookies[2]|cookies[3]) == 0) {
3277c478bd9Sstevel@tonic-gate return 0;
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate ipsec->ipsc_rckset = 1;
3307c478bd9Sstevel@tonic-gate ipsec->ipsc_rcookie[0] = cookies[2];
3317c478bd9Sstevel@tonic-gate ipsec->ipsc_rcookie[1] = cookies[3];
3327c478bd9Sstevel@tonic-gate return 0;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate if ((cookies[2] != ipsec->ipsc_rcookie[0]) ||
3367c478bd9Sstevel@tonic-gate (cookies[3] != ipsec->ipsc_rcookie[1]))
3377c478bd9Sstevel@tonic-gate return -1;
3387c478bd9Sstevel@tonic-gate return 0;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate * clean up after ourselves.
3447c478bd9Sstevel@tonic-gate */
345f4b3ec61Sdh /*ARGSUSED*/
ippr_ipsec_del(aps,private,ifs)346f4b3ec61Sdh void ippr_ipsec_del(aps, private, ifs)
3477c478bd9Sstevel@tonic-gate ap_session_t *aps;
348f4b3ec61Sdh void *private;
349f4b3ec61Sdh ipf_stack_t *ifs;
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate ipsec_pxy_t *ipsec;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate ipsec = aps->aps_data;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate if (ipsec != NULL) {
3567c478bd9Sstevel@tonic-gate /*
357ab25eeb5Syz * Don't bother changing any of the NAT structure details,
358ab25eeb5Syz * *_del() is on a callback from aps_free(), from nat_delete()
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate
361f4b3ec61Sdh READ_ENTER(&ifs->ifs_ipf_state);
3627c478bd9Sstevel@tonic-gate if (ipsec->ipsc_state != NULL) {
363f4b3ec61Sdh ipsec->ipsc_state->is_die = ifs->ifs_fr_ticks + 1;
364ab25eeb5Syz ipsec->ipsc_state->is_me = NULL;
3657c478bd9Sstevel@tonic-gate fr_queuefront(&ipsec->ipsc_state->is_sti);
3667c478bd9Sstevel@tonic-gate }
367f4b3ec61Sdh RWLOCK_EXIT(&ifs->ifs_ipf_state);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate ipsec->ipsc_state = NULL;
3707c478bd9Sstevel@tonic-gate ipsec->ipsc_nat = NULL;
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate }
373