blob: efd927ec5375ab0cb226d19e3c9c92fb8e518e4b [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
jjako0fe0df02004-09-17 11:30:40 +000012#include "../config.h"
13
14#ifdef HAVE_STDINT_H
15#include <stdint.h>
16#endif
17
jjako06e9f122004-01-19 18:37:58 +000018#include <sys/types.h>
jjakoa7cd2492003-04-11 09:40:12 +000019#include <netinet/in.h> /* in_addr */
20#include <stdlib.h> /* calloc */
21#include <stdio.h> /* sscanf */
jjakoc3213962004-09-09 20:23:50 +000022#include <syslog.h>
23#include <string.h>
24#include <sys/socket.h>
25#include <arpa/inet.h>
jjakoa7cd2492003-04-11 09:40:12 +000026
jjakoc3213962004-09-09 20:23:50 +000027#include "syserr.h"
jjakoa7cd2492003-04-11 09:40:12 +000028#include "ippool.h"
29
jjako88c22162003-07-06 19:33:18 +000030/**
31 * lookup()
32 * Generates a 32 bit hash.
33 * Based on public domain code by Bob Jenkins
34 * It should be one of the best hash functions around in terms of both
35 * statistical properties and speed. It is NOT recommended for cryptographic
36 * purposes.
37 **/
jjako3cfb81c2004-01-29 09:13:55 +000038unsigned long int static lookup( k, length, level)
jjako88c22162003-07-06 19:33:18 +000039register unsigned char *k; /* the key */
40register unsigned long int length; /* the length of the key */
41register unsigned long int level; /* the previous hash, or an arbitrary value*/
42{
jjakoa7cd2492003-04-11 09:40:12 +000043
jjakoa7cd2492003-04-11 09:40:12 +000044#define mix(a,b,c) \
45{ \
46 a -= b; a -= c; a ^= (c>>13); \
47 b -= c; b -= a; b ^= (a<<8); \
48 c -= a; c -= b; c ^= (b>>13); \
49 a -= b; a -= c; a ^= (c>>12); \
50 b -= c; b -= a; b ^= (a<<16); \
51 c -= a; c -= b; c ^= (b>>5); \
52 a -= b; a -= c; a ^= (c>>3); \
53 b -= c; b -= a; b ^= (a<<10); \
54 c -= a; c -= b; c ^= (b>>15); \
55}
jjakoa7cd2492003-04-11 09:40:12 +000056
jjako88c22162003-07-06 19:33:18 +000057 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
58 typedef unsigned char ub1; /* unsigned 1-byte quantities */
59 register unsigned long int a,b,c,len;
60
61 /* Set up the internal state */
62 len = length;
63 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
64 c = level; /* the previous hash value */
65
66 /*---------------------------------------- handle most of the key */
67 while (len >= 12)
68 {
jjakoa7cd2492003-04-11 09:40:12 +000069 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
70 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
71 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
72 mix(a,b,c);
73 k += 12; len -= 12;
jjako88c22162003-07-06 19:33:18 +000074 }
75
76 /*------------------------------------- handle the last 11 bytes */
77 c += length;
78 switch(len) /* all the case statements fall through */
79 {
80 case 11: c+=((ub4)k[10]<<24);
81 case 10: c+=((ub4)k[9]<<16);
82 case 9 : c+=((ub4)k[8]<<8);
jjakoa7cd2492003-04-11 09:40:12 +000083 /* the first byte of c is reserved for the length */
jjako88c22162003-07-06 19:33:18 +000084 case 8 : b+=((ub4)k[7]<<24);
85 case 7 : b+=((ub4)k[6]<<16);
86 case 6 : b+=((ub4)k[5]<<8);
87 case 5 : b+=k[4];
88 case 4 : a+=((ub4)k[3]<<24);
89 case 3 : a+=((ub4)k[2]<<16);
90 case 2 : a+=((ub4)k[1]<<8);
91 case 1 : a+=k[0];
92 /* case 0: nothing left to add */
93 }
94 mix(a,b,c);
95 /*-------------------------------------------- report the result */
96 return c;
jjakoa7cd2492003-04-11 09:40:12 +000097}
98
jjakoa7cd2492003-04-11 09:40:12 +000099
100int ippool_printaddr(struct ippool_t *this) {
101 int n;
102 printf("ippool_printaddr\n");
jjako88c22162003-07-06 19:33:18 +0000103 printf("Firstdyn %d\n", this->firstdyn - this->member);
104 printf("Lastdyn %d\n", this->lastdyn - this->member);
105 printf("Firststat %d\n", this->firststat - this->member);
106 printf("Laststat %d\n", this->laststat - this->member);
jjakoa7cd2492003-04-11 09:40:12 +0000107 printf("Listsize %d\n", this->listsize);
108
109 for (n=0; n<this->listsize; n++) {
jjakoc3213962004-09-09 20:23:50 +0000110 printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
jjakoa7cd2492003-04-11 09:40:12 +0000111 n,
112 this->member[n].inuse,
113 this->member[n].prev - this->member,
114 this->member[n].next - this->member,
jjakoc3213962004-09-09 20:23:50 +0000115 inet_ntoa(this->member[n].addr),
jjakoa7cd2492003-04-11 09:40:12 +0000116 this->member[n].addr.s_addr
117 );
118 }
119 return 0;
120}
121
122
jjako88c22162003-07-06 19:33:18 +0000123int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member) {
124 uint32_t hash;
125 struct ippoolm_t *p;
126 struct ippoolm_t *p_prev = NULL;
127
128 /* Insert into hash table */
129 hash = ippool_hash4(&member->addr) & this->hashmask;
130 for (p = this->hash[hash]; p; p = p->nexthash)
131 p_prev = p;
132 if (!p_prev)
133 this->hash[hash] = member;
134 else
135 p_prev->nexthash = member;
136 return 0; /* Always OK to insert */
137}
138
139int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member) {
140 uint32_t hash;
141 struct ippoolm_t *p;
142 struct ippoolm_t *p_prev = NULL;
143
144 /* Find in hash table */
145 hash = ippool_hash4(&member->addr) & this->hashmask;
146 for (p = this->hash[hash]; p; p = p->nexthash) {
147 if (p == member) {
148 break;
149 }
150 p_prev = p;
151 }
152
153 if (p!= member) {
jjakoc3213962004-09-09 20:23:50 +0000154 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
155 "ippool_hashdel: Tried to delete member not in hash table");
156 return -1;
jjako88c22162003-07-06 19:33:18 +0000157 }
158
159 if (!p_prev)
jjakoc3213962004-09-09 20:23:50 +0000160 this->hash[hash] = p->nexthash;
jjako88c22162003-07-06 19:33:18 +0000161 else
jjakoc3213962004-09-09 20:23:50 +0000162 p_prev->nexthash = p->nexthash;
jjako88c22162003-07-06 19:33:18 +0000163
164 return 0;
165}
166
167
jjakoa7cd2492003-04-11 09:40:12 +0000168unsigned long int ippool_hash4(struct in_addr *addr) {
jjakoc3213962004-09-09 20:23:50 +0000169 return lookup((unsigned char*) &addr->s_addr, sizeof(addr->s_addr), 0);
jjakoa7cd2492003-04-11 09:40:12 +0000170}
171
172#ifndef IPPOOL_NOIP6
173unsigned long int ippool_hash6(struct in6_addr *addr) {
jjakoc3213962004-09-09 20:23:50 +0000174 return lookup((unsigned char*) addr->u6_addr8, sizeof(addr->u6_addr8), 0);
jjakoa7cd2492003-04-11 09:40:12 +0000175}
176#endif
177
178
179/* Get IP address and mask */
180int ippool_aton(struct in_addr *addr, struct in_addr *mask,
181 char *pool, int number) {
182
183 /* Parse only first instance of network for now */
184 /* Eventually "number" will indicate the token which we want to parse */
185
186 unsigned int a1, a2, a3, a4;
187 unsigned int m1, m2, m3, m4;
188 int c;
189 unsigned int m;
190 int masklog;
191
192 c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
193 &a1, &a2, &a3, &a4,
194 &m1, &m2, &m3, &m4);
195 switch (c) {
196 case 4:
jjako504ee452003-08-20 15:25:54 +0000197 mask->s_addr = 0xffffffff;
jjakoa7cd2492003-04-11 09:40:12 +0000198 break;
199 case 5:
200 if (m1 < 0 || m1 > 32) {
jjakoc3213962004-09-09 20:23:50 +0000201 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000202 return -1; /* Invalid mask */
203 }
204 mask->s_addr = htonl(0xffffffff << (32 - m1));
205 break;
206 case 8:
jjakoc3213962004-09-09 20:23:50 +0000207 if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
208 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000209 return -1; /* Wrong mask format */
jjakoc3213962004-09-09 20:23:50 +0000210 }
jjakoa7cd2492003-04-11 09:40:12 +0000211 m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
212 for (masklog = 0; ((1 << masklog) < ((~m)+1)); masklog++);
jjakoc3213962004-09-09 20:23:50 +0000213 if (((~m)+1) != (1 << masklog)) {
214 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000215 return -1; /* Wrong mask format (not all ones followed by all zeros)*/
jjakoc3213962004-09-09 20:23:50 +0000216 }
jjakoa7cd2492003-04-11 09:40:12 +0000217 mask->s_addr = htonl(m);
218 break;
219 default:
jjakoc3213962004-09-09 20:23:50 +0000220 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
jjakoa7cd2492003-04-11 09:40:12 +0000221 return -1; /* Invalid mask */
222 }
223
jjakoc3213962004-09-09 20:23:50 +0000224 if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
225 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Wrong IP address format");
226 return -1;
227 }
jjakoa7cd2492003-04-11 09:40:12 +0000228 else
229 addr->s_addr = htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
230
231 return 0;
232}
233
234/* Create new address pool */
jjako88c22162003-07-06 19:33:18 +0000235int ippool_new(struct ippool_t **this, char *dyn, char *stat,
236 int allowdyn, int allowstat, int flags) {
jjakoa7cd2492003-04-11 09:40:12 +0000237
jjako88c22162003-07-06 19:33:18 +0000238 /* Parse only first instance of pool for now */
jjakoa7cd2492003-04-11 09:40:12 +0000239
240 int i;
jjakoa7cd2492003-04-11 09:40:12 +0000241 struct in_addr addr;
242 struct in_addr mask;
jjako88c22162003-07-06 19:33:18 +0000243 struct in_addr stataddr;
244 struct in_addr statmask;
jjakoa7cd2492003-04-11 09:40:12 +0000245 unsigned int m;
246 unsigned int listsize;
jjako88c22162003-07-06 19:33:18 +0000247 unsigned int dynsize;
248 unsigned int statsize;
jjakoa7cd2492003-04-11 09:40:12 +0000249
jjako88c22162003-07-06 19:33:18 +0000250 if (!allowdyn) {
251 dynsize = 0;
252 }
253 else {
jjakoc3213962004-09-09 20:23:50 +0000254 if (ippool_aton(&addr, &mask, dyn, 0)) {
255 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
256 "Failed to parse dynamic pool");
257 return -1;
jjakoc6762cf2004-04-28 14:52:58 +0000258 }
259
jjako504ee452003-08-20 15:25:54 +0000260 /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
261 if (flags & IPPOOL_NOGATEWAY) {
262 flags |= IPPOOL_NONETWORK;
263 }
jjako88c22162003-07-06 19:33:18 +0000264
265 m = ntohl(mask.s_addr);
266 dynsize = ((~m)+1);
267 if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
268 dynsize--;
jjako504ee452003-08-20 15:25:54 +0000269 if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
270 dynsize--;
jjako88c22162003-07-06 19:33:18 +0000271 if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
272 dynsize--;
273 }
jjakoa7cd2492003-04-11 09:40:12 +0000274
jjako88c22162003-07-06 19:33:18 +0000275 if (!allowstat) {
276 statsize = 0;
277 stataddr.s_addr = 0;
278 statmask.s_addr = 0;
279 }
280 else {
jjakoc3213962004-09-09 20:23:50 +0000281 if (ippool_aton(&stataddr, &statmask, stat, 0)) {
282 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
283 "Failed to parse static range");
284 return -1;
285 }
286
jjako88c22162003-07-06 19:33:18 +0000287 m = ntohl(statmask.s_addr);
288 statsize = ((~m)+1);
289 if (statsize > IPPOOL_STATSIZE) statsize = IPPOOL_STATSIZE;
290 }
291
292 listsize = dynsize + statsize; /* Allocate space for static IP addresses */
jjakoa7cd2492003-04-11 09:40:12 +0000293
294 if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
jjakoc3213962004-09-09 20:23:50 +0000295 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
296 "Failed to allocate memory for ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000297 return -1;
298 }
299
jjako88c22162003-07-06 19:33:18 +0000300 (*this)->allowdyn = allowdyn;
301 (*this)->allowstat = allowstat;
302 (*this)->stataddr = stataddr;
303 (*this)->statmask = statmask;
304
jjakoa7cd2492003-04-11 09:40:12 +0000305 (*this)->listsize += listsize;
jjako88c22162003-07-06 19:33:18 +0000306 if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))){
jjakoc3213962004-09-09 20:23:50 +0000307 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
308 "Failed to allocate memory for members in ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000309 return -1;
310 }
311
312 for ((*this)->hashlog = 0;
313 ((1 << (*this)->hashlog) < listsize);
314 (*this)->hashlog++);
315
316 /* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
317
318 /* Determine hashsize */
319 (*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet*/
320 (*this)->hashmask = (*this)->hashsize -1;
321
322 /* Allocate hash table */
323 if (!((*this)->hash = calloc(sizeof(struct ippoolm_t), (*this)->hashsize))){
jjakoc3213962004-09-09 20:23:50 +0000324 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
325 "Failed to allocate memory for hash members in ippool");
jjakoa7cd2492003-04-11 09:40:12 +0000326 return -1;
327 }
328
jjako88c22162003-07-06 19:33:18 +0000329 (*this)->firstdyn = NULL;
330 (*this)->lastdyn = NULL;
331 for (i = 0; i<dynsize; i++) {
jjakoa7cd2492003-04-11 09:40:12 +0000332
jjakoc3213962004-09-09 20:23:50 +0000333 if (flags & IPPOOL_NOGATEWAY)
jjako504ee452003-08-20 15:25:54 +0000334 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 2);
335 else if (flags & IPPOOL_NONETWORK)
jjakoa7cd2492003-04-11 09:40:12 +0000336 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 1);
337 else
338 (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i);
jjako504ee452003-08-20 15:25:54 +0000339
jjakoa7cd2492003-04-11 09:40:12 +0000340 (*this)->member[i].inuse = 0;
jjakoa7cd2492003-04-11 09:40:12 +0000341
342 /* Insert into list of unused */
jjako88c22162003-07-06 19:33:18 +0000343 (*this)->member[i].prev = (*this)->lastdyn;
344 if ((*this)->lastdyn) {
345 (*this)->lastdyn->next = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000346 }
347 else {
jjako88c22162003-07-06 19:33:18 +0000348 (*this)->firstdyn = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000349 }
jjako88c22162003-07-06 19:33:18 +0000350 (*this)->lastdyn = &((*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000351 (*this)->member[i].next = NULL; /* Redundant */
352
jjako88c22162003-07-06 19:33:18 +0000353 ippool_hashadd(*this, &(*this)->member[i]);
jjakoa7cd2492003-04-11 09:40:12 +0000354 }
jjako88c22162003-07-06 19:33:18 +0000355
356 (*this)->firststat = NULL;
357 (*this)->laststat = NULL;
358 for (i = dynsize; i<listsize; i++) {
359
360 (*this)->member[i].addr.s_addr = 0;
361 (*this)->member[i].inuse = 0;
362
363 /* Insert into list of unused */
364 (*this)->member[i].prev = (*this)->laststat;
365 if ((*this)->laststat) {
366 (*this)->laststat->next = &((*this)->member[i]);
367 }
368 else {
369 (*this)->firststat = &((*this)->member[i]);
370 }
371 (*this)->laststat = &((*this)->member[i]);
372 (*this)->member[i].next = NULL; /* Redundant */
373 }
374
375 if (0) ippool_printaddr(*this);
jjakoa7cd2492003-04-11 09:40:12 +0000376 return 0;
377}
378
379/* Delete existing address pool */
380int ippool_free(struct ippool_t *this) {
381 free(this->hash);
382 free(this->member);
383 free(this);
384 return 0; /* Always OK */
385}
386
387/* Find an IP address in the pool */
388int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
389 struct in_addr *addr) {
390 struct ippoolm_t *p;
391 uint32_t hash;
392
393 /* Find in hash table */
394 hash = ippool_hash4(addr) & this->hashmask;
395 for (p = this->hash[hash]; p; p = p->nexthash) {
396 if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
397 *member = p;
398 return 0;
399 }
400 }
401 *member = NULL;
jjakoc3213962004-09-09 20:23:50 +0000402 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found");
403 return -1;
jjakoa7cd2492003-04-11 09:40:12 +0000404}
405
jjako88c22162003-07-06 19:33:18 +0000406/**
407 * ippool_newip
408 * Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
409 * check to see if the given address is available. If available within
410 * dynamic address space allocate it there, otherwise allocate within static
411 * address space.
412**/
jjakoa7cd2492003-04-11 09:40:12 +0000413int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
414 struct in_addr *addr) {
415 struct ippoolm_t *p;
416 struct ippoolm_t *p2 = NULL;
417 uint32_t hash;
418
jjako88c22162003-07-06 19:33:18 +0000419 /* If static:
420 * Look in dynaddr.
421 * If found remove from firstdyn/lastdyn linked list.
422 * Else allocate from stataddr.
423 * Remove from firststat/laststat linked list.
424 * Insert into hash table.
425 *
426 * If dynamic
427 * Remove from firstdyn/lastdyn linked list.
428 *
429 */
430
431 if (0) ippool_printaddr(this);
432
433 /* First check to see if this type of address is allowed */
434 if ((addr) && (addr->s_addr)) { /* IP address given */
435 if (!this->allowstat) {
jjakoc3213962004-09-09 20:23:50 +0000436 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static IP address not allowed");
437 return -1;
jjako88c22162003-07-06 19:33:18 +0000438 }
439 if ((addr->s_addr & this->statmask.s_addr) != this->stataddr.s_addr) {
jjakoc3213962004-09-09 20:23:50 +0000440 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static out of range");
441 return -1;
jjako88c22162003-07-06 19:33:18 +0000442 }
443 }
444 else {
445 if (!this->allowdyn) {
jjakoc3213962004-09-09 20:23:50 +0000446 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
447 "Dynamic IP address not allowed");
448 return -1;
jjako88c22162003-07-06 19:33:18 +0000449 }
450 }
jjakoa7cd2492003-04-11 09:40:12 +0000451
452 if ((addr) && (addr->s_addr)) { /* IP address given */
453 /* Find in hash table */
454 hash = ippool_hash4(addr) & this->hashmask;
455 for (p = this->hash[hash]; p; p = p->nexthash) {
456 if ((p->addr.s_addr == addr->s_addr)) {
457 p2 = p;
458 break;
459 }
460 }
461 }
462 else { /* No ip address given */
jjakoc3213962004-09-09 20:23:50 +0000463 if (!this ->firstdyn) {
464 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
465 "No more IP addresses available");
466 return -1;
467 }
jjako88c22162003-07-06 19:33:18 +0000468 else
469 p2 = this ->firstdyn;
jjakoa7cd2492003-04-11 09:40:12 +0000470 }
471
jjako88c22162003-07-06 19:33:18 +0000472 if (p2) { /* Was allocated from dynamic address pool */
jjakoc3213962004-09-09 20:23:50 +0000473 if (p2->inuse) {
474 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
475 "IP address allready in use");
476 return -1; /* Allready in use / Should not happen */
477 }
478
jjako88c22162003-07-06 19:33:18 +0000479 /* Remove from linked list of free dynamic addresses */
480 if (p2->prev)
481 p2->prev->next = p2->next;
482 else
483 this->firstdyn = p2->next;
484 if (p2->next)
485 p2->next->prev = p2->prev;
486 else
487 this->lastdyn = p2->prev;
488 p2->next = NULL;
489 p2->prev = NULL;
490 p2->inuse = 1; /* Dynamic address in use */
491
492 *member = p2;
493 if (0) ippool_printaddr(this);
494 return 0; /* Success */
495 }
496
497 /* It was not possible to allocate from dynamic address pool */
498 /* Try to allocate from static address space */
499
500 if ((addr) && (addr->s_addr)) { /* IP address given */
jjakoc3213962004-09-09 20:23:50 +0000501 if (this->firststat) {
502 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
503 "No more IP addresses available");
jjako88c22162003-07-06 19:33:18 +0000504 return -1; /* No more available */
jjakoc3213962004-09-09 20:23:50 +0000505 }
jjako88c22162003-07-06 19:33:18 +0000506 else
507 p2 = this ->firststat;
508
509 /* Remove from linked list of free static addresses */
510 if (p2->prev)
511 p2->prev->next = p2->next;
512 else
513 this->firststat = p2->next;
514 if (p2->next)
515 p2->next->prev = p2->prev;
516 else
517 this->laststat = p2->prev;
518 p2->next = NULL;
519 p2->prev = NULL;
520 p2->inuse = 1; /* Static address in use */
521
jjakoc3213962004-09-09 20:23:50 +0000522 memcpy(&p2->addr, addr, sizeof(addr));
jjako88c22162003-07-06 19:33:18 +0000523 *member = p2;
jjakoc3213962004-09-09 20:23:50 +0000524 ippool_hashadd(this, *member);
jjako88c22162003-07-06 19:33:18 +0000525 if (0) ippool_printaddr(this);
526 return 0; /* Success */
527 }
528
jjakoc3213962004-09-09 20:23:50 +0000529 sys_err(LOG_ERR, __FILE__, __LINE__, 0,
530 "Could not allocate IP address");
jjako88c22162003-07-06 19:33:18 +0000531 return -1; /* Should never get here. TODO: Bad code */
jjakoa7cd2492003-04-11 09:40:12 +0000532}
533
534
jjako88c22162003-07-06 19:33:18 +0000535int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member) {
jjakoa7cd2492003-04-11 09:40:12 +0000536
jjako88c22162003-07-06 19:33:18 +0000537 if (0) ippool_printaddr(this);
jjakoa7cd2492003-04-11 09:40:12 +0000538
jjakoc3213962004-09-09 20:23:50 +0000539 if (!member->inuse) {
540 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
541 return -1; /* Not in use: Should not happen */
542 }
jjakoa7cd2492003-04-11 09:40:12 +0000543
jjako88c22162003-07-06 19:33:18 +0000544 switch (member->inuse) {
545 case 0: /* Not in use: Should not happen */
jjakoc3213962004-09-09 20:23:50 +0000546 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
jjako88c22162003-07-06 19:33:18 +0000547 return -1;
548 case 1: /* Allocated from dynamic address space */
549 /* Insert into list of unused */
550 member->prev = this->lastdyn;
551 if (this->lastdyn) {
552 this->lastdyn->next = member;
553 }
554 else {
555 this->firstdyn = member;
556 }
557 this->lastdyn = member;
558
559 member->inuse = 0;
560 member->peer = NULL;
561 if (0) ippool_printaddr(this);
562 return 0;
563 case 2: /* Allocated from static address space */
564 if (ippool_hashdel(this, member))
565 return -1;
566 /* Insert into list of unused */
567 member->prev = this->laststat;
568 if (this->laststat) {
569 this->laststat->next = member;
570 }
571 else {
572 this->firststat = member;
573 }
574 this->laststat = member;
575
576 member->inuse = 0;
577 member->addr.s_addr = 0;
578 member->peer = NULL;
579 member->nexthash = NULL;
580 if (0) ippool_printaddr(this);
581 return 0;
582 default: /* Should not happen */
jjakoc3213962004-09-09 20:23:50 +0000583 sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Could not free IP address");
jjako88c22162003-07-06 19:33:18 +0000584 return -1;
jjakoa7cd2492003-04-11 09:40:12 +0000585 }
jjakoa7cd2492003-04-11 09:40:12 +0000586}
587
588
589#ifndef IPPOOL_NOIP6
590extern unsigned long int ippool_hash6(struct in6_addr *addr);
591extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
592extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
593#endif