1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/apputils/net-server.c - Network code for krb5 servers (kdc, kadmind) */ 3 /* 4 * Copyright 1990,2000,2007,2008,2009,2010,2016 by the Massachusetts Institute 5 * of Technology. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include "k5-int.h" 28 #include "adm_proto.h" 29 #include <sys/ioctl.h> 30 #include <syslog.h> 31 32 #include <stddef.h> 33 #include "port-sockets.h" 34 #include "socket-utils.h" 35 36 #include <gssrpc/rpc.h> 37 38 #ifdef HAVE_NETINET_IN_H 39 #include <sys/types.h> 40 #include <netinet/in.h> 41 #include <sys/socket.h> 42 #ifdef HAVE_SYS_SOCKIO_H 43 /* for SIOCGIFCONF, etc. */ 44 #include <sys/sockio.h> 45 #endif 46 #include <sys/time.h> 47 #if HAVE_SYS_SELECT_H 48 #include <sys/select.h> 49 #endif 50 #include <arpa/inet.h> 51 52 #ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */ 53 #include <net/if.h> 54 #endif 55 56 #ifdef HAVE_SYS_FILIO_H 57 #include <sys/filio.h> /* FIONBIO */ 58 #endif 59 60 #include "fake-addrinfo.h" 61 #include "net-server.h" 62 #include <signal.h> 63 #include <netdb.h> 64 65 #include "udppktinfo.h" 66 67 /* XXX */ 68 #define KDC5_NONET (-1779992062L) 69 70 static int tcp_or_rpc_data_counter; 71 static int max_tcp_or_rpc_data_connections = 45; 72 73 static int 74 setreuseaddr(int sock, int value) 75 { 76 int st; 77 78 st = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); 79 if (st) 80 return st; 81 #ifdef SO_REUSEPORT 82 st = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)); 83 if (st) 84 return st; 85 #endif 86 return 0; 87 } 88 89 #if defined(IPV6_V6ONLY) 90 static int 91 setv6only(int sock, int value) 92 { 93 return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)); 94 } 95 #endif 96 97 static const char * 98 paddr(struct sockaddr *sa) 99 { 100 static char buf[100]; 101 char portbuf[10]; 102 if (getnameinfo(sa, sa_socklen(sa), 103 buf, sizeof(buf), portbuf, sizeof(portbuf), 104 NI_NUMERICHOST|NI_NUMERICSERV)) 105 strlcpy(buf, "<unprintable>", sizeof(buf)); 106 else { 107 unsigned int len = sizeof(buf) - strlen(buf); 108 char *p = buf + strlen(buf); 109 if (len > 2+strlen(portbuf)) { 110 *p++ = '.'; 111 len--; 112 strncpy(p, portbuf, len); 113 } 114 } 115 return buf; 116 } 117 118 /* KDC data. */ 119 120 enum conn_type { 121 CONN_UDP, CONN_TCP_LISTENER, CONN_TCP, CONN_RPC_LISTENER, CONN_RPC 122 }; 123 124 enum bind_type { 125 UDP, TCP, RPC 126 }; 127 128 static const char *const bind_type_names[] = { 129 [UDP] = "UDP", 130 [TCP] = "TCP", 131 [RPC] = "RPC", 132 }; 133 134 /* Per-connection info. */ 135 struct connection { 136 void *handle; 137 const char *prog; 138 enum conn_type type; 139 140 /* Connection fields (TCP or RPC) */ 141 struct sockaddr_storage addr_s; 142 socklen_t addrlen; 143 char addrbuf[56]; 144 krb5_address remote_addr_buf; 145 krb5_fulladdr remote_addr; 146 147 /* Incoming data (TCP) */ 148 size_t bufsiz; 149 size_t offset; 150 char *buffer; 151 size_t msglen; 152 153 /* Outgoing data (TCP) */ 154 krb5_data *response; 155 unsigned char lenbuf[4]; 156 sg_buf sgbuf[2]; 157 sg_buf *sgp; 158 int sgnum; 159 160 /* Crude denial-of-service avoidance support (TCP or RPC) */ 161 time_t start_time; 162 163 /* RPC-specific fields */ 164 SVCXPRT *transp; 165 int rpc_force_close; 166 }; 167 168 #define SET(TYPE) struct { TYPE *data; size_t n, max; } 169 170 /* Start at the top and work down -- this should allow for deletions 171 without disrupting the iteration, since we delete by overwriting 172 the element to be removed with the last element. */ 173 #define FOREACH_ELT(set,idx,vvar) \ 174 for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--) 175 176 #define GROW_SET(set, incr, tmpptr) \ 177 ((set.max + incr < set.max \ 178 || ((set.max + incr) * sizeof(set.data[0]) / sizeof(set.data[0]) \ 179 != set.max + incr)) \ 180 ? 0 /* overflow */ \ 181 : ((tmpptr = realloc(set.data, \ 182 (set.max + incr) * sizeof(set.data[0]))) \ 183 ? (set.data = tmpptr, set.max += incr, 1) \ 184 : 0)) 185 186 /* 1 = success, 0 = failure */ 187 #define ADD(set, val, tmpptr) \ 188 ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \ 189 ? (set.data[set.n++] = val, 1) \ 190 : 0) 191 192 #define DEL(set, idx) \ 193 (set.data[idx] = set.data[--set.n], 0) 194 195 #define FREE_SET_DATA(set) \ 196 (free(set.data), set.data = 0, set.max = 0, set.n = 0) 197 198 /* 199 * N.B.: The Emacs cc-mode indentation code seems to get confused if 200 * the macro argument here is one word only. So use "unsigned short" 201 * instead of the "u_short" we were using before. 202 */ 203 struct rpc_svc_data { 204 u_long prognum; 205 u_long versnum; 206 void (*dispatch)(); 207 }; 208 209 struct bind_address { 210 char *address; 211 u_short port; 212 enum bind_type type; 213 struct rpc_svc_data rpc_svc_data; 214 }; 215 216 static SET(verto_ev *) events; 217 static SET(struct bind_address) bind_addresses; 218 219 verto_ctx * 220 loop_init(verto_ev_type types) 221 { 222 types |= VERTO_EV_TYPE_IO; 223 types |= VERTO_EV_TYPE_SIGNAL; 224 types |= VERTO_EV_TYPE_TIMEOUT; 225 return verto_default(NULL, types); 226 } 227 228 static void 229 do_break(verto_ctx *ctx, verto_ev *ev) 230 { 231 krb5_klog_syslog(LOG_DEBUG, _("Got signal to request exit")); 232 verto_break(ctx); 233 } 234 235 struct sighup_context { 236 void *handle; 237 void (*reset)(void *); 238 }; 239 240 static void 241 do_reset(verto_ctx *ctx, verto_ev *ev) 242 { 243 struct sighup_context *sc = (struct sighup_context*) verto_get_private(ev); 244 245 krb5_klog_syslog(LOG_DEBUG, _("Got signal to reset")); 246 krb5_klog_reopen(get_context(sc->handle)); 247 if (sc->reset) 248 sc->reset(sc->handle); 249 } 250 251 static void 252 free_sighup_context(verto_ctx *ctx, verto_ev *ev) 253 { 254 free(verto_get_private(ev)); 255 } 256 257 krb5_error_code 258 loop_setup_signals(verto_ctx *ctx, void *handle, void (*reset)()) 259 { 260 struct sighup_context *sc; 261 verto_ev *ev; 262 263 if (!verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGINT) || 264 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGTERM) || 265 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGQUIT) || 266 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGPIPE)) 267 return ENOMEM; 268 269 ev = verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_reset, SIGHUP); 270 if (!ev) 271 return ENOMEM; 272 273 sc = malloc(sizeof(*sc)); 274 if (!sc) 275 return ENOMEM; 276 277 sc->handle = handle; 278 sc->reset = reset; 279 verto_set_private(ev, sc, free_sighup_context); 280 return 0; 281 } 282 283 /* 284 * Add a bind address to the loop. 285 * 286 * Arguments: 287 * - address 288 * A string for the address (or hostname). Pass NULL to use the wildcard 289 * address. The address is parsed with k5_parse_host_string(). 290 * - port 291 * What port the socket should be set to. 292 * - type 293 * bind_type for the socket. 294 * - rpc_data 295 * For RPC addresses, the svc_register() arguments to use when TCP 296 * connections are created. Ignored for other types. 297 */ 298 static krb5_error_code 299 loop_add_address(const char *address, int port, enum bind_type type, 300 struct rpc_svc_data *rpc_data) 301 { 302 struct bind_address addr, val; 303 int i; 304 void *tmp; 305 char *addr_copy = NULL; 306 307 assert(!(type == RPC && rpc_data == NULL)); 308 309 /* Make sure a valid port number was passed. */ 310 if (port < 0 || port > 65535) { 311 krb5_klog_syslog(LOG_ERR, _("Invalid port %d"), port); 312 return EINVAL; 313 } 314 315 /* Check for conflicting addresses. */ 316 FOREACH_ELT(bind_addresses, i, val) { 317 if (type != val.type || port != val.port) 318 continue; 319 320 /* If a wildcard address is being added, make sure to remove any direct 321 * addresses. */ 322 if (address == NULL && val.address != NULL) { 323 krb5_klog_syslog(LOG_DEBUG, 324 _("Removing address %s since wildcard address" 325 " is being added"), 326 val.address); 327 free(val.address); 328 DEL(bind_addresses, i); 329 } else if (val.address == NULL || !strcmp(address, val.address)) { 330 krb5_klog_syslog(LOG_DEBUG, 331 _("Address already added to server")); 332 return 0; 333 } 334 } 335 336 /* Copy the address if it is specified. */ 337 if (address != NULL) { 338 addr_copy = strdup(address); 339 if (addr_copy == NULL) 340 return ENOMEM; 341 } 342 343 /* Add the new address to bind_addresses. */ 344 memset(&addr, 0, sizeof(addr)); 345 addr.address = addr_copy; 346 addr.port = port; 347 addr.type = type; 348 if (rpc_data != NULL) 349 addr.rpc_svc_data = *rpc_data; 350 if (!ADD(bind_addresses, addr, tmp)) { 351 free(addr_copy); 352 return ENOMEM; 353 } 354 355 return 0; 356 } 357 358 /* 359 * Add bind addresses to the loop. 360 * 361 * Arguments: 362 * 363 * - addresses 364 * A string for the addresses. Pass NULL to use the wildcard address. 365 * Supported delimiters can be found in ADDRESSES_DELIM. Addresses are 366 * parsed with k5_parse_host_name(). 367 * - default_port 368 * What port the socket should be set to if not specified in addresses. 369 * - type 370 * bind_type for the socket. 371 * - rpc_data 372 * For RPC addresses, the svc_register() arguments to use when TCP 373 * connections are created. Ignored for other types. 374 */ 375 static krb5_error_code 376 loop_add_addresses(const char *addresses, int default_port, 377 enum bind_type type, struct rpc_svc_data *rpc_data) 378 { 379 krb5_error_code ret = 0; 380 char *addresses_copy = NULL, *host = NULL, *saveptr, *addr; 381 int port; 382 383 /* If no addresses are set, add a wildcard address. */ 384 if (addresses == NULL) 385 return loop_add_address(NULL, default_port, type, rpc_data); 386 387 /* Copy the addresses string before using strtok(). */ 388 addresses_copy = strdup(addresses); 389 if (addresses_copy == NULL) { 390 ret = ENOMEM; 391 goto cleanup; 392 } 393 394 /* Start tokenizing the addresses string. If we get NULL the string 395 * contained no addresses, so add a wildcard address. */ 396 addr = strtok_r(addresses_copy, ADDRESSES_DELIM, &saveptr); 397 if (addr == NULL) { 398 ret = loop_add_address(NULL, default_port, type, rpc_data); 399 goto cleanup; 400 } 401 402 /* Loop through each address and add it to the loop. */ 403 for (; addr != NULL; addr = strtok_r(NULL, ADDRESSES_DELIM, &saveptr)) { 404 /* Parse the host string. */ 405 ret = k5_parse_host_string(addr, default_port, &host, &port); 406 if (ret) 407 goto cleanup; 408 409 ret = loop_add_address(host, port, type, rpc_data); 410 if (ret) 411 goto cleanup; 412 413 free(host); 414 host = NULL; 415 } 416 417 cleanup: 418 free(addresses_copy); 419 free(host); 420 return ret; 421 } 422 423 krb5_error_code 424 loop_add_udp_address(int default_port, const char *addresses) 425 { 426 return loop_add_addresses(addresses, default_port, UDP, NULL); 427 } 428 429 krb5_error_code 430 loop_add_tcp_address(int default_port, const char *addresses) 431 { 432 return loop_add_addresses(addresses, default_port, TCP, NULL); 433 } 434 435 krb5_error_code 436 loop_add_rpc_service(int default_port, const char *addresses, u_long prognum, 437 u_long versnum, void (*dispatchfn)()) 438 { 439 struct rpc_svc_data svc; 440 441 svc.prognum = prognum; 442 svc.versnum = versnum; 443 svc.dispatch = dispatchfn; 444 return loop_add_addresses(addresses, default_port, RPC, &svc); 445 } 446 447 #define USE_AF AF_INET 448 #define USE_TYPE SOCK_DGRAM 449 #define USE_PROTO 0 450 #define SOCKET_ERRNO errno 451 #include "foreachaddr.h" 452 453 static void 454 free_connection(struct connection *conn) 455 { 456 if (!conn) 457 return; 458 if (conn->response) 459 krb5_free_data(get_context(conn->handle), conn->response); 460 if (conn->buffer) 461 free(conn->buffer); 462 if (conn->type == CONN_RPC_LISTENER && conn->transp != NULL) 463 svc_destroy(conn->transp); 464 free(conn); 465 } 466 467 static void 468 remove_event_from_set(verto_ev *ev) 469 { 470 verto_ev *tmp; 471 int i; 472 473 /* Remove the event from the events. */ 474 FOREACH_ELT(events, i, tmp) 475 if (tmp == ev) { 476 DEL(events, i); 477 break; 478 } 479 } 480 481 static void 482 free_socket(verto_ctx *ctx, verto_ev *ev) 483 { 484 struct connection *conn = NULL; 485 fd_set fds; 486 int fd; 487 488 remove_event_from_set(ev); 489 490 fd = verto_get_fd(ev); 491 conn = verto_get_private(ev); 492 493 /* Close the file descriptor. */ 494 krb5_klog_syslog(LOG_INFO, _("closing down fd %d"), fd); 495 if (fd >= 0 && (!conn || conn->type != CONN_RPC || conn->rpc_force_close)) 496 close(fd); 497 498 /* Free the connection struct. */ 499 if (conn) { 500 switch (conn->type) { 501 case CONN_RPC: 502 if (conn->rpc_force_close) { 503 FD_ZERO(&fds); 504 FD_SET(fd, &fds); 505 svc_getreqset(&fds); 506 if (FD_ISSET(fd, &svc_fdset)) { 507 krb5_klog_syslog(LOG_ERR, 508 _("descriptor %d closed but still " 509 "in svc_fdset"), 510 fd); 511 } 512 } 513 /* Fall through. */ 514 case CONN_TCP: 515 tcp_or_rpc_data_counter--; 516 break; 517 default: 518 break; 519 } 520 521 free_connection(conn); 522 } 523 } 524 525 static verto_ev * 526 make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback, 527 int sock, struct connection *conn) 528 { 529 verto_ev *ev; 530 void *tmp; 531 532 ev = verto_add_io(ctx, flags, callback, sock); 533 if (!ev) { 534 com_err(conn->prog, ENOMEM, _("cannot create io event")); 535 return NULL; 536 } 537 538 if (!ADD(events, ev, tmp)) { 539 com_err(conn->prog, ENOMEM, _("cannot save event")); 540 verto_del(ev); 541 return NULL; 542 } 543 544 verto_set_private(ev, conn, free_socket); 545 return ev; 546 } 547 548 static krb5_error_code 549 add_fd(int sock, enum conn_type conntype, verto_ev_flag flags, void *handle, 550 const char *prog, verto_ctx *ctx, verto_callback callback, 551 verto_ev **ev_out) 552 { 553 struct connection *newconn; 554 555 *ev_out = NULL; 556 557 #ifndef _WIN32 558 if (sock >= FD_SETSIZE) { 559 com_err(prog, 0, _("file descriptor number %d too high"), sock); 560 return EMFILE; 561 } 562 #endif 563 newconn = malloc(sizeof(*newconn)); 564 if (newconn == NULL) { 565 com_err(prog, ENOMEM, 566 _("cannot allocate storage for connection info")); 567 return ENOMEM; 568 } 569 memset(newconn, 0, sizeof(*newconn)); 570 newconn->handle = handle; 571 newconn->prog = prog; 572 newconn->type = conntype; 573 574 *ev_out = make_event(ctx, flags, callback, sock, newconn); 575 return 0; 576 } 577 578 static void process_packet(verto_ctx *ctx, verto_ev *ev); 579 static void accept_tcp_connection(verto_ctx *ctx, verto_ev *ev); 580 static void process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev); 581 static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev); 582 static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev); 583 static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev); 584 585 /* 586 * Create a socket and bind it to addr. Ensure the socket will work with 587 * select(). Set the socket cloexec, reuseaddr, and if applicable v6-only. 588 * Does not call listen(). On failure, log an error and return an error code. 589 */ 590 static krb5_error_code 591 create_server_socket(struct sockaddr *addr, int type, const char *prog, 592 int *fd_out) 593 { 594 int sock, e; 595 596 *fd_out = -1; 597 598 sock = socket(addr->sa_family, type, 0); 599 if (sock == -1) { 600 e = errno; 601 com_err(prog, e, _("Cannot create TCP server socket on %s"), 602 paddr(addr)); 603 return e; 604 } 605 set_cloexec_fd(sock); 606 607 #ifndef _WIN32 /* Windows FD_SETSIZE is a count. */ 608 if (sock >= FD_SETSIZE) { 609 close(sock); 610 com_err(prog, 0, _("TCP socket fd number %d (for %s) too high"), 611 sock, paddr(addr)); 612 return EMFILE; 613 } 614 #endif 615 616 if (setreuseaddr(sock, 1) < 0) 617 com_err(prog, errno, _("Cannot enable SO_REUSEADDR on fd %d"), sock); 618 619 if (addr->sa_family == AF_INET6) { 620 #ifdef IPV6_V6ONLY 621 if (setv6only(sock, 1)) { 622 com_err(prog, errno, _("setsockopt(%d,IPV6_V6ONLY,1) failed"), 623 sock); 624 } else { 625 com_err(prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"), sock); 626 } 627 #else 628 krb5_klog_syslog(LOG_INFO, _("no IPV6_V6ONLY socket option support")); 629 #endif /* IPV6_V6ONLY */ 630 } 631 632 if (bind(sock, addr, sa_socklen(addr)) == -1) { 633 e = errno; 634 com_err(prog, e, _("Cannot bind server socket on %s"), paddr(addr)); 635 close(sock); 636 return e; 637 } 638 639 *fd_out = sock; 640 return 0; 641 } 642 643 static const int one = 1; 644 645 static int 646 setnbio(int sock) 647 { 648 return ioctlsocket(sock, FIONBIO, (const void *)&one); 649 } 650 651 static int 652 setkeepalive(int sock) 653 { 654 return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)); 655 } 656 657 static int 658 setnolinger(int s) 659 { 660 static const struct linger ling = { 0, 0 }; 661 return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); 662 } 663 664 /* An enum map to socket families for each bind_type. */ 665 static const int bind_socktypes[] = 666 { 667 [UDP] = SOCK_DGRAM, 668 [TCP] = SOCK_STREAM, 669 [RPC] = SOCK_STREAM 670 }; 671 672 /* An enum map containing conn_type (for struct connection) for each 673 * bind_type. */ 674 static const enum conn_type bind_conn_types[] = 675 { 676 [UDP] = CONN_UDP, 677 [TCP] = CONN_TCP_LISTENER, 678 [RPC] = CONN_RPC_LISTENER 679 }; 680 681 /* 682 * Set up a listening socket. 683 * 684 * Arguments: 685 * 686 * - ba 687 * The bind address and port for the socket. 688 * - ai 689 * The addrinfo struct to use for creating the socket. 690 * - ctype 691 * The conn_type of this socket. 692 */ 693 static krb5_error_code 694 setup_socket(struct bind_address *ba, struct sockaddr *sock_address, 695 void *handle, const char *prog, verto_ctx *ctx, 696 int tcp_listen_backlog, verto_callback vcb, enum conn_type ctype) 697 { 698 krb5_error_code ret; 699 struct connection *conn; 700 verto_ev_flag flags; 701 verto_ev *ev = NULL; 702 int sock = -1; 703 704 krb5_klog_syslog(LOG_DEBUG, _("Setting up %s socket for address %s"), 705 bind_type_names[ba->type], paddr(sock_address)); 706 707 /* Create the socket. */ 708 ret = create_server_socket(sock_address, bind_socktypes[ba->type], prog, 709 &sock); 710 if (ret) 711 goto cleanup; 712 713 /* Listen for backlogged connections on TCP sockets. (For RPC sockets this 714 * will be done by svc_register().) */ 715 if (ba->type == TCP && listen(sock, tcp_listen_backlog) != 0) { 716 ret = errno; 717 com_err(prog, errno, _("Cannot listen on %s server socket on %s"), 718 bind_type_names[ba->type], paddr(sock_address)); 719 goto cleanup; 720 } 721 722 /* Set non-blocking I/O for UDP and TCP listener sockets. */ 723 if (ba->type != RPC && setnbio(sock) != 0) { 724 ret = errno; 725 com_err(prog, errno, 726 _("cannot set listening %s socket on %s non-blocking"), 727 bind_type_names[ba->type], paddr(sock_address)); 728 goto cleanup; 729 } 730 731 /* Turn off the linger option for TCP sockets. */ 732 if (ba->type == TCP && setnolinger(sock) != 0) { 733 ret = errno; 734 com_err(prog, errno, _("cannot set SO_LINGER on %s socket on %s"), 735 bind_type_names[ba->type], paddr(sock_address)); 736 goto cleanup; 737 } 738 739 /* Try to turn on pktinfo for UDP wildcard sockets. */ 740 if (ba->type == UDP && sa_is_wildcard(sock_address)) { 741 krb5_klog_syslog(LOG_DEBUG, _("Setting pktinfo on socket %s"), 742 paddr(sock_address)); 743 ret = set_pktinfo(sock, sock_address->sa_family); 744 if (ret) { 745 com_err(prog, ret, 746 _("Cannot request packet info for UDP socket address " 747 "%s port %d"), paddr(sock_address), ba->port); 748 krb5_klog_syslog(LOG_INFO, _("System does not support pktinfo yet " 749 "binding to a wildcard address. " 750 "Packets are not guaranteed to " 751 "return on the received address.")); 752 } 753 } 754 755 /* Add the socket to the event loop. */ 756 flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST | 757 VERTO_EV_FLAG_REINITIABLE; 758 ret = add_fd(sock, ctype, flags, handle, prog, ctx, vcb, &ev); 759 if (ret) { 760 krb5_klog_syslog(LOG_ERR, _("Error attempting to add verto event")); 761 goto cleanup; 762 } 763 764 if (ba->type == RPC) { 765 conn = verto_get_private(ev); 766 conn->transp = svctcp_create(sock, 0, 0); 767 if (conn->transp == NULL) { 768 ret = errno; 769 krb5_klog_syslog(LOG_ERR, _("Cannot create RPC service: %s"), 770 strerror(ret)); 771 goto cleanup; 772 } 773 774 ret = svc_register(conn->transp, ba->rpc_svc_data.prognum, 775 ba->rpc_svc_data.versnum, ba->rpc_svc_data.dispatch, 776 0); 777 if (!ret) { 778 ret = errno; 779 krb5_klog_syslog(LOG_ERR, _("Cannot register RPC service: %s"), 780 strerror(ret)); 781 goto cleanup; 782 } 783 } 784 785 ev = NULL; 786 sock = -1; 787 ret = 0; 788 789 cleanup: 790 if (sock >= 0) 791 close(sock); 792 if (ev != NULL) 793 verto_del(ev); 794 return ret; 795 } 796 797 /* 798 * Setup all the socket addresses that the net-server should listen to. 799 * 800 * This function uses getaddrinfo to figure out all the addresses. This will 801 * automatically figure out which socket families that should be used on the 802 * host making it useful even for wildcard addresses. 803 */ 804 static krb5_error_code 805 setup_addresses(verto_ctx *ctx, void *handle, const char *prog, 806 int tcp_listen_backlog) 807 { 808 /* An bind_type enum map for the verto callback functions. */ 809 static verto_callback *const verto_callbacks[] = { 810 [UDP] = &process_packet, 811 [TCP] = &accept_tcp_connection, 812 [RPC] = &accept_rpc_connection 813 }; 814 krb5_error_code ret = 0; 815 size_t i; 816 int err, bound_any; 817 struct bind_address addr; 818 struct addrinfo hints, *ai_list = NULL, *ai = NULL; 819 verto_callback vcb; 820 821 /* Check to make sure addresses were added to the server. */ 822 if (bind_addresses.n == 0) { 823 krb5_klog_syslog(LOG_ERR, _("No addresses added to the net server")); 824 return EINVAL; 825 } 826 827 /* Ask for all address families, listener addresses, and no port name 828 * resolution. */ 829 memset(&hints, 0, sizeof(struct addrinfo)); 830 hints.ai_family = AF_UNSPEC; 831 hints.ai_flags = AI_PASSIVE; 832 #ifdef AI_NUMERICSERV 833 hints.ai_flags |= AI_NUMERICSERV; 834 #endif 835 836 /* Add all the requested addresses. */ 837 for (i = 0; i < bind_addresses.n; i++) { 838 addr = bind_addresses.data[i]; 839 hints.ai_socktype = bind_socktypes[addr.type]; 840 841 /* Call getaddrinfo, using a dummy port value. */ 842 err = getaddrinfo(addr.address, "0", &hints, &ai_list); 843 if (err) { 844 krb5_klog_syslog(LOG_ERR, 845 _("Failed getting address info (for %s): %s"), 846 (addr.address == NULL) ? "<wildcard>" : 847 addr.address, gai_strerror(err)); 848 ret = EIO; 849 goto cleanup; 850 } 851 852 /* 853 * Loop through all the sockets that getaddrinfo could find to match 854 * the requested address. For wildcard listeners, this should usually 855 * have two results, one for each of IPv4 and IPv6, or one or the 856 * other, depending on the system. On IPv4-only systems, getaddrinfo() 857 * may return both IPv4 and IPv6 addresses, but creating an IPv6 socket 858 * may give an EAFNOSUPPORT error, so tolerate that error as long as we 859 * can bind at least one socket. 860 */ 861 bound_any = 0; 862 for (ai = ai_list; ai != NULL; ai = ai->ai_next) { 863 /* Make sure getaddrinfo returned a socket with the same type that 864 * was requested. */ 865 assert(hints.ai_socktype == ai->ai_socktype); 866 867 /* Set the real port number. */ 868 sa_setport(ai->ai_addr, addr.port); 869 870 ret = setup_socket(&addr, ai->ai_addr, handle, prog, ctx, 871 tcp_listen_backlog, verto_callbacks[addr.type], 872 bind_conn_types[addr.type]); 873 if (ret) { 874 krb5_klog_syslog(LOG_ERR, 875 _("Failed setting up a %s socket (for %s)"), 876 bind_type_names[addr.type], 877 paddr(ai->ai_addr)); 878 if (ret != EAFNOSUPPORT) 879 goto cleanup; 880 } else { 881 bound_any = 1; 882 } 883 } 884 if (!bound_any) 885 goto cleanup; 886 ret = 0; 887 888 if (ai_list != NULL) 889 freeaddrinfo(ai_list); 890 ai_list = NULL; 891 } 892 893 cleanup: 894 if (ai_list != NULL) 895 freeaddrinfo(ai_list); 896 return ret; 897 } 898 899 krb5_error_code 900 loop_setup_network(verto_ctx *ctx, void *handle, const char *prog, 901 int tcp_listen_backlog) 902 { 903 krb5_error_code ret; 904 verto_ev *ev; 905 int i; 906 907 /* Check to make sure that at least one address was added to the loop. */ 908 if (bind_addresses.n == 0) 909 return EINVAL; 910 911 /* Close any open connections. */ 912 FOREACH_ELT(events, i, ev) 913 verto_del(ev); 914 events.n = 0; 915 916 krb5_klog_syslog(LOG_INFO, _("setting up network...")); 917 ret = setup_addresses(ctx, handle, prog, tcp_listen_backlog); 918 if (ret) { 919 com_err(prog, ret, _("Error setting up network")); 920 exit(1); 921 } 922 krb5_klog_syslog (LOG_INFO, _("set up %d sockets"), (int) events.n); 923 if (events.n == 0) { 924 /* If no sockets were set up, we can't continue. */ 925 com_err(prog, 0, _("no sockets set up?")); 926 exit (1); 927 } 928 929 return 0; 930 } 931 932 void 933 init_addr(krb5_fulladdr *faddr, struct sockaddr *sa) 934 { 935 switch (sa->sa_family) { 936 case AF_INET: 937 faddr->address->addrtype = ADDRTYPE_INET; 938 faddr->address->length = 4; 939 faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr; 940 faddr->port = ntohs(sa2sin(sa)->sin_port); 941 break; 942 case AF_INET6: 943 if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) { 944 faddr->address->addrtype = ADDRTYPE_INET; 945 faddr->address->length = 4; 946 faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr; 947 } else { 948 faddr->address->addrtype = ADDRTYPE_INET6; 949 faddr->address->length = 16; 950 faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr; 951 } 952 faddr->port = ntohs(sa2sin6(sa)->sin6_port); 953 break; 954 default: 955 faddr->address->addrtype = -1; 956 faddr->address->length = 0; 957 faddr->address->contents = 0; 958 faddr->port = 0; 959 break; 960 } 961 } 962 963 struct udp_dispatch_state { 964 void *handle; 965 const char *prog; 966 int port_fd; 967 krb5_address remote_addr_buf; 968 krb5_fulladdr remote_addr; 969 krb5_address local_addr_buf; 970 krb5_fulladdr local_addr; 971 socklen_t saddr_len; 972 socklen_t daddr_len; 973 struct sockaddr_storage saddr; 974 struct sockaddr_storage daddr; 975 aux_addressing_info auxaddr; 976 krb5_data request; 977 char pktbuf[MAX_DGRAM_SIZE]; 978 }; 979 980 static void 981 process_packet_response(void *arg, krb5_error_code code, krb5_data *response) 982 { 983 struct udp_dispatch_state *state = arg; 984 int cc; 985 986 if (code) 987 com_err(state->prog ? state->prog : NULL, code, 988 _("while dispatching (udp)")); 989 if (code || response == NULL) 990 goto out; 991 992 cc = send_to_from(state->port_fd, response->data, 993 (socklen_t) response->length, 0, 994 (struct sockaddr *)&state->saddr, state->saddr_len, 995 (struct sockaddr *)&state->daddr, state->daddr_len, 996 &state->auxaddr); 997 if (cc == -1) { 998 /* Note that the local address (daddr*) has no port number 999 * info associated with it. */ 1000 char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV]; 1001 char daddrbuf[NI_MAXHOST]; 1002 int e = errno; 1003 1004 if (getnameinfo((struct sockaddr *)&state->daddr, state->daddr_len, 1005 daddrbuf, sizeof(daddrbuf), 0, 0, 1006 NI_NUMERICHOST) != 0) { 1007 strlcpy(daddrbuf, "?", sizeof(daddrbuf)); 1008 } 1009 1010 if (getnameinfo((struct sockaddr *)&state->saddr, state->saddr_len, 1011 saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf), 1012 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 1013 strlcpy(saddrbuf, "?", sizeof(saddrbuf)); 1014 strlcpy(sportbuf, "?", sizeof(sportbuf)); 1015 } 1016 1017 com_err(state->prog, e, _("while sending reply to %s/%s from %s"), 1018 saddrbuf, sportbuf, daddrbuf); 1019 goto out; 1020 } 1021 if ((size_t)cc != response->length) { 1022 com_err(state->prog, 0, _("short reply write %d vs %d\n"), 1023 response->length, cc); 1024 } 1025 1026 out: 1027 krb5_free_data(get_context(state->handle), response); 1028 free(state); 1029 } 1030 1031 static void 1032 process_packet(verto_ctx *ctx, verto_ev *ev) 1033 { 1034 int cc; 1035 struct connection *conn; 1036 struct udp_dispatch_state *state; 1037 1038 conn = verto_get_private(ev); 1039 1040 state = malloc(sizeof(*state)); 1041 if (!state) { 1042 com_err(conn->prog, ENOMEM, _("while dispatching (udp)")); 1043 return; 1044 } 1045 1046 state->handle = conn->handle; 1047 state->prog = conn->prog; 1048 state->port_fd = verto_get_fd(ev); 1049 assert(state->port_fd >= 0); 1050 1051 state->saddr_len = sizeof(state->saddr); 1052 state->daddr_len = sizeof(state->daddr); 1053 memset(&state->auxaddr, 0, sizeof(state->auxaddr)); 1054 cc = recv_from_to(state->port_fd, state->pktbuf, sizeof(state->pktbuf), 0, 1055 (struct sockaddr *)&state->saddr, &state->saddr_len, 1056 (struct sockaddr *)&state->daddr, &state->daddr_len, 1057 &state->auxaddr); 1058 if (cc == -1) { 1059 if (errno != EINTR && errno != EAGAIN 1060 /* 1061 * This is how Linux indicates that a previous transmission was 1062 * refused, e.g., if the client timed out before getting the 1063 * response packet. 1064 */ 1065 && errno != ECONNREFUSED 1066 ) 1067 com_err(conn->prog, errno, _("while receiving from network")); 1068 free(state); 1069 return; 1070 } 1071 if (!cc) { /* zero-length packet? */ 1072 free(state); 1073 return; 1074 } 1075 1076 if (state->daddr_len == 0 && conn->type == CONN_UDP) { 1077 /* 1078 * An address couldn't be obtained, so the PKTINFO option probably 1079 * isn't available. If the socket is bound to a specific address, then 1080 * try to get the address here. 1081 */ 1082 state->daddr_len = sizeof(state->daddr); 1083 if (getsockname(state->port_fd, (struct sockaddr *)&state->daddr, 1084 &state->daddr_len) != 0) 1085 state->daddr_len = 0; 1086 /* On failure, keep going anyways. */ 1087 } 1088 1089 state->request.length = cc; 1090 state->request.data = state->pktbuf; 1091 1092 state->remote_addr.address = &state->remote_addr_buf; 1093 init_addr(&state->remote_addr, ss2sa(&state->saddr)); 1094 1095 state->local_addr.address = &state->local_addr_buf; 1096 init_addr(&state->local_addr, ss2sa(&state->daddr)); 1097 1098 /* This address is in net order. */ 1099 dispatch(state->handle, &state->local_addr, &state->remote_addr, 1100 &state->request, 0, ctx, process_packet_response, state); 1101 } 1102 1103 static int 1104 kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev) 1105 { 1106 struct connection *c = NULL, *oldest_c = NULL; 1107 verto_ev *ev, *oldest_ev = NULL; 1108 int i, fd = -1; 1109 1110 krb5_klog_syslog(LOG_INFO, _("too many connections")); 1111 1112 FOREACH_ELT (events, i, ev) { 1113 if (ev == newev) 1114 continue; 1115 1116 c = verto_get_private(ev); 1117 if (!c) 1118 continue; 1119 if (c->type != CONN_TCP && c->type != CONN_RPC) 1120 continue; 1121 if (oldest_c == NULL 1122 || oldest_c->start_time > c->start_time) { 1123 oldest_ev = ev; 1124 oldest_c = c; 1125 } 1126 } 1127 if (oldest_c != NULL) { 1128 krb5_klog_syslog(LOG_INFO, _("dropping %s fd %d from %s"), 1129 c->type == CONN_RPC ? "rpc" : "tcp", 1130 verto_get_fd(oldest_ev), oldest_c->addrbuf); 1131 if (oldest_c->type == CONN_RPC) 1132 oldest_c->rpc_force_close = 1; 1133 verto_del(oldest_ev); 1134 } 1135 return fd; 1136 } 1137 1138 static void 1139 accept_tcp_connection(verto_ctx *ctx, verto_ev *ev) 1140 { 1141 int s; 1142 struct sockaddr_storage addr_s; 1143 struct sockaddr *addr = (struct sockaddr *)&addr_s; 1144 socklen_t addrlen = sizeof(addr_s); 1145 struct connection *newconn, *conn; 1146 char tmpbuf[10]; 1147 verto_ev_flag flags; 1148 verto_ev *newev; 1149 1150 conn = verto_get_private(ev); 1151 s = accept(verto_get_fd(ev), addr, &addrlen); 1152 if (s < 0) 1153 return; 1154 set_cloexec_fd(s); 1155 #ifndef _WIN32 1156 if (s >= FD_SETSIZE) { 1157 close(s); 1158 return; 1159 } 1160 #endif 1161 setnbio(s), setnolinger(s), setkeepalive(s); 1162 1163 flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; 1164 if (add_fd(s, CONN_TCP, flags, conn->handle, conn->prog, ctx, 1165 process_tcp_connection_read, &newev) != 0) { 1166 close(s); 1167 return; 1168 } 1169 newconn = verto_get_private(newev); 1170 1171 if (getnameinfo((struct sockaddr *)&addr_s, addrlen, 1172 newconn->addrbuf, sizeof(newconn->addrbuf), 1173 tmpbuf, sizeof(tmpbuf), 1174 NI_NUMERICHOST | NI_NUMERICSERV)) 1175 strlcpy(newconn->addrbuf, "???", sizeof(newconn->addrbuf)); 1176 else { 1177 char *p, *end; 1178 p = newconn->addrbuf; 1179 end = p + sizeof(newconn->addrbuf); 1180 p += strlen(p); 1181 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) { 1182 *p++ = '.'; 1183 strlcpy(p, tmpbuf, end - p); 1184 } 1185 } 1186 1187 newconn->addr_s = addr_s; 1188 newconn->addrlen = addrlen; 1189 newconn->bufsiz = 1024 * 1024; 1190 newconn->buffer = malloc(newconn->bufsiz); 1191 newconn->start_time = time(0); 1192 1193 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) 1194 kill_lru_tcp_or_rpc_connection(conn->handle, newev); 1195 1196 if (newconn->buffer == 0) { 1197 com_err(conn->prog, errno, 1198 _("allocating buffer for new TCP session from %s"), 1199 newconn->addrbuf); 1200 verto_del(newev); 1201 return; 1202 } 1203 newconn->offset = 0; 1204 newconn->remote_addr.address = &newconn->remote_addr_buf; 1205 init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); 1206 SG_SET(&newconn->sgbuf[0], newconn->lenbuf, 4); 1207 SG_SET(&newconn->sgbuf[1], 0, 0); 1208 } 1209 1210 struct tcp_dispatch_state { 1211 struct sockaddr_storage local_saddr; 1212 krb5_address local_addr_buf; 1213 krb5_fulladdr local_addr; 1214 struct connection *conn; 1215 krb5_data request; 1216 verto_ctx *ctx; 1217 int sock; 1218 }; 1219 1220 static void 1221 process_tcp_response(void *arg, krb5_error_code code, krb5_data *response) 1222 { 1223 struct tcp_dispatch_state *state = arg; 1224 verto_ev *ev; 1225 1226 assert(state); 1227 state->conn->response = response; 1228 1229 if (code) 1230 com_err(state->conn->prog, code, _("while dispatching (tcp)")); 1231 if (code || !response) 1232 goto kill_tcp_connection; 1233 1234 /* Queue outgoing response. */ 1235 store_32_be(response->length, state->conn->lenbuf); 1236 SG_SET(&state->conn->sgbuf[1], response->data, response->length); 1237 state->conn->sgp = state->conn->sgbuf; 1238 state->conn->sgnum = 2; 1239 1240 ev = make_event(state->ctx, VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST, 1241 process_tcp_connection_write, state->sock, state->conn); 1242 if (ev) { 1243 free(state); 1244 return; 1245 } 1246 1247 kill_tcp_connection: 1248 tcp_or_rpc_data_counter--; 1249 free_connection(state->conn); 1250 close(state->sock); 1251 free(state); 1252 } 1253 1254 /* Creates the tcp_dispatch_state and deletes the verto event. */ 1255 static struct tcp_dispatch_state * 1256 prepare_for_dispatch(verto_ctx *ctx, verto_ev *ev) 1257 { 1258 struct tcp_dispatch_state *state; 1259 1260 state = malloc(sizeof(*state)); 1261 if (!state) { 1262 krb5_klog_syslog(LOG_ERR, _("error allocating tcp dispatch private!")); 1263 return NULL; 1264 } 1265 state->conn = verto_get_private(ev); 1266 state->sock = verto_get_fd(ev); 1267 state->ctx = ctx; 1268 verto_set_private(ev, NULL, NULL); /* Don't close the fd or free conn! */ 1269 remove_event_from_set(ev); /* Remove it from the set. */ 1270 verto_del(ev); 1271 return state; 1272 } 1273 1274 static void 1275 process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev) 1276 { 1277 struct tcp_dispatch_state *state = NULL; 1278 struct connection *conn = NULL; 1279 ssize_t nread; 1280 size_t len; 1281 1282 conn = verto_get_private(ev); 1283 1284 /* 1285 * Read message length and data into one big buffer, already allocated 1286 * at connect time. If we have a complete message, we stop reading, so 1287 * we should only be here if there is no data in the buffer, or only an 1288 * incomplete message. 1289 */ 1290 if (conn->offset < 4) { 1291 krb5_data *response = NULL; 1292 1293 /* msglen has not been computed. XXX Doing at least two reads 1294 * here, letting the kernel worry about buffering. */ 1295 len = 4 - conn->offset; 1296 nread = SOCKET_READ(verto_get_fd(ev), 1297 conn->buffer + conn->offset, len); 1298 if (nread < 0) /* error */ 1299 goto kill_tcp_connection; 1300 if (nread == 0) /* eof */ 1301 goto kill_tcp_connection; 1302 conn->offset += nread; 1303 if (conn->offset == 4) { 1304 unsigned char *p = (unsigned char *)conn->buffer; 1305 conn->msglen = load_32_be(p); 1306 if (conn->msglen > conn->bufsiz - 4) { 1307 krb5_error_code err; 1308 /* Message too big. */ 1309 krb5_klog_syslog(LOG_ERR, _("TCP client %s wants %lu bytes, " 1310 "cap is %lu"), conn->addrbuf, 1311 (unsigned long) conn->msglen, 1312 (unsigned long) conn->bufsiz - 4); 1313 /* XXX Should return an error. */ 1314 err = make_toolong_error (conn->handle, 1315 &response); 1316 if (err) { 1317 krb5_klog_syslog(LOG_ERR, _("error constructing " 1318 "KRB_ERR_FIELD_TOOLONG error! %s"), 1319 error_message(err)); 1320 goto kill_tcp_connection; 1321 } 1322 1323 state = prepare_for_dispatch(ctx, ev); 1324 if (!state) { 1325 krb5_free_data(get_context(conn->handle), response); 1326 goto kill_tcp_connection; 1327 } 1328 process_tcp_response(state, 0, response); 1329 } 1330 } 1331 } else { 1332 /* msglen known. */ 1333 socklen_t local_saddrlen = sizeof(struct sockaddr_storage); 1334 1335 len = conn->msglen - (conn->offset - 4); 1336 nread = SOCKET_READ(verto_get_fd(ev), 1337 conn->buffer + conn->offset, len); 1338 if (nread < 0) /* error */ 1339 goto kill_tcp_connection; 1340 if (nread == 0) /* eof */ 1341 goto kill_tcp_connection; 1342 conn->offset += nread; 1343 if (conn->offset < conn->msglen + 4) 1344 return; 1345 1346 /* Have a complete message, and exactly one message. */ 1347 state = prepare_for_dispatch(ctx, ev); 1348 if (!state) 1349 goto kill_tcp_connection; 1350 1351 state->request.length = conn->msglen; 1352 state->request.data = conn->buffer + 4; 1353 1354 if (getsockname(verto_get_fd(ev), ss2sa(&state->local_saddr), 1355 &local_saddrlen) < 0) { 1356 krb5_klog_syslog(LOG_ERR, _("getsockname failed: %s"), 1357 error_message(errno)); 1358 goto kill_tcp_connection; 1359 } 1360 state->local_addr.address = &state->local_addr_buf; 1361 init_addr(&state->local_addr, ss2sa(&state->local_saddr)); 1362 dispatch(state->conn->handle, &state->local_addr, &conn->remote_addr, 1363 &state->request, 1, ctx, process_tcp_response, state); 1364 } 1365 1366 return; 1367 1368 kill_tcp_connection: 1369 verto_del(ev); 1370 } 1371 1372 static void 1373 process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev) 1374 { 1375 struct connection *conn; 1376 SOCKET_WRITEV_TEMP tmp; 1377 ssize_t nwrote; 1378 int sock; 1379 1380 conn = verto_get_private(ev); 1381 sock = verto_get_fd(ev); 1382 1383 nwrote = SOCKET_WRITEV(sock, conn->sgp, 1384 conn->sgnum, tmp); 1385 if (nwrote > 0) { /* non-error and non-eof */ 1386 while (nwrote) { 1387 sg_buf *sgp = conn->sgp; 1388 if ((size_t)nwrote < SG_LEN(sgp)) { 1389 SG_ADVANCE(sgp, (size_t)nwrote); 1390 nwrote = 0; 1391 } else { 1392 nwrote -= SG_LEN(sgp); 1393 conn->sgp++; 1394 conn->sgnum--; 1395 if (conn->sgnum == 0 && nwrote != 0) 1396 abort(); 1397 } 1398 } 1399 1400 /* If we still have more data to send, just return so that 1401 * the main loop can call this function again when the socket 1402 * is ready for more writing. */ 1403 if (conn->sgnum > 0) 1404 return; 1405 } 1406 1407 /* Finished sending. We should go back to reading, though if we 1408 * sent a FIELD_TOOLONG error in reply to a length with the high 1409 * bit set, RFC 4120 says we have to close the TCP stream. */ 1410 verto_del(ev); 1411 } 1412 1413 void 1414 loop_free(verto_ctx *ctx) 1415 { 1416 int i; 1417 struct bind_address val; 1418 1419 verto_free(ctx); 1420 1421 /* Free each addresses added to the loop. */ 1422 FOREACH_ELT(bind_addresses, i, val) 1423 free(val.address); 1424 FREE_SET_DATA(bind_addresses); 1425 FREE_SET_DATA(events); 1426 } 1427 1428 static int 1429 have_event_for_fd(int fd) 1430 { 1431 verto_ev *ev; 1432 int i; 1433 1434 FOREACH_ELT(events, i, ev) { 1435 if (verto_get_fd(ev) == fd) 1436 return 1; 1437 } 1438 1439 return 0; 1440 } 1441 1442 static void 1443 accept_rpc_connection(verto_ctx *ctx, verto_ev *ev) 1444 { 1445 verto_ev_flag flags; 1446 struct connection *conn; 1447 fd_set fds; 1448 int s; 1449 1450 conn = verto_get_private(ev); 1451 1452 /* Service the woken RPC listener descriptor. */ 1453 FD_ZERO(&fds); 1454 FD_SET(verto_get_fd(ev), &fds); 1455 svc_getreqset(&fds); 1456 1457 /* Scan svc_fdset for any new connections. */ 1458 for (s = 0; s < FD_SETSIZE; s++) { 1459 struct sockaddr_storage addr_s; 1460 struct sockaddr *addr = (struct sockaddr *) &addr_s; 1461 socklen_t addrlen = sizeof(addr_s); 1462 struct connection *newconn; 1463 char tmpbuf[10]; 1464 verto_ev *newev; 1465 1466 /* If we already have this fd, continue. */ 1467 if (!FD_ISSET(s, &svc_fdset) || have_event_for_fd(s)) 1468 continue; 1469 1470 flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; 1471 if (add_fd(s, CONN_RPC, flags, conn->handle, conn->prog, ctx, 1472 process_rpc_connection, &newev) != 0) 1473 continue; 1474 newconn = verto_get_private(newev); 1475 1476 set_cloexec_fd(s); 1477 1478 if (getpeername(s, addr, &addrlen) || 1479 getnameinfo(addr, addrlen, 1480 newconn->addrbuf, 1481 sizeof(newconn->addrbuf), 1482 tmpbuf, sizeof(tmpbuf), 1483 NI_NUMERICHOST | NI_NUMERICSERV)) { 1484 strlcpy(newconn->addrbuf, "???", 1485 sizeof(newconn->addrbuf)); 1486 } else { 1487 char *p, *end; 1488 p = newconn->addrbuf; 1489 end = p + sizeof(newconn->addrbuf); 1490 p += strlen(p); 1491 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) { 1492 *p++ = '.'; 1493 strlcpy(p, tmpbuf, end - p); 1494 } 1495 } 1496 1497 newconn->addr_s = addr_s; 1498 newconn->addrlen = addrlen; 1499 newconn->start_time = time(0); 1500 1501 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) 1502 kill_lru_tcp_or_rpc_connection(newconn->handle, newev); 1503 1504 newconn->remote_addr.address = &newconn->remote_addr_buf; 1505 init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); 1506 } 1507 } 1508 1509 static void 1510 process_rpc_connection(verto_ctx *ctx, verto_ev *ev) 1511 { 1512 fd_set fds; 1513 1514 FD_ZERO(&fds); 1515 FD_SET(verto_get_fd(ev), &fds); 1516 svc_getreqset(&fds); 1517 1518 if (!FD_ISSET(verto_get_fd(ev), &svc_fdset)) 1519 verto_del(ev); 1520 } 1521 1522 #endif /* INET */ 1523