Commit 5fcef1ca authored by Martin Sustrik's avatar Martin Sustrik

ZMQ_MAXMSGSIZE option added

The new option allows user to guard against peers sending
oversized messages. Connection to peer sending oversized message
is dropped.
Signed-off-by: 's avatarMartin Sustrik <sustrik@250bpm.com>
parent 4c744621
...@@ -311,6 +311,20 @@ Default value:: 100 ...@@ -311,6 +311,20 @@ Default value:: 100
Applicable socket types:: all, only for connection-oriented transports Applicable socket types:: all, only for connection-oriented transports
ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The options shall retrieve limit for the inbound messages. If a peer sends
a message larger than ZMQ_MAXMSGSIZE it is disconnected. Value of -1 means
'no limit'.
[horizontal]
Option value type:: int64_t
Option value unit:: bytes
Default value:: -1
Applicable socket types:: all
ZMQ_FD: Retrieve file descriptor associated with the socket ZMQ_FD: Retrieve file descriptor associated with the socket
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'ZMQ_FD' option shall retrieve the file descriptor associated with the The 'ZMQ_FD' option shall retrieve the file descriptor associated with the
......
...@@ -319,6 +319,18 @@ Option value unit:: connections ...@@ -319,6 +319,18 @@ Option value unit:: connections
Default value:: 100 Default value:: 100
Applicable socket types:: all, only for connection-oriented transports. Applicable socket types:: all, only for connection-oriented transports.
ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Limits the size of the inbound message. If a peer sends a message larger than
ZMQ_MAXMSGSIZE it is disconnected. Value of -1 means 'no limit'.
[horizontal]
Option value type:: int64_t
Option value unit:: bytes
Default value:: -1
Applicable socket types:: all
RETURN VALUE RETURN VALUE
------------ ------------
......
...@@ -204,6 +204,7 @@ ZMQ_EXPORT int zmq_term (void *context); ...@@ -204,6 +204,7 @@ ZMQ_EXPORT int zmq_term (void *context);
#define ZMQ_BACKLOG 19 #define ZMQ_BACKLOG 19
#define ZMQ_RECOVERY_IVL_MSEC 20 /* opt. recovery time, reconcile in 3.x */ #define ZMQ_RECOVERY_IVL_MSEC 20 /* opt. recovery time, reconcile in 3.x */
#define ZMQ_RECONNECT_IVL_MAX 21 #define ZMQ_RECONNECT_IVL_MAX 21
#define ZMQ_MAXMSGSIZE 22
/* Send/recv options. */ /* Send/recv options. */
#define ZMQ_NOBLOCK 1 #define ZMQ_NOBLOCK 1
......
...@@ -25,9 +25,10 @@ ...@@ -25,9 +25,10 @@
#include "wire.hpp" #include "wire.hpp"
#include "err.hpp" #include "err.hpp"
zmq::decoder_t::decoder_t (size_t bufsize_) : zmq::decoder_t::decoder_t (size_t bufsize_, int64_t maxmsgsize_) :
decoder_base_t <decoder_t> (bufsize_), decoder_base_t <decoder_t> (bufsize_),
destination (NULL) destination (NULL),
maxmsgsize (maxmsgsize_)
{ {
zmq_msg_init (&in_progress); zmq_msg_init (&in_progress);
...@@ -63,7 +64,13 @@ bool zmq::decoder_t::one_byte_size_ready () ...@@ -63,7 +64,13 @@ bool zmq::decoder_t::one_byte_size_ready ()
// in_progress is initialised at this point so in theory we should // in_progress is initialised at this point so in theory we should
// close it before calling zmq_msg_init_size, however, it's a 0-byte // close it before calling zmq_msg_init_size, however, it's a 0-byte
// message and thus we can treat it as uninitialised... // message and thus we can treat it as uninitialised...
int rc = zmq_msg_init_size (&in_progress, *tmpbuf - 1); int rc;
if (maxmsgsize >= 0 && (int64_t) (*tmpbuf - 1) > maxmsgsize) {
rc = -1;
errno = ENOMEM;
}
else
rc = zmq_msg_init_size (&in_progress, *tmpbuf - 1);
if (rc != 0 && errno == ENOMEM) { if (rc != 0 && errno == ENOMEM) {
rc = zmq_msg_init (&in_progress); rc = zmq_msg_init (&in_progress);
errno_assert (rc == 0); errno_assert (rc == 0);
...@@ -92,7 +99,13 @@ bool zmq::decoder_t::eight_byte_size_ready () ...@@ -92,7 +99,13 @@ bool zmq::decoder_t::eight_byte_size_ready ()
// in_progress is initialised at this point so in theory we should // in_progress is initialised at this point so in theory we should
// close it before calling zmq_msg_init_size, however, it's a 0-byte // close it before calling zmq_msg_init_size, however, it's a 0-byte
// message and thus we can treat it as uninitialised... // message and thus we can treat it as uninitialised...
int rc = zmq_msg_init_size (&in_progress, size - 1); int rc;
if (maxmsgsize >= 0 && (int64_t) (size - 1) > maxmsgsize) {
rc = -1;
errno = ENOMEM;
}
else
rc = zmq_msg_init_size (&in_progress, size - 1);
if (rc != 0 && errno == ENOMEM) { if (rc != 0 && errno == ENOMEM) {
rc = zmq_msg_init (&in_progress); rc = zmq_msg_init (&in_progress);
errno_assert (rc == 0); errno_assert (rc == 0);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <algorithm> #include <algorithm>
#include "err.hpp" #include "err.hpp"
#include "stdint.hpp"
#include "../include/zmq.h" #include "../include/zmq.h"
...@@ -180,7 +181,7 @@ namespace zmq ...@@ -180,7 +181,7 @@ namespace zmq
{ {
public: public:
decoder_t (size_t bufsize_); decoder_t (size_t bufsize_, int64_t maxmsgsize_);
~decoder_t (); ~decoder_t ();
void set_inout (struct i_inout *destination_); void set_inout (struct i_inout *destination_);
...@@ -196,6 +197,8 @@ namespace zmq ...@@ -196,6 +197,8 @@ namespace zmq
unsigned char tmpbuf [8]; unsigned char tmpbuf [8];
::zmq_msg_t in_progress; ::zmq_msg_t in_progress;
int64_t maxmsgsize;
decoder_t (const decoder_t&); decoder_t (const decoder_t&);
void operator = (const decoder_t&); void operator = (const decoder_t&);
}; };
......
...@@ -39,6 +39,7 @@ zmq::options_t::options_t () : ...@@ -39,6 +39,7 @@ zmq::options_t::options_t () :
reconnect_ivl (100), reconnect_ivl (100),
reconnect_ivl_max (0), reconnect_ivl_max (0),
backlog (100), backlog (100),
maxmsgsize (-1),
requires_in (false), requires_in (false),
requires_out (false), requires_out (false),
immediate_connect (true) immediate_connect (true)
...@@ -182,6 +183,14 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -182,6 +183,14 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
backlog = *((int*) optval_); backlog = *((int*) optval_);
return 0; return 0;
case ZMQ_MAXMSGSIZE:
if (optvallen_ != sizeof (int64_t)) {
errno = EINVAL;
return -1;
}
maxmsgsize = *((int64_t*) optval_);
return 0;
} }
errno = EINVAL; errno = EINVAL;
...@@ -328,6 +337,15 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) ...@@ -328,6 +337,15 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
*optvallen_ = sizeof (int); *optvallen_ = sizeof (int);
return 0; return 0;
case ZMQ_MAXMSGSIZE:
if (*optvallen_ < sizeof (int64_t)) {
errno = EINVAL;
return -1;
}
*((int64_t*) optval_) = maxmsgsize;
*optvallen_ = sizeof (int64_t);
return 0;
} }
errno = EINVAL; errno = EINVAL;
......
...@@ -69,6 +69,9 @@ namespace zmq ...@@ -69,6 +69,9 @@ namespace zmq
// Maximum backlog for pending connections. // Maximum backlog for pending connections.
int backlog; int backlog;
// Maximal size of message to handle.
int64_t maxmsgsize;
// These options are never set by the user directly. Instead they are // These options are never set by the user directly. Instead they are
// provided by the specific socket type. // provided by the specific socket type.
bool requires_in; bool requires_in;
......
...@@ -211,7 +211,8 @@ void zmq::pgm_receiver_t::in_event () ...@@ -211,7 +211,8 @@ void zmq::pgm_receiver_t::in_event ()
it->second.joined = true; it->second.joined = true;
// Create and connect decoder for the peer. // Create and connect decoder for the peer.
it->second.decoder = new (std::nothrow) decoder_t (0); it->second.decoder = new (std::nothrow) decoder_t (0,
options.maxmsgsize);
alloc_assert (it->second.decoder); alloc_assert (it->second.decoder);
it->second.decoder->set_inout (inout); it->second.decoder->set_inout (inout);
} }
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
zmq::zmq_engine_t::zmq_engine_t (fd_t fd_, const options_t &options_) : zmq::zmq_engine_t::zmq_engine_t (fd_t fd_, const options_t &options_) :
inpos (NULL), inpos (NULL),
insize (0), insize (0),
decoder (in_batch_size), decoder (in_batch_size, options_.maxmsgsize),
outpos (NULL), outpos (NULL),
outsize (0), outsize (0),
encoder (out_batch_size), encoder (out_batch_size),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment