licensing: use FreeBSD license (was GNUv3)
[debian/dhcpd-pools.git] / src / dhcpd-pools.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 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <stdio.h>
41 #ifdef  HAVE_STDLIB_H
42 #include <stdlib.h>
43 #else                           /* Not STDC_HEADERS */
44 extern char *malloc();
45 #endif                          /* STDC_HEADERS */
46 #ifdef  HAVE_STRING_H
47 #include <string.h>
48 #else
49 #include <strings.h>
50 #endif
51 #include <err.h>
52 #include <errno.h>
53 #include <getopt.h>
54
55 #include "defaults.h"
56 #include "dhcpd-pools.h"
57
58 int main(int argc, char **argv)
59 {
60         int i, c, sorts = 0;
61         int option_index = 0;
62         char *tmp;
63         struct range_t *tmp_ranges;
64
65         /* Options for getopt_long */
66         static struct option const long_options[] = {
67                 {"config", required_argument, 0, (int) 'c'},
68                 {"leases", required_argument, 0, (int) 'l'},
69                 {"format", required_argument, 0, (int) 'f'},
70                 {"sort", required_argument, 0, (int) 's'},
71                 {"reverse", no_argument, 0, (int) 'r'},
72                 {"output", required_argument, 0, (int) 'o'},
73                 {"limit", required_argument, 0, (int) 'L'},
74                 {"version", no_argument, 0, (int) 'v'},
75                 {"help", no_argument, 0, (int) 'h'},
76                 {0, 0, 0, 0}
77         };
78
79         /* FIXME: make these allocations dynamic up on need. */
80         config.dhcpdconf_file = safe_malloc(sizeof(char) * MAXLEN);
81         config.dhcpdlease_file = safe_malloc(sizeof(char) * MAXLEN);
82         config.output_file = safe_malloc(sizeof(char) * MAXLEN);
83
84         /* Make sure string has zero lenght if there is no
85          * command line option */
86         config.output_file[0] = '\0';
87
88         /* File location defaults */
89         strncpy(config.dhcpdconf_file, DHCPDCONF_FILE,
90                 (size_t) MAXLEN - 1);
91         strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE,
92                 (size_t) MAXLEN - 1);
93         tmp = OUTPUT_LIMIT;
94         config.output_limit[0] = (int) (*tmp - '0');
95         tmp++;
96         config.output_limit[1] = (int) (*tmp - '0');
97         fullhtml = false;
98
99         /* Make sure some output format is selected by default */
100         strncpy(config.output_format, OUTPUT_FORMAT, (size_t) 1);
101
102         /* Default sort order is by IPs small to big */
103         config.reverse_order = false;
104
105         /* Parse command line options */
106         while (1) {
107                 c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh",
108                                 long_options, &option_index);
109
110                 if (c == EOF)
111                         break;
112
113                 switch (c) {
114                 case 'c':
115                         /* config file */
116                         strncpy(config.dhcpdconf_file, optarg,
117                                 (size_t) MAXLEN - 1);
118                         break;
119                 case 'l':
120                         /* lease file */
121                         strncpy(config.dhcpdlease_file, optarg,
122                                 (size_t) MAXLEN - 1);
123                         break;
124                 case 'f':
125                         /* Output format */
126                         strncpy(config.output_format, optarg, (size_t) 1);
127                         break;
128                 case 's':
129                         /* Output sorting option */
130                         sorts = strlen(optarg);
131                         if (5 < sorts) {
132                                 warnx
133                                     ("main: only first 5 sort orders will be used");
134                                 strncpy(config.sort, optarg, (size_t) 5);
135                                 sorts = 5;
136                         } else {
137                                 strncpy(config.sort, optarg,
138                                         (size_t) sorts);
139                         }
140                         for (i = 0; i < sorts; i++) {
141                                 field_selector(config.sort[i]);
142                         }
143                         break;
144                 case 'r':
145                         /* What ever sort in reverse order */
146                         config.reverse_order = true;
147                         break;
148                 case 'o':
149                         /* Output file */
150                         strncpy(config.output_file, optarg,
151                                 (size_t) MAXLEN - 1);
152                         break;
153                 case 'L':
154                         /* Specification what will be printed */
155                         for (i = 0; i < 2; i++) {
156                                 if (optarg[i] >= '0' && optarg[i] < '8') {
157                                         config.output_limit[i] =
158                                             (int) optarg[i] - '0';
159                                 } else {
160                                         errx(EXIT_FAILURE,
161                                              "main: output mask `%s' is illegal",
162                                              optarg);
163                                 }
164                         }
165                         break;
166                 case 'v':
167                         /* Print version */
168                         print_version();
169                 case 'h':
170                         /* Print help */
171                         usage(EXIT_SUCCESS);
172                 default:
173                         errx(EXIT_FAILURE,
174                              "Try `%s --help' for more information.",
175                              program_invocation_short_name);
176                 }
177         }
178
179         /* Output function selection */
180         switch (config.output_format[0]) {
181         case 't':
182                 output_analysis = output_txt;
183                 break;
184         case 'h':
185                 output_analysis = output_html;
186                 break;
187         case 'H':
188                 output_analysis = output_html;
189                 fullhtml = true;
190                 break;
191         case 'x':
192                 output_analysis = output_xml;
193                 break;
194         case 'X':
195                 output_analysis = output_xml;
196                 break;
197         case 'c':
198                 output_analysis = output_csv;
199                 break;
200         default:
201                 errx(EXIT_FAILURE, "main: unknown output format `%c'",
202                      config.output_format[0]);
203         }
204
205         /* Do the job */
206         prepare_memory();
207         parse_config(true, config.dhcpdconf_file, shared_networks);
208
209         parse_leases();
210         prepare_data();
211         do_counting();
212         tmp_ranges = safe_malloc(sizeof(struct range_t) * num_ranges);
213         if (sorts != 0) {
214                 mergesort_ranges(ranges, num_ranges, tmp_ranges);
215         }
216         if (config.reverse_order == true) {
217                 flip_ranges(ranges, tmp_ranges);
218         }
219         free(tmp_ranges);
220         output_analysis();
221
222         clean_up();
223         return (EXIT_SUCCESS);
224 }
225
226 /* Global allocations, counter resets etc */
227 int prepare_memory()
228 {
229         RANGES = 64;
230         num_ranges = num_shared_networks = 0;
231         shared_networks =
232             safe_malloc(sizeof(struct shared_network_t) * SHARED_NETWORKS);
233
234         ranges = safe_malloc(sizeof(struct range_t) * RANGES);
235         macaddr = NULL;
236
237         /* First shared network entry is all networks */
238         shared_networks->name = safe_strdup("All networks");
239         shared_networks->used = 0;
240         shared_networks->touched = 0;
241         shared_networks->backups = 0;
242
243         return 0;
244 }