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