diff --git a/scapy.py b/scapy.py index 097142b0b72fadd51176ac24c42d905be7f0bbfd..a39871e99d0d717b5645ae2d88fe44533912c604 100755 --- a/scapy.py +++ b/scapy.py @@ -1354,6 +1354,45 @@ else: ## Random numbers ## #################### +def randseq(inf, sup, seed=None, forever=1, renewkeys=0): + """iterate through a sequence in random order. + When all the values have been drawn, if forever=1, the drawing is done again. + If renewkeys=0, the draw will be in the same order, guaranteeing that the same + number will be drawn in not less than the number of integers of the sequence""" + rnd = random.Random(seed) + sbox_size = 256 + + top = sup-inf+1 + + n=0 + while (1<<n) < top: + n += 1 + + fs = min(3,(n+1)/2) + fsmask = 2**fs-1 + rounds = max(n,3) + turns = 0 + + while 1: + if turns == 0 or renewkeys: + sbox = [rnd.randint(0,fsmask) for k in xrange(sbox_size)] + turns += 1 + i = 0 + while i < 2**n: + ct = i + i += 1 + for k in range(rounds): # Unbalanced Feistel Network + lsb = ct & fsmask + ct >>= fs + lsb ^= sbox[ct%sbox_size] + ct |= lsb << (n-fs) + + if ct < top: + yield inf+ct + if not forever: + break + + class VolatileValue: def __repr__(self): return "<%s>" % self.__class__.__name__ @@ -1373,11 +1412,9 @@ class RandNum(RandField): min = 0 max = 0 def __init__(self, min, max): - self.min = min - self.max = max + self.seq = randseq(min,max) def _fix(self): - # XXX: replace with sth that guarantee unicity - return random.randrange(self.min, self.max) + return self.seq.next() class RandNumGamma(RandField): def __init__(self, alpha, beta):