1 /* $OpenBSD: udp.c,v 1.64 2003/06/10 16:41:29 deraadt Exp $ */ 2 /* $EOM: udp.c,v 1.57 2001/01/26 10:09:57 niklas Exp $ */ 3 4 /* 5 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. 6 * Copyright (c) 2000 Angelos D. Keromytis. 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 /* 30 * This code was written under funding by Ericsson Radio Systems. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/ioctl.h> 35 #include <sys/socket.h> 36 #ifndef linux 37 #include <sys/sockio.h> 38 #endif 39 #include <net/if.h> 40 #include <netinet/in.h> 41 #include <arpa/inet.h> 42 #include <ctype.h> 43 #include <err.h> 44 #include <limits.h> 45 #include <netdb.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "sysdep.h" 51 52 #include "conf.h" 53 #include "if.h" 54 #include "isakmp.h" 55 #include "log.h" 56 #include "message.h" 57 #include "monitor.h" 58 #include "sysdep.h" 59 #include "transport.h" 60 #include "udp.h" 61 #include "util.h" 62 63 #define UDP_SIZE 65536 64 65 /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do. */ 66 #ifndef SO_REUSEPORT 67 #define SO_REUSEPORT SO_REUSEADDR 68 #endif 69 70 struct udp_transport { 71 struct transport transport; 72 struct sockaddr *src; 73 struct sockaddr *dst; 74 int s; 75 LIST_ENTRY (udp_transport) link; 76 }; 77 78 static struct transport *udp_clone (struct udp_transport *, struct sockaddr *); 79 static struct transport *udp_create (char *); 80 static void udp_reinit (void); 81 static void udp_remove (struct transport *); 82 static void udp_report (struct transport *); 83 static int udp_fd_set (struct transport *, fd_set *, int); 84 static int udp_fd_isset (struct transport *, fd_set *); 85 static void udp_handle_message (struct transport *); 86 static struct transport *udp_make (struct sockaddr *); 87 static int udp_send_message (struct message *); 88 static void udp_get_dst (struct transport *, struct sockaddr **); 89 static void udp_get_src (struct transport *, struct sockaddr **); 90 static char *udp_decode_ids (struct transport *); 91 #if 0 92 static in_port_t udp_decode_port (char *); 93 #endif 94 95 static struct transport_vtbl udp_transport_vtbl = { 96 { 0 }, "udp", 97 udp_create, 98 udp_reinit, 99 udp_remove, 100 udp_report, 101 udp_fd_set, 102 udp_fd_isset, 103 udp_handle_message, 104 udp_send_message, 105 udp_get_dst, 106 udp_get_src, 107 udp_decode_ids 108 }; 109 110 /* A list of UDP transports we listen for messages on. */ 111 static LIST_HEAD (udp_listen_list, udp_transport) udp_listen_list; 112 113 char *udp_default_port = 0; 114 char *udp_bind_port = 0; 115 int bind_family = 0; 116 static struct transport *default_transport, *default_transport6; 117 118 /* Find an UDP transport listening on ADDR:PORT. */ 119 static struct udp_transport * 120 udp_listen_lookup (struct sockaddr *addr) 121 { 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; 129 } 130 131 /* Create a UDP transport structure bound to LADDR just for listening. */ 132 static struct transport * 133 udp_make (struct sockaddr *laddr) 134 { 135 struct udp_transport *t = 0; 136 int s, on, wildcardaddress = 0; 137 138 t = calloc (1, sizeof *t); 139 if (!t) 140 { 141 log_print ("udp_make: malloc (%lu) failed", (unsigned long)sizeof *t); 142 return 0; 143 } 144 145 s = socket (laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 146 if (s == -1) 147 { 148 log_error ("udp_make: socket (%d, %d, %d)", laddr->sa_family, SOCK_DGRAM, 149 IPPROTO_UDP); 150 goto err; 151 } 152 153 /* Make sure we don't get our traffic encrypted. */ 154 if (sysdep_cleartext (s, laddr->sa_family) == -1) 155 goto err; 156 157 /* Wildcard address ? */ 158 switch (laddr->sa_family) 159 { 160 case AF_INET: 161 if (((struct sockaddr_in *)laddr)->sin_addr.s_addr == INADDR_ANY) 162 wildcardaddress = 1; 163 break; 164 case AF_INET6: 165 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr)) 166 wildcardaddress = 1; 167 break; 168 } 169 170 /* 171 * In order to have several bound specific address-port combinations 172 * with the same port SO_REUSEADDR is needed. 173 * If this is a wildcard socket and we are not listening there, but only 174 * sending from it make sure it is entirely reuseable with SO_REUSEPORT. 175 */ 176 on = 1; 177 if (setsockopt (s, SOL_SOCKET, 178 wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, 179 (void *)&on, sizeof on) == -1) 180 { 181 log_error ("udp_make: setsockopt (%d, %d, %d, %p, %lu)", s, SOL_SOCKET, 182 wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, 183 &on, (unsigned long)sizeof on); 184 goto err; 185 } 186 187 t->transport.vtbl = &udp_transport_vtbl; 188 t->src = laddr; 189 if (monitor_bind (s, t->src, sysdep_sa_len (t->src))) 190 { 191 char *tstr; 192 if (sockaddr2text (t->src, &tstr, 0)) 193 log_error ("udp_make: bind (%d, %p, %lu)", s, &t->src, 194 (unsigned long)sizeof t->src); 195 else 196 { 197 log_error ("udp_make: bind (%d, %s, %lu)", s, tstr, 198 (unsigned long)sizeof t->src); 199 free (tstr); 200 } 201 goto err; 202 } 203 204 t->s = s; 205 transport_add (&t->transport); 206 transport_reference (&t->transport); 207 t->transport.flags |= TRANSPORT_LISTEN; 208 return &t->transport; 209 210 err: 211 if (s >= 0) 212 close (s); 213 if (t) 214 { 215 /* Already closed. */ 216 t->s = -1; 217 udp_remove (&t->transport); 218 } 219 return 0; 220 } 221 222 /* Clone a listen transport U, record a destination RADDR for outbound use. */ 223 static struct transport * 224 udp_clone (struct udp_transport *u, struct sockaddr *raddr) 225 { 226 struct transport *t; 227 struct udp_transport *u2; 228 229 t = malloc (sizeof *u); 230 if (!t) 231 { 232 log_error ("udp_clone: malloc (%lu) failed", (unsigned long)sizeof *u); 233 return 0; 234 } 235 u2 = (struct udp_transport *)t; 236 237 memcpy (u2, u, sizeof *u); 238 239 u2->src = malloc (sysdep_sa_len (u->src)); 240 if (!u2->src) 241 { 242 log_error ("udp_clone: malloc (%d) failed", sysdep_sa_len (u->src)); 243 free (t); 244 return 0; 245 } 246 memcpy (u2->src, u->src, sysdep_sa_len (u->src)); 247 248 u2->dst = malloc (sysdep_sa_len (raddr)); 249 if (!u2->dst) 250 { 251 log_error ("udp_clone: malloc (%d) failed", sysdep_sa_len (raddr)); 252 free (u2->src); 253 free (t); 254 return 0; 255 } 256 memcpy (u2->dst, raddr, sysdep_sa_len (raddr)); 257 258 t->flags &= ~TRANSPORT_LISTEN; 259 260 transport_add (t); 261 262 return t; 263 } 264 265 /* 266 * Initialize an object of the UDP transport class. Fill in the local 267 * IP address and port information and create a server socket bound to 268 * that specific port. Add the polymorphic transport structure to the 269 * system-wide pools of known ISAKMP transports. 270 */ 271 static struct transport * 272 udp_bind (const struct sockaddr *addr) 273 { 274 struct sockaddr *src = malloc (sysdep_sa_len ((struct sockaddr *)addr)); 275 276 if (!src) 277 return 0; 278 279 memcpy (src, addr, sysdep_sa_len ((struct sockaddr *)addr)); 280 return udp_make (src); 281 } 282 283 /* 284 * When looking at a specific network interface address, if it's an INET one, 285 * create an UDP server socket bound to it. 286 * Return 0 if successful, -1 otherwise. 287 */ 288 static int 289 udp_bind_if (char *ifname, struct sockaddr *if_addr, void *arg) 290 { 291 char *port = (char *)arg; 292 struct sockaddr_storage saddr_st; 293 struct sockaddr *saddr = (struct sockaddr *)&saddr_st; 294 struct conf_list *listen_on; 295 struct udp_transport *u; 296 struct conf_list_node *address; 297 struct sockaddr *addr; 298 struct transport *t; 299 struct ifreq flags_ifr; 300 char *addr_str, *ep; 301 int s, error; 302 long lport; 303 304 /* 305 * Well, UDP is an internet protocol after all so drop other ifreqs. 306 */ 307 if ((if_addr->sa_family != AF_INET 308 || sysdep_sa_len (if_addr) != sizeof (struct sockaddr_in)) 309 && (if_addr->sa_family != AF_INET6 310 || sysdep_sa_len (if_addr) != sizeof (struct sockaddr_in6))) 311 return 0; 312 313 /* 314 * Only create sockets for families we should listen to. 315 */ 316 if (bind_family) 317 switch (if_addr->sa_family) 318 { 319 case AF_INET: 320 if ((bind_family & BIND_FAMILY_INET4) == 0) 321 return 0; 322 break; 323 case AF_INET6: 324 if ((bind_family & BIND_FAMILY_INET6) == 0) 325 return 0; 326 break; 327 default: 328 return 0; 329 } 330 331 /* 332 * These special addresses are not useable as they have special meaning 333 * in the IP stack. 334 */ 335 if (if_addr->sa_family == AF_INET 336 && (((struct sockaddr_in *)if_addr)->sin_addr.s_addr == INADDR_ANY 337 || (((struct sockaddr_in *)if_addr)->sin_addr.s_addr 338 == INADDR_NONE)) ) 339 return 0; 340 341 /* 342 * Go through the list of transports and see if we already have this 343 * address bound. If so, unmark the transport and skip it; this allows 344 * us to call this function when we suspect a new address has appeared. 345 */ 346 memcpy (saddr, if_addr, sizeof saddr_st); 347 switch (saddr->sa_family) /* Add the port number to the sockaddr. */ 348 { 349 case AF_INET: 350 ((struct sockaddr_in *)saddr)->sin_port 351 = htons (strtol (port, &ep, 10)); 352 break; 353 case AF_INET6: 354 ((struct sockaddr_in6 *)saddr)->sin6_port 355 = htons (strtol (port, &ep, 10)); 356 break; 357 } 358 359 if ((u = udp_listen_lookup (saddr)) != 0) 360 { 361 u->transport.flags &= ~TRANSPORT_MARK; 362 return 0; 363 } 364 365 /* Don't bother with interfaces that are down. */ 366 s = socket (if_addr->sa_family, SOCK_DGRAM, 0); 367 if (s == -1) 368 { 369 log_error ("udp_bind_if: socket (%d, SOCK_DGRAM, 0) failed", 370 if_addr->sa_family); 371 return -1; 372 } 373 strlcpy (flags_ifr.ifr_name, ifname, sizeof flags_ifr.ifr_name); 374 if (ioctl (s, SIOCGIFFLAGS, (caddr_t)&flags_ifr) == -1) 375 { 376 log_error ("udp_bind_if: ioctl (%d, SIOCGIFFLAGS, ...) failed", s); 377 return -1; 378 } 379 close (s); 380 if (!(flags_ifr.ifr_flags & IFF_UP)) 381 return 0; 382 383 /* 384 * Set port. 385 * XXX Use getservbyname too. 386 */ 387 lport = strtol (port, &ep, 10); 388 if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) 389 { 390 log_print ("udp_bind_if: " 391 "port string \"%s\" not convertible to in_port_t", port); 392 return -1; 393 } 394 395 switch (if_addr->sa_family) 396 { 397 case AF_INET: 398 ((struct sockaddr_in *)if_addr)->sin_port = htons (lport); 399 break; 400 case AF_INET6: 401 ((struct sockaddr_in6 *)if_addr)->sin6_port = htons (lport); 402 break; 403 default: 404 log_print ("udp_bind_if: unsupported protocol family %d", 405 if_addr->sa_family); 406 break; 407 } 408 409 /* 410 * If we are explicit about what addresses we can listen to, be sure 411 * to respect that option. 412 * This is quite wasteful redoing the list-run for every interface, 413 * but who cares? This is not an operation that needs to be fast. 414 */ 415 listen_on = conf_get_list ("General", "Listen-on"); 416 if (listen_on) 417 { 418 for (address = TAILQ_FIRST (&listen_on->fields); address; 419 address = TAILQ_NEXT (address, link)) 420 { 421 if (text2sockaddr (address->field, port, &addr)) 422 { 423 log_print ("udp_bind_if: invalid address %s in \"Listen-on\"", 424 address->field); 425 continue; 426 } 427 428 /* If found, take the easy way out. */ 429 if (memcmp (addr, if_addr, sysdep_sa_len (addr)) == 0) 430 { 431 free (addr); 432 break; 433 } 434 free (addr); 435 } 436 conf_free_list (listen_on); 437 438 /* 439 * If address is zero then we did not find the address among the ones 440 * we should listen to. 441 * XXX We do not discover if we do not find our listen addresses... 442 * Maybe this should be the other way round. 443 */ 444 if (!address) 445 return 0; 446 } 447 448 t = udp_bind (if_addr); 449 if (!t) 450 { 451 error = sockaddr2text (if_addr, &addr_str, 0); 452 log_print ("udp_bind_if: failed to create a socket on %s:%s", 453 error ? "unknown" : addr_str, port); 454 if (!error) 455 free (addr_str); 456 return -1; 457 } 458 LIST_INSERT_HEAD (&udp_listen_list, (struct udp_transport *)t, link); 459 return 0; 460 } 461 462 /* 463 * NAME is a section name found in the config database. Setup and return 464 * a transport useable to talk to the peer specified by that name. 465 */ 466 static struct transport * 467 udp_create (char *name) 468 { 469 struct udp_transport *u; 470 struct transport *rv; 471 struct sockaddr *dst, *addr; 472 char *addr_str, *port_str; 473 474 port_str = conf_get_str (name, "Port"); 475 if (!port_str) 476 port_str = udp_default_port; 477 if (!port_str) 478 port_str = "500"; 479 480 addr_str = conf_get_str (name, "Address"); 481 if (!addr_str) 482 { 483 log_print ("udp_create: no address configured for \"%s\"", name); 484 return 0; 485 } 486 if (text2sockaddr (addr_str, port_str, &dst)) 487 { 488 log_print ("udp_create: address \"%s\" not understood", addr_str); 489 return 0; 490 } 491 492 addr_str = conf_get_str (name, "Local-address"); 493 if (!addr_str) 494 addr_str = conf_get_str ("General", "Listen-on"); 495 if (!addr_str) 496 { 497 if ((dst->sa_family == AF_INET && !default_transport) 498 || (dst->sa_family == AF_INET6 && !default_transport6)) 499 { 500 log_print ("udp_create: no default transport"); 501 rv = 0; 502 goto ret; 503 } 504 else 505 { 506 /* XXX Ugly! */ 507 rv = udp_clone ((struct udp_transport *)(dst->sa_family == AF_INET 508 ? default_transport 509 : default_transport6), dst); 510 goto ret; 511 } 512 } 513 514 if (text2sockaddr (addr_str, port_str, &addr)) 515 { 516 log_print ("udp_create: address \"%s\" not understood", addr_str); 517 rv = 0; 518 goto ret; 519 } 520 u = udp_listen_lookup (addr); 521 free (addr); 522 if (!u) 523 { 524 log_print ("udp_create: %s:%s must exist as a listener too", addr_str, 525 port_str); 526 rv = 0; 527 goto ret; 528 } 529 rv = udp_clone (u, dst); 530 531 ret: 532 free (dst); 533 return rv; 534 } 535 536 void 537 udp_remove (struct transport *t) 538 { 539 struct udp_transport *u = (struct udp_transport *)t; 540 541 if (u->src) 542 free (u->src); 543 if (u->dst) 544 free (u->dst); 545 if (t->flags & TRANSPORT_LISTEN) 546 { 547 if (u->s >= 0) 548 close (u->s); 549 if (t == default_transport) 550 default_transport = 0; 551 else if (t == default_transport6) 552 default_transport6 = 0; 553 if (u->link.le_prev) 554 LIST_REMOVE (u, link); 555 } 556 free (t); 557 } 558 559 /* Report transport-method specifics of the T transport. */ 560 void 561 udp_report (struct transport *t) 562 { 563 struct udp_transport *u = (struct udp_transport *)t; 564 char *src, *dst; 565 566 if (sockaddr2text (u->src, &src, 0)) 567 goto ret; 568 569 if (!u->dst || sockaddr2text (u->dst, &dst, 0)) 570 dst = 0; 571 572 LOG_DBG ((LOG_REPORT, 0, "udp_report: fd %d src %s dst %s", u->s, src, 573 dst ? dst : "<none>")); 574 575 ret: 576 if (dst) 577 free (dst); 578 if (src) 579 free (src); 580 } 581 582 /* 583 * Probe the interface list and determine what new interfaces have 584 * appeared. 585 * 586 * At the same time, we try to determine whether existing interfaces have 587 * been rendered invalid; we do this by marking all UDP transports before 588 * we call udp_bind_if () through if_map (), and then releasing those 589 * transports that have not been unmarked. 590 */ 591 static void 592 udp_reinit (void) 593 { 594 struct udp_transport *u, *u2; 595 char *port; 596 597 /* Initialize the protocol and port numbers. */ 598 port = udp_default_port ? udp_default_port : "500"; 599 600 /* Mark all UDP transports, except the default ones. */ 601 for (u = LIST_FIRST (&udp_listen_list); u; u = LIST_NEXT (u, link)) 602 if (&u->transport != default_transport 603 && &u->transport != default_transport6) 604 u->transport.flags |= TRANSPORT_MARK; 605 606 /* Re-probe interface list. */ 607 if (if_map (udp_bind_if, port) == -1) 608 log_print ("udp_init: Could not bind the ISAKMP UDP port %s on all " 609 "interfaces", port); 610 611 /* 612 * Release listening transports for local addresses that no 613 * longer exist. udp_bind_if () will have left those still marked. 614 */ 615 u = LIST_FIRST (&udp_listen_list); 616 while (u) 617 { 618 u2 = LIST_NEXT (u, link); 619 620 if (u->transport.flags & TRANSPORT_MARK) 621 { 622 LIST_REMOVE (u, link); 623 transport_release (&u->transport); 624 } 625 626 u = u2; 627 } 628 } 629 630 /* 631 * Find out the magic numbers for the UDP protocol as well as the UDP port 632 * to use. Setup an UDP server for each address of this machine, and one 633 * for the generic case when we are the initiator. 634 */ 635 void 636 udp_init (void) 637 { 638 struct sockaddr_storage dflt_stor; 639 struct sockaddr_in *dflt = (struct sockaddr_in *)&dflt_stor; 640 char *port; 641 long lport; 642 char *ep; 643 644 /* Initialize the protocol and port numbers. */ 645 port = udp_default_port ? udp_default_port : "500"; 646 647 LIST_INIT (&udp_listen_list); 648 649 transport_method_add (&udp_transport_vtbl); 650 651 /* Bind the ISAKMP UDP port on all network interfaces we have. */ 652 if (if_map (udp_bind_if, port) == -1) 653 log_fatal ("udp_init: Could not bind the ISAKMP UDP port %s on all " 654 "interfaces", port); 655 656 /* 657 * Get port. 658 * XXX Use getservbyname too. 659 */ 660 lport = strtol (port, &ep, 10); 661 if (*ep != '\0' || lport < 0 || lport > USHRT_MAX) 662 { 663 log_print ("udp_init: port string \"%s\" not convertible to in_port_t", 664 port); 665 return; 666 } 667 668 /* 669 * Bind to INADDR_ANY in case of new addresses popping up. 670 * Packet reception on this transport is taken as a hint to reprobe the 671 * interface list. 672 */ 673 if (!bind_family || (bind_family & BIND_FAMILY_INET4)) 674 { 675 memset (&dflt_stor, 0, sizeof dflt_stor); 676 dflt->sin_family = AF_INET; 677 #if !defined (LINUX_IPSEC) 678 ((struct sockaddr_in *)dflt)->sin_len = sizeof (struct sockaddr_in); 679 #endif 680 ((struct sockaddr_in *)dflt)->sin_port = htons (lport); 681 682 default_transport = udp_bind ((struct sockaddr *)&dflt_stor); 683 if (!default_transport) 684 { 685 log_error ("udp_init: could not allocate default " 686 "IPv4 ISAKMP UDP port"); 687 return; 688 } 689 LIST_INSERT_HEAD (&udp_listen_list, 690 (struct udp_transport *)default_transport, link); 691 } 692 693 if (!bind_family || (bind_family & BIND_FAMILY_INET6)) 694 { 695 memset (&dflt_stor, 0, sizeof dflt_stor); 696 dflt->sin_family = AF_INET6; 697 #if !defined (LINUX_IPSEC) 698 ((struct sockaddr_in6 *)dflt)->sin6_len = sizeof (struct sockaddr_in6); 699 #endif 700 ((struct sockaddr_in6 *)dflt)->sin6_port = htons (lport); 701 702 default_transport6 = udp_bind ((struct sockaddr *)&dflt_stor); 703 if (!default_transport6) 704 { 705 log_error ("udp_init: could not allocate default " 706 "IPv6 ISAKMP UDP port"); 707 return; 708 } 709 LIST_INSERT_HEAD (&udp_listen_list, 710 (struct udp_transport *)default_transport6, link); 711 } 712 } 713 714 /* 715 * Set transport T's socket in FDS, return a value useable by select(2) 716 * as the number of file descriptors to check. 717 */ 718 static int 719 udp_fd_set (struct transport *t, fd_set *fds, int bit) 720 { 721 struct udp_transport *u = (struct udp_transport *)t; 722 723 if (bit) 724 FD_SET (u->s, fds); 725 else 726 FD_CLR (u->s, fds); 727 728 return u->s + 1; 729 } 730 731 /* Check if transport T's socket is set in FDS. */ 732 static int 733 udp_fd_isset (struct transport *t, fd_set *fds) 734 { 735 struct udp_transport *u = (struct udp_transport *)t; 736 737 return FD_ISSET (u->s, fds); 738 } 739 740 /* 741 * A message has arrived on transport T's socket. If T is single-ended, 742 * clone it into a double-ended transport which we will use from now on. 743 * Package the message as we want it and continue processing in the message 744 * module. 745 */ 746 static void 747 udp_handle_message (struct transport *t) 748 { 749 struct udp_transport *u = (struct udp_transport *)t; 750 u_int8_t buf[UDP_SIZE]; 751 struct sockaddr_storage from; 752 u_int32_t len = sizeof from; 753 ssize_t n; 754 struct message *msg; 755 756 n = recvfrom (u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len); 757 if (n == -1) 758 { 759 log_error ("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf, UDP_SIZE, 0, 760 &from, &len); 761 return; 762 } 763 764 /* 765 * If we received the packet over the default transports, reprobe the 766 * interfaces. 767 */ 768 if (t == default_transport || t == default_transport6) 769 { 770 udp_reinit (); 771 772 /* 773 * As we don't know the actual destination address of the packet, 774 * we can't really deal with it. So, just ignore it and hope we 775 * catch the retransmission. 776 */ 777 return; 778 } 779 780 /* 781 * Make a specialized UDP transport structure out of the incoming 782 * transport and the address information we got from recvfrom(2). 783 */ 784 t = udp_clone (u, (struct sockaddr *)&from); 785 if (!t) 786 return; 787 788 msg = message_alloc (t, buf, n); 789 if (!msg) 790 { 791 log_error ("failed to allocate message structure, dropping packet " 792 "received on transport %p", u); 793 return; 794 } 795 message_recv (msg); 796 } 797 798 /* Physically send the message MSG over its associated transport. */ 799 static int 800 udp_send_message (struct message *msg) 801 { 802 struct udp_transport *u = (struct udp_transport *)msg->transport; 803 ssize_t n; 804 struct msghdr m; 805 806 /* 807 * Sending on connected sockets requires that no destination address is 808 * given, or else EISCONN will occur. 809 */ 810 m.msg_name = (caddr_t)u->dst; 811 m.msg_namelen = sysdep_sa_len (u->dst); 812 m.msg_iov = msg->iov; 813 m.msg_iovlen = msg->iovlen; 814 m.msg_control = 0; 815 m.msg_controllen = 0; 816 m.msg_flags = 0; 817 n = sendmsg (u->s, &m, 0); 818 if (n == -1) 819 { 820 /* XXX We should check whether the address has gone away */ 821 log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0); 822 return -1; 823 } 824 return 0; 825 } 826 827 /* 828 * Get transport T's peer address and stuff it into the sockaddr pointed 829 * to by DST. 830 */ 831 static void 832 udp_get_dst (struct transport *t, struct sockaddr **dst) 833 { 834 *dst = ((struct udp_transport *)t)->dst; 835 } 836 837 /* 838 * Get transport T's local address and stuff it into the sockaddr pointed 839 * to by SRC. Put its length into SRC_LEN. 840 */ 841 static void 842 udp_get_src (struct transport *t, struct sockaddr **src) 843 { 844 *src = ((struct udp_transport *)t)->src; 845 } 846 847 static char * 848 udp_decode_ids (struct transport *t) 849 { 850 static char result[1024]; 851 char idsrc[256], iddst[256]; 852 853 #ifdef HAVE_GETNAMEINFO 854 if (getnameinfo (((struct udp_transport *)t)->src, 855 sysdep_sa_len (((struct udp_transport *)t)->src), 856 idsrc, sizeof idsrc, NULL, 0, NI_NUMERICHOST) != 0) 857 { 858 log_print ("udp_decode_ids: getnameinfo () failed for 'src'"); 859 strlcpy (idsrc, "<error>", 256); 860 } 861 862 if (getnameinfo (((struct udp_transport *)t)->dst, 863 sysdep_sa_len (((struct udp_transport *)t)->dst), 864 iddst, sizeof iddst, NULL, 0, NI_NUMERICHOST) != 0) 865 { 866 log_print ("udp_decode_ids: getnameinfo () failed for 'dst'"); 867 strlcpy (iddst, "<error>", 256); 868 } 869 #else 870 strlcpy (idsrc, inet_ntoa (((struct udp_transport *)t)->src.sin_addr), 256); 871 strlcpy (iddst, inet_ntoa (((struct udp_transport *)t)->dst.sin_addr), 256); 872 #endif /* HAVE_GETNAMEINFO */ 873 874 snprintf (result, sizeof result, "src: %s dst: %s", idsrc, iddst); 875 876 return result; 877 } 878 879 #if 0 880 /* 881 * Take a string containing an ext representation of port and return a 882 * binary port number in host byte order. Return zero if anything goes wrong. 883 * XXX Currently unused. 884 */ 885 static in_port_t 886 udp_decode_port (char *port_str) 887 { 888 char *port_str_end; 889 long port_long; 890 struct servent *service; 891 892 port_long = ntohl (strtol (port_str, &port_str_end, 0)); 893 if (port_str == port_str_end) 894 { 895 service = getservbyname (port_str, "udp"); 896 if (!service) 897 { 898 log_print ("udp_decode_port: service \"%s\" unknown", port_str); 899 return 0; 900 } 901 return ntohs (service->s_port); 902 } 903 else if (port_long < 1 || port_long > 65535) 904 { 905 log_print ("udp_decode_port: port %ld out of range", port_long); 906 return 0; 907 } 908 909 return port_long; 910 } 911 #endif 912