OpenVPN
pool.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "pool.h"
30#include "buffer.h"
31#include "error.h"
32#include "socket_util.h"
33#include "otime.h"
34
35#include "memdbg.h"
36
37static void
39{
40 ipe->in_use = false;
41 if (hard && ipe->common_name)
42 {
43 free(ipe->common_name);
44 ipe->common_name = NULL;
45 }
46 if (hard)
47 {
48 ipe->last_release = 0;
49 }
50 else
51 {
52 ipe->last_release = now;
53 }
54}
55
56static int
57ifconfig_pool_find(struct ifconfig_pool *pool, const char *common_name)
58{
59 int i;
60 time_t earliest_release = 0;
61 int previous_usage = -1;
62 int new_usage = -1;
63
64 for (i = 0; i < pool->size; ++i)
65 {
66 const struct ifconfig_pool_entry *ipe = &pool->list[i];
67 if (!ipe->in_use)
68 {
69 /*
70 * If duplicate_cn mode, take first available IP address
71 */
72 if (pool->duplicate_cn)
73 {
74 new_usage = i;
75 break;
76 }
77
78 /*
79 * Keep track of the unused IP address entry which
80 * was released earliest.
81 */
82 if ((new_usage == -1 || ipe->last_release < earliest_release) && !ipe->fixed)
83 {
84 earliest_release = ipe->last_release;
85 new_usage = i;
86 }
87
88 /*
89 * Keep track of a possible allocation to us
90 * from an earlier session.
91 */
92 if (previous_usage < 0 && common_name && ipe->common_name
93 && !strcmp(common_name, ipe->common_name))
94 {
95 previous_usage = i;
96 }
97 }
98 }
99
100 if (previous_usage >= 0)
101 {
102 return previous_usage;
103 }
104
105 if (new_usage >= 0)
106 {
107 return new_usage;
108 }
109
110 return -1;
111}
112
113/*
114 * Verify start/end range
115 */
116bool
117ifconfig_pool_verify_range(const msglvl_t msglevel, const in_addr_t start, const in_addr_t end)
118{
119 struct gc_arena gc = gc_new();
120 bool ret = true;
121
122 if (start > end)
123 {
124 msg(msglevel, "--ifconfig-pool start IP [%s] is greater than end IP [%s]",
125 print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc));
126 ret = false;
127 }
128 if (end - start >= IFCONFIG_POOL_MAX)
129 {
130 msg(msglevel,
131 "--ifconfig-pool address range is too large [%s -> %s]. Current maximum is %d addresses, as defined by IFCONFIG_POOL_MAX variable.",
132 print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc), IFCONFIG_POOL_MAX);
133 ret = false;
134 }
135 gc_free(&gc);
136 return ret;
137}
138
139struct ifconfig_pool *
140ifconfig_pool_init(const bool ipv4_pool, enum pool_type type, in_addr_t start, in_addr_t end,
141 const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base,
142 const int ipv6_netbits)
143{
144 struct gc_arena gc = gc_new();
145 struct ifconfig_pool *pool = NULL;
146 int pool_ipv4_size = -1, pool_ipv6_size = -1;
147
148 ASSERT(start <= end && end - start < IFCONFIG_POOL_MAX);
149 ALLOC_OBJ_CLEAR(pool, struct ifconfig_pool);
150
152
153 pool->ipv4.enabled = ipv4_pool;
154
155 if (pool->ipv4.enabled)
156 {
157 pool->ipv4.type = type;
158 switch (pool->ipv4.type)
159 {
161 pool->ipv4.base = start & ~3u;
162 pool_ipv4_size = (((end | 3) + 1) - pool->ipv4.base) >> 2;
163 break;
164
166 pool->ipv4.base = start;
167 pool_ipv4_size = end - start + 1;
168 break;
169
170 default:
171 ASSERT(0);
172 }
173
174 if (pool_ipv4_size < 2)
175 {
176 msg(M_FATAL, "IPv4 pool size is too small (%d), must be at least 2", pool_ipv4_size);
177 }
178
179 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv4: base=%s size=%d",
180 print_in_addr_t(pool->ipv4.base, 0, &gc), pool_ipv4_size);
181
182 pool->size = pool_ipv4_size;
183 }
184
185 /* IPv6 pools are always "INDIV" type */
186 pool->ipv6.enabled = ipv6_pool;
187
188 if (pool->ipv6.enabled)
189 {
190 /* the host portion of the address will always be contained in the last
191 * 4 bytes, therefore we can just extract that and use it as base in
192 * integer form
193 */
194 uint32_t base = (ipv6_base.s6_addr[12] << 24) | (ipv6_base.s6_addr[13] << 16)
195 | (ipv6_base.s6_addr[14] << 8) | ipv6_base.s6_addr[15];
196 /* some bits of the last 4 bytes may still be part of the network
197 * portion of the address, therefore we need to set them to 0
198 */
199 if ((128 - ipv6_netbits) < 32)
200 {
201 /* extract only the bits that are really part of the host portion of
202 * the address.
203 *
204 * Example: if we have netbits=31, the first bit has to be zero'd,
205 * the following operation first computes mask=0x3fffff and then
206 * uses mask to extract the wanted bits from base
207 */
208 uint32_t mask = (1 << (128 - ipv6_netbits)) - 1;
209 base &= mask;
210 }
211
212 pool->ipv6.base = ipv6_base;
213
214 /* if a pool starts at a base address that has all-zero in the
215 * host part, that first IPv6 address must not be assigned to
216 * clients because it is not usable (subnet anycast address).
217 * Start with 1, then.
218 *
219 * NOTE: this will also (mis-)fire for something like
220 * ifconfig-ipv6-pool 2001:db8:0:1:1234::0/64
221 * as we only check the rightmost 32 bits of the host part. So be it.
222 */
223 if (base == 0)
224 {
225 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: incrementing pool start "
226 "to avoid ::0 assignment");
227 base++;
228 pool->ipv6.base.s6_addr[15]++;
229 }
230
231 pool_ipv6_size =
232 ipv6_netbits >= 112 ? (1 << (128 - ipv6_netbits)) - base : IFCONFIG_POOL_MAX;
233
234 if (pool_ipv6_size < 2)
235 {
236 msg(M_FATAL, "IPv6 pool size is too small (%d), must be at least 2", pool_ipv6_size);
237 }
238
239 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: base=%s size=%d netbits=%d",
240 print_in6_addr(pool->ipv6.base, 0, &gc), pool_ipv6_size, ipv6_netbits);
241
242 /* if there is no v4 pool, or the v6 pool is smaller, use
243 * v6 pool size as "unified pool size"
244 */
245 if (pool->size <= 0 || pool_ipv6_size < pool->size)
246 {
247 pool->size = pool_ipv6_size;
248 }
249 }
250
251 if (pool->ipv4.enabled && pool->ipv6.enabled)
252 {
253 if (pool_ipv4_size < pool_ipv6_size)
254 {
255 msg(M_INFO,
256 "NOTE: IPv4 pool size is %d, IPv6 pool size is %d. "
257 "IPv4 pool size limits the number of clients that can be "
258 "served from the pool",
259 pool_ipv4_size, pool_ipv6_size);
260 }
261 else if (pool_ipv4_size > pool_ipv6_size)
262 {
263 msg(M_WARN,
264 "WARNING: IPv4 pool size is %d, IPv6 pool size is %d. "
265 "IPv6 pool size limits the number of clients that can be "
266 "served from the pool. This is likely a MISTAKE - please check "
267 "your configuration",
268 pool_ipv4_size, pool_ipv6_size);
269 }
270 }
271
272 ASSERT(pool->size > 0);
273
274 ALLOC_ARRAY_CLEAR(pool->list, struct ifconfig_pool_entry, pool->size);
275
276 gc_free(&gc);
277 return pool;
278}
279
280void
282{
283 if (pool)
284 {
285 int i;
286
287 for (i = 0; i < pool->size; ++i)
288 {
289 ifconfig_pool_entry_free(&pool->list[i], true);
290 }
291 free(pool->list);
292 free(pool);
293 }
294}
295
298 struct in6_addr *remote_ipv6, const char *common_name)
299{
300 int i;
301
302 i = ifconfig_pool_find(pool, common_name);
303 if (i >= 0)
304 {
305 struct ifconfig_pool_entry *ipe = &pool->list[i];
306 ASSERT(!ipe->in_use);
307 ifconfig_pool_entry_free(ipe, true);
308 ipe->in_use = true;
309 if (common_name)
310 {
312 }
313
314 if (pool->ipv4.enabled && local && remote)
315 {
316 switch (pool->ipv4.type)
317 {
319 {
320 in_addr_t b = pool->ipv4.base + (i << 2);
321 *local = b + 1;
322 *remote = b + 2;
323 break;
324 }
325
327 {
328 in_addr_t b = pool->ipv4.base + i;
329 *local = 0;
330 *remote = b;
331 break;
332 }
333
334 default:
335 ASSERT(0);
336 }
337 }
338
339 /* IPv6 pools are always INDIV (--linear) */
340 if (pool->ipv6.enabled && remote_ipv6)
341 {
342 *remote_ipv6 = add_in6_addr(pool->ipv6.base, i);
343 }
344 }
345 return i;
346}
347
348bool
349ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard)
350{
351 bool ret = false;
352
353 if (pool && hand >= 0 && hand < pool->size)
354 {
355 ifconfig_pool_entry_free(&pool->list[hand], hard);
356 ret = true;
357 }
358 return ret;
359}
360
361/*
362 * private access functions
363 */
364
365/* currently handling IPv4 logic only */
368{
369 ifconfig_pool_handle ret = -1;
370
371 switch (pool->ipv4.type)
372 {
374 {
375 ret = (addr - pool->ipv4.base) >> 2;
376 break;
377 }
378
380 {
381 ret = (addr - pool->ipv4.base);
382 break;
383 }
384
385 default:
386 ASSERT(0);
387 }
388
389 if (ret < 0 || ret >= pool->size)
390 {
391 ret = -1;
392 }
393
394 return ret;
395}
396
398ifconfig_pool_ipv6_base_to_handle(const struct ifconfig_pool *pool, const struct in6_addr *in_addr)
399{
401 uint32_t base, addr;
402
403 /* IPv6 pool is always IFCONFIG_POOL_INDIV.
404 *
405 * We assume the offset can't be larger than 2^32-1, therefore we compute
406 * the difference only among the last 4 bytes like if they were two 32bit
407 * long integers. The rest of the address must match.
408 */
409 for (int i = 0; i < (12); i++)
410 {
411 if (pool->ipv6.base.s6_addr[i] != in_addr->s6_addr[i])
412 {
413 return -1;
414 }
415 }
416
417 base = (pool->ipv6.base.s6_addr[12] << 24) | (pool->ipv6.base.s6_addr[13] << 16)
418 | (pool->ipv6.base.s6_addr[14] << 8) | pool->ipv6.base.s6_addr[15];
419
420 addr = (in_addr->s6_addr[12] << 24) | (in_addr->s6_addr[13] << 16) | (in_addr->s6_addr[14] << 8)
421 | in_addr->s6_addr[15];
422
423 ret = addr - base;
424 if (ret < 0 || ret >= pool->size)
425 {
426 ret = -1;
427 }
428
429 return ret;
430}
431
432static in_addr_t
434{
435 in_addr_t ret = 0;
436
437 if (pool->ipv4.enabled && hand >= 0 && hand < pool->size)
438 {
439 switch (pool->ipv4.type)
440 {
442 {
443 ret = pool->ipv4.base + (hand << 2);
444 break;
445 }
446
448 {
449 ret = pool->ipv4.base + hand;
450 break;
451 }
452
453 default:
454 ASSERT(0);
455 }
456 }
457
458 return ret;
459}
460
461static struct in6_addr
463{
464 struct in6_addr ret = IN6ADDR_ANY_INIT;
465
466 /* IPv6 pools are always INDIV (--linear) */
467 if (pool->ipv6.enabled && hand >= 0 && hand < pool->size)
468 {
469 ret = add_in6_addr(pool->ipv6.base, hand);
470 }
471 return ret;
472}
473
474static void
476 const bool fixed)
477{
478 struct ifconfig_pool_entry *e = &pool->list[h];
480 e->in_use = false;
481 e->common_name = string_alloc(cn, NULL);
482 e->last_release = now;
483 e->fixed = fixed;
484}
485
486static void
487ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out)
488{
489 if (pool && out)
490 {
491 struct gc_arena gc = gc_new();
492 int i;
493
494 for (i = 0; i < pool->size; ++i)
495 {
496 const struct ifconfig_pool_entry *e = &pool->list[i];
497
498 if (e->common_name)
499 {
500 const char *ip6_str = "";
501 const char *ip_str = "";
502
503 if (pool->ipv4.enabled)
504 {
505 const in_addr_t ip = ifconfig_pool_handle_to_ip_base(pool, i);
506 ip_str = print_in_addr_t(ip, 0, &gc);
507 }
508
509 if (pool->ipv6.enabled)
510 {
511 const struct in6_addr ip6 = ifconfig_pool_handle_to_ipv6_base(pool, i);
512 ip6_str = print_in6_addr(ip6, 0, &gc);
513 }
514
515 status_printf(out, "%s,%s,%s", e->common_name, ip_str, ip6_str);
516 }
517 }
518 gc_free(&gc);
519 }
520}
521
522static void
523ifconfig_pool_msg(const struct ifconfig_pool *pool, int msglevel)
524{
525 struct status_output *so = status_open(NULL, 0, msglevel, NULL, 0);
526 ASSERT(so);
527 status_printf(so, "IFCONFIG POOL LIST");
528 ifconfig_pool_list(pool, so);
529 status_close(so);
530}
531
532/*
533 * Deal with reading/writing the ifconfig pool database to a file
534 */
535
537ifconfig_pool_persist_init(const char *filename, int refresh_freq)
538{
539 struct ifconfig_pool_persist *ret;
540
541 ASSERT(filename);
542
544 if (refresh_freq > 0)
545 {
546 ret->fixed = false;
547 ret->file =
548 status_open(filename, refresh_freq, -1, NULL, STATUS_OUTPUT_READ | STATUS_OUTPUT_WRITE);
549 }
550 else
551 {
552 ret->fixed = true;
553 ret->file = status_open(filename, 0, -1, NULL, STATUS_OUTPUT_READ);
554 }
555 return ret;
556}
557
558void
560{
561 if (persist)
562 {
563 if (persist->file)
564 {
565 status_close(persist->file);
566 }
567 free(persist);
568 }
569}
570
571bool
573{
574 if (persist->file)
575 {
576 return status_trigger(persist->file);
577 }
578 else
579 {
580 return false;
581 }
582}
583
584void
586{
587 const int buf_size = 128;
588
589 update_time();
590
591 if (persist && persist->file && pool)
592 {
593 struct gc_arena gc = gc_new();
594 struct buffer in = alloc_buf_gc(256, &gc);
595 char *cn_buf, *ip_buf, *ip6_buf;
596
600
601 while (true)
602 {
603 ASSERT(buf_init(&in, 0));
604 if (!status_read(persist->file, &in))
605 {
606 break;
607 }
608 if (!BLEN(&in))
609 {
610 continue;
611 }
612
613 int c = *BSTR(&in);
614 if (c == '#' || c == ';')
615 {
616 continue;
617 }
618
619 msg(M_INFO, "ifconfig_pool_read(), in='%s'", BSTR(&in));
620
621 /* The expected format of a line is: "CN,IP4,IP6".
622 *
623 * IP4 or IP6 may be empty when respectively no v4 or v6 pool
624 * was previously specified.
625 *
626 * This means that accepted strings can be:
627 * - CN,IP4,IP6
628 * - CN,IP4
629 * - CN,,IP6
630 */
631 if (!buf_parse(&in, ',', cn_buf, buf_size) || !buf_parse(&in, ',', ip_buf, buf_size))
632 {
633 continue;
634 }
635
636 ifconfig_pool_handle h = -1, h6 = -1;
637
638 if (strlen(ip_buf) > 0)
639 {
640 bool v4_ok = true;
642
643 if (!v4_ok)
644 {
645 msg(M_WARN, "pool: invalid IPv4 (%s) for CN=%s", ip_buf, cn_buf);
646 }
647 else
648 {
650 if (h < 0)
651 {
652 msg(M_WARN, "pool: IPv4 (%s) out of pool range for CN=%s", ip_buf, cn_buf);
653 }
654 }
655 }
656
657 if (buf_parse(&in, ',', ip6_buf, buf_size) && strlen(ip6_buf) > 0)
658 {
659 struct in6_addr addr6;
660
661 if (!get_ipv6_addr(ip6_buf, &addr6, NULL, M_WARN))
662 {
663 msg(M_WARN, "pool: invalid IPv6 (%s) for CN=%s", ip6_buf, cn_buf);
664 }
665 else
666 {
667 h6 = ifconfig_pool_ipv6_base_to_handle(pool, &addr6);
668 if (h6 < 0)
669 {
670 msg(M_WARN, "pool: IPv6 (%s) out of pool range for CN=%s", ip6_buf, cn_buf);
671 }
672
673 /* Rely on IPv6 if no IPv4 was provided or the one provided
674 * was not valid
675 */
676 if (h < 0)
677 {
678 h = h6;
679 }
680 }
681 }
682
683 /* at the moment IPv4 and IPv6 share the same pool, therefore offsets
684 * have to match for the same client.
685 *
686 * If offsets differ we use the IPv4, therefore warn the user about this.
687 */
688 if ((h6 >= 0) && (h != h6))
689 {
690 msg(M_WARN, "pool: IPv4 (%s) and IPv6 (%s) have different offsets! Relying on IPv4",
691 ip_buf, ip6_buf);
692 }
693
694 /* if at least one among v4 and v6 was properly parsed, attempt
695 * setting an handle for this client
696 */
697 if (h >= 0)
698 {
699 msg(M_INFO, "succeeded -> ifconfig_pool_set(hand=%d)", h);
700 ifconfig_pool_set(pool, cn_buf, h, persist->fixed);
701 }
702 }
703
705
706 gc_free(&gc);
707 }
708}
709
710void
711ifconfig_pool_write(struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool)
712{
713 if (persist && persist->file && (status_rw_flags(persist->file) & STATUS_OUTPUT_WRITE) && pool)
714 {
715 status_reset(persist->file);
716 ifconfig_pool_list(pool, persist->file);
717 status_flush(persist->file);
718 }
719}
720
721/*
722 * TESTING ONLY
723 */
724
725#ifdef IFCONFIG_POOL_TEST
726
727#define DUP_CN
728
729void
730ifconfig_pool_test(in_addr_t start, in_addr_t end)
731{
732 struct gc_arena gc = gc_new();
734 /*struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_INDIV, start, end);*/
735 ifconfig_pool_handle array[256];
736 int i;
737
738 CLEAR(array);
739
740 msg(M_INFO | M_NOPREFIX, "************ 1");
741 for (i = 0; i < (int)SIZE(array); ++i)
742 {
743 char *cn;
745 in_addr_t local, remote;
746 char buf[256];
747 snprintf(buf, sizeof(buf), "common-name-%d", i);
748#ifdef DUP_CN
749 cn = NULL;
750#else
751 cn = buf;
752#endif
753 h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn);
754 if (h < 0)
755 {
756 break;
757 }
758 msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s",
759 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn ? cn : "[NULL]");
760 array[i] = h;
761 }
762
763 msg(M_INFO | M_NOPREFIX, "************* 2");
764 for (i = (int)SIZE(array) / 16; i < (int)SIZE(array) / 8; ++i)
765 {
766 msg(M_INFO, "Attempt to release %d cn=%s", array[i], p->list[i].common_name);
767 if (!ifconfig_pool_release(p, array[i]))
768 {
769 break;
770 }
771 msg(M_INFO, "Succeeded");
772 }
773
774 CLEAR(array);
775
776 msg(M_INFO | M_NOPREFIX, "**************** 3");
777 for (i = 0; i < (int)SIZE(array); ++i)
778 {
779 char *cn;
781 in_addr_t local, remote;
782 char buf[256];
783 snprintf(buf, sizeof(buf), "common-name-%d", i + 24);
784#ifdef DUP_CN
785 cn = NULL;
786#else
787 cn = buf;
788#endif
789 h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn);
790 if (h < 0)
791 {
792 break;
793 }
794 msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s",
795 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn ? cn : "[NULL]");
796 array[i] = h;
797 }
798
800 gc_free(&gc);
801}
802
803#endif /* ifdef IFCONFIG_POOL_TEST */
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Extract the next token from a buffer, delimited by a given character.
Definition buffer.c:775
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Definition buffer.c:616
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
#define ALLOC_ARRAY_CLEAR(dptr, type, n)
Allocate and zero-initialise an array of n elements of the given type.
Definition buffer.h:2079
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Allocate and zero-initialise a garbage-collected array of n elements.
Definition buffer.h:2093
#define BLEN(buf)
Return the length of the buffer content in bytes.
Definition buffer.h:151
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1976
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
Definition buffer.h:2038
#define buf_init(buf, offset)
Definition buffer.h:364
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1960
#define D_IFCONFIG_POOL
Definition errlevel.h:83
#define M_INFO
Definition errlevel.h:54
#define CLEAR(x)
Definition basic.h:32
#define SIZE(x)
Definition basic.h:29
#define M_NOPREFIX
Definition error.h:98
#define M_FATAL
Definition error.h:90
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:221
#define M_WARN
Definition error.h:92
time_t now
Definition otime.c:33
static void update_time(void)
Definition otime.h:84
ifconfig_pool_handle ifconfig_pool_acquire(struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, struct in6_addr *remote_ipv6, const char *common_name)
Definition pool.c:297
static void ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out)
Definition pool.c:487
static void ifconfig_pool_entry_free(struct ifconfig_pool_entry *ipe, bool hard)
Definition pool.c:38
static in_addr_t ifconfig_pool_handle_to_ip_base(const struct ifconfig_pool *pool, ifconfig_pool_handle hand)
Definition pool.c:433
static ifconfig_pool_handle ifconfig_pool_ip_base_to_handle(const struct ifconfig_pool *pool, const in_addr_t addr)
Definition pool.c:367
static ifconfig_pool_handle ifconfig_pool_ipv6_base_to_handle(const struct ifconfig_pool *pool, const struct in6_addr *in_addr)
Definition pool.c:398
bool ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard)
Definition pool.c:349
struct ifconfig_pool_persist * ifconfig_pool_persist_init(const char *filename, int refresh_freq)
Definition pool.c:537
void ifconfig_pool_write(struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool)
Definition pool.c:711
static void ifconfig_pool_set(struct ifconfig_pool *pool, const char *cn, ifconfig_pool_handle h, const bool fixed)
Definition pool.c:475
void ifconfig_pool_persist_close(struct ifconfig_pool_persist *persist)
Definition pool.c:559
bool ifconfig_pool_write_trigger(struct ifconfig_pool_persist *persist)
Definition pool.c:572
bool ifconfig_pool_verify_range(const msglvl_t msglevel, const in_addr_t start, const in_addr_t end)
Definition pool.c:117
static int ifconfig_pool_find(struct ifconfig_pool *pool, const char *common_name)
Definition pool.c:57
void ifconfig_pool_free(struct ifconfig_pool *pool)
Definition pool.c:281
static void ifconfig_pool_msg(const struct ifconfig_pool *pool, int msglevel)
Definition pool.c:523
void ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool)
Definition pool.c:585
struct ifconfig_pool * ifconfig_pool_init(const bool ipv4_pool, enum pool_type type, in_addr_t start, in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits)
Definition pool.c:140
static struct in6_addr ifconfig_pool_handle_to_ipv6_base(const struct ifconfig_pool *pool, ifconfig_pool_handle hand)
Definition pool.c:462
#define IFCONFIG_POOL_MAX
Definition pool.h:31
pool_type
Definition pool.h:35
@ IFCONFIG_POOL_30NET
Definition pool.h:36
@ IFCONFIG_POOL_INDIV
Definition pool.h:37
int ifconfig_pool_handle
Definition pool.h:72
bool get_ipv6_addr(const char *hostname, struct in6_addr *network, unsigned int *netbits, msglvl_t msglevel)
Translate an IPv6 addr or hostname from string form to in6_addr.
Definition socket.c:222
in_addr_t getaddr(unsigned int flags, const char *hostname, int resolve_retry_seconds, bool *succeeded, struct signal_info *sig_info)
Translate an IPv4 addr or hostname from string form to in_addr_t.
Definition socket.c:195
struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add)
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
#define GETADDR_HOST_ORDER
bool status_trigger(struct status_output *so)
Definition status.c:123
void status_printf(struct status_output *so, const char *format,...)
Definition status.c:212
bool status_read(struct status_output *so, struct buffer *buf)
Definition status.c:257
struct status_output * status_open(const char *filename, const int refresh_freq, const int msglevel, const struct virtual_output *vout, const unsigned int flags)
Definition status.c:59
void status_flush(struct status_output *so)
Definition status.c:147
void status_reset(struct status_output *so)
Definition status.c:138
bool status_close(struct status_output *so)
Definition status.c:178
static unsigned int status_rw_flags(const struct status_output *so)
Definition status.h:91
#define STATUS_OUTPUT_WRITE
Definition status.h:51
#define STATUS_OUTPUT_READ
Definition status.h:50
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
Definition pool.h:41
bool fixed
Definition pool.h:45
time_t last_release
Definition pool.h:44
bool in_use
Definition pool.h:42
char * common_name
Definition pool.h:43
struct status_output * file
Definition pool.h:68
struct ifconfig_pool_entry * list
Definition pool.h:63
bool duplicate_cn
Definition pool.h:50
in_addr_t base
Definition pool.h:55
struct ifconfig_pool::@22 ipv6
struct ifconfig_pool::@21 ipv4
int size
Definition pool.h:62
bool enabled
Definition pool.h:53
enum pool_type type
Definition pool.h:54
int msglevel
Definition status.h:57
uint32_t in_addr_t
Definition syshead.h:52
struct gc_arena gc
Definition test_ssl.c:122