licensing: use FreeBSD license (was GNUv3)
[debian/dhcpd-pools.git] / src / analyze.c
1 /*
2  * The dhcpd-pools has BSD 2-clause license which also known as "Simplified
3  * BSD License" or "FreeBSD License".
4  *
5  * Copyright 2006- Sami Kerola. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  *    1. Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *
14  *    2. Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in the
16  *       documentation and/or other materials provided with the
17  *       distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29  * THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * The views and conclusions contained in the software and documentation are
32  * those of the authors and should not be interpreted as representing
33  * official policies, either expressed or implied, of Sami Kerola.
34  */
35
36 #include <stddef.h>
37 #include <stdlib.h>
38
39 #include "dhcpd-pools.h"
40
41 /* Clean up data */
42 int prepare_data(void)
43 {
44         unsigned long int i, j, k;
45
46         /* Sort leases */
47         qsort(leases, (size_t) num_leases, sizeof(long int), &intcomp);
48
49         /* Get rid of lease dublicates */
50         for (k = j = i = 0; i < num_leases; i++) {
51                 if (j != leases[i]) {
52                         leases[k] = leases[i];
53                         j = leases[i];
54                         k++;
55                 }
56         }
57         num_leases = k;
58
59         /* Delete touched IPs that are in use. */
60         j = 0;
61         for (i = 0; i < num_touches; i++) {
62                 if (bsearch
63                     (&touches[i], leases, (size_t) num_leases,
64                      sizeof(long int), &intcomp) == NULL) {
65                         touches[j] = touches[i];
66                         j++;
67                 }
68         }
69         num_touches = j;
70         qsort(touches, (size_t) num_touches, sizeof(long int), &intcomp);
71
72         /* Sort ranges */
73         qsort(ranges, (size_t) num_ranges, sizeof(struct range_t),
74               &rangecomp);
75
76         /* Sort backups */
77         if (0 < num_backups) {
78                 qsort(backups, (size_t) num_backups, sizeof(long int),
79                       &intcomp);
80         }
81
82         return 0;
83 }
84
85 /* Join leases and ranges into couter structs */
86 int do_counting(void)
87 {
88         struct range_t *range_p;
89         unsigned int i, j, k, m, block_size;
90
91         i = j = m = 0;
92         range_p = ranges;
93
94         /* Walk through ranges */
95         for (k = 0; k < num_ranges; k++) {
96                 /* Count IPs in use */
97                 for (; leases[i] < range_p->last_ip
98                      && (unsigned long) i < num_leases; i++) {
99                         if (leases[i] < range_p->first_ip) {
100                                 continue;
101                         }
102                         /* IP with in range */
103                         range_p->count++;
104                         if (range_p->shared_net) {
105                                 range_p->shared_net->used++;
106                         }
107                 }
108
109                 /* Count touched IPs */
110                 for (; touches[j] < range_p->last_ip
111                      && (unsigned long) j < num_touches; j++) {
112                         if (touches[j] < range_p->first_ip) {
113                                 continue;
114                         }
115                         /* IP with in range */
116                         range_p->touched++;
117                         if (range_p->shared_net) {
118                                 range_p->shared_net->touched++;
119                         }
120                 }
121
122                 /* Count backup IPs */
123                 if (0 < num_backups) {
124                         for (; backups[m] < range_p->last_ip
125                              && (unsigned long) m < num_touches; m++) {
126                                 if (touches[m] < range_p->first_ip) {
127                                         continue;
128                                 }
129                                 /* IP with in range */
130                                 range_p->backups++;
131                                 if (range_p->shared_net) {
132                                         range_p->shared_net->backups++;
133                                 }
134                         }
135                 }
136
137                 /* Size of range, shared net & all networks */
138                 block_size =
139                     (unsigned int) (range_p->last_ip - range_p->first_ip -
140                                     1);
141                 if (range_p->shared_net) {
142                         range_p->shared_net->available += block_size;
143                 }
144
145                 /* Go backwards one step so that not even a one IP will be
146                  * missed. This is possibly always unnecessary. */
147                 if (i) {
148                         i--;
149                 }
150                 if (j) {
151                         j--;
152                 }
153
154                 range_p++;
155         }
156
157         /* FIXME: During count of other shared networks default network and
158          * all networks got mixed to gether semantically. This fixes the
159          * problem, but is not elegant. */
160         shared_networks->available = 0;
161         shared_networks->used = 0;
162         shared_networks->touched = 0;
163         range_p = ranges;
164         for (k = 0; k < num_ranges; k++) {
165                 shared_networks->available +=
166                     range_p->last_ip - range_p->first_ip - 1;
167                 shared_networks->used += range_p->count;
168                 shared_networks->touched += range_p->touched;
169                 shared_networks->backups += range_p->backups;
170                 range_p++;
171         }
172
173         return 0;
174 }