blob: 1f79a77e37ce89921df20c534526de7056c6b55a [file] [log] [blame]
jjakoada9ffa2004-12-30 16:39:11 +00001/*
jjakoa7cd2492003-04-11 09:40:12 +00002 * IP address pool functions.
jjakoc3213962004-09-09 20:23:50 +00003 * Copyright (C) 2003, 2004 Mondru AB.
jjakoada9ffa2004-12-30 16:39:11 +00004 *
jjakoa7cd2492003-04-11 09:40:12 +00005 * 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>
Harald Weltebed35df2011-11-02 13:06:18 +010013#include <netinet/in.h> /* in_addr */
14#include <stdlib.h> /* calloc */
15#include <stdio.h> /* sscanf */
jjakoc3213962004-09-09 20:23:50 +000016#include <string.h>
17#include <sys/socket.h>
18#include <arpa/inet.h>
jjakoc3213962004-09-09 20:23:50 +000019#include "syserr.h"
jjakoa7cd2492003-04-11 09:40:12 +000020#include "ippool.h"
jjakoada9ffa2004-12-30 16:39:11 +000021#include "lookup.h"
jjakoa7cd2492003-04-11 09:40:12 +000022
Harald Weltebed35df2011-11-02 13:06:18 +010023int ippool_printaddr(struct ippool_t *this)
24{
25 unsigned int n;
26 printf("ippool_printaddr\n");
27 printf("Firstdyn %d\n", this->firstdyn - this->member);
28 printf("Lastdyn %d\n", this->lastdyn - this->member);
29 printf("Firststat %d\n", this->firststat - this->member);
30 printf("Laststat %d\n", this->laststat - this->member);
31 printf("Listsize %d\n", this->listsize);
jjakoa7cd2492003-04-11 09:40:12 +000032
Harald Weltebed35df2011-11-02 13:06:18 +010033 for (n = 0; n < this->listsize; n++) {
34 printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
35 n,
36 this->member[n].inuse,
37 this->member[n].prev - this->member,
38 this->member[n].next - this->member,
39 inet_ntoa(this->member[n].addr),
40 this->member[n].addr.s_addr);
41 }
42 return 0;
jjakoa7cd2492003-04-11 09:40:12 +000043}
44
Harald Weltebed35df2011-11-02 13:06:18 +010045int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
46{
47 uint32_t hash;
48 struct ippoolm_t *p;
49 struct ippoolm_t *p_prev = NULL;
jjako88c22162003-07-06 19:33:18 +000050
Harald Weltebed35df2011-11-02 13:06:18 +010051 /* Insert into hash table */
52 hash = ippool_hash4(&member->addr) & this->hashmask;
53 for (p = this->hash[hash]; p; p = p->nexthash)
54 p_prev = p;
55 if (!p_prev)
56 this->hash[hash] = member;
57 else
58 p_prev->nexthash = member;
59 return 0; /* Always OK to insert */
jjako88c22162003-07-06 19:33:18 +000060}
61
Harald Weltebed35df2011-11-02 13:06:18 +010062int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
63{
64 uint32_t hash;
65 struct ippoolm_t *p;
66 struct ippoolm_t *p_prev = NULL;
jjako88c22162003-07-06 19:33:18 +000067
Harald Weltebed35df2011-11-02 13:06:18 +010068 /* Find in hash table */
69 hash = ippool_hash4(&member->addr) & this->hashmask;
70 for (p = this->hash[hash]; p; p = p->nexthash) {
71 if (p == member) {
72 break;
73 }
74 p_prev = p;
75 }
jjako88c22162003-07-06 19:33:18 +000076
Harald Weltebed35df2011-11-02 13:06:18 +010077 if (p != member) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +010078 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +010079 "ippool_hashdel: Tried to delete member not in hash table");
80 return -1;
81 }
jjako88c22162003-07-06 19:33:18 +000082
Harald Weltebed35df2011-11-02 13:06:18 +010083 if (!p_prev)
84 this->hash[hash] = p->nexthash;
85 else
86 p_prev->nexthash = p->nexthash;
jjako88c22162003-07-06 19:33:18 +000087
Harald Weltebed35df2011-11-02 13:06:18 +010088 return 0;
jjako88c22162003-07-06 19:33:18 +000089}
90
Harald Weltebed35df2011-11-02 13:06:18 +010091unsigned long int ippool_hash4(struct in_addr *addr)
92{
93 return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
jjakoa7cd2492003-04-11 09:40:12 +000094}
95
96#ifndef IPPOOL_NOIP6
Harald Weltebed35df2011-11-02 13:06:18 +010097unsigned long int ippool_hash6(struct in6_addr *addr)
98{
99 return lookup((unsigned char *)addr->u6_addr8, sizeof(addr->u6_addr8),
100 0);
jjakoa7cd2492003-04-11 09:40:12 +0000101}
102#endif
103
jjakoa7cd2492003-04-11 09:40:12 +0000104/* Get IP address and mask */
105int ippool_aton(struct in_addr *addr, struct in_addr *mask,
Harald Weltebed35df2011-11-02 13:06:18 +0100106 char *pool, int number)
107{
jjakoa7cd2492003-04-11 09:40:12 +0000108
Harald Weltebed35df2011-11-02 13:06:18 +0100109 /* Parse only first instance of network for now */
110 /* Eventually "number" will indicate the token which we want to parse */
jjakoa7cd2492003-04-11 09:40:12 +0000111
Harald Weltebed35df2011-11-02 13:06:18 +0100112 unsigned int a1, a2, a3, a4;
113 unsigned int m1, m2, m3, m4;
114 int c;
115 int m;
116 int masklog;
jjakoa7cd2492003-04-11 09:40:12 +0000117
Harald Weltebed35df2011-11-02 13:06:18 +0100118 c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
119 &a1, &a2, &a3, &a4, &m1, &m2, &m3, &m4);
120 switch (c) {
121 case 4:
122 mask->s_addr = 0xffffffff;
123 break;
124 case 5:
125 if (m1 > 32) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100126 SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
Harald Weltebed35df2011-11-02 13:06:18 +0100127 return -1; /* Invalid mask */
128 }
129 mask->s_addr = htonl(0xffffffff << (32 - m1));
130 break;
131 case 8:
132 if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100133 SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
Harald Weltebed35df2011-11-02 13:06:18 +0100134 return -1; /* Wrong mask format */
135 }
136 m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
137 for (masklog = 0; ((1 << masklog) < ((~m) + 1)); masklog++) ;
138 if (((~m) + 1) != (1 << masklog)) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100139 SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
Harald Weltebed35df2011-11-02 13:06:18 +0100140 return -1; /* Wrong mask format (not all ones followed by all zeros) */
141 }
142 mask->s_addr = htonl(m);
143 break;
144 default:
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100145 SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
Harald Weltebed35df2011-11-02 13:06:18 +0100146 return -1; /* Invalid mask */
147 }
jjakoa7cd2492003-04-11 09:40:12 +0000148
Harald Weltebed35df2011-11-02 13:06:18 +0100149 if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100150 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100151 "Wrong IP address format");
152 return -1;
153 } else
154 addr->s_addr =
155 htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
jjakoa7cd2492003-04-11 09:40:12 +0000156
Harald Weltebed35df2011-11-02 13:06:18 +0100157 return 0;
jjakoa7cd2492003-04-11 09:40:12 +0000158}
159
160/* Create new address pool */
Harald Weltebed35df2011-11-02 13:06:18 +0100161int ippool_new(struct ippool_t **this, char *dyn, char *stat,
162 int allowdyn, int allowstat, int flags)
163{
jjakoa7cd2492003-04-11 09:40:12 +0000164
Harald Weltebed35df2011-11-02 13:06:18 +0100165 /* Parse only first instance of pool for now */
jjakoa7cd2492003-04-11 09:40:12 +0000166
Harald Weltebed35df2011-11-02 13:06:18 +0100167 int i;
168 struct in_addr addr;
169 struct in_addr mask;
170 struct in_addr stataddr;
171 struct in_addr statmask;
172 unsigned int m;
173 int listsize;
174 int dynsize;
175 unsigned int statsize;
jjakoa7cd2492003-04-11 09:40:12 +0000176
Harald Weltebed35df2011-11-02 13:06:18 +0100177 if (!allowdyn) {
178 dynsize = 0;
179 } else {
180 if (ippool_aton(&addr, &mask, dyn, 0)) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100181 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100182 "Failed to parse dynamic pool");
183 return -1;
184 }
jjakoc6762cf2004-04-28 14:52:58 +0000185
Harald Weltebed35df2011-11-02 13:06:18 +0100186 /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
187 if (flags & IPPOOL_NOGATEWAY) {
188 flags |= IPPOOL_NONETWORK;
189 }
jjakoa7cd2492003-04-11 09:40:12 +0000190
Harald Weltebed35df2011-11-02 13:06:18 +0100191 m = ntohl(mask.s_addr);
192 dynsize = ((~m) + 1);
193 if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
194 dynsize--;
195 if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
196 dynsize--;
197 if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
198 dynsize--;
199 }
jjakoc3213962004-09-09 20:23:50 +0000200
Harald Weltebed35df2011-11-02 13:06:18 +0100201 if (!allowstat) {
202 statsize = 0;
203 stataddr.s_addr = 0;
204 statmask.s_addr = 0;
205 } else {
206 if (ippool_aton(&stataddr, &statmask, stat, 0)) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100207 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100208 "Failed to parse static range");
209 return -1;
210 }
jjako88c22162003-07-06 19:33:18 +0000211
Harald Weltebed35df2011-11-02 13:06:18 +0100212 m = ntohl(statmask.s_addr);
213 statsize = ((~m) + 1);
214 if (statsize > IPPOOL_STATSIZE)
215 statsize = IPPOOL_STATSIZE;
216 }
jjakoa7cd2492003-04-11 09:40:12 +0000217
Harald Weltebed35df2011-11-02 13:06:18 +0100218 listsize = dynsize + statsize; /* Allocate space for static IP addresses */
jjako88c22162003-07-06 19:33:18 +0000219
Harald Weltebed35df2011-11-02 13:06:18 +0100220 if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100221 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100222 "Failed to allocate memory for ippool");
223 return -1;
224 }
jjakoa7cd2492003-04-11 09:40:12 +0000225
Harald Weltebed35df2011-11-02 13:06:18 +0100226 (*this)->allowdyn = allowdyn;
227 (*this)->allowstat = allowstat;
228 (*this)->stataddr = stataddr;
229 (*this)->statmask = statmask;
jjakoa7cd2492003-04-11 09:40:12 +0000230
Harald Weltebed35df2011-11-02 13:06:18 +0100231 (*this)->listsize += listsize;
232 if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100233 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100234 "Failed to allocate memory for members in ippool");
235 return -1;
236 }
jjakoa7cd2492003-04-11 09:40:12 +0000237
Harald Weltebed35df2011-11-02 13:06:18 +0100238 for ((*this)->hashlog = 0;
239 ((1 << (*this)->hashlog) < listsize); (*this)->hashlog++) ;
jjakoa7cd2492003-04-11 09:40:12 +0000240
Harald Weltebed35df2011-11-02 13:06:18 +0100241 /* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
jjakoa7cd2492003-04-11 09:40:12 +0000242
Harald Weltebed35df2011-11-02 13:06:18 +0100243 /* Determine hashsize */
244 (*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet */
245 (*this)->hashmask = (*this)->hashsize - 1;
jjako88c22162003-07-06 19:33:18 +0000246
Harald Weltebed35df2011-11-02 13:06:18 +0100247 /* Allocate hash table */
248 if (!
249 ((*this)->hash =
250 calloc(sizeof(struct ippoolm_t), (*this)->hashsize))) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100251 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100252 "Failed to allocate memory for hash members in ippool");
253 return -1;
254 }
jjako88c22162003-07-06 19:33:18 +0000255
Harald Weltebed35df2011-11-02 13:06:18 +0100256 (*this)->firstdyn = NULL;
257 (*this)->lastdyn = NULL;
258 for (i = 0; i < dynsize; i++) {
jjako88c22162003-07-06 19:33:18 +0000259
Harald Weltebed35df2011-11-02 13:06:18 +0100260 if (flags & IPPOOL_NOGATEWAY)
261 (*this)->member[i].addr.s_addr =
262 htonl(ntohl(addr.s_addr) + i + 2);
263 else if (flags & IPPOOL_NONETWORK)
264 (*this)->member[i].addr.s_addr =
265 htonl(ntohl(addr.s_addr) + i + 1);
266 else
267 (*this)->member[i].addr.s_addr =
268 htonl(ntohl(addr.s_addr) + i);
jjako88c22162003-07-06 19:33:18 +0000269
Harald Weltebed35df2011-11-02 13:06:18 +0100270 (*this)->member[i].inuse = 0;
271
272 /* Insert into list of unused */
273 (*this)->member[i].prev = (*this)->lastdyn;
274 if ((*this)->lastdyn) {
275 (*this)->lastdyn->next = &((*this)->member[i]);
276 } else {
277 (*this)->firstdyn = &((*this)->member[i]);
278 }
279 (*this)->lastdyn = &((*this)->member[i]);
280 (*this)->member[i].next = NULL; /* Redundant */
281
282 (void)ippool_hashadd(*this, &(*this)->member[i]);
283 }
284
285 (*this)->firststat = NULL;
286 (*this)->laststat = NULL;
287 for (i = dynsize; i < listsize; i++) {
288
289 (*this)->member[i].addr.s_addr = 0;
290 (*this)->member[i].inuse = 0;
291
292 /* Insert into list of unused */
293 (*this)->member[i].prev = (*this)->laststat;
294 if ((*this)->laststat) {
295 (*this)->laststat->next = &((*this)->member[i]);
296 } else {
297 (*this)->firststat = &((*this)->member[i]);
298 }
299 (*this)->laststat = &((*this)->member[i]);
300 (*this)->member[i].next = NULL; /* Redundant */
301 }
302
303 if (0)
304 (void)ippool_printaddr(*this);
305 return 0;
jjakoa7cd2492003-04-11 09:40:12 +0000306}
307
308/* Delete existing address pool */
Harald Weltebed35df2011-11-02 13:06:18 +0100309int ippool_free(struct ippool_t *this)
310{
311 free(this->hash);
312 free(this->member);
313 free(this);
314 return 0; /* Always OK */
jjakoa7cd2492003-04-11 09:40:12 +0000315}
316
317/* Find an IP address in the pool */
318int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
Harald Weltebed35df2011-11-02 13:06:18 +0100319 struct in_addr *addr)
320{
321 struct ippoolm_t *p;
322 uint32_t hash;
jjakoa7cd2492003-04-11 09:40:12 +0000323
Harald Weltebed35df2011-11-02 13:06:18 +0100324 /* Find in hash table */
325 hash = ippool_hash4(addr) & this->hashmask;
326 for (p = this->hash[hash]; p; p = p->nexthash) {
327 if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
328 if (member)
329 *member = p;
330 return 0;
331 }
332 }
333 if (member)
334 *member = NULL;
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100335 /*SYS_ERR(DIP, LOGL_ERROR, 0, "Address could not be found"); */
Harald Weltebed35df2011-11-02 13:06:18 +0100336 return -1;
jjakoa7cd2492003-04-11 09:40:12 +0000337}
338
jjako88c22162003-07-06 19:33:18 +0000339/**
340 * ippool_newip
341 * Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
342 * check to see if the given address is available. If available within
343 * dynamic address space allocate it there, otherwise allocate within static
344 * address space.
345**/
jjakoa7cd2492003-04-11 09:40:12 +0000346int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
Harald Weltebed35df2011-11-02 13:06:18 +0100347 struct in_addr *addr, int statip)
348{
349 struct ippoolm_t *p;
350 struct ippoolm_t *p2 = NULL;
351 uint32_t hash;
jjakoa7cd2492003-04-11 09:40:12 +0000352
Harald Weltebed35df2011-11-02 13:06:18 +0100353 /* If static:
354 * Look in dynaddr.
355 * If found remove from firstdyn/lastdyn linked list.
356 * Else allocate from stataddr.
357 * Remove from firststat/laststat linked list.
358 * Insert into hash table.
359 *
360 * If dynamic
361 * Remove from firstdyn/lastdyn linked list.
362 *
363 */
jjako88c22162003-07-06 19:33:18 +0000364
Harald Weltebed35df2011-11-02 13:06:18 +0100365 if (0)
366 (void)ippool_printaddr(this);
jjako88c22162003-07-06 19:33:18 +0000367
Harald Weltebed35df2011-11-02 13:06:18 +0100368 /* First check to see if this type of address is allowed */
369 if ((addr) && (addr->s_addr) && statip) { /* IP address given */
370 if (!this->allowstat) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100371 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100372 "Static IP address not allowed");
373 return -1;
374 }
375 if ((addr->s_addr & this->statmask.s_addr) !=
376 this->stataddr.s_addr) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100377 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100378 "Static out of range");
379 return -1;
380 }
381 } else {
382 if (!this->allowdyn) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100383 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100384 "Dynamic IP address not allowed");
385 return -1;
386 }
387 }
jjakoa7cd2492003-04-11 09:40:12 +0000388
Harald Weltebed35df2011-11-02 13:06:18 +0100389 /* If IP address given try to find it in dynamic address pool */
390 if ((addr) && (addr->s_addr)) { /* IP address given */
391 /* Find in hash table */
392 hash = ippool_hash4(addr) & this->hashmask;
393 for (p = this->hash[hash]; p; p = p->nexthash) {
394 if ((p->addr.s_addr == addr->s_addr)) {
395 p2 = p;
396 break;
397 }
398 }
399 }
jjakoada9ffa2004-12-30 16:39:11 +0000400
Harald Weltebed35df2011-11-02 13:06:18 +0100401 /* If IP was already allocated we can not use it */
402 if ((!statip) && (p2) && (p2->inuse)) {
403 p2 = NULL;
404 }
jjakoada9ffa2004-12-30 16:39:11 +0000405
Harald Weltebed35df2011-11-02 13:06:18 +0100406 /* If not found yet and dynamic IP then allocate dynamic IP */
407 if ((!p2) && (!statip)) {
408 if (!this->firstdyn) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100409 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100410 "No more IP addresses available");
411 return -1;
412 } else
413 p2 = this->firstdyn;
414 }
jjakoc3213962004-09-09 20:23:50 +0000415
Harald Weltebed35df2011-11-02 13:06:18 +0100416 if (p2) { /* Was allocated from dynamic address pool */
417 if (p2->inuse) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100418 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100419 "IP address allready in use");
420 return -1; /* Allready in use / Should not happen */
421 }
jjako88c22162003-07-06 19:33:18 +0000422
Harald Weltebed35df2011-11-02 13:06:18 +0100423 /* Remove from linked list of free dynamic addresses */
424 if (p2->prev)
425 p2->prev->next = p2->next;
426 else
427 this->firstdyn = p2->next;
428 if (p2->next)
429 p2->next->prev = p2->prev;
430 else
431 this->lastdyn = p2->prev;
432 p2->next = NULL;
433 p2->prev = NULL;
434 p2->inuse = 1; /* Dynamic address in use */
jjako88c22162003-07-06 19:33:18 +0000435
Harald Weltebed35df2011-11-02 13:06:18 +0100436 *member = p2;
437 if (0)
438 (void)ippool_printaddr(this);
439 return 0; /* Success */
440 }
jjako88c22162003-07-06 19:33:18 +0000441
Harald Weltebed35df2011-11-02 13:06:18 +0100442 /* It was not possible to allocate from dynamic address pool */
443 /* Try to allocate from static address space */
jjako88c22162003-07-06 19:33:18 +0000444
Harald Weltebed35df2011-11-02 13:06:18 +0100445 if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
446 if (!this->firststat) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100447 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100448 "No more IP addresses available");
449 return -1; /* No more available */
450 } else
451 p2 = this->firststat;
452
453 /* Remove from linked list of free static addresses */
454 if (p2->prev)
455 p2->prev->next = p2->next;
456 else
457 this->firststat = p2->next;
458 if (p2->next)
459 p2->next->prev = p2->prev;
460 else
461 this->laststat = p2->prev;
462 p2->next = NULL;
463 p2->prev = NULL;
464 p2->inuse = 2; /* Static address in use */
465 memcpy(&p2->addr, addr, sizeof(addr));
466 *member = p2;
467 (void)ippool_hashadd(this, *member);
468 if (0)
469 (void)ippool_printaddr(this);
470 return 0; /* Success */
471 }
472
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100473 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100474 "Could not allocate IP address");
475 return -1; /* Should never get here. TODO: Bad code */
jjakoa7cd2492003-04-11 09:40:12 +0000476}
477
Harald Weltebed35df2011-11-02 13:06:18 +0100478int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
479{
jjakoa7cd2492003-04-11 09:40:12 +0000480
Harald Weltebed35df2011-11-02 13:06:18 +0100481 if (0)
482 (void)ippool_printaddr(this);
jjakoa7cd2492003-04-11 09:40:12 +0000483
Harald Weltebed35df2011-11-02 13:06:18 +0100484 if (!member->inuse) {
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100485 SYS_ERR(DIP, LOGL_ERROR, 0, "Address not in use");
Harald Weltebed35df2011-11-02 13:06:18 +0100486 return -1; /* Not in use: Should not happen */
487 }
jjakoa7cd2492003-04-11 09:40:12 +0000488
Harald Weltebed35df2011-11-02 13:06:18 +0100489 switch (member->inuse) {
490 case 0: /* Not in use: Should not happen */
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100491 SYS_ERR(DIP, LOGL_ERROR, 0, "Address not in use");
Harald Weltebed35df2011-11-02 13:06:18 +0100492 return -1;
493 case 1: /* Allocated from dynamic address space */
494 /* Insert into list of unused */
495 member->prev = this->lastdyn;
496 if (this->lastdyn) {
497 this->lastdyn->next = member;
498 } else {
499 this->firstdyn = member;
500 }
501 this->lastdyn = member;
502
503 member->inuse = 0;
504 member->peer = NULL;
505 if (0)
506 (void)ippool_printaddr(this);
507 return 0;
508 case 2: /* Allocated from static address space */
509 if (ippool_hashdel(this, member))
510 return -1;
511 /* Insert into list of unused */
512 member->prev = this->laststat;
513 if (this->laststat) {
514 this->laststat->next = member;
515 } else {
516 this->firststat = member;
517 }
518 this->laststat = member;
519
520 member->inuse = 0;
521 member->addr.s_addr = 0;
522 member->peer = NULL;
523 member->nexthash = NULL;
524 if (0)
525 (void)ippool_printaddr(this);
526 return 0;
527 default: /* Should not happen */
Holger Hans Peter Freyther9c7fd8e2014-12-04 16:32:37 +0100528 SYS_ERR(DIP, LOGL_ERROR, 0,
Harald Weltebed35df2011-11-02 13:06:18 +0100529 "Could not free IP address");
530 return -1;
531 }
jjakoa7cd2492003-04-11 09:40:12 +0000532}
533
jjakoa7cd2492003-04-11 09:40:12 +0000534#ifndef IPPOOL_NOIP6
535extern unsigned long int ippool_hash6(struct in6_addr *addr);
536extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
537extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
538#endif