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