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"
62 #include "verto-k5ev.h"
68 #define KDC5_NONET (-1779992062L)
70 static int tcp_or_rpc_data_counter;
71 static int max_tcp_or_rpc_data_connections = 45;
73 /* Misc utility routines. */
75 set_sa_port(struct sockaddr *addr, int port)
77 switch (addr->sa_family) {
79 sa2sin(addr)->sin_port = port;
83 sa2sin6(addr)->sin6_port = port;
95 static int result = -1;
98 s = socket(AF_INET6, SOCK_STREAM, 0);
112 setreuseaddr(int sock, int value)
114 return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
117 #if defined(KRB5_USE_INET6) && defined(IPV6_V6ONLY)
119 setv6only(int sock, int value)
121 return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value));
125 /* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to
126 IPV6_PKTINFO for RFC 2292 implementations. */
127 #ifndef IPV6_RECVPKTINFO
128 #define IPV6_RECVPKTINFO IPV6_PKTINFO
130 /* Parallel, though not standardized. */
131 #ifndef IP_RECVPKTINFO
132 #define IP_RECVPKTINFO IP_PKTINFO
136 set_pktinfo(int sock, int family)
139 int option = 0, proto = 0;
142 #if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
145 option = IP_RECVPKTINFO;
148 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
150 proto = IPPROTO_IPV6;
151 option = IPV6_RECVPKTINFO;
157 if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt)))
164 paddr(struct sockaddr *sa)
166 static char buf[100];
168 if (getnameinfo(sa, socklen(sa),
169 buf, sizeof(buf), portbuf, sizeof(portbuf),
170 NI_NUMERICHOST|NI_NUMERICSERV))
171 strlcpy(buf, "<unprintable>", sizeof(buf));
173 unsigned int len = sizeof(buf) - strlen(buf);
174 char *p = buf + strlen(buf);
175 if (len > 2+strlen(portbuf)) {
178 strncpy(p, portbuf, len);
187 CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP,
188 CONN_RPC_LISTENER, CONN_RPC,
192 /* Per-connection info. */
198 /* Connection fields (TCP or RPC) */
199 struct sockaddr_storage addr_s;
205 /* Incoming data (TCP) */
211 /* Outgoing data (TCP) */
213 unsigned char lenbuf[4];
218 /* Crude denial-of-service avoidance support (TCP or RPC) */
221 /* RPC-specific fields */
227 #define SET(TYPE) struct { TYPE *data; size_t n, max; }
229 /* Start at the top and work down -- this should allow for deletions
230 without disrupting the iteration, since we delete by overwriting
231 the element to be removed with the last element. */
232 #define FOREACH_ELT(set,idx,vvar) \
233 for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--)
235 #define GROW_SET(set, incr, tmpptr) \
236 ((set.max + incr < set.max \
237 || ((set.max + incr) * sizeof(set.data[0]) / sizeof(set.data[0]) \
238 != set.max + incr)) \
240 : ((tmpptr = realloc(set.data, \
241 (set.max + incr) * sizeof(set.data[0]))) \
242 ? (set.data = tmpptr, set.max += incr, 1) \
245 /* 1 = success, 0 = failure */
246 #define ADD(set, val, tmpptr) \
247 ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \
248 ? (set.data[set.n++] = val, 1) \
251 #define DEL(set, idx) \
252 (set.data[idx] = set.data[--set.n], 0)
254 #define FREE_SET_DATA(set) \
255 (free(set.data), set.data = 0, set.max = 0, set.n = 0)
258 * N.B.: The Emacs cc-mode indentation code seems to get confused if
259 * the macro argument here is one word only. So use "unsigned short"
260 * instead of the "u_short" we were using before.
262 struct rpc_svc_data {
268 static SET(unsigned short) udp_port_data, tcp_port_data;
269 static SET(struct rpc_svc_data) rpc_svc_data;
270 static SET(verto_ev *) events;
273 loop_init(verto_ev_type types)
275 types |= VERTO_EV_TYPE_IO;
276 types |= VERTO_EV_TYPE_SIGNAL;
277 types |= VERTO_EV_TYPE_TIMEOUT;
279 #ifdef INTERNAL_VERTO
280 return verto_default_k5ev();
282 return verto_default(NULL, types);
287 do_break(verto_ctx *ctx, verto_ev *ev)
289 krb5_klog_syslog(LOG_DEBUG, _("Got signal to request exit"));
293 struct sighup_context {
299 do_reset(verto_ctx *ctx, verto_ev *ev)
301 struct sighup_context *sc = (struct sighup_context*) verto_get_private(ev);
303 krb5_klog_syslog(LOG_DEBUG, _("Got signal to reset"));
304 krb5_klog_reopen(get_context(sc->handle));
310 free_sighup_context(verto_ctx *ctx, verto_ev *ev)
312 free(verto_get_private(ev));
316 loop_setup_signals(verto_ctx *ctx, void *handle, void (*reset)())
318 struct sighup_context *sc;
321 if (!verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGINT) ||
322 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGTERM) ||
323 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGQUIT) ||
324 !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGPIPE))
327 ev = verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_reset, SIGHUP);
331 sc = malloc(sizeof(*sc));
337 verto_set_private(ev, sc, free_sighup_context);
342 loop_add_udp_port(int port)
347 u_short s_port = port;
352 FOREACH_ELT (udp_port_data, i, val)
355 if (!ADD(udp_port_data, s_port, tmp))
361 loop_add_tcp_port(int port)
366 u_short s_port = port;
371 FOREACH_ELT (tcp_port_data, i, val)
374 if (!ADD(tcp_port_data, s_port, tmp))
380 loop_add_rpc_service(int port, u_long prognum,
381 u_long versnum, void (*dispatchfn)())
385 struct rpc_svc_data svc, val;
388 if (svc.port != port)
390 svc.prognum = prognum;
391 svc.versnum = versnum;
392 svc.dispatch = dispatchfn;
394 FOREACH_ELT (rpc_svc_data, i, val) {
395 if (val.port == port)
398 if (!ADD(rpc_svc_data, svc, tmp))
404 #define USE_AF AF_INET
405 #define USE_TYPE SOCK_DGRAM
407 #define SOCKET_ERRNO errno
408 #include "foreachaddr.h"
414 krb5_error_code retval;
416 #define UDP_DO_IPV4 1
417 #define UDP_DO_IPV6 2
421 free_connection(struct connection *conn)
426 krb5_free_data(get_context(conn->handle), conn->response);
429 if (conn->type == CONN_RPC_LISTENER && conn->transp != NULL)
430 svc_destroy(conn->transp);
435 remove_event_from_set(verto_ev *ev)
440 /* Remove the event from the events. */
441 FOREACH_ELT(events, i, tmp)
449 free_socket(verto_ctx *ctx, verto_ev *ev)
451 struct connection *conn = NULL;
455 remove_event_from_set(ev);
457 fd = verto_get_fd(ev);
458 conn = verto_get_private(ev);
460 /* Close the file descriptor. */
461 krb5_klog_syslog(LOG_INFO, _("closing down fd %d"), fd);
462 if (fd >= 0 && (!conn || conn->type != CONN_RPC || conn->rpc_force_close))
465 /* Free the connection struct. */
467 switch (conn->type) {
469 if (conn->rpc_force_close) {
473 if (FD_ISSET(fd, &svc_fdset)) {
474 krb5_klog_syslog(LOG_ERR,
475 _("descriptor %d closed but still "
482 tcp_or_rpc_data_counter--;
488 free_connection(conn);
493 make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback,
494 int sock, struct connection *conn, int addevent)
499 ev = verto_add_io(ctx, flags, callback, sock);
501 com_err(conn->prog, ENOMEM, _("cannot create io event"));
506 if (!ADD(events, ev, tmp)) {
507 com_err(conn->prog, ENOMEM, _("cannot save event"));
513 verto_set_private(ev, conn, free_socket);
518 add_fd(struct socksetup *data, int sock, enum conn_type conntype,
519 verto_ev_flag flags, verto_callback callback, int addevent)
521 struct connection *newconn;
524 if (sock >= FD_SETSIZE) {
525 data->retval = EMFILE; /* XXX */
526 com_err(data->prog, 0,
527 _("file descriptor number %d too high"), sock);
531 newconn = malloc(sizeof(*newconn));
532 if (newconn == NULL) {
533 data->retval = ENOMEM;
534 com_err(data->prog, ENOMEM,
535 _("cannot allocate storage for connection info"));
538 memset(newconn, 0, sizeof(*newconn));
539 newconn->handle = data->handle;
540 newconn->prog = data->prog;
541 newconn->type = conntype;
543 return make_event(data->ctx, flags, callback, sock, newconn, addevent);
546 static void process_packet(verto_ctx *ctx, verto_ev *ev);
547 static void accept_tcp_connection(verto_ctx *ctx, verto_ev *ev);
548 static void process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev);
549 static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev);
550 static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev);
551 static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev);
554 add_udp_fd(struct socksetup *data, int sock, int pktinfo)
556 return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : CONN_UDP,
557 VERTO_EV_FLAG_IO_READ |
558 VERTO_EV_FLAG_PERSIST |
559 VERTO_EV_FLAG_REINITIABLE,
564 add_tcp_listener_fd(struct socksetup *data, int sock)
566 return add_fd(data, sock, CONN_TCP_LISTENER,
567 VERTO_EV_FLAG_IO_READ |
568 VERTO_EV_FLAG_PERSIST |
569 VERTO_EV_FLAG_REINITIABLE,
570 accept_tcp_connection, 1);
574 add_tcp_read_fd(struct socksetup *data, int sock)
576 return add_fd(data, sock, CONN_TCP,
577 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
578 process_tcp_connection_read, 1);
582 * Create a socket and bind it to addr. Ensure the socket will work with
583 * select(). Set the socket cloexec, reuseaddr, and if applicable v6-only.
584 * Does not call listen(). Returns -1 on failure after logging an error.
587 create_server_socket(struct socksetup *data, struct sockaddr *addr, int type)
591 sock = socket(addr->sa_family, type, 0);
593 data->retval = errno;
594 com_err(data->prog, errno, _("Cannot create TCP server socket on %s"),
598 set_cloexec_fd(sock);
600 #ifndef _WIN32 /* Windows FD_SETSIZE is a count. */
601 if (sock >= FD_SETSIZE) {
603 com_err(data->prog, 0, _("TCP socket fd number %d (for %s) too high"),
609 if (setreuseaddr(sock, 1) < 0) {
610 com_err(data->prog, errno,
611 _("Cannot enable SO_REUSEADDR on fd %d"), sock);
614 #ifdef KRB5_USE_INET6
615 if (addr->sa_family == AF_INET6) {
617 if (setv6only(sock, 1))
618 com_err(data->prog, errno,
619 _("setsockopt(%d,IPV6_V6ONLY,1) failed"), sock);
621 com_err(data->prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"),
624 krb5_klog_syslog(LOG_INFO, _("no IPV6_V6ONLY socket option support"));
625 #endif /* IPV6_V6ONLY */
627 #endif /* KRB5_USE_INET6 */
629 if (bind(sock, addr, socklen(addr)) == -1) {
630 data->retval = errno;
631 com_err(data->prog, errno, _("Cannot bind server socket on %s"),
641 add_rpc_listener_fd(struct socksetup *data, struct rpc_svc_data *svc, int sock)
643 struct connection *conn;
646 ev = add_fd(data, sock, CONN_RPC_LISTENER,
647 VERTO_EV_FLAG_IO_READ |
648 VERTO_EV_FLAG_PERSIST |
649 VERTO_EV_FLAG_REINITIABLE,
650 accept_rpc_connection, 1);
654 conn = verto_get_private(ev);
655 conn->transp = svctcp_create(sock, 0, 0);
656 if (conn->transp == NULL) {
657 krb5_klog_syslog(LOG_ERR,
658 _("Cannot create RPC service: %s; continuing"),
664 if (!svc_register(conn->transp, svc->prognum, svc->versnum,
666 krb5_klog_syslog(LOG_ERR,
667 _("Cannot register RPC service: %s; continuing"),
677 add_rpc_data_fd(struct socksetup *data, int sock)
679 return add_fd(data, sock, CONN_RPC,
680 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
681 process_rpc_connection, 1);
684 static const int one = 1;
689 return ioctlsocket(sock, FIONBIO, (const void *)&one);
693 setkeepalive(int sock)
695 return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
701 static const struct linger ling = { 0, 0 };
702 return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
705 /* Returns -1 or socket fd. */
707 setup_a_tcp_listener(struct socksetup *data, struct sockaddr *addr)
711 sock = create_server_socket(data, addr, SOCK_STREAM);
714 if (listen(sock, 5) < 0) {
715 com_err(data->prog, errno,
716 _("Cannot listen on TCP server socket on %s"), paddr(addr));
721 com_err(data->prog, errno,
722 _("cannot set listening tcp socket on %s non-blocking"),
727 if (setnolinger(sock)) {
728 com_err(data->prog, errno,
729 _("disabling SO_LINGER on TCP socket on %s"), paddr(addr));
737 setup_tcp_listener_ports(struct socksetup *data)
739 struct sockaddr_in sin4;
740 #ifdef KRB5_USE_INET6
741 struct sockaddr_in6 sin6;
745 memset(&sin4, 0, sizeof(sin4));
746 sin4.sin_family = AF_INET;
748 sin4.sin_len = sizeof(sin4);
750 sin4.sin_addr.s_addr = INADDR_ANY;
752 #ifdef KRB5_USE_INET6
753 memset(&sin6, 0, sizeof(sin6));
754 sin6.sin6_family = AF_INET6;
756 sin6.sin6_len = sizeof(sin6);
758 sin6.sin6_addr = in6addr_any;
761 FOREACH_ELT (tcp_port_data, i, port) {
764 set_sa_port((struct sockaddr *)&sin4, htons(port));
765 if (!ipv6_enabled()) {
766 s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
771 #ifndef KRB5_USE_INET6
776 set_sa_port((struct sockaddr *)&sin6, htons(port));
778 s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6);
782 s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4);
783 #endif /* KRB5_USE_INET6 */
786 /* Sockets are created, prepare to listen on them. */
788 if (add_tcp_listener_fd(data, s4) == NULL)
791 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: tcp %s"),
792 s4, paddr((struct sockaddr *)&sin4));
795 #ifdef KRB5_USE_INET6
797 if (add_tcp_listener_fd(data, s6) == NULL) {
801 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: tcp %s"),
802 s6, paddr((struct sockaddr *)&sin6));
805 krb5_klog_syslog(LOG_INFO,
806 _("assuming IPv6 socket accepts IPv4"));
814 setup_rpc_listener_ports(struct socksetup *data)
816 struct sockaddr_in sin4;
817 #ifdef KRB5_USE_INET6
818 struct sockaddr_in6 sin6;
821 struct rpc_svc_data svc;
823 memset(&sin4, 0, sizeof(sin4));
824 sin4.sin_family = AF_INET;
826 sin4.sin_len = sizeof(sin4);
828 sin4.sin_addr.s_addr = INADDR_ANY;
830 #ifdef KRB5_USE_INET6
831 memset(&sin6, 0, sizeof(sin6));
832 sin6.sin6_family = AF_INET6;
834 sin6.sin6_len = sizeof(sin6);
836 sin6.sin6_addr = in6addr_any;
839 FOREACH_ELT (rpc_svc_data, i, svc) {
841 #ifdef KRB5_USE_INET6
845 set_sa_port((struct sockaddr *)&sin4, htons(svc.port));
846 s4 = create_server_socket(data, (struct sockaddr *)&sin4, SOCK_STREAM);
850 if (add_rpc_listener_fd(data, &svc, s4) == NULL)
853 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: rpc %s"),
854 s4, paddr((struct sockaddr *)&sin4));
856 #ifdef KRB5_USE_INET6
857 if (ipv6_enabled()) {
858 set_sa_port((struct sockaddr *)&sin6, htons(svc.port));
859 s6 = create_server_socket(data, (struct sockaddr *)&sin6,
864 if (add_rpc_listener_fd(data, &svc, s6) == NULL)
867 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: rpc %s"),
868 s6, paddr((struct sockaddr *)&sin6));
876 #if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && \
877 (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))
879 #ifdef HAVE_STRUCT_IN6_PKTINFO
880 struct in6_pktinfo pi6;
882 #ifdef HAVE_STRUCT_IN_PKTINFO
883 struct in_pktinfo pi4;
889 setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
890 char *haddrbuf, int pktinfo);
893 setup_udp_pktinfo_ports(struct socksetup *data)
897 struct sockaddr_in sa;
900 memset(&sa, 0, sizeof(sa));
901 sa.sin_family = AF_INET;
903 sa.sin_len = sizeof(sa);
905 r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4);
907 data->udp_flags &= ~UDP_DO_IPV4;
912 struct sockaddr_in6 sa;
915 memset(&sa, 0, sizeof(sa));
916 sa.sin6_family = AF_INET6;
918 sa.sin6_len = sizeof(sa);
920 r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6);
922 data->udp_flags &= ~UDP_DO_IPV6;
926 #else /* no pktinfo compile-time support */
928 setup_udp_pktinfo_ports(struct socksetup *data)
934 setup_udp_port_1(struct socksetup *data, struct sockaddr *addr,
935 char *haddrbuf, int pktinfo)
940 FOREACH_ELT (udp_port_data, i, port) {
941 set_sa_port(addr, htons(port));
942 sock = create_server_socket(data, addr, SOCK_DGRAM);
947 #if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && \
948 (defined(IP_PKTINFO) || defined(IPV6_PKTINFO)))
949 assert(pktinfo == 0);
952 r = set_pktinfo(sock, addr->sa_family);
954 com_err(data->prog, r,
955 _("Cannot request packet info for udp socket address "
956 "%s port %d"), haddrbuf, port);
961 krb5_klog_syslog(LOG_INFO, _("listening on fd %d: udp %s%s"), sock,
962 paddr((struct sockaddr *)addr),
963 pktinfo ? " (pktinfo)" : "");
964 if (add_udp_fd (data, sock, pktinfo) == 0) {
973 setup_udp_port(void *P_data, struct sockaddr *addr)
975 struct socksetup *data = P_data;
976 char haddrbuf[NI_MAXHOST];
979 if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4))
982 if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6))
985 err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf),
986 0, 0, NI_NUMERICHOST);
988 strlcpy(haddrbuf, "<unprintable>", sizeof(haddrbuf));
990 switch (addr->sa_family) {
995 #ifdef KRB5_USE_INET6
999 static int first = 1;
1001 krb5_klog_syslog(LOG_INFO, _("skipping local ipv6 addresses"));
1008 #ifdef AF_LINK /* some BSD systems, AIX */
1012 #ifdef AF_DLI /* Direct Link Interface - DEC Ultrix/OSF1 link layer? */
1021 krb5_klog_syslog(LOG_INFO,
1022 _("skipping unrecognized local address family %d"),
1026 return setup_udp_port_1(data, addr, haddrbuf, 0);
1031 klog_handler(const void *data, size_t len)
1033 static char buf[BUFSIZ];
1034 static int bufoffset;
1037 #define flush_buf() \
1039 ? (((buf[0] == 0 || buf[0] == '\n') \
1040 ? (fork()==0?abort():(void)0) \
1042 krb5_klog_syslog(LOG_INFO, "%s", buf), \
1043 memset(buf, 0, sizeof(buf)), \
1047 p = memchr(data, 0, len);
1049 len = (const char *)p - (const char *)data;
1053 p = memchr(data, '\n', len);
1056 klog_handler(data, (size_t)((const char *)p - (const char *)data));
1058 len -= ((const char *)p - (const char *)data) + 1;
1059 data = 1 + (const char *)p;
1060 goto scan_for_newlines;
1061 } else if (len > sizeof(buf) - 1 || len + bufoffset > sizeof(buf) - 1) {
1062 size_t x = sizeof(buf) - len - 1;
1063 klog_handler(data, x);
1066 data = (const char *)data + x;
1067 goto scan_for_newlines;
1069 memcpy(buf + bufoffset, data, len);
1075 #ifdef HAVE_STRUCT_RT_MSGHDR
1076 #include <net/route.h>
1079 rtm_type_name(int type)
1082 case RTM_ADD: return "RTM_ADD";
1083 case RTM_DELETE: return "RTM_DELETE";
1084 case RTM_NEWADDR: return "RTM_NEWADDR";
1085 case RTM_DELADDR: return "RTM_DELADDR";
1086 case RTM_IFINFO: return "RTM_IFINFO";
1087 case RTM_OLDADD: return "RTM_OLDADD";
1088 case RTM_OLDDEL: return "RTM_OLDDEL";
1089 case RTM_RESOLVE: return "RTM_RESOLVE";
1091 case RTM_NEWMADDR: return "RTM_NEWMADDR";
1092 case RTM_DELMADDR: return "RTM_DELMADDR";
1094 case RTM_MISS: return "RTM_MISS";
1095 case RTM_REDIRECT: return "RTM_REDIRECT";
1096 case RTM_LOSING: return "RTM_LOSING";
1097 case RTM_GET: return "RTM_GET";
1098 default: return "?";
1103 do_network_reconfig(verto_ctx *ctx, verto_ev *ev)
1105 struct connection *conn = verto_get_private(ev);
1106 assert(loop_setup_network(ctx, conn->handle, conn->prog) == 0);
1110 routing_update_needed(struct rt_msghdr *rtm)
1112 switch (rtm->rtm_type) {
1121 * Some flags indicate routing table updates that don't
1122 * indicate local address changes. They may come from
1123 * redirects, or ARP, etc.
1125 * This set of symbols is just an initial guess based on
1126 * some messages observed in real life; working out which
1127 * other flags also indicate messages we should ignore,
1128 * and which flags are portable to all system and thus
1129 * don't need to be conditionalized, is left as a future
1133 if (rtm->rtm_flags & RTF_DYNAMIC)
1137 if (rtm->rtm_flags & RTF_CLONED)
1141 if (rtm->rtm_flags & RTF_LLINFO)
1145 krb5_klog_syslog(LOG_DEBUG,
1146 "network reconfiguration message (%s) received",
1147 rtm_type_name(rtm->rtm_type));
1159 /* Not interesting. */
1161 krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting");
1165 krb5_klog_syslog(LOG_INFO,
1166 _("unhandled routing message type %d, "
1167 "will reconfigure just for the fun of it"),
1176 process_routing_update(verto_ctx *ctx, verto_ev *ev)
1179 struct rt_msghdr rtm;
1180 struct connection *conn;
1182 fd = verto_get_fd(ev);
1183 conn = verto_get_private(ev);
1184 while ((n_read = read(fd, &rtm, sizeof(rtm))) > 0) {
1185 if (n_read < sizeof(rtm)) {
1186 /* Quick hack to figure out if the interesting
1187 fields are present in a short read.
1189 A short read seems to be normal for some message types.
1190 Only complain if we don't have the critical initial
1192 #define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD))
1193 if (n_read < RS(rtm_type) ||
1194 n_read < RS(rtm_version) ||
1195 n_read < RS(rtm_msglen)) {
1196 krb5_klog_syslog(LOG_ERR,
1197 _("short read (%d/%d) from routing socket"),
1198 n_read, (int) sizeof(rtm));
1203 krb5_klog_syslog(LOG_INFO,
1204 _("got routing msg type %d(%s) v%d"),
1205 rtm.rtm_type, rtm_type_name(rtm.rtm_type),
1208 if (rtm.rtm_msglen > sizeof(rtm)) {
1209 /* It appears we get a partial message and the rest is
1211 } else if (rtm.rtm_msglen != n_read) {
1212 krb5_klog_syslog(LOG_ERR,
1213 _("read %d from routing socket but msglen is %d"),
1214 n_read, rtm.rtm_msglen);
1217 if (routing_update_needed(&rtm)) {
1218 /* Ideally we would use idle here instead of timeout. However, idle
1219 * is not universally supported yet in all backends. So let's just
1220 * use timeout for now to avoid locking into a loop. */
1221 ev = verto_add_timeout(ctx, VERTO_EV_FLAG_NONE,
1222 do_network_reconfig, 0);
1223 verto_set_private(ev, conn, NULL);
1231 loop_setup_routing_socket(verto_ctx *ctx, void *handle, const char *progname)
1233 #ifdef HAVE_STRUCT_RT_MSGHDR
1234 struct socksetup data;
1238 data.handle = handle;
1239 data.prog = progname;
1242 sock = socket(PF_ROUTE, SOCK_RAW, 0);
1245 krb5_klog_syslog(LOG_INFO, _("couldn't set up routing socket: %s"),
1248 krb5_klog_syslog(LOG_INFO, _("routing socket is fd %d"), sock);
1250 add_fd(&data, sock, CONN_ROUTING,
1251 VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST,
1252 process_routing_update, 0);
1259 extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
1262 loop_setup_network(verto_ctx *ctx, void *handle, const char *prog)
1264 struct socksetup setup_data;
1268 krb5int_sendtokdc_debug_handler = klog_handler;
1270 /* Close any open connections. */
1271 FOREACH_ELT(events, i, ev)
1275 setup_data.ctx = ctx;
1276 setup_data.handle = handle;
1277 setup_data.prog = prog;
1278 setup_data.retval = 0;
1279 krb5_klog_syslog(LOG_INFO, _("setting up network..."));
1282 * To do: Use RFC 2292 interface (or follow-on) and IPV6_PKTINFO,
1283 * so we might need only one UDP socket; fall back to binding
1284 * sockets on each address only if IPV6_PKTINFO isn't
1287 setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6;
1288 setup_udp_pktinfo_ports(&setup_data);
1289 if (setup_data.udp_flags) {
1290 if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
1291 return setup_data.retval;
1294 setup_tcp_listener_ports(&setup_data);
1295 setup_rpc_listener_ports(&setup_data);
1296 krb5_klog_syslog (LOG_INFO, _("set up %d sockets"), (int) events.n);
1297 if (events.n == 0) {
1298 com_err(prog, 0, _("no sockets set up?"));
1306 init_addr(krb5_fulladdr *faddr, struct sockaddr *sa)
1308 switch (sa->sa_family) {
1310 faddr->address->addrtype = ADDRTYPE_INET;
1311 faddr->address->length = 4;
1312 faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr;
1313 faddr->port = ntohs(sa2sin(sa)->sin_port);
1315 #ifdef KRB5_USE_INET6
1317 if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) {
1318 faddr->address->addrtype = ADDRTYPE_INET;
1319 faddr->address->length = 4;
1320 faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr;
1322 faddr->address->addrtype = ADDRTYPE_INET6;
1323 faddr->address->length = 16;
1324 faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr;
1326 faddr->port = ntohs(sa2sin6(sa)->sin6_port);
1330 faddr->address->addrtype = -1;
1331 faddr->address->length = 0;
1332 faddr->address->contents = 0;
1339 * This holds whatever additional information might be needed to
1340 * properly send back to the client from the correct local address.
1342 * In this case, we only need one datum so far: On Mac OS X, the
1343 * kernel doesn't seem to like sending from link-local addresses
1344 * unless we specify the correct interface.
1347 union aux_addressing_info {
1352 recv_from_to(int s, void *buf, size_t len, int flags,
1353 struct sockaddr *from, socklen_t *fromlen,
1354 struct sockaddr *to, socklen_t *tolen,
1355 union aux_addressing_info *auxaddr)
1357 #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
1359 /* Clobber with something recognizeable in case we try to use
1361 memset(to, 0x40, *tolen);
1365 return recvfrom(s, buf, len, flags, from, fromlen);
1369 char cmsg[CMSG_SPACE(sizeof(union pktinfo))];
1370 struct cmsghdr *cmsgptr;
1374 return recvfrom(s, buf, len, flags, from, fromlen);
1376 /* Clobber with something recognizeable in case we can't extract
1377 the address but try to use it anyways. */
1378 memset(to, 0x40, *tolen);
1382 memset(&msg, 0, sizeof(msg));
1383 msg.msg_name = from;
1384 msg.msg_namelen = *fromlen;
1387 msg.msg_control = cmsg;
1388 msg.msg_controllen = sizeof(cmsg);
1390 r = recvmsg(s, &msg, flags);
1393 *fromlen = msg.msg_namelen;
1395 /* On Darwin (and presumably all *BSD with KAME stacks),
1396 CMSG_FIRSTHDR doesn't check for a non-zero controllen. RFC
1397 3542 recommends making this check, even though the (new) spec
1398 for CMSG_FIRSTHDR says it's supposed to do the check. */
1399 if (msg.msg_controllen) {
1400 cmsgptr = CMSG_FIRSTHDR(&msg);
1403 if (cmsgptr->cmsg_level == IPPROTO_IP
1404 && cmsgptr->cmsg_type == IP_PKTINFO
1405 && *tolen >= sizeof(struct sockaddr_in)) {
1406 struct in_pktinfo *pktinfo;
1407 memset(to, 0, sizeof(struct sockaddr_in));
1408 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
1409 ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr;
1410 ((struct sockaddr_in *)to)->sin_family = AF_INET;
1411 *tolen = sizeof(struct sockaddr_in);
1415 #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && \
1416 defined(HAVE_STRUCT_IN6_PKTINFO)
1417 if (cmsgptr->cmsg_level == IPPROTO_IPV6
1418 && cmsgptr->cmsg_type == IPV6_PKTINFO
1419 && *tolen >= sizeof(struct sockaddr_in6)) {
1420 struct in6_pktinfo *pktinfo;
1421 memset(to, 0, sizeof(struct sockaddr_in6));
1422 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
1423 ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr;
1424 ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6;
1425 *tolen = sizeof(struct sockaddr_in6);
1426 auxaddr->ipv6_ifindex = pktinfo->ipi6_ifindex;
1430 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr);
1433 /* No info about destination addr was available. */
1440 send_to_from(int s, void *buf, size_t len, int flags,
1441 const struct sockaddr *to, socklen_t tolen,
1442 const struct sockaddr *from, socklen_t fromlen,
1443 union aux_addressing_info *auxaddr)
1445 #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE)
1446 return sendto(s, buf, len, flags, to, tolen);
1450 struct cmsghdr *cmsgptr;
1451 char cbuf[CMSG_SPACE(sizeof(union pktinfo))];
1453 if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) {
1455 return sendto(s, buf, len, flags, to, tolen);
1461 if (iov.iov_len != len)
1463 memset(cbuf, 0, sizeof(cbuf));
1464 memset(&msg, 0, sizeof(msg));
1465 msg.msg_name = (void *) to;
1466 msg.msg_namelen = tolen;
1469 msg.msg_control = cbuf;
1470 /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL
1472 msg.msg_controllen = sizeof(cbuf);
1473 cmsgptr = CMSG_FIRSTHDR(&msg);
1474 msg.msg_controllen = 0;
1476 switch (from->sa_family) {
1477 #if defined(IP_PKTINFO)
1479 if (fromlen != sizeof(struct sockaddr_in))
1481 cmsgptr->cmsg_level = IPPROTO_IP;
1482 cmsgptr->cmsg_type = IP_PKTINFO;
1483 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1485 struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr);
1486 const struct sockaddr_in *from4 = (const struct sockaddr_in *)from;
1487 p->ipi_spec_dst = from4->sin_addr;
1489 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
1492 #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && \
1493 defined(HAVE_STRUCT_IN6_PKTINFO)
1495 if (fromlen != sizeof(struct sockaddr_in6))
1497 cmsgptr->cmsg_level = IPPROTO_IPV6;
1498 cmsgptr->cmsg_type = IPV6_PKTINFO;
1499 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1501 struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
1502 const struct sockaddr_in6 *from6 =
1503 (const struct sockaddr_in6 *)from;
1504 p->ipi6_addr = from6->sin6_addr;
1506 * Because of the possibility of asymmetric routing, we
1507 * normally don't want to specify an interface. However,
1508 * Mac OS X doesn't like sending from a link-local address
1509 * (which can come up in testing at least, if you wind up
1510 * with a "foo.local" name) unless we do specify the
1513 if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr))
1514 p->ipi6_ifindex = auxaddr->ipv6_ifindex;
1515 /* otherwise, already zero */
1517 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
1523 return sendmsg(s, &msg, flags);
1527 struct udp_dispatch_state {
1532 krb5_fulladdr faddr;
1533 socklen_t saddr_len;
1534 socklen_t daddr_len;
1535 struct sockaddr_storage saddr;
1536 struct sockaddr_storage daddr;
1537 union aux_addressing_info auxaddr;
1539 char pktbuf[MAX_DGRAM_SIZE];
1543 process_packet_response(void *arg, krb5_error_code code, krb5_data *response)
1545 struct udp_dispatch_state *state = arg;
1549 com_err(state->prog ? state->prog : NULL, code,
1550 _("while dispatching (udp)"));
1551 if (code || response == NULL || state == NULL)
1554 cc = send_to_from(state->port_fd, response->data,
1555 (socklen_t) response->length, 0,
1556 (struct sockaddr *)&state->saddr, state->saddr_len,
1557 (struct sockaddr *)&state->daddr, state->daddr_len,
1560 /* Note that the local address (daddr*) has no port number
1561 * info associated with it. */
1562 char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV];
1563 char daddrbuf[NI_MAXHOST];
1566 if (getnameinfo((struct sockaddr *)&state->daddr, state->daddr_len,
1567 daddrbuf, sizeof(daddrbuf), 0, 0,
1568 NI_NUMERICHOST) != 0) {
1569 strlcpy(daddrbuf, "?", sizeof(daddrbuf));
1572 if (getnameinfo((struct sockaddr *)&state->saddr, state->saddr_len,
1573 saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf),
1574 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
1575 strlcpy(saddrbuf, "?", sizeof(saddrbuf));
1576 strlcpy(sportbuf, "?", sizeof(sportbuf));
1579 com_err(state->prog, e, _("while sending reply to %s/%s from %s"),
1580 saddrbuf, sportbuf, daddrbuf);
1583 if ((size_t)cc != response->length) {
1584 com_err(state->prog, 0, _("short reply write %d vs %d\n"),
1585 response->length, cc);
1589 krb5_free_data(get_context(state->handle), response);
1594 process_packet(verto_ctx *ctx, verto_ev *ev)
1597 struct connection *conn;
1598 struct udp_dispatch_state *state;
1600 conn = verto_get_private(ev);
1602 state = malloc(sizeof(*state));
1604 com_err(conn->prog, ENOMEM, _("while dispatching (udp)"));
1608 state->handle = conn->handle;
1609 state->prog = conn->prog;
1610 state->port_fd = verto_get_fd(ev);
1611 assert(state->port_fd >= 0);
1613 state->saddr_len = sizeof(state->saddr);
1614 state->daddr_len = sizeof(state->daddr);
1615 memset(&state->auxaddr, 0, sizeof(state->auxaddr));
1616 cc = recv_from_to(state->port_fd, state->pktbuf, sizeof(state->pktbuf), 0,
1617 (struct sockaddr *)&state->saddr, &state->saddr_len,
1618 (struct sockaddr *)&state->daddr, &state->daddr_len,
1621 if (errno != EINTR && errno != EAGAIN
1623 * This is how Linux indicates that a previous transmission was
1624 * refused, e.g., if the client timed out before getting the
1627 && errno != ECONNREFUSED
1629 com_err(conn->prog, errno, _("while receiving from network"));
1633 if (!cc) { /* zero-length packet? */
1639 if (state->daddr_len > 0) {
1641 if (getnameinfo(ss2sa(&state->daddr), state->daddr_len,
1642 addrbuf, sizeof(addrbuf),
1643 0, 0, NI_NUMERICHOST))
1644 strlcpy(addrbuf, "?", sizeof(addrbuf));
1645 com_err(conn->prog, 0, _("pktinfo says local addr is %s"), addrbuf);
1649 if (state->daddr_len == 0 && conn->type == CONN_UDP) {
1651 * If the PKTINFO option isn't set, this socket should be bound to a
1652 * specific local address. This info probably should've been saved in
1653 * our socket data structure at setup time.
1655 state->daddr_len = sizeof(state->daddr);
1656 if (getsockname(state->port_fd, (struct sockaddr *)&state->daddr,
1657 &state->daddr_len) != 0)
1658 state->daddr_len = 0;
1659 /* On failure, keep going anyways. */
1662 state->request.length = cc;
1663 state->request.data = state->pktbuf;
1664 state->faddr.address = &state->addr;
1665 init_addr(&state->faddr, ss2sa(&state->saddr));
1666 /* This address is in net order. */
1667 dispatch(state->handle, ss2sa(&state->daddr), &state->faddr,
1668 &state->request, 0, process_packet_response, state);
1672 kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
1674 struct connection *c = NULL, *oldest_c = NULL;
1675 verto_ev *ev, *oldest_ev = NULL;
1678 krb5_klog_syslog(LOG_INFO, _("too many connections"));
1680 FOREACH_ELT (events, i, ev) {
1684 c = verto_get_private(ev);
1687 if (c->type != CONN_TCP && c->type != CONN_RPC)
1690 krb5_klog_syslog(LOG_INFO, "fd %d started at %ld",
1691 verto_get_fd(oldest_ev),
1694 if (oldest_c == NULL
1695 || oldest_c->start_time > c->start_time) {
1700 if (oldest_c != NULL) {
1701 krb5_klog_syslog(LOG_INFO, _("dropping %s fd %d from %s"),
1702 c->type == CONN_RPC ? "rpc" : "tcp",
1703 verto_get_fd(oldest_ev), oldest_c->addrbuf);
1704 if (oldest_c->type == CONN_RPC)
1705 oldest_c->rpc_force_close = 1;
1706 verto_del(oldest_ev);
1712 accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
1715 struct sockaddr_storage addr_s;
1716 struct sockaddr *addr = (struct sockaddr *)&addr_s;
1717 socklen_t addrlen = sizeof(addr_s);
1718 struct socksetup sockdata;
1719 struct connection *newconn, *conn;
1723 conn = verto_get_private(ev);
1724 s = accept(verto_get_fd(ev), addr, &addrlen);
1729 if (s >= FD_SETSIZE) {
1734 setnbio(s), setnolinger(s), setkeepalive(s);
1737 sockdata.handle = conn->handle;
1738 sockdata.prog = conn->prog;
1739 sockdata.retval = 0;
1741 newev = add_tcp_read_fd(&sockdata, s);
1742 if (newev == NULL) {
1746 newconn = verto_get_private(newev);
1748 if (getnameinfo((struct sockaddr *)&addr_s, addrlen,
1749 newconn->addrbuf, sizeof(newconn->addrbuf),
1750 tmpbuf, sizeof(tmpbuf),
1751 NI_NUMERICHOST | NI_NUMERICSERV))
1752 strlcpy(newconn->addrbuf, "???", sizeof(newconn->addrbuf));
1755 p = newconn->addrbuf;
1756 end = p + sizeof(newconn->addrbuf);
1758 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
1760 strlcpy(p, tmpbuf, end - p);
1764 krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s",
1765 s, newconn->addrbuf);
1768 newconn->addr_s = addr_s;
1769 newconn->addrlen = addrlen;
1770 newconn->bufsiz = 1024 * 1024;
1771 newconn->buffer = malloc(newconn->bufsiz);
1772 newconn->start_time = time(0);
1774 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
1775 kill_lru_tcp_or_rpc_connection(conn->handle, newev);
1777 if (newconn->buffer == 0) {
1778 com_err(conn->prog, errno,
1779 _("allocating buffer for new TCP session from %s"),
1784 newconn->offset = 0;
1785 newconn->faddr.address = &newconn->kaddr;
1786 init_addr(&newconn->faddr, ss2sa(&newconn->addr_s));
1787 SG_SET(&newconn->sgbuf[0], newconn->lenbuf, 4);
1788 SG_SET(&newconn->sgbuf[1], 0, 0);
1791 struct tcp_dispatch_state {
1792 struct sockaddr_storage local_saddr;
1793 struct connection *conn;
1800 process_tcp_response(void *arg, krb5_error_code code, krb5_data *response)
1802 struct tcp_dispatch_state *state = arg;
1806 state->conn->response = response;
1809 com_err(state->conn->prog, code, _("while dispatching (tcp)"));
1810 if (code || !response)
1811 goto kill_tcp_connection;
1813 /* Queue outgoing response. */
1814 store_32_be(response->length, state->conn->lenbuf);
1815 SG_SET(&state->conn->sgbuf[1], response->data, response->length);
1816 state->conn->sgp = state->conn->sgbuf;
1817 state->conn->sgnum = 2;
1819 ev = make_event(state->ctx, VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST,
1820 process_tcp_connection_write, state->sock, state->conn, 1);
1826 kill_tcp_connection:
1827 tcp_or_rpc_data_counter--;
1828 free_connection(state->conn);
1833 /* Creates the tcp_dispatch_state and deletes the verto event. */
1834 static struct tcp_dispatch_state *
1835 prepare_for_dispatch(verto_ctx *ctx, verto_ev *ev)
1837 struct tcp_dispatch_state *state;
1839 state = malloc(sizeof(*state));
1841 krb5_klog_syslog(LOG_ERR, _("error allocating tcp dispatch private!"));
1844 state->conn = verto_get_private(ev);
1845 state->sock = verto_get_fd(ev);
1847 verto_set_private(ev, NULL, NULL); /* Don't close the fd or free conn! */
1848 remove_event_from_set(ev); /* Remove it from the set. */
1854 process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
1856 struct tcp_dispatch_state *state = NULL;
1857 struct connection *conn = NULL;
1861 conn = verto_get_private(ev);
1864 * Read message length and data into one big buffer, already allocated
1865 * at connect time. If we have a complete message, we stop reading, so
1866 * we should only be here if there is no data in the buffer, or only an
1867 * incomplete message.
1869 if (conn->offset < 4) {
1870 krb5_data *response = NULL;
1872 /* msglen has not been computed. XXX Doing at least two reads
1873 * here, letting the kernel worry about buffering. */
1874 len = 4 - conn->offset;
1875 nread = SOCKET_READ(verto_get_fd(ev),
1876 conn->buffer + conn->offset, len);
1877 if (nread < 0) /* error */
1878 goto kill_tcp_connection;
1879 if (nread == 0) /* eof */
1880 goto kill_tcp_connection;
1881 conn->offset += nread;
1882 if (conn->offset == 4) {
1883 unsigned char *p = (unsigned char *)conn->buffer;
1884 conn->msglen = load_32_be(p);
1885 if (conn->msglen > conn->bufsiz - 4) {
1886 krb5_error_code err;
1887 /* Message too big. */
1888 krb5_klog_syslog(LOG_ERR, _("TCP client %s wants %lu bytes, "
1889 "cap is %lu"), conn->addrbuf,
1890 (unsigned long) conn->msglen,
1891 (unsigned long) conn->bufsiz - 4);
1892 /* XXX Should return an error. */
1893 err = make_toolong_error (conn->handle,
1896 krb5_klog_syslog(LOG_ERR, _("error constructing "
1897 "KRB_ERR_FIELD_TOOLONG error! %s"),
1898 error_message(err));
1899 goto kill_tcp_connection;
1902 state = prepare_for_dispatch(ctx, ev);
1904 goto kill_tcp_connection;
1905 process_tcp_response(state, 0, response);
1910 socklen_t local_saddrlen = sizeof(struct sockaddr_storage);
1911 struct sockaddr *local_saddrp = NULL;
1913 len = conn->msglen - (conn->offset - 4);
1914 nread = SOCKET_READ(verto_get_fd(ev),
1915 conn->buffer + conn->offset, len);
1916 if (nread < 0) /* error */
1917 goto kill_tcp_connection;
1918 if (nread == 0) /* eof */
1919 goto kill_tcp_connection;
1920 conn->offset += nread;
1921 if (conn->offset < conn->msglen + 4)
1924 /* Have a complete message, and exactly one message. */
1925 state = prepare_for_dispatch(ctx, ev);
1927 goto kill_tcp_connection;
1929 state->request.length = conn->msglen;
1930 state->request.data = conn->buffer + 4;
1932 if (getsockname(verto_get_fd(ev), ss2sa(&state->local_saddr),
1933 &local_saddrlen) == 0)
1934 local_saddrp = ss2sa(&state->local_saddr);
1936 dispatch(state->conn->handle, local_saddrp, &conn->faddr,
1937 &state->request, 1, process_tcp_response, state);
1942 kill_tcp_connection:
1947 process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev)
1949 struct connection *conn;
1950 SOCKET_WRITEV_TEMP tmp;
1954 conn = verto_get_private(ev);
1955 sock = verto_get_fd(ev);
1957 nwrote = SOCKET_WRITEV(sock, conn->sgp,
1959 if (nwrote > 0) { /* non-error and non-eof */
1961 sg_buf *sgp = conn->sgp;
1962 if ((size_t)nwrote < SG_LEN(sgp)) {
1963 SG_ADVANCE(sgp, (size_t)nwrote);
1966 nwrote -= SG_LEN(sgp);
1969 if (conn->sgnum == 0 && nwrote != 0)
1974 /* If we still have more data to send, just return so that
1975 * the main loop can call this function again when the socket
1976 * is ready for more writing. */
1977 if (conn->sgnum > 0)
1981 /* Finished sending. We should go back to reading, though if we
1982 * sent a FIELD_TOOLONG error in reply to a length with the high
1983 * bit set, RFC 4120 says we have to close the TCP stream. */
1988 loop_free(verto_ctx *ctx)
1991 FREE_SET_DATA(events);
1992 FREE_SET_DATA(udp_port_data);
1993 FREE_SET_DATA(tcp_port_data);
1994 FREE_SET_DATA(rpc_svc_data);
1998 have_event_for_fd(int fd)
2003 FOREACH_ELT(events, i, ev) {
2004 if (verto_get_fd(ev) == fd)
2012 accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
2014 struct socksetup sockdata;
2015 struct connection *conn;
2019 conn = verto_get_private(ev);
2022 sockdata.handle = conn->handle;
2023 sockdata.prog = conn->prog;
2024 sockdata.retval = 0;
2026 /* Service the woken RPC listener descriptor. */
2028 FD_SET(verto_get_fd(ev), &fds);
2029 svc_getreqset(&fds);
2031 /* Scan svc_fdset for any new connections. */
2032 for (s = 0; s < FD_SETSIZE; s++) {
2033 struct sockaddr_storage addr_s;
2034 struct sockaddr *addr = (struct sockaddr *) &addr_s;
2035 socklen_t addrlen = sizeof(addr_s);
2036 struct connection *newconn;
2040 /* If we already have this fd, continue. */
2041 if (!FD_ISSET(s, &svc_fdset) || have_event_for_fd(s))
2044 newev = add_rpc_data_fd(&sockdata, s);
2047 newconn = verto_get_private(newev);
2051 setnbio(s), setnolinger(s), setkeepalive(s);
2054 if (getpeername(s, addr, &addrlen) ||
2055 getnameinfo(addr, addrlen,
2057 sizeof(newconn->addrbuf),
2058 tmpbuf, sizeof(tmpbuf),
2059 NI_NUMERICHOST | NI_NUMERICSERV)) {
2060 strlcpy(newconn->addrbuf, "???",
2061 sizeof(newconn->addrbuf));
2064 p = newconn->addrbuf;
2065 end = p + sizeof(newconn->addrbuf);
2067 if ((size_t)(end - p) > 2 + strlen(tmpbuf)) {
2069 strlcpy(p, tmpbuf, end - p);
2073 krb5_klog_syslog(LOG_INFO, _("accepted RPC connection on socket %d "
2074 "from %s"), s, newconn->addrbuf);
2077 newconn->addr_s = addr_s;
2078 newconn->addrlen = addrlen;
2079 newconn->start_time = time(0);
2081 if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
2082 kill_lru_tcp_or_rpc_connection(newconn->handle, newev);
2084 newconn->faddr.address = &newconn->kaddr;
2085 init_addr(&newconn->faddr, ss2sa(&newconn->addr_s));
2090 process_rpc_connection(verto_ctx *ctx, verto_ev *ev)
2095 FD_SET(verto_get_fd(ev), &fds);
2096 svc_getreqset(&fds);
2098 if (!FD_ISSET(verto_get_fd(ev), &svc_fdset))