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-2025 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 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 int 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
297ifconfig_pool_acquire(struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote,
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 */
367ifconfig_pool_ip_base_to_handle(const struct ifconfig_pool *pool, const in_addr_t addr)
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 struct in6_addr ip6;
498 in_addr_t ip;
499 const char *ip6_str = "";
500 const char *ip_str = "";
501
502 if (e->common_name)
503 {
504 if (pool->ipv4.enabled)
505 {
507 ip_str = print_in_addr_t(ip, 0, &gc);
508 }
509
510 if (pool->ipv6.enabled)
511 {
513 ip6_str = print_in6_addr(ip6, 0, &gc);
514 }
515
516 status_printf(out, "%s,%s,%s", e->common_name, ip_str, ip6_str);
517 }
518 }
519 gc_free(&gc);
520 }
521}
522
523static void
524ifconfig_pool_msg(const struct ifconfig_pool *pool, int msglevel)
525{
526 struct status_output *so = status_open(NULL, 0, msglevel, NULL, 0);
527 ASSERT(so);
528 status_printf(so, "IFCONFIG POOL LIST");
529 ifconfig_pool_list(pool, so);
530 status_close(so);
531}
532
533/*
534 * Deal with reading/writing the ifconfig pool database to a file
535 */
536
538ifconfig_pool_persist_init(const char *filename, int refresh_freq)
539{
540 struct ifconfig_pool_persist *ret;
541
542 ASSERT(filename);
543
545 if (refresh_freq > 0)
546 {
547 ret->fixed = false;
548 ret->file =
549 status_open(filename, refresh_freq, -1, NULL, STATUS_OUTPUT_READ | STATUS_OUTPUT_WRITE);
550 }
551 else
552 {
553 ret->fixed = true;
554 ret->file = status_open(filename, 0, -1, NULL, STATUS_OUTPUT_READ);
555 }
556 return ret;
557}
558
559void
561{
562 if (persist)
563 {
564 if (persist->file)
565 {
566 status_close(persist->file);
567 }
568 free(persist);
569 }
570}
571
572bool
574{
575 if (persist->file)
576 {
577 return status_trigger(persist->file);
578 }
579 else
580 {
581 return false;
582 }
583}
584
585void
587{
588 const int buf_size = 128;
589
590 update_time();
591
592 if (persist && persist->file && pool)
593 {
594 struct gc_arena gc = gc_new();
595 struct buffer in = alloc_buf_gc(256, &gc);
596 char *cn_buf, *ip_buf, *ip6_buf;
597
601
602 while (true)
603 {
604 ASSERT(buf_init(&in, 0));
605 if (!status_read(persist->file, &in))
606 {
607 break;
608 }
609 if (!BLEN(&in))
610 {
611 continue;
612 }
613
614 int c = *BSTR(&in);
615 if (c == '#' || c == ';')
616 {
617 continue;
618 }
619
620 msg(M_INFO, "ifconfig_pool_read(), in='%s'", BSTR(&in));
621
622 /* The expected format of a line is: "CN,IP4,IP6".
623 *
624 * IP4 or IP6 may be empty when respectively no v4 or v6 pool
625 * was previously specified.
626 *
627 * This means that accepted strings can be:
628 * - CN,IP4,IP6
629 * - CN,IP4
630 * - CN,,IP6
631 */
632 if (!buf_parse(&in, ',', cn_buf, buf_size) || !buf_parse(&in, ',', ip_buf, buf_size))
633 {
634 continue;
635 }
636
637 ifconfig_pool_handle h = -1, h6 = -1;
638
639 if (strlen(ip_buf) > 0)
640 {
641 bool v4_ok = true;
643
644 if (!v4_ok)
645 {
646 msg(M_WARN, "pool: invalid IPv4 (%s) for CN=%s", ip_buf, cn_buf);
647 }
648 else
649 {
651 if (h < 0)
652 {
653 msg(M_WARN, "pool: IPv4 (%s) out of pool range for CN=%s", ip_buf, cn_buf);
654 }
655 }
656 }
657
658 if (buf_parse(&in, ',', ip6_buf, buf_size) && strlen(ip6_buf) > 0)
659 {
660 struct in6_addr addr6;
661
662 if (!get_ipv6_addr(ip6_buf, &addr6, NULL, M_WARN))
663 {
664 msg(M_WARN, "pool: invalid IPv6 (%s) for CN=%s", ip6_buf, cn_buf);
665 }
666 else
667 {
668 h6 = ifconfig_pool_ipv6_base_to_handle(pool, &addr6);
669 if (h6 < 0)
670 {
671 msg(M_WARN, "pool: IPv6 (%s) out of pool range for CN=%s", ip6_buf, cn_buf);
672 }
673
674 /* Rely on IPv6 if no IPv4 was provided or the one provided
675 * was not valid
676 */
677 if (h < 0)
678 {
679 h = h6;
680 }
681 }
682 }
683
684 /* at the moment IPv4 and IPv6 share the same pool, therefore offsets
685 * have to match for the same client.
686 *
687 * If offsets differ we use the IPv4, therefore warn the user about this.
688 */
689 if ((h6 >= 0) && (h != h6))
690 {
691 msg(M_WARN, "pool: IPv4 (%s) and IPv6 (%s) have different offsets! Relying on IPv4",
692 ip_buf, ip6_buf);
693 }
694
695 /* if at least one among v4 and v6 was properly parsed, attempt
696 * setting an handle for this client
697 */
698 if (h >= 0)
699 {
700 msg(M_INFO, "succeeded -> ifconfig_pool_set(hand=%d)", h);
701 ifconfig_pool_set(pool, cn_buf, h, persist->fixed);
702 }
703 }
704
706
707 gc_free(&gc);
708 }
709}
710
711void
712ifconfig_pool_write(struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool)
713{
714 if (persist && persist->file && (status_rw_flags(persist->file) & STATUS_OUTPUT_WRITE) && pool)
715 {
716 status_reset(persist->file);
717 ifconfig_pool_list(pool, persist->file);
718 status_flush(persist->file);
719 }
720}
721
722/*
723 * TESTING ONLY
724 */
725
726#ifdef IFCONFIG_POOL_TEST
727
728#define DUP_CN
729
730void
731ifconfig_pool_test(in_addr_t start, in_addr_t end)
732{
733 struct gc_arena gc = gc_new();
735 /*struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_INDIV, start, end);*/
736 ifconfig_pool_handle array[256];
737 int i;
738
739 CLEAR(array);
740
741 msg(M_INFO | M_NOPREFIX, "************ 1");
742 for (i = 0; i < (int)SIZE(array); ++i)
743 {
744 char *cn;
746 in_addr_t local, remote;
747 char buf[256];
748 snprintf(buf, sizeof(buf), "common-name-%d", i);
749#ifdef DUP_CN
750 cn = NULL;
751#else
752 cn = buf;
753#endif
754 h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn);
755 if (h < 0)
756 {
757 break;
758 }
759 msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s",
760 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn);
761 array[i] = h;
762 }
763
764 msg(M_INFO | M_NOPREFIX, "************* 2");
765 for (i = (int)SIZE(array) / 16; i < (int)SIZE(array) / 8; ++i)
766 {
767 msg(M_INFO, "Attempt to release %d cn=%s", array[i], p->list[i].common_name);
768 if (!ifconfig_pool_release(p, array[i]))
769 {
770 break;
771 }
772 msg(M_INFO, "Succeeded");
773 }
774
775 CLEAR(array);
776
777 msg(M_INFO | M_NOPREFIX, "**************** 3");
778 for (i = 0; i < (int)SIZE(array); ++i)
779 {
780 char *cn;
782 in_addr_t local, remote;
783 char buf[256];
784 snprintf(buf, sizeof(buf), "common-name-%d", i + 24);
785#ifdef DUP_CN
786 cn = NULL;
787#else
788 cn = buf;
789#endif
790 h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn);
791 if (h < 0)
792 {
793 break;
794 }
795 msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s",
796 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn);
797 array[i] = h;
798 }
799
801 gc_free(&gc);
802}
803
804#endif /* ifdef IFCONFIG_POOL_TEST */
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition buffer.c:825
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:649
#define BSTR(buf)
Definition buffer.h:128
#define ALLOC_ARRAY_CLEAR(dptr, type, n)
Definition buffer.h:1058
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Definition buffer.h:1064
#define BLEN(buf)
Definition buffer.h:126
static void gc_free(struct gc_arena *a)
Definition buffer.h:1015
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1042
#define buf_init(buf, offset)
Definition buffer.h:209
static struct gc_arena gc_new(void)
Definition buffer.h:1007
#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:96
#define M_FATAL
Definition error.h:88
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
#define M_WARN
Definition error.h:90
time_t now
Definition otime.c:33
static void update_time(void)
Definition otime.h:76
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
bool ifconfig_pool_verify_range(const int msglevel, const in_addr_t start, const in_addr_t end)
Definition pool.c:117
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:538
void ifconfig_pool_write(struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool)
Definition pool.c:712
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:560
bool ifconfig_pool_write_trigger(struct ifconfig_pool_persist *persist)
Definition pool.c:573
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:524
void ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool)
Definition pool.c:586
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, int msglevel)
Translate an IPv6 addr or hostname from string form to in6_addr.
Definition socket.c:214
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:187
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:124
void status_printf(struct status_output *so, const char *format,...)
Definition status.c:213
bool status_read(struct status_output *so, struct buffer *buf)
Definition status.c:259
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:60
void status_flush(struct status_output *so)
Definition status.c:148
void status_reset(struct status_output *so)
Definition status.c:139
bool status_close(struct status_output *so)
Definition status.c:179
static unsigned int status_rw_flags(const struct status_output *so)
Definition status.h:90
#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:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
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:56
struct gc_arena gc
Definition test_ssl.c:154