diff --git a/include/zmq.h b/include/zmq.h index 070b43a8..b9f194ea 100644 --- a/include/zmq.h +++ b/include/zmq.h @@ -241,7 +241,7 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval); #define ZMQ_MULTICAST_HOPS 25 #define ZMQ_RCVTIMEO 27 #define ZMQ_SNDTIMEO 28 -#define ZMQ_IPV4ONLY 31 +#define ZMQ_IPV4ONLY 31 /* Request replacement by IPV6 */ #define ZMQ_LAST_ENDPOINT 32 #define ZMQ_ROUTER_MANDATORY 33 #define ZMQ_TCP_KEEPALIVE 34 @@ -252,6 +252,7 @@ ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval); #define ZMQ_DELAY_ATTACH_ON_CONNECT 39 #define ZMQ_XPUB_VERBOSE 40 #define ZMQ_ROUTER_RAW 41 +#define ZMQ_IPV6 42 /* Message options */ diff --git a/src/options.cpp b/src/options.cpp index 4a371693..b2f3da9a 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -61,281 +61,203 @@ zmq::options_t::options_t () : int zmq::options_t::setsockopt (int option_, const void *optval_, size_t optvallen_) { - switch (option_) { - - case ZMQ_SNDHWM: - if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - sndhwm = *((int*) optval_); - return 0; - - case ZMQ_RCVHWM: - if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - rcvhwm = *((int*) optval_); - return 0; - - case ZMQ_AFFINITY: - if (optvallen_ != sizeof (uint64_t)) { - errno = EINVAL; - return -1; - } - affinity = *((uint64_t*) optval_); - return 0; - - case ZMQ_IDENTITY: - - // Empty identity is invalid as well as identity longer than - // 255 bytes. Identity starting with binary zero is invalid - // as these are used for auto-generated identities. - if (optvallen_ < 1 || optvallen_ > 255 || - *((const unsigned char*) optval_) == 0) { - errno = EINVAL; - return -1; - } - identity_size = optvallen_; - memcpy (identity, optval_, identity_size); - return 0; - - case ZMQ_RATE: - if (optvallen_ != sizeof (int) || *((int*) optval_) <= 0) { - errno = EINVAL; - return -1; - } - rate = *((int*) optval_); - return 0; - - case ZMQ_RECOVERY_IVL: - if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - recovery_ivl = *((int*) optval_); - return 0; - - case ZMQ_SNDBUF: - if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - sndbuf = *((int*) optval_); - return 0; - - case ZMQ_RCVBUF: - if (optvallen_ != sizeof (int) || *((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - rcvbuf = *((int*) optval_); - return 0; - - case ZMQ_LINGER: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - linger = *((int*) optval_); - return 0; - - case ZMQ_RECONNECT_IVL: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - if (*((int*) optval_) < -1) { - errno = EINVAL; - return -1; - } - reconnect_ivl = *((int*) optval_); - return 0; - - case ZMQ_RECONNECT_IVL_MAX: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - if (*((int*) optval_) < 0) { - errno = EINVAL; - return -1; - } - reconnect_ivl_max = *((int*) optval_); - return 0; - - case ZMQ_BACKLOG: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - backlog = *((int*) optval_); - return 0; - - case ZMQ_MAXMSGSIZE: - if (optvallen_ != sizeof (int64_t)) { - errno = EINVAL; - return -1; - } - maxmsgsize = *((int64_t*) optval_); - return 0; - - case ZMQ_MULTICAST_HOPS: - if (optvallen_ != sizeof (int) || *((int*) optval_) <= 0) { - errno = EINVAL; - return -1; - } - multicast_hops = *((int*) optval_); - return 0; - - case ZMQ_RCVTIMEO: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - rcvtimeo = *((int*) optval_); - return 0; - - case ZMQ_SNDTIMEO: - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - sndtimeo = *((int*) optval_); - return 0; - - case ZMQ_IPV4ONLY: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val != 0 && val != 1) { - errno = EINVAL; - return -1; - } - ipv4only = val; - return 0; - } - + bool valid = true; + bool is_int = (optvallen_ == sizeof (int)); + int value = is_int? *((int *) optval_): 0; + switch (option_) { + case ZMQ_SNDHWM: + if (is_int && value >= 0) + sndhwm = value; + else + valid = false; + break; + + case ZMQ_RCVHWM: + if (is_int && value >= 0) + rcvhwm = value; + else + valid = false; + break; - case ZMQ_TCP_KEEPALIVE: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val != -1 && val != 0 && val != 1) { - errno = EINVAL; - return -1; - } -#if defined ZMQ_HAVE_SO_KEEPALIVE - tcp_keepalive = val; -#endif - return 0; - } + case ZMQ_AFFINITY: + if (optvallen_ == sizeof (uint64_t)) + affinity = *((uint64_t*) optval_); + else + valid = false; + break; - case ZMQ_DELAY_ATTACH_ON_CONNECT: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val != 0 && val != 1) { - errno = EINVAL; - return -1; - } - delay_attach_on_connect = val; - return 0; - } - - case ZMQ_TCP_KEEPALIVE_CNT: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val <= 0 && val != -1) { - errno = EINVAL; - return -1; - } -#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPCNT - tcp_keepalive_cnt = val; -#endif - return 0; - } - - case ZMQ_TCP_KEEPALIVE_IDLE: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val <= 0 && val != -1) { - errno = EINVAL; - return -1; - } - -#if defined ZMQ_HAVE_SO_KEEPALIVE && (defined ZMQ_HAVE_TCP_KEEPIDLE || defined ZMQ_HAVE_TCP_KEEPALIVE) - tcp_keepalive_idle = val; -#endif - return 0; - } - - case ZMQ_TCP_KEEPALIVE_INTVL: - { - if (optvallen_ != sizeof (int)) { - errno = EINVAL; - return -1; - } - int val = *((int*) optval_); - if (val <= 0 && val != -1) { - errno = EINVAL; - return -1; - } -#if defined ZMQ_HAVE_SO_KEEPALIVE && defined ZMQ_HAVE_TCP_KEEPINTVL - tcp_keepalive_intvl = val; -#endif - return 0; - } - - case ZMQ_TCP_ACCEPT_FILTER: - { - if (optvallen_ == 0 && optval_ == NULL) { - tcp_accept_filters.clear (); - return 0; + case ZMQ_IDENTITY: + // Empty identity is invalid as well as identity longer than + // 255 bytes. Identity starting with binary zero is invalid + // as these are used for auto-generated identities. + if (optvallen_ > 0 && optvallen_ < 256 + && *((const unsigned char *) optval_) != 0) { + identity_size = optvallen_; + memcpy (identity, optval_, identity_size); } else - if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0) { - errno = EINVAL; - return -1; - } + valid = false; + break; + + case ZMQ_RATE: + if (is_int && value > 0) + rate = value; + else + valid = false; + break; + + case ZMQ_RECOVERY_IVL: + if (is_int && value >= 0) + recovery_ivl = value; + else + valid = false; + + case ZMQ_SNDBUF: + if (is_int && value >= 0) + sndbuf = value; + else + valid = false; + break; + + case ZMQ_RCVBUF: + if (is_int && value >= 0) + rcvbuf = value; + else + valid = false; + break; + + case ZMQ_LINGER: + if (is_int && value >= -1) + linger = value; + else + valid = false; + break; + + case ZMQ_RECONNECT_IVL: + if (is_int && value >= -1) + reconnect_ivl = value; + else + valid = false; + break; + + case ZMQ_RECONNECT_IVL_MAX: + if (is_int && value >= 0) + reconnect_ivl_max = value; + else + valid = false; + break; + + case ZMQ_BACKLOG: + if (is_int && value >= 0) + backlog = value; + else + valid = false; + break; + + case ZMQ_MAXMSGSIZE: + if (optvallen_ == sizeof (int64_t)) + maxmsgsize = *((int64_t *) optval_); + else + valid = false; + + case ZMQ_MULTICAST_HOPS: + if (is_int && value > 0) + multicast_hops = value; + else + valid = false; + break; + + case ZMQ_RCVTIMEO: + if (is_int && value >= -1) + rcvtimeo = value; + else + valid = false; + break; + + case ZMQ_SNDTIMEO: + if (is_int && value >= -1) + sndtimeo = value; + else + valid = false; + break; + + case ZMQ_IPV4ONLY: + if (is_int && (value == 0 || value == 1)) + ipv4only = value; + else + valid = false; + break; + + /* To replace the somewhat surprising IPV4ONLY */ + case ZMQ_IPV6: + if (is_int && (value == 0 || value == 1)) + ipv4only = 1 - value; + else + valid = false; + break; + + case ZMQ_TCP_KEEPALIVE: + if (is_int && (value >= -1 || value <= 1)) + tcp_keepalive = value; + else + valid = false; + break; + + case ZMQ_TCP_KEEPALIVE_CNT: + if (is_int && (value == -1 || value >= 0)) + tcp_keepalive_cnt = value; + else + valid = false; + break; + + case ZMQ_TCP_KEEPALIVE_IDLE: + if (is_int && (value == -1 || value >= 0)) + tcp_keepalive_idle = value; + else + valid = false; + break; + + case ZMQ_TCP_KEEPALIVE_INTVL: + if (is_int && (value == -1 || value >= 0)) + tcp_keepalive_intvl = value; + else + valid = false; + break; + + case ZMQ_DELAY_ATTACH_ON_CONNECT: + if (is_int && (value == 0 || value == 1)) + delay_attach_on_connect = value; + else + valid = false; + break; + + case ZMQ_TCP_ACCEPT_FILTER: + if (optvallen_ == 0 && optval_ == NULL) + tcp_accept_filters.clear (); + else + if (optvallen_ < 1 || optvallen_ > 255 || optval_ == NULL || *((const char*) optval_) == 0) + valid = false; else { - std::string filter_str ((const char*) optval_, optvallen_); - + std::string filter_str ((const char *) optval_, optvallen_); tcp_address_mask_t mask; - int rc = mask.resolve (filter_str.c_str (), ipv4only ? true : false); - if (rc != 0) { - errno = EINVAL; - return -1; - } - tcp_accept_filters.push_back(mask); - - return 0; + int rc = mask.resolve (filter_str.c_str (), ipv4only); + if (rc == 0) + tcp_accept_filters.push_back (mask); + else + valid = false; } - } - default: - { - errno = EINVAL; - return -1; - } + break; + + default: + valid = false; + break; + } + if (valid) + return 0; + else { + errno = EINVAL; + return -1; } } @@ -505,6 +427,15 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) *optvallen_ = sizeof (int); return 0; + case ZMQ_IPV6: + if (*optvallen_ < sizeof (int)) { + errno = EINVAL; + return -1; + } + *((int*) optval_) = 1 - ipv4only; + *optvallen_ = sizeof (int); + return 0; + case ZMQ_DELAY_ATTACH_ON_CONNECT: if (*optvallen_ < sizeof (int)) { errno = EINVAL;