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
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
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.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "config-win32.h"
44 ifconfig_pool_entry_free (struct ifconfig_pool_entry
*ipe
, bool hard
)
47 if (hard
&& ipe
->common_name
)
49 free (ipe
->common_name
);
50 ipe
->common_name
= NULL
;
53 ipe
->last_release
= 0;
55 ipe
->last_release
= now
;
59 ifconfig_pool_find (struct ifconfig_pool
*pool
, const char *common_name
)
62 time_t earliest_release
= 0;
63 int previous_usage
= -1;
66 for (i
= 0; i
< pool
->size
; ++i
)
68 struct ifconfig_pool_entry
*ipe
= &pool
->list
[i
];
72 * If duplicate_cn mode, take first available IP address
74 if (pool
->duplicate_cn
)
81 * Keep track of the unused IP address entry which
82 * was released earliest.
84 if ((new_usage
== -1 || ipe
->last_release
< earliest_release
) && !ipe
->fixed
)
86 earliest_release
= ipe
->last_release
;
91 * Keep track of a possible allocation to us
92 * from an earlier session.
94 if (previous_usage
< 0
97 && !strcmp (common_name
, ipe
->common_name
))
103 if (previous_usage
>= 0)
104 return previous_usage
;
113 * Verify start/end range
116 ifconfig_pool_verify_range (const int msglevel
, const in_addr_t start
, const in_addr_t end
)
118 struct gc_arena gc
= gc_new ();
123 msg (msglevel
, "--ifconfig-pool start IP [%s] is greater than end IP [%s]",
124 print_in_addr_t (start
, 0, &gc
),
125 print_in_addr_t (end
, 0, &gc
));
128 if (end
- start
>= IFCONFIG_POOL_MAX
)
130 msg (msglevel
, "--ifconfig-pool address range is too large [%s -> %s]. Current maximum is %d addresses, as defined by IFCONFIG_POOL_MAX variable.",
131 print_in_addr_t (start
, 0, &gc
),
132 print_in_addr_t (end
, 0, &gc
),
140 struct ifconfig_pool
*
141 ifconfig_pool_init (int type
, in_addr_t start
, in_addr_t end
, const bool duplicate_cn
)
143 struct gc_arena gc
= gc_new ();
144 struct ifconfig_pool
*pool
= NULL
;
146 ASSERT (start
<= end
&& end
- start
< IFCONFIG_POOL_MAX
);
147 ALLOC_OBJ_CLEAR (pool
, struct ifconfig_pool
);
150 pool
->duplicate_cn
= duplicate_cn
;
154 case IFCONFIG_POOL_30NET
:
155 pool
->base
= start
& ~3;
156 pool
->size
= (((end
| 3) + 1) - pool
->base
) >> 2;
158 case IFCONFIG_POOL_INDIV
:
160 pool
->size
= end
- start
+ 1;
166 ALLOC_ARRAY_CLEAR (pool
->list
, struct ifconfig_pool_entry
, pool
->size
);
168 msg (D_IFCONFIG_POOL
, "IFCONFIG POOL: base=%s size=%d",
169 print_in_addr_t (pool
->base
, 0, &gc
),
177 ifconfig_pool_free (struct ifconfig_pool
*pool
)
182 for (i
= 0; i
< pool
->size
; ++i
)
183 ifconfig_pool_entry_free (&pool
->list
[i
], true);
190 ifconfig_pool_acquire (struct ifconfig_pool
*pool
, in_addr_t
*local
, in_addr_t
*remote
, const char *common_name
)
194 i
= ifconfig_pool_find (pool
, common_name
);
197 struct ifconfig_pool_entry
*ipe
= &pool
->list
[i
];
198 ASSERT (!ipe
->in_use
);
199 ifconfig_pool_entry_free (ipe
, true);
202 ipe
->common_name
= string_alloc (common_name
, NULL
);
206 case IFCONFIG_POOL_30NET
:
208 in_addr_t b
= pool
->base
+ (i
<< 2);
213 case IFCONFIG_POOL_INDIV
:
215 in_addr_t b
= pool
->base
+ i
;
228 ifconfig_pool_release (struct ifconfig_pool
* pool
, ifconfig_pool_handle hand
, const bool hard
)
231 if (pool
&& hand
>= 0 && hand
< pool
->size
)
233 ifconfig_pool_entry_free (&pool
->list
[hand
], hard
);
240 * private access functions
243 static ifconfig_pool_handle
244 ifconfig_pool_ip_base_to_handle (const struct ifconfig_pool
* pool
, const in_addr_t addr
)
246 ifconfig_pool_handle ret
= -1;
250 case IFCONFIG_POOL_30NET
:
252 ret
= (addr
- pool
->base
) >> 2;
255 case IFCONFIG_POOL_INDIV
:
257 ret
= (addr
- pool
->base
);
264 if (ret
< 0 || ret
>= pool
->size
)
271 ifconfig_pool_handle_to_ip_base (const struct ifconfig_pool
* pool
, ifconfig_pool_handle hand
)
275 if (hand
>= 0 && hand
< pool
->size
)
279 case IFCONFIG_POOL_30NET
:
281 ret
= pool
->base
+ (hand
<< 2);;
284 case IFCONFIG_POOL_INDIV
:
286 ret
= pool
->base
+ hand
;
298 ifconfig_pool_set (struct ifconfig_pool
* pool
, const char *cn
, const in_addr_t addr
, const bool fixed
)
300 ifconfig_pool_handle h
= ifconfig_pool_ip_base_to_handle (pool
, addr
);
303 struct ifconfig_pool_entry
*e
= &pool
->list
[h
];
304 ifconfig_pool_entry_free (e
, true);
306 e
->common_name
= string_alloc (cn
, NULL
);
307 e
->last_release
= now
;
313 ifconfig_pool_list (const struct ifconfig_pool
* pool
, struct status_output
*out
)
317 struct gc_arena gc
= gc_new ();
320 for (i
= 0; i
< pool
->size
; ++i
)
322 const struct ifconfig_pool_entry
*e
= &pool
->list
[i
];
325 const in_addr_t ip
= ifconfig_pool_handle_to_ip_base (pool
, i
);
326 status_printf (out
, "%s,%s",
328 print_in_addr_t (ip
, 0, &gc
));
336 ifconfig_pool_msg (const struct ifconfig_pool
* pool
, int msglevel
)
338 struct status_output
*so
= status_open (NULL
, 0, msglevel
, NULL
, 0);
340 status_printf (so
, "IFCONFIG POOL LIST");
341 ifconfig_pool_list (pool
, so
);
346 * Deal with reading/writing the ifconfig pool database to a file
349 struct ifconfig_pool_persist
*
350 ifconfig_pool_persist_init (const char *filename
, int refresh_freq
)
352 struct ifconfig_pool_persist
*ret
;
356 ALLOC_OBJ_CLEAR (ret
, struct ifconfig_pool_persist
);
357 if (refresh_freq
> 0)
360 ret
->file
= status_open (filename
, refresh_freq
, -1, NULL
, STATUS_OUTPUT_READ
|STATUS_OUTPUT_WRITE
);
365 ret
->file
= status_open (filename
, 0, -1, NULL
, STATUS_OUTPUT_READ
);
371 ifconfig_pool_persist_close (struct ifconfig_pool_persist
*persist
)
376 status_close (persist
->file
);
382 ifconfig_pool_write_trigger (struct ifconfig_pool_persist
*persist
)
385 return status_trigger (persist
->file
);
391 ifconfig_pool_read (struct ifconfig_pool_persist
*persist
, struct ifconfig_pool
*pool
)
393 const int buf_size
= 128;
396 if (persist
&& persist
->file
&& pool
)
398 struct gc_arena gc
= gc_new ();
399 struct buffer in
= alloc_buf_gc (256, &gc
);
404 ALLOC_ARRAY_CLEAR_GC (cn_buf
, char, buf_size
, &gc
);
405 ALLOC_ARRAY_CLEAR_GC (ip_buf
, char, buf_size
, &gc
);
409 ASSERT (buf_init (&in
, 0));
410 if (!status_read (persist
->file
, &in
))
416 if (c
== '#' || c
== ';')
418 if (buf_parse (&in
, ',', cn_buf
, buf_size
)
419 && buf_parse (&in
, ',', ip_buf
, buf_size
))
422 const in_addr_t addr
= getaddr (GETADDR_HOST_ORDER
, ip_buf
, 0, &succeeded
, NULL
);
425 ifconfig_pool_set (pool
, cn_buf
, addr
, persist
->fixed
);
431 ifconfig_pool_msg (pool
, D_IFCONFIG_POOL
);
438 ifconfig_pool_write (struct ifconfig_pool_persist
*persist
, const struct ifconfig_pool
*pool
)
440 if (persist
&& persist
->file
&& (status_rw_flags (persist
->file
) & STATUS_OUTPUT_WRITE
) && pool
)
442 status_reset (persist
->file
);
443 ifconfig_pool_list (pool
, persist
->file
);
444 status_flush (persist
->file
);
452 #ifdef IFCONFIG_POOL_TEST
457 ifconfig_pool_test (in_addr_t start
, in_addr_t end
)
459 struct gc_arena gc
= gc_new ();
460 struct ifconfig_pool
*p
= ifconfig_pool_init (IFCONFIG_POOL_30NET
, start
, end
);
461 /*struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_INDIV, start, end);*/
462 ifconfig_pool_handle array
[256];
467 msg (M_INFO
| M_NOPREFIX
, "************ 1");
468 for (i
= 0; i
< (int) SIZE (array
); ++i
)
471 ifconfig_pool_handle h
;
472 in_addr_t local
, remote
;
474 openvpn_snprintf (buf
, sizeof(buf
), "common-name-%d", i
);
480 h
= ifconfig_pool_acquire (p
, &local
, &remote
, cn
);
483 msg (M_INFO
| M_NOPREFIX
, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s",
484 print_in_addr_t (local
, 0, &gc
),
485 print_in_addr_t (remote
, 0, &gc
),
491 msg (M_INFO
| M_NOPREFIX
, "************* 2");
492 for (i
= (int) SIZE (array
) / 16; i
< (int) SIZE (array
) / 8; ++i
)
494 msg (M_INFO
, "Attempt to release %d cn=%s", array
[i
], p
->list
[i
].common_name
);
495 if (!ifconfig_pool_release (p
, array
[i
]))
497 msg (M_INFO
, "Succeeded");
502 msg (M_INFO
| M_NOPREFIX
, "**************** 3");
503 for (i
= 0; i
< (int) SIZE (array
); ++i
)
506 ifconfig_pool_handle h
;
507 in_addr_t local
, remote
;
509 snprintf (buf
, sizeof(buf
), "common-name-%d", i
+24);
515 h
= ifconfig_pool_acquire (p
, &local
, &remote
, cn
);
518 msg (M_INFO
| M_NOPREFIX
, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s",
519 print_in_addr_t (local
, 0, &gc
),
520 print_in_addr_t (remote
, 0, &gc
),
526 ifconfig_pool_free (p
);