1*6ee513e5Sjca /* $OpenBSD: nat_traversal.c,v 1.25 2017/12/05 20:31:45 jca Exp $ */
2cd6bf844Sho
3cd6bf844Sho /*
4cd6bf844Sho * Copyright (c) 2004 H�kan Olsson. All rights reserved.
5cd6bf844Sho *
6cd6bf844Sho * Redistribution and use in source and binary forms, with or without
7cd6bf844Sho * modification, are permitted provided that the following conditions
8cd6bf844Sho * are met:
9cd6bf844Sho * 1. Redistributions of source code must retain the above copyright
10cd6bf844Sho * notice, this list of conditions and the following disclaimer.
11cd6bf844Sho * 2. Redistributions in binary form must reproduce the above copyright
12cd6bf844Sho * notice, this list of conditions and the following disclaimer in the
13cd6bf844Sho * documentation and/or other materials provided with the distribution.
14cd6bf844Sho *
15cd6bf844Sho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16cd6bf844Sho * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17cd6bf844Sho * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18cd6bf844Sho * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19cd6bf844Sho * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20cd6bf844Sho * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21cd6bf844Sho * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22cd6bf844Sho * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23cd6bf844Sho * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24cd6bf844Sho * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25cd6bf844Sho */
26cd6bf844Sho
27cd6bf844Sho #include <sys/types.h>
28cd6bf844Sho #include <stdlib.h>
299c491683Shshoexer #include <string.h>
30cd6bf844Sho
31adfd2491Sho #include "conf.h"
32cd6bf844Sho #include "exchange.h"
33cd6bf844Sho #include "hash.h"
34cd6bf844Sho #include "ipsec.h"
35cd6bf844Sho #include "isakmp_fld.h"
36cd6bf844Sho #include "isakmp_num.h"
37cd6bf844Sho #include "ipsec_num.h"
38cd6bf844Sho #include "log.h"
39cd6bf844Sho #include "message.h"
40cd6bf844Sho #include "nat_traversal.h"
41cd6bf844Sho #include "prf.h"
42cd6bf844Sho #include "sa.h"
43adfd2491Sho #include "timer.h"
44cd6bf844Sho #include "transport.h"
45cd6bf844Sho #include "util.h"
46adfd2491Sho #include "virtual.h"
47cd6bf844Sho
48bfb67d4dScloder int disable_nat_t = 0;
49bfb67d4dScloder
50cd6bf844Sho /*
519f8f63b2Sho * NAT-T capability of the other peer is determined by a particular vendor
529f8f63b2Sho * ID sent in the first message. This vendor ID string is supposed to be a
539f8f63b2Sho * MD5 hash of "RFC 3947".
54cd6bf844Sho *
55cd6bf844Sho * These seem to be the "well" known variants of this string in use by
56cd6bf844Sho * products today.
577498162fShshoexer *
587498162fShshoexer * Note that the VID specified in draft 2 is ambiguous: It was
597498162fShshoexer * accidentally calculated from the string "draft-ietf-ipsec-nat-t-ike-02\n"
607498162fShshoexer * although the string was documented without the trailing '\n'. The authors
617498162fShshoexer * suggested afterwards to use the string with the trailing '\n'.
62cd6bf844Sho */
63875f57d0Shshoexer
64875f57d0Shshoexer static struct nat_t_cap isakmp_nat_t_cap[] = {
65875f57d0Shshoexer { VID_DRAFT_V2_N, EXCHANGE_FLAG_NAT_T_DRAFT,
66875f57d0Shshoexer "draft-ietf-ipsec-nat-t-ike-02\n", NULL, 0 },
67875f57d0Shshoexer { VID_DRAFT_V3, EXCHANGE_FLAG_NAT_T_DRAFT,
68875f57d0Shshoexer "draft-ietf-ipsec-nat-t-ike-03", NULL, 0 },
69875f57d0Shshoexer { VID_RFC3947, EXCHANGE_FLAG_NAT_T_RFC,
70875f57d0Shshoexer "RFC 3947", NULL, 0 },
71cd6bf844Sho };
72cd6bf844Sho
73875f57d0Shshoexer #define NUMNATTCAP (sizeof isakmp_nat_t_cap / sizeof isakmp_nat_t_cap[0])
74875f57d0Shshoexer
75adfd2491Sho /* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09. */
76adfd2491Sho #define NAT_T_KEEPALIVE_INTERVAL 20
77adfd2491Sho
78cd6bf844Sho static int nat_t_setup_hashes(void);
79875f57d0Shshoexer static int nat_t_add_vendor_payload(struct message *, struct nat_t_cap *);
80cd6bf844Sho static int nat_t_add_nat_d(struct message *, struct sockaddr *);
81cd6bf844Sho static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *);
82cd6bf844Sho
83cd6bf844Sho void
nat_t_init(void)84cd6bf844Sho nat_t_init(void)
85cd6bf844Sho {
86875f57d0Shshoexer nat_t_setup_hashes();
87cd6bf844Sho }
88cd6bf844Sho
89cd6bf844Sho /* Generate the NAT-T capability marker hashes. Executed only once. */
90cd6bf844Sho static int
nat_t_setup_hashes(void)91cd6bf844Sho nat_t_setup_hashes(void)
92cd6bf844Sho {
93cd6bf844Sho struct hash *hash;
94875f57d0Shshoexer int n = NUMNATTCAP;
95cd6bf844Sho int i;
96cd6bf844Sho
97cd6bf844Sho /* The draft says to use MD5. */
98cd6bf844Sho hash = hash_get(HASH_MD5);
99cd6bf844Sho if (!hash) {
100cd6bf844Sho /* Should never happen. */
101cd6bf844Sho log_print("nat_t_setup_hashes: "
102cd6bf844Sho "could not find MD5 hash structure!");
103cd6bf844Sho return -1;
104cd6bf844Sho }
105cd6bf844Sho
106875f57d0Shshoexer /* Populate isakmp_nat_t_cap with hashes. */
107cd6bf844Sho for (i = 0; i < n; i++) {
108875f57d0Shshoexer isakmp_nat_t_cap[i].hashsize = hash->hashsize;
1095ae94ef8Sderaadt isakmp_nat_t_cap[i].hash = malloc(hash->hashsize);
110875f57d0Shshoexer if (!isakmp_nat_t_cap[i].hash) {
111cd6bf844Sho log_error("nat_t_setup_hashes: malloc (%lu) failed",
112875f57d0Shshoexer (unsigned long)hash->hashsize);
113cd6bf844Sho goto errout;
114cd6bf844Sho }
115cd6bf844Sho
116cd6bf844Sho hash->Init(hash->ctx);
117cd6bf844Sho hash->Update(hash->ctx,
118875f57d0Shshoexer (unsigned char *)isakmp_nat_t_cap[i].text,
119875f57d0Shshoexer strlen(isakmp_nat_t_cap[i].text));
120875f57d0Shshoexer hash->Final(isakmp_nat_t_cap[i].hash, hash->ctx);
121cd6bf844Sho
122cd6bf844Sho LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: "
123875f57d0Shshoexer "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap[i].text,
124875f57d0Shshoexer (unsigned long)hash->hashsize));
125cd6bf844Sho LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes",
126875f57d0Shshoexer isakmp_nat_t_cap[i].hash, hash->hashsize));
127cd6bf844Sho }
128cd6bf844Sho
129cd6bf844Sho return 0;
130cd6bf844Sho
131cd6bf844Sho errout:
132cd6bf844Sho for (i = 0; i < n; i++)
133875f57d0Shshoexer free(isakmp_nat_t_cap[i].hash);
134cd6bf844Sho return -1;
135cd6bf844Sho }
136cd6bf844Sho
137cd6bf844Sho /* Add one NAT-T VENDOR payload. */
138cd6bf844Sho static int
nat_t_add_vendor_payload(struct message * msg,struct nat_t_cap * cap)139875f57d0Shshoexer nat_t_add_vendor_payload(struct message *msg, struct nat_t_cap *cap)
140cd6bf844Sho {
141875f57d0Shshoexer size_t buflen = cap->hashsize + ISAKMP_GEN_SZ;
142cd6bf844Sho u_int8_t *buf;
143cd6bf844Sho
144bfb67d4dScloder if (disable_nat_t)
145bfb67d4dScloder return 0;
146bfb67d4dScloder
147cd6bf844Sho buf = malloc(buflen);
148cd6bf844Sho if (!buf) {
149cd6bf844Sho log_error("nat_t_add_vendor_payload: malloc (%lu) failed",
150cd6bf844Sho (unsigned long)buflen);
151cd6bf844Sho return -1;
152cd6bf844Sho }
153cd6bf844Sho
154cd6bf844Sho SET_ISAKMP_GEN_LENGTH(buf, buflen);
155875f57d0Shshoexer memcpy(buf + ISAKMP_VENDOR_ID_OFF, cap->hash, cap->hashsize);
156cd6bf844Sho if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) {
157cd6bf844Sho free(buf);
158cd6bf844Sho return -1;
159cd6bf844Sho }
160cd6bf844Sho return 0;
161cd6bf844Sho }
162cd6bf844Sho
163cd6bf844Sho /* Add the NAT-T capability markers (VENDOR payloads). */
164cd6bf844Sho int
nat_t_add_vendor_payloads(struct message * msg)165cd6bf844Sho nat_t_add_vendor_payloads(struct message *msg)
166cd6bf844Sho {
167875f57d0Shshoexer int i;
168cd6bf844Sho
169bfb67d4dScloder if (disable_nat_t)
170bfb67d4dScloder return 0;
171bfb67d4dScloder
172875f57d0Shshoexer for (i = 0; i < NUMNATTCAP; i++)
173875f57d0Shshoexer if (nat_t_add_vendor_payload(msg, &isakmp_nat_t_cap[i]))
174cd6bf844Sho return -1;
175cd6bf844Sho return 0;
176cd6bf844Sho }
177cd6bf844Sho
178cd6bf844Sho /*
179cd6bf844Sho * Check an incoming message for NAT-T capability markers.
180cd6bf844Sho */
181cd6bf844Sho void
nat_t_check_vendor_payload(struct message * msg,struct payload * p)182cd6bf844Sho nat_t_check_vendor_payload(struct message *msg, struct payload *p)
183cd6bf844Sho {
184cd6bf844Sho u_int8_t *pbuf = p->p;
185cd6bf844Sho size_t vlen;
186875f57d0Shshoexer int i;
187cd6bf844Sho
188bfb67d4dScloder if (disable_nat_t)
189bfb67d4dScloder return;
190bfb67d4dScloder
191cd6bf844Sho vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ;
192875f57d0Shshoexer
193875f57d0Shshoexer for (i = 0; i < NUMNATTCAP; i++) {
194875f57d0Shshoexer if (vlen != isakmp_nat_t_cap[i].hashsize) {
195875f57d0Shshoexer continue;
196cd6bf844Sho }
197875f57d0Shshoexer if (memcmp(isakmp_nat_t_cap[i].hash, pbuf + ISAKMP_GEN_SZ,
198cd6bf844Sho vlen) == 0) {
199cd6bf844Sho /* This peer is NAT-T capable. */
200cd6bf844Sho msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER;
201875f57d0Shshoexer msg->exchange->flags |= isakmp_nat_t_cap[i].flags;
202cd6bf844Sho LOG_DBG((LOG_EXCHANGE, 10,
203cd6bf844Sho "nat_t_check_vendor_payload: "
204cd6bf844Sho "NAT-T capable peer detected"));
205cd6bf844Sho p->flags |= PL_MARK;
206cd6bf844Sho }
207cd6bf844Sho }
208cd6bf844Sho
209875f57d0Shshoexer return;
210875f57d0Shshoexer }
211875f57d0Shshoexer
212cd6bf844Sho /* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */
213cd6bf844Sho static u_int8_t *
nat_t_generate_nat_d_hash(struct message * msg,struct sockaddr * sa,size_t * hashlen)214cd6bf844Sho nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa,
215cd6bf844Sho size_t *hashlen)
216cd6bf844Sho {
217cd6bf844Sho struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data;
218cd6bf844Sho struct hash *hash;
219cd6bf844Sho u_int8_t *res;
220cd6bf844Sho in_port_t port;
221cd6bf844Sho
222cd6bf844Sho hash = hash_get(ie->hash->type);
223cd6bf844Sho if (hash == NULL) {
224cd6bf844Sho log_print ("nat_t_generate_nat_d_hash: no hash");
225cd6bf844Sho return NULL;
226cd6bf844Sho }
227cd6bf844Sho
22835dfcbf4Shshoexer *hashlen = hash->hashsize;
229cd6bf844Sho
230c52ea152Sderaadt res = malloc(*hashlen);
231cd6bf844Sho if (!res) {
232cd6bf844Sho log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed",
233cd6bf844Sho (unsigned long)*hashlen);
234cd6bf844Sho *hashlen = 0;
235cd6bf844Sho return NULL;
236cd6bf844Sho }
237cd6bf844Sho
238cd6bf844Sho port = sockaddr_port(sa);
2390dc10397Shshoexer bzero(res, *hashlen);
240cd6bf844Sho
24135dfcbf4Shshoexer hash->Init(hash->ctx);
24235dfcbf4Shshoexer hash->Update(hash->ctx, msg->exchange->cookies,
24335dfcbf4Shshoexer sizeof msg->exchange->cookies);
24435dfcbf4Shshoexer hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
24535dfcbf4Shshoexer hash->Update(hash->ctx, (unsigned char *)&port, sizeof port);
24635dfcbf4Shshoexer hash->Final(res, hash->ctx);
247cd6bf844Sho return res;
248cd6bf844Sho }
249cd6bf844Sho
250cd6bf844Sho /* Add a NAT-D payload to our message. */
251cd6bf844Sho static int
nat_t_add_nat_d(struct message * msg,struct sockaddr * sa)252cd6bf844Sho nat_t_add_nat_d(struct message *msg, struct sockaddr *sa)
253cd6bf844Sho {
254875f57d0Shshoexer int ret;
255cd6bf844Sho u_int8_t *hbuf, *buf;
256cd6bf844Sho size_t hbuflen, buflen;
257cd6bf844Sho
258cd6bf844Sho hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
259cd6bf844Sho if (!hbuf) {
260cd6bf844Sho log_print("nat_t_add_nat_d: NAT-D hash gen failed");
261cd6bf844Sho return -1;
262cd6bf844Sho }
263cd6bf844Sho
264cd6bf844Sho buflen = ISAKMP_NAT_D_DATA_OFF + hbuflen;
265cd6bf844Sho buf = malloc(buflen);
266cd6bf844Sho if (!buf) {
267cd6bf844Sho log_error("nat_t_add_nat_d: malloc (%lu) failed",
268cd6bf844Sho (unsigned long)buflen);
269cd6bf844Sho free(hbuf);
270cd6bf844Sho return -1;
271cd6bf844Sho }
272cd6bf844Sho
273cd6bf844Sho SET_ISAKMP_GEN_LENGTH(buf, buflen);
274cd6bf844Sho memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen);
275cd6bf844Sho free(hbuf);
276cd6bf844Sho
277875f57d0Shshoexer if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_RFC)
278875f57d0Shshoexer ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf,
279875f57d0Shshoexer buflen, 1);
280875f57d0Shshoexer else if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT)
281875f57d0Shshoexer ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT,
282875f57d0Shshoexer buf, buflen, 1);
283875f57d0Shshoexer else
284875f57d0Shshoexer ret = -1;
285875f57d0Shshoexer
286875f57d0Shshoexer if (ret) {
287cd6bf844Sho free(buf);
288cd6bf844Sho return -1;
289cd6bf844Sho }
290cd6bf844Sho return 0;
291cd6bf844Sho }
292cd6bf844Sho
293cd6bf844Sho /* We add two NAT-D payloads, one each for src and dst. */
294cd6bf844Sho int
nat_t_exchange_add_nat_d(struct message * msg)295cd6bf844Sho nat_t_exchange_add_nat_d(struct message *msg)
296cd6bf844Sho {
297cd6bf844Sho struct sockaddr *sa;
298cd6bf844Sho
29935dfcbf4Shshoexer /* Remote address first. */
30035dfcbf4Shshoexer msg->transport->vtbl->get_dst(msg->transport, &sa);
301cd6bf844Sho if (nat_t_add_nat_d(msg, sa))
302cd6bf844Sho return -1;
303cd6bf844Sho
30435dfcbf4Shshoexer msg->transport->vtbl->get_src(msg->transport, &sa);
305cd6bf844Sho if (nat_t_add_nat_d(msg, sa))
306cd6bf844Sho return -1;
307cd6bf844Sho return 0;
308cd6bf844Sho }
309cd6bf844Sho
310cd6bf844Sho /* Generate and match a NAT-D hash against the NAT-D payload (pl.) data. */
311cd6bf844Sho static int
nat_t_match_nat_d_payload(struct message * msg,struct sockaddr * sa)312cd6bf844Sho nat_t_match_nat_d_payload(struct message *msg, struct sockaddr *sa)
313cd6bf844Sho {
314cd6bf844Sho struct payload *p;
315cd6bf844Sho u_int8_t *hbuf;
316cd6bf844Sho size_t hbuflen;
317cd6bf844Sho int found = 0;
318cd6bf844Sho
3193ca9511cSho /*
3203ca9511cSho * If there are no NAT-D payloads in the message, return "found"
3213ca9511cSho * as this will avoid NAT-T (see nat_t_exchange_check_nat_d()).
3223ca9511cSho */
323b14af008Shshoexer if ((p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT)) == NULL &&
324b14af008Shshoexer (p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D)) == NULL)
3253ca9511cSho return 1;
3263ca9511cSho
327cd6bf844Sho hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
328cd6bf844Sho if (!hbuf)
329cd6bf844Sho return 0;
330cd6bf844Sho
331b71022a1Smarkus for (; p; p = TAILQ_NEXT(p, link)) {
332cd6bf844Sho if (GET_ISAKMP_GEN_LENGTH (p->p) !=
333cd6bf844Sho hbuflen + ISAKMP_NAT_D_DATA_OFF)
334cd6bf844Sho continue;
335cd6bf844Sho
336cd6bf844Sho if (memcmp(p->p + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen) == 0) {
337cd6bf844Sho found++;
338cd6bf844Sho break;
339cd6bf844Sho }
340cd6bf844Sho }
341cd6bf844Sho free(hbuf);
342cd6bf844Sho return found;
343cd6bf844Sho }
344cd6bf844Sho
345cd6bf844Sho /*
346cd6bf844Sho * Check if we need to activate NAT-T, and if we need to send keepalive
347cd6bf844Sho * messages to the other side, i.e if we are a nat:ed peer.
348cd6bf844Sho */
349cd6bf844Sho int
nat_t_exchange_check_nat_d(struct message * msg)350cd6bf844Sho nat_t_exchange_check_nat_d(struct message *msg)
351cd6bf844Sho {
352cd6bf844Sho struct sockaddr *sa;
353cd6bf844Sho int outgoing_path_is_clear, incoming_path_is_clear;
354cd6bf844Sho
355cd6bf844Sho /* Assume trouble, i.e NAT-boxes in our path. */
356cd6bf844Sho outgoing_path_is_clear = incoming_path_is_clear = 0;
357cd6bf844Sho
358cd6bf844Sho msg->transport->vtbl->get_src(msg->transport, &sa);
359cd6bf844Sho if (nat_t_match_nat_d_payload(msg, sa))
360cd6bf844Sho outgoing_path_is_clear = 1;
361cd6bf844Sho
362cd6bf844Sho msg->transport->vtbl->get_dst(msg->transport, &sa);
363cd6bf844Sho if (nat_t_match_nat_d_payload(msg, sa))
364cd6bf844Sho incoming_path_is_clear = 1;
365cd6bf844Sho
366cd6bf844Sho if (outgoing_path_is_clear && incoming_path_is_clear) {
367cd6bf844Sho LOG_DBG((LOG_EXCHANGE, 40, "nat_t_exchange_check_nat_d: "
368cd6bf844Sho "no NAT"));
369cd6bf844Sho return 0; /* No NAT-T required. */
370cd6bf844Sho }
371cd6bf844Sho
372cd6bf844Sho /* NAT-T handling required. */
373cd6bf844Sho msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE;
374cd6bf844Sho
375cd6bf844Sho if (!outgoing_path_is_clear) {
376cd6bf844Sho msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE;
377cd6bf844Sho LOG_DBG((LOG_EXCHANGE, 10, "nat_t_exchange_check_nat_d: "
378cd6bf844Sho "NAT detected, we're behind it"));
379cd6bf844Sho } else
380cd6bf844Sho LOG_DBG ((LOG_EXCHANGE, 10,
381cd6bf844Sho "nat_t_exchange_check_nat_d: NAT detected"));
382cd6bf844Sho return 1;
383cd6bf844Sho }
384adfd2491Sho
385adfd2491Sho static void
nat_t_send_keepalive(void * v_arg)386adfd2491Sho nat_t_send_keepalive(void *v_arg)
387adfd2491Sho {
388adfd2491Sho struct sa *sa = (struct sa *)v_arg;
389adfd2491Sho struct transport *t;
390*6ee513e5Sjca struct timespec now;
391adfd2491Sho int interval;
392adfd2491Sho
393adfd2491Sho /* Send the keepalive message. */
394adfd2491Sho t = ((struct virtual_transport *)sa->transport)->encap;
395adfd2491Sho t->vtbl->send_message(NULL, t);
396adfd2491Sho
397adfd2491Sho /* Set new timer. */
398adfd2491Sho interval = conf_get_num("General", "NAT-T-Keepalive", 0);
399adfd2491Sho if (interval < 1)
400adfd2491Sho interval = NAT_T_KEEPALIVE_INTERVAL;
401*6ee513e5Sjca clock_gettime(CLOCK_MONOTONIC, &now);
402adfd2491Sho now.tv_sec += interval;
403adfd2491Sho
404adfd2491Sho sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive",
405adfd2491Sho nat_t_send_keepalive, v_arg, &now);
406adfd2491Sho if (!sa->nat_t_keepalive)
407adfd2491Sho log_print("nat_t_send_keepalive: "
408adfd2491Sho "timer_add_event() failed, will send no more keepalives");
409adfd2491Sho }
410adfd2491Sho
411adfd2491Sho void
nat_t_setup_keepalive(struct sa * sa)412adfd2491Sho nat_t_setup_keepalive(struct sa *sa)
413adfd2491Sho {
414adfd2491Sho struct sockaddr *src;
415*6ee513e5Sjca struct timespec now;
416adfd2491Sho
417dec6ea27Sho if (sa->initiator)
418adfd2491Sho sa->transport->vtbl->get_src(sa->transport, &src);
419dec6ea27Sho else
420dec6ea27Sho sa->transport->vtbl->get_dst(sa->transport, &src);
421dec6ea27Sho
422adfd2491Sho if (!virtual_listen_lookup(src))
423adfd2491Sho return;
424adfd2491Sho
425*6ee513e5Sjca clock_gettime(CLOCK_MONOTONIC, &now);
426adfd2491Sho now.tv_sec += NAT_T_KEEPALIVE_INTERVAL;
427adfd2491Sho
428adfd2491Sho sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive",
429adfd2491Sho nat_t_send_keepalive, sa, &now);
430adfd2491Sho if (!sa->nat_t_keepalive)
431adfd2491Sho log_print("nat_t_setup_keepalive: "
432adfd2491Sho "timer_add_event() failed, will not send keepalives");
433dec6ea27Sho
434dec6ea27Sho LOG_DBG((LOG_TRANSPORT, 50, "nat_t_setup_keepalive: "
435dec6ea27Sho "added event for phase 1 SA %p", sa));
436adfd2491Sho }
437