1*f04ff968Sreyk /* $OpenBSD: shuffle.c,v 1.4 2015/01/22 17:42:09 reyk Exp $ */
28661b3ffSreyk
38661b3ffSreyk /*
48661b3ffSreyk * Portions Copyright (C) 2008 Theo de Raadt
58661b3ffSreyk *
68661b3ffSreyk * Permission to use, copy, modify, and distribute this software for any
78661b3ffSreyk * purpose with or without fee is hereby granted, provided that the above
88661b3ffSreyk * copyright notice and this permission notice appear in all copies.
98661b3ffSreyk *
108661b3ffSreyk * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
118661b3ffSreyk * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
128661b3ffSreyk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
138661b3ffSreyk * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
148661b3ffSreyk * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
158661b3ffSreyk * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
168661b3ffSreyk * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
178661b3ffSreyk * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
188661b3ffSreyk */
198661b3ffSreyk
208661b3ffSreyk /* based on: bind/lib/isc/shuffle.c,v 1.4 2008/07/09 17:07:32 reyk Exp $ */
218661b3ffSreyk
228661b3ffSreyk #include <sys/types.h>
238661b3ffSreyk
248661b3ffSreyk #include <stdlib.h>
258661b3ffSreyk #include <assert.h>
268661b3ffSreyk
278661b3ffSreyk #include "relayd.h"
288661b3ffSreyk
298661b3ffSreyk #define VALID_SHUFFLE(x) (x != NULL)
308661b3ffSreyk
318661b3ffSreyk void
shuffle_init(struct shuffle * shuffle)328661b3ffSreyk shuffle_init(struct shuffle *shuffle)
338661b3ffSreyk {
348661b3ffSreyk int i, i2;
358661b3ffSreyk
368661b3ffSreyk assert(VALID_SHUFFLE(shuffle));
378661b3ffSreyk
388661b3ffSreyk shuffle->isindex = 0;
398661b3ffSreyk /* Initialize using a Knuth shuffle */
408661b3ffSreyk for (i = 0; i < 65536; ++i) {
418661b3ffSreyk i2 = arc4random_uniform(i + 1);
428661b3ffSreyk shuffle->id_shuffle[i] = shuffle->id_shuffle[i2];
438661b3ffSreyk shuffle->id_shuffle[i2] = i;
448661b3ffSreyk }
458661b3ffSreyk }
468661b3ffSreyk
478661b3ffSreyk u_int16_t
shuffle_generate16(struct shuffle * shuffle)488661b3ffSreyk shuffle_generate16(struct shuffle *shuffle)
498661b3ffSreyk {
508661b3ffSreyk u_int32_t si;
518661b3ffSreyk u_int16_t r;
528661b3ffSreyk int i, i2;
538661b3ffSreyk
548661b3ffSreyk assert(VALID_SHUFFLE(shuffle));
558661b3ffSreyk
568661b3ffSreyk do {
578661b3ffSreyk si = arc4random();
588661b3ffSreyk i = shuffle->isindex & 0xFFFF;
598661b3ffSreyk i2 = (shuffle->isindex - (si & 0x7FFF)) & 0xFFFF;
608661b3ffSreyk r = shuffle->id_shuffle[i];
618661b3ffSreyk shuffle->id_shuffle[i] = shuffle->id_shuffle[i2];
628661b3ffSreyk shuffle->id_shuffle[i2] = r;
638661b3ffSreyk shuffle->isindex++;
648661b3ffSreyk } while (r == 0);
658661b3ffSreyk
668661b3ffSreyk return (r);
678661b3ffSreyk }
68