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