jcs's openbsd hax
openbsd

NAT-Traversal for isakmpd. Work in progress... hshoexer@ ok.

ho cd6bf844 c7adf84c

+2205 -561
+9 -5
sbin/isakmpd/Makefile
··· 1 - # $OpenBSD: Makefile,v 1.52 2004/04/07 22:43:14 ho Exp $ 1 + # $OpenBSD: Makefile,v 1.53 2004/06/20 15:24:05 ho Exp $ 2 2 # $EOM: Makefile,v 1.78 2000/10/15 21:33:42 niklas Exp $ 3 3 4 4 # ··· 47 47 # Compile-time configuration of otherwise optional features 48 48 #FEATURES= tripledes des blowfish cast aes 49 49 #FEATURES+= policy x509 ec aggressive debug gmp 50 - #FEATURES+= rawkey isakmp_cfg dnssec privsep 50 + #FEATURES+= rawkey isakmp_cfg dnssec privsep dpd nat_traversal 51 51 FEATURES= tripledes des blowfish cast aes 52 52 FEATURES+= policy x509 ec aggressive debug 53 - FEATURES+= rawkey isakmp_cfg privsep 53 + FEATURES+= rawkey isakmp_cfg privsep 54 54 55 55 .PATH: ${.CURDIR}/sysdep/${OS} 56 56 ··· 63 63 ike_phase_1.c ike_quick_mode.c init.c ipsec.c ipsec_fld.c \ 64 64 ipsec_num.c isakmpd.c isakmp_doi.c isakmp_fld.c isakmp_num.c \ 65 65 key.c libcrypto.c log.c message.c math_2n.c math_group.c \ 66 - prf.c sa.c sysdep.c timer.c transport.c udp.c ui.c util.c 66 + prf.c sa.c sysdep.c timer.c transport.c virtual.c udp.c \ 67 + ui.c util.c 67 68 68 69 GENERATED= exchange_num.h ipsec_fld.h ipsec_num.h isakmp_fld.h \ 69 70 isakmp_num.h ··· 178 179 .endif 179 180 180 181 SRCS+= ${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} \ 181 - ${ISAKMP_CFG} ${PRIVSEP} 182 + ${ISAKMP_CFG} ${PRIVSEP} ${DPD} ${NAT_TRAVERSAL} 182 183 CFLAGS+= ${IPSEC_CFLAGS} ${DNSSEC_CFLAGS} 183 184 184 185 LDADD+= ${DESLIB} ${LWRESLIB} ··· 203 204 204 205 .include <bsd.prog.mk> 205 206 .include <bsd.subdir.mk> 207 + 208 + debug: 209 + (cd ${.CURDIR}; ${MAKE} DEBUG="-g -Werror")
+8 -4
sbin/isakmpd/exchange.h
··· 1 - /* $OpenBSD: exchange.h,v 1.26 2004/05/03 21:23:51 hshoexer Exp $ */ 1 + /* $OpenBSD: exchange.h,v 1.27 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: exchange.h,v 1.28 2000/09/28 12:54:28 niklas Exp $ */ 3 3 4 4 /* ··· 212 212 }; 213 213 214 214 /* The flag bits. */ 215 - #define EXCHANGE_FLAG_I_COMMITTED 1 216 - #define EXCHANGE_FLAG_HE_COMMITTED 2 215 + #define EXCHANGE_FLAG_I_COMMITTED 0x01 216 + #define EXCHANGE_FLAG_HE_COMMITTED 0x02 217 217 #define EXCHANGE_FLAG_COMMITTED (EXCHANGE_FLAG_I_COMMITTED \ 218 218 | EXCHANGE_FLAG_HE_COMMITTED) 219 - #define EXCHANGE_FLAG_ENCRYPT 4 219 + #define EXCHANGE_FLAG_ENCRYPT 0x04 220 + #define EXCHANGE_FLAG_NAT_T_CAP_PEER 0x08 /* Peer is NAT capable. */ 221 + #define EXCHANGE_FLAG_NAT_T_ENABLE 0x10 /* We are doing NAT-T. */ 222 + #define EXCHANGE_FLAG_NAT_T_KEEPALIVE 0x20 /* We are the NAT:ed peer. */ 223 + #define EXCHANGE_FLAG_DPD_CAP_PEER 0x40 /* Peer is DPD capable. */ 220 224 221 225 extern int exchange_add_certs(struct message *); 222 226 extern void exchange_finalize(struct message *);
+54
sbin/isakmpd/features/nat_traversal
··· 1 + # $OpenBSD: nat_traversal,v 1.1 2004/06/20 15:24:05 ho Exp $ 2 + 3 + # 4 + # Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 + # 6 + # Redistribution and use in source and binary forms, with or without 7 + # modification, are permitted provided that the following conditions 8 + # are met: 9 + # 1. Redistributions of source code must retain the above copyright 10 + # notice, this list of conditions and the following disclaimer. 11 + # 2. Redistributions in binary form must reproduce the above copyright 12 + # notice, this list of conditions and the following disclaimer in the 13 + # documentation and/or other materials provided with the distribution. 14 + # 15 + # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 + # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 + # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 + # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 + # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 + # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 + # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 + # 26 + 27 + NAT_TRAVERSAL= nat_traversal.c udp_encap.c 28 + # $OpenBSD: nat_traversal,v 1.1 2004/06/20 15:24:05 ho Exp $ 29 + 30 + # 31 + # Copyright (c) 2004 H�kan Olsson. All rights reserved. 32 + # 33 + # Redistribution and use in source and binary forms, with or without 34 + # modification, are permitted provided that the following conditions 35 + # are met: 36 + # 1. Redistributions of source code must retain the above copyright 37 + # notice, this list of conditions and the following disclaimer. 38 + # 2. Redistributions in binary form must reproduce the above copyright 39 + # notice, this list of conditions and the following disclaimer in the 40 + # documentation and/or other materials provided with the distribution. 41 + # 42 + # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 43 + # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 44 + # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 45 + # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 46 + # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 + # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 48 + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 49 + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 51 + # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 + # 53 + 54 + NAT_TRAVERSAL= nat_traversal.c udp_encap.c
+47 -2
sbin/isakmpd/ike_phase_1.c
··· 1 - /* $OpenBSD: ike_phase_1.c,v 1.50 2004/06/14 09:55:41 ho Exp $ */ 1 + /* $OpenBSD: ike_phase_1.c,v 1.51 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: ike_phase_1.c,v 1.31 2000/12/11 23:47:56 niklas Exp $ */ 3 3 4 4 /* ··· 45 45 #include "crypto.h" 46 46 #include "dh.h" 47 47 #include "doi.h" 48 + #ifdef USE_DPD 49 + #include "dpd.h" 50 + #endif 48 51 #include "exchange.h" 49 52 #include "hash.h" 50 53 #include "ike_auth.h" ··· 55 58 #include "log.h" 56 59 #include "math_group.h" 57 60 #include "message.h" 61 + #if defined (USE_NAT_TRAVERSAL) 62 + #include "nat_traversal.h" 63 + #endif 58 64 #include "prf.h" 59 65 #include "sa.h" 60 66 #include "transport.h" ··· 359 365 transforms_len += transform_len[i]; 360 366 } 361 367 368 + #if defined (USE_NAT_TRAVERSAL) 369 + /* Advertise NAT-T capability. */ 370 + if (nat_t_add_vendor_payloads(msg)) 371 + goto bail_out; 372 + #endif 373 + 374 + #if defined (USE_DPD) 375 + /* Advertise DPD capability. */ 376 + if (dpd_add_vendor_payload(msg)) 377 + goto bail_out; 378 + #endif 379 + 362 380 conf_free_list(conf); 363 381 free(transform); 364 382 free(transform_len); ··· 511 529 ike_phase_1_responder_send_SA(struct message *msg) 512 530 { 513 531 /* Add the SA payload with the transform that was chosen. */ 514 - return message_add_sa_payload(msg); 532 + if (message_add_sa_payload(msg)) 533 + return -1; 534 + 535 + #if defined (USE_NAT_TRAVERSAL) 536 + /* Advertise NAT-T capability. */ 537 + if (nat_t_add_vendor_payloads(msg)) 538 + return -1; 539 + #endif 540 + 541 + #if defined (USE_DPD) 542 + /* Advertise DPD capability. */ 543 + if (dpd_add_vendor_payload(msg)) 544 + return -1; 545 + #endif 546 + return 0; 515 547 } 516 548 517 549 /* Send our public DH value and a nonce to the peer. */ ··· 533 565 /* XXX Log? */ 534 566 return -1; 535 567 } 568 + #if defined (USE_NAT_TRAVERSAL) 569 + /* If this exchange uses NAT-Traversal, add NAT-D payloads now. */ 570 + if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER) 571 + if (nat_t_exchange_add_nat_d(msg)) { 572 + /* XXX Log? */ 573 + return -1; 574 + } 575 + #endif 536 576 return 0; 537 577 } 538 578 ··· 555 595 /* XXX How to log and notify peer? */ 556 596 return -1; 557 597 } 598 + #if defined (USE_NAT_TRAVERSAL) 599 + /* Check NAT-D payloads and contents. */ 600 + if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER) 601 + (void)nat_t_exchange_check_nat_d(msg); 602 + #endif 558 603 return 0; 559 604 } 560 605
+17 -6
sbin/isakmpd/init.c
··· 1 - /* $OpenBSD: init.c,v 1.29 2004/04/15 18:39:25 deraadt Exp $ */ 1 + /* $OpenBSD: init.c,v 1.30 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: init.c,v 1.25 2000/03/30 14:27:24 ho Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. 6 6 * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved. 7 - * Copyright (c) 2003 H�kan Olsson. All rights reserved. 7 + * Copyright (c) 2003, 2004 H�kan Olsson. All rights reserved. 8 8 * 9 9 * Redistribution and use in source and binary forms, with or without 10 10 * modification, are permitted provided that the following conditions ··· 50 50 #include "sa.h" 51 51 #include "timer.h" 52 52 #include "transport.h" 53 + #include "virtual.h" 53 54 #include "udp.h" 54 55 #include "ui.h" 55 56 #include "util.h" 56 57 57 - #ifdef USE_POLICY 58 + #if defined (USE_POLICY) 58 59 #include "policy.h" 60 + #endif 61 + 62 + #if defined (USE_NAT_TRAVERSAL) 63 + #include "nat_traversal.h" 64 + #include "udp_encap.h" 59 65 #endif 60 66 61 67 void ··· 78 84 /* This depends on conf_init, thus check as soon as possible. */ 79 85 log_reinit(); 80 86 81 - #ifdef USE_POLICY 87 + #if defined (USE_POLICY) 82 88 /* policy_init depends on conf_init having run. */ 83 89 policy_init(); 84 90 #endif ··· 89 95 90 96 sa_init(); 91 97 transport_init(); 98 + virtual_init(); 92 99 udp_init(); 100 + #if defined (USE_NAT_TRAVERSAL) 101 + nat_t_init(); 102 + udp_encap_init(); 103 + #endif 93 104 ui_init(); 94 105 } 95 106 ··· 116 127 117 128 log_reinit(); 118 129 119 - #ifdef USE_POLICY 130 + #if defined (USE_POLICY) 120 131 /* Reread the policies. */ 121 132 policy_init(); 122 133 #endif ··· 129 140 connection_reinit(); 130 141 131 142 /* 132 - * Rescan interfaces. 143 + * Rescan interfaces (call reinit() in all transports). 133 144 */ 134 145 transport_reinit(); 135 146
+29 -21
sbin/isakmpd/ipsec.c
··· 1 - /* $OpenBSD: ipsec.c,v 1.96 2004/06/17 19:39:38 hshoexer Exp $ */ 1 + /* $OpenBSD: ipsec.c,v 1.97 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ 3 3 4 4 /* ··· 1119 1119 void *vmsg) 1120 1120 { 1121 1121 struct message *msg = vmsg; 1122 + u_int16_t dv = decode_16(value); 1122 1123 1123 1124 if (msg->exchange->phase == 1) { 1124 1125 switch (type) { 1125 1126 case IKE_ATTR_ENCRYPTION_ALGORITHM: 1126 - return !crypto_get(from_ike_crypto(decode_16(value))); 1127 + return !crypto_get(from_ike_crypto(dv)); 1127 1128 case IKE_ATTR_HASH_ALGORITHM: 1128 - return !hash_get(from_ike_hash(decode_16(value))); 1129 + return !hash_get(from_ike_hash(dv)); 1129 1130 case IKE_ATTR_AUTHENTICATION_METHOD: 1130 - return !ike_auth_get(decode_16(value)); 1131 + return !ike_auth_get(dv); 1131 1132 case IKE_ATTR_GROUP_DESCRIPTION: 1132 - return (decode_16(value) < IKE_GROUP_DESC_MODP_768 1133 - || decode_16(value) > IKE_GROUP_DESC_MODP_1536) 1134 - && (decode_16(value) < IKE_GROUP_DESC_MODP_2048 1135 - || decode_16(value) > IKE_GROUP_DESC_MODP_8192); 1133 + return (dv < IKE_GROUP_DESC_MODP_768 1134 + || dv > IKE_GROUP_DESC_MODP_1536) 1135 + && (dv < IKE_GROUP_DESC_MODP_2048 1136 + || dv > IKE_GROUP_DESC_MODP_8192); 1136 1137 case IKE_ATTR_GROUP_TYPE: 1137 1138 return 1; 1138 1139 case IKE_ATTR_GROUP_PRIME: ··· 1146 1147 case IKE_ATTR_GROUP_CURVE_B: 1147 1148 return 1; 1148 1149 case IKE_ATTR_LIFE_TYPE: 1149 - return decode_16(value) < IKE_DURATION_SECONDS 1150 - || decode_16(value) > IKE_DURATION_KILOBYTES; 1150 + return dv < IKE_DURATION_SECONDS 1151 + || dv > IKE_DURATION_KILOBYTES; 1151 1152 case IKE_ATTR_LIFE_DURATION: 1152 1153 return len != 2 && len != 4; 1153 1154 case IKE_ATTR_PRF: ··· 1157 1158 * Our crypto routines only allows key-lengths which 1158 1159 * are multiples of an octet. 1159 1160 */ 1160 - return decode_16(value) % 8 != 0; 1161 + return dv % 8 != 0; 1161 1162 case IKE_ATTR_FIELD_SIZE: 1162 1163 return 1; 1163 1164 case IKE_ATTR_GROUP_ORDER: ··· 1166 1167 } else { 1167 1168 switch (type) { 1168 1169 case IPSEC_ATTR_SA_LIFE_TYPE: 1169 - return decode_16(value) < IPSEC_DURATION_SECONDS 1170 - || decode_16(value) > IPSEC_DURATION_KILOBYTES; 1170 + return dv < IPSEC_DURATION_SECONDS 1171 + || dv > IPSEC_DURATION_KILOBYTES; 1171 1172 case IPSEC_ATTR_SA_LIFE_DURATION: 1172 1173 return len != 2 && len != 4; 1173 1174 case IPSEC_ATTR_GROUP_DESCRIPTION: 1174 - return (decode_16(value) < IKE_GROUP_DESC_MODP_768 1175 - || decode_16(value) > IKE_GROUP_DESC_MODP_1536) 1176 - && (decode_16(value) < IKE_GROUP_DESC_MODP_2048 1177 - || IKE_GROUP_DESC_MODP_8192 < decode_16(value)); 1175 + return (dv < IKE_GROUP_DESC_MODP_768 1176 + || dv > IKE_GROUP_DESC_MODP_1536) 1177 + && (dv < IKE_GROUP_DESC_MODP_2048 1178 + || IKE_GROUP_DESC_MODP_8192 < dv); 1178 1179 case IPSEC_ATTR_ENCAPSULATION_MODE: 1179 - return decode_16(value) < IPSEC_ENCAP_TUNNEL 1180 - || decode_16(value) > IPSEC_ENCAP_TRANSPORT; 1180 + #if defined (USE_NAT_TRAVERSAL) 1181 + return dv != IPSEC_ENCAP_TUNNEL 1182 + && dv != IPSEC_ENCAP_TRANSPORT 1183 + && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL 1184 + && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT; 1185 + #else 1186 + return dv < IPSEC_ENCAP_TUNNEL 1187 + || dv > IPSEC_ENCAP_TRANSPORT; 1188 + #endif /* USE_NAT_TRAVERSAL */ 1181 1189 case IPSEC_ATTR_AUTHENTICATION_ALGORITHM: 1182 - return decode_16(value) < IPSEC_AUTH_HMAC_MD5 1183 - || decode_16(value) > IPSEC_AUTH_HMAC_RIPEMD; 1190 + return dv < IPSEC_AUTH_HMAC_MD5 1191 + || dv > IPSEC_AUTH_HMAC_RIPEMD; 1184 1192 case IPSEC_ATTR_KEY_LENGTH: 1185 1193 /* 1186 1194 * XXX Blowfish needs '0'. Others appear to disregard
+10 -5
sbin/isakmpd/isakmp.h
··· 1 - /* $OpenBSD: isakmp.h,v 1.6 2004/04/15 18:39:26 deraadt Exp $ */ 1 + /* $OpenBSD: isakmp.h,v 1.7 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: isakmp.h,v 1.11 2000/07/05 10:48:43 ho Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. 6 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 6 7 * 7 8 * Redistribution and use in source and binary forms, with or without 8 9 * modification, are permitted provided that the following conditions ··· 35 36 #include "isakmp_fld.h" 36 37 #include "isakmp_num.h" 37 38 38 - /* ISAKMP default transport */ 39 - #define ISAKMP_DEFAULT_TRANSPORT "udp" 40 - 41 39 /* IANA assigned port */ 42 - #define UDP_DEFAULT_PORT 500 40 + #define UDP_DEFAULT_PORT 500 41 + #define UDP_DEFAULT_PORT_STR "500" 42 + 43 + #define ISAKMP_DEFAULT_TRANSPORT "udp" 44 + 45 + /* draft-ietf-ipsec-nat-t-ike-07.txt */ 46 + #define UDP_ENCAP_DEFAULT_PORT 4500 47 + #define UDP_ENCAP_DEFAULT_PORT_STR "4500" 43 48 44 49 /* ISAKMP header extras defines */ 45 50 #define ISAKMP_HDR_COOKIES_OFF ISAKMP_HDR_ICOOKIE_OFF
+13 -1
sbin/isakmpd/isakmp_fld.fld
··· 1 - # $OpenBSD: isakmp_fld.fld,v 1.7 2003/06/03 14:28:16 ho Exp $ 1 + # $OpenBSD: isakmp_fld.fld,v 1.8 2004/06/20 15:24:05 ho Exp $ 2 2 # $EOM: isakmp_fld.fld,v 1.5 1999/04/25 13:38:22 niklas Exp $ 3 3 4 4 # ··· 150 150 ID num 2 151 151 ATTRS raw 152 152 . 153 + 154 + # NAT Discovery payload. 155 + ISAKMP_NAT_D : ISAKMP_GEN 156 + DATA raw 157 + . 158 + 159 + # NAT Original Address payload. 160 + ISAKMP_NAT_OA : ISAKMP_GEN 161 + TYPE num 1 162 + RESERVED ign 3 163 + DATA raw 164 + .
+80 -23
sbin/isakmpd/message.c
··· 1 - /* $OpenBSD: message.c,v 1.80 2004/06/20 15:11:29 ho Exp $ */ 1 + /* $OpenBSD: message.c,v 1.81 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. 6 6 * Copyright (c) 1999 Angelos D. Keromytis. All rights reserved. 7 - * Copyright (c) 1999, 2000, 2001 H�kan Olsson. All rights reserved. 7 + * Copyright (c) 1999, 2000, 2001, 2004 H�kan Olsson. All rights reserved. 8 8 * 9 9 * Redistribution and use in source and binary forms, with or without 10 10 * modification, are permitted provided that the following conditions ··· 45 45 #include "constants.h" 46 46 #include "crypto.h" 47 47 #include "doi.h" 48 + #ifdef USE_DPD 49 + #include "dpd.h" 50 + #endif 48 51 #include "exchange.h" 49 52 #include "field.h" 50 53 #include "hash.h" ··· 53 56 #include "isakmp.h" 54 57 #include "log.h" 55 58 #include "message.h" 59 + #if defined (USE_NAT_TRAVERSAL) 60 + #include "nat_traversal.h" 61 + #endif 56 62 #include "prf.h" 57 63 #include "sa.h" 58 64 #include "timer.h" ··· 85 91 static int message_validate_hash(struct message *, struct payload *); 86 92 static int message_validate_id(struct message *, struct payload *); 87 93 static int message_validate_key_exch(struct message *, struct payload *); 94 + static int message_validate_nat_d(struct message *, struct payload *); 95 + static int message_validate_nat_oa(struct message *, struct payload *); 88 96 static int message_validate_nonce(struct message *, struct payload *); 89 97 static int message_validate_notify(struct message *, struct payload *); 90 98 static int message_validate_proposal(struct message *, struct payload *); ··· 102 110 message_validate_id, message_validate_cert, message_validate_cert_req, 103 111 message_validate_hash, message_validate_sig, message_validate_nonce, 104 112 message_validate_notify, message_validate_delete, 105 - message_validate_vendor, message_validate_attribute 113 + message_validate_vendor, message_validate_attribute, 114 + message_validate_nat_d, message_validate_nat_oa 106 115 }; 107 116 108 117 static struct field *fields[] = { 109 118 isakmp_sa_fld, isakmp_prop_fld, isakmp_transform_fld, isakmp_ke_fld, 110 119 isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld, 111 120 isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld, 112 - isakmp_vendor_fld, isakmp_attribute_fld 121 + isakmp_vendor_fld, isakmp_attribute_fld, isakmp_nat_d_fld, 122 + isakmp_nat_oa_fld 113 123 }; 114 124 115 125 /* ··· 211 221 link); 212 222 213 223 /* If we are on the send queue, remove us from there. */ 214 - if (msg->flags & MSG_IN_TRANSIT) { 215 - if (msg->flags & MSG_PRIORITIZED) 216 - TAILQ_REMOVE(&msg->transport->prio_sendq, msg, link); 217 - else 218 - TAILQ_REMOVE(&msg->transport->sendq, msg, link); 219 - } 224 + if (msg->flags & MSG_IN_TRANSIT) 225 + TAILQ_REMOVE(msg->transport->vtbl->get_queue(msg), msg, link); 226 + 220 227 transport_release(msg->transport); 221 228 222 229 if (msg->isakmp_sa) ··· 478 485 return -1; 479 486 } 480 487 /* 481 - * Check the certificate types we support and if an acceptable authority 482 - * is included in the payload check if it can be decoded 488 + * Check the certificate types we support and if an acceptable 489 + * authority is included in the payload check if it can be decoded 483 490 */ 484 491 cert = cert_get(GET_ISAKMP_CERTREQ_TYPE(p->p)); 485 492 if (!cert || (len && !cert->certreq_validate(p->p + ··· 745 752 return 0; 746 753 } 747 754 755 + /* Validate the NAT-D payload P in message MSG. */ 756 + static int 757 + message_validate_nat_d(struct message *msg, struct payload *p) 758 + { 759 + struct exchange *exchange = msg->exchange; 760 + 761 + if (!exchange) { 762 + /* We should have an exchange at this point. */ 763 + log_print("message_validate_nat_d: payload out of sequence"); 764 + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); 765 + return -1; 766 + } 767 + 768 + if (exchange->phase != 1) { 769 + log_print("message_validate_nat_d: " 770 + "NAT-D payload must be in phase 1"); 771 + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); 772 + return -1; 773 + } 774 + 775 + /* Mark as handled. */ 776 + p->flags |= PL_MARK; 777 + 778 + return 0; 779 + } 780 + 781 + /* Validate the NAT-OA payload P in message MSG. */ 782 + static int 783 + message_validate_nat_oa(struct message *msg, struct payload *p) 784 + { 785 + struct exchange *exchange = msg->exchange; 786 + 787 + if (!exchange) { 788 + /* We should have an exchange at this point. */ 789 + log_print("message_validate_nat_d: payload out of sequence"); 790 + message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); 791 + return -1; 792 + } 793 + 794 + #ifdef notyet /* XXX Probably never, due to patent issues. */ 795 + /* Mark as handled. */ 796 + p->flags |= PL_MARK; 797 + #endif 798 + 799 + return 0; 800 + } 801 + 748 802 /* Validate the nonce payload P in message MSG. */ 749 803 static int 750 804 message_validate_nonce(struct message *msg, struct payload *p) ··· 1020 1074 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE, 0, 1, 1); 1021 1075 return -1; 1022 1076 } 1023 - LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: vendor ID seen")); 1077 + #if defined (USE_DPD) 1078 + dpd_check_vendor_payload(msg, p); 1079 + #endif 1080 + #if defined (USE_NAT_TRAVERSAL) 1081 + nat_t_check_vendor_payload(msg, p); 1082 + #endif 1083 + if (!(p->flags & PL_MARK)) 1084 + LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: " 1085 + "vendor ID seen")); 1024 1086 return 0; 1025 1087 } 1026 1088 ··· 1134 1196 * made nicer. 1135 1197 */ 1136 1198 setup_isakmp_sa = zero_test(buf + ISAKMP_HDR_RCOOKIE_OFF, 1137 - ISAKMP_HDR_RCOOKIE_LEN); 1199 + ISAKMP_HDR_RCOOKIE_LEN); 1138 1200 if (setup_isakmp_sa) { 1139 1201 /* 1140 1202 * This might be a retransmission of a former ISAKMP SA setup ··· 1445 1507 * has left the queue, don't queue it again, as it will result 1446 1508 * in a circular list. 1447 1509 */ 1448 - q = msg->flags & MSG_PRIORITIZED ? &msg->transport->prio_sendq : 1449 - &msg->transport->sendq; 1450 - 1510 + q = msg->transport->vtbl->get_queue(msg); 1451 1511 for (m = TAILQ_FIRST(q); m; m = TAILQ_NEXT(m, link)) 1452 1512 if (m == msg) { 1453 1513 LOG_DBG((LOG_MESSAGE, 60, ··· 1880 1940 */ 1881 1941 if (exchange->last_sent) { 1882 1942 if (exchange->last_sent == exchange->in_transit) { 1883 - if (exchange->in_transit->flags & MSG_PRIORITIZED) 1884 - TAILQ_REMOVE(&exchange->in_transit->transport->prio_sendq, 1885 - exchange->in_transit, link); 1886 - else 1887 - TAILQ_REMOVE(&exchange->in_transit->transport->sendq, 1888 - exchange->in_transit, link); 1943 + struct message *m = exchange->in_transit; 1944 + TAILQ_REMOVE(m->transport->vtbl->get_queue(m), m, 1945 + link); 1889 1946 exchange->in_transit = 0; 1890 1947 } 1891 1948 message_free(exchange->last_sent);
+384
sbin/isakmpd/nat_traversal.c
··· 1 + /* $OpenBSD: nat_traversal.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 + * 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions 8 + * are met: 9 + * 1. Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * 2. Redistributions in binary form must reproduce the above copyright 12 + * notice, this list of conditions and the following disclaimer in the 13 + * documentation and/or other materials provided with the distribution. 14 + * 15 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 + */ 26 + 27 + #include <sys/types.h> 28 + #include <stdlib.h> 29 + 30 + #include "sysdep.h" 31 + 32 + #include "exchange.h" 33 + #include "hash.h" 34 + #include "ipsec.h" 35 + #include "isakmp_fld.h" 36 + #include "isakmp_num.h" 37 + #include "ipsec_num.h" 38 + #include "hash.h" 39 + #include "log.h" 40 + #include "message.h" 41 + #include "nat_traversal.h" 42 + #include "prf.h" 43 + #include "sa.h" 44 + #include "transport.h" 45 + #include "util.h" 46 + 47 + /* 48 + * XXX According to draft-ietf-ipsec-nat-t-ike-07.txt, the NAT-T 49 + * capability of the other peer is determined by a particular vendor ID 50 + * sent as the first message. This vendor ID string is supposed to be a 51 + * MD5 hash of "RFC XXXX", where XXXX is the future RFC number. 52 + * 53 + * These seem to be the "well" known variants of this string in use by 54 + * products today. 55 + */ 56 + static const char *isakmp_nat_t_cap_text[] = { 57 + "draft-ietf-ipsec-nat-t-ike-00", /* V1 (XXX: may be obsolete) */ 58 + "draft-ietf-ipsec-nat-t-ike-02\n", /* V2 */ 59 + "draft-ietf-ipsec-nat-t-ike-03", /* V3 */ 60 + #ifdef notyet 61 + "RFC XXXX", 62 + #endif 63 + }; 64 + 65 + /* The MD5 hashes of the above strings is put in this array. */ 66 + static char **nat_t_hashes; 67 + static size_t nat_t_hashsize; 68 + 69 + static int nat_t_setup_hashes(void); 70 + static int nat_t_add_vendor_payload(struct message *, char *); 71 + static int nat_t_add_nat_d(struct message *, struct sockaddr *); 72 + static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *); 73 + 74 + void 75 + nat_t_init(void) 76 + { 77 + nat_t_hashes = (char **)NULL; 78 + } 79 + 80 + /* Generate the NAT-T capability marker hashes. Executed only once. */ 81 + static int 82 + nat_t_setup_hashes(void) 83 + { 84 + struct hash *hash; 85 + int n = sizeof isakmp_nat_t_cap_text / sizeof isakmp_nat_t_cap_text[0]; 86 + int i; 87 + 88 + /* The draft says to use MD5. */ 89 + hash = hash_get(HASH_MD5); 90 + if (!hash) { 91 + /* Should never happen. */ 92 + log_print("nat_t_setup_hashes: " 93 + "could not find MD5 hash structure!"); 94 + return -1; 95 + } 96 + nat_t_hashsize = hash->hashsize; 97 + 98 + /* Allocate one more than is necessary, i.e NULL terminated. */ 99 + nat_t_hashes = (char **)calloc((size_t)(n + 1), sizeof(char *)); 100 + if (!nat_t_hashes) { 101 + log_error("nat_t_setup_hashes: calloc (%lu,%lu) failed", 102 + (unsigned long)n, (unsigned long)sizeof(char *)); 103 + return -1; 104 + } 105 + 106 + /* Populate with hashes. */ 107 + for (i = 0; i < n; i++) { 108 + nat_t_hashes[i] = (char *)malloc(nat_t_hashsize); 109 + if (!nat_t_hashes[i]) { 110 + log_error("nat_t_setup_hashes: malloc (%lu) failed", 111 + (unsigned long)nat_t_hashsize); 112 + goto errout; 113 + } 114 + 115 + hash->Init(hash->ctx); 116 + hash->Update(hash->ctx, 117 + (unsigned char *)isakmp_nat_t_cap_text[i], 118 + strlen(isakmp_nat_t_cap_text[i])); 119 + hash->Final(nat_t_hashes[i], hash->ctx); 120 + 121 + LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: " 122 + "MD5(\"%s\") (%d bytes)", isakmp_nat_t_cap_text[i], 123 + nat_t_hashsize)); 124 + LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes", 125 + nat_t_hashes[i], nat_t_hashsize)); 126 + } 127 + 128 + return 0; 129 + 130 + errout: 131 + for (i = 0; i < n; i++) 132 + if (nat_t_hashes[i]) 133 + free(nat_t_hashes[i]); 134 + free(nat_t_hashes); 135 + nat_t_hashes = NULL; 136 + return -1; 137 + } 138 + 139 + /* Add one NAT-T VENDOR payload. */ 140 + static int 141 + nat_t_add_vendor_payload(struct message *msg, char *hash) 142 + { 143 + size_t buflen = nat_t_hashsize + ISAKMP_GEN_SZ; 144 + u_int8_t *buf; 145 + 146 + buf = malloc(buflen); 147 + if (!buf) { 148 + log_error("nat_t_add_vendor_payload: malloc (%lu) failed", 149 + (unsigned long)buflen); 150 + return -1; 151 + } 152 + 153 + SET_ISAKMP_GEN_LENGTH(buf, buflen); 154 + memcpy(buf + ISAKMP_VENDOR_ID_OFF, hash, nat_t_hashsize); 155 + if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) { 156 + free(buf); 157 + return -1; 158 + } 159 + 160 + return 0; 161 + } 162 + 163 + /* Add the NAT-T capability markers (VENDOR payloads). */ 164 + int 165 + nat_t_add_vendor_payloads(struct message *msg) 166 + { 167 + int i = 0; 168 + 169 + if (!nat_t_hashes) 170 + if (nat_t_setup_hashes()) 171 + return 0; /* XXX should this be an error? */ 172 + 173 + while (nat_t_hashes[i]) 174 + if (nat_t_add_vendor_payload(msg, nat_t_hashes[i++])) 175 + return -1; 176 + 177 + return 0; 178 + } 179 + 180 + /* 181 + * Check an incoming message for NAT-T capability markers. 182 + */ 183 + void 184 + nat_t_check_vendor_payload(struct message *msg, struct payload *p) 185 + { 186 + u_int8_t *pbuf = p->p; 187 + size_t vlen; 188 + int i = 0; 189 + 190 + /* Already checked? */ 191 + if (p->flags & PL_MARK || 192 + msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER) 193 + return; 194 + 195 + if (!nat_t_hashes) 196 + if (nat_t_setup_hashes()) 197 + return; 198 + 199 + vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ; 200 + if (vlen != nat_t_hashsize) { 201 + LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: " 202 + "bad size %d != %d", vlen, nat_t_hashsize)); 203 + return; 204 + } 205 + 206 + while (nat_t_hashes[i]) 207 + if (memcmp(nat_t_hashes[i++], pbuf + ISAKMP_GEN_SZ, 208 + vlen) == 0) { 209 + /* This peer is NAT-T capable. */ 210 + msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER; 211 + LOG_DBG((LOG_EXCHANGE, 10, 212 + "nat_t_check_vendor_payload: " 213 + "NAT-T capable peer detected")); 214 + p->flags |= PL_MARK; 215 + return; 216 + } 217 + 218 + return; 219 + } 220 + 221 + /* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */ 222 + static u_int8_t * 223 + nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa, 224 + size_t *hashlen) 225 + { 226 + struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data; 227 + struct hash *hash; 228 + struct prf *prf; 229 + u_int8_t *res; 230 + in_port_t port; 231 + int prf_type = PRF_HMAC; /* XXX */ 232 + 233 + hash = hash_get(ie->hash->type); 234 + if (hash == NULL) { 235 + log_print ("nat_t_generate_nat_d_hash: no hash"); 236 + return NULL; 237 + } 238 + 239 + prf = prf_alloc(prf_type, hash->type, msg->exchange->cookies, 240 + ISAKMP_HDR_COOKIES_LEN); 241 + if(!prf) { 242 + log_print("nat_t_generate_nat_d_hash: prf_alloc failed"); 243 + return NULL; 244 + } 245 + 246 + *hashlen = prf->blocksize; 247 + res = (u_int8_t *)malloc((unsigned long)*hashlen); 248 + if (!res) { 249 + log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed", 250 + (unsigned long)*hashlen); 251 + prf_free(prf); 252 + *hashlen = 0; 253 + return NULL; 254 + } 255 + 256 + port = sockaddr_port(sa); 257 + memset(res, 0, *hashlen); 258 + 259 + prf->Update(prf->prfctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa)); 260 + prf->Update(prf->prfctx, (unsigned char *)&port, sizeof port); 261 + prf->Final(res, prf->prfctx); 262 + prf_free (prf); 263 + 264 + return res; 265 + } 266 + 267 + /* Add a NAT-D payload to our message. */ 268 + static int 269 + nat_t_add_nat_d(struct message *msg, struct sockaddr *sa) 270 + { 271 + u_int8_t *hbuf, *buf; 272 + size_t hbuflen, buflen; 273 + 274 + hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen); 275 + if (!hbuf) { 276 + log_print("nat_t_add_nat_d: NAT-D hash gen failed"); 277 + return -1; 278 + } 279 + 280 + buflen = ISAKMP_NAT_D_DATA_OFF + hbuflen; 281 + buf = malloc(buflen); 282 + if (!buf) { 283 + log_error("nat_t_add_nat_d: malloc (%lu) failed", 284 + (unsigned long)buflen); 285 + free(hbuf); 286 + return -1; 287 + } 288 + 289 + SET_ISAKMP_GEN_LENGTH(buf, buflen); 290 + memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen); 291 + free(hbuf); 292 + 293 + if (message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, buflen, 1)) { 294 + free(buf); 295 + return -1; 296 + } 297 + 298 + return 0; 299 + } 300 + 301 + /* We add two NAT-D payloads, one each for src and dst. */ 302 + int 303 + nat_t_exchange_add_nat_d(struct message *msg) 304 + { 305 + struct sockaddr *sa; 306 + 307 + msg->transport->vtbl->get_src(msg->transport, &sa); 308 + if (nat_t_add_nat_d(msg, sa)) 309 + return -1; 310 + 311 + msg->transport->vtbl->get_dst(msg->transport, &sa); 312 + if (nat_t_add_nat_d(msg, sa)) 313 + return -1; 314 + 315 + return 0; 316 + } 317 + 318 + /* Generate and match a NAT-D hash against the NAT-D payload (pl.) data. */ 319 + static int 320 + nat_t_match_nat_d_payload(struct message *msg, struct sockaddr *sa) 321 + { 322 + struct payload *p; 323 + u_int8_t *hbuf; 324 + size_t hbuflen; 325 + int found = 0; 326 + 327 + hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen); 328 + if (!hbuf) 329 + return 0; 330 + 331 + for (p = TAILQ_FIRST(&msg->payload[ISAKMP_PAYLOAD_NAT_D]); p; 332 + p = TAILQ_NEXT(p, link)) { 333 + if (GET_ISAKMP_GEN_LENGTH (p->p) != 334 + hbuflen + ISAKMP_NAT_D_DATA_OFF) 335 + continue; 336 + 337 + if (memcmp(p->p + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen) == 0) { 338 + found++; 339 + break; 340 + } 341 + } 342 + free(hbuf); 343 + return found; 344 + } 345 + 346 + /* 347 + * Check if we need to activate NAT-T, and if we need to send keepalive 348 + * messages to the other side, i.e if we are a nat:ed peer. 349 + */ 350 + int 351 + nat_t_exchange_check_nat_d(struct message *msg) 352 + { 353 + struct sockaddr *sa; 354 + int outgoing_path_is_clear, incoming_path_is_clear; 355 + 356 + /* Assume trouble, i.e NAT-boxes in our path. */ 357 + outgoing_path_is_clear = incoming_path_is_clear = 0; 358 + 359 + msg->transport->vtbl->get_src(msg->transport, &sa); 360 + if (nat_t_match_nat_d_payload(msg, sa)) 361 + outgoing_path_is_clear = 1; 362 + 363 + msg->transport->vtbl->get_dst(msg->transport, &sa); 364 + if (nat_t_match_nat_d_payload(msg, sa)) 365 + incoming_path_is_clear = 1; 366 + 367 + if (outgoing_path_is_clear && incoming_path_is_clear) { 368 + LOG_DBG((LOG_EXCHANGE, 40, "nat_t_exchange_check_nat_d: " 369 + "no NAT")); 370 + return 0; /* No NAT-T required. */ 371 + } 372 + 373 + /* NAT-T handling required. */ 374 + msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; 375 + 376 + if (!outgoing_path_is_clear) { 377 + msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; 378 + LOG_DBG((LOG_EXCHANGE, 10, "nat_t_exchange_check_nat_d: " 379 + "NAT detected, we're behind it")); 380 + } else 381 + LOG_DBG ((LOG_EXCHANGE, 10, 382 + "nat_t_exchange_check_nat_d: NAT detected")); 383 + return 1; 384 + }
+36
sbin/isakmpd/nat_traversal.h
··· 1 + /* $OpenBSD: nat_traversal.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 + * 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions 8 + * are met: 9 + * 1. Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * 2. Redistributions in binary form must reproduce the above copyright 12 + * notice, this list of conditions and the following disclaimer in the 13 + * documentation and/or other materials provided with the distribution. 14 + * 15 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 + */ 26 + 27 + #ifndef _NAT_TRAVERSAL_H_ 28 + #define _NAT_TRAVERSAL_H_ 29 + 30 + void nat_t_init(void); 31 + int nat_t_add_vendor_payloads(struct message *); 32 + void nat_t_check_vendor_payload(struct message *, struct payload *); 33 + int nat_t_exchange_add_nat_d(struct message *); 34 + int nat_t_exchange_check_nat_d(struct message *); 35 + 36 + #endif /* _NAT_TRAVERSAL_H_ */
+18 -1
sbin/isakmpd/policy.c
··· 1 - /* $OpenBSD: policy.c,v 1.74 2004/06/14 09:55:42 ho Exp $ */ 1 + /* $OpenBSD: policy.c,v 1.75 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ 3 3 4 4 /* ··· 509 509 comp_encapsulation = "tunnel"; 510 510 break; 511 511 } 512 + #if defined (USE_NAT_TRAVERSAL) 513 + else if (decode_16(value) == IPSEC_ENCAP_UDP_ENCAP_TUNNEL) 514 + switch (proto->proto) { 515 + case IPSEC_PROTO_IPSEC_AH: 516 + ah_encapsulation = "udp-encap-tunnel"; 517 + break; 518 + 519 + case IPSEC_PROTO_IPSEC_ESP: 520 + esp_encapsulation = "udp-encap-tunnel"; 521 + break; 522 + 523 + case IPSEC_PROTO_IPCOMP: 524 + comp_encapsulation = "udp-encap-tunnel"; 525 + break; 526 + } 527 + /* XXX IPSEC_ENCAP_UDP_ENCAP_TRANSPORT */ 528 + #endif 512 529 else 513 530 switch (proto->proto) { 514 531 case IPSEC_PROTO_IPSEC_AH:
+94 -55
sbin/isakmpd/transport.c
··· 1 - /* $OpenBSD: transport.c,v 1.26 2004/06/14 09:55:42 ho Exp $ */ 1 + /* $OpenBSD: transport.c,v 1.27 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: transport.c,v 1.43 2000/10/10 12:36:39 provos Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. 6 - * Copyright (c) 2001 H�kan Olsson. All rights reserved. 6 + * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved. 7 7 * 8 8 * Redistribution and use in source and binary forms, with or without 9 9 * modification, are permitted provided that the following conditions ··· 43 43 #include "sa.h" 44 44 #include "timer.h" 45 45 #include "transport.h" 46 + #include "virtual.h" 46 47 47 48 /* If no retransmit limit is given, use this as a default. */ 48 49 #define RETRANSMIT_DEFAULT 10 ··· 51 52 LIST_HEAD(transport_method_list, transport_vtbl) transport_method_list; 52 53 53 54 /* Call the reinit function of the various transports. */ 54 - void 55 - transport_reinit(void) 55 + void 56 + transport_reinit(void) 56 57 { 57 58 struct transport_vtbl *method; 58 59 59 60 for (method = LIST_FIRST(&transport_method_list); method; 60 61 method = LIST_NEXT(method, link)) 61 - method->reinit(); 62 + if (method->reinit) 63 + method->reinit(); 62 64 } 63 65 64 66 /* Initialize the transport maintenance module. */ ··· 71 73 72 74 /* Register another transport T. */ 73 75 void 74 - transport_add(struct transport *t) 76 + transport_setup(struct transport *t, int toplevel) 75 77 { 76 - LOG_DBG((LOG_TRANSPORT, 70, "transport_add: adding %p", t)); 77 - TAILQ_INIT(&t->sendq); 78 - TAILQ_INIT(&t->prio_sendq); 79 - LIST_INSERT_HEAD(&transport_list, t, link); 78 + LOG_DBG((LOG_TRANSPORT, 70, "transport_setup: adding %p", t)); 79 + if (toplevel == 0) 80 + LIST_INSERT_HEAD(&transport_list, t, link); 81 + else { 82 + /* Only the toplevel (virtual) transport has the sendqueues. */ 83 + TAILQ_INIT(&t->sendq); 84 + TAILQ_INIT(&t->prio_sendq); 85 + } 80 86 t->flags = 0; 81 87 t->refcnt = 0; 82 88 } ··· 87 93 { 88 94 t->refcnt++; 89 95 LOG_DBG((LOG_TRANSPORT, 95, 90 - "transport_reference: transport %p now has %d references", t, 91 - t->refcnt)); 96 + "transport_reference: transport %p now has %d references", t, 97 + t->refcnt)); 92 98 } 93 99 94 100 /* ··· 98 104 transport_release(struct transport *t) 99 105 { 100 106 LOG_DBG((LOG_TRANSPORT, 95, 101 - "transport_release: transport %p had %d references", t, 102 - t->refcnt)); 107 + "transport_release: transport %p had %d references", t, 108 + t->refcnt)); 103 109 if (--t->refcnt) 104 110 return; 105 111 106 112 LOG_DBG((LOG_TRANSPORT, 70, "transport_release: freeing %p", t)); 107 - LIST_REMOVE(t, link); 113 + if (t->virtual) { 114 + struct virtual_transport *v = 115 + (struct virtual_transport *)t->virtual; 116 + if (v->main == t) 117 + v->main = 0; 118 + else 119 + v->encap = 0; 120 + LIST_REMOVE(t, link); 121 + } 108 122 t->vtbl->remove(t); 109 123 } 110 124 111 125 void 112 126 transport_report(void) 113 127 { 128 + struct virtual_transport *v; 114 129 struct transport *t; 115 130 struct message *msg; 116 131 ··· 119 134 "transport_report: transport %p flags %x refcnt %d", t, 120 135 t->flags, t->refcnt)); 121 136 137 + /* XXX Report sth on the virtual transport? */ 122 138 t->vtbl->report(t); 123 139 124 140 /* 125 141 * This is the reason message_dump_raw lives outside 126 142 * message.c. 127 143 */ 128 - for (msg = TAILQ_FIRST(&t->prio_sendq); msg; 129 - msg = TAILQ_NEXT(msg, link)) 130 - message_dump_raw("udp_report", msg, LOG_REPORT); 144 + v = (struct virtual_transport *)t->virtual; 145 + if ((v->encap_is_active && v->encap == t) || 146 + (!v->encap_is_active && v->main == t)) { 147 + for (msg = TAILQ_FIRST(&t->virtual->prio_sendq); msg; 148 + msg = TAILQ_NEXT(msg, link)) 149 + message_dump_raw("udp_report(prio)", msg, 150 + LOG_REPORT); 131 151 132 - for (msg = TAILQ_FIRST(&t->sendq); msg; msg = TAILQ_NEXT(msg, link)) 133 - message_dump_raw("udp_report", msg, LOG_REPORT); 152 + for (msg = TAILQ_FIRST(&t->virtual->sendq); msg; 153 + msg = TAILQ_NEXT(msg, link)) 154 + message_dump_raw("udp_report", msg, 155 + LOG_REPORT); 156 + } 134 157 } 135 158 } 136 159 ··· 140 163 struct transport *t; 141 164 142 165 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) 143 - if (TAILQ_FIRST(&t->prio_sendq)) 166 + if (TAILQ_FIRST(&t->virtual->prio_sendq)) 144 167 return 0; 145 168 return 1; 146 169 } ··· 152 175 LIST_INSERT_HEAD(&transport_method_list, t, link); 153 176 } 154 177 155 - /* Apply a function FUNC on all registered transports. */ 178 + /* Apply a function FUNC on all registered (non-toplevel) transports. */ 156 179 void 157 180 transport_map(void (*func) (struct transport *)) 158 181 { ··· 170 193 int 171 194 transport_fd_set(fd_set * fds) 172 195 { 173 - int n; 174 - int max = -1; 175 196 struct transport *t; 197 + int n; 198 + int max = -1; 176 199 177 200 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) 178 - if (t->flags & TRANSPORT_LISTEN) { 179 - n = t->vtbl->fd_set(t, fds, 1); 201 + if (t->virtual->flags & TRANSPORT_LISTEN) { 202 + n = t->virtual->vtbl->fd_set(t->virtual, fds, 1); 180 203 if (n > max) 181 204 max = n; 205 + 206 + LOG_DBG((LOG_TRANSPORT,95,"transport_fd_set: " 207 + "transport %p (virtual %p) fd %d", t, 208 + t->virtual, n)); 182 209 } 183 210 return max + 1; 184 211 } ··· 192 219 int 193 220 transport_pending_wfd_set(fd_set * fds) 194 221 { 195 - int n; 196 - int max = -1; 197 222 struct transport *t; 223 + int n; 224 + int max = -1; 198 225 199 226 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { 200 - if (TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq)) { 201 - n = t->vtbl->fd_set(t, fds, 1); 227 + if (TAILQ_FIRST(&t->virtual->sendq) || 228 + TAILQ_FIRST(&t->virtual->prio_sendq)) { 229 + n = t->virtual->vtbl->fd_set(t->virtual, fds, 1); 230 + LOG_DBG((LOG_TRANSPORT,95,"transport_pending_wfd_set: " 231 + "transport %p (virtual %p) fd %d pending", t, 232 + t->virtual, n)); 202 233 if (n > max) 203 234 max = n; 204 235 } ··· 211 242 * incoming message and start processing it. 212 243 */ 213 244 void 214 - transport_handle_messages(fd_set * fds) 245 + transport_handle_messages(fd_set *fds) 215 246 { 216 247 struct transport *t; 217 248 218 - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) 249 + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { 219 250 if ((t->flags & TRANSPORT_LISTEN) && 220 - (*t->vtbl->fd_isset) (t, fds)) 221 - (*t->vtbl->handle_message) (t); 251 + (*t->virtual->vtbl->fd_isset)(t->virtual, fds)) { 252 + (*t->virtual->vtbl->handle_message)(t->virtual); 253 + (*t->virtual->vtbl->fd_set)(t->virtual, fds, 0); 254 + } 255 + } 222 256 } 223 257 224 258 /* ··· 243 277 * Reference all transports first so noone will disappear while in 244 278 * use. 245 279 */ 246 - for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) 280 + for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { 281 + transport_reference(t->virtual); 247 282 transport_reference(t); 248 - 283 + } 284 + 249 285 for (t = LIST_FIRST(&transport_list); t; t = LIST_NEXT(t, link)) { 250 - if ((TAILQ_FIRST(&t->sendq) || TAILQ_FIRST(&t->prio_sendq)) 251 - && t->vtbl->fd_isset(t, fds)) { 252 - t->vtbl->fd_set(t, fds, 0); 286 + if ((TAILQ_FIRST(&t->virtual->sendq) || 287 + TAILQ_FIRST(&t->virtual->prio_sendq)) && 288 + t->virtual->vtbl->fd_isset(t->virtual, fds)) { 289 + /* Remove fd bit. */ 290 + t->virtual->vtbl->fd_set(t->virtual, fds, 0); 253 291 254 292 /* Prefer a message from the prioritized sendq. */ 255 - if (TAILQ_FIRST(&t->prio_sendq)) { 256 - msg = TAILQ_FIRST(&t->prio_sendq); 257 - TAILQ_REMOVE(&t->prio_sendq, msg, link); 293 + if (TAILQ_FIRST(&t->virtual->prio_sendq)) { 294 + msg = TAILQ_FIRST(&t->virtual->prio_sendq); 295 + TAILQ_REMOVE(&t->virtual->prio_sendq, msg, 296 + link); 258 297 } else { 259 - msg = TAILQ_FIRST(&t->sendq); 260 - TAILQ_REMOVE(&t->sendq, msg, link); 298 + msg = TAILQ_FIRST(&t->virtual->sendq); 299 + TAILQ_REMOVE(&t->virtual->sendq, msg, link); 261 300 } 262 301 263 302 msg->flags &= ~MSG_IN_TRANSIT; ··· 269 308 * hoping that the retransmit will go better. 270 309 * XXX Consider a retry/fatal error discriminator. 271 310 */ 272 - t->vtbl->send_message(msg); 311 + t->virtual->vtbl->send_message(msg, 0); 273 312 msg->xmits++; 274 313 275 314 /* 276 315 * This piece of code has been proven to be quite 277 - * delicate. Think twice for before altering. Here's 278 - * an outline: If this message is not the one which 279 - * finishes an exchange, check if we have reached the 280 - * number of retransmit before queuing it up for 281 - * another. 316 + * delicate. Think twice for before altering. 317 + * Here's an outline: 318 + * 319 + * If this message is not the one which finishes an 320 + * exchange, check if we have reached the number of 321 + * retransmit before queuing it up for another. 282 322 * 283 323 * If it is a finishing message we still may have to 284 324 * keep it around for an on-demand retransmit when 285 325 * seeing a duplicate of our peer's previous message. 286 326 * 287 - * If we have no previous message from our peer, we 288 - * need not to keep the message around. 289 327 */ 290 328 if ((msg->flags & MSG_LAST) == 0) { 291 329 if (msg->xmits > conf_get_num("General", ··· 357 395 /* 358 396 * If this is not a retransmit call post-send 359 397 * functions that allows parallel work to be done 360 - * while the network and peer does their share of the 361 - * job. Note that a post-send function may take away 362 - * the exchange we belong to, but only if no 398 + * while the network and peer does their share of 399 + * the job. Note that a post-send function may take 400 + * away the exchange we belong to, but only if no 363 401 * retransmits are possible. 364 402 */ 365 403 if (msg->xmits == 1) ··· 372 410 373 411 for (t = LIST_FIRST(&transport_list); t; t = next) { 374 412 next = LIST_NEXT(t, link); 413 + transport_release(t->virtual); 375 414 transport_release(t); 376 415 } 377 416 }
+20 -7
sbin/isakmpd/transport.h
··· 1 - /* $OpenBSD: transport.h,v 1.14 2004/04/15 18:39:26 deraadt Exp $ */ 1 + /* $OpenBSD: transport.h,v 1.15 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: transport.h,v 1.16 2000/07/17 18:57:59 provos Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. 6 - * Copyright (c) 2001 H�kan Olsson. All rights reserved. 6 + * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved. 7 7 * 8 8 * Redistribution and use in source and binary forms, with or without 9 9 * modification, are permitted provided that the following conditions ··· 80 80 void (*handle_message) (struct transport *); 81 81 82 82 /* Send a message through the outgoing pipe. */ 83 - int (*send_message) (struct message *); 83 + int (*send_message) (struct message *, struct transport *); 84 84 85 85 /* 86 86 * Fill out a sockaddr structure with the transport's destination end's ··· 98 98 * Return a string with decoded src and dst information 99 99 */ 100 100 char *(*decode_ids) (struct transport *); 101 + 102 + /* 103 + * Clone a transport for outbound use. 104 + */ 105 + struct transport *(*clone) (struct transport *, struct sockaddr *); 106 + 107 + /* 108 + * Locate the correct sendq to use for outbound messages. 109 + */ 110 + struct msg_head *(*get_queue) (struct message *); 101 111 }; 102 112 103 113 struct transport { ··· 120 130 /* Flags describing the transport. */ 121 131 int flags; 122 132 123 - /* References counter. */ 133 + /* Reference counter. */ 124 134 int refcnt; 135 + 136 + /* Pointer to parent virtual transport, if any. */ 137 + struct transport *virtual; 125 138 }; 126 139 127 140 /* Set if this is a transport we want to listen on. */ ··· 129 142 /* Used for mark-and-sweep-type garbage collection of transports */ 130 143 #define TRANSPORT_MARK 2 131 144 132 - extern void transport_add(struct transport *); 133 145 extern struct transport *transport_create(char *, char *); 134 146 extern int transport_fd_set(fd_set *); 135 147 extern void transport_handle_messages(fd_set *); ··· 137 149 extern void transport_map(void (*) (struct transport *)); 138 150 extern void transport_method_add(struct transport_vtbl *); 139 151 extern int transport_pending_wfd_set(fd_set *); 152 + extern int transport_prio_sendqs_empty(void); 140 153 extern void transport_reference(struct transport *); 154 + extern void transport_reinit(void); 141 155 extern void transport_release(struct transport *); 142 156 extern void transport_report(void); 143 157 extern void transport_send_messages(fd_set *); 144 - extern void transport_reinit(void); 145 - extern int transport_prio_sendqs_empty(void); 158 + extern void transport_setup(struct transport *, int); 146 159 #endif /* _TRANSPORT_H_ */
+109 -422
sbin/isakmpd/udp.c
··· 1 - /* $OpenBSD: udp.c,v 1.74 2004/06/17 19:36:36 hshoexer Exp $ */ 1 + /* $OpenBSD: udp.c,v 1.75 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. 6 6 * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved. 7 + * Copyright (c) 2003, 2004 H�kan Olsson. All rights reserved. 7 8 * 8 9 * Redistribution and use in source and binary forms, with or without 9 10 * modification, are permitted provided that the following conditions ··· 59 60 #include "transport.h" 60 61 #include "udp.h" 61 62 #include "util.h" 63 + #include "virtual.h" 62 64 63 65 #define UDP_SIZE 65536 64 66 ··· 67 69 #define SO_REUSEPORT SO_REUSEADDR 68 70 #endif 69 71 70 - struct udp_transport { 71 - struct transport transport; 72 - struct sockaddr *src, *dst; 73 - int s; 74 - LIST_ENTRY(udp_transport) link; 75 - }; 72 + /* These are reused by udp_encap.c, thus not 'static' here. */ 73 + struct transport *udp_clone(struct transport *, struct sockaddr *); 74 + void udp_get_dst(struct transport *, struct sockaddr **); 75 + void udp_get_src(struct transport *, struct sockaddr **); 76 + char *udp_decode_ids(struct transport *); 76 77 77 - static struct transport *udp_clone(struct udp_transport *, struct sockaddr *); 78 78 static struct transport *udp_create(char *); 79 - static void udp_reinit(void); 80 79 static void udp_remove(struct transport *); 81 80 static void udp_report(struct transport *); 82 - static int udp_fd_set(struct transport *, fd_set *, int); 83 - static int udp_fd_isset(struct transport *, fd_set *); 84 81 static void udp_handle_message(struct transport *); 85 82 static struct transport *udp_make(struct sockaddr *); 86 - static int udp_send_message(struct message *); 87 - static void udp_get_dst(struct transport *, struct sockaddr **); 88 - static void udp_get_src(struct transport *, struct sockaddr **); 89 - static char *udp_decode_ids(struct transport *); 83 + static int udp_send_message(struct message *, struct transport *); 90 84 #if 0 91 85 static in_port_t udp_decode_port(char *); 92 86 #endif 93 87 94 88 static struct transport_vtbl udp_transport_vtbl = { 95 - {0}, "udp", 89 + {0}, "udp_physical", 96 90 udp_create, 97 - udp_reinit, 91 + 0, 98 92 udp_remove, 99 93 udp_report, 100 - udp_fd_set, 101 - udp_fd_isset, 94 + 0, 95 + 0, 102 96 udp_handle_message, 103 97 udp_send_message, 104 98 udp_get_dst, 105 99 udp_get_src, 106 - udp_decode_ids 100 + udp_decode_ids, 101 + udp_clone, 102 + 0 107 103 }; 108 104 109 - /* A list of UDP transports we listen for messages on. */ 110 - static 111 - LIST_HEAD(udp_listen_list, udp_transport) udp_listen_list; 112 - 113 - static struct transport *default_transport, *default_transport6; 114 105 char *udp_default_port = 0; 115 106 char *udp_bind_port = 0; 116 107 int bind_family = 0; 117 108 118 - /* Find an UDP transport listening on ADDR:PORT. */ 119 - static struct udp_transport * 120 - udp_listen_lookup(struct sockaddr *addr) 109 + void 110 + udp_init(void) 121 111 { 122 - struct udp_transport *u; 123 - 124 - for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link)) 125 - if (sysdep_sa_len(u->src) == sysdep_sa_len(addr) && 126 - memcmp(u->src, addr, sysdep_sa_len(addr)) == 0) 127 - return u; 128 - return 0; 112 + transport_method_add(&udp_transport_vtbl); 129 113 } 130 114 131 115 /* Create a UDP transport structure bound to LADDR just for listening. */ ··· 133 117 udp_make(struct sockaddr *laddr) 134 118 { 135 119 struct udp_transport *t = 0; 136 - int s, on, wildcardaddress = 0; 120 + int s, on, wildcardaddress = 0; 121 + char *tstr; 137 122 138 123 t = calloc(1, sizeof *t); 139 124 if (!t) { 140 - log_print("udp_make: malloc (%lu) failed", 125 + log_print("udp_make: calloc (1, %lu) failed", 141 126 (unsigned long)sizeof *t); 142 127 free(laddr); 143 128 return 0; ··· 184 169 } 185 170 t->transport.vtbl = &udp_transport_vtbl; 186 171 if (monitor_bind(s, t->src, sysdep_sa_len(t->src))) { 187 - char *tstr; 188 - 189 172 if (sockaddr2text(t->src, &tstr, 0)) 190 173 log_error("udp_make: bind (%d, %p, %lu)", s, &t->src, 191 174 (unsigned long)sizeof t->src); ··· 197 180 goto err; 198 181 } 199 182 t->s = s; 200 - transport_add(&t->transport); 183 + if (sockaddr2text(t->src, &tstr, 0)) 184 + LOG_DBG((LOG_MISC, 20, "udp_make: " 185 + "transport %p socket %d family %d", t, s, 186 + t->src->sa_family == AF_INET ? 4 : 6)); 187 + else { 188 + LOG_DBG((LOG_MISC, 20, "udp_make: " 189 + "transport %p socket %d ip %s port %d", t, s, 190 + tstr, ntohs(sockaddr_port(t->src)))); 191 + free (tstr); 192 + } 193 + transport_setup(&t->transport, 0); 201 194 transport_reference(&t->transport); 202 195 t->transport.flags |= TRANSPORT_LISTEN; 203 196 return &t->transport; ··· 214 207 } 215 208 216 209 /* Clone a listen transport U, record a destination RADDR for outbound use. */ 217 - static struct transport * 218 - udp_clone(struct udp_transport *u, struct sockaddr *raddr) 210 + struct transport * 211 + udp_clone(struct transport *ut, struct sockaddr *raddr) 219 212 { 213 + struct udp_transport *u = (struct udp_transport *)ut; 220 214 struct udp_transport *u2; 221 215 struct transport *t; 222 216 ··· 250 244 memcpy(u2->dst, raddr, sysdep_sa_len(raddr)); 251 245 252 246 t->flags &= ~TRANSPORT_LISTEN; 253 - transport_add(t); 247 + transport_setup(t, 0); 254 248 return t; 255 249 } 256 250 ··· 260 254 * that specific port. Add the polymorphic transport structure to the 261 255 * system-wide pools of known ISAKMP transports. 262 256 */ 263 - static struct transport * 257 + struct transport * 264 258 udp_bind(const struct sockaddr *addr) 265 259 { 266 260 struct sockaddr *src; ··· 274 268 } 275 269 276 270 /* 277 - * When looking at a specific network interface address, if it's an INET one, 278 - * create an UDP server socket bound to it. 279 - * Return 0 if successful, -1 otherwise. 280 - */ 281 - static int 282 - udp_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) 283 - { 284 - char *port = (char *) arg, *addr_str, *ep; 285 - struct sockaddr_storage saddr_st; 286 - struct sockaddr *saddr = (struct sockaddr *) & saddr_st; 287 - struct conf_list *listen_on; 288 - struct udp_transport *u; 289 - struct conf_list_node *address; 290 - struct sockaddr *addr; 291 - struct transport *t; 292 - struct ifreq flags_ifr; 293 - int s, error; 294 - long lport; 295 - 296 - /* 297 - * Well, UDP is an internet protocol after all so drop other ifreqs. 298 - */ 299 - if ((if_addr->sa_family != AF_INET || 300 - sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in)) && 301 - (if_addr->sa_family != AF_INET6 || 302 - sysdep_sa_len(if_addr) != sizeof(struct sockaddr_in6))) 303 - return 0; 304 - 305 - /* 306 - * Only create sockets for families we should listen to. 307 - */ 308 - if (bind_family) { 309 - switch (if_addr->sa_family) { 310 - case AF_INET: 311 - if ((bind_family & BIND_FAMILY_INET4) == 0) 312 - return 0; 313 - break; 314 - case AF_INET6: 315 - if ((bind_family & BIND_FAMILY_INET6) == 0) 316 - return 0; 317 - break; 318 - default: 319 - return 0; 320 - } 321 - } 322 - 323 - /* 324 - * These special addresses are not useable as they have special meaning 325 - * in the IP stack. 326 - */ 327 - if (if_addr->sa_family == AF_INET && 328 - (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY || 329 - (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_NONE))) 330 - return 0; 331 - 332 - /* 333 - * Go through the list of transports and see if we already have this 334 - * address bound. If so, unmark the transport and skip it; this allows 335 - * us to call this function when we suspect a new address has appeared. 336 - */ 337 - if (sysdep_sa_len(if_addr) > sizeof saddr_st) 338 - return 0; 339 - memcpy(saddr, if_addr, sysdep_sa_len(if_addr)); 340 - switch (saddr->sa_family) { /* Add the port number to the sockaddr. */ 341 - case AF_INET: 342 - ((struct sockaddr_in *)saddr)->sin_port = 343 - htons(strtol(port, &ep, 10)); 344 - break; 345 - case AF_INET6: 346 - ((struct sockaddr_in6 *)saddr)->sin6_port = 347 - htons(strtol(port, &ep, 10)); 348 - break; 349 - } 350 - 351 - if ((u = udp_listen_lookup(saddr)) != 0) { 352 - u->transport.flags &= ~TRANSPORT_MARK; 353 - return 0; 354 - } 355 - /* Don't bother with interfaces that are down. */ 356 - s = socket(if_addr->sa_family, SOCK_DGRAM, 0); 357 - if (s == -1) { 358 - log_error("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed", 359 - if_addr->sa_family); 360 - return -1; 361 - } 362 - strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); 363 - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) & flags_ifr) == -1) { 364 - log_error("udp_bind_if: ioctl (%d, SIOCGIFFLAGS, ...) failed", 365 - s); 366 - return -1; 367 - } 368 - close(s); 369 - if (!(flags_ifr.ifr_flags & IFF_UP)) 370 - return 0; 371 - 372 - /* 373 - * Set port. 374 - * XXX Use getservbyname too. 375 - */ 376 - lport = strtol(port, &ep, 10); 377 - if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) { 378 - log_print("udp_bind_if: " 379 - "port string \"%s\" not convertible to in_port_t", port); 380 - return -1; 381 - } 382 - switch (if_addr->sa_family) { 383 - case AF_INET: 384 - ((struct sockaddr_in *)if_addr)->sin_port = htons(lport); 385 - break; 386 - case AF_INET6: 387 - ((struct sockaddr_in6 *)if_addr)->sin6_port = htons(lport); 388 - break; 389 - default: 390 - log_print("udp_bind_if: unsupported protocol family %d", 391 - if_addr->sa_family); 392 - break; 393 - } 394 - 395 - /* 396 - * If we are explicit about what addresses we can listen to, be sure 397 - * to respect that option. 398 - * This is quite wasteful redoing the list-run for every interface, 399 - * but who cares? This is not an operation that needs to be fast. 400 - */ 401 - listen_on = conf_get_list("General", "Listen-on"); 402 - if (listen_on) { 403 - for (address = TAILQ_FIRST(&listen_on->fields); address; 404 - address = TAILQ_NEXT(address, link)) { 405 - if (text2sockaddr(address->field, port, &addr)) { 406 - log_print("udp_bind_if: invalid address %s " 407 - "in \"Listen-on\"", address->field); 408 - continue; 409 - } 410 - /* If found, take the easy way out. */ 411 - if (memcmp(addr, if_addr, sysdep_sa_len(addr)) == 0) { 412 - free(addr); 413 - break; 414 - } 415 - free(addr); 416 - } 417 - conf_free_list(listen_on); 418 - 419 - /* 420 - * If address is zero then we did not find the address among 421 - * the ones we should listen to. 422 - * XXX We do not discover if we do not find our listen 423 - * addresses... Maybe this should be the other way round. 424 - */ 425 - if (!address) 426 - return 0; 427 - } 428 - t = udp_bind(if_addr); 429 - if (!t) { 430 - error = sockaddr2text(if_addr, &addr_str, 0); 431 - log_print("udp_bind_if: failed to create a socket on %s:%s", 432 - error ? "unknown" : addr_str, port); 433 - if (!error) 434 - free(addr_str); 435 - return -1; 436 - } 437 - LIST_INSERT_HEAD(&udp_listen_list, (struct udp_transport *)t, link); 438 - return 0; 439 - } 440 - 441 - /* 442 271 * NAME is a section name found in the config database. Setup and return 443 272 * a transport useable to talk to the peer specified by that name. 444 273 */ 445 274 static struct transport * 446 275 udp_create(char *name) 447 276 { 277 + struct virtual_transport *v; 448 278 struct udp_transport *u; 449 - struct transport *rv; 450 - struct sockaddr *dst, *addr; 279 + struct transport *rv, *t; 280 + struct sockaddr *dst, *addr; 451 281 char *addr_str, *port_str; 282 + struct conf_list *addr_list = 0; 283 + struct conf_list_node *addr_node; 452 284 453 285 port_str = conf_get_str(name, "Port"); 454 286 if (!port_str) 455 287 port_str = udp_default_port; 456 288 if (!port_str) 457 - port_str = "500"; 289 + port_str = UDP_DEFAULT_PORT_STR; 458 290 459 291 addr_str = conf_get_str(name, "Address"); 460 292 if (!addr_str) { ··· 469 301 } 470 302 addr_str = conf_get_str(name, "Local-address"); 471 303 if (!addr_str) 472 - addr_str = conf_get_str("General", "Listen-on"); 473 - if (!addr_str) { 474 - if ((dst->sa_family == AF_INET && !default_transport) || 475 - (dst->sa_family == AF_INET6 && !default_transport6)) { 304 + addr_list = conf_get_list("General", "Listen-on"); 305 + if (!addr_str && !addr_list) { 306 + v = virtual_get_default(dst->sa_family); 307 + u = (struct udp_transport *)v->main; 308 + 309 + if (!u) { 476 310 log_print("udp_create: no default transport"); 477 311 rv = 0; 478 312 goto ret; 479 313 } else { 480 - /* XXX Ugly! */ 481 - rv = udp_clone((struct udp_transport *) 482 - (dst->sa_family == AF_INET ? default_transport : 483 - default_transport6), dst); 314 + rv = udp_clone((struct transport *)u, dst); 315 + if (rv) 316 + rv->vtbl = &udp_transport_vtbl; 317 + goto ret; 318 + } 319 + } 320 + 321 + if (addr_list) { 322 + for (addr_node = TAILQ_FIRST(&addr_list->fields); 323 + addr_node; addr_node = TAILQ_NEXT(addr_node, link)) 324 + if (text2sockaddr(addr_node->field, port_str, &addr) 325 + == 0) { 326 + v = virtual_listen_lookup(addr); 327 + free(addr); 328 + if (v) { 329 + addr_str = addr_node->field; 330 + break; 331 + } 332 + } 333 + if (!addr_str) { 334 + log_print("udp_create: no matching listener found"); 335 + rv = 0; 484 336 goto ret; 485 337 } 486 338 } ··· 490 342 rv = 0; 491 343 goto ret; 492 344 } 493 - u = udp_listen_lookup(addr); 345 + 346 + v = virtual_listen_lookup(addr); 494 347 free(addr); 495 - if (!u) { 348 + if (!v) { 496 349 log_print("udp_create: %s:%s must exist as a listener too", 497 350 addr_str, port_str); 498 351 rv = 0; 499 352 goto ret; 500 353 } 501 - rv = udp_clone(u, dst); 354 + t = (struct transport *)v; 355 + rv = udp_clone(v->main, dst); 356 + if (rv) { 357 + rv->vtbl = &udp_transport_vtbl; 358 + transport_reference(rv->virtual); 359 + } 502 360 503 361 ret: 362 + if (addr_list) 363 + conf_free_list(addr_list); 504 364 free(dst); 505 365 return rv; 506 366 } ··· 517 377 if (t->flags & TRANSPORT_LISTEN) { 518 378 if (u->s >= 0) 519 379 close(u->s); 520 - if (t == default_transport) 521 - default_transport = 0; 522 - else if (t == default_transport6) 523 - default_transport6 = 0; 524 380 if (u->link.le_prev) 525 381 LIST_REMOVE(u, link); 526 382 } ··· 532 388 udp_report(struct transport *t) 533 389 { 534 390 struct udp_transport *u = (struct udp_transport *)t; 535 - char *src = NULL, *dst = NULL; 391 + char *src = NULL, *dst = NULL; 392 + in_port_t sport, dport; 536 393 537 394 if (sockaddr2text(u->src, &src, 0)) 538 395 goto ret; 396 + sport = sockaddr_port(u->src); 539 397 540 398 if (!u->dst || sockaddr2text(u->dst, &dst, 0)) 541 399 dst = 0; 400 + dport = dst ? sockaddr_port(u->dst) : 0; 542 401 543 - LOG_DBG((LOG_REPORT, 0, "udp_report: fd %d src %s dst %s", u->s, src, 544 - dst ? dst : "<none>")); 402 + LOG_DBG((LOG_REPORT, 0, "udp_report: fd %d src %s:%u dst %s:%u", u->s, 403 + src, ntohs(sport), dst ? dst : "<none>", ntohs(dport))); 545 404 546 405 ret: 547 406 if (dst) ··· 551 410 } 552 411 553 412 /* 554 - * Probe the interface list and determine what new interfaces have 555 - * appeared. 556 - * 557 - * At the same time, we try to determine whether existing interfaces have 558 - * been rendered invalid; we do this by marking all UDP transports before 559 - * we call udp_bind_if () through if_map (), and then releasing those 560 - * transports that have not been unmarked. 561 - */ 562 - static void 563 - udp_reinit(void) 564 - { 565 - struct udp_transport *u, *u2; 566 - char *port; 567 - 568 - /* Initialize the protocol and port numbers. */ 569 - port = udp_default_port ? udp_default_port : "500"; 570 - 571 - /* Mark all UDP transports, except the default ones. */ 572 - for (u = LIST_FIRST(&udp_listen_list); u; u = LIST_NEXT(u, link)) 573 - if (&u->transport != default_transport && 574 - &u->transport != default_transport6) 575 - u->transport.flags |= TRANSPORT_MARK; 576 - 577 - /* Re-probe interface list. */ 578 - if (if_map(udp_bind_if, port) == -1) 579 - log_print("udp_init: Could not bind the ISAKMP UDP port %s " 580 - "on all interfaces", port); 581 - 582 - /* 583 - * Release listening transports for local addresses that no 584 - * longer exist. udp_bind_if () will have left those still marked. 585 - */ 586 - u = LIST_FIRST(&udp_listen_list); 587 - while (u) { 588 - u2 = LIST_NEXT(u, link); 589 - 590 - if (u->transport.flags & TRANSPORT_MARK) { 591 - LIST_REMOVE(u, link); 592 - transport_release(&u->transport); 593 - } 594 - u = u2; 595 - } 596 - } 597 - 598 - /* 599 - * Find out the magic numbers for the UDP protocol as well as the UDP port 600 - * to use. Setup an UDP server for each address of this machine, and one 601 - * for the generic case when we are the initiator. 602 - */ 603 - void 604 - udp_init(void) 605 - { 606 - struct sockaddr_storage dflt_stor; 607 - struct sockaddr_in *dflt = (struct sockaddr_in *) & dflt_stor; 608 - struct conf_list *listen_on; 609 - char *port; 610 - long lport; 611 - char *ep; 612 - 613 - /* Initialize the protocol and port numbers. */ 614 - port = udp_default_port ? udp_default_port : "500"; 615 - 616 - LIST_INIT(&udp_listen_list); 617 - 618 - transport_method_add(&udp_transport_vtbl); 619 - 620 - /* Bind the ISAKMP UDP port on all network interfaces we have. */ 621 - if (if_map(udp_bind_if, port) == -1) 622 - log_fatal("udp_init: Could not bind the ISAKMP UDP port %s " 623 - "on all interfaces", port); 624 - 625 - /* Only listen to the specified address if Listen-on is configured */ 626 - listen_on = conf_get_list("General", "Listen-on"); 627 - if (listen_on) { 628 - LOG_DBG((LOG_TRANSPORT, 50, 629 - "udp_init: not binding ISAKMP UDP port to INADDR_ANY")); 630 - conf_free_list(listen_on); 631 - return; 632 - } 633 - /* 634 - * Get port. 635 - * XXX Use getservbyname too. 636 - */ 637 - lport = strtol(port, &ep, 10); 638 - if (*ep != '\0' || lport < (long) 0 || lport > (long) USHRT_MAX) { 639 - log_print("udp_init: port string \"%s\" not convertible to " 640 - "in_port_t", port); 641 - return; 642 - } 643 - /* 644 - * Bind to INADDR_ANY in case of new addresses popping up. Packet 645 - * reception on this transport is taken as a hint to reprobe the 646 - * interface list. 647 - */ 648 - if (!bind_family || (bind_family & BIND_FAMILY_INET4)) { 649 - memset(&dflt_stor, 0, sizeof dflt_stor); 650 - dflt->sin_family = AF_INET; 651 - #if !defined (LINUX_IPSEC) 652 - ((struct sockaddr_in *)dflt)->sin_len = 653 - sizeof(struct sockaddr_in); 654 - #endif 655 - ((struct sockaddr_in *)dflt)->sin_port = htons(lport); 656 - 657 - default_transport = udp_bind((struct sockaddr *)&dflt_stor); 658 - if (!default_transport) { 659 - log_error("udp_init: could not allocate default " 660 - "IPv4 ISAKMP UDP port"); 661 - return; 662 - } 663 - LIST_INSERT_HEAD(&udp_listen_list, 664 - (struct udp_transport *)default_transport, link); 665 - } 666 - if (!bind_family || (bind_family & BIND_FAMILY_INET6)) { 667 - memset(&dflt_stor, 0, sizeof dflt_stor); 668 - dflt->sin_family = AF_INET6; 669 - #if !defined (LINUX_IPSEC) 670 - ((struct sockaddr_in6 *)dflt)->sin6_len = 671 - sizeof(struct sockaddr_in6); 672 - #endif 673 - ((struct sockaddr_in6 *)dflt)->sin6_port = htons(lport); 674 - 675 - default_transport6 = udp_bind((struct sockaddr *)&dflt_stor); 676 - if (!default_transport6) { 677 - log_error("udp_init: could not allocate default " 678 - "IPv6 ISAKMP UDP port"); 679 - return; 680 - } 681 - LIST_INSERT_HEAD(&udp_listen_list, 682 - (struct udp_transport *)default_transport6, link); 683 - } 684 - } 685 - 686 - /* 687 - * Set transport T's socket in FDS, return a value useable by select(2) 688 - * as the number of file descriptors to check. 689 - */ 690 - static int 691 - udp_fd_set(struct transport *t, fd_set *fds, int bit) 692 - { 693 - struct udp_transport *u = (struct udp_transport *)t; 694 - 695 - if (bit) 696 - FD_SET(u->s, fds); 697 - else 698 - FD_CLR(u->s, fds); 699 - 700 - return u->s + 1; 701 - } 702 - 703 - /* Check if transport T's socket is set in FDS. */ 704 - static int 705 - udp_fd_isset(struct transport *t, fd_set *fds) 706 - { 707 - struct udp_transport *u = (struct udp_transport *)t; 708 - 709 - return FD_ISSET(u->s, fds); 710 - } 711 - 712 - /* 713 413 * A message has arrived on transport T's socket. If T is single-ended, 714 414 * clone it into a double-ended transport which we will use from now on. 715 415 * Package the message as we want it and continue processing in the message ··· 718 418 static void 719 419 udp_handle_message(struct transport *t) 720 420 { 721 - struct udp_transport *u = (struct udp_transport *) t; 421 + struct udp_transport *u = (struct udp_transport *)t; 722 422 u_int8_t buf[UDP_SIZE]; 723 423 struct sockaddr_storage from; 724 424 u_int32_t len = sizeof from; 725 425 ssize_t n; 726 426 struct message *msg; 727 427 728 - n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *) & from, &len); 428 + n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len); 729 429 if (n == -1) { 730 430 log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf, 731 431 UDP_SIZE, 0, &from, &len); 732 432 return; 733 433 } 734 434 /* 735 - * If we received the packet over the default transports, reprobe the 736 - * interfaces. 737 - */ 738 - if (t == default_transport || t == default_transport6) { 739 - udp_reinit(); 740 - 741 - /* 742 - * As we don't know the actual destination address of the 743 - * packet, we can't really deal with it. So, just ignore it 744 - * and hope we catch the retransmission. 745 - */ 746 - return; 747 - } 748 - /* 749 435 * Make a specialized UDP transport structure out of the incoming 750 436 * transport and the address information we got from recvfrom(2). 751 437 */ 752 - t = udp_clone(u, (struct sockaddr *)&from); 438 + t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from); 753 439 if (!t) 754 440 return; 755 441 ··· 757 443 if (!msg) { 758 444 log_error("failed to allocate message structure, dropping " 759 445 "packet received on transport %p", u); 446 + t->vtbl->remove(t); 760 447 return; 761 448 } 762 449 message_recv(msg); ··· 764 451 765 452 /* Physically send the message MSG over its associated transport. */ 766 453 static int 767 - udp_send_message(struct message *msg) 454 + udp_send_message(struct message *msg, struct transport *t) 768 455 { 769 - struct udp_transport *u = (struct udp_transport *)msg->transport; 456 + struct udp_transport *u = (struct udp_transport *)t; 770 457 ssize_t n; 771 458 struct msghdr m; 772 459 ··· 794 481 * Get transport T's peer address and stuff it into the sockaddr pointed 795 482 * to by DST. 796 483 */ 797 - static void 484 + void 798 485 udp_get_dst(struct transport *t, struct sockaddr **dst) 799 486 { 800 487 *dst = ((struct udp_transport *)t)->dst; ··· 804 491 * Get transport T's local address and stuff it into the sockaddr pointed 805 492 * to by SRC. Put its length into SRC_LEN. 806 493 */ 807 - static void 494 + void 808 495 udp_get_src(struct transport *t, struct sockaddr **src) 809 496 { 810 497 *src = ((struct udp_transport *)t)->src; 811 498 } 812 499 813 - static char * 500 + char * 814 501 udp_decode_ids(struct transport *t) 815 502 { 503 + struct sockaddr *src, *dst; 816 504 static char result[1024]; 817 505 char idsrc[256], iddst[256]; 818 506 507 + t->vtbl->get_src(t, &src); 508 + t->vtbl->get_dst(t, &dst); 509 + 819 510 #ifdef HAVE_GETNAMEINFO 820 - if (getnameinfo(((struct udp_transport *)t)->src, 821 - sysdep_sa_len(((struct udp_transport *)t)->src), 822 - idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) { 511 + if (getnameinfo(src, sysdep_sa_len(src), idsrc, sizeof idsrc, NULL, 0, 512 + NI_NUMERICHOST) != 0) { 823 513 log_print("udp_decode_ids: getnameinfo () failed for 'src'"); 824 514 strlcpy(idsrc, "<error>", 256); 825 515 } 826 - if (getnameinfo(((struct udp_transport *)t)->dst, 827 - sysdep_sa_len(((struct udp_transport *)t)->dst), 828 - iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) { 516 + if (getnameinfo(dst, sysdep_sa_len(dst), iddst, sizeof iddst, NULL, 0, 517 + NI_NUMERICHOST) != 0) { 829 518 log_print("udp_decode_ids: getnameinfo () failed for 'dst'"); 830 519 strlcpy(iddst, "<error>", 256); 831 520 } 832 521 #else 833 - strlcpy(idsrc, inet_ntoa(((struct udp_transport *)t)->src.sin_addr), 834 - 256); 835 - strlcpy(iddst, inet_ntoa(((struct udp_transport *)t)->dst.sin_addr), 836 - 256); 837 - #endif /* HAVE_GETNAMEINFO */ 522 + strlcpy(idsrc, inet_ntoa(src->sin_addr), 256); 523 + strlcpy(iddst, inet_ntoa(dst->sin_addr), 256); 524 + #endif /* HAVE_GETNAMEINFO */ 838 525 839 526 snprintf(result, sizeof result, "src: %s dst: %s", idsrc, iddst); 840 527 return result;
+11 -5
sbin/isakmpd/udp.h
··· 1 - /* $OpenBSD: udp.h,v 1.8 2004/04/15 18:39:26 deraadt Exp $ */ 1 + /* $OpenBSD: udp.h,v 1.9 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: udp.h,v 1.4 1998/12/22 02:23:43 niklas Exp $ */ 3 3 4 4 /* ··· 39 39 #define BIND_FAMILY_INET4 0x0001 40 40 #define BIND_FAMILY_INET6 0x0002 41 41 42 - #if 0 43 - extern in_port_t udp_decode_port(char *); 44 - #endif 45 - extern void udp_init(void); 42 + struct transport *udp_bind(const struct sockaddr *); 43 + void udp_init(void); 44 + 45 + struct udp_transport { 46 + struct transport transport; 47 + struct sockaddr *src; 48 + struct sockaddr *dst; 49 + int s; 50 + LIST_ENTRY(udp_transport) link; 51 + }; 46 52 47 53 #endif /* _UDP_H_ */
+461
sbin/isakmpd/udp_encap.c
··· 1 + /* $OpenBSD: udp_encap.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. 5 + * Copyright (c) 2000 Angelos D. Keromytis. All rights reserved. 6 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 7 + * 8 + * Redistribution and use in source and binary forms, with or without 9 + * modification, are permitted provided that the following conditions 10 + * are met: 11 + * 1. Redistributions of source code must retain the above copyright 12 + * notice, this list of conditions and the following disclaimer. 13 + * 2. Redistributions in binary form must reproduce the above copyright 14 + * notice, this list of conditions and the following disclaimer in the 15 + * documentation and/or other materials provided with the distribution. 16 + * 17 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 + */ 28 + 29 + #include <sys/types.h> 30 + #include <sys/ioctl.h> 31 + #include <sys/socket.h> 32 + #ifndef linux 33 + #include <sys/sockio.h> 34 + #endif 35 + #include <net/if.h> 36 + #include <netinet/in.h> 37 + #include <arpa/inet.h> 38 + #include <ctype.h> 39 + #include <err.h> 40 + #include <limits.h> 41 + #include <netdb.h> 42 + #include <stdlib.h> 43 + #include <string.h> 44 + #include <unistd.h> 45 + 46 + #include "sysdep.h" 47 + 48 + #include "conf.h" 49 + #include "if.h" 50 + #include "ipsec_doi.h" 51 + #include "isakmp.h" 52 + #include "log.h" 53 + #include "message.h" 54 + #include "monitor.h" 55 + #include "sysdep.h" 56 + #include "transport.h" 57 + #include "udp.h" 58 + #include "udp_encap.h" 59 + #include "util.h" 60 + #include "virtual.h" 61 + 62 + #define UDP_SIZE 65536 63 + 64 + /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */ 65 + #ifndef SO_REUSEPORT 66 + #define SO_REUSEPORT SO_REUSEADDR 67 + #endif 68 + 69 + /* Reused, from udp.c */ 70 + struct transport *udp_clone (struct transport *, struct sockaddr *); 71 + void udp_get_dst (struct transport *, struct sockaddr **); 72 + void udp_get_src (struct transport *, struct sockaddr **); 73 + char *udp_decode_ids (struct transport *); 74 + 75 + static struct transport *udp_encap_create (char *); 76 + static void udp_encap_remove (struct transport *); 77 + static void udp_encap_report (struct transport *); 78 + static void udp_encap_handle_message (struct transport *); 79 + static struct transport *udp_encap_make (struct sockaddr *); 80 + static int udp_encap_send_message (struct message *, 81 + struct transport *); 82 + 83 + static struct transport_vtbl udp_encap_transport_vtbl = { 84 + { 0 }, "udp_encap", 85 + udp_encap_create, 86 + 0, 87 + udp_encap_remove, 88 + udp_encap_report, 89 + 0, 90 + 0, 91 + udp_encap_handle_message, 92 + udp_encap_send_message, 93 + udp_get_dst, 94 + udp_get_src, 95 + udp_decode_ids, 96 + udp_clone, 97 + 0 98 + }; 99 + 100 + char *udp_encap_default_port = 0; 101 + char *udp_encap_bind_port = 0; 102 + 103 + void 104 + udp_encap_init(void) 105 + { 106 + transport_method_add(&udp_encap_transport_vtbl); 107 + } 108 + 109 + /* Create a UDP transport structure bound to LADDR just for listening. */ 110 + static struct transport * 111 + udp_encap_make(struct sockaddr *laddr) 112 + { 113 + struct udp_transport *t = 0; 114 + int s, on, wildcardaddress = 0; 115 + char *tstr; 116 + 117 + t = calloc(1, sizeof *t); 118 + if (!t) { 119 + log_print("udp_encap_make: malloc (%lu) failed", 120 + (unsigned long)sizeof *t); 121 + return 0; 122 + } 123 + 124 + s = socket(laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 125 + if (s == -1) { 126 + log_error("udp_encap_make: socket (%d, %d, %d)", 127 + laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 128 + goto err; 129 + } 130 + 131 + /* Make sure we don't get our traffic encrypted. */ 132 + if (sysdep_cleartext(s, laddr->sa_family) == -1) 133 + goto err; 134 + 135 + /* Wildcard address ? */ 136 + switch (laddr->sa_family) { 137 + case AF_INET: 138 + if (((struct sockaddr_in *)laddr)->sin_addr.s_addr 139 + == INADDR_ANY) 140 + wildcardaddress = 1; 141 + break; 142 + case AF_INET6: 143 + if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr)) 144 + wildcardaddress = 1; 145 + break; 146 + } 147 + 148 + /* 149 + * In order to have several bound specific address-port combinations 150 + * with the same port SO_REUSEADDR is needed. 151 + * If this is a wildcard socket and we are not listening there, but 152 + * only sending from it make sure it is entirely reuseable with 153 + * SO_REUSEPORT. 154 + */ 155 + on = 1; 156 + if (setsockopt(s, SOL_SOCKET, 157 + wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, 158 + (void *)&on, sizeof on) == -1) { 159 + log_error("udp_encap_make: setsockopt (%d, %d, %d, %p, %lu)", 160 + s, SOL_SOCKET, 161 + wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, &on, 162 + (unsigned long)sizeof on); 163 + goto err; 164 + } 165 + 166 + t->transport.vtbl = &udp_encap_transport_vtbl; 167 + t->src = laddr; 168 + if (monitor_bind(s, t->src, sysdep_sa_len (t->src))) { 169 + if (sockaddr2text(t->src, &tstr, 0)) 170 + log_error("udp_encap_make: bind (%d, %p, %lu)", s, 171 + &t->src, (unsigned long)sizeof t->src); 172 + else { 173 + log_error("udp_encap_make: bind (%d, %s, %lu)", s, 174 + tstr, (unsigned long)sizeof t->src); 175 + free(tstr); 176 + } 177 + goto err; 178 + } 179 + 180 + t->s = s; 181 + if (sockaddr2text(t->src, &tstr, 0)) 182 + LOG_DBG((LOG_MISC, 20, "udp_encap_make: " 183 + "transport %p socket %d family %d", t, s, 184 + t->src->sa_family == AF_INET ? 4 : 6)); 185 + else { 186 + LOG_DBG((LOG_MISC, 20, "udp_encap_make: " 187 + "transport %p socket %d ip %s port %d", t, s, 188 + tstr, ntohs(sockaddr_port(t->src)))); 189 + free(tstr); 190 + } 191 + transport_setup(&t->transport, 0); 192 + transport_reference(&t->transport); 193 + t->transport.flags |= TRANSPORT_LISTEN; 194 + return &t->transport; 195 + 196 + err: 197 + if (s >= 0) 198 + close (s); 199 + if (t) { 200 + /* Already closed. */ 201 + t->s = -1; 202 + udp_encap_remove(&t->transport); 203 + } 204 + return 0; 205 + } 206 + 207 + /* 208 + * Initialize an object of the UDP transport class. Fill in the local 209 + * IP address and port information and create a server socket bound to 210 + * that specific port. Add the polymorphic transport structure to the 211 + * system-wide pools of known ISAKMP transports. 212 + */ 213 + struct transport * 214 + udp_encap_bind(const struct sockaddr *addr) 215 + { 216 + struct sockaddr *src = 217 + malloc(sysdep_sa_len((struct sockaddr *)addr)); 218 + 219 + if (!src) 220 + return 0; 221 + 222 + memcpy(src, addr, sysdep_sa_len((struct sockaddr *)addr)); 223 + return udp_encap_make(src); 224 + } 225 + 226 + /* 227 + * NAME is a section name found in the config database. Setup and return 228 + * a transport useable to talk to the peer specified by that name. 229 + */ 230 + static struct transport * 231 + udp_encap_create(char *name) 232 + { 233 + struct virtual_transport *v; 234 + struct udp_transport *u; 235 + struct transport *rv, *t; 236 + struct sockaddr *dst, *addr; 237 + struct conf_list *addr_list = 0; 238 + struct conf_list_node *addr_node; 239 + char *addr_str, *port_str; 240 + 241 + port_str = conf_get_str(name, "Port"); /* XXX "Encap-port" ? */ 242 + if (!port_str) 243 + port_str = udp_encap_default_port; 244 + if (!port_str) 245 + port_str = UDP_ENCAP_DEFAULT_PORT_STR; 246 + 247 + addr_str = conf_get_str(name, "Address"); 248 + if (!addr_str) { 249 + log_print("udp_encap_create: no address configured " 250 + "for \"%s\"", name); 251 + return 0; 252 + } 253 + if (text2sockaddr(addr_str, port_str, &dst)) { 254 + log_print("udp_encap_create: address \"%s\" not understood", 255 + addr_str); 256 + return 0; 257 + } 258 + 259 + addr_str = conf_get_str(name, "Local-address"); 260 + if (!addr_str) 261 + addr_list = conf_get_list("General", "Listen-on"); 262 + if (!addr_str && !addr_list) { 263 + v = virtual_get_default(dst->sa_family); 264 + u = (struct udp_transport *)v->encap; 265 + 266 + if (!u) { 267 + log_print("udp_encap_create: no default transport"); 268 + rv = 0; 269 + goto ret; 270 + } else { 271 + rv = udp_clone((struct transport *)u, dst); 272 + if (rv) 273 + rv->vtbl = &udp_encap_transport_vtbl; 274 + goto ret; 275 + } 276 + } 277 + 278 + if (addr_list) { 279 + for (addr_node = TAILQ_FIRST(&addr_list->fields); 280 + addr_node; addr_node = TAILQ_NEXT(addr_node, link)) 281 + if (text2sockaddr(addr_node->field, port_str, 282 + &addr) == 0) { 283 + v = virtual_listen_lookup(addr); 284 + free(addr); 285 + if (v) { 286 + addr_str = addr_node->field; 287 + break; 288 + } 289 + } 290 + if (!addr_str) { 291 + log_print("udp_encap_create: " 292 + "no matching listener found"); 293 + rv = 0; 294 + goto ret; 295 + } 296 + } 297 + if (text2sockaddr(addr_str, port_str, &addr)) { 298 + log_print("udp_encap_create: " 299 + "address \"%s\" not understood", addr_str); 300 + rv = 0; 301 + goto ret; 302 + } 303 + v = virtual_listen_lookup(addr); 304 + free(addr); 305 + if (!v) { 306 + log_print("udp_encap_create: " 307 + "%s:%s must exist as a listener too", addr_str, port_str); 308 + rv = 0; 309 + goto ret; 310 + } 311 + t = (struct transport *)v; 312 + rv = udp_clone(v->encap, dst); 313 + if (rv) { 314 + rv->vtbl = &udp_encap_transport_vtbl; /* XXX Necessary? */ 315 + transport_reference(rv->virtual); 316 + } 317 + 318 + ret: 319 + if (addr_list) 320 + conf_free_list(addr_list); 321 + free(dst); 322 + return rv; 323 + } 324 + 325 + void 326 + udp_encap_remove(struct transport *t) 327 + { 328 + struct udp_transport *u = (struct udp_transport *)t; 329 + 330 + if (u->src) 331 + free (u->src); 332 + if (u->dst) 333 + free (u->dst); 334 + if (t->flags & TRANSPORT_LISTEN) { 335 + if (u->s >= 0) 336 + close (u->s); 337 + if (u->link.le_prev) 338 + LIST_REMOVE (u, link); 339 + } 340 + free (t); 341 + } 342 + 343 + /* Report transport-method specifics of the T transport. */ 344 + void 345 + udp_encap_report(struct transport *t) 346 + { 347 + struct udp_transport *u = (struct udp_transport *)t; 348 + char *src, *dst; 349 + in_port_t sport, dport; 350 + 351 + if (sockaddr2text(u->src, &src, 0)) 352 + goto ret; 353 + sport = sockaddr_port(u->src); 354 + 355 + if (!u->dst || sockaddr2text(u->dst, &dst, 0)) 356 + dst = 0; 357 + dport = dst ? sockaddr_port(u->dst) : 0; 358 + 359 + LOG_DBG ((LOG_REPORT, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u", 360 + u->s, src, ntohs(sport), dst ? dst : "*", ntohs(dport))); 361 + 362 + ret: 363 + if (dst) 364 + free(dst); 365 + if (src) 366 + free(src); 367 + } 368 + 369 + /* 370 + * A message has arrived on transport T's socket. If T is single-ended, 371 + * clone it into a double-ended transport which we will use from now on. 372 + * Package the message as we want it and continue processing in the message 373 + * module. 374 + */ 375 + static void 376 + udp_encap_handle_message(struct transport *t) 377 + { 378 + struct udp_transport *u = (struct udp_transport *)t; 379 + struct sockaddr_storage from; 380 + struct message *msg; 381 + u_int32_t len = sizeof from; 382 + ssize_t n; 383 + u_int8_t buf[UDP_SIZE]; 384 + 385 + n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len); 386 + if (n == -1) { 387 + log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf, 388 + UDP_SIZE, 0, &from, &len); 389 + return; 390 + } 391 + 392 + /* 393 + * Make a specialized UDP transport structure out of the incoming 394 + * transport and the address information we got from recvfrom(2). 395 + */ 396 + t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from); 397 + if (!t) 398 + return; 399 + 400 + /* Check NULL-ESP marker. */ 401 + if (n < sizeof (u_int32_t) || *(u_int32_t *)buf != 0) { 402 + /* Should never happen. */ 403 + log_print ("udp_encap_handle_message: " 404 + "Null-ESP marker not NULL or short message"); 405 + return; 406 + } 407 + 408 + msg = message_alloc(t, buf + sizeof (u_int32_t), 409 + n - sizeof (u_int32_t)); 410 + if (!msg) { 411 + log_error ("failed to allocate message structure, dropping " 412 + "packet received on transport %p", u); 413 + return; 414 + } 415 + message_recv (msg); 416 + } 417 + 418 + /* Physically send the message MSG over its associated transport. */ 419 + static int 420 + udp_encap_send_message(struct message *msg, struct transport *t) 421 + { 422 + struct udp_transport *u = (struct udp_transport *)t; 423 + struct msghdr m; 424 + struct iovec *new_iov; 425 + ssize_t n; 426 + u_int32_t marker = 0; /* NULL-ESP Marker */ 427 + 428 + /* Construct new iov array, prefixing NULL-ESP Marker. */ 429 + new_iov = (struct iovec *)calloc (msg->iovlen + 1, sizeof *new_iov); 430 + if (!new_iov) { 431 + log_error ("udp_encap_send_message: calloc (%lu, %lu) failed", 432 + (unsigned long)msg->iovlen + 1, 433 + (unsigned long)sizeof *new_iov); 434 + return -1; 435 + } 436 + new_iov[0].iov_base = &marker; 437 + new_iov[0].iov_len = IPSEC_SPI_SIZE; 438 + memcpy (new_iov + sizeof *new_iov, msg->iov, 439 + msg->iovlen * sizeof *new_iov); 440 + 441 + /* 442 + * Sending on connected sockets requires that no destination address is 443 + * given, or else EISCONN will occur. 444 + */ 445 + m.msg_name = (caddr_t)u->dst; 446 + m.msg_namelen = sysdep_sa_len (u->dst); 447 + m.msg_iov = new_iov; 448 + m.msg_iovlen = msg->iovlen + 1; 449 + m.msg_control = 0; 450 + m.msg_controllen = 0; 451 + m.msg_flags = 0; 452 + n = sendmsg (u->s, &m, 0); 453 + if (n == -1) { 454 + /* XXX We should check whether the address has gone away */ 455 + log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0); 456 + free (new_iov); 457 + return -1; 458 + } 459 + free (new_iov); 460 + return 0; 461 + }
+37
sbin/isakmpd/udp_encap.h
··· 1 + /* $OpenBSD: udp_encap.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. 5 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 6 + * 7 + * Redistribution and use in source and binary forms, with or without 8 + * modification, are permitted provided that the following conditions 9 + * are met: 10 + * 1. Redistributions of source code must retain the above copyright 11 + * notice, this list of conditions and the following disclaimer. 12 + * 2. Redistributions in binary form must reproduce the above copyright 13 + * notice, this list of conditions and the following disclaimer in the 14 + * documentation and/or other materials provided with the distribution. 15 + * 16 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 + */ 27 + 28 + #ifndef _UDP_ENCAP_H_ 29 + #define _UDP_ENCAP_H_ 30 + 31 + struct transport *udp_encap_bind (const struct sockaddr *); 32 + void udp_encap_init (void); 33 + 34 + extern char *udp_encap_default_port; 35 + extern char *udp_encap_bind_port; 36 + 37 + #endif /* _UDP_H_ */
+17 -2
sbin/isakmpd/util.c
··· 1 - /* $OpenBSD: util.c,v 1.42 2004/06/16 15:08:20 hshoexer Exp $ */ 1 + /* $OpenBSD: util.c,v 1.43 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. 6 - * Copyright (c) 2000, 2001 H�kan Olsson. All rights reserved. 6 + * Copyright (c) 2000, 2001, 2004 H�kan Olsson. All rights reserved. 7 7 * 8 8 * Redistribution and use in source and binary forms, with or without 9 9 * modification, are permitted provided that the following conditions ··· 450 450 log_print("sockaddr_port: unsupported protocol family %d", 451 451 sa->sa_family); 452 452 return 0; 453 + } 454 + } 455 + 456 + /* Utility function used to set the port of a sockaddr. */ 457 + void 458 + sockaddr_set_port(struct sockaddr *sa, in_port_t port) 459 + { 460 + switch (sa->sa_family) { 461 + case AF_INET: 462 + ((struct sockaddr_in *)sa)->sin_port = htons (port); 463 + break; 464 + 465 + case AF_INET6: 466 + ((struct sockaddr_in6 *)sa)->sin6_port = htons (port); 467 + break; 453 468 } 454 469 } 455 470
+3 -2
sbin/isakmpd/util.h
··· 1 - /* $OpenBSD: util.h,v 1.19 2004/05/23 16:14:22 deraadt Exp $ */ 1 + /* $OpenBSD: util.h,v 1.20 2004/06/20 15:24:05 ho Exp $ */ 2 2 /* $EOM: util.h,v 1.10 2000/10/24 13:33:39 niklas Exp $ */ 3 3 4 4 /* 5 5 * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. 6 - * Copyright (c) 2001 H�kan Olsson. All rights reserved. 6 + * Copyright (c) 2001, 2004 H�kan Olsson. All rights reserved. 7 7 * 8 8 * Redistribution and use in source and binary forms, with or without 9 9 * modification, are permitted provided that the following conditions ··· 63 63 extern u_int8_t *sockaddr_addrdata(struct sockaddr *); 64 64 extern int sockaddr_addrlen(struct sockaddr *); 65 65 extern in_port_t sockaddr_port(struct sockaddr *); 66 + extern void sockaddr_set_port(struct sockaddr *, in_port_t); 66 67 extern int text2sockaddr(char *, char *, struct sockaddr **); 67 68 extern void util_ntoa(char **, int, u_int8_t *); 68 69 extern int zero_test(const u_int8_t *, size_t);
+706
sbin/isakmpd/virtual.c
··· 1 + /* $OpenBSD: virtual.c,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 + * 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions 8 + * are met: 9 + * 1. Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * 2. Redistributions in binary form must reproduce the above copyright 12 + * notice, this list of conditions and the following disclaimer in the 13 + * documentation and/or other materials provided with the distribution. 14 + * 15 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 + */ 26 + 27 + #include <sys/types.h> 28 + #include <sys/ioctl.h> 29 + #include <sys/socket.h> 30 + #ifndef linux 31 + #include <sys/sockio.h> 32 + #endif 33 + #include <net/if.h> 34 + #include <netinet/in.h> 35 + #include <arpa/inet.h> 36 + #include <ctype.h> 37 + #include <err.h> 38 + #include <limits.h> 39 + #include <netdb.h> 40 + #include <stdlib.h> 41 + #include <string.h> 42 + #include <unistd.h> 43 + 44 + #include "conf.h" 45 + #include "if.h" 46 + #include "exchange.h" 47 + #include "log.h" 48 + #include "transport.h" 49 + #include "virtual.h" 50 + #include "udp.h" 51 + #include "util.h" 52 + 53 + #if defined (USE_NAT_TRAVERSAL) 54 + #include "udp_encap.h" 55 + #endif 56 + 57 + static struct transport *virtual_bind(const struct sockaddr *); 58 + static struct transport *virtual_bind_ADDR_ANY(sa_family_t); 59 + static int virtual_bind_if(char *, struct sockaddr *, void *); 60 + static struct transport *virtual_clone(struct transport *, struct sockaddr *); 61 + static struct transport *virtual_create(char *); 62 + static char *virtual_decode_ids (struct transport *); 63 + static int virtual_fd_set(struct transport *, fd_set *, int); 64 + static int virtual_fd_isset(struct transport *, fd_set *); 65 + static void virtual_get_dst(struct transport *, 66 + struct sockaddr **); 67 + static struct msg_head *virtual_get_queue(struct message *); 68 + static void virtual_get_src(struct transport *, 69 + struct sockaddr **); 70 + static void virtual_handle_message(struct transport *); 71 + static void virtual_reinit(void); 72 + static void virtual_remove(struct transport *); 73 + static void virtual_report(struct transport *); 74 + static int virtual_send_message(struct message *, 75 + struct transport *); 76 + 77 + static struct transport_vtbl virtual_transport_vtbl = { 78 + { 0 }, "udp", 79 + virtual_create, 80 + virtual_reinit, 81 + virtual_remove, 82 + virtual_report, 83 + virtual_fd_set, 84 + virtual_fd_isset, 85 + virtual_handle_message, 86 + virtual_send_message, 87 + virtual_get_dst, 88 + virtual_get_src, 89 + virtual_decode_ids, 90 + virtual_clone, 91 + virtual_get_queue 92 + }; 93 + 94 + static LIST_HEAD (virtual_listen_list, virtual_transport) virtual_listen_list; 95 + static struct transport *default_transport, *default_transport6; 96 + 97 + void 98 + virtual_init(void) 99 + { 100 + struct conf_list *listen_on; 101 + 102 + LIST_INIT(&virtual_listen_list); 103 + 104 + transport_method_add(&virtual_transport_vtbl); 105 + 106 + /* Bind the ISAKMP port(s) on all network interfaces we have. */ 107 + if (if_map(virtual_bind_if, 0) == -1) 108 + log_fatal("virtual_init: " 109 + "could not bind the ISAKMP port(s) on all interfaces"); 110 + 111 + /* Only listen to the specified address if Listen-on is configured */ 112 + listen_on = conf_get_list("General", "Listen-on"); 113 + if (listen_on) { 114 + LOG_DBG((LOG_TRANSPORT, 50, 115 + "virtual_init: not binding ISAKMP port(s) to ADDR_ANY")); 116 + conf_free_list(listen_on); 117 + return; 118 + } 119 + 120 + /* 121 + * Bind to INADDR_ANY in case of new addresses popping up. 122 + * Packet reception on this transport is taken as a hint to reprobe the 123 + * interface list. 124 + */ 125 + if (!bind_family || (bind_family & BIND_FAMILY_INET4)) { 126 + default_transport = virtual_bind_ADDR_ANY(AF_INET); 127 + if (!default_transport) 128 + return; 129 + LIST_INSERT_HEAD(&virtual_listen_list, 130 + (struct virtual_transport *)default_transport, link); 131 + } 132 + 133 + if (!bind_family || (bind_family & BIND_FAMILY_INET6)) { 134 + default_transport6 = virtual_bind_ADDR_ANY(AF_INET6); 135 + if (!default_transport6) 136 + return; 137 + LIST_INSERT_HEAD(&virtual_listen_list, 138 + (struct virtual_transport *)default_transport6, link); 139 + } 140 + } 141 + 142 + struct virtual_transport * 143 + virtual_get_default(sa_family_t af) 144 + { 145 + switch (af) { 146 + case AF_INET: 147 + return (struct virtual_transport *)default_transport; 148 + case AF_INET6: 149 + return (struct virtual_transport *)default_transport6; 150 + default: 151 + return 0; 152 + } 153 + } 154 + 155 + /* 156 + * Probe the interface list and determine what new interfaces have 157 + * appeared. 158 + * 159 + * At the same time, we try to determine whether existing interfaces have 160 + * been rendered invalid; we do this by marking all virtual transports before 161 + * we call virtual_bind_if () through if_map (), and then releasing those 162 + * transports that have not been unmarked. 163 + */ 164 + void 165 + virtual_reinit(void) 166 + { 167 + struct virtual_transport *v, *v2; 168 + 169 + /* Mark all UDP transports, except the default ones. */ 170 + for (v = LIST_FIRST(&virtual_listen_list); v; v = LIST_NEXT(v, link)) 171 + if (&v->transport != default_transport 172 + && &v->transport != default_transport6) 173 + v->transport.flags |= TRANSPORT_MARK; 174 + 175 + /* Re-probe interface list. */ 176 + if (if_map(virtual_bind_if, 0) == -1) 177 + log_print("virtual_init: " 178 + "could not bind the ISAKMP port(s) on all interfaces"); 179 + 180 + /* 181 + * Release listening transports for local addresses that no 182 + * longer exist. virtual_bind_if () will have left those still marked. 183 + */ 184 + v = LIST_FIRST(&virtual_listen_list); 185 + while (v) { 186 + v2 = LIST_NEXT(v, link); 187 + if (v->transport.flags & TRANSPORT_MARK) { 188 + LIST_REMOVE(v, link); 189 + transport_release(&v->transport); 190 + } 191 + v = v2; 192 + } 193 + } 194 + 195 + struct virtual_transport * 196 + virtual_listen_lookup(struct sockaddr *addr) 197 + { 198 + struct virtual_transport *v; 199 + struct udp_transport *u; 200 + 201 + for (v = LIST_FIRST(&virtual_listen_list); v; 202 + v = LIST_NEXT(v, link)) { 203 + u = (struct udp_transport *)v->main; 204 + if (u->src->sa_family == addr->sa_family 205 + && sockaddr_addrlen(u->src) == sockaddr_addrlen(addr) 206 + && memcmp(sockaddr_addrdata (u->src), 207 + sockaddr_addrdata(addr), 208 + sockaddr_addrlen(addr)) == 0) 209 + return v; 210 + } 211 + 212 + return 0; 213 + } 214 + 215 + /* 216 + * Initialize an object of the VIRTUAL transport class. 217 + */ 218 + static struct transport * 219 + virtual_bind(const struct sockaddr *addr) 220 + { 221 + struct virtual_transport *v; 222 + struct sockaddr_storage tmp_sa; 223 + char *port; 224 + char *ep; 225 + long lport; 226 + 227 + v = (struct virtual_transport *)calloc(1, sizeof *v); 228 + if (!v) { 229 + log_error("virtual_bind: calloc(1, %lu) failed", 230 + (unsigned long)sizeof *v); 231 + return 0; 232 + } 233 + 234 + v->transport.vtbl = &virtual_transport_vtbl; 235 + 236 + memcpy(&tmp_sa, addr, sysdep_sa_len((struct sockaddr *)addr)); 237 + 238 + /* 239 + * Get port. 240 + * XXX Use getservbyname too. 241 + */ 242 + port = udp_default_port ? udp_default_port : UDP_DEFAULT_PORT_STR; 243 + lport = strtol(port, &ep, 10); 244 + if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) { 245 + log_print("virtual_bind: " 246 + "port string \"%s\" not convertible to in_port_t", port); 247 + return 0; 248 + } 249 + 250 + sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport); 251 + v->main = udp_bind((struct sockaddr *)&tmp_sa); 252 + ((struct transport *)v->main)->virtual = (struct transport *)v; 253 + 254 + #if defined (USE_NAT_TRAVERSAL) 255 + memcpy(&tmp_sa, addr, sysdep_sa_len((struct sockaddr *)addr)); 256 + 257 + /* 258 + * Get port. 259 + * XXX Use getservbyname too. 260 + */ 261 + port = udp_encap_default_port 262 + ? udp_encap_default_port : UDP_ENCAP_DEFAULT_PORT_STR; 263 + lport = strtol(port, &ep, 10); 264 + if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) { 265 + log_print("virtual_bind: " 266 + "port string \"%s\" not convertible to in_port_t", port); 267 + return 0; 268 + } 269 + 270 + sockaddr_set_port((struct sockaddr *)&tmp_sa, (in_port_t)lport); 271 + v->encap = udp_encap_bind((struct sockaddr *)&tmp_sa); 272 + ((struct transport *)v->encap)->virtual = (struct transport *)v; 273 + #endif 274 + v->encap_is_active = 0; 275 + 276 + transport_setup(&v->transport, 1); 277 + transport_reference(&v->transport); 278 + v->transport.flags |= TRANSPORT_LISTEN; 279 + 280 + return (struct transport *)v; 281 + } 282 + 283 + static struct transport * 284 + virtual_bind_ADDR_ANY(sa_family_t af) 285 + { 286 + struct sockaddr_storage dflt_stor; 287 + struct sockaddr_in *d4 = (struct sockaddr_in *)&dflt_stor; 288 + struct sockaddr_in6 *d6 = (struct sockaddr_in6 *)&dflt_stor; 289 + struct transport *t; 290 + struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 291 + 292 + memset(&dflt_stor, 0, sizeof dflt_stor); 293 + switch (af) { 294 + case AF_INET: 295 + d4->sin_family = af; 296 + #if !defined (LINUX_IPSEC) 297 + d4->sin_len = sizeof(struct sockaddr_in); 298 + #endif 299 + d4->sin_addr.s_addr = INADDR_ANY; 300 + break; 301 + 302 + case AF_INET6: 303 + d6->sin6_family = af; 304 + #if !defined (LINUX_IPSEC) 305 + d6->sin6_len = sizeof(struct sockaddr_in6); 306 + #endif 307 + memcpy(&d6->sin6_addr.s6_addr, &in6addr_any, 308 + sizeof in6addr_any); 309 + break; 310 + } 311 + 312 + t = virtual_bind((struct sockaddr *)&dflt_stor); 313 + if (!t) 314 + log_error("virtual_bind_ADDR_ANY: " 315 + "could not allocate default IPv%s ISAKMP port(s)", 316 + af == AF_INET ? "4" : "6"); 317 + return t; 318 + } 319 + 320 + static int 321 + virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) 322 + { 323 + struct conf_list *listen_on; 324 + struct virtual_transport *v; 325 + struct conf_list_node *address; 326 + struct sockaddr *addr; 327 + struct transport *t; 328 + struct ifreq flags_ifr; 329 + char *addr_str; 330 + int s, error; 331 + 332 + #if defined (USE_DEBUG) 333 + if (sockaddr2text(if_addr, &addr_str, 0)) 334 + addr_str = 0; 335 + 336 + LOG_DBG((LOG_TRANSPORT, 90, 337 + "virtual_bind_if: interface %s family %s address %s", 338 + ifname ? ifname : "<unknown>", 339 + if_addr->sa_family == AF_INET ? "v4" : 340 + (if_addr->sa_family == AF_INET6 ? "v6" : "<unknown>"), 341 + addr_str ? addr_str : "<invalid>")); 342 + if (addr_str) 343 + free(addr_str); 344 + #endif 345 + 346 + /* 347 + * Drop non-Internet stuff. 348 + */ 349 + if ((if_addr->sa_family != AF_INET 350 + || sysdep_sa_len(if_addr) != sizeof (struct sockaddr_in)) 351 + && (if_addr->sa_family != AF_INET6 352 + || sysdep_sa_len(if_addr) != sizeof (struct sockaddr_in6))) 353 + return 0; 354 + 355 + /* 356 + * Only create sockets for families we should listen to. 357 + */ 358 + if (bind_family) 359 + switch (if_addr->sa_family) { 360 + case AF_INET: 361 + if ((bind_family & BIND_FAMILY_INET4) == 0) 362 + return 0; 363 + break; 364 + case AF_INET6: 365 + if ((bind_family & BIND_FAMILY_INET6) == 0) 366 + return 0; 367 + break; 368 + default: 369 + return 0; 370 + } 371 + 372 + /* 373 + * These special addresses are not useable as they have special meaning 374 + * in the IP stack. 375 + */ 376 + if (if_addr->sa_family == AF_INET 377 + && (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY 378 + || (((struct sockaddr_in *)if_addr)->sin_addr.s_addr 379 + == INADDR_NONE))) 380 + return 0; 381 + 382 + /* 383 + * Go through the list of transports and see if we already have this 384 + * address bound. If so, unmark the transport and skip it; this allows 385 + * us to call this function when we suspect a new address has appeared. 386 + */ 387 + if ((v = virtual_listen_lookup(if_addr)) != 0) { 388 + LOG_DBG ((LOG_TRANSPORT, 90, "virtual_bind_if: " 389 + "already bound")); 390 + v->transport.flags &= ~TRANSPORT_MARK; 391 + return 0; 392 + } 393 + 394 + /* 395 + * Don't bother with interfaces that are down. 396 + * Note: This socket is only used to collect the interface status. 397 + */ 398 + s = socket(if_addr->sa_family, SOCK_DGRAM, 0); 399 + if (s == -1) { 400 + log_error("virtual_bind_if: " 401 + "socket (%d, SOCK_DGRAM, 0) failed", if_addr->sa_family); 402 + return -1; 403 + } 404 + strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); 405 + if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&flags_ifr) == -1) { 406 + log_error("virtual_bind_if: " 407 + "ioctl (%d, SIOCGIFFLAGS, ...) failed", s); 408 + return -1; 409 + } 410 + close(s); 411 + if (!(flags_ifr.ifr_flags & IFF_UP)) 412 + return 0; 413 + 414 + /* Set the port number to zero. */ 415 + switch (if_addr->sa_family) { 416 + case AF_INET: 417 + ((struct sockaddr_in *)if_addr)->sin_port = htons(0); 418 + break; 419 + case AF_INET6: 420 + ((struct sockaddr_in6 *)if_addr)->sin6_port = htons(0); 421 + break; 422 + default: 423 + log_print("virtual_bind_if: unsupported protocol family %d", 424 + if_addr->sa_family); 425 + break; 426 + } 427 + 428 + /* 429 + * If we are explicit about what addresses we can listen to, be sure 430 + * to respect that option. 431 + * This is quite wasteful redoing the list-run for every interface, 432 + * but who cares? This is not an operation that needs to be fast. 433 + */ 434 + listen_on = conf_get_list("General", "Listen-on"); 435 + if (listen_on) { 436 + for (address = TAILQ_FIRST(&listen_on->fields); address; 437 + address = TAILQ_NEXT(address, link)) { 438 + if (text2sockaddr(address->field, 0, &addr)) { 439 + log_print("virtual_bind_if: " 440 + "invalid address %s in \"Listen-on\"", 441 + address->field); 442 + continue; 443 + } 444 + 445 + /* If found, take the easy way out. */ 446 + if (memcmp(addr, if_addr, 447 + sysdep_sa_len(addr)) == 0) { 448 + free(addr); 449 + break; 450 + } 451 + free(addr); 452 + } 453 + conf_free_list(listen_on); 454 + 455 + /* 456 + * If address is zero then we did not find the address among 457 + * the ones we should listen to. 458 + * XXX We do not discover if we do not find our listen 459 + * addresses. Maybe this should be the other way round. 460 + */ 461 + if (!address) 462 + return 0; 463 + } 464 + 465 + t = virtual_bind(if_addr); 466 + if (!t) { 467 + error = sockaddr2text(if_addr, &addr_str, 0); 468 + log_print("virtual_bind_if: failed to create a socket on %s", 469 + error ? "unknown" : addr_str); 470 + if (!error) 471 + free(addr_str); 472 + return -1; 473 + } 474 + LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)t, 475 + link); 476 + return 0; 477 + } 478 + 479 + static struct transport * 480 + virtual_clone(struct transport *vt, struct sockaddr *raddr) 481 + { 482 + struct virtual_transport *v = (struct virtual_transport *)vt; 483 + struct virtual_transport *v2; 484 + struct transport *t; 485 + 486 + t = malloc(sizeof *v); 487 + if (!t) { 488 + log_error("virtual_clone: malloc(%lu) failed", 489 + (unsigned long)sizeof *v); 490 + return 0; 491 + } 492 + v2 = (struct virtual_transport *)t; 493 + 494 + memcpy(v2, v, sizeof *v); 495 + 496 + if (v->encap_is_active) { 497 + v2->main = 0; 498 + v2->encap = v->encap->vtbl->clone(v->encap, raddr); 499 + v2->encap->virtual = (struct transport *)v2; 500 + } else { 501 + v2->main = v->main->vtbl->clone(v->main, raddr); 502 + v2->main->virtual = (struct transport *)v2; 503 + v2->encap = 0; 504 + } 505 + LOG_DBG((LOG_TRANSPORT, 50, "virtual_clone: old %p new %p (->%s %p)", 506 + v, t, v->encap_is_active ? "encap" : "main", 507 + v->encap_is_active ? v2->encap : v2->main)); 508 + 509 + t->flags &= ~TRANSPORT_LISTEN; 510 + transport_setup(t, 1); 511 + 512 + transport_reference(t); 513 + transport_reference(v->encap_is_active ? v2->encap : v2->main); 514 + 515 + return t; 516 + } 517 + 518 + static struct transport * 519 + virtual_create(char *name) 520 + { 521 + struct virtual_transport *v; 522 + struct transport *t, *t2; 523 + 524 + t = transport_create("udp_physical", name); 525 + if (!t) 526 + return 0; 527 + 528 + #if defined (USE_NAT_TRAVERSAL) 529 + t2 = transport_create("udp_encap", name); 530 + if (!t2) { 531 + t->vtbl->remove(t); 532 + return 0; 533 + } 534 + #else 535 + t2 = 0; 536 + #endif 537 + 538 + v = (struct virtual_transport *)calloc(1, sizeof *v); 539 + if (!v) { 540 + log_error("virtual_create: calloc(1, %lu) failed", 541 + (unsigned long)sizeof *v); 542 + t->vtbl->remove(t); 543 + if (t2) 544 + t2->vtbl->remove(t2); 545 + return 0; 546 + } 547 + 548 + memcpy(v, t, sizeof *t); 549 + v->transport.virtual = 0; 550 + v->main = t; 551 + v->encap = t2; 552 + v->transport.vtbl = &virtual_transport_vtbl; 553 + t->virtual = (struct transport *)v; 554 + if (t2) 555 + t2->virtual = (struct transport *)v; 556 + transport_setup(&v->transport, 1); 557 + LIST_INSERT_HEAD(&virtual_listen_list, v, link); 558 + 559 + return (struct transport *)v; 560 + } 561 + 562 + static void 563 + virtual_remove(struct transport *t) 564 + { 565 + struct virtual_transport *v = (struct virtual_transport *)t; 566 + 567 + if (v->encap) 568 + v->encap->vtbl->remove(v->encap); 569 + if (v->main) 570 + v->main->vtbl->remove(v->main); 571 + if (v->link.le_prev) 572 + LIST_REMOVE(v, link); 573 + 574 + free(t); 575 + } 576 + 577 + static void 578 + virtual_report(struct transport *t) 579 + { 580 + return; 581 + } 582 + 583 + static void 584 + virtual_handle_message(struct transport *t) 585 + { 586 + struct virtual_transport *v = (struct virtual_transport *)t; 587 + 588 + if (t == default_transport || t == default_transport6) { 589 + /* XXX drain pending message. See udp_handle_message(). */ 590 + 591 + virtual_reinit(); 592 + 593 + /* 594 + * As we don't know the actual destination address of the 595 + * packet, we can't really deal with it. So, just ignore it 596 + * and hope we catch the retransmission. 597 + */ 598 + return; 599 + } 600 + 601 + if (v->encap_is_active) 602 + v->encap->vtbl->handle_message(v->encap); 603 + else 604 + v->main->vtbl->handle_message(v->main); 605 + } 606 + 607 + static int 608 + virtual_send_message(struct message *msg, struct transport *t) 609 + { 610 + struct virtual_transport *v = 611 + (struct virtual_transport *)msg->transport; 612 + 613 + /* XXX Debug */ 614 + if (t) 615 + log_print("virtual_send_message: called with " 616 + "transport %p != NULL", t); 617 + 618 + #if defined (USE_NAT_TRAVERSAL) 619 + if (v->encap_is_active == 0 && 620 + (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE)) { 621 + LOG_DBG((LOG_MESSAGE, 10, "virtual_send_message: " 622 + "switching to ENCAP")); 623 + v->encap_is_active++; 624 + } 625 + #endif 626 + 627 + if (v->encap_is_active) 628 + return v->encap->vtbl->send_message(msg, v->encap); 629 + else 630 + return v->main->vtbl->send_message(msg, v->main); 631 + } 632 + 633 + static int 634 + virtual_fd_set(struct transport *t, fd_set *fds, int bit) 635 + { 636 + struct virtual_transport *v = (struct virtual_transport *)t; 637 + struct udp_transport *u; 638 + 639 + if (v->encap_is_active) 640 + u = (struct udp_transport *)v->encap; 641 + else 642 + u = (struct udp_transport *)v->main; 643 + 644 + if (bit) 645 + FD_SET(u->s, fds); 646 + else 647 + FD_CLR(u->s, fds); 648 + 649 + return u->s + 1; 650 + } 651 + 652 + static int 653 + virtual_fd_isset(struct transport *t, fd_set *fds) 654 + { 655 + struct virtual_transport *v = (struct virtual_transport *)t; 656 + struct udp_transport *u; 657 + 658 + if (v->encap_is_active) 659 + u = (struct udp_transport *)v->encap; 660 + else 661 + u = (struct udp_transport *)v->main; 662 + 663 + return FD_ISSET(u->s, fds); 664 + } 665 + 666 + static void 667 + virtual_get_src(struct transport *t, struct sockaddr **s) 668 + { 669 + struct virtual_transport *v = (struct virtual_transport *)t; 670 + 671 + if (v->encap_is_active) 672 + v->encap->vtbl->get_src(v->encap, s); 673 + else 674 + v->main->vtbl->get_src(v->main, s); 675 + } 676 + 677 + static void 678 + virtual_get_dst(struct transport *t, struct sockaddr **s) 679 + { 680 + struct virtual_transport *v = (struct virtual_transport *)t; 681 + 682 + if (v->encap_is_active) 683 + v->encap->vtbl->get_dst(v->encap, s); 684 + else 685 + v->main->vtbl->get_dst(v->main, s); 686 + } 687 + 688 + static char * 689 + virtual_decode_ids(struct transport *t) 690 + { 691 + struct virtual_transport *v = (struct virtual_transport *)t; 692 + 693 + if (v->encap_is_active) 694 + return v->encap->vtbl->decode_ids(t); 695 + else 696 + return v->main->vtbl->decode_ids(t); 697 + } 698 + 699 + static struct msg_head * 700 + virtual_get_queue(struct message *msg) 701 + { 702 + if (msg->flags & MSG_PRIORITIZED) 703 + return &msg->transport->prio_sendq; 704 + else 705 + return &msg->transport->sendq; 706 + }
+42
sbin/isakmpd/virtual.h
··· 1 + /* $OpenBSD: virtual.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */ 2 + 3 + /* 4 + * Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 + * 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions 8 + * are met: 9 + * 1. Redistributions of source code must retain the above copyright 10 + * notice, this list of conditions and the following disclaimer. 11 + * 2. Redistributions in binary form must reproduce the above copyright 12 + * notice, this list of conditions and the following disclaimer in the 13 + * documentation and/or other materials provided with the distribution. 14 + * 15 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 + */ 26 + 27 + #ifndef _TRP_VIRTUAL_H_ 28 + #define _TRP_VIRTUAL_H_ 29 + 30 + struct virtual_transport { 31 + struct transport transport; 32 + struct transport *main; /* Normally this transport is used. */ 33 + struct transport *encap; /* Or this, depending on 'encap_is_active'. */ 34 + int encap_is_active; 35 + LIST_ENTRY (virtual_transport) link; 36 + }; 37 + 38 + void virtual_init(void); 39 + struct virtual_transport *virtual_get_default(sa_family_t); 40 + struct virtual_transport *virtual_listen_lookup(struct sockaddr *); 41 + 42 + #endif /* _TRP_VIRTUAL_H_ */