+#define TCP_RNDISS_ROUNDS 16
+#define TCP_RNDISS_OUT 7200
+#define TCP_RNDISS_MAX 30000
+
+u_int8_t tcp_rndiss_sbox[128];
+u_int16_t tcp_rndiss_msb;
+u_int16_t tcp_rndiss_cnt;
+long tcp_rndiss_reseed;
+
+u_int16_t
+tcp_rndiss_encrypt(val)
+ u_int16_t val;
+{
+ u_int16_t sum = 0, i;
+
+ for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
+ sum += 0x79b9;
+ val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7;
+ val = ((val & 0xff) << 7) | (val >> 8);
+ }
+
+ return val;
+}
+
+void
+tcp_rndiss_init()
+{
+ struct timeval time;
+
+ getmicrotime(&time);
+ read_random(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox));
+
+ tcp_rndiss_reseed = time.tv_sec + TCP_RNDISS_OUT;
+ tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
+ tcp_rndiss_cnt = 0;
+}
+
+tcp_seq
+tcp_rndiss_next()
+{
+ u_int32_t tmp;
+ struct timeval time;
+
+ getmicrotime(&time);
+
+ if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
+ time.tv_sec > tcp_rndiss_reseed)
+ tcp_rndiss_init();
+
+ tmp = random();
+
+ /* (tmp & 0x7fff) ensures a 32768 byte gap between ISS */
+ return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) |
+ (tmp & 0x7fff);
+}
+
+