1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/apputils/net-server.c - Network code for krb5 servers (kdc, kadmind) */
4 * Copyright 1990,2000,2007,2008,2009,2010 by the Massachusetts Institute of Technology.
6 * Export of this software from the United States of America may
7 * require a specific license from the United States Government.
8 * It is the responsibility of any person or organization contemplating
9 * export to obtain such a license before exporting.
11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12 * distribute this software and its documentation for any purpose and
13 * without fee is hereby granted, provided that the above copyright
14 * notice appear in all copies and that both that copyright notice and
15 * this permission notice appear in supporting documentation, and that
16 * the name of M.I.T. not be used in advertising or publicity pertaining
17 * to distribution of the software without specific, written prior
18 * permission. Furthermore if you modify this software you must label
19 * your software as modified software and not distribute it in such a
20 * fashion that it might be confused with the original M.I.T. software.
21 * M.I.T. makes no representations about the suitability of
22 * this software for any purpose. It is provided "as is" without express
23 * or implied warranty.
27 #include "adm_proto.h"
28 #include <sys/ioctl.h>
32 #include "port-sockets.h"
33 #include "socket-utils.h"
35 #include <gssrpc/rpc.h>
37 #ifdef HAVE_NETINET_IN_H
38 #include <sys/types.h>
39 #include <netinet/in.h>
40 #include <sys/socket.h>
41 #ifdef HAVE_SYS_SOCKIO_H
42 /* for SIOCGIFCONF, etc. */
43 #include <sys/sockio.h>
47 #include <sys/select.h>
49 #include <arpa/inet.h>
51 #ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */
55 #ifdef HAVE_SYS_FILIO_H
56 #include <sys/filio.h> /* FIONBIO */
59 #include "fake-addrinfo.h"
60 #include "net-server.h"
65 #define KDC5_NONET (-1779992062L)
67 static int tcp_or_rpc_data_counter;
68 static int max_tcp_or_rpc_data_connections = 45;
70 /* Misc utility routines. */
72 set_sa_port(struct sockaddr *addr, int port)
74 switch (addr->sa_family) {
76 sa2sin(addr)->sin_port = port;
80 sa2sin6(addr)->sin6_port = port;
92 static int result = -1;
95 s = socket(AF_INET6, SOCK_STREAM, 0);
109 setreuseaddr(int sock, int value)
111 return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
114 #if defined(KRB5_USE_INET6) && defined(IPV6_V6ONLY)
116 setv6only(int sock, int value)
118 return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value));
122 /* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to
123 IPV6_PKTINFO for RFC 2292 implementations. */
124 #ifndef IPV6_RECVPKTINFO
125 #define IPV6_RECVPKTINFO IPV6_PKTINFO
127 /* Parallel, though not standardized. */
128 #ifndef IP_RECVPKTINFO
129 #define IP_RECVPKTINFO IP_PKTINFO
133 set_pktinfo(int sock, int family)
136 int option = 0, proto = 0;
139 #if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
142 option = IP_RECVPKTINFO;
145 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
147 proto = IPPROTO_IPV6;
148 option = IPV6_RECVPKTINFO;
154 if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt)))
161 paddr(struct sockaddr *sa)
163 static char buf[100];
165 if (getnameinfo(sa, socklen(sa),
166 buf, sizeof(buf), portbuf, sizeof(portbuf),
167 NI_NUMERICHOST|NI_NUMERICSERV))
168 strlcpy(buf, "<unprintable>", sizeof(buf));
170 unsigned int len = sizeof(buf) - strlen(buf);
171 char *p = buf + strlen(buf);
172 if (len > 2+strlen(portbuf)) {
175 strncpy(p, portbuf, len);
184 CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP,
185 CONN_RPC_LISTENER, CONN_RPC,
189 /* Per-connection info. */
195 /* Type-specific information. */
198 struct sockaddr_storage addr_s;
210 unsigned char lenbuf[4];
214 /* crude denial-of-service avoidance support */
225 #define SET(TYPE) struct { TYPE *data; size_t n, max; }
227 /* Start at the top and work down -- this should allow for deletions
228 without disrupting the iteration, since we delete by overwriting
229 the element to be removed with the last element. */
230 #define FOREACH_ELT(set,idx,vvar) \
231 for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--)
233 #define GROW_SET(set, incr, tmpptr) \
234 ((set.max + incr < set.max \
235 || ((set.max + incr) * sizeof(set.data[0]) / sizeof(set.data[0]) \
236 != set.max + incr)) \
238 : ((tmpptr = realloc(set.data, \
239 (set.max + incr) * sizeof(set.data[0]))) \
240 ? (set.data = tmpptr, set.max += incr, 1) \
243 /* 1 = success, 0 = failure */
244 #define ADD(set, val, tmpptr) \
245 ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \
246 ? (set.data[set.n++] = val, 1) \
249 #define DEL(set, idx) \
250 (set.data[idx] = set.data[--set.n], 0)
252 #define FREE_SET_DATA(set) \
253 (free(set.data), set.data = 0, set.max = 0, set.n = 0)
256 * N.B.: The Emacs cc-mode indentation code seems to get confused if
257 * the macro argument here is one word only. So use "unsigned short"
258 * instead of the "u_short" we were using before.
260 struct rpc_svc_data {
266 static SET(unsigned short) udp_port_data, tcp_port_data;
267 static SET(struct rpc_svc_data) rpc_svc_data;
268 static SET(verto_ev *) events;
271 do_break(verto_ctx *ctx, verto_ev *ev)
273 krb5_klog_syslog(LOG_DEBUG, _("Got signal to request exit"));
277 struct sighup_context {
283 do_reset(verto_ctx *ctx, verto_ev *ev)
285 struct sighup_context *sc = (struct sighup_context*) verto_get_private(ev);
287 krb5_klog_syslog(LOG_DEBUG, _("Got signal to reset"));
288 krb5_klog_reopen(get_context(sc->handle));
294 free_sighup_context(verto_ctx *ctx, verto_ev *ev)
296 free(verto_get_private(ev));
300 loop_init(verto_ev_type types, void *handle, void (*reset)())
302 struct sighup_context *sc;
306 types |= VERTO_EV_TYPE_IO;
307 types |= VERTO_EV_TYPE_SIGNAL;
308 types |= VERTO_EV_TYPE_TIMEOUT;
309 ctx = verto_default(NULL, types);
310 if (!verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGINT) ||
311 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGTERM) ||
312 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGQUIT) ||
313 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGPIPE))
316 ev = verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_reset, SIGHUP);
320 sc = malloc(sizeof(*sc));
326 verto_set_private(ev, sc, free_sighup_context);
335 loop_add_udp_port(int port)
340 u_short s_port = port;
345 FOREACH_ELT (udp_port_data, i, val)
348 if (!ADD(udp_port_data, s_port, tmp))
354 loop_add_tcp_port(int port)
359 u_short s_port = port;
364 FOREACH_ELT (tcp_port_data, i, val)
367 if (!ADD(tcp_port_data, s_port, tmp))
373 loop_add_rpc_service(int port, u_long prognum,
374 u_long versnum, void (*dispatchfn)())
378 struct rpc_svc_data svc, val;
381 if (svc.port != port)
383 svc.prognum = prognum;
384 svc.versnum = versnum;
385 svc.dispatch = dispatchfn;
387 FOREACH_ELT (rpc_svc_data, i, val) {
388 if (val.port == port)
391 if (!ADD(rpc_svc_data, svc, tmp))
397 #define USE_AF AF_INET
398 #define USE_TYPE SOCK_DGRAM
400 #define SOCKET_ERRNO errno
401 #include "foreachaddr.h"
407 krb5_error_code retval;
409 #define UDP_DO_IPV4 1
410 #define UDP_DO_IPV6 2
414 free_connection(struct connection *conn)
418 if (conn->u.tcp.response)
419 krb5_free_data(get_context(conn->handle), conn->u.tcp.response);
420 if (conn->u.tcp.buffer)
421 free(conn->u.tcp.buffer);
422 if (conn->type == CONN_RPC_LISTENER && conn->u.rpc.transp != NULL)
423 svc_destroy(conn->u.rpc.transp);
428 remove_event_from_set(verto_ev *ev)
433 /* Remove the event from the events. */
434 FOREACH_ELT(events, i, tmp)
442 free_socket(verto_ctx *ctx, verto_ev *ev)
444 struct connection *conn = NULL;
448 remove_event_from_set(ev);
450 fd = verto_get_fd(ev);
451 conn = verto_get_private(ev);
453 /* Close the file descriptor. */
454 krb5_klog_syslog(LOG_INFO, _("closing down fd %d"), fd);
455 if (fd >= 0 && (!conn || conn->type != CONN_RPC || conn->u.rpc.closed))
458 /* Free the connection struct. */
460 switch (conn->type) {
462 if (conn->u.rpc.closed) {
466 if (FD_ISSET(fd, &svc_fdset)) {
467 krb5_klog_syslog(LOG_ERR,
468 _("descriptor %d closed but still "
475 tcp_or_rpc_data_counter--;
481 free_connection(conn);
486 make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback,
487 int sock, struct connection *conn, int addevent)
491 ev = verto_add_io(ctx, flags, callback, sock);
493 com_err(conn->prog, ENOMEM, _("cannot create io event"));
498 if (!ADD(events, ev, tmp)) {
499 com_err(conn->prog, ENOMEM, _("cannot save event"));
505 verto_set_private(ev, conn, free_socket);
510 convert_event(verto_ctx *ctx, verto_ev *ev, verto_ev_flag flags,
511 verto_callback callback)
513 struct connection *conn;
517 conn = verto_get_private(ev);
518 sock = verto_get_fd(ev);
522 newev = make_event(ctx, flags, callback, sock, conn, 1);
524 /* Delete the read event without closing the socket
525 * or freeing the connection struct. */
527 verto_set_private(ev, NULL, NULL); /* Reset the destructor. */
528 remove_event_from_set(ev); /* Remove it from the set. */
536 add_fd(struct socksetup *data, int sock, enum conn_type conntype,
537 verto_ev_flag flags, verto_callback callback, int addevent)
539 struct connection *newconn;
542 if (sock >= FD_SETSIZE) {
543 data->retval = EMFILE; /* XXX */
544 com_err(data->prog, 0,
545 _("file descriptor number %d too high"), sock);
549 newconn = malloc(sizeof(*newconn));
550 if (newconn == NULL) {
551 data->retval = ENOMEM;
552 com_err(data->prog, ENOMEM,
553 _("cannot allocate storage for connection info"));
556 memset(newconn, 0, sizeof(*newconn));
557 newconn->handle = data->handle;
558 newconn->prog = data->prog;
559 newconn->type = conntype;
561 return make_event(data->ctx, flags, callback, sock, newconn, addevent);
564 static void process_packet(verto_ctx *ctx, verto_ev *ev);
565 static void accept_tcp_connection(verto_ctx *ctx, verto_ev *ev);
566 static void process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev);
567 static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev);
568 static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev);
569 static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev);
572 add_udp_fd(struct socksetup *data, int sock, int pktinfo)
574 return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : CONN_UDP,
575 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
580 add_tcp_listener_fd(struct socksetup *data, int sock)
582 return add_fd(data, sock, CONN_TCP_LISTENER,
583 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
584 accept_tcp_connection, 1);
588 add_tcp_read_fd(struct socksetup *data, int sock)
590 return add_fd(data, sock, CONN_TCP,
591 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
592 process_tcp_connection_read, 1);
596 * Create a socket and bind it to addr. Ensure the socket will work with
597 * select(). Set the socket cloexec, reuseaddr, and if applicable v6-only.
598 * Does not call listen(). Returns -1 on failure after logging an error.
601 create_server_socket(struct socksetup *data, struct sockaddr *addr, int type)
605 sock = socket(addr->sa_family, type, 0);
607 data->retval = errno;
608 com_err(data->prog, errno, _("Cannot create TCP server socket on %s"),
612 set_cloexec_fd(sock);
614 #ifndef _WIN32 /* Windows FD_SETSIZE is a count. */
615 if (sock >= FD_SETSIZE) {
617 com_err(data->prog, 0, _("TCP socket fd number %d (for %s) too high"),
623 if (setreuseaddr(sock, 1) < 0) {
624 com_err(data->prog, errno,
625 _("Cannot enable SO_REUSEADDR on fd %d"), sock);
628 #ifdef KRB5_USE_INET6
629 if (addr->sa_family == AF_INET6) {
631 if (setv6only(sock, 1))
632 com_err(data->prog, errno,
633 _("setsockopt(%d,IPV6_V6ONLY,1) failed"), sock);
635 com_err(data->prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"),
638 krb5_klog_syslog(LOG_INFO, _("no IPV6_V6ONLY socket option support"));
639 #endif /* IPV6_V6ONLY */
641 #endif /* KRB5_USE_INET6 */
643 if (bind(sock, addr, socklen(addr)) == -1) {
644 data->retval = errno;
645 com_err(data->prog, errno, _("Cannot bind server socket on %s"),
655 add_rpc_listener_fd(struct socksetup *data, struct rpc_svc_data *svc, int sock)
657 struct connection *conn;
660 ev = add_fd(data, sock, CONN_RPC_LISTENER,
661 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
662 accept_rpc_connection, 1);
666 conn = verto_get_private(ev);
667 conn->u.rpc.transp = svctcp_create(sock, 0, 0);
668 if (conn->u.rpc.transp == NULL) {
669 krb5_klog_syslog(LOG_ERR,
670 _("Cannot create RPC service: %s; continuing"),
676 if (!svc_register(conn->u.rpc.transp, svc->prognum, svc->versnum,
678 krb5_klog_syslog(LOG_ERR,
679 _("Cannot register RPC service: %s; continuing"),
689 add_rpc_data_fd(struct socksetup *data, int sock)
691 return add_fd(data, sock, CONN_RPC,
692 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
693 process_rpc_connection, 1);
696 static const int one = 1;
701 return ioctlsocket(sock, FIONBIO, (const void *)&one);
705 setkeepalive(int sock)
707 return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
713 static const struct linger ling = { 0, 0 };
714 return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
717 /* Returns -1 or socket fd. */
719 setup_a_tcp_listener(struct socksetup *data, struct sockaddr *addr)
723 sock = create_server_socket(data, addr, SOCK_STREAM);
726 if (listen(sock, 5) < 0) {
727 com_err(data->prog, errno,
728 _("Cannot listen on TCP server socket on %s"), paddr(addr));
733 com_err(data->prog, errno,
734 _("cannot set listening tcp socket on %s non-blocking"),
739 if (setnolinger(sock)) {
740 com_err(data->prog, errno,
741 _("disabling SO_LINGER on TCP socket on %s"), paddr(addr));
749 setup_tcp_listener_ports(struct socksetup *data)
751 struct sockaddr_in sin4;
752 #ifdef KRB5_USE_INET6
753 struct sockaddr_in6 sin6;
757 memset(&sin4, 0, sizeof(sin4));
758 sin4.sin_family = AF_INET;
760 sin4.sin_len = sizeof(sin4);
762 sin4.sin_addr.s_addr = INADDR_ANY;
764 #ifdef KRB5_USE_INET6
765 memset(&sin6, 0, sizeof(sin6));
766 sin6.sin6_family = AF_INET6;
768 sin6.sin6_len = sizeof(sin6);
770 sin6.sin6_addr = in6addr_any;
773 FOREACH_ELT (tcp_port_data, i, port) {
776 set_sa_port((struct sockaddr *)&sin4, htons(port));
777 if (!ipv6_enabled()) {
778 s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
783 #ifndef KRB5_USE_INET6
788 set_sa_port((struct sockaddr *)&sin6, htons(port));
790 s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6);
794 s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
795 #endif /* KRB5_USE_INET6 */
798 /* Sockets are created, prepare to listen on them. */
800 if (add_tcp_listener_fd(data, s4) == NULL)
803 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: tcp %s"),
804 s4, paddr((struct sockaddr *)&sin4));
807 #ifdef KRB5_USE_INET6
809 if (add_tcp_listener_fd(data, s6) == NULL) {
813 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: tcp %s"),
814 s6, paddr((struct sockaddr *)&sin6));
817 krb5_klog_syslog(LOG_INFO,
818 _("assuming IPv6 socket accepts IPv4"));
826 setup_rpc_listener_ports(struct socksetup *data)
828 struct sockaddr_in sin4;
829 #ifdef KRB5_USE_INET6
830 struct sockaddr_in6 sin6;
833 struct rpc_svc_data svc;
835 memset(&sin4, 0, sizeof(sin4));
836 sin4.sin_family = AF_INET;
838 sin4.sin_len = sizeof(sin4);
840 sin4.sin_addr.s_addr = INADDR_ANY;
842 #ifdef KRB5_USE_INET6
843 memset(&sin6, 0, sizeof(sin6));
844 sin6.sin6_family = AF_INET6;
846 sin6.sin6_len = sizeof(sin6);
848 sin6.sin6_addr = in6addr_any;
851 FOREACH_ELT (rpc_svc_data, i, svc) {
853 #ifdef KRB5_USE_INET6
857 set_sa_port((struct sockaddr *)&sin4, htons(svc.port));
858 s4 = create_server_socket(data, (struct sockaddr *)&sin4, SOCK_STREAM);
862 if (add_rpc_listener_fd(data, &svc, s4) == NULL)
865 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: rpc %s"),
866 s4, paddr((struct sockaddr *)&sin4));
868 #ifdef KRB5_USE_INET6
869 if (ipv6_enabled()) {
870 set_sa_port((struct sockaddr *)&sin6, htons(svc.port));
871 s6 = create_server_socket(data, (struct sockaddr *)&sin6,
876 if (add_rpc_listener_fd(data, &svc, s6) == NULL)
879 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: rpc %s"),
880 s6, paddr((struct sockaddr *)&sin6));
888 #if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && \
889 (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))
891 #ifdef HAVE_STRUCT_IN6_PKTINFO
892 struct in6_pktinfo pi6;
894 #ifdef HAVE_STRUCT_IN_PKTINFO
895 struct in_pktinfo pi4;
901 setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
902 char *haddrbuf, int pktinfo);
905 setup_udp_pktinfo_ports(struct socksetup *data)
909 struct sockaddr_in sa;
912 memset(&sa, 0, sizeof(sa));
913 sa.sin_family = AF_INET;
915 sa.sin_len = sizeof(sa);
917 r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4);
919 data->udp_flags &= ~UDP_DO_IPV4;
924 struct sockaddr_in6 sa;
927 memset(&sa, 0, sizeof(sa));
928 sa.sin6_family = AF_INET6;
930 sa.sin6_len = sizeof(sa);
932 r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6);
934 data->udp_flags &= ~UDP_DO_IPV6;
938 #else /* no pktinfo compile-time support */
940 setup_udp_pktinfo_ports(verto_ctx *ctx, struct socksetup *data)
946 setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
947 char *haddrbuf, int pktinfo)
952 FOREACH_ELT (udp_port_data, i, port) {
953 set_sa_port(addr, htons(port));
954 sock = create_server_socket(data, addr, SOCK_DGRAM);
959 #if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && \
960 (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)))
961 assert(pktinfo == 0);
964 r = set_pktinfo(sock, addr->sa_family);
966 com_err(data->prog, r,
967 _("Cannot request packet info for udp socket address "
968 "%s port %d"), haddrbuf, port);
973 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: udp %s%s"), sock,
974 paddr((struct sockaddr *)addr),
975 pktinfo ? " (pktinfo)" : "");
976 if (add_udp_fd (data, sock, pktinfo) == 0) {
985 setup_udp_port(void *P_data, struct sockaddr *addr)
987 struct socksetup *data = P_data;
988 char haddrbuf[NI_MAXHOST];
991 if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4))
994 if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6))
997 err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf),
998 0, 0, NI_NUMERICHOST);
1000 strlcpy(haddrbuf, "<unprintable>", sizeof(haddrbuf));
1002 switch (addr->sa_family) {
1007 #ifdef KRB5_USE_INET6
1011 static int first = 1;
1013 krb5_klog_syslog(LOG_INFO, _("skipping local ipv6 addresses"));
1020 #ifdef AF_LINK /* some BSD systems, AIX */
1024 #ifdef AF_DLI /* Direct Link Interface - DEC Ultrix/OSF1 link layer? */
1033 krb5_klog_syslog(LOG_INFO,
1034 _("skipping unrecognized local address family %d"),
1038 return setup_udp_port_1(data, addr, haddrbuf, 0);
1043 klog_handler(const void *data, size_t len)
1045 static char buf[BUFSIZ];
1046 static int bufoffset;
1049 #define flush_buf() \
1051 ? (((buf[0] == 0 || buf[0] == '\n') \
1052 ? (fork()==0?abort():(void)0) \
1054 krb5_klog_syslog(LOG_INFO, "%s", buf), \
1055 memset(buf, 0, sizeof(buf)), \
1059 p = memchr(data, 0, len);
1061 len = (const char *)p - (const char *)data;
1065 p = memchr(data, '\n', len);
1068 klog_handler(data, (size_t)((const char *)p - (const char *)data));
1070 len -= ((const char *)p - (const char *)data) + 1;
1071 data = 1 + (const char *)p;
1072 goto scan_for_newlines;
1073 } else if (len > sizeof(buf) - 1 || len + bufoffset > sizeof(buf) - 1) {
1074 size_t x = sizeof(buf) - len - 1;
1075 klog_handler(data, x);
1078 data = (const char *)data + x;
1079 goto scan_for_newlines;
1081 memcpy(buf + bufoffset, data, len);
1087 #ifdef HAVE_STRUCT_RT_MSGHDR
1088 #include <net/route.h>
1091 rtm_type_name(int type)
1094 case RTM_ADD: return "RTM_ADD";
1095 case RTM_DELETE: return "RTM_DELETE";
1096 case RTM_NEWADDR: return "RTM_NEWADDR";
1097 case RTM_DELADDR: return "RTM_DELADDR";
1098 case RTM_IFINFO: return "RTM_IFINFO";
1099 case RTM_OLDADD: return "RTM_OLDADD";
1100 case RTM_OLDDEL: return "RTM_OLDDEL";
1101 case RTM_RESOLVE: return "RTM_RESOLVE";
1103 case RTM_NEWMADDR: return "RTM_NEWMADDR";
1104 case RTM_DELMADDR: return "RTM_DELMADDR";
1106 case RTM_MISS: return "RTM_MISS";
1107 case RTM_REDIRECT: return "RTM_REDIRECT";
1108 case RTM_LOSING: return "RTM_LOSING";
1109 case RTM_GET: return "RTM_GET";
1110 default: return "?";
1115 do_network_reconfig(verto_ctx *ctx, verto_ev *ev)
1117 struct connection *conn = verto_get_private(ev);
1118 assert(loop_setup_network(ctx, conn->handle, conn->prog) == 0);
1122 routing_update_needed(struct rt_msghdr *rtm)
1124 switch (rtm->rtm_type) {
1133 * Some flags indicate routing table updates that don't
1134 * indicate local address changes. They may come from
1135 * redirects, or ARP, etc.
1137 * This set of symbols is just an initial guess based on
1138 * some messages observed in real life; working out which
1139 * other flags also indicate messages we should ignore,
1140 * and which flags are portable to all system and thus
1141 * don't need to be conditionalized, is left as a future
1145 if (rtm->rtm_flags & RTF_DYNAMIC)
1149 if (rtm->rtm_flags & RTF_CLONED)
1153 if (rtm->rtm_flags & RTF_LLINFO)
1157 krb5_klog_syslog(LOG_DEBUG,
1158 "network reconfiguration message (%s) received",
1159 rtm_type_name(rtm->rtm_type));
1171 /* Not interesting. */
1173 krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting");
1177 krb5_klog_syslog(LOG_INFO,
1178 _("unhandled routing message type %d, "
1179 "will reconfigure just for the fun of it"),
1188 process_routing_update(verto_ctx *ctx, verto_ev *ev)
1191 struct rt_msghdr rtm;
1192 struct connection *conn;
1194 fd = verto_get_fd(ev);
1195 conn = verto_get_private(ev);
1196 while ((n_read = read(fd, &rtm, sizeof(rtm))) > 0) {
1197 if (n_read < sizeof(rtm)) {
1198 /* Quick hack to figure out if the interesting
1199 fields are present in a short read.
1201 A short read seems to be normal for some message types.
1202 Only complain if we don't have the critical initial
1204 #define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD))
1205 if (n_read < RS(rtm_type) ||
1206 n_read < RS(rtm_version) ||
1207 n_read < RS(rtm_msglen)) {
1208 krb5_klog_syslog(LOG_ERR,
1209 _("short read (%d/%d) from routing socket"),
1210 n_read, (int) sizeof(rtm));
1215 krb5_klog_syslog(LOG_INFO,
1216 _("got routing msg type %d(%s) v%d"),
1217 rtm.rtm_type, rtm_type_name(rtm.rtm_type),
1220 if (rtm.rtm_msglen > sizeof(rtm)) {
1221 /* It appears we get a partial message and the rest is
1223 } else if (rtm.rtm_msglen != n_read) {
1224 krb5_klog_syslog(LOG_ERR,
1225 _("read %d from routing socket but msglen is %d"),
1226 n_read, rtm.rtm_msglen);
1229 if (routing_update_needed(&rtm)) {
1230 /* Ideally we would use idle here instead of timeout. However, idle
1231 * is not universally supported yet in all backends. So let's just
1232 * use timeout for now to avoid locking into a loop. */
1233 ev = verto_add_timeout(ctx, VERTO_EV_FLAG_NONE,
1234 do_network_reconfig, 0);
1235 verto_set_private(ev, conn, NULL);
1243 loop_setup_routing_socket(verto_ctx *ctx, void *handle, const char *progname)
1245 #ifdef HAVE_STRUCT_RT_MSGHDR
1246 struct socksetup data;
1249 data.handle = handle;
1250 data.prog = progname;
1253 int sock = socket(PF_ROUTE, SOCK_RAW, 0);
1256 krb5_klog_syslog(LOG_INFO, _("couldn't set up routing socket: %s"),
1259 krb5_klog_syslog(LOG_INFO, _("routing socket is fd %d"), sock);
1261 add_fd(&data, sock, CONN_ROUTING,
1262 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
1263 process_routing_update, 0);
1270 extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
1273 loop_setup_network(verto_ctx *ctx, void *handle, const char *prog)
1275 struct socksetup setup_data;
1279 krb5int_sendtokdc_debug_handler = klog_handler;
1281 /* Close any open connections. */
1282 FOREACH_ELT(events, i, ev)
1286 setup_data.ctx = ctx;
1287 setup_data.handle = handle;
1288 setup_data.prog = prog;
1289 setup_data.retval = 0;
1290 krb5_klog_syslog(LOG_INFO, _("setting up network..."));
1293 * To do: Use RFC 2292 interface (or follow-on) and IPV6_PKTINFO,
1294 * so we might need only one UDP socket; fall back to binding
1295 * sockets on each address only if IPV6_PKTINFO isn't
1298 setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6;
1299 setup_udp_pktinfo_ports(&setup_data);
1300 if (setup_data.udp_flags) {
1301 if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
1302 return setup_data.retval;
1305 setup_tcp_listener_ports(&setup_data);
1306 setup_rpc_listener_ports(&setup_data);
1307 krb5_klog_syslog (LOG_INFO, _("set up %d sockets"), (int) events.n);
1308 if (events.n == 0) {
1309 com_err(prog, 0, _("no sockets set up?"));
1317 init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
1319 switch (sa->sa_family) {
1321 faddr->address->addrtype = ADDRTYPE_INET;
1322 faddr->address->length = 4;
1323 faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr;
1324 faddr->port = ntohs(sa2sin(sa)->sin_port);
1326 #ifdef KRB5_USE_INET6
1328 if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) {
1329 faddr->address->addrtype = ADDRTYPE_INET;
1330 faddr->address->length = 4;
1331 faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr;
1333 faddr->address->addrtype = ADDRTYPE_INET6;
1334 faddr->address->length = 16;
1335 faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr;
1337 faddr->port = ntohs(sa2sin6(sa)->sin6_port);
1341 faddr->address->addrtype = -1;
1342 faddr->address->length = 0;
1343 faddr->address->contents = 0;
1350 * This holds whatever additional information might be needed to
1351 * properly send back to the client from the correct local address.
1353 * In this case, we only need one datum so far: On Mac OS X, the
1354 * kernel doesn't seem to like sending from link-local addresses
1355 * unless we specify the correct interface.
1358 union aux_addressing_info {
1363 recv_from_to(int s, void *buf, size_t len, int flags,
1364 struct sockaddr *from, socklen_t *fromlen,
1365 struct sockaddr *to, socklen_t *tolen,
1366 union aux_addressing_info *auxaddr)
1368 #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
1370 /* Clobber with something recognizeable in case we try to use
1372 memset(to, 0x40, *tolen);
1376 return recvfrom(s, buf, len, flags, from, fromlen);
1380 char cmsg[CMSG_SPACE(sizeof(union pktinfo))];
1381 struct cmsghdr *cmsgptr;
1385 return recvfrom(s, buf, len, flags, from, fromlen);
1387 /* Clobber with something recognizeable in case we can't extract
1388 the address but try to use it anyways. */
1389 memset(to, 0x40, *tolen);
1393 memset(&msg, 0, sizeof(msg));
1394 msg.msg_name = from;
1395 msg.msg_namelen = *fromlen;
1398 msg.msg_control = cmsg;
1399 msg.msg_controllen = sizeof(cmsg);
1401 r = recvmsg(s, &msg, flags);
1404 *fromlen = msg.msg_namelen;
1406 /* On Darwin (and presumably all *BSD with KAME stacks),
1407 CMSG_FIRSTHDR doesn't check for a non-zero controllen. RFC
1408 3542 recommends making this check, even though the (new) spec
1409 for CMSG_FIRSTHDR says it's supposed to do the check. */
1410 if (msg.msg_controllen) {
1411 cmsgptr = CMSG_FIRSTHDR(&msg);
1414 if (cmsgptr->cmsg_level == IPPROTO_IP
1415 && cmsgptr->cmsg_type == IP_PKTINFO
1416 && *tolen >= sizeof(struct sockaddr_in)) {
1417 struct in_pktinfo *pktinfo;
1418 memset(to, 0, sizeof(struct sockaddr_in));
1419 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
1420 ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr;
1421 ((struct sockaddr_in *)to)->sin_family = AF_INET;
1422 *tolen = sizeof(struct sockaddr_in);
1426 #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && \
1427 defined(HAVE_STRUCT_IN6_PKTINFO)
1428 if (cmsgptr->cmsg_level == IPPROTO_IPV6
1429 && cmsgptr->cmsg_type == IPV6_PKTINFO
1430 && *tolen >= sizeof(struct sockaddr_in6)) {
1431 struct in6_pktinfo *pktinfo;
1432 memset(to, 0, sizeof(struct sockaddr_in6));
1433 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
1434 ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr;
1435 ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6;
1436 *tolen = sizeof(struct sockaddr_in6);
1437 auxaddr->ipv6_ifindex = pktinfo->ipi6_ifindex;
1441 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr);
1444 /* No info about destination addr was available. */
1451 send_to_from(int s, void *buf, size_t len, int flags,
1452 const struct sockaddr *to, socklen_t tolen,
1453 const struct sockaddr *from, socklen_t fromlen,
1454 union aux_addressing_info *auxaddr)
1456 #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
1457 return sendto(s, buf, len, flags, to, tolen);
1461 struct cmsghdr *cmsgptr;
1462 char cbuf[CMSG_SPACE(sizeof(union pktinfo))];
1464 if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) {
1466 return sendto(s, buf, len, flags, to, tolen);
1472 if (iov.iov_len != len)
1474 memset(cbuf, 0, sizeof(cbuf));
1475 memset(&msg, 0, sizeof(msg));
1476 msg.msg_name = (void *) to;
1477 msg.msg_namelen = tolen;
1480 msg.msg_control = cbuf;
1481 /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL
1483 msg.msg_controllen = sizeof(cbuf);
1484 cmsgptr = CMSG_FIRSTHDR(&msg);
1485 msg.msg_controllen = 0;
1487 switch (from->sa_family) {
1488 #if defined(IP_PKTINFO)
1490 if (fromlen != sizeof(struct sockaddr_in))
1492 cmsgptr->cmsg_level = IPPROTO_IP;
1493 cmsgptr->cmsg_type = IP_PKTINFO;
1494 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1496 struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
1497 const struct sockaddr_in *from4 = (const struct sockaddr_in *)from;
1498 p->ipi_spec_dst = from4->sin_addr;
1500 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
1503 #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && \
1504 defined(HAVE_STRUCT_IN6_PKTINFO)
1506 if (fromlen != sizeof(struct sockaddr_in6))
1508 cmsgptr->cmsg_level = IPPROTO_IPV6;
1509 cmsgptr->cmsg_type = IPV6_PKTINFO;
1510 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1512 struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
1513 const struct sockaddr_in6 *from6 =
1514 (const struct sockaddr_in6 *)from;
1515 p->ipi6_addr = from6->sin6_addr;
1517 * Because of the possibility of asymmetric routing, we
1518 * normally don't want to specify an interface. However,
1519 * Mac OS X doesn't like sending from a link-local address
1520 * (which can come up in testing at least, if you wind up
1521 * with a "foo.local" name) unless we do specify the
1524 if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr))
1525 p->ipi6_ifindex = auxaddr->ipv6_ifindex;
1526 /* otherwise, already zero */
1528 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
1534 return sendmsg(s, &msg, flags);
1539 process_packet(verto_ctx *ctx, verto_ev *ev)
1542 socklen_t saddr_len, daddr_len;
1543 krb5_fulladdr faddr;
1544 krb5_error_code retval;
1545 struct sockaddr_storage saddr, daddr;
1548 krb5_data *response;
1549 char pktbuf[MAX_DGRAM_SIZE];
1551 union aux_addressing_info auxaddr;
1552 struct connection *conn;
1554 port_fd = verto_get_fd(ev);
1555 conn = verto_get_private(ev);
1556 assert(port_fd >= 0);
1559 saddr_len = sizeof(saddr);
1560 daddr_len = sizeof(daddr);
1561 memset(&auxaddr, 0, sizeof(auxaddr));
1562 cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0,
1563 (struct sockaddr *)&saddr, &saddr_len,
1564 (struct sockaddr *)&daddr, &daddr_len,
1567 if (errno != EINTR && errno != EAGAIN
1569 * This is how Linux indicates that a previous transmission was
1570 * refused, e.g., if the client timed out before getting the
1573 && errno != ECONNREFUSED
1575 com_err(conn->prog, errno, _("while receiving from network"));
1579 return; /* zero-length packet? */
1582 if (daddr_len > 0) {
1584 if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf),
1585 0, 0, NI_NUMERICHOST))
1586 strlcpy(addrbuf, "?", sizeof(addrbuf));
1587 com_err(conn->prog, 0, _("pktinfo says local addr is %s"), addrbuf);
1591 if (daddr_len == 0 && conn->type == CONN_UDP) {
1593 * If the PKTINFO option isn't set, this socket should be bound to a
1594 * specific local address. This info probably should've been saved in
1595 * our socket data structure at setup time.
1597 daddr_len = sizeof(daddr);
1598 if (getsockname(port_fd, (struct sockaddr *)&daddr, &daddr_len) != 0)
1600 /* On failure, keep going anyways. */
1603 request.length = cc;
1604 request.data = pktbuf;
1605 faddr.address = &addr;
1606 init_addr(&faddr, ss2sa(&saddr));
1607 /* This address is in net order. */
1608 retval = dispatch(conn->handle, ss2sa(&daddr),
1609 &faddr, &request, &response, 0);
1611 com_err(conn->prog, retval, _("while dispatching (udp)"));
1614 if (response == NULL)
1616 cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0,
1617 (struct sockaddr *)&saddr, saddr_len,
1618 (struct sockaddr *)&daddr, daddr_len,
1621 /* Note that the local address (daddr*) has no port number
1622 * info associated with it. */
1623 char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV];
1624 char daddrbuf[NI_MAXHOST];
1626 krb5_free_data(get_context(conn->handle), response);
1627 if (getnameinfo((struct sockaddr *)&daddr, daddr_len,
1628 daddrbuf, sizeof(daddrbuf), 0, 0,
1629 NI_NUMERICHOST) != 0) {
1630 strlcpy(daddrbuf, "?", sizeof(daddrbuf));
1632 if (getnameinfo((struct sockaddr *)&saddr, saddr_len,
1633 saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf),
1634 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
1635 strlcpy(saddrbuf, "?", sizeof(saddrbuf));
1636 strlcpy(sportbuf, "?", sizeof(sportbuf));
1638 com_err(conn->prog, e, _("while sending reply to %s/%s from %s"),
1639 saddrbuf, sportbuf, daddrbuf);
1642 if ((size_t)cc != response->length) {
1643 com_err(conn->prog, 0, _("short reply write %d vs %d\n"),
1644 response->length, cc);
1646 krb5_free_data(get_context(conn->handle), response);
1651 kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
1653 struct connection *c, *oldest_c = NULL;
1654 verto_ev *ev, *oldest_ev = NULL;
1657 krb5_klog_syslog(LOG_INFO, _("too many connections"));
1659 FOREACH_ELT (events, i, ev) {
1663 c = verto_get_private(ev);
1666 if (c->type != CONN_TCP && c->type != CONN_RPC)
1669 krb5_klog_syslog(LOG_INFO, "fd %d started at %ld",
1670 verto_get_fd(oldest_ev),
1671 c->u.tcp.start_time);
1673 if (oldest_c == NULL
1674 || oldest_c->u.tcp.start_time > c->u.tcp.start_time) {
1679 if (oldest_c != NULL) {
1680 krb5_klog_syslog(LOG_INFO, _("dropping %s fd %d from %s"),
1681 c->type == CONN_RPC ? "rpc" : "tcp",
1682 verto_get_fd(oldest_ev), oldest_c->u.tcp.addrbuf);
1683 if (oldest_c->type == CONN_RPC)
1684 oldest_c->u.rpc.closed = 1;
1685 verto_del(oldest_ev);
1691 accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
1694 struct sockaddr_storage addr_s;
1695 struct sockaddr *addr = (struct sockaddr *)&addr_s;
1696 socklen_t addrlen = sizeof(addr_s);
1697 struct socksetup sockdata;
1698 struct connection *newconn, *conn;
1702 conn = verto_get_private(ev);
1703 s = accept(verto_get_fd(ev), addr, &addrlen);
1708 if (s >= FD_SETSIZE) {
1713 setnbio(s), setnolinger(s), setkeepalive(s);
1716 sockdata.handle = conn->handle;
1717 sockdata.prog = conn->prog;
1718 sockdata.retval = 0;
1720 newev = add_tcp_read_fd(&sockdata, s);
1721 if (newev == NULL) {
1725 newconn = verto_get_private(newev);
1727 if (getnameinfo((struct sockaddr *)&addr_s, addrlen,
1728 newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf),
1729 tmpbuf, sizeof(tmpbuf),
1730 NI_NUMERICHOST | NI_NUMERICSERV))
1731 strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(newconn->u.tcp.addrbuf));
1734 p = newconn->u.tcp.addrbuf;
1735 end = p + sizeof(newconn->u.tcp.addrbuf);
1737 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
1739 strlcpy(p, tmpbuf, end - p);
1743 krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s",
1744 s, newconn->u.tcp.addrbuf);
1747 newconn->u.tcp.addr_s = addr_s;
1748 newconn->u.tcp.addrlen = addrlen;
1749 newconn->u.tcp.bufsiz = 1024 * 1024;
1750 newconn->u.tcp.buffer = malloc(newconn->u.tcp.bufsiz);
1751 newconn->u.tcp.start_time = time(0);
1753 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
1754 kill_lru_tcp_or_rpc_connection(conn->handle, newev);
1756 if (newconn->u.tcp.buffer == 0) {
1757 com_err(conn->prog, errno,
1758 _("allocating buffer for new TCP session from %s"),
1759 newconn->u.tcp.addrbuf);
1763 newconn->u.tcp.offset = 0;
1764 newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr;
1765 init_addr(&newconn->u.tcp.faddr, ss2sa(&newconn->u.tcp.addr_s));
1766 SG_SET(&newconn->u.tcp.sgbuf[0], newconn->u.tcp.lenbuf, 4);
1767 SG_SET(&newconn->u.tcp.sgbuf[1], 0, 0);
1771 process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
1773 struct connection *conn;
1778 conn = verto_get_private(ev);
1779 sock = verto_get_fd(ev);
1782 * Read message length and data into one big buffer, already allocated
1783 * at connect time. If we have a complete message, we stop reading, so
1784 * we should only be here if there is no data in the buffer, or only an
1785 * incomplete message.
1787 if (conn->u.tcp.offset < 4) {
1788 /* msglen has not been computed. XXX Doing at least two reads
1789 * here, letting the kernel worry about buffering. */
1790 len = 4 - conn->u.tcp.offset;
1791 nread = SOCKET_READ(sock,
1792 conn->u.tcp.buffer + conn->u.tcp.offset, len);
1793 if (nread < 0) /* error */
1794 goto kill_tcp_connection;
1795 if (nread == 0) /* eof */
1796 goto kill_tcp_connection;
1797 conn->u.tcp.offset += nread;
1798 if (conn->u.tcp.offset == 4) {
1799 unsigned char *p = (unsigned char *)conn->u.tcp.buffer;
1800 conn->u.tcp.msglen = load_32_be(p);
1801 if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) {
1802 krb5_error_code err;
1803 /* Message too big. */
1804 krb5_klog_syslog(LOG_ERR, _("TCP client %s wants %lu bytes, "
1805 "cap is %lu"), conn->u.tcp.addrbuf,
1806 (unsigned long) conn->u.tcp.msglen,
1807 (unsigned long) conn->u.tcp.bufsiz - 4);
1808 /* XXX Should return an error. */
1809 err = make_toolong_error (conn->handle,
1810 &conn->u.tcp.response);
1812 krb5_klog_syslog(LOG_ERR, _("error constructing "
1813 "KRB_ERR_FIELD_TOOLONG error! %s"),
1814 error_message(err));
1815 goto kill_tcp_connection;
1823 krb5_error_code err;
1824 struct sockaddr_storage local_saddr;
1825 socklen_t local_saddrlen = sizeof(local_saddr);
1826 struct sockaddr *local_saddrp = NULL;
1828 len = conn->u.tcp.msglen - (conn->u.tcp.offset - 4);
1829 nread = SOCKET_READ(sock,
1830 conn->u.tcp.buffer + conn->u.tcp.offset, len);
1831 if (nread < 0) /* error */
1832 goto kill_tcp_connection;
1833 if (nread == 0) /* eof */
1834 goto kill_tcp_connection;
1835 conn->u.tcp.offset += nread;
1836 if (conn->u.tcp.offset < conn->u.tcp.msglen + 4)
1838 /* Have a complete message, and exactly one message. */
1839 request.length = conn->u.tcp.msglen;
1840 request.data = conn->u.tcp.buffer + 4;
1842 if (getsockname(sock, ss2sa(&local_saddr),
1843 &local_saddrlen) == 0)
1844 local_saddrp = ss2sa(&local_saddr);
1846 err = dispatch(conn->handle, local_saddrp, &conn->u.tcp.faddr,
1847 &request, &conn->u.tcp.response, 1);
1849 com_err(conn->prog, err, _("while dispatching (tcp)"));
1850 goto kill_tcp_connection;
1852 if (conn->u.tcp.response == NULL)
1853 goto kill_tcp_connection;
1855 /* Queue outgoing response. */
1856 store_32_be(conn->u.tcp.response->length, conn->u.tcp.lenbuf);
1857 SG_SET(&conn->u.tcp.sgbuf[1], conn->u.tcp.response->data,
1858 conn->u.tcp.response->length);
1859 conn->u.tcp.sgp = conn->u.tcp.sgbuf;
1860 conn->u.tcp.sgnum = 2;
1862 if (convert_event(ctx, ev,
1863 VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST,
1864 process_tcp_connection_write))
1870 kill_tcp_connection:
1875 process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev)
1877 struct connection *conn;
1878 SOCKET_WRITEV_TEMP tmp;
1882 conn = verto_get_private(ev);
1883 sock = verto_get_fd(ev);
1885 nwrote = SOCKET_WRITEV(sock, conn->u.tcp.sgp,
1886 conn->u.tcp.sgnum, tmp);
1887 if (nwrote > 0) { /* non-error and non-eof */
1889 sg_buf *sgp = conn->u.tcp.sgp;
1890 if ((size_t)nwrote < SG_LEN(sgp)) {
1891 SG_ADVANCE(sgp, (size_t)nwrote);
1894 nwrote -= SG_LEN(sgp);
1896 conn->u.tcp.sgnum--;
1897 if (conn->u.tcp.sgnum == 0 && nwrote != 0)
1902 /* If we still have more data to send, just return so that
1903 * the main loop can call this function again when the socket
1904 * is ready for more writing. */
1905 if (conn->u.tcp.sgnum > 0)
1909 /* Finished sending. We should go back to reading, though if we
1910 * sent a FIELD_TOOLONG error in reply to a length with the high
1911 * bit set, RFC 4120 says we have to close the TCP stream. */
1916 loop_free(verto_ctx *ctx)
1919 FREE_SET_DATA(events);
1920 FREE_SET_DATA(udp_port_data);
1921 FREE_SET_DATA(tcp_port_data);
1922 FREE_SET_DATA(rpc_svc_data);
1926 have_event_for_fd(int fd)
1931 FOREACH_ELT(events, i, ev) {
1932 if (verto_get_fd(ev) == fd)
1940 accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
1942 struct socksetup sockdata;
1943 struct connection *conn;
1947 conn = verto_get_private(ev);
1950 sockdata.handle = conn->handle;
1951 sockdata.prog = conn->prog;
1952 sockdata.retval = 0;
1954 /* Service the woken RPC listener descriptor. */
1956 FD_SET(verto_get_fd(ev), &fds);
1957 svc_getreqset(&fds);
1959 /* Scan svc_fdset for any new connections. */
1960 for (s = 0; s < FD_SETSIZE; s++) {
1961 struct sockaddr_storage addr_s;
1962 struct sockaddr *addr = (struct sockaddr *) &addr_s;
1963 socklen_t addrlen = sizeof(addr_s);
1964 struct connection *newconn;
1968 /* If we already have this fd, continue. */
1969 if (!FD_ISSET(s, &svc_fdset) || have_event_for_fd(s))
1972 newev = add_rpc_data_fd(&sockdata, s);
1975 newconn = verto_get_private(newev);
1979 setnbio(s), setnolinger(s), setkeepalive(s);
1982 if (getpeername(s, addr, &addrlen) ||
1983 getnameinfo(addr, addrlen,
1984 newconn->u.tcp.addrbuf,
1985 sizeof(newconn->u.tcp.addrbuf),
1986 tmpbuf, sizeof(tmpbuf),
1987 NI_NUMERICHOST | NI_NUMERICSERV)) {
1988 strlcpy(newconn->u.tcp.addrbuf, "???",
1989 sizeof(newconn->u.tcp.addrbuf));
1992 p = newconn->u.tcp.addrbuf;
1993 end = p + sizeof(newconn->u.tcp.addrbuf);
1995 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
1997 strlcpy(p, tmpbuf, end - p);
2001 krb5_klog_syslog(LOG_INFO, _("accepted RPC connection on socket %d "
2002 "from %s"), s, newconn->u.tcp.addrbuf);
2005 newconn->u.tcp.addr_s = addr_s;
2006 newconn->u.tcp.addrlen = addrlen;
2007 newconn->u.tcp.start_time = time(0);
2009 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
2010 kill_lru_tcp_or_rpc_connection(newconn->handle, newev);
2012 newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr;
2013 init_addr(&newconn->u.tcp.faddr, ss2sa(&newconn->u.tcp.addr_s));
2018 process_rpc_connection(verto_ctx *ctx, verto_ev *ev)
2023 FD_SET(verto_get_fd(ev), &fds);
2024 svc_getreqset(&fds);
2026 if (!FD_ISSET(verto_get_fd(ev), &svc_fdset))