Import from release candidate 2.13.
[debian/dhcpd-pools.git] / src / dhcpd-pools.c
1 /*
2 ** Copyright (C) 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 2 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, write to the Free Software 
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef  HAVE_STDLIB_H
28 #include <stdlib.h>
29 #else                           /* Not STDC_HEADERS */
30 extern void exit();
31 extern char *malloc();
32 #endif                          /* STDC_HEADERS */
33 #ifdef  HAVE_STRING_H
34 #include <string.h>
35 #else
36 #include <strings.h>
37 #endif
38 #include <getopt.h>
39
40 #include "dhcpd-pools.h"
41 #include "defaults.h"
42
43 int main(int argc, char **argv)
44 {
45         int c, sorts = 0;
46         int option_index = 0;
47         char *tmp;
48         struct range_t *tmp_ranges;
49
50         /* Options for getopt_long */
51         static struct option const long_options[] = {
52                 {"config", required_argument, 0, (int) 'c'},
53                 {"leases", required_argument, 0, (int) 'l'},
54                 {"format", required_argument, 0, (int) 'f'},
55                 {"sort", required_argument, 0, (int) 's'},
56                 {"reverse", no_argument, 0, (int) 'r'},
57                 {"output", required_argument, 0, (int) 'o'},
58                 {"limit", required_argument, 0, (int) 'L'},
59                 {"version", no_argument, 0, (int) 'v'},
60                 {"help", no_argument, 0, (int) 'h'},
61                 {0, 0, 0, 0}
62         };
63
64         program_name = argv[0];
65         atexit(clean_up);
66
67         /* TODO: make either dynamic or find out max path lenght that auto config
68          * provides */
69         config.dhcpdconf_file = safe_malloc(sizeof(char) * MAXLEN);
70         config.dhcpdlease_file = safe_malloc(sizeof(char) * MAXLEN);
71         config.output_file = safe_malloc(sizeof(char) * MAXLEN);
72
73         /* Make sure string has zero lenght if there is no command line
74          * option */
75         config.output_file[0] = '\0';
76
77         /* File location defaults */
78         strncpy(config.dhcpdconf_file, DHCPDCONF_FILE,
79                 (size_t) MAXLEN - 1);
80         strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE,
81                 (size_t) MAXLEN - 1);
82         tmp = OUTPUT_LIMIT;
83         config.output_limit[0] = (int) (*tmp - '0');
84         tmp++;
85         config.output_limit[1] = (int) (*tmp - '0');
86         fullhtml = false;
87
88         /* Make sure some output format is selected by default */
89         strncpy(config.output_format, OUTPUT_FORMAT, (size_t) 1);
90
91         /* Default sort order is by IPs small to big */
92         config.reverse_order = false;
93
94         /* Parse command line options */
95         while (1) {
96                 c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh",
97                                 long_options, &option_index);
98
99                 if (c == EOF)
100                         break;
101
102                 switch (c) {
103                 case 0:
104                         break;
105                 case 'c':
106                         /* config file */
107                         if (optarg != NULL) {
108                                 strncpy(config.dhcpdconf_file, optarg,
109                                         (size_t) MAXLEN - 1);
110                         } else {
111                                 eprintf
112                                     ("main: for argument configuration file parameter not set");
113                                 usage(EXIT_FAILURE);
114                         }
115                         break;
116                 case 'l':
117                         /* lease file */
118                         if (optarg != NULL) {
119                                 strncpy(config.dhcpdlease_file, optarg,
120                                         (size_t) MAXLEN - 1);
121                         } else {
122                                 eprintf
123                                     ("main: for argument lease file parameter not set");
124                                 usage(EXIT_FAILURE);
125                         }
126                         break;
127                 case 'f':
128                         /* Output format */
129                         if (optarg != NULL) {
130                                 strncpy(config.output_format, optarg,
131                                         (size_t) 1);
132                         } else {
133                                 eprintf
134                                     ("main: for argument output format parameter not set");
135                                 usage(EXIT_FAILURE);
136                         }
137                         break;
138                 case 's':
139                         /* Output sorting option */
140                         if (optarg != NULL) {
141                                 sorts = strlen(optarg);
142                                 if (sorts > 5) {
143                                         eprintf
144                                             ("main: only 5 first sort orders will be used");
145                                         strncpy(config.sort, optarg,
146                                                 (size_t) 5);
147                                         sorts = 5;
148                                 } else {
149                                         strncpy(config.sort, optarg,
150                                                 (size_t) sorts);
151                                 }
152                         } else {
153                                 eprintf
154                                     ("main: for argument sort order parameter not set");
155                                 usage(EXIT_FAILURE);
156                         }
157                         break;
158                 case 'r':
159                         /* What ever sort in reverse order */
160                         config.reverse_order = true;
161                         break;
162                 case 'o':
163                         /* Output file */
164                         if (optarg != NULL) {
165                                 strncpy(config.output_file, optarg,
166                                         (size_t) MAXLEN - 1);
167                         } else {
168                                 eprintf
169                                     ("main: for argument output file parameter not set");
170                                 usage(EXIT_FAILURE);
171                         }
172                         break;
173                 case 'L':
174                         /* Specification what will be printed */
175                         if (optarg != NULL) {
176                                 if (optarg[0] >= '0' && optarg[0] < '8') {
177                                         config.output_limit[0] =
178                                             (int) optarg[0] - '0';
179                                 } else {
180                                         eprintf
181                                             ("main: output mask %s illegal",
182                                              argv[optind]);
183                                         usage(EXIT_FAILURE);
184                                 }
185                                 if (optarg[1] >= '0' && optarg[1] < '8') {
186                                         config.output_limit[1] =
187                                             (int) optarg[1] - '0';
188                                 } else {
189                                         eprintf
190                                             ("main: output mask %s illegal",
191                                              optarg);
192                                         usage(EXIT_FAILURE);
193                                 }
194                         } else {
195                                 eprintf
196                                     ("main: for argument output mask parameter not set");
197                                 usage(EXIT_FAILURE);
198                         }
199                         break;
200                 case 'v':
201                         /* Print version */
202                         print_version();
203                         exit(EXIT_SUCCESS);
204                 case 'h':
205                         /* Print help */
206                         usage(EXIT_SUCCESS);
207                 default:
208                         usage(EXIT_FAILURE);
209                 }
210         }
211
212         /* Output function selection */
213         switch (config.output_format[0]) {
214         case 't':
215                 output_analysis = output_txt;
216                 break;
217         case 'h':
218                 output_analysis = output_html;
219                 break;
220         case 'H':
221                 output_analysis = output_html;
222                 fullhtml = true;
223                 break;
224         case 'x':
225                 output_analysis = output_xml;
226                 break;
227         case 'X':
228                 output_analysis = output_xml;
229                 break;
230         case 'c':
231                 output_analysis = output_csv;
232                 break;
233         case 's':
234                 /* output_analysis = output_snmp; */
235                 output_analysis = output_txt;
236                 break;
237         default:
238                 eprintf("main: unknown ouput format");
239                 usage(EXIT_FAILURE);
240         }
241
242         /* Do the job */
243         prepare_memory();
244         parse_config(true, config.dhcpdconf_file, shared_net_names,
245                      shared_net_names + strlen(shared_net_names) + 1,
246                      shared_networks);
247
248         if ((config.output_format[0] == 'x')
249             || (config.output_format[0] == 'X')) {
250                 printf("<dhcpstatus>\n");
251         };
252
253         parse_leases();
254         prepare_data();
255         do_counting();
256         tmp_ranges = safe_malloc(sizeof(struct range_t) * num_ranges);
257         if (sorts != 0) {
258                 mergesort_ranges(ranges, num_ranges, tmp_ranges);
259         }
260         if (config.reverse_order == true) {
261                 flip_ranges(ranges, tmp_ranges);
262         }
263         free(tmp_ranges);
264         output_analysis();
265
266         if ((config.output_format[0] == 'x')
267             || (config.output_format[0] == 'X')) {
268                 printf("</dhcpstatus>\n");
269         };
270
271         exit(EXIT_SUCCESS);
272 }
273
274 /* Global allocations, counter resets etc */
275 int prepare_memory()
276 {
277         num_ranges = num_shared_networks = 0;
278         shared_networks =
279             safe_malloc(sizeof(struct shared_network_t) * SHARED_NETWORKS);
280         shared_net_names =
281             safe_malloc(sizeof(char) * SHARED_NETWORKS_NAMES);
282
283         ranges = safe_malloc(sizeof(struct range_t) * RANGES);
284
285         /* First shared network entry is all networks */
286         strcpy(shared_net_names, "All networks");
287         return 0;
288 }