По трем IP-адресам. Внутренний IP-адрес источника, внешний начальный, внешний конечный. Для себя накидал программку, на вход 3 ip на выходе внешний ip. Потом вокруг нее написал парсер правил iptables на питоне и теперь счастлив.
#include <stdio.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint32_t u32;
typedef uint64_t u64;
#define JHASH_INITVAL 0xdeadbeef
u32 parseIp(char *ipStr)
{
int i1, i2, i3, i4;
sscanf(ipStr, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
return (i1 << 24) + (i2 << 16) + (i3 << 8) + i4;
}
u32 rparseIp(char *ipStr)
{
int i1, i2, i3, i4;
sscanf(ipStr, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
return (i4 << 24) + (i3 << 16) + (i2 << 8) + i1;
}
static inline u32 rol32(u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
static inline u32 jhash_2words(u32 a, u32 b, u32 c)
{
a += JHASH_INITVAL;
b += JHASH_INITVAL;
c ^= b; c -= rol32(b, 14);
a ^= c; a -= rol32(c, 11);
b ^= a; b -= rol32(a, 25);
c ^= b; c -= rol32(b, 16);
a ^= c; a -= rol32(c, 4);
b ^= a; b -= rol32(a, 14);
c ^= b; c -= rol32(b, 24);
return c;
}
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("fail");
}
u32 minip, maxip, srcip, j, result;
minip = parseIp(argv[1]);
maxip = parseIp(argv[2]);
srcip = rparseIp(argv[3]);
j = jhash_2words(srcip, 0, 0);
j = ((u64)j * (maxip - minip + 1)) >> 32;
result = minip + j;
printf("%d.%d.%d.%d\n", (u8)(result >> 24), (u8)(result >> 16), (u8)(result >> 8), (u8)result);
return 0;
}