···11-/* $OpenBSD: exchange.h,v 1.26 2004/05/03 21:23:51 hshoexer Exp $ */
11+/* $OpenBSD: exchange.h,v 1.27 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: exchange.h,v 1.28 2000/09/28 12:54:28 niklas Exp $ */
3344/*
···212212};
213213214214/* The flag bits. */
215215-#define EXCHANGE_FLAG_I_COMMITTED 1
216216-#define EXCHANGE_FLAG_HE_COMMITTED 2
215215+#define EXCHANGE_FLAG_I_COMMITTED 0x01
216216+#define EXCHANGE_FLAG_HE_COMMITTED 0x02
217217#define EXCHANGE_FLAG_COMMITTED (EXCHANGE_FLAG_I_COMMITTED \
218218 | EXCHANGE_FLAG_HE_COMMITTED)
219219-#define EXCHANGE_FLAG_ENCRYPT 4
219219+#define EXCHANGE_FLAG_ENCRYPT 0x04
220220+#define EXCHANGE_FLAG_NAT_T_CAP_PEER 0x08 /* Peer is NAT capable. */
221221+#define EXCHANGE_FLAG_NAT_T_ENABLE 0x10 /* We are doing NAT-T. */
222222+#define EXCHANGE_FLAG_NAT_T_KEEPALIVE 0x20 /* We are the NAT:ed peer. */
223223+#define EXCHANGE_FLAG_DPD_CAP_PEER 0x40 /* Peer is DPD capable. */
220224221225extern int exchange_add_certs(struct message *);
222226extern void exchange_finalize(struct message *);
+54
sbin/isakmpd/features/nat_traversal
···11+# $OpenBSD: nat_traversal,v 1.1 2004/06/20 15:24:05 ho Exp $
22+33+#
44+# Copyright (c) 2004 H�kan Olsson. All rights reserved.
55+#
66+# Redistribution and use in source and binary forms, with or without
77+# modification, are permitted provided that the following conditions
88+# are met:
99+# 1. Redistributions of source code must retain the above copyright
1010+# notice, this list of conditions and the following disclaimer.
1111+# 2. Redistributions in binary form must reproduce the above copyright
1212+# notice, this list of conditions and the following disclaimer in the
1313+# documentation and/or other materials provided with the distribution.
1414+#
1515+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1616+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1919+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2020+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2121+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2323+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525+#
2626+2727+NAT_TRAVERSAL= nat_traversal.c udp_encap.c
2828+# $OpenBSD: nat_traversal,v 1.1 2004/06/20 15:24:05 ho Exp $
2929+3030+#
3131+# Copyright (c) 2004 H�kan Olsson. All rights reserved.
3232+#
3333+# Redistribution and use in source and binary forms, with or without
3434+# modification, are permitted provided that the following conditions
3535+# are met:
3636+# 1. Redistributions of source code must retain the above copyright
3737+# notice, this list of conditions and the following disclaimer.
3838+# 2. Redistributions in binary form must reproduce the above copyright
3939+# notice, this list of conditions and the following disclaimer in the
4040+# documentation and/or other materials provided with the distribution.
4141+#
4242+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4343+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4444+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4545+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4646+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4747+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4848+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4949+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5050+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5151+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5252+#
5353+5454+NAT_TRAVERSAL= nat_traversal.c udp_encap.c
+47-2
sbin/isakmpd/ike_phase_1.c
···11-/* $OpenBSD: ike_phase_1.c,v 1.50 2004/06/14 09:55:41 ho Exp $ */
11+/* $OpenBSD: ike_phase_1.c,v 1.51 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: ike_phase_1.c,v 1.31 2000/12/11 23:47:56 niklas Exp $ */
3344/*
···4545#include "crypto.h"
4646#include "dh.h"
4747#include "doi.h"
4848+#ifdef USE_DPD
4949+#include "dpd.h"
5050+#endif
4851#include "exchange.h"
4952#include "hash.h"
5053#include "ike_auth.h"
···5558#include "log.h"
5659#include "math_group.h"
5760#include "message.h"
6161+#if defined (USE_NAT_TRAVERSAL)
6262+#include "nat_traversal.h"
6363+#endif
5864#include "prf.h"
5965#include "sa.h"
6066#include "transport.h"
···359365 transforms_len += transform_len[i];
360366 }
361367368368+#if defined (USE_NAT_TRAVERSAL)
369369+ /* Advertise NAT-T capability. */
370370+ if (nat_t_add_vendor_payloads(msg))
371371+ goto bail_out;
372372+#endif
373373+374374+#if defined (USE_DPD)
375375+ /* Advertise DPD capability. */
376376+ if (dpd_add_vendor_payload(msg))
377377+ goto bail_out;
378378+#endif
379379+362380 conf_free_list(conf);
363381 free(transform);
364382 free(transform_len);
···511529ike_phase_1_responder_send_SA(struct message *msg)
512530{
513531 /* Add the SA payload with the transform that was chosen. */
514514- return message_add_sa_payload(msg);
532532+ if (message_add_sa_payload(msg))
533533+ return -1;
534534+535535+#if defined (USE_NAT_TRAVERSAL)
536536+ /* Advertise NAT-T capability. */
537537+ if (nat_t_add_vendor_payloads(msg))
538538+ return -1;
539539+#endif
540540+541541+#if defined (USE_DPD)
542542+ /* Advertise DPD capability. */
543543+ if (dpd_add_vendor_payload(msg))
544544+ return -1;
545545+#endif
546546+ return 0;
515547}
516548517549/* Send our public DH value and a nonce to the peer. */
···533565 /* XXX Log? */
534566 return -1;
535567 }
568568+#if defined (USE_NAT_TRAVERSAL)
569569+ /* If this exchange uses NAT-Traversal, add NAT-D payloads now. */
570570+ if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
571571+ if (nat_t_exchange_add_nat_d(msg)) {
572572+ /* XXX Log? */
573573+ return -1;
574574+ }
575575+#endif
536576 return 0;
537577}
538578···555595 /* XXX How to log and notify peer? */
556596 return -1;
557597 }
598598+#if defined (USE_NAT_TRAVERSAL)
599599+ /* Check NAT-D payloads and contents. */
600600+ if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
601601+ (void)nat_t_exchange_check_nat_d(msg);
602602+#endif
558603 return 0;
559604}
560605
+17-6
sbin/isakmpd/init.c
···11-/* $OpenBSD: init.c,v 1.29 2004/04/15 18:39:25 deraadt Exp $ */
11+/* $OpenBSD: init.c,v 1.30 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: init.c,v 1.25 2000/03/30 14:27:24 ho Exp $ */
3344/*
55 * Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved.
66 * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved.
77- * Copyright (c) 2003 H�kan Olsson. All rights reserved.
77+ * Copyright (c) 2003, 2004 H�kan Olsson. All rights reserved.
88 *
99 * Redistribution and use in source and binary forms, with or without
1010 * modification, are permitted provided that the following conditions
···5050#include "sa.h"
5151#include "timer.h"
5252#include "transport.h"
5353+#include "virtual.h"
5354#include "udp.h"
5455#include "ui.h"
5556#include "util.h"
56575757-#ifdef USE_POLICY
5858+#if defined (USE_POLICY)
5859#include "policy.h"
6060+#endif
6161+6262+#if defined (USE_NAT_TRAVERSAL)
6363+#include "nat_traversal.h"
6464+#include "udp_encap.h"
5965#endif
60666167void
···7884 /* This depends on conf_init, thus check as soon as possible. */
7985 log_reinit();
80868181-#ifdef USE_POLICY
8787+#if defined (USE_POLICY)
8288 /* policy_init depends on conf_init having run. */
8389 policy_init();
8490#endif
···89959096 sa_init();
9197 transport_init();
9898+ virtual_init();
9299 udp_init();
100100+#if defined (USE_NAT_TRAVERSAL)
101101+ nat_t_init();
102102+ udp_encap_init();
103103+#endif
93104 ui_init();
94105}
95106···116127117128 log_reinit();
118129119119-#ifdef USE_POLICY
130130+#if defined (USE_POLICY)
120131 /* Reread the policies. */
121132 policy_init();
122133#endif
···129140 connection_reinit();
130141131142 /*
132132- * Rescan interfaces.
143143+ * Rescan interfaces (call reinit() in all transports).
133144 */
134145 transport_reinit();
135146
+29-21
sbin/isakmpd/ipsec.c
···11-/* $OpenBSD: ipsec.c,v 1.96 2004/06/17 19:39:38 hshoexer Exp $ */
11+/* $OpenBSD: ipsec.c,v 1.97 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */
3344/*
···11191119 void *vmsg)
11201120{
11211121 struct message *msg = vmsg;
11221122+ u_int16_t dv = decode_16(value);
1122112311231124 if (msg->exchange->phase == 1) {
11241125 switch (type) {
11251126 case IKE_ATTR_ENCRYPTION_ALGORITHM:
11261126- return !crypto_get(from_ike_crypto(decode_16(value)));
11271127+ return !crypto_get(from_ike_crypto(dv));
11271128 case IKE_ATTR_HASH_ALGORITHM:
11281128- return !hash_get(from_ike_hash(decode_16(value)));
11291129+ return !hash_get(from_ike_hash(dv));
11291130 case IKE_ATTR_AUTHENTICATION_METHOD:
11301130- return !ike_auth_get(decode_16(value));
11311131+ return !ike_auth_get(dv);
11311132 case IKE_ATTR_GROUP_DESCRIPTION:
11321132- return (decode_16(value) < IKE_GROUP_DESC_MODP_768
11331133- || decode_16(value) > IKE_GROUP_DESC_MODP_1536)
11341134- && (decode_16(value) < IKE_GROUP_DESC_MODP_2048
11351135- || decode_16(value) > IKE_GROUP_DESC_MODP_8192);
11331133+ return (dv < IKE_GROUP_DESC_MODP_768
11341134+ || dv > IKE_GROUP_DESC_MODP_1536)
11351135+ && (dv < IKE_GROUP_DESC_MODP_2048
11361136+ || dv > IKE_GROUP_DESC_MODP_8192);
11361137 case IKE_ATTR_GROUP_TYPE:
11371138 return 1;
11381139 case IKE_ATTR_GROUP_PRIME:
···11461147 case IKE_ATTR_GROUP_CURVE_B:
11471148 return 1;
11481149 case IKE_ATTR_LIFE_TYPE:
11491149- return decode_16(value) < IKE_DURATION_SECONDS
11501150- || decode_16(value) > IKE_DURATION_KILOBYTES;
11501150+ return dv < IKE_DURATION_SECONDS
11511151+ || dv > IKE_DURATION_KILOBYTES;
11511152 case IKE_ATTR_LIFE_DURATION:
11521153 return len != 2 && len != 4;
11531154 case IKE_ATTR_PRF:
···11571158 * Our crypto routines only allows key-lengths which
11581159 * are multiples of an octet.
11591160 */
11601160- return decode_16(value) % 8 != 0;
11611161+ return dv % 8 != 0;
11611162 case IKE_ATTR_FIELD_SIZE:
11621163 return 1;
11631164 case IKE_ATTR_GROUP_ORDER:
···11661167 } else {
11671168 switch (type) {
11681169 case IPSEC_ATTR_SA_LIFE_TYPE:
11691169- return decode_16(value) < IPSEC_DURATION_SECONDS
11701170- || decode_16(value) > IPSEC_DURATION_KILOBYTES;
11701170+ return dv < IPSEC_DURATION_SECONDS
11711171+ || dv > IPSEC_DURATION_KILOBYTES;
11711172 case IPSEC_ATTR_SA_LIFE_DURATION:
11721173 return len != 2 && len != 4;
11731174 case IPSEC_ATTR_GROUP_DESCRIPTION:
11741174- return (decode_16(value) < IKE_GROUP_DESC_MODP_768
11751175- || decode_16(value) > IKE_GROUP_DESC_MODP_1536)
11761176- && (decode_16(value) < IKE_GROUP_DESC_MODP_2048
11771177- || IKE_GROUP_DESC_MODP_8192 < decode_16(value));
11751175+ return (dv < IKE_GROUP_DESC_MODP_768
11761176+ || dv > IKE_GROUP_DESC_MODP_1536)
11771177+ && (dv < IKE_GROUP_DESC_MODP_2048
11781178+ || IKE_GROUP_DESC_MODP_8192 < dv);
11781179 case IPSEC_ATTR_ENCAPSULATION_MODE:
11791179- return decode_16(value) < IPSEC_ENCAP_TUNNEL
11801180- || decode_16(value) > IPSEC_ENCAP_TRANSPORT;
11801180+#if defined (USE_NAT_TRAVERSAL)
11811181+ return dv != IPSEC_ENCAP_TUNNEL
11821182+ && dv != IPSEC_ENCAP_TRANSPORT
11831183+ && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL
11841184+ && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT;
11851185+#else
11861186+ return dv < IPSEC_ENCAP_TUNNEL
11871187+ || dv > IPSEC_ENCAP_TRANSPORT;
11881188+#endif /* USE_NAT_TRAVERSAL */
11811189 case IPSEC_ATTR_AUTHENTICATION_ALGORITHM:
11821182- return decode_16(value) < IPSEC_AUTH_HMAC_MD5
11831183- || decode_16(value) > IPSEC_AUTH_HMAC_RIPEMD;
11901190+ return dv < IPSEC_AUTH_HMAC_MD5
11911191+ || dv > IPSEC_AUTH_HMAC_RIPEMD;
11841192 case IPSEC_ATTR_KEY_LENGTH:
11851193 /*
11861194 * XXX Blowfish needs '0'. Others appear to disregard
+10-5
sbin/isakmpd/isakmp.h
···11-/* $OpenBSD: isakmp.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */
11+/* $OpenBSD: isakmp.h,v 1.7 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: isakmp.h,v 1.11 2000/07/05 10:48:43 ho Exp $ */
3344/*
55 * Copyright (c) 1998 Niklas Hallqvist. All rights reserved.
66+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
67 *
78 * Redistribution and use in source and binary forms, with or without
89 * modification, are permitted provided that the following conditions
···3536#include "isakmp_fld.h"
3637#include "isakmp_num.h"
37383838-/* ISAKMP default transport */
3939-#define ISAKMP_DEFAULT_TRANSPORT "udp"
4040-4139/* IANA assigned port */
4242-#define UDP_DEFAULT_PORT 500
4040+#define UDP_DEFAULT_PORT 500
4141+#define UDP_DEFAULT_PORT_STR "500"
4242+4343+#define ISAKMP_DEFAULT_TRANSPORT "udp"
4444+4545+/* draft-ietf-ipsec-nat-t-ike-07.txt */
4646+#define UDP_ENCAP_DEFAULT_PORT 4500
4747+#define UDP_ENCAP_DEFAULT_PORT_STR "4500"
43484449/* ISAKMP header extras defines */
4550#define ISAKMP_HDR_COOKIES_OFF ISAKMP_HDR_ICOOKIE_OFF
+13-1
sbin/isakmpd/isakmp_fld.fld
···11-# $OpenBSD: isakmp_fld.fld,v 1.7 2003/06/03 14:28:16 ho Exp $
11+# $OpenBSD: isakmp_fld.fld,v 1.8 2004/06/20 15:24:05 ho Exp $
22# $EOM: isakmp_fld.fld,v 1.5 1999/04/25 13:38:22 niklas Exp $
3344#
···150150 ID num 2
151151 ATTRS raw
152152.
153153+154154+# NAT Discovery payload.
155155+ISAKMP_NAT_D : ISAKMP_GEN
156156+ DATA raw
157157+.
158158+159159+# NAT Original Address payload.
160160+ISAKMP_NAT_OA : ISAKMP_GEN
161161+ TYPE num 1
162162+ RESERVED ign 3
163163+ DATA raw
164164+.
+80-23
sbin/isakmpd/message.c
···11-/* $OpenBSD: message.c,v 1.80 2004/06/20 15:11:29 ho Exp $ */
11+/* $OpenBSD: message.c,v 1.81 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */
3344/*
55 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved.
66 * Copyright (c) 1999 Angelos D. Keromytis. All rights reserved.
77- * Copyright (c) 1999, 2000, 2001 H�kan Olsson. All rights reserved.
77+ * Copyright (c) 1999, 2000, 2001, 2004 H�kan Olsson. All rights reserved.
88 *
99 * Redistribution and use in source and binary forms, with or without
1010 * modification, are permitted provided that the following conditions
···4545#include "constants.h"
4646#include "crypto.h"
4747#include "doi.h"
4848+#ifdef USE_DPD
4949+#include "dpd.h"
5050+#endif
4851#include "exchange.h"
4952#include "field.h"
5053#include "hash.h"
···5356#include "isakmp.h"
5457#include "log.h"
5558#include "message.h"
5959+#if defined (USE_NAT_TRAVERSAL)
6060+#include "nat_traversal.h"
6161+#endif
5662#include "prf.h"
5763#include "sa.h"
5864#include "timer.h"
···8591static int message_validate_hash(struct message *, struct payload *);
8692static int message_validate_id(struct message *, struct payload *);
8793static int message_validate_key_exch(struct message *, struct payload *);
9494+static int message_validate_nat_d(struct message *, struct payload *);
9595+static int message_validate_nat_oa(struct message *, struct payload *);
8896static int message_validate_nonce(struct message *, struct payload *);
8997static int message_validate_notify(struct message *, struct payload *);
9098static int message_validate_proposal(struct message *, struct payload *);
···102110 message_validate_id, message_validate_cert, message_validate_cert_req,
103111 message_validate_hash, message_validate_sig, message_validate_nonce,
104112 message_validate_notify, message_validate_delete,
105105- message_validate_vendor, message_validate_attribute
113113+ message_validate_vendor, message_validate_attribute,
114114+ message_validate_nat_d, message_validate_nat_oa
106115};
107116108117static struct field *fields[] = {
109118 isakmp_sa_fld, isakmp_prop_fld, isakmp_transform_fld, isakmp_ke_fld,
110119 isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld,
111120 isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld,
112112- isakmp_vendor_fld, isakmp_attribute_fld
121121+ isakmp_vendor_fld, isakmp_attribute_fld, isakmp_nat_d_fld,
122122+ isakmp_nat_oa_fld
113123};
114124115125/*
···211221 link);
212222213223 /* If we are on the send queue, remove us from there. */
214214- if (msg->flags & MSG_IN_TRANSIT) {
215215- if (msg->flags & MSG_PRIORITIZED)
216216- TAILQ_REMOVE(&msg->transport->prio_sendq, msg, link);
217217- else
218218- TAILQ_REMOVE(&msg->transport->sendq, msg, link);
219219- }
224224+ if (msg->flags & MSG_IN_TRANSIT)
225225+ TAILQ_REMOVE(msg->transport->vtbl->get_queue(msg), msg, link);
226226+220227 transport_release(msg->transport);
221228222229 if (msg->isakmp_sa)
···478485 return -1;
479486 }
480487 /*
481481- * Check the certificate types we support and if an acceptable authority
482482- * is included in the payload check if it can be decoded
488488+ * Check the certificate types we support and if an acceptable
489489+ * authority is included in the payload check if it can be decoded
483490 */
484491 cert = cert_get(GET_ISAKMP_CERTREQ_TYPE(p->p));
485492 if (!cert || (len && !cert->certreq_validate(p->p +
···745752 return 0;
746753}
747754755755+/* Validate the NAT-D payload P in message MSG. */
756756+static int
757757+message_validate_nat_d(struct message *msg, struct payload *p)
758758+{
759759+ struct exchange *exchange = msg->exchange;
760760+761761+ if (!exchange) {
762762+ /* We should have an exchange at this point. */
763763+ log_print("message_validate_nat_d: payload out of sequence");
764764+ message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1);
765765+ return -1;
766766+ }
767767+768768+ if (exchange->phase != 1) {
769769+ log_print("message_validate_nat_d: "
770770+ "NAT-D payload must be in phase 1");
771771+ message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1);
772772+ return -1;
773773+ }
774774+775775+ /* Mark as handled. */
776776+ p->flags |= PL_MARK;
777777+778778+ return 0;
779779+}
780780+781781+/* Validate the NAT-OA payload P in message MSG. */
782782+static int
783783+message_validate_nat_oa(struct message *msg, struct payload *p)
784784+{
785785+ struct exchange *exchange = msg->exchange;
786786+787787+ if (!exchange) {
788788+ /* We should have an exchange at this point. */
789789+ log_print("message_validate_nat_d: payload out of sequence");
790790+ message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1);
791791+ return -1;
792792+ }
793793+794794+#ifdef notyet /* XXX Probably never, due to patent issues. */
795795+ /* Mark as handled. */
796796+ p->flags |= PL_MARK;
797797+#endif
798798+799799+ return 0;
800800+}
801801+748802/* Validate the nonce payload P in message MSG. */
749803static int
750804message_validate_nonce(struct message *msg, struct payload *p)
···10201074 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1);
10211075 return -1;
10221076 }
10231023- LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: vendor ID seen"));
10771077+#if defined (USE_DPD)
10781078+ dpd_check_vendor_payload(msg, p);
10791079+#endif
10801080+#if defined (USE_NAT_TRAVERSAL)
10811081+ nat_t_check_vendor_payload(msg, p);
10821082+#endif
10831083+ if (!(p->flags & PL_MARK))
10841084+ LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: "
10851085+ "vendor ID seen"));
10241086 return 0;
10251087}
10261088···11341196 * made nicer.
11351197 */
11361198 setup_isakmp_sa = zero_test(buf + ISAKMP_HDR_RCOOKIE_OFF,
11371137- ISAKMP_HDR_RCOOKIE_LEN);
11991199+ ISAKMP_HDR_RCOOKIE_LEN);
11381200 if (setup_isakmp_sa) {
11391201 /*
11401202 * This might be a retransmission of a former ISAKMP SA setup
···14451507 * has left the queue, don't queue it again, as it will result
14461508 * in a circular list.
14471509 */
14481448- q = msg->flags & MSG_PRIORITIZED ? &msg->transport->prio_sendq :
14491449- &msg->transport->sendq;
14501450-15101510+ q = msg->transport->vtbl->get_queue(msg);
14511511 for (m = TAILQ_FIRST(q); m; m = TAILQ_NEXT(m, link))
14521512 if (m == msg) {
14531513 LOG_DBG((LOG_MESSAGE, 60,
···18801940 */
18811941 if (exchange->last_sent) {
18821942 if (exchange->last_sent == exchange->in_transit) {
18831883- if (exchange->in_transit->flags & MSG_PRIORITIZED)
18841884- TAILQ_REMOVE(&exchange->in_transit->transport->prio_sendq,
18851885- exchange->in_transit, link);
18861886- else
18871887- TAILQ_REMOVE(&exchange->in_transit->transport->sendq,
18881888- exchange->in_transit, link);
19431943+ struct message *m = exchange->in_transit;
19441944+ TAILQ_REMOVE(m->transport->vtbl->get_queue(m), m,
19451945+ link);
18891946 exchange->in_transit = 0;
18901947 }
18911948 message_free(exchange->last_sent);
+384
sbin/isakmpd/nat_traversal.c
···11+/* $OpenBSD: nat_traversal.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
55+ *
66+ * Redistribution and use in source and binary forms, with or without
77+ * modification, are permitted provided that the following conditions
88+ * are met:
99+ * 1. Redistributions of source code must retain the above copyright
1010+ * notice, this list of conditions and the following disclaimer.
1111+ * 2. Redistributions in binary form must reproduce the above copyright
1212+ * notice, this list of conditions and the following disclaimer in the
1313+ * documentation and/or other materials provided with the distribution.
1414+ *
1515+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1616+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1919+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2020+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2121+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2323+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525+ */
2626+2727+#include <sys/types.h>
2828+#include <stdlib.h>
2929+3030+#include "sysdep.h"
3131+3232+#include "exchange.h"
3333+#include "hash.h"
3434+#include "ipsec.h"
3535+#include "isakmp_fld.h"
3636+#include "isakmp_num.h"
3737+#include "ipsec_num.h"
3838+#include "hash.h"
3939+#include "log.h"
4040+#include "message.h"
4141+#include "nat_traversal.h"
4242+#include "prf.h"
4343+#include "sa.h"
4444+#include "transport.h"
4545+#include "util.h"
4646+4747+/*
4848+ * XXX According to draft-ietf-ipsec-nat-t-ike-07.txt, the NAT-T
4949+ * capability of the other peer is determined by a particular vendor ID
5050+ * sent as the first message. This vendor ID string is supposed to be a
5151+ * MD5 hash of "RFC XXXX", where XXXX is the future RFC number.
5252+ *
5353+ * These seem to be the "well" known variants of this string in use by
5454+ * products today.
5555+ */
5656+static const char *isakmp_nat_t_cap_text[] = {
5757+ "draft-ietf-ipsec-nat-t-ike-00", /* V1 (XXX: may be obsolete) */
5858+ "draft-ietf-ipsec-nat-t-ike-02\n", /* V2 */
5959+ "draft-ietf-ipsec-nat-t-ike-03", /* V3 */
6060+#ifdef notyet
6161+ "RFC XXXX",
6262+#endif
6363+};
6464+6565+/* The MD5 hashes of the above strings is put in this array. */
6666+static char **nat_t_hashes;
6767+static size_t nat_t_hashsize;
6868+6969+static int nat_t_setup_hashes(void);
7070+static int nat_t_add_vendor_payload(struct message *, char *);
7171+static int nat_t_add_nat_d(struct message *, struct sockaddr *);
7272+static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *);
7373+7474+void
7575+nat_t_init(void)
7676+{
7777+ nat_t_hashes = (char **)NULL;
7878+}
7979+8080+/* Generate the NAT-T capability marker hashes. Executed only once. */
8181+static int
8282+nat_t_setup_hashes(void)
8383+{
8484+ struct hash *hash;
8585+ int n = sizeof isakmp_nat_t_cap_text / sizeof isakmp_nat_t_cap_text[0];
8686+ int i;
8787+8888+ /* The draft says to use MD5. */
8989+ hash = hash_get(HASH_MD5);
9090+ if (!hash) {
9191+ /* Should never happen. */
9292+ log_print("nat_t_setup_hashes: "
9393+ "could not find MD5 hash structure!");
9494+ return -1;
9595+ }
9696+ nat_t_hashsize = hash->hashsize;
9797+9898+ /* Allocate one more than is necessary, i.e NULL terminated. */
9999+ nat_t_hashes = (char **)calloc((size_t)(n + 1), sizeof(char *));
100100+ if (!nat_t_hashes) {
101101+ log_error("nat_t_setup_hashes: calloc (%lu,%lu) failed",
102102+ (unsigned long)n, (unsigned long)sizeof(char *));
103103+ return -1;
104104+ }
105105+106106+ /* Populate with hashes. */
107107+ for (i = 0; i < n; i++) {
108108+ nat_t_hashes[i] = (char *)malloc(nat_t_hashsize);
109109+ if (!nat_t_hashes[i]) {
110110+ log_error("nat_t_setup_hashes: malloc (%lu) failed",
111111+ (unsigned long)nat_t_hashsize);
112112+ goto errout;
113113+ }
114114+115115+ hash->Init(hash->ctx);
116116+ hash->Update(hash->ctx,
117117+ (unsigned char *)isakmp_nat_t_cap_text[i],
118118+ strlen(isakmp_nat_t_cap_text[i]));
119119+ hash->Final(nat_t_hashes[i], hash->ctx);
120120+121121+ LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: "
122122+ "MD5(\"%s\") (%d bytes)", isakmp_nat_t_cap_text[i],
123123+ nat_t_hashsize));
124124+ LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes",
125125+ nat_t_hashes[i], nat_t_hashsize));
126126+ }
127127+128128+ return 0;
129129+130130+ errout:
131131+ for (i = 0; i < n; i++)
132132+ if (nat_t_hashes[i])
133133+ free(nat_t_hashes[i]);
134134+ free(nat_t_hashes);
135135+ nat_t_hashes = NULL;
136136+ return -1;
137137+}
138138+139139+/* Add one NAT-T VENDOR payload. */
140140+static int
141141+nat_t_add_vendor_payload(struct message *msg, char *hash)
142142+{
143143+ size_t buflen = nat_t_hashsize + ISAKMP_GEN_SZ;
144144+ u_int8_t *buf;
145145+146146+ buf = malloc(buflen);
147147+ if (!buf) {
148148+ log_error("nat_t_add_vendor_payload: malloc (%lu) failed",
149149+ (unsigned long)buflen);
150150+ return -1;
151151+ }
152152+153153+ SET_ISAKMP_GEN_LENGTH(buf, buflen);
154154+ memcpy(buf + ISAKMP_VENDOR_ID_OFF, hash, nat_t_hashsize);
155155+ if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) {
156156+ free(buf);
157157+ return -1;
158158+ }
159159+160160+ return 0;
161161+}
162162+163163+/* Add the NAT-T capability markers (VENDOR payloads). */
164164+int
165165+nat_t_add_vendor_payloads(struct message *msg)
166166+{
167167+ int i = 0;
168168+169169+ if (!nat_t_hashes)
170170+ if (nat_t_setup_hashes())
171171+ return 0; /* XXX should this be an error? */
172172+173173+ while (nat_t_hashes[i])
174174+ if (nat_t_add_vendor_payload(msg, nat_t_hashes[i++]))
175175+ return -1;
176176+177177+ return 0;
178178+}
179179+180180+/*
181181+ * Check an incoming message for NAT-T capability markers.
182182+ */
183183+void
184184+nat_t_check_vendor_payload(struct message *msg, struct payload *p)
185185+{
186186+ u_int8_t *pbuf = p->p;
187187+ size_t vlen;
188188+ int i = 0;
189189+190190+ /* Already checked? */
191191+ if (p->flags & PL_MARK ||
192192+ msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
193193+ return;
194194+195195+ if (!nat_t_hashes)
196196+ if (nat_t_setup_hashes())
197197+ return;
198198+199199+ vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ;
200200+ if (vlen != nat_t_hashsize) {
201201+ LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: "
202202+ "bad size %d != %d", vlen, nat_t_hashsize));
203203+ return;
204204+ }
205205+206206+ while (nat_t_hashes[i])
207207+ if (memcmp(nat_t_hashes[i++], pbuf + ISAKMP_GEN_SZ,
208208+ vlen) == 0) {
209209+ /* This peer is NAT-T capable. */
210210+ msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER;
211211+ LOG_DBG((LOG_EXCHANGE, 10,
212212+ "nat_t_check_vendor_payload: "
213213+ "NAT-T capable peer detected"));
214214+ p->flags |= PL_MARK;
215215+ return;
216216+ }
217217+218218+ return;
219219+}
220220+221221+/* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */
222222+static u_int8_t *
223223+nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa,
224224+ size_t *hashlen)
225225+{
226226+ struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data;
227227+ struct hash *hash;
228228+ struct prf *prf;
229229+ u_int8_t *res;
230230+ in_port_t port;
231231+ int prf_type = PRF_HMAC; /* XXX */
232232+233233+ hash = hash_get(ie->hash->type);
234234+ if (hash == NULL) {
235235+ log_print ("nat_t_generate_nat_d_hash: no hash");
236236+ return NULL;
237237+ }
238238+239239+ prf = prf_alloc(prf_type, hash->type, msg->exchange->cookies,
240240+ ISAKMP_HDR_COOKIES_LEN);
241241+ if(!prf) {
242242+ log_print("nat_t_generate_nat_d_hash: prf_alloc failed");
243243+ return NULL;
244244+ }
245245+246246+ *hashlen = prf->blocksize;
247247+ res = (u_int8_t *)malloc((unsigned long)*hashlen);
248248+ if (!res) {
249249+ log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed",
250250+ (unsigned long)*hashlen);
251251+ prf_free(prf);
252252+ *hashlen = 0;
253253+ return NULL;
254254+ }
255255+256256+ port = sockaddr_port(sa);
257257+ memset(res, 0, *hashlen);
258258+259259+ prf->Update(prf->prfctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
260260+ prf->Update(prf->prfctx, (unsigned char *)&port, sizeof port);
261261+ prf->Final(res, prf->prfctx);
262262+ prf_free (prf);
263263+264264+ return res;
265265+}
266266+267267+/* Add a NAT-D payload to our message. */
268268+static int
269269+nat_t_add_nat_d(struct message *msg, struct sockaddr *sa)
270270+{
271271+ u_int8_t *hbuf, *buf;
272272+ size_t hbuflen, buflen;
273273+274274+ hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
275275+ if (!hbuf) {
276276+ log_print("nat_t_add_nat_d: NAT-D hash gen failed");
277277+ return -1;
278278+ }
279279+280280+ buflen = ISAKMP_NAT_D_DATA_OFF + hbuflen;
281281+ buf = malloc(buflen);
282282+ if (!buf) {
283283+ log_error("nat_t_add_nat_d: malloc (%lu) failed",
284284+ (unsigned long)buflen);
285285+ free(hbuf);
286286+ return -1;
287287+ }
288288+289289+ SET_ISAKMP_GEN_LENGTH(buf, buflen);
290290+ memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen);
291291+ free(hbuf);
292292+293293+ if (message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, buflen, 1)) {
294294+ free(buf);
295295+ return -1;
296296+ }
297297+298298+ return 0;
299299+}
300300+301301+/* We add two NAT-D payloads, one each for src and dst. */
302302+int
303303+nat_t_exchange_add_nat_d(struct message *msg)
304304+{
305305+ struct sockaddr *sa;
306306+307307+ msg->transport->vtbl->get_src(msg->transport, &sa);
308308+ if (nat_t_add_nat_d(msg, sa))
309309+ return -1;
310310+311311+ msg->transport->vtbl->get_dst(msg->transport, &sa);
312312+ if (nat_t_add_nat_d(msg, sa))
313313+ return -1;
314314+315315+ return 0;
316316+}
317317+318318+/* Generate and match a NAT-D hash against the NAT-D payload (pl.) data. */
319319+static int
320320+nat_t_match_nat_d_payload(struct message *msg, struct sockaddr *sa)
321321+{
322322+ struct payload *p;
323323+ u_int8_t *hbuf;
324324+ size_t hbuflen;
325325+ int found = 0;
326326+327327+ hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
328328+ if (!hbuf)
329329+ return 0;
330330+331331+ for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_NAT_D]); p;
332332+ p = TAILQ_NEXT(p, link)) {
333333+ if (GET_ISAKMP_GEN_LENGTH (p->p) !=
334334+ hbuflen + ISAKMP_NAT_D_DATA_OFF)
335335+ continue;
336336+337337+ if (memcmp(p->p + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen) == 0) {
338338+ found++;
339339+ break;
340340+ }
341341+ }
342342+ free(hbuf);
343343+ return found;
344344+}
345345+346346+/*
347347+ * Check if we need to activate NAT-T, and if we need to send keepalive
348348+ * messages to the other side, i.e if we are a nat:ed peer.
349349+ */
350350+int
351351+nat_t_exchange_check_nat_d(struct message *msg)
352352+{
353353+ struct sockaddr *sa;
354354+ int outgoing_path_is_clear, incoming_path_is_clear;
355355+356356+ /* Assume trouble, i.e NAT-boxes in our path. */
357357+ outgoing_path_is_clear = incoming_path_is_clear = 0;
358358+359359+ msg->transport->vtbl->get_src(msg->transport, &sa);
360360+ if (nat_t_match_nat_d_payload(msg, sa))
361361+ outgoing_path_is_clear = 1;
362362+363363+ msg->transport->vtbl->get_dst(msg->transport, &sa);
364364+ if (nat_t_match_nat_d_payload(msg, sa))
365365+ incoming_path_is_clear = 1;
366366+367367+ if (outgoing_path_is_clear && incoming_path_is_clear) {
368368+ LOG_DBG((LOG_EXCHANGE, 40, "nat_t_exchange_check_nat_d: "
369369+ "no NAT"));
370370+ return 0; /* No NAT-T required. */
371371+ }
372372+373373+ /* NAT-T handling required. */
374374+ msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE;
375375+376376+ if (!outgoing_path_is_clear) {
377377+ msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE;
378378+ LOG_DBG((LOG_EXCHANGE, 10, "nat_t_exchange_check_nat_d: "
379379+ "NAT detected, we're behind it"));
380380+ } else
381381+ LOG_DBG ((LOG_EXCHANGE, 10,
382382+ "nat_t_exchange_check_nat_d: NAT detected"));
383383+ return 1;
384384+}
+36
sbin/isakmpd/nat_traversal.h
···11+/* $OpenBSD: nat_traversal.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
55+ *
66+ * Redistribution and use in source and binary forms, with or without
77+ * modification, are permitted provided that the following conditions
88+ * are met:
99+ * 1. Redistributions of source code must retain the above copyright
1010+ * notice, this list of conditions and the following disclaimer.
1111+ * 2. Redistributions in binary form must reproduce the above copyright
1212+ * notice, this list of conditions and the following disclaimer in the
1313+ * documentation and/or other materials provided with the distribution.
1414+ *
1515+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1616+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1919+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2020+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2121+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2323+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525+ */
2626+2727+#ifndef _NAT_TRAVERSAL_H_
2828+#define _NAT_TRAVERSAL_H_
2929+3030+void nat_t_init(void);
3131+int nat_t_add_vendor_payloads(struct message *);
3232+void nat_t_check_vendor_payload(struct message *, struct payload *);
3333+int nat_t_exchange_add_nat_d(struct message *);
3434+int nat_t_exchange_check_nat_d(struct message *);
3535+3636+#endif /* _NAT_TRAVERSAL_H_ */
···11-/* $OpenBSD: transport.c,v 1.26 2004/06/14 09:55:42 ho Exp $ */
11+/* $OpenBSD: transport.c,v 1.27 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */
3344/*
55 * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
66- * Copyright (c) 2001 H�kan Olsson. All rights reserved.
66+ * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved.
77 *
88 * Redistribution and use in source and binary forms, with or without
99 * modification, are permitted provided that the following conditions
···4343#include "sa.h"
4444#include "timer.h"
4545#include "transport.h"
4646+#include "virtual.h"
46474748/* If no retransmit limit is given, use this as a default. */
4849#define RETRANSMIT_DEFAULT 10
···5152LIST_HEAD(transport_method_list, transport_vtbl) transport_method_list;
52535354/* Call the reinit function of the various transports. */
5454- void
5555- transport_reinit(void)
5555+void
5656+transport_reinit(void)
5657{
5758 struct transport_vtbl *method;
58595960 for (method = LIST_FIRST(&transport_method_list); method;
6061 method = LIST_NEXT(method, link))
6161- method->reinit();
6262+ if (method->reinit)
6363+ method->reinit();
6264}
63656466/* Initialize the transport maintenance module. */
···71737274/* Register another transport T. */
7375void
7474-transport_add(struct transport *t)
7676+transport_setup(struct transport *t, int toplevel)
7577{
7676- LOG_DBG((LOG_TRANSPORT, 70, "transport_add: adding %p", t));
7777- TAILQ_INIT(&t->sendq);
7878- TAILQ_INIT(&t->prio_sendq);
7979- LIST_INSERT_HEAD(&transport_list, t, link);
7878+ LOG_DBG((LOG_TRANSPORT, 70, "transport_setup: adding %p", t));
7979+ if (toplevel == 0)
8080+ LIST_INSERT_HEAD(&transport_list, t, link);
8181+ else {
8282+ /* Only the toplevel (virtual) transport has the sendqueues. */
8383+ TAILQ_INIT(&t->sendq);
8484+ TAILQ_INIT(&t->prio_sendq);
8585+ }
8086 t->flags = 0;
8187 t->refcnt = 0;
8288}
···8793{
8894 t->refcnt++;
8995 LOG_DBG((LOG_TRANSPORT, 95,
9090- "transport_reference: transport %p now has %d references", t,
9191- t->refcnt));
9696+ "transport_reference: transport %p now has %d references", t,
9797+ t->refcnt));
9298}
939994100/*
···98104transport_release(struct transport *t)
99105{
100106 LOG_DBG((LOG_TRANSPORT, 95,
101101- "transport_release: transport %p had %d references", t,
102102- t->refcnt));
107107+ "transport_release: transport %p had %d references", t,
108108+ t->refcnt));
103109 if (--t->refcnt)
104110 return;
105111106112 LOG_DBG((LOG_TRANSPORT, 70, "transport_release: freeing %p", t));
107107- LIST_REMOVE(t, link);
113113+ if (t->virtual) {
114114+ struct virtual_transport *v =
115115+ (struct virtual_transport *)t->virtual;
116116+ if (v->main == t)
117117+ v->main = 0;
118118+ else
119119+ v->encap = 0;
120120+ LIST_REMOVE(t, link);
121121+ }
108122 t->vtbl->remove(t);
109123}
110124111125void
112126transport_report(void)
113127{
128128+ struct virtual_transport *v;
114129 struct transport *t;
115130 struct message *msg;
116131···119134 "transport_report: transport %p flags %x refcnt %d", t,
120135 t->flags, t->refcnt));
121136137137+ /* XXX Report sth on the virtual transport? */
122138 t->vtbl->report(t);
123139124140 /*
125141 * This is the reason message_dump_raw lives outside
126142 * message.c.
127143 */
128128- for (msg = TAILQ_FIRST(&t->prio_sendq); msg;
129129- msg = TAILQ_NEXT(msg, link))
130130- message_dump_raw("udp_report", msg, LOG_REPORT);
144144+ v = (struct virtual_transport *)t->virtual;
145145+ if ((v->encap_is_active && v->encap == t) ||
146146+ (!v->encap_is_active && v->main == t)) {
147147+ for (msg = TAILQ_FIRST(&t->virtual->prio_sendq); msg;
148148+ msg = TAILQ_NEXT(msg, link))
149149+ message_dump_raw("udp_report(prio)", msg,
150150+ LOG_REPORT);
131151132132- for (msg = TAILQ_FIRST(&t->sendq); msg; msg = TAILQ_NEXT(msg, link))
133133- message_dump_raw("udp_report", msg, LOG_REPORT);
152152+ for (msg = TAILQ_FIRST(&t->virtual->sendq); msg;
153153+ msg = TAILQ_NEXT(msg, link))
154154+ message_dump_raw("udp_report", msg,
155155+ LOG_REPORT);
156156+ }
134157 }
135158}
136159···140163 struct transport *t;
141164142165 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link))
143143- if (TAILQ_FIRST(&t->prio_sendq))
166166+ if (TAILQ_FIRST(&t->virtual->prio_sendq))
144167 return 0;
145168 return 1;
146169}
···152175 LIST_INSERT_HEAD(&transport_method_list, t, link);
153176}
154177155155-/* Apply a function FUNC on all registered transports. */
178178+/* Apply a function FUNC on all registered (non-toplevel) transports. */
156179void
157180transport_map(void (*func) (struct transport *))
158181{
···170193int
171194transport_fd_set(fd_set * fds)
172195{
173173- int n;
174174- int max = -1;
175196 struct transport *t;
197197+ int n;
198198+ int max = -1;
176199177200 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link))
178178- if (t->flags & TRANSPORT_LISTEN) {
179179- n = t->vtbl->fd_set(t, fds, 1);
201201+ if (t->virtual->flags & TRANSPORT_LISTEN) {
202202+ n = t->virtual->vtbl->fd_set(t->virtual, fds, 1);
180203 if (n > max)
181204 max = n;
205205+206206+ LOG_DBG((LOG_TRANSPORT,95,"transport_fd_set: "
207207+ "transport %p (virtual %p) fd %d", t,
208208+ t->virtual, n));
182209 }
183210 return max + 1;
184211}
···192219int
193220transport_pending_wfd_set(fd_set * fds)
194221{
195195- int n;
196196- int max = -1;
197222 struct transport *t;
223223+ int n;
224224+ int max = -1;
198225199226 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) {
200200- if (TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq)) {
201201- n = t->vtbl->fd_set(t, fds, 1);
227227+ if (TAILQ_FIRST(&t->virtual->sendq) ||
228228+ TAILQ_FIRST(&t->virtual->prio_sendq)) {
229229+ n = t->virtual->vtbl->fd_set(t->virtual, fds, 1);
230230+ LOG_DBG((LOG_TRANSPORT,95,"transport_pending_wfd_set: "
231231+ "transport %p (virtual %p) fd %d pending", t,
232232+ t->virtual, n));
202233 if (n > max)
203234 max = n;
204235 }
···211242 * incoming message and start processing it.
212243 */
213244void
214214-transport_handle_messages(fd_set * fds)
245245+transport_handle_messages(fd_set *fds)
215246{
216247 struct transport *t;
217248218218- for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link))
249249+ for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) {
219250 if ((t->flags & TRANSPORT_LISTEN) &&
220220- (*t->vtbl->fd_isset) (t, fds))
221221- (*t->vtbl->handle_message) (t);
251251+ (*t->virtual->vtbl->fd_isset)(t->virtual, fds)) {
252252+ (*t->virtual->vtbl->handle_message)(t->virtual);
253253+ (*t->virtual->vtbl->fd_set)(t->virtual, fds, 0);
254254+ }
255255+ }
222256}
223257224258/*
···243277 * Reference all transports first so noone will disappear while in
244278 * use.
245279 */
246246- for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link))
280280+ for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) {
281281+ transport_reference(t->virtual);
247282 transport_reference(t);
248248-283283+ }
284284+249285 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) {
250250- if ((TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq))
251251- && t->vtbl->fd_isset(t, fds)) {
252252- t->vtbl->fd_set(t, fds, 0);
286286+ if ((TAILQ_FIRST(&t->virtual->sendq) ||
287287+ TAILQ_FIRST(&t->virtual->prio_sendq)) &&
288288+ t->virtual->vtbl->fd_isset(t->virtual, fds)) {
289289+ /* Remove fd bit. */
290290+ t->virtual->vtbl->fd_set(t->virtual, fds, 0);
253291254292 /* Prefer a message from the prioritized sendq. */
255255- if (TAILQ_FIRST(&t->prio_sendq)) {
256256- msg = TAILQ_FIRST(&t->prio_sendq);
257257- TAILQ_REMOVE(&t->prio_sendq, msg, link);
293293+ if (TAILQ_FIRST(&t->virtual->prio_sendq)) {
294294+ msg = TAILQ_FIRST(&t->virtual->prio_sendq);
295295+ TAILQ_REMOVE(&t->virtual->prio_sendq, msg,
296296+ link);
258297 } else {
259259- msg = TAILQ_FIRST(&t->sendq);
260260- TAILQ_REMOVE(&t->sendq, msg, link);
298298+ msg = TAILQ_FIRST(&t->virtual->sendq);
299299+ TAILQ_REMOVE(&t->virtual->sendq, msg, link);
261300 }
262301263302 msg->flags &= ~MSG_IN_TRANSIT;
···269308 * hoping that the retransmit will go better.
270309 * XXX Consider a retry/fatal error discriminator.
271310 */
272272- t->vtbl->send_message(msg);
311311+ t->virtual->vtbl->send_message(msg, 0);
273312 msg->xmits++;
274313275314 /*
276315 * This piece of code has been proven to be quite
277277- * delicate. Think twice for before altering. Here's
278278- * an outline: If this message is not the one which
279279- * finishes an exchange, check if we have reached the
280280- * number of retransmit before queuing it up for
281281- * another.
316316+ * delicate. Think twice for before altering.
317317+ * Here's an outline:
318318+ *
319319+ * If this message is not the one which finishes an
320320+ * exchange, check if we have reached the number of
321321+ * retransmit before queuing it up for another.
282322 *
283323 * If it is a finishing message we still may have to
284324 * keep it around for an on-demand retransmit when
285325 * seeing a duplicate of our peer's previous message.
286326 *
287287- * If we have no previous message from our peer, we
288288- * need not to keep the message around.
289327 */
290328 if ((msg->flags & MSG_LAST) == 0) {
291329 if (msg->xmits > conf_get_num("General",
···357395 /*
358396 * If this is not a retransmit call post-send
359397 * functions that allows parallel work to be done
360360- * while the network and peer does their share of the
361361- * job. Note that a post-send function may take away
362362- * the exchange we belong to, but only if no
398398+ * while the network and peer does their share of
399399+ * the job. Note that a post-send function may take
400400+ * away the exchange we belong to, but only if no
363401 * retransmits are possible.
364402 */
365403 if (msg->xmits == 1)
···372410373411 for (t = LIST_FIRST(&transport_list); t; t = next) {
374412 next = LIST_NEXT(t, link);
413413+ transport_release(t->virtual);
375414 transport_release(t);
376415 }
377416}
+20-7
sbin/isakmpd/transport.h
···11-/* $OpenBSD: transport.h,v 1.14 2004/04/15 18:39:26 deraadt Exp $ */
11+/* $OpenBSD: transport.h,v 1.15 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: transport.h,v 1.16 2000/07/17 18:57:59 provos Exp $ */
3344/*
55 * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
66- * Copyright (c) 2001 H�kan Olsson. All rights reserved.
66+ * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved.
77 *
88 * Redistribution and use in source and binary forms, with or without
99 * modification, are permitted provided that the following conditions
···8080 void (*handle_message) (struct transport *);
81818282 /* Send a message through the outgoing pipe. */
8383- int (*send_message) (struct message *);
8383+ int (*send_message) (struct message *, struct transport *);
84848585 /*
8686 * Fill out a sockaddr structure with the transport's destination end's
···9898 * Return a string with decoded src and dst information
9999 */
100100 char *(*decode_ids) (struct transport *);
101101+102102+ /*
103103+ * Clone a transport for outbound use.
104104+ */
105105+ struct transport *(*clone) (struct transport *, struct sockaddr *);
106106+107107+ /*
108108+ * Locate the correct sendq to use for outbound messages.
109109+ */
110110+ struct msg_head *(*get_queue) (struct message *);
101111};
102112103113struct transport {
···120130 /* Flags describing the transport. */
121131 int flags;
122132123123- /* References counter. */
133133+ /* Reference counter. */
124134 int refcnt;
135135+136136+ /* Pointer to parent virtual transport, if any. */
137137+ struct transport *virtual;
125138};
126139127140/* Set if this is a transport we want to listen on. */
···129142/* Used for mark-and-sweep-type garbage collection of transports */
130143#define TRANSPORT_MARK 2
131144132132-extern void transport_add(struct transport *);
133145extern struct transport *transport_create(char *, char *);
134146extern int transport_fd_set(fd_set *);
135147extern void transport_handle_messages(fd_set *);
···137149extern void transport_map(void (*) (struct transport *));
138150extern void transport_method_add(struct transport_vtbl *);
139151extern int transport_pending_wfd_set(fd_set *);
152152+extern int transport_prio_sendqs_empty(void);
140153extern void transport_reference(struct transport *);
154154+extern void transport_reinit(void);
141155extern void transport_release(struct transport *);
142156extern void transport_report(void);
143157extern void transport_send_messages(fd_set *);
144144-extern void transport_reinit(void);
145145-extern int transport_prio_sendqs_empty(void);
158158+extern void transport_setup(struct transport *, int);
146159#endif /* _TRANSPORT_H_ */
+109-422
sbin/isakmpd/udp.c
···11-/* $OpenBSD: udp.c,v 1.74 2004/06/17 19:36:36 hshoexer Exp $ */
11+/* $OpenBSD: udp.c,v 1.75 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */
3344/*
55 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
66 * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved.
77+ * Copyright (c) 2003, 2004 H�kan Olsson. All rights reserved.
78 *
89 * Redistribution and use in source and binary forms, with or without
910 * modification, are permitted provided that the following conditions
···5960#include "transport.h"
6061#include "udp.h"
6162#include "util.h"
6363+#include "virtual.h"
62646365#define UDP_SIZE 65536
6466···6769#define SO_REUSEPORT SO_REUSEADDR
6870#endif
69717070-struct udp_transport {
7171- struct transport transport;
7272- struct sockaddr *src, *dst;
7373- int s;
7474- LIST_ENTRY(udp_transport) link;
7575-};
7272+/* These are reused by udp_encap.c, thus not 'static' here. */
7373+struct transport *udp_clone(struct transport *, struct sockaddr *);
7474+void udp_get_dst(struct transport *, struct sockaddr **);
7575+void udp_get_src(struct transport *, struct sockaddr **);
7676+char *udp_decode_ids(struct transport *);
76777777-static struct transport *udp_clone(struct udp_transport *, struct sockaddr *);
7878static struct transport *udp_create(char *);
7979-static void udp_reinit(void);
8079static void udp_remove(struct transport *);
8180static void udp_report(struct transport *);
8282-static int udp_fd_set(struct transport *, fd_set *, int);
8383-static int udp_fd_isset(struct transport *, fd_set *);
8481static void udp_handle_message(struct transport *);
8582static struct transport *udp_make(struct sockaddr *);
8686-static int udp_send_message(struct message *);
8787-static void udp_get_dst(struct transport *, struct sockaddr **);
8888-static void udp_get_src(struct transport *, struct sockaddr **);
8989-static char *udp_decode_ids(struct transport *);
8383+static int udp_send_message(struct message *, struct transport *);
9084#if 0
9185static in_port_t udp_decode_port(char *);
9286#endif
93879488static struct transport_vtbl udp_transport_vtbl = {
9595- {0}, "udp",
8989+ {0}, "udp_physical",
9690 udp_create,
9797- udp_reinit,
9191+ 0,
9892 udp_remove,
9993 udp_report,
100100- udp_fd_set,
101101- udp_fd_isset,
9494+ 0,
9595+ 0,
10296 udp_handle_message,
10397 udp_send_message,
10498 udp_get_dst,
10599 udp_get_src,
106106- udp_decode_ids
100100+ udp_decode_ids,
101101+ udp_clone,
102102+ 0
107103};
108104109109-/* A list of UDP transports we listen for messages on. */
110110-static
111111-LIST_HEAD(udp_listen_list, udp_transport) udp_listen_list;
112112-113113-static struct transport *default_transport, *default_transport6;
114105char *udp_default_port = 0;
115106char *udp_bind_port = 0;
116107int bind_family = 0;
117108118118-/* Find an UDP transport listening on ADDR:PORT. */
119119-static struct udp_transport *
120120-udp_listen_lookup(struct sockaddr *addr)
109109+void
110110+udp_init(void)
121111{
122122- struct udp_transport *u;
123123-124124- for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link))
125125- if (sysdep_sa_len(u->src) == sysdep_sa_len(addr) &&
126126- memcmp(u->src, addr, sysdep_sa_len(addr)) == 0)
127127- return u;
128128- return 0;
112112+ transport_method_add(&udp_transport_vtbl);
129113}
130114131115/* Create a UDP transport structure bound to LADDR just for listening. */
···133117udp_make(struct sockaddr *laddr)
134118{
135119 struct udp_transport *t = 0;
136136- int s, on, wildcardaddress = 0;
120120+ int s, on, wildcardaddress = 0;
121121+ char *tstr;
137122138123 t = calloc(1, sizeof *t);
139124 if (!t) {
140140- log_print("udp_make: malloc (%lu) failed",
125125+ log_print("udp_make: calloc (1, %lu) failed",
141126 (unsigned long)sizeof *t);
142127 free(laddr);
143128 return 0;
···184169 }
185170 t->transport.vtbl = &udp_transport_vtbl;
186171 if (monitor_bind(s, t->src, sysdep_sa_len(t->src))) {
187187- char *tstr;
188188-189172 if (sockaddr2text(t->src, &tstr, 0))
190173 log_error("udp_make: bind (%d, %p, %lu)", s, &t->src,
191174 (unsigned long)sizeof t->src);
···197180 goto err;
198181 }
199182 t->s = s;
200200- transport_add(&t->transport);
183183+ if (sockaddr2text(t->src, &tstr, 0))
184184+ LOG_DBG((LOG_MISC, 20, "udp_make: "
185185+ "transport %p socket %d family %d", t, s,
186186+ t->src->sa_family == AF_INET ? 4 : 6));
187187+ else {
188188+ LOG_DBG((LOG_MISC, 20, "udp_make: "
189189+ "transport %p socket %d ip %s port %d", t, s,
190190+ tstr, ntohs(sockaddr_port(t->src))));
191191+ free (tstr);
192192+ }
193193+ transport_setup(&t->transport, 0);
201194 transport_reference(&t->transport);
202195 t->transport.flags |= TRANSPORT_LISTEN;
203196 return &t->transport;
···214207}
215208216209/* Clone a listen transport U, record a destination RADDR for outbound use. */
217217-static struct transport *
218218-udp_clone(struct udp_transport *u, struct sockaddr *raddr)
210210+struct transport *
211211+udp_clone(struct transport *ut, struct sockaddr *raddr)
219212{
213213+ struct udp_transport *u = (struct udp_transport *)ut;
220214 struct udp_transport *u2;
221215 struct transport *t;
222216···250244 memcpy(u2->dst, raddr, sysdep_sa_len(raddr));
251245252246 t->flags &= ~TRANSPORT_LISTEN;
253253- transport_add(t);
247247+ transport_setup(t, 0);
254248 return t;
255249}
256250···260254 * that specific port. Add the polymorphic transport structure to the
261255 * system-wide pools of known ISAKMP transports.
262256 */
263263-static struct transport *
257257+struct transport *
264258udp_bind(const struct sockaddr *addr)
265259{
266260 struct sockaddr *src;
···274268}
275269276270/*
277277- * When looking at a specific network interface address, if it's an INET one,
278278- * create an UDP server socket bound to it.
279279- * Return 0 if successful, -1 otherwise.
280280- */
281281-static int
282282-udp_bind_if(char *ifname, struct sockaddr *if_addr, void *arg)
283283-{
284284- char *port = (char *) arg, *addr_str, *ep;
285285- struct sockaddr_storage saddr_st;
286286- struct sockaddr *saddr = (struct sockaddr *) & saddr_st;
287287- struct conf_list *listen_on;
288288- struct udp_transport *u;
289289- struct conf_list_node *address;
290290- struct sockaddr *addr;
291291- struct transport *t;
292292- struct ifreq flags_ifr;
293293- int s, error;
294294- long lport;
295295-296296- /*
297297- * Well, UDP is an internet protocol after all so drop other ifreqs.
298298- */
299299- if ((if_addr->sa_family != AF_INET ||
300300- sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in)) &&
301301- (if_addr->sa_family != AF_INET6 ||
302302- sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in6)))
303303- return 0;
304304-305305- /*
306306- * Only create sockets for families we should listen to.
307307- */
308308- if (bind_family) {
309309- switch (if_addr->sa_family) {
310310- case AF_INET:
311311- if ((bind_family & BIND_FAMILY_INET4) == 0)
312312- return 0;
313313- break;
314314- case AF_INET6:
315315- if ((bind_family & BIND_FAMILY_INET6) == 0)
316316- return 0;
317317- break;
318318- default:
319319- return 0;
320320- }
321321- }
322322-323323- /*
324324- * These special addresses are not useable as they have special meaning
325325- * in the IP stack.
326326- */
327327- if (if_addr->sa_family == AF_INET &&
328328- (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY ||
329329- (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_NONE)))
330330- return 0;
331331-332332- /*
333333- * Go through the list of transports and see if we already have this
334334- * address bound. If so, unmark the transport and skip it; this allows
335335- * us to call this function when we suspect a new address has appeared.
336336- */
337337- if (sysdep_sa_len(if_addr) > sizeof saddr_st)
338338- return 0;
339339- memcpy(saddr, if_addr, sysdep_sa_len(if_addr));
340340- switch (saddr->sa_family) { /* Add the port number to the sockaddr. */
341341- case AF_INET:
342342- ((struct sockaddr_in *)saddr)->sin_port =
343343- htons(strtol(port, &ep, 10));
344344- break;
345345- case AF_INET6:
346346- ((struct sockaddr_in6 *)saddr)->sin6_port =
347347- htons(strtol(port, &ep, 10));
348348- break;
349349- }
350350-351351- if ((u = udp_listen_lookup(saddr)) != 0) {
352352- u->transport.flags &= ~TRANSPORT_MARK;
353353- return 0;
354354- }
355355- /* Don't bother with interfaces that are down. */
356356- s = socket(if_addr->sa_family, SOCK_DGRAM, 0);
357357- if (s == -1) {
358358- log_error("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed",
359359- if_addr->sa_family);
360360- return -1;
361361- }
362362- strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name);
363363- if (ioctl(s, SIOCGIFFLAGS, (caddr_t) & flags_ifr) == -1) {
364364- log_error("udp_bind_if: ioctl (%d, SIOCGIFFLAGS, ...) failed",
365365- s);
366366- return -1;
367367- }
368368- close(s);
369369- if (!(flags_ifr.ifr_flags & IFF_UP))
370370- return 0;
371371-372372- /*
373373- * Set port.
374374- * XXX Use getservbyname too.
375375- */
376376- lport = strtol(port, &ep, 10);
377377- if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) {
378378- log_print("udp_bind_if: "
379379- "port string \"%s\" not convertible to in_port_t", port);
380380- return -1;
381381- }
382382- switch (if_addr->sa_family) {
383383- case AF_INET:
384384- ((struct sockaddr_in *)if_addr)->sin_port = htons(lport);
385385- break;
386386- case AF_INET6:
387387- ((struct sockaddr_in6 *)if_addr)->sin6_port = htons(lport);
388388- break;
389389- default:
390390- log_print("udp_bind_if: unsupported protocol family %d",
391391- if_addr->sa_family);
392392- break;
393393- }
394394-395395- /*
396396- * If we are explicit about what addresses we can listen to, be sure
397397- * to respect that option.
398398- * This is quite wasteful redoing the list-run for every interface,
399399- * but who cares? This is not an operation that needs to be fast.
400400- */
401401- listen_on = conf_get_list("General", "Listen-on");
402402- if (listen_on) {
403403- for (address = TAILQ_FIRST(&listen_on->fields); address;
404404- address = TAILQ_NEXT(address, link)) {
405405- if (text2sockaddr(address->field, port, &addr)) {
406406- log_print("udp_bind_if: invalid address %s "
407407- "in \"Listen-on\"", address->field);
408408- continue;
409409- }
410410- /* If found, take the easy way out. */
411411- if (memcmp(addr, if_addr, sysdep_sa_len(addr)) == 0) {
412412- free(addr);
413413- break;
414414- }
415415- free(addr);
416416- }
417417- conf_free_list(listen_on);
418418-419419- /*
420420- * If address is zero then we did not find the address among
421421- * the ones we should listen to.
422422- * XXX We do not discover if we do not find our listen
423423- * addresses... Maybe this should be the other way round.
424424- */
425425- if (!address)
426426- return 0;
427427- }
428428- t = udp_bind(if_addr);
429429- if (!t) {
430430- error = sockaddr2text(if_addr, &addr_str, 0);
431431- log_print("udp_bind_if: failed to create a socket on %s:%s",
432432- error ? "unknown" : addr_str, port);
433433- if (!error)
434434- free(addr_str);
435435- return -1;
436436- }
437437- LIST_INSERT_HEAD(&udp_listen_list, (struct udp_transport *)t, link);
438438- return 0;
439439-}
440440-441441-/*
442271 * NAME is a section name found in the config database. Setup and return
443272 * a transport useable to talk to the peer specified by that name.
444273 */
445274static struct transport *
446275udp_create(char *name)
447276{
277277+ struct virtual_transport *v;
448278 struct udp_transport *u;
449449- struct transport *rv;
450450- struct sockaddr *dst, *addr;
279279+ struct transport *rv, *t;
280280+ struct sockaddr *dst, *addr;
451281 char *addr_str, *port_str;
282282+ struct conf_list *addr_list = 0;
283283+ struct conf_list_node *addr_node;
452284453285 port_str = conf_get_str(name, "Port");
454286 if (!port_str)
455287 port_str = udp_default_port;
456288 if (!port_str)
457457- port_str = "500";
289289+ port_str = UDP_DEFAULT_PORT_STR;
458290459291 addr_str = conf_get_str(name, "Address");
460292 if (!addr_str) {
···469301 }
470302 addr_str = conf_get_str(name, "Local-address");
471303 if (!addr_str)
472472- addr_str = conf_get_str("General", "Listen-on");
473473- if (!addr_str) {
474474- if ((dst->sa_family == AF_INET && !default_transport) ||
475475- (dst->sa_family == AF_INET6 && !default_transport6)) {
304304+ addr_list = conf_get_list("General", "Listen-on");
305305+ if (!addr_str && !addr_list) {
306306+ v = virtual_get_default(dst->sa_family);
307307+ u = (struct udp_transport *)v->main;
308308+309309+ if (!u) {
476310 log_print("udp_create: no default transport");
477311 rv = 0;
478312 goto ret;
479313 } else {
480480- /* XXX Ugly! */
481481- rv = udp_clone((struct udp_transport *)
482482- (dst->sa_family == AF_INET ? default_transport :
483483- default_transport6), dst);
314314+ rv = udp_clone((struct transport *)u, dst);
315315+ if (rv)
316316+ rv->vtbl = &udp_transport_vtbl;
317317+ goto ret;
318318+ }
319319+ }
320320+321321+ if (addr_list) {
322322+ for (addr_node = TAILQ_FIRST(&addr_list->fields);
323323+ addr_node; addr_node = TAILQ_NEXT(addr_node, link))
324324+ if (text2sockaddr(addr_node->field, port_str, &addr)
325325+ == 0) {
326326+ v = virtual_listen_lookup(addr);
327327+ free(addr);
328328+ if (v) {
329329+ addr_str = addr_node->field;
330330+ break;
331331+ }
332332+ }
333333+ if (!addr_str) {
334334+ log_print("udp_create: no matching listener found");
335335+ rv = 0;
484336 goto ret;
485337 }
486338 }
···490342 rv = 0;
491343 goto ret;
492344 }
493493- u = udp_listen_lookup(addr);
345345+346346+ v = virtual_listen_lookup(addr);
494347 free(addr);
495495- if (!u) {
348348+ if (!v) {
496349 log_print("udp_create: %s:%s must exist as a listener too",
497350 addr_str, port_str);
498351 rv = 0;
499352 goto ret;
500353 }
501501- rv = udp_clone(u, dst);
354354+ t = (struct transport *)v;
355355+ rv = udp_clone(v->main, dst);
356356+ if (rv) {
357357+ rv->vtbl = &udp_transport_vtbl;
358358+ transport_reference(rv->virtual);
359359+ }
502360503361ret:
362362+ if (addr_list)
363363+ conf_free_list(addr_list);
504364 free(dst);
505365 return rv;
506366}
···517377 if (t->flags & TRANSPORT_LISTEN) {
518378 if (u->s >= 0)
519379 close(u->s);
520520- if (t == default_transport)
521521- default_transport = 0;
522522- else if (t == default_transport6)
523523- default_transport6 = 0;
524380 if (u->link.le_prev)
525381 LIST_REMOVE(u, link);
526382 }
···532388udp_report(struct transport *t)
533389{
534390 struct udp_transport *u = (struct udp_transport *)t;
535535- char *src = NULL, *dst = NULL;
391391+ char *src = NULL, *dst = NULL;
392392+ in_port_t sport, dport;
536393537394 if (sockaddr2text(u->src, &src, 0))
538395 goto ret;
396396+ sport = sockaddr_port(u->src);
539397540398 if (!u->dst || sockaddr2text(u->dst, &dst, 0))
541399 dst = 0;
400400+ dport = dst ? sockaddr_port(u->dst) : 0;
542401543543- LOG_DBG((LOG_REPORT, 0, "udp_report: fd %d src %s dst %s", u->s, src,
544544- dst ? dst : "<none>"));
402402+ LOG_DBG((LOG_REPORT, 0, "udp_report: fd %d src %s:%u dst %s:%u", u->s,
403403+ src, ntohs(sport), dst ? dst : "<none>", ntohs(dport)));
545404546405ret:
547406 if (dst)
···551410}
552411553412/*
554554- * Probe the interface list and determine what new interfaces have
555555- * appeared.
556556- *
557557- * At the same time, we try to determine whether existing interfaces have
558558- * been rendered invalid; we do this by marking all UDP transports before
559559- * we call udp_bind_if () through if_map (), and then releasing those
560560- * transports that have not been unmarked.
561561- */
562562-static void
563563-udp_reinit(void)
564564-{
565565- struct udp_transport *u, *u2;
566566- char *port;
567567-568568- /* Initialize the protocol and port numbers. */
569569- port = udp_default_port ? udp_default_port : "500";
570570-571571- /* Mark all UDP transports, except the default ones. */
572572- for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link))
573573- if (&u->transport != default_transport &&
574574- &u->transport != default_transport6)
575575- u->transport.flags |= TRANSPORT_MARK;
576576-577577- /* Re-probe interface list. */
578578- if (if_map(udp_bind_if, port) == -1)
579579- log_print("udp_init: Could not bind the ISAKMP UDP port %s "
580580- "on all interfaces", port);
581581-582582- /*
583583- * Release listening transports for local addresses that no
584584- * longer exist. udp_bind_if () will have left those still marked.
585585- */
586586- u = LIST_FIRST(&udp_listen_list);
587587- while (u) {
588588- u2 = LIST_NEXT(u, link);
589589-590590- if (u->transport.flags & TRANSPORT_MARK) {
591591- LIST_REMOVE(u, link);
592592- transport_release(&u->transport);
593593- }
594594- u = u2;
595595- }
596596-}
597597-598598-/*
599599- * Find out the magic numbers for the UDP protocol as well as the UDP port
600600- * to use. Setup an UDP server for each address of this machine, and one
601601- * for the generic case when we are the initiator.
602602- */
603603-void
604604-udp_init(void)
605605-{
606606- struct sockaddr_storage dflt_stor;
607607- struct sockaddr_in *dflt = (struct sockaddr_in *) & dflt_stor;
608608- struct conf_list *listen_on;
609609- char *port;
610610- long lport;
611611- char *ep;
612612-613613- /* Initialize the protocol and port numbers. */
614614- port = udp_default_port ? udp_default_port : "500";
615615-616616- LIST_INIT(&udp_listen_list);
617617-618618- transport_method_add(&udp_transport_vtbl);
619619-620620- /* Bind the ISAKMP UDP port on all network interfaces we have. */
621621- if (if_map(udp_bind_if, port) == -1)
622622- log_fatal("udp_init: Could not bind the ISAKMP UDP port %s "
623623- "on all interfaces", port);
624624-625625- /* Only listen to the specified address if Listen-on is configured */
626626- listen_on = conf_get_list("General", "Listen-on");
627627- if (listen_on) {
628628- LOG_DBG((LOG_TRANSPORT, 50,
629629- "udp_init: not binding ISAKMP UDP port to INADDR_ANY"));
630630- conf_free_list(listen_on);
631631- return;
632632- }
633633- /*
634634- * Get port.
635635- * XXX Use getservbyname too.
636636- */
637637- lport = strtol(port, &ep, 10);
638638- if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) {
639639- log_print("udp_init: port string \"%s\" not convertible to "
640640- "in_port_t", port);
641641- return;
642642- }
643643- /*
644644- * Bind to INADDR_ANY in case of new addresses popping up. Packet
645645- * reception on this transport is taken as a hint to reprobe the
646646- * interface list.
647647- */
648648- if (!bind_family || (bind_family & BIND_FAMILY_INET4)) {
649649- memset(&dflt_stor, 0, sizeof dflt_stor);
650650- dflt->sin_family = AF_INET;
651651-#if !defined (LINUX_IPSEC)
652652- ((struct sockaddr_in *)dflt)->sin_len =
653653- sizeof(struct sockaddr_in);
654654-#endif
655655- ((struct sockaddr_in *)dflt)->sin_port = htons(lport);
656656-657657- default_transport = udp_bind((struct sockaddr *)&dflt_stor);
658658- if (!default_transport) {
659659- log_error("udp_init: could not allocate default "
660660- "IPv4 ISAKMP UDP port");
661661- return;
662662- }
663663- LIST_INSERT_HEAD(&udp_listen_list,
664664- (struct udp_transport *)default_transport, link);
665665- }
666666- if (!bind_family || (bind_family & BIND_FAMILY_INET6)) {
667667- memset(&dflt_stor, 0, sizeof dflt_stor);
668668- dflt->sin_family = AF_INET6;
669669-#if !defined (LINUX_IPSEC)
670670- ((struct sockaddr_in6 *)dflt)->sin6_len =
671671- sizeof(struct sockaddr_in6);
672672-#endif
673673- ((struct sockaddr_in6 *)dflt)->sin6_port = htons(lport);
674674-675675- default_transport6 = udp_bind((struct sockaddr *)&dflt_stor);
676676- if (!default_transport6) {
677677- log_error("udp_init: could not allocate default "
678678- "IPv6 ISAKMP UDP port");
679679- return;
680680- }
681681- LIST_INSERT_HEAD(&udp_listen_list,
682682- (struct udp_transport *)default_transport6, link);
683683- }
684684-}
685685-686686-/*
687687- * Set transport T's socket in FDS, return a value useable by select(2)
688688- * as the number of file descriptors to check.
689689- */
690690-static int
691691-udp_fd_set(struct transport *t, fd_set *fds, int bit)
692692-{
693693- struct udp_transport *u = (struct udp_transport *)t;
694694-695695- if (bit)
696696- FD_SET(u->s, fds);
697697- else
698698- FD_CLR(u->s, fds);
699699-700700- return u->s + 1;
701701-}
702702-703703-/* Check if transport T's socket is set in FDS. */
704704-static int
705705-udp_fd_isset(struct transport *t, fd_set *fds)
706706-{
707707- struct udp_transport *u = (struct udp_transport *)t;
708708-709709- return FD_ISSET(u->s, fds);
710710-}
711711-712712-/*
713413 * A message has arrived on transport T's socket. If T is single-ended,
714414 * clone it into a double-ended transport which we will use from now on.
715415 * Package the message as we want it and continue processing in the message
···718418static void
719419udp_handle_message(struct transport *t)
720420{
721721- struct udp_transport *u = (struct udp_transport *) t;
421421+ struct udp_transport *u = (struct udp_transport *)t;
722422 u_int8_t buf[UDP_SIZE];
723423 struct sockaddr_storage from;
724424 u_int32_t len = sizeof from;
725425 ssize_t n;
726426 struct message *msg;
727427728728- n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *) & from, &len);
428428+ n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len);
729429 if (n == -1) {
730430 log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf,
731431 UDP_SIZE, 0, &from, &len);
732432 return;
733433 }
734434 /*
735735- * If we received the packet over the default transports, reprobe the
736736- * interfaces.
737737- */
738738- if (t == default_transport || t == default_transport6) {
739739- udp_reinit();
740740-741741- /*
742742- * As we don't know the actual destination address of the
743743- * packet, we can't really deal with it. So, just ignore it
744744- * and hope we catch the retransmission.
745745- */
746746- return;
747747- }
748748- /*
749435 * Make a specialized UDP transport structure out of the incoming
750436 * transport and the address information we got from recvfrom(2).
751437 */
752752- t = udp_clone(u, (struct sockaddr *)&from);
438438+ t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from);
753439 if (!t)
754440 return;
755441···757443 if (!msg) {
758444 log_error("failed to allocate message structure, dropping "
759445 "packet received on transport %p", u);
446446+ t->vtbl->remove(t);
760447 return;
761448 }
762449 message_recv(msg);
···764451765452/* Physically send the message MSG over its associated transport. */
766453static int
767767-udp_send_message(struct message *msg)
454454+udp_send_message(struct message *msg, struct transport *t)
768455{
769769- struct udp_transport *u = (struct udp_transport *)msg->transport;
456456+ struct udp_transport *u = (struct udp_transport *)t;
770457 ssize_t n;
771458 struct msghdr m;
772459···794481 * Get transport T's peer address and stuff it into the sockaddr pointed
795482 * to by DST.
796483 */
797797-static void
484484+void
798485udp_get_dst(struct transport *t, struct sockaddr **dst)
799486{
800487 *dst = ((struct udp_transport *)t)->dst;
···804491 * Get transport T's local address and stuff it into the sockaddr pointed
805492 * to by SRC. Put its length into SRC_LEN.
806493 */
807807-static void
494494+void
808495udp_get_src(struct transport *t, struct sockaddr **src)
809496{
810497 *src = ((struct udp_transport *)t)->src;
811498}
812499813813-static char *
500500+char *
814501udp_decode_ids(struct transport *t)
815502{
503503+ struct sockaddr *src, *dst;
816504 static char result[1024];
817505 char idsrc[256], iddst[256];
818506507507+ t->vtbl->get_src(t, &src);
508508+ t->vtbl->get_dst(t, &dst);
509509+819510#ifdef HAVE_GETNAMEINFO
820820- if (getnameinfo(((struct udp_transport *)t)->src,
821821- sysdep_sa_len(((struct udp_transport *)t)->src),
822822- idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) {
511511+ if (getnameinfo(src, sysdep_sa_len(src), idsrc, sizeof idsrc, NULL, 0,
512512+ NI_NUMERICHOST) != 0) {
823513 log_print("udp_decode_ids: getnameinfo () failed for 'src'");
824514 strlcpy(idsrc, "<error>", 256);
825515 }
826826- if (getnameinfo(((struct udp_transport *)t)->dst,
827827- sysdep_sa_len(((struct udp_transport *)t)->dst),
828828- iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) {
516516+ if (getnameinfo(dst, sysdep_sa_len(dst), iddst, sizeof iddst, NULL, 0,
517517+ NI_NUMERICHOST) != 0) {
829518 log_print("udp_decode_ids: getnameinfo () failed for 'dst'");
830519 strlcpy(iddst, "<error>", 256);
831520 }
832521#else
833833- strlcpy(idsrc, inet_ntoa(((struct udp_transport *)t)->src.sin_addr),
834834- 256);
835835- strlcpy(iddst, inet_ntoa(((struct udp_transport *)t)->dst.sin_addr),
836836- 256);
837837-#endif /* HAVE_GETNAMEINFO */
522522+ strlcpy(idsrc, inet_ntoa(src->sin_addr), 256);
523523+ strlcpy(iddst, inet_ntoa(dst->sin_addr), 256);
524524+#endif /* HAVE_GETNAMEINFO */
838525839526 snprintf(result, sizeof result, "src: %s dst: %s", idsrc, iddst);
840527 return result;
···11+/* $OpenBSD: udp_encap.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
55+ * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved.
66+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
77+ *
88+ * Redistribution and use in source and binary forms, with or without
99+ * modification, are permitted provided that the following conditions
1010+ * are met:
1111+ * 1. Redistributions of source code must retain the above copyright
1212+ * notice, this list of conditions and the following disclaimer.
1313+ * 2. Redistributions in binary form must reproduce the above copyright
1414+ * notice, this list of conditions and the following disclaimer in the
1515+ * documentation and/or other materials provided with the distribution.
1616+ *
1717+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1818+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1919+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2020+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2121+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2222+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2323+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2424+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2525+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2626+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2727+ */
2828+2929+#include <sys/types.h>
3030+#include <sys/ioctl.h>
3131+#include <sys/socket.h>
3232+#ifndef linux
3333+#include <sys/sockio.h>
3434+#endif
3535+#include <net/if.h>
3636+#include <netinet/in.h>
3737+#include <arpa/inet.h>
3838+#include <ctype.h>
3939+#include <err.h>
4040+#include <limits.h>
4141+#include <netdb.h>
4242+#include <stdlib.h>
4343+#include <string.h>
4444+#include <unistd.h>
4545+4646+#include "sysdep.h"
4747+4848+#include "conf.h"
4949+#include "if.h"
5050+#include "ipsec_doi.h"
5151+#include "isakmp.h"
5252+#include "log.h"
5353+#include "message.h"
5454+#include "monitor.h"
5555+#include "sysdep.h"
5656+#include "transport.h"
5757+#include "udp.h"
5858+#include "udp_encap.h"
5959+#include "util.h"
6060+#include "virtual.h"
6161+6262+#define UDP_SIZE 65536
6363+6464+/* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */
6565+#ifndef SO_REUSEPORT
6666+#define SO_REUSEPORT SO_REUSEADDR
6767+#endif
6868+6969+/* Reused, from udp.c */
7070+struct transport *udp_clone (struct transport *, struct sockaddr *);
7171+void udp_get_dst (struct transport *, struct sockaddr **);
7272+void udp_get_src (struct transport *, struct sockaddr **);
7373+char *udp_decode_ids (struct transport *);
7474+7575+static struct transport *udp_encap_create (char *);
7676+static void udp_encap_remove (struct transport *);
7777+static void udp_encap_report (struct transport *);
7878+static void udp_encap_handle_message (struct transport *);
7979+static struct transport *udp_encap_make (struct sockaddr *);
8080+static int udp_encap_send_message (struct message *,
8181+ struct transport *);
8282+8383+static struct transport_vtbl udp_encap_transport_vtbl = {
8484+ { 0 }, "udp_encap",
8585+ udp_encap_create,
8686+ 0,
8787+ udp_encap_remove,
8888+ udp_encap_report,
8989+ 0,
9090+ 0,
9191+ udp_encap_handle_message,
9292+ udp_encap_send_message,
9393+ udp_get_dst,
9494+ udp_get_src,
9595+ udp_decode_ids,
9696+ udp_clone,
9797+ 0
9898+};
9999+100100+char *udp_encap_default_port = 0;
101101+char *udp_encap_bind_port = 0;
102102+103103+void
104104+udp_encap_init(void)
105105+{
106106+ transport_method_add(&udp_encap_transport_vtbl);
107107+}
108108+109109+/* Create a UDP transport structure bound to LADDR just for listening. */
110110+static struct transport *
111111+udp_encap_make(struct sockaddr *laddr)
112112+{
113113+ struct udp_transport *t = 0;
114114+ int s, on, wildcardaddress = 0;
115115+ char *tstr;
116116+117117+ t = calloc(1, sizeof *t);
118118+ if (!t) {
119119+ log_print("udp_encap_make: malloc (%lu) failed",
120120+ (unsigned long)sizeof *t);
121121+ return 0;
122122+ }
123123+124124+ s = socket(laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
125125+ if (s == -1) {
126126+ log_error("udp_encap_make: socket (%d, %d, %d)",
127127+ laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
128128+ goto err;
129129+ }
130130+131131+ /* Make sure we don't get our traffic encrypted. */
132132+ if (sysdep_cleartext(s, laddr->sa_family) == -1)
133133+ goto err;
134134+135135+ /* Wildcard address ? */
136136+ switch (laddr->sa_family) {
137137+ case AF_INET:
138138+ if (((struct sockaddr_in *)laddr)->sin_addr.s_addr
139139+ == INADDR_ANY)
140140+ wildcardaddress = 1;
141141+ break;
142142+ case AF_INET6:
143143+ if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr))
144144+ wildcardaddress = 1;
145145+ break;
146146+ }
147147+148148+ /*
149149+ * In order to have several bound specific address-port combinations
150150+ * with the same port SO_REUSEADDR is needed.
151151+ * If this is a wildcard socket and we are not listening there, but
152152+ * only sending from it make sure it is entirely reuseable with
153153+ * SO_REUSEPORT.
154154+ */
155155+ on = 1;
156156+ if (setsockopt(s, SOL_SOCKET,
157157+ wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR,
158158+ (void *)&on, sizeof on) == -1) {
159159+ log_error("udp_encap_make: setsockopt (%d, %d, %d, %p, %lu)",
160160+ s, SOL_SOCKET,
161161+ wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, &on,
162162+ (unsigned long)sizeof on);
163163+ goto err;
164164+ }
165165+166166+ t->transport.vtbl = &udp_encap_transport_vtbl;
167167+ t->src = laddr;
168168+ if (monitor_bind(s, t->src, sysdep_sa_len (t->src))) {
169169+ if (sockaddr2text(t->src, &tstr, 0))
170170+ log_error("udp_encap_make: bind (%d, %p, %lu)", s,
171171+ &t->src, (unsigned long)sizeof t->src);
172172+ else {
173173+ log_error("udp_encap_make: bind (%d, %s, %lu)", s,
174174+ tstr, (unsigned long)sizeof t->src);
175175+ free(tstr);
176176+ }
177177+ goto err;
178178+ }
179179+180180+ t->s = s;
181181+ if (sockaddr2text(t->src, &tstr, 0))
182182+ LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
183183+ "transport %p socket %d family %d", t, s,
184184+ t->src->sa_family == AF_INET ? 4 : 6));
185185+ else {
186186+ LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
187187+ "transport %p socket %d ip %s port %d", t, s,
188188+ tstr, ntohs(sockaddr_port(t->src))));
189189+ free(tstr);
190190+ }
191191+ transport_setup(&t->transport, 0);
192192+ transport_reference(&t->transport);
193193+ t->transport.flags |= TRANSPORT_LISTEN;
194194+ return &t->transport;
195195+196196+ err:
197197+ if (s >= 0)
198198+ close (s);
199199+ if (t) {
200200+ /* Already closed. */
201201+ t->s = -1;
202202+ udp_encap_remove(&t->transport);
203203+ }
204204+ return 0;
205205+}
206206+207207+/*
208208+ * Initialize an object of the UDP transport class. Fill in the local
209209+ * IP address and port information and create a server socket bound to
210210+ * that specific port. Add the polymorphic transport structure to the
211211+ * system-wide pools of known ISAKMP transports.
212212+ */
213213+struct transport *
214214+udp_encap_bind(const struct sockaddr *addr)
215215+{
216216+ struct sockaddr *src =
217217+ malloc(sysdep_sa_len((struct sockaddr *)addr));
218218+219219+ if (!src)
220220+ return 0;
221221+222222+ memcpy(src, addr, sysdep_sa_len((struct sockaddr *)addr));
223223+ return udp_encap_make(src);
224224+}
225225+226226+/*
227227+ * NAME is a section name found in the config database. Setup and return
228228+ * a transport useable to talk to the peer specified by that name.
229229+ */
230230+static struct transport *
231231+udp_encap_create(char *name)
232232+{
233233+ struct virtual_transport *v;
234234+ struct udp_transport *u;
235235+ struct transport *rv, *t;
236236+ struct sockaddr *dst, *addr;
237237+ struct conf_list *addr_list = 0;
238238+ struct conf_list_node *addr_node;
239239+ char *addr_str, *port_str;
240240+241241+ port_str = conf_get_str(name, "Port"); /* XXX "Encap-port" ? */
242242+ if (!port_str)
243243+ port_str = udp_encap_default_port;
244244+ if (!port_str)
245245+ port_str = UDP_ENCAP_DEFAULT_PORT_STR;
246246+247247+ addr_str = conf_get_str(name, "Address");
248248+ if (!addr_str) {
249249+ log_print("udp_encap_create: no address configured "
250250+ "for \"%s\"", name);
251251+ return 0;
252252+ }
253253+ if (text2sockaddr(addr_str, port_str, &dst)) {
254254+ log_print("udp_encap_create: address \"%s\" not understood",
255255+ addr_str);
256256+ return 0;
257257+ }
258258+259259+ addr_str = conf_get_str(name, "Local-address");
260260+ if (!addr_str)
261261+ addr_list = conf_get_list("General", "Listen-on");
262262+ if (!addr_str && !addr_list) {
263263+ v = virtual_get_default(dst->sa_family);
264264+ u = (struct udp_transport *)v->encap;
265265+266266+ if (!u) {
267267+ log_print("udp_encap_create: no default transport");
268268+ rv = 0;
269269+ goto ret;
270270+ } else {
271271+ rv = udp_clone((struct transport *)u, dst);
272272+ if (rv)
273273+ rv->vtbl = &udp_encap_transport_vtbl;
274274+ goto ret;
275275+ }
276276+ }
277277+278278+ if (addr_list) {
279279+ for (addr_node = TAILQ_FIRST(&addr_list->fields);
280280+ addr_node; addr_node = TAILQ_NEXT(addr_node, link))
281281+ if (text2sockaddr(addr_node->field, port_str,
282282+ &addr) == 0) {
283283+ v = virtual_listen_lookup(addr);
284284+ free(addr);
285285+ if (v) {
286286+ addr_str = addr_node->field;
287287+ break;
288288+ }
289289+ }
290290+ if (!addr_str) {
291291+ log_print("udp_encap_create: "
292292+ "no matching listener found");
293293+ rv = 0;
294294+ goto ret;
295295+ }
296296+ }
297297+ if (text2sockaddr(addr_str, port_str, &addr)) {
298298+ log_print("udp_encap_create: "
299299+ "address \"%s\" not understood", addr_str);
300300+ rv = 0;
301301+ goto ret;
302302+ }
303303+ v = virtual_listen_lookup(addr);
304304+ free(addr);
305305+ if (!v) {
306306+ log_print("udp_encap_create: "
307307+ "%s:%s must exist as a listener too", addr_str, port_str);
308308+ rv = 0;
309309+ goto ret;
310310+ }
311311+ t = (struct transport *)v;
312312+ rv = udp_clone(v->encap, dst);
313313+ if (rv) {
314314+ rv->vtbl = &udp_encap_transport_vtbl; /* XXX Necessary? */
315315+ transport_reference(rv->virtual);
316316+ }
317317+318318+ ret:
319319+ if (addr_list)
320320+ conf_free_list(addr_list);
321321+ free(dst);
322322+ return rv;
323323+}
324324+325325+void
326326+udp_encap_remove(struct transport *t)
327327+{
328328+ struct udp_transport *u = (struct udp_transport *)t;
329329+330330+ if (u->src)
331331+ free (u->src);
332332+ if (u->dst)
333333+ free (u->dst);
334334+ if (t->flags & TRANSPORT_LISTEN) {
335335+ if (u->s >= 0)
336336+ close (u->s);
337337+ if (u->link.le_prev)
338338+ LIST_REMOVE (u, link);
339339+ }
340340+ free (t);
341341+}
342342+343343+/* Report transport-method specifics of the T transport. */
344344+void
345345+udp_encap_report(struct transport *t)
346346+{
347347+ struct udp_transport *u = (struct udp_transport *)t;
348348+ char *src, *dst;
349349+ in_port_t sport, dport;
350350+351351+ if (sockaddr2text(u->src, &src, 0))
352352+ goto ret;
353353+ sport = sockaddr_port(u->src);
354354+355355+ if (!u->dst || sockaddr2text(u->dst, &dst, 0))
356356+ dst = 0;
357357+ dport = dst ? sockaddr_port(u->dst) : 0;
358358+359359+ LOG_DBG ((LOG_REPORT, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u",
360360+ u->s, src, ntohs(sport), dst ? dst : "*", ntohs(dport)));
361361+362362+ ret:
363363+ if (dst)
364364+ free(dst);
365365+ if (src)
366366+ free(src);
367367+}
368368+369369+/*
370370+ * A message has arrived on transport T's socket. If T is single-ended,
371371+ * clone it into a double-ended transport which we will use from now on.
372372+ * Package the message as we want it and continue processing in the message
373373+ * module.
374374+ */
375375+static void
376376+udp_encap_handle_message(struct transport *t)
377377+{
378378+ struct udp_transport *u = (struct udp_transport *)t;
379379+ struct sockaddr_storage from;
380380+ struct message *msg;
381381+ u_int32_t len = sizeof from;
382382+ ssize_t n;
383383+ u_int8_t buf[UDP_SIZE];
384384+385385+ n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len);
386386+ if (n == -1) {
387387+ log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf,
388388+ UDP_SIZE, 0, &from, &len);
389389+ return;
390390+ }
391391+392392+ /*
393393+ * Make a specialized UDP transport structure out of the incoming
394394+ * transport and the address information we got from recvfrom(2).
395395+ */
396396+ t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from);
397397+ if (!t)
398398+ return;
399399+400400+ /* Check NULL-ESP marker. */
401401+ if (n < sizeof (u_int32_t) || *(u_int32_t *)buf != 0) {
402402+ /* Should never happen. */
403403+ log_print ("udp_encap_handle_message: "
404404+ "Null-ESP marker not NULL or short message");
405405+ return;
406406+ }
407407+408408+ msg = message_alloc(t, buf + sizeof (u_int32_t),
409409+ n - sizeof (u_int32_t));
410410+ if (!msg) {
411411+ log_error ("failed to allocate message structure, dropping "
412412+ "packet received on transport %p", u);
413413+ return;
414414+ }
415415+ message_recv (msg);
416416+}
417417+418418+/* Physically send the message MSG over its associated transport. */
419419+static int
420420+udp_encap_send_message(struct message *msg, struct transport *t)
421421+{
422422+ struct udp_transport *u = (struct udp_transport *)t;
423423+ struct msghdr m;
424424+ struct iovec *new_iov;
425425+ ssize_t n;
426426+ u_int32_t marker = 0; /* NULL-ESP Marker */
427427+428428+ /* Construct new iov array, prefixing NULL-ESP Marker. */
429429+ new_iov = (struct iovec *)calloc (msg->iovlen + 1, sizeof *new_iov);
430430+ if (!new_iov) {
431431+ log_error ("udp_encap_send_message: calloc (%lu, %lu) failed",
432432+ (unsigned long)msg->iovlen + 1,
433433+ (unsigned long)sizeof *new_iov);
434434+ return -1;
435435+ }
436436+ new_iov[0].iov_base = ▮
437437+ new_iov[0].iov_len = IPSEC_SPI_SIZE;
438438+ memcpy (new_iov + sizeof *new_iov, msg->iov,
439439+ msg->iovlen * sizeof *new_iov);
440440+441441+ /*
442442+ * Sending on connected sockets requires that no destination address is
443443+ * given, or else EISCONN will occur.
444444+ */
445445+ m.msg_name = (caddr_t)u->dst;
446446+ m.msg_namelen = sysdep_sa_len (u->dst);
447447+ m.msg_iov = new_iov;
448448+ m.msg_iovlen = msg->iovlen + 1;
449449+ m.msg_control = 0;
450450+ m.msg_controllen = 0;
451451+ m.msg_flags = 0;
452452+ n = sendmsg (u->s, &m, 0);
453453+ if (n == -1) {
454454+ /* XXX We should check whether the address has gone away */
455455+ log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0);
456456+ free (new_iov);
457457+ return -1;
458458+ }
459459+ free (new_iov);
460460+ return 0;
461461+}
+37
sbin/isakmpd/udp_encap.h
···11+/* $OpenBSD: udp_encap.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 1998 Niklas Hallqvist. All rights reserved.
55+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
66+ *
77+ * Redistribution and use in source and binary forms, with or without
88+ * modification, are permitted provided that the following conditions
99+ * are met:
1010+ * 1. Redistributions of source code must retain the above copyright
1111+ * notice, this list of conditions and the following disclaimer.
1212+ * 2. Redistributions in binary form must reproduce the above copyright
1313+ * notice, this list of conditions and the following disclaimer in the
1414+ * documentation and/or other materials provided with the distribution.
1515+ *
1616+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1717+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1818+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1919+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2020+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2121+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2222+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2323+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2424+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2525+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2626+ */
2727+2828+#ifndef _UDP_ENCAP_H_
2929+#define _UDP_ENCAP_H_
3030+3131+struct transport *udp_encap_bind (const struct sockaddr *);
3232+void udp_encap_init (void);
3333+3434+extern char *udp_encap_default_port;
3535+extern char *udp_encap_bind_port;
3636+3737+#endif /* _UDP_H_ */
+17-2
sbin/isakmpd/util.c
···11-/* $OpenBSD: util.c,v 1.42 2004/06/16 15:08:20 hshoexer Exp $ */
11+/* $OpenBSD: util.c,v 1.43 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $ */
3344/*
55 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
66- * Copyright (c) 2000, 2001 H�kan Olsson. All rights reserved.
66+ * Copyright (c) 2000, 2001, 2004 H�kan Olsson. All rights reserved.
77 *
88 * Redistribution and use in source and binary forms, with or without
99 * modification, are permitted provided that the following conditions
···450450 log_print("sockaddr_port: unsupported protocol family %d",
451451 sa->sa_family);
452452 return 0;
453453+ }
454454+}
455455+456456+/* Utility function used to set the port of a sockaddr. */
457457+void
458458+sockaddr_set_port(struct sockaddr *sa, in_port_t port)
459459+{
460460+ switch (sa->sa_family) {
461461+ case AF_INET:
462462+ ((struct sockaddr_in *)sa)->sin_port = htons (port);
463463+ break;
464464+465465+ case AF_INET6:
466466+ ((struct sockaddr_in6 *)sa)->sin6_port = htons (port);
467467+ break;
453468 }
454469}
455470
+3-2
sbin/isakmpd/util.h
···11-/* $OpenBSD: util.h,v 1.19 2004/05/23 16:14:22 deraadt Exp $ */
11+/* $OpenBSD: util.h,v 1.20 2004/06/20 15:24:05 ho Exp $ */
22/* $EOM: util.h,v 1.10 2000/10/24 13:33:39 niklas Exp $ */
3344/*
55 * Copyright (c) 1998 Niklas Hallqvist. All rights reserved.
66- * Copyright (c) 2001 H�kan Olsson. All rights reserved.
66+ * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved.
77 *
88 * Redistribution and use in source and binary forms, with or without
99 * modification, are permitted provided that the following conditions
···6363extern u_int8_t *sockaddr_addrdata(struct sockaddr *);
6464extern int sockaddr_addrlen(struct sockaddr *);
6565extern in_port_t sockaddr_port(struct sockaddr *);
6666+extern void sockaddr_set_port(struct sockaddr *, in_port_t);
6667extern int text2sockaddr(char *, char *, struct sockaddr **);
6768extern void util_ntoa(char **, int, u_int8_t *);
6869extern int zero_test(const u_int8_t *, size_t);
+706
sbin/isakmpd/virtual.c
···11+/* $OpenBSD: virtual.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
55+ *
66+ * Redistribution and use in source and binary forms, with or without
77+ * modification, are permitted provided that the following conditions
88+ * are met:
99+ * 1. Redistributions of source code must retain the above copyright
1010+ * notice, this list of conditions and the following disclaimer.
1111+ * 2. Redistributions in binary form must reproduce the above copyright
1212+ * notice, this list of conditions and the following disclaimer in the
1313+ * documentation and/or other materials provided with the distribution.
1414+ *
1515+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1616+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1919+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2020+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2121+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2323+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525+ */
2626+2727+#include <sys/types.h>
2828+#include <sys/ioctl.h>
2929+#include <sys/socket.h>
3030+#ifndef linux
3131+#include <sys/sockio.h>
3232+#endif
3333+#include <net/if.h>
3434+#include <netinet/in.h>
3535+#include <arpa/inet.h>
3636+#include <ctype.h>
3737+#include <err.h>
3838+#include <limits.h>
3939+#include <netdb.h>
4040+#include <stdlib.h>
4141+#include <string.h>
4242+#include <unistd.h>
4343+4444+#include "conf.h"
4545+#include "if.h"
4646+#include "exchange.h"
4747+#include "log.h"
4848+#include "transport.h"
4949+#include "virtual.h"
5050+#include "udp.h"
5151+#include "util.h"
5252+5353+#if defined (USE_NAT_TRAVERSAL)
5454+#include "udp_encap.h"
5555+#endif
5656+5757+static struct transport *virtual_bind(const struct sockaddr *);
5858+static struct transport *virtual_bind_ADDR_ANY(sa_family_t);
5959+static int virtual_bind_if(char *, struct sockaddr *, void *);
6060+static struct transport *virtual_clone(struct transport *, struct sockaddr *);
6161+static struct transport *virtual_create(char *);
6262+static char *virtual_decode_ids (struct transport *);
6363+static int virtual_fd_set(struct transport *, fd_set *, int);
6464+static int virtual_fd_isset(struct transport *, fd_set *);
6565+static void virtual_get_dst(struct transport *,
6666+ struct sockaddr **);
6767+static struct msg_head *virtual_get_queue(struct message *);
6868+static void virtual_get_src(struct transport *,
6969+ struct sockaddr **);
7070+static void virtual_handle_message(struct transport *);
7171+static void virtual_reinit(void);
7272+static void virtual_remove(struct transport *);
7373+static void virtual_report(struct transport *);
7474+static int virtual_send_message(struct message *,
7575+ struct transport *);
7676+7777+static struct transport_vtbl virtual_transport_vtbl = {
7878+ { 0 }, "udp",
7979+ virtual_create,
8080+ virtual_reinit,
8181+ virtual_remove,
8282+ virtual_report,
8383+ virtual_fd_set,
8484+ virtual_fd_isset,
8585+ virtual_handle_message,
8686+ virtual_send_message,
8787+ virtual_get_dst,
8888+ virtual_get_src,
8989+ virtual_decode_ids,
9090+ virtual_clone,
9191+ virtual_get_queue
9292+};
9393+9494+static LIST_HEAD (virtual_listen_list, virtual_transport) virtual_listen_list;
9595+static struct transport *default_transport, *default_transport6;
9696+9797+void
9898+virtual_init(void)
9999+{
100100+ struct conf_list *listen_on;
101101+102102+ LIST_INIT(&virtual_listen_list);
103103+104104+ transport_method_add(&virtual_transport_vtbl);
105105+106106+ /* Bind the ISAKMP port(s) on all network interfaces we have. */
107107+ if (if_map(virtual_bind_if, 0) == -1)
108108+ log_fatal("virtual_init: "
109109+ "could not bind the ISAKMP port(s) on all interfaces");
110110+111111+ /* Only listen to the specified address if Listen-on is configured */
112112+ listen_on = conf_get_list("General", "Listen-on");
113113+ if (listen_on) {
114114+ LOG_DBG((LOG_TRANSPORT, 50,
115115+ "virtual_init: not binding ISAKMP port(s) to ADDR_ANY"));
116116+ conf_free_list(listen_on);
117117+ return;
118118+ }
119119+120120+ /*
121121+ * Bind to INADDR_ANY in case of new addresses popping up.
122122+ * Packet reception on this transport is taken as a hint to reprobe the
123123+ * interface list.
124124+ */
125125+ if (!bind_family || (bind_family & BIND_FAMILY_INET4)) {
126126+ default_transport = virtual_bind_ADDR_ANY(AF_INET);
127127+ if (!default_transport)
128128+ return;
129129+ LIST_INSERT_HEAD(&virtual_listen_list,
130130+ (struct virtual_transport *)default_transport, link);
131131+ }
132132+133133+ if (!bind_family || (bind_family & BIND_FAMILY_INET6)) {
134134+ default_transport6 = virtual_bind_ADDR_ANY(AF_INET6);
135135+ if (!default_transport6)
136136+ return;
137137+ LIST_INSERT_HEAD(&virtual_listen_list,
138138+ (struct virtual_transport *)default_transport6, link);
139139+ }
140140+}
141141+142142+struct virtual_transport *
143143+virtual_get_default(sa_family_t af)
144144+{
145145+ switch (af) {
146146+ case AF_INET:
147147+ return (struct virtual_transport *)default_transport;
148148+ case AF_INET6:
149149+ return (struct virtual_transport *)default_transport6;
150150+ default:
151151+ return 0;
152152+ }
153153+}
154154+155155+/*
156156+ * Probe the interface list and determine what new interfaces have
157157+ * appeared.
158158+ *
159159+ * At the same time, we try to determine whether existing interfaces have
160160+ * been rendered invalid; we do this by marking all virtual transports before
161161+ * we call virtual_bind_if () through if_map (), and then releasing those
162162+ * transports that have not been unmarked.
163163+ */
164164+void
165165+virtual_reinit(void)
166166+{
167167+ struct virtual_transport *v, *v2;
168168+169169+ /* Mark all UDP transports, except the default ones. */
170170+ for (v = LIST_FIRST(&virtual_listen_list); v; v = LIST_NEXT(v, link))
171171+ if (&v->transport != default_transport
172172+ && &v->transport != default_transport6)
173173+ v->transport.flags |= TRANSPORT_MARK;
174174+175175+ /* Re-probe interface list. */
176176+ if (if_map(virtual_bind_if, 0) == -1)
177177+ log_print("virtual_init: "
178178+ "could not bind the ISAKMP port(s) on all interfaces");
179179+180180+ /*
181181+ * Release listening transports for local addresses that no
182182+ * longer exist. virtual_bind_if () will have left those still marked.
183183+ */
184184+ v = LIST_FIRST(&virtual_listen_list);
185185+ while (v) {
186186+ v2 = LIST_NEXT(v, link);
187187+ if (v->transport.flags & TRANSPORT_MARK) {
188188+ LIST_REMOVE(v, link);
189189+ transport_release(&v->transport);
190190+ }
191191+ v = v2;
192192+ }
193193+}
194194+195195+struct virtual_transport *
196196+virtual_listen_lookup(struct sockaddr *addr)
197197+{
198198+ struct virtual_transport *v;
199199+ struct udp_transport *u;
200200+201201+ for (v = LIST_FIRST(&virtual_listen_list); v;
202202+ v = LIST_NEXT(v, link)) {
203203+ u = (struct udp_transport *)v->main;
204204+ if (u->src->sa_family == addr->sa_family
205205+ && sockaddr_addrlen(u->src) == sockaddr_addrlen(addr)
206206+ && memcmp(sockaddr_addrdata (u->src),
207207+ sockaddr_addrdata(addr),
208208+ sockaddr_addrlen(addr)) == 0)
209209+ return v;
210210+ }
211211+212212+ return 0;
213213+}
214214+215215+/*
216216+ * Initialize an object of the VIRTUAL transport class.
217217+ */
218218+static struct transport *
219219+virtual_bind(const struct sockaddr *addr)
220220+{
221221+ struct virtual_transport *v;
222222+ struct sockaddr_storage tmp_sa;
223223+ char *port;
224224+ char *ep;
225225+ long lport;
226226+227227+ v = (struct virtual_transport *)calloc(1, sizeof *v);
228228+ if (!v) {
229229+ log_error("virtual_bind: calloc(1, %lu) failed",
230230+ (unsigned long)sizeof *v);
231231+ return 0;
232232+ }
233233+234234+ v->transport.vtbl = &virtual_transport_vtbl;
235235+236236+ memcpy(&tmp_sa, addr, sysdep_sa_len((struct sockaddr *)addr));
237237+238238+ /*
239239+ * Get port.
240240+ * XXX Use getservbyname too.
241241+ */
242242+ port = udp_default_port ? udp_default_port : UDP_DEFAULT_PORT_STR;
243243+ lport = strtol(port, &ep, 10);
244244+ if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) {
245245+ log_print("virtual_bind: "
246246+ "port string \"%s\" not convertible to in_port_t", port);
247247+ return 0;
248248+ }
249249+250250+ sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport);
251251+ v->main = udp_bind((struct sockaddr *)&tmp_sa);
252252+ ((struct transport *)v->main)->virtual = (struct transport *)v;
253253+254254+#if defined (USE_NAT_TRAVERSAL)
255255+ memcpy(&tmp_sa, addr, sysdep_sa_len((struct sockaddr *)addr));
256256+257257+ /*
258258+ * Get port.
259259+ * XXX Use getservbyname too.
260260+ */
261261+ port = udp_encap_default_port
262262+ ? udp_encap_default_port : UDP_ENCAP_DEFAULT_PORT_STR;
263263+ lport = strtol(port, &ep, 10);
264264+ if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) {
265265+ log_print("virtual_bind: "
266266+ "port string \"%s\" not convertible to in_port_t", port);
267267+ return 0;
268268+ }
269269+270270+ sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport);
271271+ v->encap = udp_encap_bind((struct sockaddr *)&tmp_sa);
272272+ ((struct transport *)v->encap)->virtual = (struct transport *)v;
273273+#endif
274274+ v->encap_is_active = 0;
275275+276276+ transport_setup(&v->transport, 1);
277277+ transport_reference(&v->transport);
278278+ v->transport.flags |= TRANSPORT_LISTEN;
279279+280280+ return (struct transport *)v;
281281+}
282282+283283+static struct transport *
284284+virtual_bind_ADDR_ANY(sa_family_t af)
285285+{
286286+ struct sockaddr_storage dflt_stor;
287287+ struct sockaddr_in *d4 = (struct sockaddr_in *)&dflt_stor;
288288+ struct sockaddr_in6 *d6 = (struct sockaddr_in6 *)&dflt_stor;
289289+ struct transport *t;
290290+ struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
291291+292292+ memset(&dflt_stor, 0, sizeof dflt_stor);
293293+ switch (af) {
294294+ case AF_INET:
295295+ d4->sin_family = af;
296296+#if !defined (LINUX_IPSEC)
297297+ d4->sin_len = sizeof(struct sockaddr_in);
298298+#endif
299299+ d4->sin_addr.s_addr = INADDR_ANY;
300300+ break;
301301+302302+ case AF_INET6:
303303+ d6->sin6_family = af;
304304+#if !defined (LINUX_IPSEC)
305305+ d6->sin6_len = sizeof(struct sockaddr_in6);
306306+#endif
307307+ memcpy(&d6->sin6_addr.s6_addr, &in6addr_any,
308308+ sizeof in6addr_any);
309309+ break;
310310+ }
311311+312312+ t = virtual_bind((struct sockaddr *)&dflt_stor);
313313+ if (!t)
314314+ log_error("virtual_bind_ADDR_ANY: "
315315+ "could not allocate default IPv%s ISAKMP port(s)",
316316+ af == AF_INET ? "4" : "6");
317317+ return t;
318318+}
319319+320320+static int
321321+virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg)
322322+{
323323+ struct conf_list *listen_on;
324324+ struct virtual_transport *v;
325325+ struct conf_list_node *address;
326326+ struct sockaddr *addr;
327327+ struct transport *t;
328328+ struct ifreq flags_ifr;
329329+ char *addr_str;
330330+ int s, error;
331331+332332+#if defined (USE_DEBUG)
333333+ if (sockaddr2text(if_addr, &addr_str, 0))
334334+ addr_str = 0;
335335+336336+ LOG_DBG((LOG_TRANSPORT, 90,
337337+ "virtual_bind_if: interface %s family %s address %s",
338338+ ifname ? ifname : "<unknown>",
339339+ if_addr->sa_family == AF_INET ? "v4" :
340340+ (if_addr->sa_family == AF_INET6 ? "v6" : "<unknown>"),
341341+ addr_str ? addr_str : "<invalid>"));
342342+ if (addr_str)
343343+ free(addr_str);
344344+#endif
345345+346346+ /*
347347+ * Drop non-Internet stuff.
348348+ */
349349+ if ((if_addr->sa_family != AF_INET
350350+ || sysdep_sa_len(if_addr) != sizeof (struct sockaddr_in))
351351+ && (if_addr->sa_family != AF_INET6
352352+ || sysdep_sa_len(if_addr) != sizeof (struct sockaddr_in6)))
353353+ return 0;
354354+355355+ /*
356356+ * Only create sockets for families we should listen to.
357357+ */
358358+ if (bind_family)
359359+ switch (if_addr->sa_family) {
360360+ case AF_INET:
361361+ if ((bind_family & BIND_FAMILY_INET4) == 0)
362362+ return 0;
363363+ break;
364364+ case AF_INET6:
365365+ if ((bind_family & BIND_FAMILY_INET6) == 0)
366366+ return 0;
367367+ break;
368368+ default:
369369+ return 0;
370370+ }
371371+372372+ /*
373373+ * These special addresses are not useable as they have special meaning
374374+ * in the IP stack.
375375+ */
376376+ if (if_addr->sa_family == AF_INET
377377+ && (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY
378378+ || (((struct sockaddr_in *)if_addr)->sin_addr.s_addr
379379+ == INADDR_NONE)))
380380+ return 0;
381381+382382+ /*
383383+ * Go through the list of transports and see if we already have this
384384+ * address bound. If so, unmark the transport and skip it; this allows
385385+ * us to call this function when we suspect a new address has appeared.
386386+ */
387387+ if ((v = virtual_listen_lookup(if_addr)) != 0) {
388388+ LOG_DBG ((LOG_TRANSPORT, 90, "virtual_bind_if: "
389389+ "already bound"));
390390+ v->transport.flags &= ~TRANSPORT_MARK;
391391+ return 0;
392392+ }
393393+394394+ /*
395395+ * Don't bother with interfaces that are down.
396396+ * Note: This socket is only used to collect the interface status.
397397+ */
398398+ s = socket(if_addr->sa_family, SOCK_DGRAM, 0);
399399+ if (s == -1) {
400400+ log_error("virtual_bind_if: "
401401+ "socket (%d, SOCK_DGRAM, 0) failed", if_addr->sa_family);
402402+ return -1;
403403+ }
404404+ strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name);
405405+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&flags_ifr) == -1) {
406406+ log_error("virtual_bind_if: "
407407+ "ioctl (%d, SIOCGIFFLAGS, ...) failed", s);
408408+ return -1;
409409+ }
410410+ close(s);
411411+ if (!(flags_ifr.ifr_flags & IFF_UP))
412412+ return 0;
413413+414414+ /* Set the port number to zero. */
415415+ switch (if_addr->sa_family) {
416416+ case AF_INET:
417417+ ((struct sockaddr_in *)if_addr)->sin_port = htons(0);
418418+ break;
419419+ case AF_INET6:
420420+ ((struct sockaddr_in6 *)if_addr)->sin6_port = htons(0);
421421+ break;
422422+ default:
423423+ log_print("virtual_bind_if: unsupported protocol family %d",
424424+ if_addr->sa_family);
425425+ break;
426426+ }
427427+428428+ /*
429429+ * If we are explicit about what addresses we can listen to, be sure
430430+ * to respect that option.
431431+ * This is quite wasteful redoing the list-run for every interface,
432432+ * but who cares? This is not an operation that needs to be fast.
433433+ */
434434+ listen_on = conf_get_list("General", "Listen-on");
435435+ if (listen_on) {
436436+ for (address = TAILQ_FIRST(&listen_on->fields); address;
437437+ address = TAILQ_NEXT(address, link)) {
438438+ if (text2sockaddr(address->field, 0, &addr)) {
439439+ log_print("virtual_bind_if: "
440440+ "invalid address %s in \"Listen-on\"",
441441+ address->field);
442442+ continue;
443443+ }
444444+445445+ /* If found, take the easy way out. */
446446+ if (memcmp(addr, if_addr,
447447+ sysdep_sa_len(addr)) == 0) {
448448+ free(addr);
449449+ break;
450450+ }
451451+ free(addr);
452452+ }
453453+ conf_free_list(listen_on);
454454+455455+ /*
456456+ * If address is zero then we did not find the address among
457457+ * the ones we should listen to.
458458+ * XXX We do not discover if we do not find our listen
459459+ * addresses. Maybe this should be the other way round.
460460+ */
461461+ if (!address)
462462+ return 0;
463463+ }
464464+465465+ t = virtual_bind(if_addr);
466466+ if (!t) {
467467+ error = sockaddr2text(if_addr, &addr_str, 0);
468468+ log_print("virtual_bind_if: failed to create a socket on %s",
469469+ error ? "unknown" : addr_str);
470470+ if (!error)
471471+ free(addr_str);
472472+ return -1;
473473+ }
474474+ LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)t,
475475+ link);
476476+ return 0;
477477+}
478478+479479+static struct transport *
480480+virtual_clone(struct transport *vt, struct sockaddr *raddr)
481481+{
482482+ struct virtual_transport *v = (struct virtual_transport *)vt;
483483+ struct virtual_transport *v2;
484484+ struct transport *t;
485485+486486+ t = malloc(sizeof *v);
487487+ if (!t) {
488488+ log_error("virtual_clone: malloc(%lu) failed",
489489+ (unsigned long)sizeof *v);
490490+ return 0;
491491+ }
492492+ v2 = (struct virtual_transport *)t;
493493+494494+ memcpy(v2, v, sizeof *v);
495495+496496+ if (v->encap_is_active) {
497497+ v2->main = 0;
498498+ v2->encap = v->encap->vtbl->clone(v->encap, raddr);
499499+ v2->encap->virtual = (struct transport *)v2;
500500+ } else {
501501+ v2->main = v->main->vtbl->clone(v->main, raddr);
502502+ v2->main->virtual = (struct transport *)v2;
503503+ v2->encap = 0;
504504+ }
505505+ LOG_DBG((LOG_TRANSPORT, 50, "virtual_clone: old %p new %p (->%s %p)",
506506+ v, t, v->encap_is_active ? "encap" : "main",
507507+ v->encap_is_active ? v2->encap : v2->main));
508508+509509+ t->flags &= ~TRANSPORT_LISTEN;
510510+ transport_setup(t, 1);
511511+512512+ transport_reference(t);
513513+ transport_reference(v->encap_is_active ? v2->encap : v2->main);
514514+515515+ return t;
516516+}
517517+518518+static struct transport *
519519+virtual_create(char *name)
520520+{
521521+ struct virtual_transport *v;
522522+ struct transport *t, *t2;
523523+524524+ t = transport_create("udp_physical", name);
525525+ if (!t)
526526+ return 0;
527527+528528+#if defined (USE_NAT_TRAVERSAL)
529529+ t2 = transport_create("udp_encap", name);
530530+ if (!t2) {
531531+ t->vtbl->remove(t);
532532+ return 0;
533533+ }
534534+#else
535535+ t2 = 0;
536536+#endif
537537+538538+ v = (struct virtual_transport *)calloc(1, sizeof *v);
539539+ if (!v) {
540540+ log_error("virtual_create: calloc(1, %lu) failed",
541541+ (unsigned long)sizeof *v);
542542+ t->vtbl->remove(t);
543543+ if (t2)
544544+ t2->vtbl->remove(t2);
545545+ return 0;
546546+ }
547547+548548+ memcpy(v, t, sizeof *t);
549549+ v->transport.virtual = 0;
550550+ v->main = t;
551551+ v->encap = t2;
552552+ v->transport.vtbl = &virtual_transport_vtbl;
553553+ t->virtual = (struct transport *)v;
554554+ if (t2)
555555+ t2->virtual = (struct transport *)v;
556556+ transport_setup(&v->transport, 1);
557557+ LIST_INSERT_HEAD(&virtual_listen_list, v, link);
558558+559559+ return (struct transport *)v;
560560+}
561561+562562+static void
563563+virtual_remove(struct transport *t)
564564+{
565565+ struct virtual_transport *v = (struct virtual_transport *)t;
566566+567567+ if (v->encap)
568568+ v->encap->vtbl->remove(v->encap);
569569+ if (v->main)
570570+ v->main->vtbl->remove(v->main);
571571+ if (v->link.le_prev)
572572+ LIST_REMOVE(v, link);
573573+574574+ free(t);
575575+}
576576+577577+static void
578578+virtual_report(struct transport *t)
579579+{
580580+ return;
581581+}
582582+583583+static void
584584+virtual_handle_message(struct transport *t)
585585+{
586586+ struct virtual_transport *v = (struct virtual_transport *)t;
587587+588588+ if (t == default_transport || t == default_transport6) {
589589+ /* XXX drain pending message. See udp_handle_message(). */
590590+591591+ virtual_reinit();
592592+593593+ /*
594594+ * As we don't know the actual destination address of the
595595+ * packet, we can't really deal with it. So, just ignore it
596596+ * and hope we catch the retransmission.
597597+ */
598598+ return;
599599+ }
600600+601601+ if (v->encap_is_active)
602602+ v->encap->vtbl->handle_message(v->encap);
603603+ else
604604+ v->main->vtbl->handle_message(v->main);
605605+}
606606+607607+static int
608608+virtual_send_message(struct message *msg, struct transport *t)
609609+{
610610+ struct virtual_transport *v =
611611+ (struct virtual_transport *)msg->transport;
612612+613613+ /* XXX Debug */
614614+ if (t)
615615+ log_print("virtual_send_message: called with "
616616+ "transport %p != NULL", t);
617617+618618+#if defined (USE_NAT_TRAVERSAL)
619619+ if (v->encap_is_active == 0 &&
620620+ (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE)) {
621621+ LOG_DBG((LOG_MESSAGE, 10, "virtual_send_message: "
622622+ "switching to ENCAP"));
623623+ v->encap_is_active++;
624624+ }
625625+#endif
626626+627627+ if (v->encap_is_active)
628628+ return v->encap->vtbl->send_message(msg, v->encap);
629629+ else
630630+ return v->main->vtbl->send_message(msg, v->main);
631631+}
632632+633633+static int
634634+virtual_fd_set(struct transport *t, fd_set *fds, int bit)
635635+{
636636+ struct virtual_transport *v = (struct virtual_transport *)t;
637637+ struct udp_transport *u;
638638+639639+ if (v->encap_is_active)
640640+ u = (struct udp_transport *)v->encap;
641641+ else
642642+ u = (struct udp_transport *)v->main;
643643+644644+ if (bit)
645645+ FD_SET(u->s, fds);
646646+ else
647647+ FD_CLR(u->s, fds);
648648+649649+ return u->s + 1;
650650+}
651651+652652+static int
653653+virtual_fd_isset(struct transport *t, fd_set *fds)
654654+{
655655+ struct virtual_transport *v = (struct virtual_transport *)t;
656656+ struct udp_transport *u;
657657+658658+ if (v->encap_is_active)
659659+ u = (struct udp_transport *)v->encap;
660660+ else
661661+ u = (struct udp_transport *)v->main;
662662+663663+ return FD_ISSET(u->s, fds);
664664+}
665665+666666+static void
667667+virtual_get_src(struct transport *t, struct sockaddr **s)
668668+{
669669+ struct virtual_transport *v = (struct virtual_transport *)t;
670670+671671+ if (v->encap_is_active)
672672+ v->encap->vtbl->get_src(v->encap, s);
673673+ else
674674+ v->main->vtbl->get_src(v->main, s);
675675+}
676676+677677+static void
678678+virtual_get_dst(struct transport *t, struct sockaddr **s)
679679+{
680680+ struct virtual_transport *v = (struct virtual_transport *)t;
681681+682682+ if (v->encap_is_active)
683683+ v->encap->vtbl->get_dst(v->encap, s);
684684+ else
685685+ v->main->vtbl->get_dst(v->main, s);
686686+}
687687+688688+static char *
689689+virtual_decode_ids(struct transport *t)
690690+{
691691+ struct virtual_transport *v = (struct virtual_transport *)t;
692692+693693+ if (v->encap_is_active)
694694+ return v->encap->vtbl->decode_ids(t);
695695+ else
696696+ return v->main->vtbl->decode_ids(t);
697697+}
698698+699699+static struct msg_head *
700700+virtual_get_queue(struct message *msg)
701701+{
702702+ if (msg->flags & MSG_PRIORITIZED)
703703+ return &msg->transport->prio_sendq;
704704+ else
705705+ return &msg->transport->sendq;
706706+}
+42
sbin/isakmpd/virtual.h
···11+/* $OpenBSD: virtual.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */
22+33+/*
44+ * Copyright (c) 2004 H�kan Olsson. All rights reserved.
55+ *
66+ * Redistribution and use in source and binary forms, with or without
77+ * modification, are permitted provided that the following conditions
88+ * are met:
99+ * 1. Redistributions of source code must retain the above copyright
1010+ * notice, this list of conditions and the following disclaimer.
1111+ * 2. Redistributions in binary form must reproduce the above copyright
1212+ * notice, this list of conditions and the following disclaimer in the
1313+ * documentation and/or other materials provided with the distribution.
1414+ *
1515+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1616+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1919+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2020+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2121+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2222+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2323+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2525+ */
2626+2727+#ifndef _TRP_VIRTUAL_H_
2828+#define _TRP_VIRTUAL_H_
2929+3030+struct virtual_transport {
3131+ struct transport transport;
3232+ struct transport *main; /* Normally this transport is used. */
3333+ struct transport *encap; /* Or this, depending on 'encap_is_active'. */
3434+ int encap_is_active;
3535+ LIST_ENTRY (virtual_transport) link;
3636+};
3737+3838+void virtual_init(void);
3939+struct virtual_transport *virtual_get_default(sa_family_t);
4040+struct virtual_transport *virtual_listen_lookup(struct sockaddr *);
4141+4242+#endif /* _TRP_VIRTUAL_H_ */