a023f9819a17540b0b2cd508d9764e93378cdc10
[debian/dhcpd-pools.git] / src / analyze.c
1 /* http://dhcpd-pools.sourceforge.net/
2 ** Copyright 2006- Sami Kerola <kerolasa@iki.fi>
3 **
4 ** This program is free software: you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation, either version 3 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU General Public License for more details.
13 **
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stddef.h>
19 #include <stdlib.h>
20
21 #include "dhcpd-pools.h"
22
23 /* Clean up data */
24 int prepare_data(void)
25 {
26         unsigned long int i, j, k;
27
28         /* Sort leases */
29         qsort(leases, (size_t) num_leases, sizeof(long int), &intcomp);
30
31         /* Get rid of lease dublicates */
32         for (k = j = i = 0; i < num_leases; i++) {
33                 if (j != leases[i]) {
34                         leases[k] = leases[i];
35                         j = leases[i];
36                         k++;
37                 }
38         }
39         num_leases = k;
40
41         /* Delete touched IPs that are in use. */
42         j = 0;
43         for (i = 0; i < num_touches; i++) {
44                 if (bsearch
45                     (&touches[i], leases, (size_t) num_leases,
46                      sizeof(long int), &intcomp) == NULL) {
47                         touches[j] = touches[i];
48                         j++;
49                 }
50         }
51         num_touches = j;
52         qsort(touches, (size_t) num_touches, sizeof(long int), &intcomp);
53
54         /* Sort ranges */
55         qsort(ranges, (size_t) num_ranges, sizeof(struct range_t),
56               &rangecomp);
57
58         /* Sort backups */
59         if (0 < num_backups) {
60                 qsort(backups, (size_t) num_backups, sizeof(long int),
61                       &intcomp);
62         }
63
64         return 0;
65 }
66
67 /* Join leases and ranges into couter structs */
68 int do_counting(void)
69 {
70         struct range_t *range_p;
71         unsigned int i, j, k, m, block_size;
72
73         i = j = m = 0;
74         range_p = ranges;
75
76         /* Walk through ranges */
77         for (k = 0; k < num_ranges; k++) {
78                 /* Count IPs in use */
79                 for (; leases[i] < range_p->last_ip
80                      && (unsigned long) i < num_leases; i++) {
81                         if (leases[i] < range_p->first_ip) {
82                                 continue;
83                         }
84                         /* IP with in range */
85                         range_p->count++;
86                         if (range_p->shared_net) {
87                                 range_p->shared_net->used++;
88                         }
89                 }
90
91                 /* Count touched IPs */
92                 for (; touches[j] < range_p->last_ip
93                      && (unsigned long) j < num_touches; j++) {
94                         if (touches[j] < range_p->first_ip) {
95                                 continue;
96                         }
97                         /* IP with in range */
98                         range_p->touched++;
99                         if (range_p->shared_net) {
100                                 range_p->shared_net->touched++;
101                         }
102                 }
103
104                 /* Count backup IPs */
105                 if (0 < num_backups) {
106                         for (; backups[m] < range_p->last_ip
107                              && (unsigned long) m < num_touches; m++) {
108                                 if (touches[m] < range_p->first_ip) {
109                                         continue;
110                                 }
111                                 /* IP with in range */
112                                 range_p->backups++;
113                                 if (range_p->shared_net) {
114                                         range_p->shared_net->backups++;
115                                 }
116                         }
117                 }
118
119                 /* Size of range, shared net & all networks */
120                 block_size =
121                     (unsigned int) (range_p->last_ip - range_p->first_ip -
122                                     1);
123                 if (range_p->shared_net) {
124                         range_p->shared_net->available += block_size;
125                 }
126
127                 /* Go backwards one step so that not even a one IP will be
128                  * missed. This is possibly always unnecessary. */
129                 if (i) {
130                         i--;
131                 }
132                 if (j) {
133                         j--;
134                 }
135
136                 range_p++;
137         }
138
139         /* FIXME: During count of other shared networks default network and
140          * all networks got mixed to gether semantically. This fixes the
141          * problem, but is not elegant. */
142         shared_networks->available = 0;
143         shared_networks->used = 0;
144         shared_networks->touched = 0;
145         range_p = ranges;
146         for (k = 0; k < num_ranges; k++) {
147                 shared_networks->available +=
148                     range_p->last_ip - range_p->first_ip - 1;
149                 shared_networks->used += range_p->count;
150                 shared_networks->touched += range_p->touched;
151                 shared_networks->backups += range_p->backups;
152                 range_p++;
153         }
154
155         return 0;
156 }