output: add json format support

Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
This commit is contained in:
Gilles Bouthenot 2012-12-04 17:17:14 +01:00 committed by Sami Kerola
parent 179e2ac147
commit a302bc6829
7 changed files with 156 additions and 5 deletions

1
THANKS
View file

@ -24,3 +24,4 @@ Robert Viou
Enno Gröper
Ryan Malek
Cheer Xiao
Gilles Bouthenot

View file

@ -62,7 +62,7 @@ are equal next one is used. The IP field is default sort key.
\fB\-r\fR, \fB\-\-reverse\fR
Sort results in reverse order.
.TP
\fB\-f\fR, \fB\-\-format\fR=\fI[thHcxX]\fR
\fB\-f\fR, \fB\-\-format\fR=\fI[thHcxXjJ]\fR
Output format.
Text
.RI ( t ).
@ -77,7 +77,11 @@ stands for comma-separated values. Output format xml
.RI ( x )
is similar to the dhcpstatus Perl module output. The extended xml
.RI ( X )
format will print ethernet address details.
format will print ethernet address details. The
.RI ( j )
will output in json format, which can be extended with
.RI ( J )
to include ethernet address.
.IP
The default format is
.IR @OUTPUT_FORMAT@ .

View file

@ -207,6 +207,12 @@ int main(int argc, char **argv)
case 'X':
output_analysis = output_xml;
break;
case 'j':
output_analysis = output_json;
break;
case 'J':
output_analysis = output_json;
break;
case 'c':
output_analysis = output_csv;
break;

View file

@ -194,6 +194,7 @@ int (*output_analysis) (void);
int output_txt(void);
int output_html(void);
int output_xml(void);
int output_json(void);
int output_csv(void);
int output_alarming(void);
/* Memory release, file closing etc */

View file

@ -119,7 +119,7 @@ int parse_leases(void)
line = xmalloc(sizeof(char) * MAXLEN);
ipstring = xmalloc(sizeof(char) * MAXLEN);
if (config.output_format[0] == 'X') {
if (config.output_format[0] == 'X' || config.output_format[0] == 'J') {
macstring = xmalloc(sizeof(char) * 18);
macaddr = xmalloc(sizeof(struct macaddr_t));
macaddr_p = macaddr;

View file

@ -219,13 +219,16 @@ This is ISC dhcpd pools usage analyzer.\n\
\n", program_invocation_short_name);
fprintf(out, "\
-c, --config=FILE path to the dhcpd.conf file\n\
-l, --leases=FILE path to the dhcpd.leases file\n\
-f, --format=[thHcxX] output format\n\
-l, --leases=FILE path to the dhcpd.leases file\n");
fprintf(out, "\
-f, --format=[thHcxXjJ] output format\n\
t for text\n\
h for html table\n\
H for full html page\n\
x for xml\n\
X for xml with active lease details\n\
j for json\n\
J for json with active lease details\n\
c for comma separated values\n");
fprintf(out, "\
-s, --sort=[nimcptTe] sort ranges by\n\

View file

@ -322,6 +322,142 @@ int output_xml(void)
return 0;
}
int output_json(void)
{
unsigned int i;
struct range_t *range_p;
unsigned long range_size;
struct shared_network_t *shared_p;
struct macaddr_t *macaddr_p;
int ret;
FILE *outfile;
char sep;
if (config.output_file[0]) {
outfile = fopen(config.output_file, "w+");
if (outfile == NULL) {
err(EXIT_FAILURE, "output_json: %s",
config.output_file);
}
} else {
outfile = stdout;
}
range_p = ranges;
range_size = get_range_size(range_p);
shared_p = shared_networks;
sep = ' ';
fprintf(outfile, "{\n");
if (macaddr != NULL) {
fprintf(outfile, " %c\"active_leases\": [\n", sep);
for (i = 0, macaddr_p = macaddr; macaddr_p->next != NULL;
macaddr_p = macaddr_p->next) {
if (0 != i) {
fprintf(outfile, ",\n ");
} else {
fprintf(outfile, "\n ");
}
fprintf(outfile,
"{ \"ip\":\"%s\", \"macaddress\":\"%s\" }",
macaddr_p->ip, macaddr_p->ethernet);
i++;
}
fprintf(outfile, "\n ]"); /* end of active_leases */
sep = ',';
}
if (config.output_limit[1] & output_limit_bit_1) {
if (sep == ',')
printf(",\n");
fprintf(outfile, " \"subnets\": [\n");
for (i = 0; i < num_ranges; i++) {
fprintf(outfile, " ");
fprintf(outfile, "{ ");
if (range_p->shared_net) {
fprintf(outfile,
"\"location\":\"%s\", ",
range_p->shared_net->name);
} else {
fprintf(outfile, "\"location\":\"\", ");
}
fprintf(outfile, "\"network\":\"\", ");
fprintf(outfile, "\"netmask\":\"\", ");
fprintf(outfile, "\"range\":\"%s\", ",
ntop_ipaddr(&range_p->first_ip));
fprintf(outfile, "\"gateway\":\"\", ");
fprintf(outfile, "\"defined\":%lu, ", range_size);
fprintf(outfile, "\"used\":%lu, ", range_p->count);
fprintf(outfile, "\"free\":%lu ",
range_size - range_p->count);
range_p++;
range_size = get_range_size(range_p);
if (i + 1 < num_ranges)
fprintf(outfile, "},\n");
else
fprintf(outfile, "}\n");
}
fprintf(outfile, " ]"); /* end of subnets */
sep = ',';
}
if (config.output_limit[1] & output_limit_bit_2) {
if (sep == ',')
printf(",\n");
fprintf(outfile, " \"shared-networks\": [\n");
for (i = 0; i < num_shared_networks; i++) {
fprintf(outfile, " ");
shared_p++;
fprintf(outfile, "{ ");
fprintf(outfile, "\"location\":\"%s\", ",
shared_p->name);
fprintf(outfile, "\"defined\":%lu, ",
shared_p->available);
fprintf(outfile, "\"used\":%lu, ", shared_p->used);
fprintf(outfile, "\"free\":%lu ",
shared_p->available - shared_p->used);
if (i + 1 < num_shared_networks)
fprintf(outfile, "},\n");
else
fprintf(outfile, "}\n");
}
fprintf(outfile, " ]"); /* end of shared-networks */
sep = ',';
}
if (config.output_limit[0] & output_limit_bit_3) {
if (sep == ',')
printf(",\n");
fprintf(outfile, " \"summary\": {\n");
fprintf(outfile, " \"location\":\"%s\",\n",
shared_networks->name);
fprintf(outfile, " \"defined\":%lu,\n",
shared_networks->available);
fprintf(outfile, " \"used\":%lu,\n",
shared_networks->used);
fprintf(outfile, " \"free\":%lu\n",
shared_networks->available - shared_networks->used);
fprintf(outfile, " }"); /* end of summary */
}
fprintf(outfile, "\n}");
if (outfile == stdout) {
ret = fflush(stdout);
if (ret) {
warn("output_json: fflush");
}
} else {
ret = close_stream(outfile);
if (ret) {
warn("output_json: fclose");
}
}
return 0;
}
static void html_header(FILE *restrict f)
{
char outstr[200];