1 /* $OpenBSD: virtual.c,v 1.32 2015/08/20 22:02:21 deraadt 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 #include <sys/sockio.h> 31 #include <net/if.h> 32 #include <netinet/in.h> 33 #include <netinet6/in6_var.h> 34 #include <arpa/inet.h> 35 #include <ctype.h> 36 #include <limits.h> 37 #include <netdb.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include "conf.h" 43 #include "if.h" 44 #include "exchange.h" 45 #include "log.h" 46 #include "message.h" 47 #include "nat_traversal.h" 48 #include "transport.h" 49 #include "virtual.h" 50 #include "udp.h" 51 #include "util.h" 52 53 #include "udp_encap.h" 54 55 static struct transport *virtual_bind(const struct sockaddr *); 56 static struct transport *virtual_bind_ADDR_ANY(sa_family_t); 57 static int virtual_bind_if(char *, struct sockaddr *, void *); 58 static struct transport *virtual_clone(struct transport *, struct sockaddr *); 59 static struct transport *virtual_create(char *); 60 static char *virtual_decode_ids (struct transport *); 61 static void virtual_get_dst(struct transport *, 62 struct sockaddr **); 63 static struct msg_head *virtual_get_queue(struct message *); 64 static void virtual_get_src(struct transport *, 65 struct sockaddr **); 66 static void virtual_handle_message(struct transport *); 67 static void virtual_reinit(void); 68 static void virtual_remove(struct transport *); 69 static void virtual_report(struct transport *); 70 static int virtual_send_message(struct message *, 71 struct transport *); 72 73 static struct transport_vtbl virtual_transport_vtbl = { 74 { 0 }, "udp", 75 virtual_create, 76 virtual_reinit, 77 virtual_remove, 78 virtual_report, 79 0, 80 0, 81 virtual_handle_message, 82 virtual_send_message, 83 virtual_get_dst, 84 virtual_get_src, 85 virtual_decode_ids, 86 virtual_clone, 87 virtual_get_queue 88 }; 89 90 static LIST_HEAD (virtual_listen_list, virtual_transport) virtual_listen_list; 91 static struct transport *default_transport, *default_transport6; 92 93 void 94 virtual_init(void) 95 { 96 struct conf_list *listen_on; 97 98 LIST_INIT(&virtual_listen_list); 99 100 transport_method_add(&virtual_transport_vtbl); 101 102 /* Bind the ISAKMP port(s) on all network interfaces we have. */ 103 if (if_map(virtual_bind_if, 0) == -1) 104 log_fatal("virtual_init: " 105 "could not bind the ISAKMP port(s) on all interfaces"); 106 107 /* Only listen to the specified address if Listen-on is configured */ 108 listen_on = conf_get_list("General", "Listen-on"); 109 if (listen_on) { 110 LOG_DBG((LOG_TRANSPORT, 50, 111 "virtual_init: not binding ISAKMP port(s) to ADDR_ANY")); 112 conf_free_list(listen_on); 113 return; 114 } 115 116 /* 117 * Bind to INADDR_ANY in case of new addresses popping up. 118 * Packet reception on this transport is taken as a hint to reprobe the 119 * interface list. 120 */ 121 if (!bind_family || (bind_family & BIND_FAMILY_INET4)) { 122 default_transport = virtual_bind_ADDR_ANY(AF_INET); 123 if (!default_transport) 124 return; 125 LIST_INSERT_HEAD(&virtual_listen_list, 126 (struct virtual_transport *)default_transport, link); 127 transport_reference(default_transport); 128 } 129 130 if (!bind_family || (bind_family & BIND_FAMILY_INET6)) { 131 default_transport6 = virtual_bind_ADDR_ANY(AF_INET6); 132 if (!default_transport6) 133 return; 134 LIST_INSERT_HEAD(&virtual_listen_list, 135 (struct virtual_transport *)default_transport6, link); 136 transport_reference(default_transport6); 137 } 138 } 139 140 struct virtual_transport * 141 virtual_get_default(sa_family_t af) 142 { 143 switch (af) { 144 case AF_INET: 145 return (struct virtual_transport *)default_transport; 146 case AF_INET6: 147 return (struct virtual_transport *)default_transport6; 148 default: 149 return 0; 150 } 151 } 152 153 /* 154 * Probe the interface list and determine what new interfaces have 155 * appeared. 156 * 157 * At the same time, we try to determine whether existing interfaces have 158 * been rendered invalid; we do this by marking all virtual transports before 159 * we call virtual_bind_if() through if_map(), and then releasing those 160 * transports that have not been unmarked. 161 */ 162 void 163 virtual_reinit(void) 164 { 165 struct virtual_transport *v, *v2; 166 167 /* Mark all UDP transports, except the default ones. */ 168 for (v = LIST_FIRST(&virtual_listen_list); v; v = LIST_NEXT(v, link)) 169 if (&v->transport != default_transport && 170 &v->transport != default_transport6) 171 v->transport.flags |= TRANSPORT_MARK; 172 173 /* Re-probe interface list. */ 174 if (if_map(virtual_bind_if, 0) == -1) 175 log_print("virtual_init: " 176 "could not bind the ISAKMP port(s) on all interfaces"); 177 178 /* 179 * Release listening transports for local addresses that no 180 * longer exist. virtual_bind_if () will have left those still marked. 181 */ 182 v = LIST_FIRST(&virtual_listen_list); 183 while (v) { 184 v2 = LIST_NEXT(v, link); 185 if (v->transport.flags & TRANSPORT_MARK) { 186 LIST_REMOVE(v, link); 187 transport_release(&v->transport); 188 } 189 v = v2; 190 } 191 } 192 193 struct virtual_transport * 194 virtual_listen_lookup(struct sockaddr *addr) 195 { 196 struct virtual_transport *v; 197 struct udp_transport *u; 198 199 for (v = LIST_FIRST(&virtual_listen_list); v; 200 v = LIST_NEXT(v, link)) { 201 if (!(u = (struct udp_transport *)v->main)) 202 if (!(u = (struct udp_transport *)v->encap)) { 203 log_print("virtual_listen_lookup: " 204 "virtual %p has no low-level transports", 205 v); 206 continue; 207 } 208 209 if (u->src->sa_family == addr->sa_family && 210 sockaddr_addrlen(u->src) == sockaddr_addrlen(addr) && 211 memcmp(sockaddr_addrdata (u->src), sockaddr_addrdata(addr), 212 sockaddr_addrlen(addr)) == 0) 213 return v; 214 } 215 216 LOG_DBG((LOG_TRANSPORT, 40, "virtual_listen_lookup: no match")); 217 return 0; 218 } 219 220 /* 221 * Initialize an object of the VIRTUAL transport class. 222 */ 223 static struct transport * 224 virtual_bind(const struct sockaddr *addr) 225 { 226 struct virtual_transport *v; 227 struct sockaddr_storage tmp_sa; 228 char *stport; 229 in_port_t port; 230 231 v = calloc(1, sizeof *v); 232 if (!v) { 233 log_error("virtual_bind: calloc(1, %lu) failed", 234 (unsigned long)sizeof *v); 235 return 0; 236 } 237 238 v->transport.vtbl = &virtual_transport_vtbl; 239 240 memcpy(&tmp_sa, addr, SA_LEN(addr)); 241 242 /* Get port. */ 243 stport = udp_default_port ? udp_default_port : UDP_DEFAULT_PORT_STR; 244 port = text2port(stport); 245 if (port == 0) { 246 log_print("virtual_bind: bad port \"%s\"", stport); 247 free(v); 248 return 0; 249 } 250 251 sockaddr_set_port((struct sockaddr *)&tmp_sa, port); 252 v->main = udp_bind((struct sockaddr *)&tmp_sa); 253 if (!v->main) { 254 free(v); 255 return 0; 256 } 257 v->main->virtual = (struct transport *)v; 258 259 if (!disable_nat_t) { 260 memcpy(&tmp_sa, addr, SA_LEN(addr)); 261 262 /* Get port. */ 263 stport = udp_encap_default_port 264 ? udp_encap_default_port : UDP_ENCAP_DEFAULT_PORT_STR; 265 port = text2port(stport); 266 if (port == 0) { 267 log_print("virtual_bind: bad encap port \"%s\"", 268 stport); 269 v->main->vtbl->remove(v->main); 270 free(v); 271 return 0; 272 } 273 274 sockaddr_set_port((struct sockaddr *)&tmp_sa, port); 275 v->encap = udp_encap_bind((struct sockaddr *)&tmp_sa); 276 if (!v->encap) { 277 v->main->vtbl->remove(v->main); 278 free(v); 279 return 0; 280 } 281 v->encap->virtual = (struct transport *)v; 282 } 283 v->encap_is_active = 0; 284 285 transport_setup(&v->transport, 1); 286 v->transport.flags |= TRANSPORT_LISTEN; 287 288 return (struct transport *)v; 289 } 290 291 static struct transport * 292 virtual_bind_ADDR_ANY(sa_family_t af) 293 { 294 struct sockaddr_storage dflt_stor; 295 struct sockaddr_in *d4 = (struct sockaddr_in *)&dflt_stor; 296 struct sockaddr_in6 *d6 = (struct sockaddr_in6 *)&dflt_stor; 297 struct transport *t; 298 struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 299 300 bzero(&dflt_stor, sizeof dflt_stor); 301 switch (af) { 302 case AF_INET: 303 d4->sin_family = af; 304 d4->sin_len = sizeof(struct sockaddr_in); 305 d4->sin_addr.s_addr = INADDR_ANY; 306 break; 307 308 case AF_INET6: 309 d6->sin6_family = af; 310 d6->sin6_len = sizeof(struct sockaddr_in6); 311 memcpy(&d6->sin6_addr.s6_addr, &in6addr_any, 312 sizeof in6addr_any); 313 break; 314 } 315 316 t = virtual_bind((struct sockaddr *)&dflt_stor); 317 if (!t) 318 log_error("virtual_bind_ADDR_ANY: " 319 "could not allocate default IPv%s ISAKMP port(s)", 320 af == AF_INET ? "4" : "6"); 321 return t; 322 } 323 324 static int 325 virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) 326 { 327 struct conf_list *listen_on; 328 struct virtual_transport *v; 329 struct conf_list_node *address; 330 struct sockaddr *addr; 331 struct transport *t; 332 struct ifreq flags_ifr; 333 struct in6_ifreq flags_ifr6; 334 char *addr_str; 335 int s, error; 336 337 if (sockaddr2text(if_addr, &addr_str, 0)) 338 addr_str = 0; 339 340 LOG_DBG((LOG_TRANSPORT, 90, 341 "virtual_bind_if: interface %s family %s address %s", 342 ifname ? ifname : "<unknown>", 343 if_addr->sa_family == AF_INET ? "v4" : 344 (if_addr->sa_family == AF_INET6 ? "v6" : "<unknown>"), 345 addr_str ? addr_str : "<invalid>")); 346 free(addr_str); 347 348 /* 349 * Drop non-Internet stuff. 350 */ 351 if ((if_addr->sa_family != AF_INET || 352 SA_LEN(if_addr) != sizeof (struct sockaddr_in)) && 353 (if_addr->sa_family != AF_INET6 || 354 SA_LEN(if_addr) != sizeof (struct sockaddr_in6))) 355 return 0; 356 357 /* 358 * Only create sockets for families we should listen to. 359 */ 360 if (bind_family) 361 switch (if_addr->sa_family) { 362 case AF_INET: 363 if ((bind_family & BIND_FAMILY_INET4) == 0) 364 return 0; 365 break; 366 case AF_INET6: 367 if ((bind_family & BIND_FAMILY_INET6) == 0) 368 return 0; 369 break; 370 default: 371 return 0; 372 } 373 374 /* 375 * These special addresses are not useable as they have special meaning 376 * in the IP stack. 377 */ 378 if (if_addr->sa_family == AF_INET && 379 (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY || 380 (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_NONE))) 381 return 0; 382 383 /* 384 * Go through the list of transports and see if we already have this 385 * address bound. If so, unmark the transport and skip it; this allows 386 * us to call this function when we suspect a new address has appeared. 387 */ 388 if ((v = virtual_listen_lookup(if_addr)) != 0) { 389 LOG_DBG ((LOG_TRANSPORT, 90, "virtual_bind_if: " 390 "already bound")); 391 v->transport.flags &= ~TRANSPORT_MARK; 392 return 0; 393 } 394 395 /* 396 * Don't bother with interfaces that are down. 397 * Note: This socket is only used to collect the interface status, 398 * rtables and inet6 addresses. 399 */ 400 s = socket(if_addr->sa_family, SOCK_DGRAM, 0); 401 if (s == -1) { 402 log_error("virtual_bind_if: " 403 "socket (%d, SOCK_DGRAM, 0) failed", if_addr->sa_family); 404 return -1; 405 } 406 strlcpy(flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); 407 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&flags_ifr) == -1) { 408 log_error("virtual_bind_if: " 409 "ioctl (%d, SIOCGIFFLAGS, ...) failed", s); 410 close(s); 411 return -1; 412 } 413 if (!(flags_ifr.ifr_flags & IFF_UP)) { 414 close(s); 415 return 0; 416 } 417 /* Also skip tentative addresses during DAD since bind(2) would fail. */ 418 if (if_addr->sa_family == AF_INET6) { 419 memset(&flags_ifr6, 0, sizeof(flags_ifr6)); 420 strlcpy(flags_ifr6.ifr_name, ifname, sizeof flags_ifr6.ifr_name); 421 flags_ifr6.ifr_addr = *(struct sockaddr_in6 *)if_addr; 422 if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&flags_ifr6) < 0) { 423 log_error("virtual_bind_if: " 424 "ioctl (%d, SIOCGIFAFLAG_IN6, ...) failed", s); 425 close(s); 426 return 0; 427 } 428 if (flags_ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_ANYCAST| 429 IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED|IN6_IFF_DETACHED)) { 430 error = sockaddr2text(if_addr, &addr_str, 0); 431 log_print("virtual_bind_if: " 432 "IPv6 address %s not ready (flags 0x%x)", 433 error ? "unknown" : addr_str, 434 flags_ifr6.ifr_ifru.ifru_flags6); 435 /* XXX schedule an interface rescan */ 436 if (!error) 437 free(addr_str); 438 close(s); 439 return 0; 440 } 441 } 442 443 if (ioctl(s, SIOCGIFRDOMAIN, (caddr_t)&flags_ifr) == -1) { 444 log_error("virtual_bind_if: " 445 "ioctl (%d, SIOCGIFRDOMAIN, ...) failed", s); 446 close(s); 447 return -1; 448 } 449 450 /* 451 * Ignore interfaces outside of our rtable 452 */ 453 if (getrtable() != flags_ifr.ifr_rdomainid) { 454 close(s); 455 return 0; 456 } 457 458 close(s); 459 460 /* Set the port number to zero. */ 461 switch (if_addr->sa_family) { 462 case AF_INET: 463 ((struct sockaddr_in *)if_addr)->sin_port = htons(0); 464 break; 465 case AF_INET6: 466 ((struct sockaddr_in6 *)if_addr)->sin6_port = htons(0); 467 break; 468 default: 469 log_print("virtual_bind_if: unsupported protocol family %d", 470 if_addr->sa_family); 471 break; 472 } 473 474 /* 475 * If we are explicit about what addresses we can listen to, be sure 476 * to respect that option. 477 * This is quite wasteful redoing the list-run for every interface, 478 * but who cares? This is not an operation that needs to be fast. 479 */ 480 listen_on = conf_get_list("General", "Listen-on"); 481 if (listen_on) { 482 for (address = TAILQ_FIRST(&listen_on->fields); address; 483 address = TAILQ_NEXT(address, link)) { 484 if (text2sockaddr(address->field, 0, &addr, 0, 0)) { 485 log_print("virtual_bind_if: " 486 "invalid address %s in \"Listen-on\"", 487 address->field); 488 continue; 489 } 490 491 /* If found, take the easy way out. */ 492 if (memcmp(addr, if_addr, SA_LEN(addr)) == 0) { 493 free(addr); 494 break; 495 } 496 free(addr); 497 } 498 conf_free_list(listen_on); 499 500 /* 501 * If address is zero then we did not find the address among 502 * the ones we should listen to. 503 * XXX We do not discover if we do not find our listen 504 * addresses. Maybe this should be the other way round. 505 */ 506 if (!address) 507 return 0; 508 } 509 510 t = virtual_bind(if_addr); 511 if (!t) { 512 error = sockaddr2text(if_addr, &addr_str, 0); 513 log_print("virtual_bind_if: failed to create a socket on %s", 514 error ? "unknown" : addr_str); 515 if (!error) 516 free(addr_str); 517 return -1; 518 } 519 LIST_INSERT_HEAD(&virtual_listen_list, (struct virtual_transport *)t, 520 link); 521 transport_reference(t); 522 return 0; 523 } 524 525 static struct transport * 526 virtual_clone(struct transport *vt, struct sockaddr *raddr) 527 { 528 struct virtual_transport *v = (struct virtual_transport *)vt; 529 struct virtual_transport *v2; 530 struct transport *t; 531 char *stport; 532 in_port_t port; 533 534 t = malloc(sizeof *v); 535 if (!t) { 536 log_error("virtual_clone: malloc(%lu) failed", 537 (unsigned long)sizeof *v); 538 return 0; 539 } 540 v2 = (struct virtual_transport *)t; 541 542 memcpy(v2, v, sizeof *v); 543 /* Remove the copy's links into virtual_listen_list. */ 544 memset(&v2->link, 0, sizeof v2->link); 545 546 if (v->encap_is_active) 547 v2->main = 0; /* No need to clone this. */ 548 else { 549 v2->main = v->main->vtbl->clone(v->main, raddr); 550 v2->main->virtual = (struct transport *)v2; 551 } 552 if (!disable_nat_t) { 553 stport = udp_encap_default_port ? udp_encap_default_port : 554 UDP_ENCAP_DEFAULT_PORT_STR; 555 port = text2port(stport); 556 if (port == 0) { 557 log_print("virtual_clone: port string \"%s\" not convertible " 558 "to in_port_t", stport); 559 free(t); 560 return 0; 561 } 562 sockaddr_set_port(raddr, port); 563 v2->encap = v->encap->vtbl->clone(v->encap, raddr); 564 v2->encap->virtual = (struct transport *)v2; 565 } 566 LOG_DBG((LOG_TRANSPORT, 50, "virtual_clone: old %p new %p (%s is %p)", 567 v, t, v->encap_is_active ? "encap" : "main", 568 v->encap_is_active ? v2->encap : v2->main)); 569 570 t->flags &= ~TRANSPORT_LISTEN; 571 transport_setup(t, 1); 572 return t; 573 } 574 575 static struct transport * 576 virtual_create(char *name) 577 { 578 struct virtual_transport *v; 579 struct transport *t, *t2 = 0; 580 581 t = transport_create("udp_physical", name); 582 if (!t) 583 return 0; 584 585 if (!disable_nat_t) { 586 t2 = transport_create("udp_encap", name); 587 if (!t2) { 588 t->vtbl->remove(t); 589 return 0; 590 } 591 } 592 593 v = calloc(1, sizeof *v); 594 if (!v) { 595 log_error("virtual_create: calloc(1, %lu) failed", 596 (unsigned long)sizeof *v); 597 t->vtbl->remove(t); 598 if (t2) 599 t2->vtbl->remove(t2); 600 return 0; 601 } 602 603 memcpy(v, t, sizeof *t); 604 v->transport.virtual = 0; 605 v->main = t; 606 v->encap = t2; 607 v->transport.vtbl = &virtual_transport_vtbl; 608 t->virtual = (struct transport *)v; 609 if (t2) 610 t2->virtual = (struct transport *)v; 611 transport_setup(&v->transport, 1); 612 return (struct transport *)v; 613 } 614 615 static void 616 virtual_remove(struct transport *t) 617 { 618 struct virtual_transport *p, *v = (struct virtual_transport *)t; 619 620 if (v->encap) 621 v->encap->vtbl->remove(v->encap); 622 if (v->main) 623 v->main->vtbl->remove(v->main); 624 625 for (p = LIST_FIRST(&virtual_listen_list); p && p != v; p = 626 LIST_NEXT(p, link)) 627 ; 628 if (p == v) 629 LIST_REMOVE(v, link); 630 631 LOG_DBG((LOG_TRANSPORT, 90, "virtual_remove: removed %p", v)); 632 free(t); 633 } 634 635 static void 636 virtual_report(struct transport *t) 637 { 638 } 639 640 static void 641 virtual_handle_message(struct transport *t) 642 { 643 /* 644 * As per the NAT-T draft, in case we have already switched ports, 645 * any messages received on the old (500) port SHOULD be discarded. 646 * (Actually, while phase 1 messages should be discarded, 647 * informational exchanges MAY be processed normally. For now, we 648 * discard them all.) 649 */ 650 if (((struct virtual_transport *)t->virtual)->encap_is_active && 651 ((struct virtual_transport *)t->virtual)->main == t) { 652 LOG_DBG((LOG_MESSAGE, 10, "virtual_handle_message: " 653 "message on old port discarded")); 654 return; 655 } 656 657 t->vtbl->handle_message(t); 658 } 659 660 static int 661 virtual_send_message(struct message *msg, struct transport *t) 662 { 663 struct virtual_transport *v = 664 (struct virtual_transport *)msg->transport; 665 struct sockaddr *dst; 666 in_port_t port, default_port; 667 668 /* 669 * Activate NAT-T Encapsulation if 670 * - the exchange says we can, and 671 * - in ID_PROT, after step 4 (draft-ietf-ipsec-nat-t-ike-03), or 672 * - in other exchange (Aggressive, ), asap 673 * XXX ISAKMP_EXCH_BASE etc? 674 */ 675 676 if (msg->flags & MSG_NATT) { 677 msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; 678 msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER; 679 } 680 681 if ((v->encap_is_active == 0 && 682 (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE) && 683 (msg->exchange->type != ISAKMP_EXCH_ID_PROT || 684 msg->exchange->step > 4)) || (msg->flags & MSG_NATT)) { 685 LOG_DBG((LOG_MESSAGE, 10, "virtual_send_message: " 686 "enabling NAT-T encapsulation for this exchange")); 687 v->encap_is_active++; 688 689 /* Copy destination port if it is translated (NAT). */ 690 v->main->vtbl->get_dst(v->main, &dst); 691 port = ntohs(sockaddr_port(dst)); 692 693 if (udp_default_port) 694 default_port = text2port(udp_default_port); 695 else 696 default_port = UDP_DEFAULT_PORT; 697 if (port != default_port) { 698 v->main->vtbl->get_dst(v->encap, &dst); 699 sockaddr_set_port(dst, port); 700 } 701 } 702 703 if (v->encap_is_active) 704 return v->encap->vtbl->send_message(msg, v->encap); 705 else 706 return v->main->vtbl->send_message(msg, v->main); 707 } 708 709 static void 710 virtual_get_src(struct transport *t, struct sockaddr **s) 711 { 712 struct virtual_transport *v = (struct virtual_transport *)t; 713 714 if (v->encap_is_active) 715 v->encap->vtbl->get_src(v->encap, s); 716 else 717 v->main->vtbl->get_src(v->main, s); 718 } 719 720 static void 721 virtual_get_dst(struct transport *t, struct sockaddr **s) 722 { 723 struct virtual_transport *v = (struct virtual_transport *)t; 724 725 if (v->encap_is_active) 726 v->encap->vtbl->get_dst(v->encap, s); 727 else 728 v->main->vtbl->get_dst(v->main, s); 729 } 730 731 static char * 732 virtual_decode_ids(struct transport *t) 733 { 734 struct virtual_transport *v = (struct virtual_transport *)t; 735 736 if (v->encap_is_active) 737 return v->encap->vtbl->decode_ids(t); 738 else 739 return v->main->vtbl->decode_ids(t); 740 } 741 742 static struct msg_head * 743 virtual_get_queue(struct message *msg) 744 { 745 if (msg->flags & MSG_PRIORITIZED) 746 return &msg->transport->prio_sendq; 747 else 748 return &msg->transport->sendq; 749 } 750