blob: a942bceeb7f45af5629e8bf669cad6583c9dbbf6 [file] [log] [blame]
jjakoa7cd2492003-04-11 09:40:12 +00001/*
2 * IP address pool functions.
jjakoc3213962004-09-09 20:23:50 +00003 * Copyright (C) 2003, 2004 Mondru AB.
jjakoa7cd2492003-04-11 09:40:12 +00004 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjakoa7cd2492003-04-11 09:40:12 +000010 */
11
jjako06e9f122004-01-19 18:37:58 +000012#include <sys/types.h>
jjakoa7cd2492003-04-11 09:40:12 +000013#include <netinet/in.h> /* in_addr */
14#include <stdlib.h> /* calloc */
15#include <stdio.h> /* sscanf */
jjakoc3213962004-09-09 20:23:50 +000016#include <syslog.h>
17#include <string.h>
18#include <sys/socket.h>
19#include <arpa/inet.h>
jjakoa7cd2492003-04-11 09:40:12 +000020
jjakoc3213962004-09-09 20:23:50 +000021#include "syserr.h"
jjakoa7cd2492003-04-11 09:40:12 +000022#include "ippool.h"
23
jjako88c22162003-07-06 19:33:18 +000024/**
25 * lookup()
26 * Generates a 32 bit hash.
27 * Based on public domain code by Bob Jenkins
28 * It should be one of the best hash functions around in terms of both
29 * statistical properties and speed. It is NOT recommended for cryptographic
30 * purposes.
31 **/
jjako3cfb81c2004-01-29 09:13:55 +000032unsigned long int static lookup( k, length, level)
jjako88c22162003-07-06 19:33:18 +000033register unsigned char *k; /* the key */
34register unsigned long int length; /* the length of the key */
35register unsigned long int level; /* the previous hash, or an arbitrary value*/
36{
jjakoa7cd2492003-04-11 09:40:12 +000037
jjakoa7cd2492003-04-11 09:40:12 +000038#define mix(a,b,c) \
39{ \
40 a -= b; a -= c; a ^= (c>>13); \
41 b -= c; b -= a; b ^= (a<<8); \
42 c -= a; c -= b; c ^= (b>>13); \
43 a -= b; a -= c; a ^= (c>>12); \
44 b -= c; b -= a; b ^= (a<<16); \
45 c -= a; c -= b; c ^= (b>>5); \
46 a -= b; a -= c; a ^= (c>>3); \
47 b -= c; b -= a; b ^= (a<<10); \
48 c -= a; c -= b; c ^= (b>>15); \
49}
jjakoa7cd2492003-04-11 09:40:12 +000050
jjako88c22162003-07-06 19:33:18 +000051 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
52 typedef unsigned char ub1; /* unsigned 1-byte quantities */
53 register unsigned long int a,b,c,len;
54
55 /* Set up the internal state */
56 len = length;
57 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
58 c = level; /* the previous hash value */
59
60 /*---------------------------------------- handle most of the key */
61 while (len >= 12)
62 {
jjakoa7cd2492003-04-11 09:40:12 +000063 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
64 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
65 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
66 mix(a,b,c);
67 k += 12; len -= 12;
jjako88c22162003-07-06 19:33:18 +000068 }
69
70 /*------------------------------------- handle the last 11 bytes */
71 c += length;
72 switch(len) /* all the case statements fall through */
73 {
74 case 11: c+=((ub4)k[10]<<24);
75 case 10: c+=((ub4)k[9]<<16);
76 case 9 : c+=((ub4)k[8]<<8);
jjakoa7cd2492003-04-11 09:40:12 +000077 /* the first byte of c is reserved for the length */
jjako88c22162003-07-06 19:33:18 +000078 case 8 : b+=((ub4)k[7]<<24);
79 case 7 : b+=((ub4)k[6]<<16);
80 case 6 : b+=((ub4)k[5]<<8);
81 case 5 : b+=k[4];
82 case 4 : a+=((ub4)k[3]<<24);
83 case 3 : a+=((ub4)k[2]<<16);
84 case 2 : a+=((ub4)k[1]<<8);
85 case 1 : a+=k[0];
86 /* case 0: nothing left to add */
87 }
88 mix(a,b,c);
89 /*-------------------------------------------- report the result */
90 return c;
jjakoa7cd2492003-04-11 09:40:12 +000091}
92
jjakoa7cd2492003-04-11 09:40:12 +000093
94int ippool_printaddr(struct ippool_t *this) {
95 int n;
96 printf("ippool_printaddr\n");
jjako88c22162003-07-06 19:33:18 +000097 printf("Firstdyn %d\n", this->firstdyn - this->member);
98 printf("Lastdyn %d\n", this->lastdyn - this->member);
99 printf("Firststat %d\n", this->firststat - this->member);
100 printf("Laststat %d\n", this->laststat - this->member);
jjakoa7cd2492003-04-11 09:40:12 +0000101 printf("Listsize %d\n", this->listsize);
102
103 for (n=0; n<this->listsize; n++) {
jjakoc3213962004-09-09 20:23:50 +0000104 printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
jjakoa7cd2492003-04-11 09:40:12 +0000105 n,
106 this->member[n].inuse,
107 this->member[n].prev - this->member,
108 this->member[n].next - this->member,
jjakoc3213962004-09-09 20:23:50 +0000109 inet_ntoa(this->member[n].addr),
jjakoa7cd2492003-04-11 09:40:12 +0000110 this->member[n].addr.s_addr
111 );
112 }
113 return 0;
114}
115
116
jjako88c22162003-07-06 19:33:18 +0000117int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member) {
118 uint32_t hash;
119 struct ippoolm_t *p;
120 struct ippoolm_t *p_prev = NULL;
121
122 /* Insert into hash table */
123 hash = ippool_hash4(&member->addr) & this->hashmask;
124 for (p = this->hash[hash]; p; p = p->nexthash)
125 p_prev = p;
126 if (!p_prev)
127 this->hash[hash] = member;
128 else
129 p_prev->nexthash = member;
130 return 0; /* Always OK to insert */
131}
132
133int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member) {
134 uint32_t hash;
135 struct ippoolm_t *p;
136 struct ippoolm_t *p_prev = NULL;
137
138 /* Find in hash table */
139 hash = ippool_hash4(&member->addr) & this->hashmask;
140 for (p = this->hash[hash]; p; p = p->nexthash) {
141 if (p == member) {
142 break;
143 }
144 p_prev = p;
145 }
146
147 if (p!= member) {
jjakoc3213962004-09-09 20:23:50 +0000148 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
149 "ippool_hashdel: Tried to delete member not in hash table");
150 return -1;
jjako88c22162003-07-06 19:33:18 +0000151 }
152
153 if (!p_prev)
jjakoc3213962004-09-09 20:23:50 +0000154 this->hash[hash] = p->nexthash;
jjako88c22162003-07-06 19:33:18 +0000155 else
jjakoc3213962004-09-09 20:23:50 +0000156 p_prev->nexthash = p->nexthash;
jjako88c22162003-07-06 19:33:18 +0000157
158 return 0;
159}
160
161
jjakoa7cd2492003-04-11 09:40:12 +0000162unsigned long int ippool_hash4(struct in_addr *addr) {
jjakoc3213962004-09-09 20:23:50 +0000163 return lookup((unsigned char*) &addr->s_addr, sizeof(addr->s_addr), 0);
jjakoa7cd2492003-04-11 09:40:12 +0000164}
165
166#ifndef IPPOOL_NOIP6
167unsigned long int ippool_hash6(struct in6_addr *addr) {
jjakoc3213962004-09-09 20:23:50 +0000168 return lookup((unsigned char*) addr->u6_addr8, sizeof(addr->u6_addr8), 0);
jjakoa7cd2492003-04-11 09:40:12 +0000169}
170#endif
171
172
173/* Get IP address and mask */
174int ippool_aton(struct in_addr *addr, struct in_addr *mask,
175 char *pool, int number) {
176
177 /* Parse only first instance of network for now */
178 /* Eventually "number" will indicate the token which we want to parse */
179
180 unsigned int a1, a2, a3, a4;
181 unsigned int m1, m2, m3, m4;
182 int c;
183 unsigned int m;
184 int masklog;
185
186 c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
187 &a1, &a2, &a3, &a4,
188 &m1, &m2, &m3, &m4);
189 switch (c) {
190 case 4:
jjako504ee452003-08-20 15:25:54 +0000191 mask->s_addr = 0xffffffff;
jjakoa7cd2492003-04-11 09:40:12 +0000192 break;
193 case 5:
194 if (m1 < 0 || m1 > 32) {
jjakoc3213962004-09-09 20:23:50 +0000195 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000196 return -1; /* Invalid mask */
197 }
198 mask->s_addr = htonl(0xffffffff << (32 - m1));
199 break;
200 case 8:
jjakoc3213962004-09-09 20:23:50 +0000201 if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
202 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000203 return -1; /* Wrong mask format */
jjakoc3213962004-09-09 20:23:50 +0000204 }
jjakoa7cd2492003-04-11 09:40:12 +0000205 m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
206 for (masklog = 0; ((1 << masklog) < ((~m)+1)); masklog++);
jjakoc3213962004-09-09 20:23:50 +0000207 if (((~m)+1) != (1 << masklog)) {
208 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000209 return -1; /* Wrong mask format (not all ones followed by all zeros)*/
jjakoc3213962004-09-09 20:23:50 +0000210 }
jjakoa7cd2492003-04-11 09:40:12 +0000211 mask->s_addr = htonl(m);
212 break;
213 default:
jjakoc3213962004-09-09 20:23:50 +0000214 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000215 return -1; /* Invalid mask */
216 }
217
jjakoc3213962004-09-09 20:23:50 +0000218 if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
219 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Wrong IP address format");
220 return -1;
221 }
jjakoa7cd2492003-04-11 09:40:12 +0000222 else
223 addr->s_addr = htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
224
225 return 0;
226}
227
228/* Create new address pool */
jjako88c22162003-07-06 19:33:18 +0000229int ippool_new(struct ippool_t **this, char *dyn, char *stat,
230 int allowdyn, int allowstat, int flags) {
jjakoa7cd2492003-04-11 09:40:12 +0000231
jjako88c22162003-07-06 19:33:18 +0000232 /* Parse only first instance of pool for now */
jjakoa7cd2492003-04-11 09:40:12 +0000233
234 int i;
jjakoa7cd2492003-04-11 09:40:12 +0000235 struct in_addr addr;
236 struct in_addr mask;
jjako88c22162003-07-06 19:33:18 +0000237 struct in_addr stataddr;
238 struct in_addr statmask;
jjakoa7cd2492003-04-11 09:40:12 +0000239 unsigned int m;
240 unsigned int listsize;
jjako88c22162003-07-06 19:33:18 +0000241 unsigned int dynsize;
242 unsigned int statsize;
jjakoa7cd2492003-04-11 09:40:12 +0000243
jjako88c22162003-07-06 19:33:18 +0000244 if (!allowdyn) {
245 dynsize = 0;
246 }
247 else {
jjakoc3213962004-09-09 20:23:50 +0000248 if (ippool_aton(&addr, &mask, dyn, 0)) {
249 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
250 "Failed to parse dynamic pool");
251 return -1;
jjakoc6762cf2004-04-28 14:52:58 +0000252 }
253
jjako504ee452003-08-20 15:25:54 +0000254 /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
255 if (flags & IPPOOL_NOGATEWAY) {
256 flags |= IPPOOL_NONETWORK;
257 }
jjako88c22162003-07-06 19:33:18 +0000258
259 m = ntohl(mask.s_addr);
260 dynsize = ((~m)+1);
261 if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
262 dynsize--;
jjako504ee452003-08-20 15:25:54 +0000263 if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
264 dynsize--;
jjako88c22162003-07-06 19:33:18 +0000265 if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
266 dynsize--;
267 }
jjakoa7cd2492003-04-11 09:40:12 +0000268
jjako88c22162003-07-06 19:33:18 +0000269 if (!allowstat) {
270 statsize = 0;
271 stataddr.s_addr = 0;
272 statmask.s_addr = 0;
273 }
274 else {
jjakoc3213962004-09-09 20:23:50 +0000275 if (ippool_aton(&stataddr, &statmask, stat, 0)) {
276 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
277 "Failed to parse static range");
278 return -1;
279 }
280
jjako88c22162003-07-06 19:33:18 +0000281 m = ntohl(statmask.s_addr);
282 statsize = ((~m)+1);
283 if (statsize > IPPOOL_STATSIZE) statsize = IPPOOL_STATSIZE;
284 }
285
286 listsize = dynsize + statsize; /* Allocate space for static IP addresses */
jjakoa7cd2492003-04-11 09:40:12 +0000287
288 if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
jjakoc3213962004-09-09 20:23:50 +0000289 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
290 "Failed to allocate memory for ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000291 return -1;
292 }
293
jjako88c22162003-07-06 19:33:18 +0000294 (*this)->allowdyn = allowdyn;
295 (*this)->allowstat = allowstat;
296 (*this)->stataddr = stataddr;
297 (*this)->statmask = statmask;
298
jjakoa7cd2492003-04-11 09:40:12 +0000299 (*this)->listsize += listsize;
jjako88c22162003-07-06 19:33:18 +0000300 if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))){
jjakoc3213962004-09-09 20:23:50 +0000301 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
302 "Failed to allocate memory for members in ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000303 return -1;
304 }
305
306 for ((*this)->hashlog = 0;
307 ((1 << (*this)->hashlog) < listsize);
308 (*this)->hashlog++);
309
310 /* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
311
312 /* Determine hashsize */
313 (*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet*/
314 (*this)->hashmask = (*this)->hashsize -1;
315
316 /* Allocate hash table */
317 if (!((*this)->hash = calloc(sizeof(struct ippoolm_t), (*this)->hashsize))){
jjakoc3213962004-09-09 20:23:50 +0000318 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
319 "Failed to allocate memory for hash members in ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000320 return -1;
321 }
322
jjako88c22162003-07-06 19:33:18 +0000323 (*this)->firstdyn = NULL;
324 (*this)->lastdyn = NULL;
325 for (i = 0; i<dynsize; i++) {
jjakoa7cd2492003-04-11 09:40:12 +0000326
jjakoc3213962004-09-09 20:23:50 +0000327 if (flags & IPPOOL_NOGATEWAY)
jjako504ee452003-08-20 15:25:54 +0000328 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 2);
329 else if (flags & IPPOOL_NONETWORK)
jjakoa7cd2492003-04-11 09:40:12 +0000330 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 1);
331 else
332 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i);
jjako504ee452003-08-20 15:25:54 +0000333
jjakoa7cd2492003-04-11 09:40:12 +0000334 (*this)->member[i].inuse = 0;
jjakoa7cd2492003-04-11 09:40:12 +0000335
336 /* Insert into list of unused */
jjako88c22162003-07-06 19:33:18 +0000337 (*this)->member[i].prev = (*this)->lastdyn;
338 if ((*this)->lastdyn) {
339 (*this)->lastdyn->next = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000340 }
341 else {
jjako88c22162003-07-06 19:33:18 +0000342 (*this)->firstdyn = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000343 }
jjako88c22162003-07-06 19:33:18 +0000344 (*this)->lastdyn = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000345 (*this)->member[i].next = NULL; /* Redundant */
346
jjako88c22162003-07-06 19:33:18 +0000347 ippool_hashadd(*this, &(*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000348 }
jjako88c22162003-07-06 19:33:18 +0000349
350 (*this)->firststat = NULL;
351 (*this)->laststat = NULL;
352 for (i = dynsize; i<listsize; i++) {
353
354 (*this)->member[i].addr.s_addr = 0;
355 (*this)->member[i].inuse = 0;
356
357 /* Insert into list of unused */
358 (*this)->member[i].prev = (*this)->laststat;
359 if ((*this)->laststat) {
360 (*this)->laststat->next = &((*this)->member[i]);
361 }
362 else {
363 (*this)->firststat = &((*this)->member[i]);
364 }
365 (*this)->laststat = &((*this)->member[i]);
366 (*this)->member[i].next = NULL; /* Redundant */
367 }
368
369 if (0) ippool_printaddr(*this);
jjakoa7cd2492003-04-11 09:40:12 +0000370 return 0;
371}
372
373/* Delete existing address pool */
374int ippool_free(struct ippool_t *this) {
375 free(this->hash);
376 free(this->member);
377 free(this);
378 return 0; /* Always OK */
379}
380
381/* Find an IP address in the pool */
382int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
383 struct in_addr *addr) {
384 struct ippoolm_t *p;
385 uint32_t hash;
386
387 /* Find in hash table */
388 hash = ippool_hash4(addr) & this->hashmask;
389 for (p = this->hash[hash]; p; p = p->nexthash) {
390 if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
391 *member = p;
392 return 0;
393 }
394 }
395 *member = NULL;
jjakoc3213962004-09-09 20:23:50 +0000396 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found");
397 return -1;
jjakoa7cd2492003-04-11 09:40:12 +0000398}
399
jjako88c22162003-07-06 19:33:18 +0000400/**
401 * ippool_newip
402 * Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
403 * check to see if the given address is available. If available within
404 * dynamic address space allocate it there, otherwise allocate within static
405 * address space.
406**/
jjakoa7cd2492003-04-11 09:40:12 +0000407int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
408 struct in_addr *addr) {
409 struct ippoolm_t *p;
410 struct ippoolm_t *p2 = NULL;
411 uint32_t hash;
412
jjako88c22162003-07-06 19:33:18 +0000413 /* If static:
414 * Look in dynaddr.
415 * If found remove from firstdyn/lastdyn linked list.
416 * Else allocate from stataddr.
417 * Remove from firststat/laststat linked list.
418 * Insert into hash table.
419 *
420 * If dynamic
421 * Remove from firstdyn/lastdyn linked list.
422 *
423 */
424
425 if (0) ippool_printaddr(this);
426
427 /* First check to see if this type of address is allowed */
428 if ((addr) && (addr->s_addr)) { /* IP address given */
429 if (!this->allowstat) {
jjakoc3213962004-09-09 20:23:50 +0000430 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static IP address not allowed");
431 return -1;
jjako88c22162003-07-06 19:33:18 +0000432 }
433 if ((addr->s_addr & this->statmask.s_addr) != this->stataddr.s_addr) {
jjakoc3213962004-09-09 20:23:50 +0000434 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static out of range");
435 return -1;
jjako88c22162003-07-06 19:33:18 +0000436 }
437 }
438 else {
439 if (!this->allowdyn) {
jjakoc3213962004-09-09 20:23:50 +0000440 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
441 "Dynamic IP address not allowed");
442 return -1;
jjako88c22162003-07-06 19:33:18 +0000443 }
444 }
jjakoa7cd2492003-04-11 09:40:12 +0000445
446 if ((addr) && (addr->s_addr)) { /* IP address given */
447 /* Find in hash table */
448 hash = ippool_hash4(addr) & this->hashmask;
449 for (p = this->hash[hash]; p; p = p->nexthash) {
450 if ((p->addr.s_addr == addr->s_addr)) {
451 p2 = p;
452 break;
453 }
454 }
455 }
456 else { /* No ip address given */
jjakoc3213962004-09-09 20:23:50 +0000457 if (!this ->firstdyn) {
458 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
459 "No more IP addresses available");
460 return -1;
461 }
jjako88c22162003-07-06 19:33:18 +0000462 else
463 p2 = this ->firstdyn;
jjakoa7cd2492003-04-11 09:40:12 +0000464 }
465
jjako88c22162003-07-06 19:33:18 +0000466 if (p2) { /* Was allocated from dynamic address pool */
jjakoc3213962004-09-09 20:23:50 +0000467 if (p2->inuse) {
468 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
469 "IP address allready in use");
470 return -1; /* Allready in use / Should not happen */
471 }
472
jjako88c22162003-07-06 19:33:18 +0000473 /* Remove from linked list of free dynamic addresses */
474 if (p2->prev)
475 p2->prev->next = p2->next;
476 else
477 this->firstdyn = p2->next;
478 if (p2->next)
479 p2->next->prev = p2->prev;
480 else
481 this->lastdyn = p2->prev;
482 p2->next = NULL;
483 p2->prev = NULL;
484 p2->inuse = 1; /* Dynamic address in use */
485
486 *member = p2;
487 if (0) ippool_printaddr(this);
488 return 0; /* Success */
489 }
490
491 /* It was not possible to allocate from dynamic address pool */
492 /* Try to allocate from static address space */
493
494 if ((addr) && (addr->s_addr)) { /* IP address given */
jjakoc3213962004-09-09 20:23:50 +0000495 if (this->firststat) {
496 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
497 "No more IP addresses available");
jjako88c22162003-07-06 19:33:18 +0000498 return -1; /* No more available */
jjakoc3213962004-09-09 20:23:50 +0000499 }
jjako88c22162003-07-06 19:33:18 +0000500 else
501 p2 = this ->firststat;
502
503 /* Remove from linked list of free static addresses */
504 if (p2->prev)
505 p2->prev->next = p2->next;
506 else
507 this->firststat = p2->next;
508 if (p2->next)
509 p2->next->prev = p2->prev;
510 else
511 this->laststat = p2->prev;
512 p2->next = NULL;
513 p2->prev = NULL;
514 p2->inuse = 1; /* Static address in use */
515
jjakoc3213962004-09-09 20:23:50 +0000516 memcpy(&p2->addr, addr, sizeof(addr));
jjako88c22162003-07-06 19:33:18 +0000517 *member = p2;
jjakoc3213962004-09-09 20:23:50 +0000518 ippool_hashadd(this, *member);
jjako88c22162003-07-06 19:33:18 +0000519 if (0) ippool_printaddr(this);
520 return 0; /* Success */
521 }
522
jjakoc3213962004-09-09 20:23:50 +0000523 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
524 "Could not allocate IP address");
jjako88c22162003-07-06 19:33:18 +0000525 return -1; /* Should never get here. TODO: Bad code */
jjakoa7cd2492003-04-11 09:40:12 +0000526}
527
528
jjako88c22162003-07-06 19:33:18 +0000529int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member) {
jjakoa7cd2492003-04-11 09:40:12 +0000530
jjako88c22162003-07-06 19:33:18 +0000531 if (0) ippool_printaddr(this);
jjakoa7cd2492003-04-11 09:40:12 +0000532
jjakoc3213962004-09-09 20:23:50 +0000533 if (!member->inuse) {
534 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
535 return -1; /* Not in use: Should not happen */
536 }
jjakoa7cd2492003-04-11 09:40:12 +0000537
jjako88c22162003-07-06 19:33:18 +0000538 switch (member->inuse) {
539 case 0: /* Not in use: Should not happen */
jjakoc3213962004-09-09 20:23:50 +0000540 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
jjako88c22162003-07-06 19:33:18 +0000541 return -1;
542 case 1: /* Allocated from dynamic address space */
543 /* Insert into list of unused */
544 member->prev = this->lastdyn;
545 if (this->lastdyn) {
546 this->lastdyn->next = member;
547 }
548 else {
549 this->firstdyn = member;
550 }
551 this->lastdyn = member;
552
553 member->inuse = 0;
554 member->peer = NULL;
555 if (0) ippool_printaddr(this);
556 return 0;
557 case 2: /* Allocated from static address space */
558 if (ippool_hashdel(this, member))
559 return -1;
560 /* Insert into list of unused */
561 member->prev = this->laststat;
562 if (this->laststat) {
563 this->laststat->next = member;
564 }
565 else {
566 this->firststat = member;
567 }
568 this->laststat = member;
569
570 member->inuse = 0;
571 member->addr.s_addr = 0;
572 member->peer = NULL;
573 member->nexthash = NULL;
574 if (0) ippool_printaddr(this);
575 return 0;
576 default: /* Should not happen */
jjakoc3213962004-09-09 20:23:50 +0000577 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Could not free IP address");
jjako88c22162003-07-06 19:33:18 +0000578 return -1;
jjakoa7cd2492003-04-11 09:40:12 +0000579 }
jjakoa7cd2492003-04-11 09:40:12 +0000580}
581
582
583#ifndef IPPOOL_NOIP6
584extern unsigned long int ippool_hash6(struct in6_addr *addr);
585extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
586extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
587#endif