888bc14
From 606e2ccc0a2546a23761f910482a55c5bf0f98ac Mon Sep 17 00:00:00 2001
888bc14
From: "Robbie Harwood (frozencemetery)" <rharwood@club.cc.cmu.edu>
888bc14
Date: Fri, 16 Aug 2013 14:48:55 -0400
888bc14
Subject: [PATCH 06/13] Dispatch-style protocol switching for transport
888bc14
888bc14
Switch to using per-transport-type functions when a socket that we're
888bc14
using to communicate with a server becomes readable or writable, and add
888bc14
them as pointers to the connection state.  The functions are passed the
888bc14
name of the realm of the server being contacted, as we expect to need
888bc14
this in the near future.
888bc14
888bc14
[nalin@redhat.com: replace macros with typedefs]
888bc14
[nalin@redhat.com: compare transports with TCP_OR_UDP rather than with 0]
888bc14
888bc14
ticket: 7929
888bc14
---
888bc14
 src/lib/krb5/os/changepw.c   |   6 +-
888bc14
 src/lib/krb5/os/os-proto.h   |   1 +
888bc14
 src/lib/krb5/os/sendto_kdc.c | 297 ++++++++++++++++++++++++-------------------
888bc14
 3 files changed, 171 insertions(+), 133 deletions(-)
888bc14
888bc14
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
888bc14
index a1c9885..0ee427d 100644
888bc14
--- a/src/lib/krb5/os/changepw.c
888bc14
+++ b/src/lib/krb5/os/changepw.c
888bc14
@@ -261,9 +261,9 @@ change_set_password(krb5_context context,
888bc14
         callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
888bc14
         krb5_free_data_contents(callback_ctx.context, &chpw_rep);
888bc14
 
888bc14
-        code = k5_sendto(callback_ctx.context, NULL, &sl, strategy,
888bc14
-                         &callback_info, &chpw_rep, ss2sa(&remote_addr),
888bc14
-                         &addrlen, NULL, NULL, NULL);
888bc14
+        code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
888bc14
+                         &sl, strategy, &callback_info, &chpw_rep,
888bc14
+                         ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
888bc14
         if (code) {
888bc14
             /*
888bc14
              * Here we may want to switch to TCP on some errors.
888bc14
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
888bc14
index f23dda5..e60ccd0 100644
888bc14
--- a/src/lib/krb5/os/os-proto.h
888bc14
+++ b/src/lib/krb5/os/os-proto.h
888bc14
@@ -115,6 +115,7 @@ int _krb5_use_dns_kdc (krb5_context);
888bc14
 int _krb5_conf_boolean (const char *);
888bc14
 
888bc14
 krb5_error_code k5_sendto(krb5_context context, const krb5_data *message,
888bc14
+                          const krb5_data *realm,
888bc14
                           const struct serverlist *addrs,
888bc14
                           k5_transport_strategy strategy,
888bc14
                           struct sendto_callback_info *callback_info,
888bc14
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
888bc14
index c6aae8e..28f1c4d 100644
888bc14
--- a/src/lib/krb5/os/sendto_kdc.c
888bc14
+++ b/src/lib/krb5/os/sendto_kdc.c
888bc14
@@ -96,11 +96,18 @@ struct outgoing_message {
888bc14
     unsigned char msg_len_buf[4];
888bc14
 };
888bc14
 
888bc14
+struct conn_state;
888bc14
+typedef krb5_boolean fd_handler_fn(krb5_context context,
888bc14
+                                   const krb5_data *realm,
888bc14
+                                   struct conn_state *conn,
888bc14
+                                   struct select_state *selstate);
888bc14
+
888bc14
 struct conn_state {
888bc14
     SOCKET fd;
888bc14
     enum conn_states state;
888bc14
-    int (*service)(krb5_context context, struct conn_state *,
888bc14
-                   struct select_state *, int);
888bc14
+    fd_handler_fn *service_connect;
888bc14
+    fd_handler_fn *service_write;
888bc14
+    fd_handler_fn *service_read;
888bc14
     struct remote_address addr;
888bc14
     struct incoming_message in;
888bc14
     struct outgoing_message out;
888bc14
@@ -409,9 +416,9 @@ krb5_sendto_kdc(krb5_context context, const krb5_data *message,
888bc14
         return retval;
888bc14
 
888bc14
     err = 0;
888bc14
-    retval = k5_sendto(context, message, &servers, strategy, NULL, reply,
888bc14
-                       NULL, NULL, &server_used, check_for_svc_unavailable,
888bc14
-                       &err;;
888bc14
+    retval = k5_sendto(context, message, realm, &servers, strategy, NULL,
888bc14
+                       reply, NULL, NULL, &server_used,
888bc14
+                       check_for_svc_unavailable, &err;;
888bc14
     if (retval == KRB5_KDC_UNREACH) {
888bc14
         if (err == KDC_ERR_SVC_UNAVAILABLE) {
888bc14
             retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
888bc14
@@ -457,10 +464,10 @@ cleanup:
888bc14
  *   connections already in progress
888bc14
  */
888bc14
 
888bc14
-static int service_tcp_fd(krb5_context context, struct conn_state *conn,
888bc14
-                          struct select_state *selstate, int ssflags);
888bc14
-static int service_udp_fd(krb5_context context, struct conn_state *conn,
888bc14
-                          struct select_state *selstate, int ssflags);
888bc14
+static fd_handler_fn service_tcp_connect;
888bc14
+static fd_handler_fn service_tcp_write;
888bc14
+static fd_handler_fn service_tcp_read;
888bc14
+static fd_handler_fn service_udp_read;
888bc14
 
888bc14
 /* Set up the actual message we will send across the underlying transport to
888bc14
  * communicate the payload message, using one or both of state->out.sgbuf. */
888bc14
@@ -505,9 +512,13 @@ add_connection(struct conn_state **conns, k5_transport transport,
888bc14
     state->server_index = server_index;
888bc14
     SG_SET(&state->out.sgbuf[1], NULL, 0);
888bc14
     if (transport == TCP) {
888bc14
-        state->service = service_tcp_fd;
888bc14
+        state->service_connect = service_tcp_connect;
888bc14
+        state->service_write = service_tcp_write;
888bc14
+        state->service_read = service_tcp_read;
888bc14
     } else {
888bc14
-        state->service = service_udp_fd;
888bc14
+        state->service_connect = NULL;
888bc14
+        state->service_write = NULL;
888bc14
+        state->service_read = service_udp_read;
888bc14
 
888bc14
         if (*udpbufp == NULL) {
888bc14
             *udpbufp = malloc(MAX_DGRAM_SIZE);
888bc14
@@ -788,9 +799,13 @@ maybe_send(krb5_context context, struct conn_state *conn,
888bc14
 }
888bc14
 
888bc14
 static void
888bc14
-kill_conn(struct conn_state *conn, struct select_state *selstate)
888bc14
+kill_conn(krb5_context context, struct conn_state *conn,
888bc14
+          struct select_state *selstate)
888bc14
 {
888bc14
+    if (socktype_for_transport(conn->addr.transport) == SOCK_STREAM)
888bc14
+        TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &conn->addr);
888bc14
     cm_remove_fd(selstate, conn->fd);
888bc14
+
888bc14
     closesocket(conn->fd);
888bc14
     conn->fd = INVALID_SOCKET;
888bc14
     conn->state = FAILED;
888bc14
@@ -814,136 +829,157 @@ get_so_error(int fd)
888bc14
     return sockerr;
888bc14
 }
888bc14
 
888bc14
-/* Process events on a TCP socket.  Return 1 if we get a complete reply. */
888bc14
-static int
888bc14
-service_tcp_fd(krb5_context context, struct conn_state *conn,
888bc14
-               struct select_state *selstate, int ssflags)
888bc14
+/* Perform next step in sending.  Return true on usable data. */
888bc14
+static krb5_boolean
888bc14
+service_dispatch(krb5_context context, const krb5_data *realm,
888bc14
+                 struct conn_state *conn, struct select_state *selstate,
888bc14
+                 int ssflags)
888bc14
 {
888bc14
-    int e = 0;
888bc14
-    ssize_t nwritten, nread;
888bc14
-    SOCKET_WRITEV_TEMP tmp;
888bc14
-    struct incoming_message *in = &conn->in;
888bc14
-    struct outgoing_message *out = &conn->out;
888bc14
-
888bc14
     /* Check for a socket exception. */
888bc14
-    if (ssflags & SSF_EXCEPTION)
888bc14
-        goto kill_conn;
888bc14
+    if (ssflags & SSF_EXCEPTION) {
888bc14
+        kill_conn(context, conn, selstate);
888bc14
+        return FALSE;
888bc14
+    }
888bc14
 
888bc14
     switch (conn->state) {
888bc14
     case CONNECTING:
888bc14
-        /* Check whether the connection succeeded. */
888bc14
-        e = get_so_error(conn->fd);
888bc14
-        if (e) {
888bc14
-            TRACE_SENDTO_KDC_TCP_ERROR_CONNECT(context, &conn->addr, e);
888bc14
-            goto kill_conn;
888bc14
-        }
888bc14
-        conn->state = WRITING;
888bc14
+        assert(conn->service_connect != NULL);
888bc14
+        return conn->service_connect(context, realm, conn, selstate);
888bc14
+    case WRITING:
888bc14
+        assert(conn->service_write != NULL);
888bc14
+        return conn->service_write(context, realm, conn, selstate);
888bc14
+    case READING:
888bc14
+        assert(conn->service_read != NULL);
888bc14
+        return conn->service_read(context, realm, conn, selstate);
888bc14
+    default:
888bc14
+        abort();
888bc14
+    }
888bc14
+}
888bc14
 
888bc14
-        /* Record this connection's timeout for service_fds. */
888bc14
-        if (get_curtime_ms(&conn->endtime) == 0)
888bc14
-            conn->endtime += 10000;
888bc14
+/* Initialize TCP transport. */
888bc14
+static krb5_boolean
888bc14
+service_tcp_connect(krb5_context context, const krb5_data *realm,
888bc14
+                    struct conn_state *conn, struct select_state *selstate)
888bc14
+{
888bc14
+    /* Check whether the connection succeeded. */
888bc14
+    int e = get_so_error(conn->fd);
888bc14
 
888bc14
-        /* Fall through. */
888bc14
-    case WRITING:
888bc14
-        TRACE_SENDTO_KDC_TCP_SEND(context, &conn->addr);
888bc14
-        nwritten = SOCKET_WRITEV(conn->fd, out->sgp, out->sg_count, tmp);
888bc14
-        if (nwritten < 0) {
888bc14
-            TRACE_SENDTO_KDC_TCP_ERROR_SEND(context, &conn->addr,
888bc14
-                                            SOCKET_ERRNO);
888bc14
-            goto kill_conn;
888bc14
+    if (e) {
888bc14
+        TRACE_SENDTO_KDC_TCP_ERROR_CONNECT(context, &conn->addr, e);
888bc14
+        kill_conn(context, conn, selstate);
888bc14
+        return FALSE;
888bc14
+    }
888bc14
+
888bc14
+    conn->state = WRITING;
888bc14
+
888bc14
+    /* Record this connection's timeout for service_fds. */
888bc14
+    if (get_curtime_ms(&conn->endtime) == 0)
888bc14
+        conn->endtime += 10000;
888bc14
+
888bc14
+    return service_tcp_write(context, realm, conn, selstate);
888bc14
+}
888bc14
+
888bc14
+/* Sets conn->state to READING when done. */
888bc14
+static krb5_boolean
888bc14
+service_tcp_write(krb5_context context, const krb5_data *realm,
888bc14
+                  struct conn_state *conn, struct select_state *selstate)
888bc14
+{
888bc14
+    ssize_t nwritten;
888bc14
+    SOCKET_WRITEV_TEMP tmp;
888bc14
+
888bc14
+    TRACE_SENDTO_KDC_TCP_SEND(context, &conn->addr);
888bc14
+    nwritten = SOCKET_WRITEV(conn->fd, conn->out.sgp, conn->out.sg_count, tmp);
888bc14
+    if (nwritten < 0) {
888bc14
+        TRACE_SENDTO_KDC_TCP_ERROR_SEND(context, &conn->addr, SOCKET_ERRNO);
888bc14
+        kill_conn(context, conn, selstate);
888bc14
+        return FALSE;
888bc14
+    }
888bc14
+    while (nwritten) {
888bc14
+        sg_buf *sgp = conn->out.sgp;
888bc14
+        if ((size_t)nwritten < SG_LEN(sgp)) {
888bc14
+            SG_ADVANCE(sgp, (size_t)nwritten);
888bc14
+            nwritten = 0;
888bc14
+        } else {
888bc14
+            nwritten -= SG_LEN(sgp);
888bc14
+            conn->out.sgp++;
888bc14
+            conn->out.sg_count--;
888bc14
         }
888bc14
-        while (nwritten) {
888bc14
-            sg_buf *sgp = out->sgp;
888bc14
-            if ((size_t) nwritten < SG_LEN(sgp)) {
888bc14
-                SG_ADVANCE(sgp, (size_t) nwritten);
888bc14
-                nwritten = 0;
888bc14
-            } else {
888bc14
-                nwritten -= SG_LEN(sgp);
888bc14
-                out->sgp++;
888bc14
-                out->sg_count--;
888bc14
-            }
888bc14
+    }
888bc14
+    if (conn->out.sg_count == 0) {
888bc14
+        /* Done writing, switch to reading. */
888bc14
+        cm_read(selstate, conn->fd);
888bc14
+        conn->state = READING;
888bc14
+    }
888bc14
+    return FALSE;
888bc14
+}
888bc14
+
888bc14
+/* Return true on usable data. */
888bc14
+static krb5_boolean
888bc14
+service_tcp_read(krb5_context context, const krb5_data *realm,
888bc14
+                 struct conn_state *conn, struct select_state *selstate)
888bc14
+{
888bc14
+    ssize_t nread;
888bc14
+    int e = 0;
888bc14
+    struct incoming_message *in = &conn->in;
888bc14
+
888bc14
+    if (in->bufsizebytes_read == 4) {
888bc14
+        /* Reading data.  */
888bc14
+        nread = SOCKET_READ(conn->fd, &in->buf[in->pos], in->n_left);
888bc14
+        if (nread <= 0) {
888bc14
+            e = nread ? SOCKET_ERRNO : ECONNRESET;
888bc14
+            TRACE_SENDTO_KDC_TCP_ERROR_RECV(context, &conn->addr, e);
888bc14
+            kill_conn(context, conn, selstate);
888bc14
+            return FALSE;
888bc14
         }
888bc14
-        if (out->sg_count == 0) {
888bc14
-            /* Done writing, switch to reading. */
888bc14
-            cm_read(selstate, conn->fd);
888bc14
-            conn->state = READING;
888bc14
-            in->bufsizebytes_read = 0;
888bc14
-            in->bufsize = 0;
888bc14
-            in->pos = 0;
888bc14
-            in->buf = NULL;
888bc14
-            in->n_left = 0;
888bc14
+        in->n_left -= nread;
888bc14
+        in->pos += nread;
888bc14
+        if (in->n_left <= 0)
888bc14
+            return TRUE;
888bc14
+    } else {
888bc14
+        /* Reading length.  */
888bc14
+        nread = SOCKET_READ(conn->fd, in->bufsizebytes + in->bufsizebytes_read,
888bc14
+                            4 - in->bufsizebytes_read);
888bc14
+        if (nread <= 0) {
888bc14
+            e = nread ? SOCKET_ERRNO : ECONNRESET;
888bc14
+            TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(context, &conn->addr, e);
888bc14
+            kill_conn(context, conn, selstate);
888bc14
+            return FALSE;
888bc14
         }
888bc14
-        return 0;
888bc14
-
888bc14
-    case READING:
888bc14
+        in->bufsizebytes_read += nread;
888bc14
         if (in->bufsizebytes_read == 4) {
888bc14
-            /* Reading data.  */
888bc14
-            nread = SOCKET_READ(conn->fd, &in->buf[in->pos], in->n_left);
888bc14
-            if (nread <= 0) {
888bc14
-                e = nread ? SOCKET_ERRNO : ECONNRESET;
888bc14
-                TRACE_SENDTO_KDC_TCP_ERROR_RECV(context, &conn->addr, e);
888bc14
-                goto kill_conn;
888bc14
-            }
888bc14
-            in->n_left -= nread;
888bc14
-            in->pos += nread;
888bc14
-            if (in->n_left <= 0)
888bc14
-                return 1;
888bc14
-        } else {
888bc14
-            /* Reading length.  */
888bc14
-            nread = SOCKET_READ(conn->fd,
888bc14
-                                in->bufsizebytes + in->bufsizebytes_read,
888bc14
-                                4 - in->bufsizebytes_read);
888bc14
-            if (nread <= 0) {
888bc14
-                e = nread ? SOCKET_ERRNO : ECONNRESET;
888bc14
-                TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(context, &conn->addr, e);
888bc14
-                goto kill_conn;
888bc14
+            unsigned long len = load_32_be(in->bufsizebytes);
888bc14
+            /* Arbitrary 1M cap.  */
888bc14
+            if (len > 1 * 1024 * 1024) {
888bc14
+                kill_conn(context, conn, selstate);
888bc14
+                return FALSE;
888bc14
             }
888bc14
-            in->bufsizebytes_read += nread;
888bc14
-            if (in->bufsizebytes_read == 4) {
888bc14
-                unsigned long len = load_32_be(in->bufsizebytes);
888bc14
-                /* Arbitrary 1M cap.  */
888bc14
-                if (len > 1 * 1024 * 1024)
888bc14
-                    goto kill_conn;
888bc14
-                in->bufsize = in->n_left = len;
888bc14
-                in->pos = 0;
888bc14
-                in->buf = malloc(len);
888bc14
-                if (in->buf == NULL)
888bc14
-                    goto kill_conn;
888bc14
+            in->bufsize = in->n_left = len;
888bc14
+            in->pos = 0;
888bc14
+            in->buf = malloc(len);
888bc14
+            if (in->buf == NULL) {
888bc14
+                kill_conn(context, conn, selstate);
888bc14
+                return FALSE;
888bc14
             }
888bc14
         }
888bc14
-        break;
888bc14
-
888bc14
-    default:
888bc14
-        abort();
888bc14
     }
888bc14
-    return 0;
888bc14
-
888bc14
-kill_conn:
888bc14
-    TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &conn->addr);
888bc14
-    kill_conn(conn, selstate);
888bc14
-    return 0;
888bc14
+    return FALSE;
888bc14
 }
888bc14
 
888bc14
-/* Process events on a UDP socket.  Return 1 if we get a reply. */
888bc14
-static int
888bc14
-service_udp_fd(krb5_context context, struct conn_state *conn,
888bc14
-               struct select_state *selstate, int ssflags)
888bc14
+/* Process events on a UDP socket.  Return true if we get a reply. */
888bc14
+static krb5_boolean
888bc14
+service_udp_read(krb5_context context, const krb5_data *realm,
888bc14
+                 struct conn_state *conn, struct select_state *selstate)
888bc14
 {
888bc14
     int nread;
888bc14
 
888bc14
-    if (!(ssflags & (SSF_READ|SSF_EXCEPTION)))
888bc14
-        abort();
888bc14
-    if (conn->state != READING)
888bc14
-        abort();
888bc14
-
888bc14
     nread = recv(conn->fd, conn->in.buf, conn->in.bufsize, 0);
888bc14
     if (nread < 0) {
888bc14
         TRACE_SENDTO_KDC_UDP_ERROR_RECV(context, &conn->addr, SOCKET_ERRNO);
888bc14
-        kill_conn(conn, selstate);
888bc14
-        return 0;
888bc14
+        kill_conn(context, conn, selstate);
888bc14
+        return FALSE;
888bc14
     }
888bc14
     conn->in.pos = nread;
888bc14
-    return 1;
888bc14
+    return TRUE;
888bc14
 }
888bc14
 
888bc14
 /* Return the maximum of endtime and the endtime fields of all currently active
888bc14
@@ -965,7 +1001,7 @@ get_endtime(time_ms endtime, struct conn_state *conns)
888bc14
 static krb5_boolean
888bc14
 service_fds(krb5_context context, struct select_state *selstate,
888bc14
             time_ms interval, struct conn_state *conns,
888bc14
-            struct select_state *seltemp,
888bc14
+            struct select_state *seltemp, const krb5_data *realm,
888bc14
             int (*msg_handler)(krb5_context, const krb5_data *, void *),
888bc14
             void *msg_handler_data, struct conn_state **winner_out)
888bc14
 {
888bc14
@@ -977,7 +1013,7 @@ service_fds(krb5_context context, struct select_state *selstate,
888bc14
 
888bc14
     e = get_curtime_ms(&endtime);
888bc14
     if (e)
888bc14
-        return 1;
888bc14
+        return TRUE;
888bc14
     endtime += interval;
888bc14
 
888bc14
     e = 0;
888bc14
@@ -991,7 +1027,7 @@ service_fds(krb5_context context, struct select_state *selstate,
888bc14
 
888bc14
         if (selret == 0)
888bc14
             /* Timeout, return to caller.  */
888bc14
-            return 0;
888bc14
+            return FALSE;
888bc14
 
888bc14
         /* Got something on a socket, process it.  */
888bc14
         for (state = conns; state != NULL; state = state->next) {
888bc14
@@ -1003,7 +1039,7 @@ service_fds(krb5_context context, struct select_state *selstate,
888bc14
             if (!ssflags)
888bc14
                 continue;
888bc14
 
888bc14
-            if (state->service(context, state, selstate, ssflags)) {
888bc14
+            if (service_dispatch(context, realm, state, selstate, ssflags)) {
888bc14
                 int stop = 1;
888bc14
 
888bc14
                 if (msg_handler != NULL) {
888bc14
@@ -1014,14 +1050,14 @@ service_fds(krb5_context context, struct select_state *selstate,
888bc14
 
888bc14
                 if (stop) {
888bc14
                     *winner_out = state;
888bc14
-                    return 1;
888bc14
+                    return TRUE;
888bc14
                 }
888bc14
             }
888bc14
         }
888bc14
     }
888bc14
     if (e != 0)
888bc14
-        return 1;
888bc14
-    return 0;
888bc14
+        return TRUE;
888bc14
+    return FALSE;
888bc14
 }
888bc14
 
888bc14
 /*
888bc14
@@ -1052,7 +1088,8 @@ service_fds(krb5_context context, struct select_state *selstate,
888bc14
 
888bc14
 krb5_error_code
888bc14
 k5_sendto(krb5_context context, const krb5_data *message,
888bc14
-          const struct serverlist *servers, k5_transport_strategy strategy,
888bc14
+          const krb5_data *realm, const struct serverlist *servers,
888bc14
+          k5_transport_strategy strategy,
888bc14
           struct sendto_callback_info* callback_info, krb5_data *reply,
888bc14
           struct sockaddr *remoteaddr, socklen_t *remoteaddrlen,
888bc14
           int *server_used,
888bc14
@@ -1098,7 +1135,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
888bc14
             if (maybe_send(context, state, message, sel_state, callback_info))
888bc14
                 continue;
888bc14
             done = service_fds(context, sel_state, 1000, conns, seltemp,
888bc14
-                               msg_handler, msg_handler_data, &winner);
888bc14
+                               realm, msg_handler, msg_handler_data, &winner);
888bc14
         }
888bc14
     }
888bc14
 
888bc14
@@ -1110,13 +1147,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
888bc14
         if (maybe_send(context, state, message, sel_state, callback_info))
888bc14
             continue;
888bc14
         done = service_fds(context, sel_state, 1000, conns, seltemp,
888bc14
-                           msg_handler, msg_handler_data, &winner);
888bc14
+                           realm, msg_handler, msg_handler_data, &winner);
888bc14
     }
888bc14
 
888bc14
     /* Wait for two seconds at the end of the first pass. */
888bc14
     if (!done) {
888bc14
         done = service_fds(context, sel_state, 2000, conns, seltemp,
888bc14
-                           msg_handler, msg_handler_data, &winner);
888bc14
+                           realm, msg_handler, msg_handler_data, &winner);
888bc14
     }
888bc14
 
888bc14
     /* Make remaining passes over all of the connections. */
888bc14
@@ -1126,14 +1163,14 @@ k5_sendto(krb5_context context, const krb5_data *message,
888bc14
             if (maybe_send(context, state, message, sel_state, callback_info))
888bc14
                 continue;
888bc14
             done = service_fds(context, sel_state, 1000, conns, seltemp,
888bc14
-                               msg_handler, msg_handler_data, &winner);
888bc14
+                               realm, msg_handler, msg_handler_data, &winner);
888bc14
             if (sel_state->nfds == 0)
888bc14
                 break;
888bc14
         }
888bc14
         /* Wait for the delay backoff at the end of this pass. */
888bc14
         if (!done) {
888bc14
             done = service_fds(context, sel_state, delay, conns, seltemp,
888bc14
-                               msg_handler, msg_handler_data, &winner);
888bc14
+                               realm, msg_handler, msg_handler_data, &winner);
888bc14
         }
888bc14
         if (sel_state->nfds == 0)
888bc14
             break;
888bc14
-- 
888bc14
2.1.0
888bc14