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#include "resolve.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 const 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 && common_name && ipe->common_name
94 && !strcmp(common_name, ipe->common_name))
95 {
96 previous_usage = i;
97 }
98 }
99 }
100
101 if (previous_usage >= 0)
102 {
103 return previous_usage;
104 }
105
106 if (new_usage >= 0)
107 {
108 return new_usage;
109 }
110
111 return -1;
112}
113
114/*
115 * Verify start/end range
116 */
117bool
118ifconfig_pool_verify_range(const msglvl_t msglevel, const in_addr_t start, const in_addr_t end)
119{
120 struct gc_arena gc = gc_new();
121 bool ret = true;
122
123 if (start > end)
124 {
125 msg(msglevel, "--ifconfig-pool start IP [%s] is greater than end IP [%s]",
126 print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc));
127 ret = false;
128 }
129 if (end - start >= IFCONFIG_POOL_MAX)
130 {
131 msg(msglevel,
132 "--ifconfig-pool address range is too large [%s -> %s]. Current maximum is %d addresses, as defined by IFCONFIG_POOL_MAX variable.",
133 print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc), IFCONFIG_POOL_MAX);
134 ret = false;
135 }
136 gc_free(&gc);
137 return ret;
138}
139
140struct ifconfig_pool *
141ifconfig_pool_init(const bool ipv4_pool, enum pool_type type, in_addr_t start, in_addr_t end,
142 const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base,
143 const int ipv6_netbits)
144{
145 struct gc_arena gc = gc_new();
146 struct ifconfig_pool *pool = NULL;
147 int pool_ipv4_size = -1, pool_ipv6_size = -1;
148
149 ASSERT(start <= end && end - start < IFCONFIG_POOL_MAX);
150 ALLOC_OBJ_CLEAR(pool, struct ifconfig_pool);
151
153
154 pool->ipv4.enabled = ipv4_pool;
155
156 if (pool->ipv4.enabled)
157 {
158 pool->ipv4.type = type;
159 switch (pool->ipv4.type)
160 {
162 pool->ipv4.base = start & ~3u;
163 pool_ipv4_size = (((end | 3) + 1) - pool->ipv4.base) >> 2;
164 break;
165
167 pool->ipv4.base = start;
168 pool_ipv4_size = end - start + 1;
169 break;
170
171 default:
172 ASSERT(0);
173 }
174
175 if (pool_ipv4_size < 2)
176 {
177 msg(M_FATAL, "IPv4 pool size is too small (%d), must be at least 2", pool_ipv4_size);
178 }
179
180 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv4: base=%s size=%d",
181 print_in_addr_t(pool->ipv4.base, 0, &gc), pool_ipv4_size);
182
183 pool->size = pool_ipv4_size;
184 }
185
186 /* IPv6 pools are always "INDIV" type */
187 pool->ipv6.enabled = ipv6_pool;
188
189 if (pool->ipv6.enabled)
190 {
191 /* the host portion of the address will always be contained in the last
192 * 4 bytes, therefore we can just extract that and use it as base in
193 * integer form
194 */
195 uint32_t base = (ipv6_base.s6_addr[12] << 24) | (ipv6_base.s6_addr[13] << 16)
196 | (ipv6_base.s6_addr[14] << 8) | ipv6_base.s6_addr[15];
197 /* some bits of the last 4 bytes may still be part of the network
198 * portion of the address, therefore we need to set them to 0
199 */
200 if ((128 - ipv6_netbits) < 32)
201 {
202 /* extract only the bits that are really part of the host portion of
203 * the address.
204 *
205 * Example: if we have netbits=31, the first bit has to be zero'd,
206 * the following operation first computes mask=0x3fffff and then
207 * uses mask to extract the wanted bits from base
208 */
209 uint32_t mask = (1 << (128 - ipv6_netbits)) - 1;
210 base &= mask;
211 }
212
213 pool->ipv6.base = ipv6_base;
214
215 /* if a pool starts at a base address that has all-zero in the
216 * host part, that first IPv6 address must not be assigned to
217 * clients because it is not usable (subnet anycast address).
218 * Start with 1, then.
219 *
220 * NOTE: this will also (mis-)fire for something like
221 * ifconfig-ipv6-pool 2001:db8:0:1:1234::0/64
222 * as we only check the rightmost 32 bits of the host part. So be it.
223 */
224 if (base == 0)
225 {
226 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: incrementing pool start "
227 "to avoid ::0 assignment");
228 base++;
229 pool->ipv6.base.s6_addr[15]++;
230 }
231
232 pool_ipv6_size =
233 ipv6_netbits >= 112 ? (1 << (128 - ipv6_netbits)) - base : IFCONFIG_POOL_MAX;
234
235 if (pool_ipv6_size < 2)
236 {
237 msg(M_FATAL, "IPv6 pool size is too small (%d), must be at least 2", pool_ipv6_size);
238 }
239
240 msg(D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: base=%s size=%d netbits=%d",
241 print_in6_addr(pool->ipv6.base, 0, &gc), pool_ipv6_size, ipv6_netbits);
242
243 /* if there is no v4 pool, or the v6 pool is smaller, use
244 * v6 pool size as "unified pool size"
245 */
246 if (pool->size <= 0 || pool_ipv6_size < pool->size)
247 {
248 pool->size = pool_ipv6_size;
249 }
250 }
251
252 if (pool->ipv4.enabled && pool->ipv6.enabled)
253 {
254 if (pool_ipv4_size < pool_ipv6_size)
255 {
256 msg(M_INFO,
257 "NOTE: IPv4 pool size is %d, IPv6 pool size is %d. "
258 "IPv4 pool size limits the number of clients that can be "
259 "served from the pool",
260 pool_ipv4_size, pool_ipv6_size);
261 }
262 else if (pool_ipv4_size > pool_ipv6_size)
263 {
264 msg(M_WARN,
265 "WARNING: IPv4 pool size is %d, IPv6 pool size is %d. "
266 "IPv6 pool size limits the number of clients that can be "
267 "served from the pool. This is likely a MISTAKE - please check "
268 "your configuration",
269 pool_ipv4_size, pool_ipv6_size);
270 }
271 }
272
273 ASSERT(pool->size > 0);
274
275 ALLOC_ARRAY_CLEAR(pool->list, struct ifconfig_pool_entry, pool->size);
276
277 gc_free(&gc);
278 return pool;
279}
280
281void
283{
284 if (pool)
285 {
286 int i;
287
288 for (i = 0; i < pool->size; ++i)
289 {
290 ifconfig_pool_entry_free(&pool->list[i], true);
291 }
292 free(pool->list);
293 free(pool);
294 }
295}
296
299 struct in6_addr *remote_ipv6, const char *common_name)
300{
301 int i;
302
303 i = ifconfig_pool_find(pool, common_name);
304 if (i >= 0)
305 {
306 struct ifconfig_pool_entry *ipe = &pool->list[i];
307 ASSERT(!ipe->in_use);
308 ifconfig_pool_entry_free(ipe, true);
309 ipe->in_use = true;
310 if (common_name)
311 {
313 }
314
315 if (pool->ipv4.enabled && local && remote)
316 {
317 switch (pool->ipv4.type)
318 {
320 {
321 in_addr_t b = pool->ipv4.base + (i << 2);
322 *local = b + 1;
323 *remote = b + 2;
324 break;
325 }
326
328 {
329 in_addr_t b = pool->ipv4.base + i;
330 *local = 0;
331 *remote = b;
332 break;
333 }
334
335 default:
336 ASSERT(0);
337 }
338 }
339
340 /* IPv6 pools are always INDIV (--linear) */
341 if (pool->ipv6.enabled && remote_ipv6)
342 {
343 *remote_ipv6 = add_in6_addr(pool->ipv6.base, i);
344 }
345 }
346 return i;
347}
348
349bool
350ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard)
351{
352 bool ret = false;
353
354 if (pool && hand >= 0 && hand < pool->size)
355 {
356 ifconfig_pool_entry_free(&pool->list[hand], hard);
357 ret = true;
358 }
359 return ret;
360}
361
362/*
363 * private access functions
364 */
365
366/* currently handling IPv4 logic only */
369{
370 ifconfig_pool_handle ret = -1;
371
372 switch (pool->ipv4.type)
373 {
375 {
376 ret = (addr - pool->ipv4.base) >> 2;
377 break;
378 }
379
381 {
382 ret = (addr - pool->ipv4.base);
383 break;
384 }
385
386 default:
387 ASSERT(0);
388 }
389
390 if (ret < 0 || ret >= pool->size)
391 {
392 ret = -1;
393 }
394
395 return ret;
396}
397
399ifconfig_pool_ipv6_base_to_handle(const struct ifconfig_pool *pool, const struct in6_addr *in_addr)
400{
402 uint32_t base, addr;
403
404 /* IPv6 pool is always IFCONFIG_POOL_INDIV.
405 *
406 * We assume the offset can't be larger than 2^32-1, therefore we compute
407 * the difference only among the last 4 bytes like if they were two 32bit
408 * long integers. The rest of the address must match.
409 */
410 for (int i = 0; i < (12); i++)
411 {
412 if (pool->ipv6.base.s6_addr[i] != in_addr->s6_addr[i])
413 {
414 return -1;
415 }
416 }
417
418 base = (pool->ipv6.base.s6_addr[12] << 24) | (pool->ipv6.base.s6_addr[13] << 16)
419 | (pool->ipv6.base.s6_addr[14] << 8) | pool->ipv6.base.s6_addr[15];
420
421 addr = (in_addr->s6_addr[12] << 24) | (in_addr->s6_addr[13] << 16) | (in_addr->s6_addr[14] << 8)
422 | in_addr->s6_addr[15];
423
424 ret = addr - base;
425 if (ret < 0 || ret >= pool->size)
426 {
427 ret = -1;
428 }
429
430 return ret;
431}
432
433static in_addr_t
435{
436 in_addr_t ret = 0;
437
438 if (pool->ipv4.enabled && hand >= 0 && hand < pool->size)
439 {
440 switch (pool->ipv4.type)
441 {
443 {
444 ret = pool->ipv4.base + (hand << 2);
445 break;
446 }
447
449 {
450 ret = pool->ipv4.base + hand;
451 break;
452 }
453
454 default:
455 ASSERT(0);
456 }
457 }
458
459 return ret;
460}
461
462static struct in6_addr
464{
465 struct in6_addr ret = IN6ADDR_ANY_INIT;
466
467 /* IPv6 pools are always INDIV (--linear) */
468 if (pool->ipv6.enabled && hand >= 0 && hand < pool->size)
469 {
470 ret = add_in6_addr(pool->ipv6.base, hand);
471 }
472 return ret;
473}
474
475static void
477 const bool fixed)
478{
479 struct ifconfig_pool_entry *e = &pool->list[h];
481 e->in_use = false;
482 e->common_name = string_alloc(cn, NULL);
483 e->last_release = now;
484 e->fixed = fixed;
485}
486
487static void
488ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out)
489{
490 if (pool && out)
491 {
492 struct gc_arena gc = gc_new();
493 int i;
494
495 for (i = 0; i < pool->size; ++i)
496 {
497 const struct ifconfig_pool_entry *e = &pool->list[i];
498
499 if (e->common_name)
500 {
501 const char *ip6_str = "";
502 const char *ip_str = "";
503
504 if (pool->ipv4.enabled)
505 {
506 const in_addr_t ip = ifconfig_pool_handle_to_ip_base(pool, i);
507 ip_str = print_in_addr_t(ip, 0, &gc);
508 }
509
510 if (pool->ipv6.enabled)
511 {
512 const struct in6_addr ip6 = ifconfig_pool_handle_to_ipv6_base(pool, i);
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
598 ALLOC_ARRAY_CLEAR_GC(cn_buf, char, buf_size, &gc);
599 ALLOC_ARRAY_CLEAR_GC(ip_buf, char, buf_size, &gc);
600 ALLOC_ARRAY_CLEAR_GC(ip6_buf, char, buf_size, &gc);
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;
642 in_addr_t addr = getaddr(GETADDR_HOST_ORDER, ip_buf, 0, &v4_ok, NULL);
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 {
650 h = ifconfig_pool_ip_base_to_handle(pool, addr);
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 ? cn : "[NULL]");
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 ? cn : "[NULL]");
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)
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:757
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Definition buffer.c:601
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:2068
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Allocate and zero-initialise a garbage-collected array of n elements.
Definition buffer.h:2082
#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:1965
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
Definition buffer.h:2027
#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:1949
#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:298
static void ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out)
Definition pool.c:488
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:434
static ifconfig_pool_handle ifconfig_pool_ip_base_to_handle(const struct ifconfig_pool *pool, const in_addr_t addr)
Definition pool.c:368
static ifconfig_pool_handle ifconfig_pool_ipv6_base_to_handle(const struct ifconfig_pool *pool, const struct in6_addr *in_addr)
Definition pool.c:399
bool ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard)
Definition pool.c:350
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:476
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
bool ifconfig_pool_verify_range(const msglvl_t msglevel, const in_addr_t start, const in_addr_t end)
Definition pool.c:118
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:282
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:141
static struct in6_addr ifconfig_pool_handle_to_ipv6_base(const struct ifconfig_pool *pool, ifconfig_pool_handle hand)
Definition pool.c:463
#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 resolve.c:489
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 resolve.c:442
DNS resolution.
#define GETADDR_HOST_ORDER
Definition resolve.h:40
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)
void status_reset(const struct status_output *so)
Definition status.c:138
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:254
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
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
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::@102204320242243241112225236071133341336301303254 ipv6
struct ifconfig_pool::@054126071253267302350043225374133241003025132045 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:138