+
+
+ CSTAT(call_free_ip_address);
+
+}
+
+//
+// Fsck the address pool against the session table.
+// Normally only called when we become a master.
+//
+// This isn't perfect: We aren't keep tracking of which
+// users used to have an IP address.
+//
+void rebuild_address_pool(void)
+{
+ int i;
+
+ //
+ // Zero the IP pool allocation, and build
+ // a map from IP address to pool index.
+ for (i = 1; i < MAXIPPOOL; ++i) {
+ ip_address_pool[i].assigned = 0;
+ ip_address_pool[i].session = 0;
+ if (!ip_address_pool[i].address)
+ continue;
+
+ cache_ipmap(ip_address_pool[i].address, -i); // Map pool IP to pool index.
+ }
+
+ for (i = 0; i < MAXSESSION; ++i) {
+ int ipid;
+ if (!session[i].ip || !session[i].tunnel)
+ continue;
+ ipid = - lookup_ipmap(htonl(session[i].ip));
+
+ if (session[i].ip_pool_index < 0) { // Not allocated out of the pool.
+ if (ipid < 1) // Not found in the pool either? good.
+ continue;
+
+ log(0, 0, i, 0, "Session %d has an IP address (%s) that was marked static, but is in the pool (%d)!\n",
+ i, inet_toa(session[i].ip), ipid);
+
+ // Fall through and process it as part of the pool.
+ }
+
+
+ if (ipid > MAXIPPOOL || ipid < 0) {
+ log(0, 0, i, 0, "Session %d has a pool IP that's not found in the pool! (%d)\n", i, ipid);
+ ipid = -1;
+ session[i].ip_pool_index = ipid;
+ continue;
+ }
+
+ ip_address_pool[ipid].assigned = 1;
+ ip_address_pool[ipid].session = i;
+ ip_address_pool[ipid].last = time_now;
+ strncpy(ip_address_pool[ipid].user, session[i].user, sizeof(ip_address_pool[ipid].user) - 1);
+ session[i].ip_pool_index = ipid;
+ cache_ipmap(session[i].ip, i); // Fix the ip map.
+ }
+}
+
+//
+// Fix the address pool to match a changed session.
+// (usually when the master sends us an update).
+void fix_address_pool(int sid)
+{
+ int ipid;
+
+ ipid = session[sid].ip_pool_index;
+
+ if (ipid > ip_pool_size)
+ return; // Ignore it. rebuild_address_pool will fix it up.
+
+ if (ip_address_pool[ipid].address != session[sid].ip)
+ return; // Just ignore it. rebuild_address_pool will take care of it.
+
+ ip_address_pool[ipid].assigned = 1;
+ ip_address_pool[ipid].session = sid;
+ ip_address_pool[ipid].last = time_now;
+ strncpy(ip_address_pool[ipid].user, session[sid].user, sizeof(ip_address_pool[ipid].user) - 1);
+}
+
+//
+// Add a block of addresses to the IP pool to hand out.
+//
+void add_to_ip_pool(u32 addr, u32 mask)
+{
+ int i;
+ if (mask == 0)
+ mask = 0xffffffff; // Host route only.
+
+ addr &= mask;
+
+ if (ip_pool_size >= MAXIPPOOL) // Pool is full!
+ return ;
+
+ for (i = addr ;(i & mask) == addr; ++i)
+ {
+ if ((i & 0xff) == 0 || (i&0xff) == 255)
+ continue; // Skip 0 and broadcast addresses.
+
+ ip_address_pool[ip_pool_size].address = i;
+ ip_address_pool[ip_pool_size].assigned = 0;
+ ++ip_pool_size;
+ if (ip_pool_size >= MAXIPPOOL)
+ {
+ log(0,0,0,0, "Overflowed IP pool adding %s\n", inet_toa(htonl(addr)) );
+ return;
+ }
+ }