aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/core/init.c6
-rw-r--r--src/core/nng_impl.h1
-rw-r--r--src/core/pipe.c2
-rw-r--r--src/core/platform.h13
-rw-r--r--src/core/random.c195
-rw-r--r--src/core/random.h26
-rw-r--r--src/platform/posix/posix_config.h25
-rw-r--r--src/platform/posix/posix_debug.c56
-rw-r--r--src/platform/posix/posix_rand.c86
-rw-r--r--src/platform/posix/posix_thread.c32
-rw-r--r--src/protocol/reqrep/req.c2
-rw-r--r--src/protocol/survey/survey.c3
13 files changed, 374 insertions, 76 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ac029bc9..12700a5c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,6 +49,8 @@ set (NNG_SOURCES
core/platform.h
core/protocol.c
core/protocol.h
+ core/random.c
+ core/random.h
core/socket.c
core/socket.h
core/thread.c
@@ -63,6 +65,7 @@ set (NNG_SOURCES
platform/posix/posix_clock.c
platform/posix/posix_debug.c
platform/posix/posix_net.c
+ platform/posix/posix_rand.c
platform/posix/posix_thread.c
protocol/pair/pair.c
diff --git a/src/core/init.c b/src/core/init.c
index 3ae10a21..f10173c8 100644
--- a/src/core/init.c
+++ b/src/core/init.c
@@ -14,6 +14,11 @@
static int
nni_init_helper(void)
{
+ int rv;
+
+ if ((rv = nni_random_init()) != 0) {
+ return (rv);
+ }
nni_tran_init();
return (0);
}
@@ -30,5 +35,6 @@ void
nni_fini(void)
{
nni_tran_fini();
+ nni_random_fini();
nni_plat_fini();
}
diff --git a/src/core/nng_impl.h b/src/core/nng_impl.h
index 4c00a522..6bf0900d 100644
--- a/src/core/nng_impl.h
+++ b/src/core/nng_impl.h
@@ -31,6 +31,7 @@
#include "core/panic.h"
#include "core/platform.h"
#include "core/protocol.h"
+#include "core/random.h"
#include "core/thread.h"
#include "core/transport.h"
diff --git a/src/core/pipe.c b/src/core/pipe.c
index 249e887c..0633dea9 100644
--- a/src/core/pipe.c
+++ b/src/core/pipe.c
@@ -190,7 +190,7 @@ nni_pipe_start(nni_pipe *pipe)
// happen if we wrap -- i.e. we've had 4 billion or so pipes.
// XXX: consider making this a hash table!!
nni_pipe *check;
- pipe->p_id = nni_plat_nextid() & 0x7FFFFFFF;
+ pipe->p_id = nni_random() & 0x7FFFFFFF;
collide = 0;
NNI_LIST_FOREACH (&sock->s_pipes, check) {
if ((pipe != check) && (check->p_id == pipe->p_id)) {
diff --git a/src/core/platform.h b/src/core/platform.h
index b1662cc1..5a504dec 100644
--- a/src/core/platform.h
+++ b/src/core/platform.h
@@ -152,13 +152,6 @@ extern int nni_plat_init(int (*)(void));
// will be called until nni_platform_init is called.
extern void nni_plat_fini(void);
-// nni_plat_nextid is used to generate a new pipe ID. This should be an
-// increasing value, taken from a random starting point. (The randomness
-// helps ensure we don't confuse pipe IDs from other connections.) The
-// value must be obtained in a threadsafe way (e.g. via an atomic counter
-// or under a lock protection.)
-extern uint32_t nni_plat_nextid(void);
-
// nni_plat_strerror allows the platform to use additional error messages
// for additional error codes. The err code passed in should be the
// equivalent of errno or GetLastError, without the NNG_ESYSERR component.
@@ -215,6 +208,12 @@ extern int nni_plat_tcp_send(nni_plat_tcpsock *, nni_iov *, int);
// full, or an error condition occurs.
extern int nni_plat_tcp_recv(nni_plat_tcpsock *, nni_iov *, int);
+// nni_plat_seed_prng seeds the PRNG subsystem. The specified number
+// of bytes of entropy should be stashed. When possible, cryptographic
+// quality entropy sources should be used. Note that today we prefer
+// to seed up to 256 bytes of data.
+extern void nni_plat_seed_prng(void *, size_t);
+
// Actual platforms we support. This is included up front so that we can
// get the specific types that are supplied by the platform.
#if defined(PLATFORM_POSIX)
diff --git a/src/core/random.c b/src/core/random.c
new file mode 100644
index 00000000..b2ce0ef7
--- /dev/null
+++ b/src/core/random.c
@@ -0,0 +1,195 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include "core/nng_impl.h"
+
+// This is ISAAC, a (reputedly) cryptographically secure PRNG that is also
+// quite efficient. While the particular adjustments to fit in our code
+// base are under our copyright, the actual algorithm itself, as well as
+// sample implementations, are part of the public domain. See this:
+// http://www.burtleburtle.net/bob/c/readable.c
+//
+// Our changes include making this code thread safe/reentrant, and naming
+// and style changes, to fit C99.
+
+typedef struct {
+ // the rsl is the actual results, and the randcnt is the length
+ // of the results.
+ uint32_t randrsl[256];
+ uint32_t randcnt;
+
+ // lock to protect concurrent access
+ nni_mtx mx;
+
+ // more or less internal state
+ uint32_t mm[256];
+ uint32_t aa;
+ uint32_t bb;
+ uint32_t cc;
+} nni_isaac_ctx;
+
+
+static void
+nni_isaac(nni_isaac_ctx *ctx)
+{
+ register uint32_t i, x, y;
+
+ ctx->cc++; // cc incremented once per 256 results
+ ctx->bb += ctx->cc; // then combined with bb
+
+ for (i = 0; i < 256; ++i) {
+ x = ctx->mm[i];
+ switch (i%4) {
+ case 0:
+ ctx->aa ^= (ctx->aa<<13);
+ break;
+ case 1:
+ ctx->aa ^= (ctx->aa>>6);
+ break;
+ case 2:
+ ctx->aa ^= (ctx->aa<<2);
+ break;
+ case 3:
+ ctx->aa ^= (ctx->aa>>16);
+ break;
+ }
+ ctx->aa += ctx->mm[(i+128)%256];
+ ctx->mm[i] = y = ctx->mm[(x>>2)%256] + ctx->aa + ctx->bb;
+ ctx->randrsl[i] = ctx->bb = ctx->mm[(y>>10)%256] + x;
+
+ // Note that bits 2..9 are chosen from x but 10..17 are chosen
+ // from y. The only important thing here is that 2..9 and
+ // 10..17 don't overlap. 2..9 and 10..17 were then chosen
+ // for speed in the optimized version (rand.c)
+
+ // See http://burtleburtle.net/bob/rand/isaac.html
+ // for further explanations and analysis.
+ }
+}
+
+
+// if (flag!=0), then use the contents of randrsl[] to initialize mm[].
+#define nni_isaac_mix(a, b, c, d, e, f, g, h) \
+ { \
+ a ^= b<<11; d += a; b += c; \
+ b ^= c>>2; e += b; c += d; \
+ c ^= d<<8; f += c; d += e; \
+ d ^= e>>16; g += d; e += f; \
+ e ^= f<<10; h += e; f += g; \
+ f ^= g>>4; a += f; g += h; \
+ g ^= h<<8; b += g; h += a; \
+ h ^= a>>9; c += h; a += b; \
+ }
+
+static void
+nni_isaac_randinit(nni_isaac_ctx *ctx, int flag)
+{
+ int i;
+ uint32_t a, b, c, d, e, f, g, h;
+
+ ctx->aa = ctx->bb = ctx->cc = 0;
+ a = b = c = d = e = f = g = h = 0x9e3779b9; // the golden ratio
+
+ for (i = 0; i < 4; ++i) { // scramble it
+ nni_isaac_mix(a, b, c, d, e, f, g, h);
+ }
+
+ for (i = 0; i < 256; i += 8) { // fill in mm[] with messy stuff
+ if (flag) { // use all the information in the seed
+ a += ctx->randrsl[i];
+ b += ctx->randrsl[i+1];
+ c += ctx->randrsl[i+2];
+ d += ctx->randrsl[i+3];
+ e += ctx->randrsl[i+4];
+ f += ctx->randrsl[i+5];
+ g += ctx->randrsl[i+6];
+ h += ctx->randrsl[i+7];
+ }
+ nni_isaac_mix(a, b, c, d, e, f, g, h);
+ ctx->mm[i] = a;
+ ctx->mm[i+1] = b;
+ ctx->mm[i+2] = c;
+ ctx->mm[i+3] = d;
+ ctx->mm[i+4] = e;
+ ctx->mm[i+5] = f;
+ ctx->mm[i+6] = g;
+ ctx->mm[i+7] = h;
+ }
+
+ if (flag) {
+ // do a second pass to make all of the seed affect all of mm
+ for (i = 0; i < 256; i += 8) {
+ a += ctx->mm[i];
+ b += ctx->mm[i+1];
+ c += ctx->mm[i+2];
+ d += ctx->mm[i+3];
+ e += ctx->mm[i+4];
+ f += ctx->mm[i+5];
+ g += ctx->mm[i+6];
+ h += ctx->mm[i+7];
+ nni_isaac_mix(a, b, c, d, e, f, g, h);
+ ctx->mm[i] = a;
+ ctx->mm[i+1] = b;
+ ctx->mm[i+2] = c;
+ ctx->mm[i+3] = d;
+ ctx->mm[i+4] = e;
+ ctx->mm[i+5] = f;
+ ctx->mm[i+6] = g;
+ ctx->mm[i+7] = h;
+ }
+ }
+
+ nni_isaac(ctx); // fill in the first set of results
+ ctx->randcnt = 256; // prepare to use the first set of results
+}
+
+
+static nni_isaac_ctx nni_random_ctx;
+
+int
+nni_random_init(void)
+{
+ // minimally, grab the system clock
+ nni_isaac_ctx *ctx = &nni_random_ctx;
+ int rv;
+
+ if ((rv = nni_mtx_init(&ctx->mx)) != 0) {
+ return (rv);
+ }
+
+ nni_plat_seed_prng(ctx->randrsl, sizeof (ctx->randrsl));
+ nni_isaac_randinit(ctx, 1);
+ return (0);
+}
+
+
+uint32_t
+nni_random(void)
+{
+ uint32_t rv;
+ nni_isaac_ctx *ctx = &nni_random_ctx;
+
+ nni_mtx_lock(&ctx->mx);
+ if (ctx->randcnt < 1) {
+ nni_isaac(ctx);
+ ctx->randcnt = 256;
+ }
+ ctx->randcnt--;
+ rv = ctx->randrsl[ctx->randcnt];
+ nni_mtx_unlock(&ctx->mx);
+
+ return (rv);
+}
+
+
+void
+nni_random_fini(void)
+{
+ nni_mtx_fini(&nni_random_ctx.mx);
+}
diff --git a/src/core/random.h b/src/core/random.h
new file mode 100644
index 00000000..cf365380
--- /dev/null
+++ b/src/core/random.h
@@ -0,0 +1,26 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef CORE_RANDOM_H
+#define CORE_RANDOM_H
+
+// nni_random_init initializes the pRNG subsystem. This includes obtaining
+// suitable seeding material from the platform.
+extern int nni_random_init(void);
+
+// nni_random_fini destroys the pRNG subsystem.
+extern void nni_random_fini(void);
+
+// nni_random returns a random 32-bit integer. Note that this routine is
+// thread-safe/reentrant. The pRNG is very robust, should be of crypto
+// quality. However, its usefulness for cryptography will be determined
+// by the quality of the seeding material provided by the platform.
+extern uint32_t nni_random(void);
+
+#endif // CORE_RANDOM_H
diff --git a/src/platform/posix/posix_config.h b/src/platform/posix/posix_config.h
index 6d282f63..e1bafd5c 100644
--- a/src/platform/posix/posix_config.h
+++ b/src/platform/posix/posix_config.h
@@ -27,23 +27,38 @@
// is defined. Platforms that don't use POSIX clocks will probably
// ignore any setting here.
//
-// #define NNG_HAVE_ARC4RANDOM
-// This indicates that the platform has the superior arc4random function
-// for getting entropy.
-//
// #define NNG_HAVE_BACKTRACE
// If your system has a working backtrace(), and backtrace_symbols(),
// along with <execinfo.h>, you can define this to get richer backtrace
// information for debugging.
+//
+// #define NNG_USE_GETRANDOM
+// #define NNG_USE_GETENTROPY
+// #define NNG_USE_ARC4RANDOM
+// #define NNG_USE_DEVURANDOM
+// Thesse are options for obtaining entropy to seed the pRNG.
+// All known modern UNIX variants can support NNG_USE_DEVURANDOM,
+// but the other options are better still, but not portable.
#include <time.h>
+// These are things about systems we know about.
+#ifdef __APPLE__
// MacOS X used to lack CLOCK_MONOTONIC. Now it has it, but its
// buggy, condition variables set to use it wake early.
-#ifdef __APPLE__
#define NNG_USE_CLOCKID CLOCK_REALTIME
+// macOS 10.12 has getentropy(), but arc4random() is good enough
+// and works on older releases.
+#define NNG_USE_ARC4RANDOM 1
#endif // __APPLE__
+// It should never hurt to use DEVURANDOM, since if the device does not
+// exist then we won't open it. (Provided: it would be bad if the device
+// exists but has somehow very very different semantics. We don't know
+// of any such concerns.) This won't be used if any of the other options
+// are defined and work.
+#define NNG_USE_DEVURANDOM 1
+
#define NNG_USE_CLOCKID CLOCK_REALTIME
#ifndef CLOCK_REALTIME
#define NNG_USE_GETTIMEOFDAY
diff --git a/src/platform/posix/posix_debug.c b/src/platform/posix/posix_debug.c
index a956d777..71006b25 100644
--- a/src/platform/posix/posix_debug.c
+++ b/src/platform/posix/posix_debug.c
@@ -55,35 +55,35 @@ static struct {
int nng_err;
}
nni_plat_errnos[] = {
- NNI_ERR(EINTR, NNG_EINTR)
- NNI_ERR(EINVAL, NNG_EINVAL)
- NNI_ERR(ENOMEM, NNG_ENOMEM)
- NNI_ERR(EACCES, NNG_EPERM)
- NNI_ERR(EADDRINUSE, NNG_EADDRINUSE)
- NNI_ERR(EADDRNOTAVAIL, NNG_EADDRINVAL)
- NNI_ERR(EAFNOSUPPORT, NNG_ENOTSUP)
- NNI_ERR(EAGAIN, NNG_EAGAIN)
- NNI_ERR(EBADF, NNG_ECLOSED)
- NNI_ERR(EBUSY, NNG_EBUSY)
- NNI_ERR(ECONNABORTED, NNG_ECLOSED)
- NNI_ERR(ECONNREFUSED, NNG_ECONNREFUSED)
- NNI_ERR(ECONNRESET, NNG_ECLOSED)
- NNI_ERR(EHOSTUNREACH, NNG_EUNREACHABLE)
- NNI_ERR(ENETUNREACH, NNG_EUNREACHABLE)
- NNI_ERR(ENAMETOOLONG, NNG_EINVAL)
- NNI_ERR(ENOENT, NNG_ENOENT)
- NNI_ERR(ENOBUFS, NNG_ENOMEM)
- NNI_ERR(ENOPROTOOPT, NNG_ENOTSUP)
- NNI_ERR(ENOSYS, NNG_ENOTSUP)
- NNI_ERR(ENOTSUP, NNG_ENOTSUP)
- NNI_ERR(EPERM, NNG_EPERM)
- NNI_ERR(EPIPE, NNG_ECLOSED)
- NNI_ERR(EPROTO, NNG_EPROTO)
+ NNI_ERR(EINTR, NNG_EINTR)
+ NNI_ERR(EINVAL, NNG_EINVAL)
+ NNI_ERR(ENOMEM, NNG_ENOMEM)
+ NNI_ERR(EACCES, NNG_EPERM)
+ NNI_ERR(EADDRINUSE, NNG_EADDRINUSE)
+ NNI_ERR(EADDRNOTAVAIL, NNG_EADDRINVAL)
+ NNI_ERR(EAFNOSUPPORT, NNG_ENOTSUP)
+ NNI_ERR(EAGAIN, NNG_EAGAIN)
+ NNI_ERR(EBADF, NNG_ECLOSED)
+ NNI_ERR(EBUSY, NNG_EBUSY)
+ NNI_ERR(ECONNABORTED, NNG_ECLOSED)
+ NNI_ERR(ECONNREFUSED, NNG_ECONNREFUSED)
+ NNI_ERR(ECONNRESET, NNG_ECLOSED)
+ NNI_ERR(EHOSTUNREACH, NNG_EUNREACHABLE)
+ NNI_ERR(ENETUNREACH, NNG_EUNREACHABLE)
+ NNI_ERR(ENAMETOOLONG, NNG_EINVAL)
+ NNI_ERR(ENOENT, NNG_ENOENT)
+ NNI_ERR(ENOBUFS, NNG_ENOMEM)
+ NNI_ERR(ENOPROTOOPT, NNG_ENOTSUP)
+ NNI_ERR(ENOSYS, NNG_ENOTSUP)
+ NNI_ERR(ENOTSUP, NNG_ENOTSUP)
+ NNI_ERR(EPERM, NNG_EPERM)
+ NNI_ERR(EPIPE, NNG_ECLOSED)
+ NNI_ERR(EPROTO, NNG_EPROTO)
NNI_ERR(EPROTONOSUPPORT, NNG_ENOTSUP)
- NNI_ERR(ETIME, NNG_ETIMEDOUT)
- NNI_ERR(ETIMEDOUT, NNG_ETIMEDOUT)
- NNI_ERR(EWOULDBLOCK, NNG_EAGAIN)
- NNI_ERR(0, 0) // must be last
+ NNI_ERR(ETIME, NNG_ETIMEDOUT)
+ NNI_ERR(ETIMEDOUT, NNG_ETIMEDOUT)
+ NNI_ERR(EWOULDBLOCK, NNG_EAGAIN)
+ NNI_ERR(0, 0) // must be last
};
int
diff --git a/src/platform/posix/posix_rand.c b/src/platform/posix/posix_rand.c
new file mode 100644
index 00000000..65d1c031
--- /dev/null
+++ b/src/platform/posix/posix_rand.c
@@ -0,0 +1,86 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+// POSIX clock stuff.
+#include "core/nng_impl.h"
+
+#ifdef PLATFORM_POSIX_RANDOM
+
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+
+#ifdef NNG_USE_GETRANDOM
+#include <linux/random.h>
+#endif
+
+#ifdef NNG_USE_GETENTROPY
+#include <sys/random.h>
+#endif
+
+// This structure represents the very barest minimum that we can use as
+// a source of entropy. We mix these into our initial entropy, but really
+// really really you want to have more data than this available, especially
+// for cryptographic applications.
+struct nni_plat_prng_x {
+ nni_time now;
+ pid_t pid;
+ uid_t uid;
+ struct utsname uts;
+};
+
+void
+nni_plat_seed_prng(void *buf, size_t bufsz)
+{
+ struct nni_plat_prng_x x;
+ int i;
+
+#if defined(NNG_USE_GETRANDOM)
+ // Latest Linux has a nice API here.
+ (void) getrandom(buf, bufsz, 0);
+#elif defined(NNG_USE_GETENTROPY)
+ // Modern BSD systems prefer this, but can only generate 256 bytes
+ (void) getentropy(buf, bufsz > 256 ? 256 : 0);
+#elif defined(NNG_USE_ARC4RANDOM)
+ // This uses BSD style pRNG seeded from the kernel in libc.
+ (void) arc4random_buf(buf, bufsz);
+#elif defined(NNG_USE_DEVURANDOM)
+ // The historic /dev/urandom device. This is not as a good as
+ // a system call, since file descriptor attacks are possible,
+ // and it may need special permissions. We choose /dev/urandom
+ // over /dev/random to avoid diminishing the system entropy.
+ int fd;
+
+ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0) {
+ (void) read(fd, buf, buffz);
+ (void) close(fd);
+ }
+#endif
+
+ // As a speical extra guard, let's mixin the data from the
+ // following system calls. This ensures that even on the most
+ // limited of systems, we have at least *some* level of randomness.
+ // The mixing is done in a way to avoid diminishing entropy we may
+ // have already collected.
+ x.now = nni_clock();
+ x.pid = getpid();
+ x.uid = getuid();
+ uname(&x.uts);
+
+ for (i = 0; (i < bufsz) && (i < sizeof (x)); i++) {
+ ((uint8_t *) buf)[i] ^= ((uint8_t *) &x)[i];
+ }
+}
+
+
+#endif // PLATFORM_POSIX_RANDOM
diff --git a/src/platform/posix/posix_thread.c b/src/platform/posix/posix_thread.c
index e4e5e74b..991a08db 100644
--- a/src/platform/posix/posix_thread.c
+++ b/src/platform/posix/posix_thread.c
@@ -24,7 +24,6 @@
static pthread_mutex_t nni_plat_lock = PTHREAD_MUTEX_INITIALIZER;
static int nni_plat_inited = 0;
static int nni_plat_forked = 0;
-static int nni_plat_next = 0;
pthread_condattr_t nni_cvattr;
pthread_mutexattr_t nni_mxattr;
@@ -34,18 +33,6 @@ pthread_mutexattr_t nni_mxattr;
int nni_plat_devnull = -1;
-uint32_t
-nni_plat_nextid(void)
-{
- uint32_t id;
-
- pthread_mutex_lock(&nni_plat_lock);
- id = nni_plat_next++;
- pthread_mutex_unlock(&nni_plat_lock);
- return (id);
-}
-
-
int
nni_plat_mtx_init(nni_plat_mtx *mtx)
{
@@ -270,25 +257,6 @@ nni_plat_init(int (*helper)(void))
return (NNG_ENOMEM);
}
- // Generate a starting ID (used for Pipe IDs)
-#ifdef NNG_HAVE_ARC4RANDOM
- nni_plat_next = arc4random();
-#else
- while (nni_plat_next == 0) {
- uint16_t xsub[3];
- nni_time now = nni_clock();
- pid_t pid = getpid();
-
- xsub[0] = (uint16_t) now;
- xsub[1] = (uint16_t) (now >> 16);
- xsub[2] = (uint16_t) (now >> 24);
- xsub[0] ^= (uint16_t) pid;
- xsub[1] ^= (uint16_t) (pid >> 16);
- xsub[2] ^= (uint16_t) (pid >> 24);
- nni_plat_next = nrand48(xsub);
- }
-#endif
-
if (pthread_atfork(NULL, NULL, nni_atfork_child) != 0) {
pthread_mutex_unlock(&nni_plat_lock);
(void) close(nni_plat_devnull);
diff --git a/src/protocol/reqrep/req.c b/src/protocol/reqrep/req.c
index 3c3bba9c..5b9671f8 100644
--- a/src/protocol/reqrep/req.c
+++ b/src/protocol/reqrep/req.c
@@ -58,7 +58,7 @@ nni_req_sock_init(void **reqp, nni_sock *sock)
return (rv);
}
// this is "semi random" start for request IDs.
- req->nextid = (nni_clock() >> 32) ^ (nni_clock() & 0xffffffff);
+ req->nextid = nni_random();
req->retry = NNI_SECOND * 60;
req->sock = sock;
req->reqmsg = NULL;
diff --git a/src/protocol/survey/survey.c b/src/protocol/survey/survey.c
index cb600dc3..9def9292 100644
--- a/src/protocol/survey/survey.c
+++ b/src/protocol/survey/survey.c
@@ -54,8 +54,7 @@ nni_surv_sock_init(void **sp, nni_sock *nsock)
return (rv);
}
NNI_LIST_INIT(&psock->pipes, nni_surv_pipe, node);
- // this is "semi random" start for request IDs.
- psock->nextid = (nni_clock() >> 32) ^ (nni_clock() & 0xffffffff);
+ psock->nextid = nni_random();
psock->nsock = nsock;
psock->raw = 0;
psock->survtime = NNI_SECOND * 60;