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