]> The Tcpdump Group git mirrors - libpcap/commitdiff
Redo protocol version negotiation.
authorGuy Harris <[email protected]>
Thu, 31 Jan 2019 05:09:08 +0000 (21:09 -0800)
committerGuy Harris <[email protected]>
Thu, 31 Jan 2019 05:09:08 +0000 (21:09 -0800)
During the authentication phase, which begins when the connection is
made and ends when an authentication reply is received or the connection
is closed, require that all request have a version number of 0, and
accept version 0 in that phase, regardless of whether we support it once
we're authenticated.  That means the messages from the client will not
be rejected any server with an "unsupported version" error, and also
means we can distinguish between a plaintext request and a TLS handshake
message.

Have the server send out authentication replies with a payload giving
the minimum and maximum version number supported by the server.  Have
the client accept authentication replies whether or not they have that
additional information; if the reply has no payload, the server is
assumed to support only version 0.  This means that old servers that
don't supply that information, and new servers that do, can be handled
by the new client code; old clients discard extra payload, and only
support version 0 (no servers or clients supporting versions other than
0 have been released, yet), so they can also handle both old and new
servers.

The client then uses that information (sent or implied) to try to find
the highest version that it and the server supports.  If there is no
such version, it's impossible for the client and server to communicate
further, so the client just reports an error to its caller and gives up.
If there *is* such a version, the client then uses it in all subsequent
requests, and the server replies with the version in the request.

For data packets, the version used in the "start capture" request is
used.

This avoids timeouts or dropped connections with old servers due to the
initial request having an unsupported version number, and means that the
negotiation never requires two authentication requests.

pcap-rpcap.c
rpcap-protocol.h
rpcapd/daemon.c

index 839259e64e3974ee427d90d9c648be180e4bc8b0..c06864f9f86e79fb20cc0909d927cf9a6a0ad065 100644 (file)
@@ -163,7 +163,6 @@ static void pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter);
 static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog);
 static int pcap_setsampling_remote(pcap_t *fp);
 static int pcap_startcapture_remote(pcap_t *fp);
-static int rpcap_sendauth(SOCKET sock, SSL *, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf);
 static int rpcap_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *header, char *errbuf);
 static int rpcap_check_msg_ver(SOCKET sock, SSL *, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
 static int rpcap_check_msg_type(SOCKET sock, SSL *, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
@@ -1858,16 +1857,25 @@ static int pcap_setsampling_remote(pcap_t *fp)
 
 /*
  * This function performs authentication and protocol version
- * negotiation.  It first tries to authenticate with the maximum
- * version we support and, if that fails with an "I don't support
- * that version" error from the server, and the version number in
- * the reply from the server is one we support, tries again with
- * that version.
+ * negotiation.  It is required in order to open the connection
+ * with the other end party.
+ *
+ * It sends authentication parameters on the control socket and
+ * reads the reply.  If the reply is a success indication, it
+ * checks whether the reply includes minimum and maximum supported
+ * versions from the server; if not, it assumes both are 0, as
+ * that means it's an older server that doesn't return supported
+ * version numbers in authentication replies, so it only supports
+ * version 0.  It then tries to determine the maximum version
+ * supported both by us and by the server.  If it can find such a
+ * version, it sets us up to use that version; otherwise, it fails,
+ * indicating that there is no version supported by us and by the
+ * server.
  *
  * \param sock: the socket we are currently using.
  *
- * \param ver: pointer to variable holding protocol version number to send
- * and to set to the protocol version number in the reply.
+ * \param ver: pointer to variable to which to set the protocol version
+ * number we selected.
  *
  * \param auth: authentication parameters that have to be sent.
  *
@@ -1880,96 +1888,17 @@ static int pcap_setsampling_remote(pcap_t *fp)
  * an error message string is returned in the 'errbuf' variable.
  */
 static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
-{
-       int status;
-
-       /*
-        * Send authentication to the remote machine.
-        *
-        * First try with the maximum version number we support.
-        */
-       *ver = RPCAP_MAX_VERSION;
-       status = rpcap_sendauth(sockctrl, ssl, ver, auth, errbuf);
-       if (status == 0)
-       {
-               //
-               // Success.
-               //
-               return 0;
-       }
-       if (status == -1)
-       {
-               /* Unrecoverable error. */
-               return -1;
-       }
-
-       /*
-        * The server doesn't support the version we used in the initial
-        * message, and it sent us back a reply either with the maximum
-        * version they do support, or with the version we sent, and we
-        * support that version.  *ver has been set to that version; try
-        * authenticating again with that version.
-        */
-       status = rpcap_sendauth(sockctrl, ssl, ver, auth, errbuf);
-       if (status == 0)
-       {
-               //
-               // Success.
-               //
-               return 0;
-       }
-       if (status == -1)
-       {
-               /* Unrecoverable error. */
-               return -1;
-       }
-       if (status == -2)
-       {
-               /*
-                * The server doesn't support that version, which
-                * means there is no version we both support, so
-                * this is a fatal error.
-                */
-               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
-               return -1;
-       }
-       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "rpcap_sendauth() returned %d", status);
-       return -1;
-}
-
-/*
- * This function sends the authentication message.
- *
- * It sends the authentication parameters on the control socket.
- * It is required in order to open the connection with the other end party.
- *
- * \param sock: the socket we are currently using.
- *
- * \param ver: pointer to variable holding protocol version number to send
- * and to set to the protocol version number in the reply.
- *
- * \param auth: authentication parameters that have to be sent.
- *
- * \param errbuf: a pointer to a user-allocated buffer (of size
- * PCAP_ERRBUF_SIZE) that will contain the error message (in case there
- * is one). It could be a network problem or the fact that the authorization
- * failed.
- *
- * \return '0' if everything is fine, '-2' if the server didn't reply with
- * the protocol version we requested but replied with a version we do
- * support, or '-1' for other errors.  For errors, an error message string
- * is returned in the 'errbuf' variable.
- */
-static int rpcap_sendauth(SOCKET sock, SSL *ssl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
 {
        char sendbuf[RPCAP_NETBUF_SIZE];        /* temporary buffer in which data that has to be sent is buffered */
        int sendbufidx = 0;                     /* index which keeps the number of bytes currently buffered */
        uint16 length;                          /* length of the payload of this message */
-       uint16 errcode;
        struct rpcap_auth *rpauth;
        uint16 auth_type;
        struct rpcap_header header;
        size_t str_length;
+       uint32 plen;
+       struct rpcap_authreply authreply;       /* authentication reply message */
+       uint8 ourvers;
 
        if (auth)
        {
@@ -2016,12 +1945,11 @@ static int rpcap_sendauth(SOCKET sock, SSL *ssl, uint8 *ver, struct pcap_rmtauth
                length = sizeof(struct rpcap_auth);
        }
 
-
        if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
                &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
                return -1;
 
-       rpcap_createhdr((struct rpcap_header *) sendbuf, *ver,
+       rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
            RPCAP_MSG_AUTH_REQ, 0, length);
 
        rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
@@ -2058,62 +1986,102 @@ static int rpcap_sendauth(SOCKET sock, SSL *ssl, uint8 *ver, struct pcap_rmtauth
                rpauth->slen2 = htons(rpauth->slen2);
        }
 
-       if (sock_send(sock, ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+       if (sock_send(sockctrl, ssl, sendbuf, sendbufidx, errbuf,
+           PCAP_ERRBUF_SIZE) < 0)
                return -1;
 
-       /* Receive the reply */
-       if (rpcap_recv_msg_header(sock, ssl, &header, errbuf) == -1)
+       /* Receive and process the reply message header */
+       if (rpcap_process_msg_header(sockctrl, ssl, 0, RPCAP_MSG_AUTH_REQ,
+           &header, errbuf) == -1)
                return -1;
 
-       if (rpcap_check_msg_type(sock, ssl, RPCAP_MSG_AUTH_REQ, &header,
-           &errcode, errbuf) == -1)
+       /*
+        * OK, it's an authentication reply, so we're logged in.
+        *
+        * Did it send any additional information?
+        */
+       plen = header.plen;
+       if (plen != 0)
        {
-               /* Error message - or something else, which is a protocol error. */
-               if (header.type == RPCAP_MSG_ERROR &&
-                   errcode == PCAP_ERR_WRONGVER)
+               /* Yes - is it big enough to be version information? */
+               if (plen < sizeof(struct rpcap_authreply))
                {
-                       /*
-                        * The server didn't support the version we sent,
-                        * and replied with the maximum version it supports
-                        * if our version was too big or with the version
-                        * we sent if out version was too small.
-                        *
-                        * Do we also support it?
-                        */
-                       if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
-                       {
-                               /*
-                                * No, so there's no version we both support.
-                                * This is an unrecoverable error.
-                                */
-                               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The server doesn't support any protocol version that we support");
-                               return -1;
-                       }
+                       /* No - discard it and fail. */
+                       (void)rpcap_discard(sockctrl, ssl, plen, NULL);
+                       return -1;
+               }
 
-                       /*
-                        * OK, use that version, and tell our caller to
-                        * try again.
-                        */
-                       *ver = header.ver;
-                       return -2;
+               /* Read the reply body */
+               if (rpcap_recv(sockctrl, ssl, (char *)&authreply,
+                   sizeof(struct rpcap_authreply), &plen, errbuf) == -1)
+               {
+                       (void)rpcap_discard(sockctrl, ssl, plen, NULL);
+                       return -1;
                }
 
+               /* Discard the rest of the message, if there is any. */
+               if (rpcap_discard(sockctrl, ssl, plen, errbuf) == -1)
+                       return -1;
+
                /*
-                * Other error - unrecoverable.
+                * Check the minimum and maximum versions for sanity;
+                * the minimum must be <= the maximum.
                 */
-               return -1;
+               if (authreply.minvers > authreply.maxvers)
+               {
+                       /*
+                        * Bogus - give up on this server.
+                        */
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+                           "The server's minimum supported protocol version is greater than its maximum supported protocol version");
+                       return -1;
+               }
+       }
+       else
+       {
+               /* No - it supports only version 0. */
+               authreply.minvers = 0;
+               authreply.maxvers = 0;
        }
 
        /*
-        * OK, it's an authentication reply, so they're OK with the
-        * protocol version we sent.
-        *
-        * Discard the rest of it.
+        * OK, let's start with the maximum version the server supports.
         */
-       if (rpcap_discard(sock, ssl, header.plen, errbuf) == -1)
-               return -1;
+       ourvers = authreply.maxvers;
+
+       /*
+        * If that's less than the minimum version we support, we
+        * can't communicate.
+        */
+       if (ourvers < RPCAP_MIN_VERSION)
+               goto novers;
 
+       /*
+        * If that's greater than the maximum version we support,
+        * choose the maximum version we support.
+        */
+       if (ourvers > RPCAP_MAX_VERSION)
+       {
+               ourvers = RPCAP_MAX_VERSION;
+
+               /*
+                * If that's less than the minimum version they
+                * support, we can't communicate.
+                */
+               if (ourvers < authreply.minvers)
+                       goto novers;
+       }
+
+       *ver = ourvers;
        return 0;
+
+novers:
+       /*
+        * There is no version we both support; that is a fatal error.
+        */
+       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+           "The server doesn't support any protocol version that we support");
+       return -1;
 }
 
 /* We don't currently support non-blocking mode. */
index af966a7b0cf459f5f682399c5372c86abe8a2eed..0c8bf24db0e120057f7cb84146ce9e3d0d56eb85 100644 (file)
  *
  * Version negotiation is done as part of the authentication process:
  *
- * The client sends an authentication request, with the version number
- * in the request being the maximum version it supports.
- *
- * If the server supports that version, it attempts to authenticate the
- * client, and replies as appropriate, with the version number in the
- * reply being that version.
- *
- * If the server doesn't support that version because it's too large,
- * it replies with a RPCAP_MSG_ERROR message, with the maximum version
- * they support as the version number in the reply, and with the error
- * code being PCAP_ERR_WRONGVER.
- *
- * If the server doesn't support that version because it's too small,
- * it replies with a RPCAP_MSG_ERROR message, with that version as
- * the version number in the reply, and with the error code being
- * PCAP_ERR_WRONGVER.
- *
- * If the client supports that version, it retries the authentication
- * with that version and, if that fails for any reason, including
- * PCAP_ERR_WRONGVER, fails.  Otherwise, it fails, telling its caller
- * that there's no version that both support.
- *
- * This requires that the set of versions supported by a client or
- * server be a range of integers, with no gaps.  Thus:
- *
- * the client's version set is [Cmin, Cmax], with Cmin <= Cmax;
- *
- * the server's version set is [Smin, Smax], with Smin <= Smax;
- *
- * the client sends Cmax as the version number in the initial
- * authentication request;
- *
- * if the server doesn't support the version sent by the client,
- * either Smax < Cmax or Smin > Cmax (because the client sent Cmax
- * to the server, and the server doesn't support it);
- *
- * if Smax < Cmax:
- *
- *    the server sends Smax as the version number in the RPCAP_MSG_ERROR/
- *    PCAP_ERR_WRONGVER message - the client will accept this because
- *    Cmax != 0, as these numbers are unsigned, and this means that
- *    this isn't an old client that rejects all messages with a non-zero
- *    version number, it's a new client that accepts RPCAP_MSG_ERROR
- *    messages no matter what the version is;
- *
- *    if Smax >= Cmin, both the client and the server can use it, and
- *    the client retries with Smax;
- *
- *    if Smax < Cmin, there is no version the client and server can
- *    both support.
- *
- * if Smin > Cmax:
- *
- *    the server sends Cmax as the version number in the RPCAP_MSG_ERROR/
- *    PCAP_ERR_WRONGVER message - the client will accept this because
- *    Cmax is a valid client version number.
- *
- *    the client will retry with Cmax, get the same version failure,
- *    and report that there is no version the client and server can
- *    both support (as the version sets are disjoint).
- *
- * Old negotiation-unaware clients just send version 0 and, if they
- * get back PCAP_ERR_WRONGVER, treat it as a fatal error.  This
- * means they'll fail to talk to any server that can't handle
- * version 0, which is the appropriate thing to do, as they can
- * only use version 0.
- *
- * Old negotiation-unaware servers fail if they get a version other
- * than 0, sending back PCAP_ERR_WRONGVER with version 0, which is
- * the only version, and thus both the minimum and maximum version,
- * they support.  The client will either fail if it doesn't support
- * version 0, or will retry with version 0 and succeed, so it will
- * fail with servers that can't handle version 0 or will negotiate
- * version 0 with servers that can handle version 0.
+ * The client sends an authentication request, with a version number
+ * of 0.  All servers must accept authentication requests with a version
+ * number of 0, even if they don't support version 0 for any other
+ * requests.
+ *
+ * The server attempts to authenticate the client.  If that succeeds,
+ * older servers - which only support version 0 - will send an
+ * authentication reply with no payload.  Newer servers - which might
+ * support other versions - will send an authentication reply with
+ * a payload giving the minimum and maximum versions it supports.
+ *
+ * The client attempts to find the largest version number that is
+ * in both its range of supported versions and the server's supported
+ * versions.  If it fails, it gives up; otherwise, it uses that version.
  */
 #define RPCAP_MIN_VERSION 0
 #define RPCAP_MAX_VERSION 0
 
-/*
- * So that the server can distinguish between a non-TLS rpcapd
- * message, the first byte of which is the version number, and
- * a TLS client hello, the first byte of which is 22, we don't
- * allow 22 as an rpcap version number.
- */
-#define RPCAP_UNUSED_VERSION 22
-
-/*
- * Make sure nobody makes the mistake of making the "must not use" version
- * the minimum or maximum version; we *must* allow at least one version
- * other than that version.
- */
-#if RPCAP_MIN_VERSION == RPCAP_UNUSED_VERSION
-  #error Minimum protocol version is a version that must not be used
-#elif RPCAP_MAX_VERSION == RPCAP_UNUSED_VERSION
-  #error Maximum protocol version is a version that must not be used
-#endif
-
 /*
  * Version numbers are unsigned, so if RPCAP_MIN_VERSION is 0, they
  * are >= the minimum version, by definition; don't check against
  * RPCAP_MIN_VERSION, as you may get compiler warnings that the
  * comparison will always succeed.
- *
- * We *never* allow version RPCAP_UNUSED_VERSION, even if it's
- * otherwise in the allowed range.
  */
 #if RPCAP_MIN_VERSION == 0
 #define RPCAP_VERSION_IS_SUPPORTED(v)  \
-       ((v) <= RPCAP_MAX_VERSION && (v) != RPCAP_UNUSED_VERSION)
+       ((v) <= RPCAP_MAX_VERSION)
 #else
 #define RPCAP_VERSION_IS_SUPPORTED(v)  \
-       ((v) >= RPCAP_MIN_VERSION && (v) <= RPCAP_MAX_VERSION && \
-        (v) != RPCAP_UNUSED_VERSION)
+       ((v) >= RPCAP_MIN_VERSION && (v) <= RPCAP_MAX_VERSION)
 #endif
 
 /*
@@ -229,6 +146,19 @@ struct rpcap_header
        uint32 plen;    /* Length of the payload of this RPCAP message */
 };
 
+/*
+ * Format of data that may appear at the end of an authentication reply,
+ * giving the minimum and maximum versions of the protocol that the
+ * server supports.
+ *
+ * Older servers don't provide this; they support only version 0.
+ */
+struct rpcap_authreply
+{
+       uint8 minvers;  /* Minimum version supported */
+       uint8 maxvers;  /* Maximum version supported */
+};
+
 /* Format of the message for the interface description (findalldevs command) */
 struct rpcap_findalldevs_if
 {
index edc736aee808a645b7d221ebdd767f4be0a5c23f..4f6c5a3b6c105157f4421d26c2049b1e138c7529 100644 (file)
@@ -97,7 +97,6 @@ struct daemon_slpars
 {
        SOCKET sockctrl;        //!< SOCKET ID of the control connection
        SSL *ssl;               //!< Optional SSL handler for the controlling sockets
-       uint8 protocol_version; //!< negotiated protocol version
        int isactive;           //!< Not null if the daemon has to run in active mode
        int nullAuthAllowed;    //!< '1' if we permit NULL authentication, '0' otherwise
 };
@@ -130,18 +129,27 @@ static int daemon_msg_err(SOCKET sockctrl, SSL *, uint32 plen);
 static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
 static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
 
-static int daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen);
+static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen);
 
-static int daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen);
-static int daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, char *source, struct session **sessionp, struct rpcap_sampling *samp_param, int uses_ssl);
-static int daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session);
+static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, size_t sourcelen);
+static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param, int uses_ssl);
+static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session);
 
-static int daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen);
+static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen);
 static int daemon_unpackapplyfilter(SOCKET sockctrl, SSL *, struct session *session, uint32 *plenp, char *errbuf);
 
-static int daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt);
+static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt);
 
-static int daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap_sampling *samp_param);
+static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
+    uint32 plen, struct rpcap_sampling *samp_param);
 
 static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
 #ifdef _WIN32
@@ -232,11 +240,12 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
        // a TLS handshake message or a non-TLS rpcapd message.
        //
        // The first byte of an rpcapd request is the version number;
-       // the first byte of a TLS handshake message is 22.  We
-       // permanently reserve an rpcapd version number of 22, so that
-       // we can distinguish between rpcapd messages and TLS handshake
-       // messages; if we ever get to rpcapd version 21, and want to
-       // introduce a new version after that, we'll jump to version 23.
+       // the first byte of a TLS handshake message is 22.  The
+       // first request to an rpcapd server must be an authentication
+       // request or a close request, and must have a version number
+       // of 0, so it will be possible to distinguish between an
+       // initial plaintext request to a server and an initial TLS
+       // handshake message.
        //
        nrecv = sock_recv(sockctrl, NULL, (char *)&first_octet, 1,
            SOCK_EOF_ISNT_ERROR|SOCK_MSG_PEEK, errbuf, PCAP_ERRBUF_SIZE);
@@ -397,7 +406,6 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
        // Set parameters structure
        pars.sockctrl = sockctrl;
        pars.ssl = ssl;
-       pars.protocol_version = 0;              // not yet known
        pars.isactive = isactive;               // active mode
        pars.nullAuthAllowed = nullAuthAllowed;
 
@@ -536,49 +544,17 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                plen = header.plen;
 
                //
-               // Did the client specify a version we can handle?
+               // While we're in the authentication pharse, all requests
+               // must use version 0.
                //
-               if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+               if (header.ver != 0)
                {
                        //
-                       // Tell them it's not a valid protocol version.
-                       //
-                       uint8 reply_version;
-
-                       //
-                       // If RPCAP_MIN_VERSION is 0, no version is too
-                       // old, as the oldest supported version is 0,
-                       // and there are no negative versions.
+                       // Send it back to them with their version.
                        //
-#if RPCAP_MIN_VERSION != 0
-                       if (header.ver < RPCAP_MIN_VERSION)
-                       {
-                               //
-                               // Their maximum version is too old;
-                               // there *is* no version we can both
-                               // handle, and they might reject
-                               // an error with a version they don't
-                               // understand, so reply with the
-                               // version they sent.  That may
-                               // make them retry with that version,
-                               // but they'll give up on that
-                               // failure.
-                               //
-                               reply_version = header.ver;
-                       }
-                       else
-#endif
-                       {
-                               //
-                               // Their maximum version is too new,
-                               // but they might be able to handle
-                               // *our* maximum version, so reply
-                               // with that version.
-                               //
-                               reply_version = RPCAP_MAX_VERSION;
-                       }
-                       if (rpcap_senderror(pars.sockctrl, pars.ssl, reply_version,
-                           PCAP_ERR_WRONGVER, "RPCAP version number mismatch",
+                       if (rpcap_senderror(pars.sockctrl, pars.ssl, header.ver,
+                           PCAP_ERR_WRONGVER,
+                           "RPCAP version in requests in the authentication phase must be 0",
                            errbuf) == -1)
                        {
                                // That failed; log a message and give up.
@@ -586,22 +562,12 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                goto end;
                        }
 
-                       // Discard the rest of the message.
-                       if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
-                       {
-                               // Network error.
-                               goto end;
-                       }
-
-                       // Let them try again.
-                       continue;
+                       // Discard the rest of the message and drop the
+                       // connection.
+                       (void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
+                       goto end;
                }
 
-               //
-               // OK, we use the version the client specified.
-               //
-               pars.protocol_version = header.ver;
-
                switch (header.type)
                {
                        case RPCAP_MSG_AUTH_REQ:
@@ -667,7 +633,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
                                }
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_WRONGMSG,
+                                   header.ver, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -703,7 +669,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
                                }
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_WRONGMSG,
+                                   header.ver, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -723,7 +689,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                //
                                pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_WRONGMSG,
+                                   header.ver, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -783,7 +749,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                        {
                                sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_NETW,
+                                   header.ver, PCAP_ERR_NETW,
                                    errmsgbuf, errbuf) == -1)
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                                goto end;
@@ -794,7 +760,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                        if (retval == 0)
                        {
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version,
+                                   header.ver,
                                    PCAP_ERR_INITTIMEOUT,
                                    "The RPCAP initial timeout has expired",
                                    errbuf) == -1)
@@ -821,21 +787,20 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                plen = header.plen;
 
                //
-               // Did the client specify the version we negotiated?
+               // Did the client specify a protocol version that we
+               // support?
                //
-               // For now, there's only one version.
-               //
-               if (header.ver != pars.protocol_version)
+               if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
                {
                        //
-                       // Tell them it's not the negotiated version.
+                       // Tell them it's not a supported version.
                        // Send the error message with their version,
                        // so they don't reject it as having the wrong
                        // version.
                        //
                        if (rpcap_senderror(pars.sockctrl, pars.ssl,
                            header.ver, PCAP_ERR_WRONGVER,
-                           "RPCAP version in message isn't the negotiated version",
+                           "RPCAP version in message isn't supported by the server",
                            errbuf) == -1)
                        {
                                // That failed; log a message and give up.
@@ -861,7 +826,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
 
                        case RPCAP_MSG_FINDALLIF_REQ:
                        {
-                               if (daemon_msg_findallif_req(&pars, plen) == -1)
+                               if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
                                {
                                        // Fatal error; a message has
                                        // been logged, so just give up.
@@ -881,7 +846,8 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                // us multiple open requests, the last
                                // one wins.
                                //
-                               retval = daemon_msg_open_req(&pars, plen, source, sizeof(source));
+                               retval = daemon_msg_open_req(header.ver, &pars,
+                                   plen, source, sizeof(source));
                                if (retval == -1)
                                {
                                        // Fatal error; a message has
@@ -899,7 +865,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                        // They never told us what device
                                        // to capture on!
                                        if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                           pars.protocol_version,
+                                           header.ver,
                                            PCAP_ERR_STARTCAPTURE,
                                            "No capture device was specified",
                                            errbuf) == -1)
@@ -916,7 +882,9 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                        break;
                                }
 
-                               if (daemon_msg_startcap_req(&pars, plen, source, &session, &samp_param, uses_ssl) == -1)
+                               if (daemon_msg_startcap_req(header.ver, &pars,
+                                   plen, source, &session, &samp_param,
+                                   uses_ssl) == -1)
                                {
                                        // Fatal error; a message has
                                        // been logged, so just give up.
@@ -929,7 +897,8 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                        {
                                if (session)
                                {
-                                       if (daemon_msg_updatefilter_req(&pars, session, plen) == -1)
+                                       if (daemon_msg_updatefilter_req(header.ver,
+                                           &pars, session, plen) == -1)
                                        {
                                                // Fatal error; a message has
                                                // been logged, so just give up.
@@ -939,7 +908,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                else
                                {
                                        if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                           pars.protocol_version,
+                                           header.ver,
                                            PCAP_ERR_UPDATEFILTER,
                                            "Device not opened. Cannot update filter",
                                            errbuf) == -1)
@@ -966,7 +935,8 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
 
                        case RPCAP_MSG_STATS_REQ:
                        {
-                               if (daemon_msg_stats_req(&pars, session, plen, &stats, svrcapt) == -1)
+                               if (daemon_msg_stats_req(header.ver, &pars,
+                                   session, plen, &stats, svrcapt) == -1)
                                {
                                        // Fatal error; a message has
                                        // been logged, so just give up.
@@ -992,7 +962,8 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                                svrcapt = 0;
                                        }
 
-                                       if (daemon_msg_endcap_req(&pars, session) == -1)
+                                       if (daemon_msg_endcap_req(header.ver,
+                                           &pars, session) == -1)
                                        {
                                                free(session);
                                                session = NULL;
@@ -1006,7 +977,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                else
                                {
                                        rpcap_senderror(pars.sockctrl, pars.ssl,
-                                           pars.protocol_version,
+                                           header.ver,
                                            PCAP_ERR_ENDCAPTURE,
                                            "Device not opened. Cannot close the capture",
                                            errbuf);
@@ -1016,7 +987,8 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
 
                        case RPCAP_MSG_SETSAMPLING_REQ:
                        {
-                               if (daemon_msg_setsampling_req(&pars, plen, &samp_param) == -1)
+                               if (daemon_msg_setsampling_req(header.ver,
+                                   &pars, plen, &samp_param) == -1)
                                {
                                        // Fatal error; a message has
                                        // been logged, so just give up.
@@ -1033,7 +1005,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                //
                                rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version,
+                                   header.ver,
                                    PCAP_ERR_WRONGMSG,
                                    "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
                                    errbuf) == -1)
@@ -1073,7 +1045,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
                                }
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_WRONGMSG,
+                                   header.ver, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1094,7 +1066,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
                                rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
                                pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
                                if (rpcap_senderror(pars.sockctrl, pars.ssl,
-                                   pars.protocol_version, PCAP_ERR_WRONGMSG,
+                                   header.ver, PCAP_ERR_WRONGMSG,
                                    errbuf, errmsgbuf) == -1)
                                {
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1228,9 +1200,11 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
-       struct rpcap_header header;             // RPCAP message general header
        int status;
        struct rpcap_auth auth;                 // RPCAP authentication header
+       char sendbuf[RPCAP_NETBUF_SIZE];        // temporary buffer in which data to be sent is buffered
+       int sendbufidx = 0;                     // index which keeps the number of bytes currently buffered
+       struct rpcap_authreply *authreply;      // authentication reply message
 
        status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
        if (status == -1)
@@ -1314,8 +1288,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
                                free(username);
                                free(passwd);
                                if (rpcap_senderror(pars->sockctrl, pars->ssl,
-                                   pars->protocol_version,
-                                   PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+                                   0, PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
                                {
                                        // That failed; log a message and give up.
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1347,10 +1320,28 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        }
 
        // The authentication succeeded; let the client know.
-       rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_AUTH_REPLY, 0, 0);
+       if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
 
-       // Send the ok message back
-       if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
+           RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
+
+       authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
+
+       if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
+           RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+               goto error;
+
+       //
+       // Indicate to our peer what versions we support.
+       //
+       memset(authreply, 0, sizeof(struct rpcap_authreply));
+       authreply->minvers = RPCAP_MIN_VERSION;
+       authreply->maxvers = RPCAP_MAX_VERSION;
+
+       // Send the reply.
+       if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                // That failed; log a messsage and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1366,8 +1357,8 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
-           PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+       if (rpcap_senderror(pars->sockctrl, pars->ssl, 0, PCAP_ERR_AUTH,
+           errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1498,7 +1489,7 @@ daemon_AuthUserPwd(char *username, char *password, char *errbuf)
 }
 
 static int
-daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
+daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -1523,7 +1514,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
 
        if (alldevs == NULL)
        {
-               if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
+               if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
                        PCAP_ERR_NOREMOTEIF,
                        "No interfaces found! Make sure libpcap/WinPcap is properly installed"
                        " and you have the right to access to the remote device.",
@@ -1573,7 +1564,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
            PCAP_ERRBUF_SIZE) == -1)
                goto error;
 
-       rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
            RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
 
        // send the interface list
@@ -1689,7 +1680,7 @@ error:
        if (alldevs)
                pcap_freealldevs(alldevs);
 
-       if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
            PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1)
        {
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1703,7 +1694,8 @@ error:
        to discard excess data in the message, if present)
 */
 static int
-daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen)
+daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, size_t sourcelen)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -1746,7 +1738,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_
            RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
                goto error;
 
-       rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
            RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
 
        openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
@@ -1778,8 +1770,8 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
-           PCAP_ERR_OPEN, errmsgbuf, errbuf) == -1)
+       if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_OPEN,
+           errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1799,7 +1791,9 @@ error:
        to discard excess data in the message, if present)
 */
 static int
-daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, char *source, struct session **sessionp, struct rpcap_sampling *samp_param _U_, int uses_ssl)
+daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    char *source, struct session **sessionp,
+    struct rpcap_sampling *samp_param _U_, int uses_ssl)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -1968,7 +1962,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, char *source, s
        // Needed to send an error on the ctrl connection
        session->sockctrl = pars->sockctrl;
        session->ctrl_ssl = pars->ssl;
-       session->protocol_version = pars->protocol_version;
+       session->protocol_version = ver;
 
        // Now I can set the filter
        ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
@@ -1988,7 +1982,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, char *source, s
            RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
                goto error;
 
-       rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
            RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
 
        startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
@@ -2096,7 +2090,7 @@ error:
                free(session);
        }
 
-       if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
            PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
@@ -2130,15 +2124,15 @@ fatal_error:
 }
 
 static int
-daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session)
+daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        struct rpcap_header header;
 
        session_close(session);
 
-       rpcap_createhdr(&header, pars->protocol_version,
-           RPCAP_MSG_ENDCAP_REPLY, 0, 0);
+       rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
 
        if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
@@ -2229,7 +2223,8 @@ daemon_unpackapplyfilter(SOCKET sockctrl, SSL *ctrl_ssl, struct session *session
 }
 
 static int
-daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen)
+daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen)
 {
        char errbuf[PCAP_ERRBUF_SIZE];
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -2256,8 +2251,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session,
        }
 
        // A response is needed, otherwise the other host does not know that everything went well
-       rpcap_createhdr(&header, pars->protocol_version,
-           RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
+       rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
 
        if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
        {
@@ -2273,8 +2267,8 @@ error:
        {
                return -1;
        }
-       rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
-           PCAP_ERR_UPDATEFILTER, errmsgbuf, NULL);
+       rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_UPDATEFILTER,
+           errmsgbuf, NULL);
 
        return 0;
 }
@@ -2283,7 +2277,8 @@ error:
        \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
 */
 static int
-daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap_sampling *samp_param)
+daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+    struct rpcap_sampling *samp_param)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];
@@ -2306,8 +2301,7 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap
        samp_param->value = ntohl(rpcap_samp.value);
 
        // A response is needed, otherwise the other host does not know that everything went well
-       rpcap_createhdr(&header, pars->protocol_version,
-           RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
+       rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
 
        if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
@@ -2324,8 +2318,8 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
-           PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
+       if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_AUTH,
+           errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -2342,7 +2336,9 @@ error:
 }
 
 static int
-daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt)
+daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+    struct session *session, uint32 plen, struct pcap_stat *stats,
+    unsigned int svrcapt)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -2361,7 +2357,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32
            &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
                goto error;
 
-       rpcap_createhdr((struct rpcap_header *) sendbuf, pars->protocol_version,
+       rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
            RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
 
        netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
@@ -2404,8 +2400,8 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32
        return 0;
 
 error:
-       rpcap_senderror(pars->sockctrl, pars->ssl, pars->protocol_version,
-           PCAP_ERR_GETSTATS, errmsgbuf, NULL);
+       rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_GETSTATS,
+           errmsgbuf, NULL);
        return 0;
 }