1 /* FreeS/WAN NAT-Traversal
2 * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security
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>.
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
14 * RCSID $Id: nat_traversal.c,v 1.5 2005-12-19 00:41:37 danield Exp $
27 #include "constants.h"
32 #include "connections.h"
46 #include "nat_traversal.h"
50 /* #define FORCE_NAT_TRAVERSAL */
52 #define NAT_T_SUPPORT_LAST_DRAFTS
59 #define UDP_ESPINUDP 100
62 #define DEFAULT_KEEP_ALIVE_PERIOD 20
65 /* Alg patch: hash_digest_len -> hash_digest_size */
66 #define hash_digest_len hash_digest_size
69 bool nat_traversal_enabled = FALSE;
70 bool nat_traversal_support_port_floating = FALSE;
72 static unsigned int _kap = 0;
73 static unsigned int _ka_evt = 0;
74 static bool _force_ka = 0;
76 static const char *natt_version = "0.6";
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)"
84 void init_nat_traversal (bool activate, unsigned int keep_alive_period,
87 nat_traversal_enabled = activate;
88 #ifdef NAT_T_SUPPORT_LAST_DRAFTS
89 nat_traversal_support_port_floating = activate ? spf : FALSE;
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]" : "");
99 static void disable_nat_traversal (void)
101 nat_traversal_enabled = FALSE;
102 nat_traversal_support_port_floating = FALSE;
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)
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 !!");
117 * draft-ietf-ipsec-nat-t-ike-01.txt
119 * HASH = HASH(CKY-I | CKY-R | IP | Port)
121 * All values in network order
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)) {
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));
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));
138 hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));
139 hasher->hash_final(hash, &ctx);
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)) {
147 DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr,
148 sizeof(ip->u.v4.sin_addr.s_addr));
151 DBG_log("_natd_hash: port=%d", port);
152 DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);
158 * Add NAT-Traversal VIDs (supported ones)
160 * Used when we're Initiator
162 bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs)
165 if (nat_traversal_support_port_floating) {
167 if (r) r = out_vendorid(np, outs, VID_NATT_RFC);
169 if (r) r = out_vendorid(np, outs, VID_NATT_IETF_03);
170 if (r) r = out_vendorid(np, outs, VID_NATT_IETF_02);
172 if (r) r = out_vendorid(np, outs, VID_NATT_IETF_00);
176 u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid)
179 case VID_NATT_IETF_00:
180 return LELEM(NAT_TRAVERSAL_IETF_00_01);
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);
188 return LELEM(NAT_TRAVERSAL_RFC);
194 void nat_traversal_natd_lookup(struct msg_digest *md)
196 char hash[MAX_DIGEST_LEN];
197 struct payload_digest *p;
198 struct state *st = md->st;
201 if (!st || !md->iface || !st->st_oakley.hasher) {
202 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
208 for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++);
211 * We need at least 2 NAT-D (1 for us, many for peer)
214 loglog(RC_LOG_SERIOUS,
215 "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i);
216 st->nat_traversal = 0;
221 * First one with my IP & port
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)
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));
237 st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
241 * The others with sender IP & port
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)
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));
264 st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
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);
272 bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
273 struct msg_digest *md)
275 char hash[MAX_DIGEST_LEN];
276 struct state *st = md->st;
278 if (!st || !st->st_oakley.hasher) {
279 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
284 if (!out_modify_previous_np((st->nat_traversal & NAT_T_WITH_RFC_VALUES
285 ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), outs)) {
290 * First one with sender IP & port
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,
295 #ifdef FORCE_NAT_TRAVERSAL
298 ntohs(md->sender_port)
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")) {
308 * Second one with my IP & port
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,
313 #ifdef FORCE_NAT_TRAVERSAL
316 ntohs(st->st_connection->this.host_port)
319 return (out_generic_raw(np, &isakmp_nat_d, outs,
320 hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
324 * nat_traversal_natoa_lookup()
326 * Look for NAT-OA in message
328 void nat_traversal_natoa_lookup(struct msg_digest *md)
330 struct payload_digest *p;
331 struct state *st = md->st;
335 if (!st || !md->iface) {
336 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
341 /** Initialize NAT-OA */
342 anyaddr(AF_INET, &st->nat_oa);
345 for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++);
348 DBG_log("NAT-Traversal: received %d NAT-OA.", i);
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);
360 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
361 "using first, ignoring others", i);
365 p = md->chain[ISAKMP_NEXT_NATOA_RFC];
368 DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
371 switch (p->payload.nat_oa.isanoa_idtype) {
373 if (pbs_left(&p->pbs) == sizeof(struct in_addr)) {
374 initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip);
377 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA "
378 "with invalid IP size (%d)", pbs_left(&p->pbs));
383 if (pbs_left(&p->pbs) == sizeof(struct in6_addr)) {
384 initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip);
387 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA "
388 "with invalid IP size (%d)", pbs_left(&p->pbs));
393 loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
394 "invalid ID Type (%d) in NAT-OA - ignored",
395 p->payload.nat_oa.isanoa_idtype);
402 char ip_t[ADDRTOT_BUF];
403 addrtot(&ip, 0, ip_t, sizeof(ip_t));
404 DBG_log("received NAT-OA: %s", ip_t);
408 if (isanyaddr(&ip)) {
409 loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA...");
416 bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs,
419 struct isakmp_nat_oa natoa;
421 unsigned char ip_val[sizeof(struct in6_addr)];
425 if ((!st) || (!st->st_connection)) {
426 loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
430 ip = &(st->st_connection->this.host_addr);
432 if (!out_modify_previous_np((st->nat_traversal & NAT_T_WITH_RFC_VALUES
433 ? ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS), outs)) {
437 memset(&natoa, 0, sizeof(natoa));
438 natoa.isanoa_np = np;
440 switch (addrtypeof(ip)) {
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;
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;
452 loglog(RC_LOG_SERIOUS, "NAT-Traversal: "
453 "invalid addrtypeof()=%d", addrtypeof(ip));
457 if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs))
460 if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA"))
464 DBG_dump("NAT-OA (S):", ip_val, ip_len);
467 close_output_pbs(&pbs);
471 void nat_traversal_show_result (u_int32_t nt, u_int16_t sport)
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];
478 case LELEM(NAT_TRAVERSAL_IETF_02_03):
479 mth = natt_methods[1];
481 case LELEM(NAT_TRAVERSAL_RFC):
482 mth = natt_methods[2];
485 switch (nt & NAT_T_DETECTED) {
487 rslt = "no NAT detected";
489 case LELEM(NAT_TRAVERSAL_NAT_BHND_ME):
492 case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
493 rslt = "peer is NATed";
495 case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER):
496 rslt = "both are NATed";
499 loglog(RC_LOG_SERIOUS,
500 "NAT-Traversal: Result using %s: %s",
501 mth ? mth : "unknown method",
502 rslt ? rslt : "unknown result"
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.",
515 int nat_traversal_espinudp_socket (int sk, u_int32_t type)
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();
528 void nat_traversal_new_ka_event (void)
530 if (_ka_evt) return; /* Event already schedule */
531 event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL);
535 static void nat_traversal_send_ka (struct state *st)
537 static unsigned char ka_payload = 0xff;
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);
546 /** save state chunk */
547 setchunk(sav, st->st_tpacket.ptr, st->st_tpacket.len);
549 /** send keep alive */
550 setchunk(st->st_tpacket, &ka_payload, 1);
551 _send_packet(st, "NAT-T Keep Alive", FALSE);
553 /** restore state chunk */
554 setchunk(st->st_tpacket, sav.ptr, sav.len);
558 * Find ISAKMP States with NAT-T and send keep-alive
560 static void nat_traversal_ka_event_state (struct state *st, void *data)
562 unsigned int *_kap_st = (unsigned int *)data;
563 const struct connection *c = st->st_connection;
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))
571 * - ISAKMP established
572 * - NAT-Traversal detected
573 * - NAT-KeepAlive needed (we are NATed)
575 if (c->newest_isakmp_sa != st->st_serialno) {
577 * if newest is also valid, ignore this one, we will only use
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))
591 nat_traversal_send_ka(st);
597 void nat_traversal_ka_event (void)
599 unsigned int _kap_st = 0;
601 _ka_evt = 0; /* ready to be reschedule */
603 for_each_state((void *)nat_traversal_ka_event_state, &_kap_st);
607 * If there are still states who needs Keep-Alive, schedule new event
609 nat_traversal_new_ka_event();
613 struct _new_mapp_nfo {
615 u_int16_t sport, dport;
618 static void nat_traversal_find_new_mapp_state (struct state *st, void *data)
620 struct connection *c = st->st_connection;
621 struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data;
623 if ((c) && sameaddr(&c->that.host_addr, &(nfo->addr)) &&
624 (c->that.host_port == nfo->sport)) {
629 c->that.host_port = nfo->dport;
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)) {
635 * If ipsec update failed, restore old port or we'll
636 * not be able to update anymore.
638 c->that.host_port = nfo->sport;
644 static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport,
645 const ip_address *dst, u_int16_t dport)
647 char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF];
648 struct _new_mapp_nfo nfo;
650 addrtot(src, 0, srca, ADDRTOT_BUF);
651 addrtot(dst, 0, dsta, ADDRTOT_BUF);
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);
660 if (sport == dport) {
665 DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport);
671 for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo);
676 void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st)
678 struct connection *c = st ? st->st_connection : NULL;
679 struct iface *i = NULL;
681 if ((st == NULL) || (c == NULL)) {
687 * If interface type has changed, update local port (500/4500)
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;
696 DBG_log("NAT-T: updating local port to %d", c->this.host_port);
701 * If source port has changed, update (including other states and
702 * established kernel SA)
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;
713 * If we're initiator and NAT-T (with port floating) is detected, we
714 * need to change port (MAIN_I3 or QUICK_I1)
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)) {
721 DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT);
723 c->this.host_port = NAT_T_IKE_FLOAT_PORT;
724 c->that.host_port = NAT_T_IKE_FLOAT_PORT;
726 * Also update pending connections or they will be deleted if uniqueids
729 update_pending(st, st);
733 * Find valid interface according to local port (500/4500)
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)) {
743 DBG_log("NAT-T: using interface %s:%d", i->rname,
744 i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port);
753 struct _new_klips_mapp_nfo {
756 u_int16_t sport, dport;
759 static void nat_t_new_klips_mapp (struct state *st, void *data)
761 struct connection *c = st->st_connection;
762 struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data;
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);
772 void process_pfkey_nat_t_new_mapping(
773 struct sadb_msg *msg __attribute__ ((unused)),
774 struct sadb_ext *extensions[SADB_EXT_MAX + 1])
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;
782 nfo.sa = (void *) extensions[SADB_EXT_SA];
784 if ((!nfo.sa) || (!srcx) || (!dstx)) {
785 log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: "
790 srca = ((struct sockaddr *)(void *)&srcx[1]);
791 dsta = ((struct sockaddr *)(void *)&dstx[1]);
793 if ((srca->sa_family != AF_INET) || (dsta->sa_family != AF_INET)) {
794 ugh = "only AF_INET supported";
797 char text_said[SATOT_BUF];
798 char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF];
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);
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);
819 for_each_state((void *)nat_t_new_klips_mapp, &nfo);
823 log("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh);