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 
38 static 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 
57 static int
58 ifconfig_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
94  && common_name
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  */
120 bool
121 ifconfig_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 
145 struct ifconfig_pool *
146 ifconfig_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 
158  pool->duplicate_cn = duplicate_cn;
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  {
167  case IFCONFIG_POOL_30NET:
168  pool->ipv4.base = start & ~3;
169  pool_ipv4_size = (((end | 3) + 1) - pool->ipv4.base) >> 2;
170  break;
171 
172  case IFCONFIG_POOL_INDIV:
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 
289 void
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 
306 ifconfig_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  {
319  ipe->common_name = string_alloc(common_name, NULL);
320  }
321 
322  if (pool->ipv4.enabled && local && remote)
323  {
324  switch (pool->ipv4.type)
325  {
326  case IFCONFIG_POOL_30NET:
327  {
328  in_addr_t b = pool->ipv4.base + (i << 2);
329  *local = b + 1;
330  *remote = b + 2;
331  break;
332  }
333 
334  case IFCONFIG_POOL_INDIV:
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 
356 bool
357 ifconfig_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 */
375 ifconfig_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  {
381  case IFCONFIG_POOL_30NET:
382  {
383  ret = (addr - pool->ipv4.base) >> 2;
384  break;
385  }
386 
387  case IFCONFIG_POOL_INDIV:
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 
445 static 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  {
454  case IFCONFIG_POOL_30NET:
455  {
456  ret = pool->ipv4.base + (hand << 2);
457  break;
458  }
459 
460  case IFCONFIG_POOL_INDIV:
461  {
462  ret = pool->ipv4.base + hand;
463  break;
464  }
465 
466  default:
467  ASSERT(0);
468  }
469  }
470 
471  return ret;
472 }
473 
474 static 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 
487 static void
488 ifconfig_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];
492  ifconfig_pool_entry_free(e, true);
493  e->in_use = false;
494  e->common_name = string_alloc(cn, NULL);
495  e->last_release = now;
496  e->fixed = fixed;
497 }
498 
499 static void
500 ifconfig_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  {
519  ip = ifconfig_pool_handle_to_ip_base(pool, i);
520  ip_str = print_in_addr_t(ip, 0, &gc);
521  }
522 
523  if (pool->ipv6.enabled)
524  {
525  ip6 = ifconfig_pool_handle_to_ipv6_base(pool, i);
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 
536 static void
537 ifconfig_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 
550 struct ifconfig_pool_persist *
551 ifconfig_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 
571 void
573 {
574  if (persist)
575  {
576  if (persist->file)
577  {
578  status_close(persist->file);
579  }
580  free(persist);
581  }
582 }
583 
584 bool
586 {
587  if (persist->file)
588  {
589  return status_trigger(persist->file);
590  }
591  else
592  {
593  return false;
594  }
595 }
596 
597 void
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 
610  ALLOC_ARRAY_CLEAR_GC(cn_buf, char, buf_size, &gc);
611  ALLOC_ARRAY_CLEAR_GC(ip_buf, char, buf_size, &gc);
612  ALLOC_ARRAY_CLEAR_GC(ip6_buf, char, buf_size, &gc);
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;
655  in_addr_t addr = getaddr(GETADDR_HOST_ORDER, ip_buf, 0, &v4_ok,
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  {
665  h = ifconfig_pool_ip_base_to_handle(pool, addr);
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 
732 void
733 ifconfig_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 
751 void
752 ifconfig_pool_test(in_addr_t start, in_addr_t end)
753 {
754  struct gc_arena gc = gc_new();
755  struct ifconfig_pool *p = ifconfig_pool_init(IFCONFIG_POOL_30NET, start, end);
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 */
status_open
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
status_trigger
bool status_trigger(struct status_output *so)
Definition: status.c:133
ifconfig_pool::enabled
bool enabled
Definition: pool.h:53
ifconfig_pool_handle
int ifconfig_pool_handle
Definition: pool.h:71
M_INFO
#define M_INFO
Definition: errlevel.h:55
IFCONFIG_POOL_MAX
#define IFCONFIG_POOL_MAX
Definition: pool.h:32
ALLOC_ARRAY_CLEAR
#define ALLOC_ARRAY_CLEAR(dptr, type, n)
Definition: buffer.h:1081
error.h
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1030
status_rw_flags
static unsigned int status_rw_flags(const struct status_output *so)
Definition: status.h:93
ifconfig_pool_persist::file
struct status_output * file
Definition: pool.h:67
M_FATAL
#define M_FATAL
Definition: error.h:89
status_output::msglevel
int msglevel
Definition: status.h:56
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:209
BSTR
#define BSTR(buf)
Definition: buffer.h:129
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
ifconfig_pool_find
static int ifconfig_pool_find(struct ifconfig_pool *pool, const char *common_name)
Definition: pool.c:58
ifconfig_pool_entry::fixed
bool fixed
Definition: pool.h:46
M_NOPREFIX
#define M_NOPREFIX
Definition: error.h:97
status_read
bool status_read(struct status_output *so, struct buffer *buf)
Definition: status.c:268
ifconfig_pool_persist
Definition: pool.h:65
ifconfig_pool
Definition: pool.h:49
STATUS_OUTPUT_WRITE
#define STATUS_OUTPUT_WRITE
Definition: status.h:51
IFCONFIG_POOL_30NET
@ IFCONFIG_POOL_30NET
Definition: pool.h:37
CLEAR
#define CLEAR(x)
Definition: basic.h:33
ifconfig_pool_persist_init
struct ifconfig_pool_persist * ifconfig_pool_persist_init(const char *filename, int refresh_freq)
Definition: pool.c:551
getaddr
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:180
string_alloc
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:667
ASSERT
#define ASSERT(x)
Definition: error.h:195
print_in6_addr
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
Definition: socket.c:2924
BLEN
#define BLEN(buf)
Definition: buffer.h:127
status_reset
void status_reset(struct status_output *so)
Definition: status.c:148
ifconfig_pool_entry::in_use
bool in_use
Definition: pool.h:43
update_time
static void update_time(void)
Definition: otime.h:77
ALLOC_ARRAY_CLEAR_GC
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Definition: buffer.h:1087
ifconfig_pool_entry::common_name
char * common_name
Definition: pool.h:44
M_WARN
#define M_WARN
Definition: error.h:91
ifconfig_pool::list
struct ifconfig_pool_entry * list
Definition: pool.h:62
status_printf
void status_printf(struct status_output *so, const char *format,...)
Definition: status.c:222
pool.h
ifconfig_pool::ipv4
struct ifconfig_pool::@10 ipv4
pool_type
pool_type
Definition: pool.h:35
status_output
Definition: status.h:48
ifconfig_pool_handle_to_ip_base
static in_addr_t ifconfig_pool_handle_to_ip_base(const struct ifconfig_pool *pool, ifconfig_pool_handle hand)
Definition: pool.c:446
ifconfig_pool::duplicate_cn
bool duplicate_cn
Definition: pool.h:51
ifconfig_pool_write
void ifconfig_pool_write(struct ifconfig_pool_persist *persist, const struct ifconfig_pool *pool)
Definition: pool.c:733
SIZE
#define SIZE(x)
Definition: basic.h:30
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
IFCONFIG_POOL_INDIV
@ IFCONFIG_POOL_INDIV
Definition: pool.h:38
ifconfig_pool_ipv6_base_to_handle
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
ifconfig_pool::type
enum pool_type type
Definition: pool.h:54
print_in_addr_t
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
Definition: socket.c:2904
D_IFCONFIG_POOL
#define D_IFCONFIG_POOL
Definition: errlevel.h:84
ifconfig_pool_msg
static void ifconfig_pool_msg(const struct ifconfig_pool *pool, int msglevel)
Definition: pool.c:537
buffer.h
status_close
bool status_close(struct status_output *so)
Definition: status.c:188
syshead.h
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
ifconfig_pool_write_trigger
bool ifconfig_pool_write_trigger(struct ifconfig_pool_persist *persist)
Definition: pool.c:585
ifconfig_pool_ip_base_to_handle
static ifconfig_pool_handle ifconfig_pool_ip_base_to_handle(const struct ifconfig_pool *pool, const in_addr_t addr)
Definition: pool.c:375
ifconfig_pool_acquire
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
ifconfig_pool_persist_close
void ifconfig_pool_persist_close(struct ifconfig_pool_persist *persist)
Definition: pool.c:572
status_flush
void status_flush(struct status_output *so)
Definition: status.c:157
ifconfig_pool_free
void ifconfig_pool_free(struct ifconfig_pool *pool)
Definition: pool.c:290
ifconfig_pool_persist::fixed
bool fixed
Definition: pool.h:68
get_ipv6_addr
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:211
GETADDR_HOST_ORDER
#define GETADDR_HOST_ORDER
Definition: socket.h:506
otime.h
ifconfig_pool_set
static void ifconfig_pool_set(struct ifconfig_pool *pool, const char *cn, ifconfig_pool_handle h, const bool fixed)
Definition: pool.c:488
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1038
ifconfig_pool_handle_to_ipv6_base
static struct in6_addr ifconfig_pool_handle_to_ipv6_base(const struct ifconfig_pool *pool, ifconfig_pool_handle hand)
Definition: pool.c:475
socket.h
ALLOC_OBJ_CLEAR
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1065
now
time_t now
Definition: otime.c:34
config.h
ifconfig_pool_entry_free
static void ifconfig_pool_entry_free(struct ifconfig_pool_entry *ipe, bool hard)
Definition: pool.c:39
ifconfig_pool_list
static void ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out)
Definition: pool.c:500
ifconfig_pool_entry::last_release
time_t last_release
Definition: pool.h:45
ifconfig_pool_verify_range
bool ifconfig_pool_verify_range(const int msglevel, const in_addr_t start, const in_addr_t end)
Definition: pool.c:121
add_in6_addr
struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add)
Definition: socket.c:2955
memdbg.h
ifconfig_pool_release
bool ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard)
Definition: pool.c:357
ifconfig_pool_init
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
ifconfig_pool_read
void ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool)
Definition: pool.c:598
ifconfig_pool_entry
Definition: pool.h:41
msg
#define msg(flags,...)
Definition: error.h:144
STATUS_OUTPUT_READ
#define STATUS_OUTPUT_READ
Definition: status.h:50
ifconfig_pool::ipv6
struct ifconfig_pool::@11 ipv6
ifconfig_pool::base
in_addr_t base
Definition: pool.h:55
ifconfig_pool::size
int size
Definition: pool.h:61
buf_parse
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition: buffer.c:843