OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / pluto / nat_traversal.c
1 /* FreeS/WAN NAT-Traversal
2  * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * RCSID $Id: nat_traversal.c,v 1.5 2005-12-19 00:41:37 danield Exp $
15  */
16
17 #ifdef NAT_TRAVERSAL
18
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <string.h>
22
23 #include <freeswan.h>
24 #include <pfkeyv2.h>
25 #include <pfkey.h>
26
27 #include "constants.h"
28 #include "defs.h"
29 #include "log.h"
30 #include "id.h"
31 #include "x509.h"
32 #include "connections.h"
33 #include "packet.h"
34 #include "demux.h"
35 #include "whack.h"
36 #include "state.h"
37 #include "server.h"
38 #include "timer.h"
39 #include "sha1.h"
40 #include "md5.h"
41 #include "crypto.h"
42 #include "vendor.h"
43 #include "cookie.h"
44 #include "kernel.h"
45
46 #include "nat_traversal.h"
47
48 #include "ike_alg.h"
49
50 /* #define FORCE_NAT_TRAVERSAL */
51 #define NAT_D_DEBUG
52 #define NAT_T_SUPPORT_LAST_DRAFTS
53
54 #ifndef SOL_UDP
55 #define SOL_UDP 17
56 #endif
57
58 #ifndef UDP_ESPINUDP
59 #define UDP_ESPINUDP    100
60 #endif
61
62 #define DEFAULT_KEEP_ALIVE_PERIOD  20
63
64 #ifdef _IKE_ALG_H
65 /* Alg patch: hash_digest_len -> hash_digest_size */
66 #define hash_digest_len hash_digest_size
67 #endif
68
69 bool nat_traversal_enabled = FALSE;
70 bool nat_traversal_support_port_floating = FALSE;
71
72 static unsigned int _kap = 0;
73 static unsigned int _ka_evt = 0;
74 static bool _force_ka = 0;
75
76 static const char *natt_version = "0.6";
77
78 static const char *natt_methods[] = {
79         "draft-ietf-ipsec-nat-t-ike-00/01",
80         "draft-ietf-ipsec-nat-t-ike-02/03",
81         "RFC XXXX (NAT-Traversal)"
82 };
83
84 void init_nat_traversal (bool activate, unsigned int keep_alive_period,
85         bool fka, bool spf)
86 {
87         nat_traversal_enabled = activate;
88 #ifdef NAT_T_SUPPORT_LAST_DRAFTS
89         nat_traversal_support_port_floating = activate ? spf : FALSE;
90 #endif
91         _force_ka = fka;
92         _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD;
93         log("  including NAT-Traversal patch (Version %s)%s%s%s",
94                 natt_version, activate ? "" : " [disabled]",
95                 activate & fka ? " [Force KeepAlive]" : "",
96                 activate & !spf ? " [Port Floating disabled]" : "");
97 }
98
99 static void disable_nat_traversal (void)
100 {
101         nat_traversal_enabled = FALSE; 
102         nat_traversal_support_port_floating = FALSE;
103 }
104
105 static void _natd_hash(const struct hash_desc *hasher, char *hash,
106         u_int8_t *icookie, u_int8_t *rcookie,
107         const ip_address *ip, u_int16_t port)
108 {
109         union hash_ctx ctx;
110
111         if (is_zero_cookie(icookie))
112                 DBG_log("_natd_hash: Warning, icookie is zero !!");
113         if (is_zero_cookie(rcookie))
114                 DBG_log("_natd_hash: Warning, rcookie is zero !!");
115
116         /**
117          * draft-ietf-ipsec-nat-t-ike-01.txt
118          *
119          *   HASH = HASH(CKY-I | CKY-R | IP | Port)
120          *
121          * All values in network order
122          */
123         hasher->hash_init(&ctx);
124         hasher->hash_update(&ctx, icookie, COOKIE_SIZE);
125         hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);
126         switch (addrtypeof(ip)) {
127                 case AF_INET:
128                         hasher->hash_update(&ctx,
129                                 (const u_char *)&ip->u.v4.sin_addr.s_addr,
130                                 sizeof(ip->u.v4.sin_addr.s_addr));
131                         break;
132                 case AF_INET6:
133                         hasher->hash_update(&ctx,
134                                 (const u_char *)&ip->u.v6.sin6_addr.s6_addr,
135                                 sizeof(ip->u.v6.sin6_addr.s6_addr));
136                         break;
137         }
138         hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));
139         hasher->hash_final(hash, &ctx);
140 #ifdef NAT_D_DEBUG
141         DBG(DBG_NATT,
142                 DBG_log("_natd_hash: hasher=%p(%d)", hasher, hasher->hash_digest_len);
143                 DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE);
144                 DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE);
145                 switch (addrtypeof(ip)) {
146                         case AF_INET:
147                                 DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr,
148                                         sizeof(ip->u.v4.sin_addr.s_addr));
149                                 break;
150                 }
151                 DBG_log("_natd_hash: port=%d", port);
152                 DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);
153         );
154 #endif
155 }
156
157 /**
158  * Add NAT-Traversal VIDs (supported ones)
159  *
160  * Used when we're Initiator
161  */
162 bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs)
163 {
164         bool r = TRUE;
165         if (nat_traversal_support_port_floating) {
166 #if 0
167                 if (r) r = out_vendorid(np, outs, VID_NATT_RFC);
168 #endif
169                 if (r) r = out_vendorid(np, outs, VID_NATT_IETF_03);
170                 if (r) r = out_vendorid(np, outs, VID_NATT_IETF_02);
171         }
172         if (r) r = out_vendorid(np, outs, VID_NATT_IETF_00);
173         return r;
174 }
175
176 u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid)
177 {
178         switch (nat_t_vid) {
179                 case VID_NATT_IETF_00:
180                         return LELEM(NAT_TRAVERSAL_IETF_00_01);
181                         break;
182                 case VID_NATT_IETF_02:
183                 case VID_NATT_IETF_02_N:
184                 case VID_NATT_IETF_03:
185                         return LELEM(NAT_TRAVERSAL_IETF_02_03);
186                         break;
187                 case VID_NATT_RFC:
188                         return LELEM(NAT_TRAVERSAL_RFC);
189                         break;
190         }
191         return 0;
192 }
193
194 void nat_traversal_natd_lookup(struct msg_digest *md)
195 {
196         char hash[MAX_DIGEST_LEN];
197         struct payload_digest *p;
198         struct state *st = md->st;
199         int i;
200
201         if (!st || !md->iface || !st->st_oakley.hasher) {
202                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
203                         __FILE__, __LINE__);
204                 return;
205         }
206
207         /** Count NAT-D **/
208         for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++);
209
210         /**
211          * We need at least 2 NAT-D (1 for us, many for peer)
212          */
213         if (i < 2) {
214                 loglog(RC_LOG_SERIOUS,
215                 "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i);
216                 st->nat_traversal = 0;
217                 return;
218         }
219
220         /**
221          * First one with my IP & port
222          */
223         p = md->chain[ISAKMP_NEXT_NATD_RFC];
224         _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
225                 &(md->iface->addr), ntohs(st->st_connection->this.host_port));
226         if (!( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len) &&
227                 (memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)==0)
228                 )) {
229 #ifdef NAT_D_DEBUG
230                 DBG(DBG_NATT,
231                         DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
232                         DBG_dump("expected NAT-D:", hash,
233                                 st->st_oakley.hasher->hash_digest_len);
234                         DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
235                 );
236 #endif
237                 st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
238         }
239
240         /**
241          * The others with sender IP & port
242          */
243         _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
244                 &(md->sender), ntohs(md->sender_port));
245         for (p = p->next, i=0 ; p != NULL; p = p->next) {
246                 if ( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len) &&
247                         (memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)==0)
248                         ) {
249                         i++;
250                 }
251         }
252         if (!i) {
253 #ifdef NAT_D_DEBUG
254                 DBG(DBG_NATT,
255                         DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
256                         DBG_dump("expected NAT-D:", hash,
257                                 st->st_oakley.hasher->hash_digest_len);
258                         p = md->chain[ISAKMP_NEXT_NATD_RFC];
259                         for (p = p->next, i=0 ; p != NULL; p = p->next) {
260                                 DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
261                         }
262                 );
263 #endif
264                 st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
265         }
266 #ifdef FORCE_NAT_TRAVERSAL
267         st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
268         st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
269 #endif
270 }
271
272 bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
273         struct msg_digest *md)
274 {
275         char hash[MAX_DIGEST_LEN];
276         struct state *st = md->st;
277
278         if (!st || !st->st_oakley.hasher) {
279                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
280                         __FILE__, __LINE__);
281                 return FALSE;
282         }
283
284         if (!out_modify_previous_np((st->nat_traversal & NAT_T_WITH_RFC_VALUES
285                 ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), outs)) {
286                 return FALSE;
287         }
288
289         /**
290          * First one with sender IP & port
291          */
292         _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
293                 is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
294                 &(md->sender),
295 #ifdef FORCE_NAT_TRAVERSAL
296                 0
297 #else
298                 ntohs(md->sender_port)
299 #endif
300         );
301         if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES
302                 ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs,
303                 hash, st->st_oakley.hasher->hash_digest_len, "NAT-D")) {
304                 return FALSE;
305         }
306
307         /**
308          * Second one with my IP & port
309          */
310         _natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
311                 is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
312                 &(md->iface->addr),
313 #ifdef FORCE_NAT_TRAVERSAL
314                 0
315 #else
316                 ntohs(st->st_connection->this.host_port)
317 #endif
318         );
319         return (out_generic_raw(np, &isakmp_nat_d, outs,
320                 hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
321 }
322
323 /**
324  * nat_traversal_natoa_lookup()
325  * 
326  * Look for NAT-OA in message
327  */
328 void nat_traversal_natoa_lookup(struct msg_digest *md)
329 {
330         struct payload_digest *p;
331         struct state *st = md->st;
332         int i;
333         ip_address ip;
334
335         if (!st || !md->iface) {
336                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
337                         __FILE__, __LINE__);
338                 return;
339         }
340
341         /** Initialize NAT-OA */
342         anyaddr(AF_INET, &st->nat_oa);
343
344         /** Count NAT-OA **/
345         for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++);
346
347         DBG(DBG_NATT,
348                 DBG_log("NAT-Traversal: received %d NAT-OA.", i);
349         );
350
351         if (i==0) {
352                 return;
353         }
354         else if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) {
355                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
356                         "ignored because peer is not NATed", i);
357                 return;
358         }
359         else if (i>1) {
360                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
361                         "using first, ignoring others", i);
362         }
363
364         /** Take first **/
365         p = md->chain[ISAKMP_NEXT_NATOA_RFC];
366
367         DBG(DBG_PARSING,
368                 DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
369         );
370
371         switch (p->payload.nat_oa.isanoa_idtype) {
372                 case ID_IPV4_ADDR:
373                         if (pbs_left(&p->pbs) == sizeof(struct in_addr)) {
374                                 initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip);
375                         }
376                         else {
377                                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA "
378                                         "with invalid IP size (%d)", pbs_left(&p->pbs));
379                                 return;
380                         }
381                         break;
382                 case ID_IPV6_ADDR:
383                         if (pbs_left(&p->pbs) == sizeof(struct in6_addr)) {
384                                 initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip);
385                         }
386                         else {
387                                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA "
388                                         "with invalid IP size (%d)", pbs_left(&p->pbs));
389                                 return;
390                         }
391                         break;
392                 default:
393                         loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
394                                 "invalid ID Type (%d) in NAT-OA - ignored",
395                                 p->payload.nat_oa.isanoa_idtype);
396                         return;
397                         break;
398         }
399
400         DBG(DBG_NATT,
401                 {
402                         char ip_t[ADDRTOT_BUF];
403                         addrtot(&ip, 0, ip_t, sizeof(ip_t));
404                         DBG_log("received NAT-OA: %s", ip_t);
405                 }
406         );
407
408         if (isanyaddr(&ip)) {
409                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");
410         }
411         else {
412                 st->nat_oa = ip;
413         }
414 }
415
416 bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
417         struct state *st)
418 {
419         struct isakmp_nat_oa natoa;
420         pb_stream pbs;
421         unsigned char ip_val[sizeof(struct in6_addr)];
422         size_t ip_len = 0;
423         ip_address *ip;
424
425         if ((!st) || (!st->st_connection)) {
426                 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
427                         __FILE__, __LINE__);
428                 return FALSE;
429         }
430         ip = &(st->st_connection->this.host_addr);
431
432         if (!out_modify_previous_np((st->nat_traversal & NAT_T_WITH_RFC_VALUES
433                 ? ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS), outs)) {
434                 return FALSE;
435         }
436
437         memset(&natoa, 0, sizeof(natoa));
438         natoa.isanoa_np = np;
439
440         switch (addrtypeof(ip)) {
441                 case AF_INET:
442                         ip_len = sizeof(ip->u.v4.sin_addr.s_addr);
443                         memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len);
444                         natoa.isanoa_idtype = ID_IPV4_ADDR;
445                         break;
446                 case AF_INET6:
447                         ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr);
448                         memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len);
449                         natoa.isanoa_idtype = ID_IPV6_ADDR;
450                         break;
451                 default:
452                         loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
453                                 "invalid addrtypeof()=%d", addrtypeof(ip));
454                         return FALSE;
455         }
456
457         if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))
458                 return FALSE;
459
460         if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))
461                 return FALSE;
462
463         DBG(DBG_NATT,
464                 DBG_dump("NAT-OA (S):", ip_val, ip_len);
465         );
466
467         close_output_pbs(&pbs);
468         return TRUE;
469 }
470
471 void nat_traversal_show_result (u_int32_t nt, u_int16_t sport)
472 {
473         const char *mth = NULL, *rslt = NULL;
474         switch (nt & NAT_TRAVERSAL_METHOD) {
475                 case LELEM(NAT_TRAVERSAL_IETF_00_01):
476                         mth = natt_methods[0];
477                         break;
478                 case LELEM(NAT_TRAVERSAL_IETF_02_03):
479                         mth = natt_methods[1];
480                         break;
481                 case LELEM(NAT_TRAVERSAL_RFC):
482                         mth = natt_methods[2];
483                         break;
484         }
485         switch (nt & NAT_T_DETECTED) {
486                 case 0:
487                         rslt = "no NAT detected";
488                         break;
489                 case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):
490                         rslt = "i am NATed";
491                         break;
492                 case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
493                         rslt = "peer is NATed";
494                         break;
495                 case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
496                         rslt = "both are NATed";
497                         break;
498         }
499         loglog(RC_LOG_SERIOUS,
500                 "NAT-Traversal: Result using %s: %s",
501                 mth ? mth : "unknown method",
502                 rslt ? rslt : "unknown result"
503                 );
504         if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)) &&
505                 (sport == IKE_UDP_PORT) &&
506                 ((nt & NAT_T_WITH_PORT_FLOATING)==0)) {
507                 loglog(RC_LOG_SERIOUS,
508                         "Warning: peer is NATed but source port is still udp/%d. "
509                         "Ipsec-passthrough NAT device suspected -- NAT-T may not work.",
510                         IKE_UDP_PORT
511                 );
512         }
513 }
514
515 int nat_traversal_espinudp_socket (int sk, u_int32_t type)
516 {
517         int r;
518         r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type));
519         if ((r<0) && (errno == ENOPROTOOPT)) {
520                 loglog(RC_LOG_SERIOUS,
521                         "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- "
522                         "NAT-T disabled", type);
523                 disable_nat_traversal();
524         }
525         return r;
526 }
527
528 void nat_traversal_new_ka_event (void)
529 {
530         if (_ka_evt) return;  /* Event already schedule */
531         event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);
532         _ka_evt = 1;
533 }
534
535 static void nat_traversal_send_ka (struct state *st)
536 {
537         static unsigned char ka_payload = 0xff;
538         chunk_t sav;
539
540         DBG(DBG_NATT,
541                 DBG_log("ka_event: send NAT-KA to %s:%d",
542                         ip_str(&st->st_connection->that.host_addr),
543                         st->st_connection->that.host_port);
544         );
545
546         /** save state chunk */
547         setchunk(sav, st->st_tpacket.ptr, st->st_tpacket.len);
548
549         /** send keep alive */
550         setchunk(st->st_tpacket, &ka_payload, 1);
551         _send_packet(st, "NAT-T Keep Alive", FALSE);
552
553         /** restore state chunk */
554         setchunk(st->st_tpacket, sav.ptr, sav.len);
555 }
556
557 /**
558  * Find ISAKMP States with NAT-T and send keep-alive
559  */
560 static void nat_traversal_ka_event_state (struct state *st, void *data)
561 {
562         unsigned int *_kap_st = (unsigned int *)data;
563         const struct connection *c = st->st_connection;
564         if (!c) return;
565         if ( ((st->st_state == STATE_MAIN_R3) ||
566                         (st->st_state == STATE_MAIN_I4)) &&
567                 (st->nat_traversal & NAT_T_DETECTED) &&
568                 ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || (_force_ka))
569                 ) {
570                 /**
571                  * - ISAKMP established
572                  * - NAT-Traversal detected
573                  * - NAT-KeepAlive needed (we are NATed)
574                  */
575                 if (c->newest_isakmp_sa != st->st_serialno) {
576                         /** 
577                          * if newest is also valid, ignore this one, we will only use
578                          * newest. 
579                          */
580                         struct state *st_newest;
581                         st_newest = state_with_serialno(c->newest_isakmp_sa);
582                         if ((st_newest) && ((st_newest->st_state==STATE_MAIN_R3) ||
583                                 (st_newest->st_state==STATE_MAIN_I4)) &&
584                                 (st_newest->nat_traversal & NAT_T_DETECTED) &&
585                                 ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))
586                                 || (_force_ka))) {
587                                 return;
588                         }
589                 }
590                 set_cur_state(st);
591                 nat_traversal_send_ka(st);
592                 reset_cur_state();
593                 (*_kap_st)++;
594         }
595 }
596
597 void nat_traversal_ka_event (void)
598 {
599         unsigned int _kap_st = 0;
600
601         _ka_evt = 0;  /* ready to be reschedule */
602
603         for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);
604
605         if (_kap_st) {
606                 /**
607                  * If there are still states who needs Keep-Alive, schedule new event
608                  */
609                 nat_traversal_new_ka_event();
610         }
611 }
612
613 struct _new_mapp_nfo {
614         ip_address addr;
615         u_int16_t sport, dport;
616 };
617
618 static void nat_traversal_find_new_mapp_state (struct state *st, void *data)
619 {
620         struct connection *c = st->st_connection;
621         struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
622
623         if ((c) && sameaddr(&c->that.host_addr, &(nfo->addr)) &&
624                 (c->that.host_port == nfo->sport)) {
625
626                 /**
627                  * Change host port
628                  */
629                 c->that.host_port = nfo->dport;
630
631                 if (IS_IPSEC_SA_ESTABLISHED(st->st_state) ||
632                         IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) {
633                         if (!update_ipsec_sa(st)) {
634                                 /**
635                                  * If ipsec update failed, restore old port or we'll
636                                  * not be able to update anymore.
637                                  */
638                                 c->that.host_port = nfo->sport;
639                         }
640                 }
641         }
642 }
643
644 static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,
645         const ip_address *dst, u_int16_t dport)
646 {
647         char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];
648         struct _new_mapp_nfo nfo;
649
650         addrtot(src, 0, srca, ADDRTOT_BUF);
651         addrtot(dst, 0, dsta, ADDRTOT_BUF);
652
653         if (!sameaddr(src, dst)) {
654                 loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: "
655                         "address change currently not supported [%s:%d,%s:%d]",
656                         srca, sport, dsta, dport);
657                 return -1;
658         }
659
660         if (sport == dport) {
661                 /* no change */
662                 return 0;
663         }
664
665         DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);
666
667         nfo.addr = *src;
668         nfo.sport = sport;
669         nfo.dport = dport;
670
671         for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);
672
673         return 0;
674 }
675
676 void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
677 {
678         struct connection *c = st ? st->st_connection : NULL;
679         struct iface *i = NULL;
680
681         if ((st == NULL) || (c == NULL)) {
682                 return;
683         }
684
685         if (md) {
686                 /**
687                  * If interface type has changed, update local port (500/4500)
688                  */
689                 if (((c->this.host_port == NAT_T_IKE_FLOAT_PORT) &&
690                          (md->iface->ike_float == FALSE)) ||
691                         ((c->this.host_port != NAT_T_IKE_FLOAT_PORT) &&
692                          (md->iface->ike_float == TRUE))) {
693                         c->this.host_port = (md->iface->ike_float == TRUE)
694                                 ? NAT_T_IKE_FLOAT_PORT : pluto_port;
695                         DBG(DBG_NATT,
696                                 DBG_log("NAT-T: updating local port to %d", c->this.host_port);
697                         );
698                 }
699
700                 /**
701                  * If source port has changed, update (including other states and
702                  * established kernel SA)
703                  */
704                 if (c->that.host_port != md->sender_port) {
705                         if (md->iface->ike_float == TRUE)
706                                 nat_traversal_new_mapping(&c->that.host_addr, c->that.host_port,
707                                         &c->that.host_addr, md->sender_port);
708                         c->that.host_port = md->sender_port;
709                 }
710         }
711
712         /**
713          * If we're initiator and NAT-T (with port floating) is detected, we
714          * need to change port (MAIN_I3 or QUICK_I1)
715          */
716         if (((st->st_state == STATE_MAIN_I3) || (st->st_state == STATE_QUICK_I1)) &&
717                 (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) &&
718                 (st->nat_traversal & NAT_T_DETECTED) &&
719                 (c->this.host_port != NAT_T_IKE_FLOAT_PORT)) {
720                 DBG(DBG_NATT,
721                         DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);
722                 );
723                 c->this.host_port = NAT_T_IKE_FLOAT_PORT;
724                 c->that.host_port = NAT_T_IKE_FLOAT_PORT;
725                 /*
726                  * Also update pending connections or they will be deleted if uniqueids
727                  * option is set.
728                  */
729                 update_pending(st, st);
730         }
731
732         /**
733          * Find valid interface according to local port (500/4500)
734          */
735         if (((c->this.host_port == NAT_T_IKE_FLOAT_PORT) &&
736                  (c->interface->ike_float == FALSE)) ||
737                 ((c->this.host_port != NAT_T_IKE_FLOAT_PORT) &&
738                  (c->interface->ike_float == TRUE))) {
739                 for (i = interfaces; i !=  NULL; i = i->next) {
740                         if ((sameaddr(&c->interface->addr, &i->addr)) &&
741                                 (i->ike_float != c->interface->ike_float)) {
742                                 DBG(DBG_NATT,
743                                         DBG_log("NAT-T: using interface %s:%d", i->rname,
744                                                 i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);
745                                 );
746                                 c->interface = i;
747                                 break;
748                         }
749                 }
750         }
751 }
752
753 struct _new_klips_mapp_nfo {
754         struct sadb_sa *sa;
755         ip_address src, dst;
756         u_int16_t sport, dport;
757 };
758
759 static void nat_t_new_klips_mapp (struct state *st, void *data)
760 {
761         struct connection *c = st->st_connection;
762         struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
763
764         if ((c) && (st->st_esp.present) &&
765                 sameaddr(&c->that.host_addr, &(nfo->src)) &&
766                 (st->st_esp.our_spi == nfo->sa->sadb_sa_spi)) {
767                 nat_traversal_new_mapping(&c->that.host_addr, c->that.host_port,
768                         &(nfo->dst), nfo->dport);
769         }
770 }
771
772 void process_pfkey_nat_t_new_mapping(
773         struct sadb_msg *msg __attribute__ ((unused)),
774         struct sadb_ext *extensions[SADB_EXT_MAX + 1])
775 {
776         struct _new_klips_mapp_nfo nfo;
777         struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
778         struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
779         struct sockaddr *srca, *dsta;
780         err_t ugh = NULL;
781
782         nfo.sa = (void *) extensions[SADB_EXT_SA];
783
784         if ((!nfo.sa) || (!srcx) || (!dstx)) {
785                 log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "
786                         "got NULL params");
787                 return;
788         }
789
790         srca = ((struct sockaddr *)(void *)&srcx[1]);
791         dsta = ((struct sockaddr *)(void *)&dstx[1]);
792
793         if ((srca->sa_family != AF_INET) || (dsta->sa_family != AF_INET)) {
794                 ugh = "only AF_INET supported";
795         }
796         else {
797                 char text_said[SATOT_BUF];
798                 char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];
799                 ip_said said;
800
801                 initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr,
802                         sizeof(((const struct sockaddr_in *)srca)->sin_addr),
803                         srca->sa_family, &(nfo.src));
804                 nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port);
805                 initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr,
806                         sizeof(((const struct sockaddr_in *)dsta)->sin_addr),
807                         dsta->sa_family, &(nfo.dst));
808                 nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port);
809
810                 DBG(DBG_NATT,
811                         initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said);
812                         satot(&said, 0, text_said, SATOT_BUF);
813                         addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF);
814                         addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF);
815                         DBG_log("new klips mapping %s %s:%d %s:%d",
816                                 text_said, _srca, nfo.sport, _dsta, nfo.dport);
817                 );
818
819                 for_each_state((void *)nat_t_new_klips_mapp, &nfo);
820         }
821
822         if (ugh != NULL)
823                 log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);
824 }
825
826 #endif
827