1 /* $Id: reportdef.c 684 2018-11-07 19:26:36Z bhockney $ */
2
3 /* (C) 2004-2018 by Bob Hockney <zeus@ix.netcom.com> *
4 * *
5 * report definition parser for wfwl_syslog *
6 * *
7 * This code is distributed under the terms of GNU GPL */
8
9 #include <errno.h>
10 #include <sys/stat.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <ctype.h>
14 #include <netdb.h>
15 #include <math.h>
16
17 #include <reportdef.h>
18 #include <main.h>
19 #include <utils.h>
20
21 struct sort_order *sort = NULL;
22 struct field_order *fields = NULL;
23 struct selection *selection = NULL;
24 struct fields_used fields_used;
25 struct select_sum select_sum;
26 extern struct options opt;
27
28 unsigned int sort_count = 0;
29 unsigned int column_count = 0;
30 unsigned int selection_count = 0;
31
32 /* This array controls how report definition keys are parsed for sorting, *
33 * criteria, and columns. Fields in the array are *
34 * key: Key string *
35 * sort_key: Sort index *
36 * sel_key: Selection index *
37 * sel_type: Selection type *
38 * aggregate_value: Pointer for selection aggregate value *
39 * field_used: Pointer to fields_used struct for columns *
40 * col_key: Column index *
41 * cache_resolve: Cache constant for host and service columns *
42 * use_geoip: whether source, dest or neither geoip fields needed *
43 * */
44 struct reportdef_keys keys [] = {
45 {"ahesp_spi",SORT_AHESP_SPI,SEL_AHESP_SPI,SEL_NUM,NULL,&fields_used.ahesp_spi,COL_AHESP_SPI,0,0},
46 {"icmptype",SORT_ICMP_TYPE,0,0,NULL,&fields_used.icmp_type,COL_ICMP_TYPE,0,0},
47 {"icmpcode",SORT_ICMP_CODE,0,0,NULL,&fields_used.icmp_code,COL_ICMP_CODE,0,0},
48 {"icmpechoid",SORT_ICMP_ECHOID,0,0,NULL,&fields_used.icmp_echoid,COL_ICMP_ECHOID,0,0},
49 {"icmpechoseq",SORT_ICMP_ECHOSEQ,0,0,NULL,&fields_used.icmp_echoseq,COL_ICMP_ECHOSEQ,0,0},
50 {"icmp_code",0,SEL_ICMP_CODE,SEL_NUM,NULL,NULL,0,0,0},
51 {"icmp_type",0,SEL_ICMP_TYPE,SEL_NUM,NULL,NULL,0,0,0},
52 {"icmp_echoid",0,SEL_ICMP_ECHOID,SEL_NUM,NULL,NULL,0,0,0},
53 {"icmp_echoseq",0,SEL_ICMP_ECHOSEQ,SEL_NUM,NULL,NULL,0,0,0},
54 {"icmpv6_code",0,SEL_ICMPv6_CODE,SEL_NUM,NULL,NULL,0,0,0},
55 {"icmpv6_type",0,SEL_ICMPv6_TYPE,SEL_NUM,NULL,NULL,0,0,0},
56 {"icmpv6_echoid",0,SEL_ICMPv6_ECHOID,SEL_NUM,NULL,NULL,0,0,0},
57 {"icmpv6_echoseq",0,SEL_ICMPv6_ECHOSEQ,SEL_NUM,NULL,NULL,0,0,0},
58 {"icmp_fragmtu",SORT_ICMP_MTU,SEL_ICMP_FRAGMTU,SEL_NUM,NULL,&fields_used.icmp_mtu,COL_ICMP_MTU,0,0},
59 {"icmp_gateway",SORT_ICMP_GW,SEL_ICMP_GATEWAY,SEL_IPADDR,NULL,&fields_used.icmp_gw,COL_ICMP_GATEWAY,0,0},
60 {"ip_csum",SORT_CSUM,SEL_IP_CSUM,SEL_NUM,NULL,&fields_used.csum,COL_IP_CSUM,0,0},
61 {"ip_fragoff",SORT_FRAGOFF,SEL_IP_FRAGOFF,SEL_NUM,NULL,&fields_used.fragoff,COL_IP_FRAGOFF,0,0},
62 {"ip_id",SORT_IP_ID,SEL_IP_ID,SEL_NUM,NULL,&fields_used.ipid,COL_IP_ID,0,0},
63 {"ip_ihl",SORT_IP_IHL,SEL_IP_IHL,SEL_NUM,NULL,&fields_used.ihl,COL_IP_IHL,0,0},
64 {"ip_protocol",SORT_PROTOCOL,SEL_PROTOCOL,SEL_PROTO,NULL,&fields_used.protocol,COL_IP_PROTO,0,0},
65 {"ip_daddr",SORT_DESTHOST,SEL_DESTHOST,SEL_IPADDR,NULL,&fields_used.dhost,COL_DESTHOST,0,0},
66 {"ip_saddr",SORT_SOURCEHOST,SEL_SOURCEHOST,SEL_IPADDR,NULL,&fields_used.shost,COL_SOURCEHOST,0,0},
67 {"ip_tos",SORT_IP_TOS,SEL_IP_TOS,SEL_NUM,NULL,&fields_used.tos,COL_IP_TOS,0,0},
68 {"ip_totlen",SORT_IP_TOTLEN,SEL_IP_TOTLEN,SEL_NUM,NULL,&fields_used.totlen,COL_IP_LEN,0,0},
69 {"ip_ttl",SORT_IP_TTL,SEL_IP_TTL,SEL_NUM,NULL,&fields_used.ttl,COL_IP_TTL,0,0},
70 {"ip_df",0,SEL_IP_DF,SEL_DFMF,NULL,NULL,0,0,0},
71 {"ip_mf",0,SEL_IP_MF,SEL_DFMF,NULL,NULL,0,0,0},
72 {"ip6_payloadlen",SORT_IP6_PAY_LEN,SEL_IP6_PAY_LEN,SEL_NUM,NULL,&fields_used.pay_len,COL_IP6_PAY_LEN,0,0},
73 {"ip6_flowlabel",SORT_IP6_FLOWLABEL,SEL_IP6_FLOWLABEL,SEL_NUM,NULL,&fields_used.flowlabel,COL_IP6_FLOWLABEL,0,0},
74 {"dport",SORT_DESTPORT,0,0,NULL,&fields_used.dport,COL_DESTPORT,0,0},
75 {"sport",SORT_SOURCEPORT,0,0,NULL,&fields_used.sport,COL_SOURCEPORT,0,0},
76 {"tcp_dport",0,SEL_TCP_DPORT,SEL_NUM,NULL,NULL,0,0,0},
77 {"tcp_sport",0,SEL_TCP_SPORT,SEL_NUM,NULL,NULL,0,0,0},
78 {"udp_dport",0,SEL_UDP_DPORT,SEL_NUM,NULL,NULL,0,0,0},
79 {"udp_sport",0,SEL_UDP_SPORT,SEL_NUM,NULL,NULL,0,0,0},
80 {"dst_host",0,0,0,NULL,&fields_used.dhost_name,COL_DESTHOST_NAME,CACHE_RESOLVE,0},
81 {"src_host",0,0,0,NULL,&fields_used.shost_name,COL_SOURCEHOST_NAME,CACHE_RESOLVE,0},
82 {"dst_service",0,0,0,NULL,&fields_used.dst_service,COL_DEST_SERVICE,CACHE_RESOLVE,0},
83 {"src_service",0,0,0,NULL,&fields_used.src_service,COL_SOURCE_SERVICE,CACHE_RESOLVE,0},
84 {"tcp_ackseq",SORT_TCP_ACKSEQ,SEL_TCP_ACKSEQ,SEL_NUM,NULL,&fields_used.tcp_ack_seq,COL_TCP_ACKSEQ,0,0},
85 {"tcp_options",SORT_TCP_OPTS,SEL_TCP_OPTS_EXACT,SEL_BOOLEAN,NULL,&fields_used.flags,COL_TCP_OPTIONS,0,0},
86 {"tcp_seq",SORT_TCP_SEQ,SEL_TCP_SEQ,SEL_NUM,NULL,&fields_used.tcp_seq,COL_TCP_SEQ,0,0},
87 {"tcp_urgp",SORT_TCP_URGP,SEL_TCP_URGP,SEL_NUM,NULL,&fields_used.tcp_urgp,COL_TCP_URGP,0,0},
88 {"tcp_window",SORT_TCP_WINDOW,SEL_TCP_WINDOW,SEL_NUM,NULL,&fields_used.tcp_window,COL_TCP_WINDOW,0,0},
89 {"tcp_ack",0,SEL_TCP_ACK,SEL_BOOLEAN,NULL,NULL,0,0,0},
90 {"tcp_fin",0,SEL_TCP_FIN,SEL_BOOLEAN,NULL,NULL,0,0,0},
91 {"tcp_psh",0,SEL_TCP_PSH,SEL_BOOLEAN,NULL,NULL,0,0,0},
92 {"tcp_rst",0,SEL_TCP_RST,SEL_BOOLEAN,NULL,NULL,0,0,0},
93 {"tcp_syn",0,SEL_TCP_SYN,SEL_BOOLEAN,NULL,NULL,0,0,0},
94 {"tcp_urg",0,SEL_TCP_URG,SEL_BOOLEAN,NULL,NULL,0,0,0},
95 {"tcp_flags",0,SEL_TCP_FLAGS,SEL_BOOLEAN,NULL,NULL,0,0,0},
96 {"udp_len",SORT_UDP_LEN,SEL_UDP_LEN,SEL_NUM,NULL,&fields_used.udp_len,COL_UDP_LEN,0,0},
97 {"local_hostname",SORT_LOCAL_HOST,SEL_LOCAL_HOST,SEL_REGEX,NULL,&fields_used.hostname,COL_LOCAL_HOST,0,0},
98 {"oob_in",SORT_IN_IF,SEL_IN_IF,SEL_REGEX,NULL,&fields_used.inif,COL_IN_IF,0,0},
99 {"oob_mark",SORT_FWMARK,SEL_OOB_MARK,SEL_NUM,NULL,&fields_used.fwmark,COL_FWMARK,0,0},
100 {"oob_out",SORT_OUT_IF,SEL_OUT_IF,SEL_REGEX,NULL,&fields_used.outif,COL_OUT_IF,0,0},
101 {"oob_prefix",SORT_PREFIX,SEL_PREFIX,SEL_REGEX,NULL,&fields_used.log_label,COL_LOG_PREFIX,0,0},
102 {"oob_family",SORT_OOB_FAMILY,SEL_OOB_FAMILY,SEL_NUM,NULL,&fields_used.family,COL_OOB_FAMILY,0,0},
103 {"oob_protocol",SORT_OOB_PROTOCOL,SEL_OOB_PROTOCOL,SEL_NUM,NULL,&fields_used.oob_protocol,COL_OOB_PROTOCOL,0,0},
104 {"mac_saddr_str",SORT_MAC_SADDR,SEL_MAC_DADDR,SEL_REGEX,NULL,&fields_used.mac_saddr_str,COL_MAC_SADDR,0,0},
105 {"mac_daddr_str",SORT_MAC_DADDR,SEL_MAC_SADDR,SEL_REGEX,NULL,&fields_used.mac_daddr_str,COL_MAC_DADDR,0,0},
106 {"raw_mac",SORT_MAC,SEL_MAC,SEL_REGEX,NULL,&fields_used.raw_mac,COL_MAC,0,0},
107 {"id",SORT_ID,0,SEL_ID,NULL,NULL,COL_ID,0,0},
108 {"sname",SORT_SNAME,0,0,NULL,&fields_used.sname,COL_SNAME,0,0},
109 {"count",SORT_COUNT,0,0,NULL,&fields_used.count,COL_COUNT,0,0},
110 {"min_count",0,0,SEL_AGG_COUNT,(time_t *)&select_sum.min_count,NULL,0,0,0},
111 {"max_count",0,0,SEL_AGG_COUNT,(time_t *)&select_sum.max_count,NULL,0,0,0},
112 {"local_time",SORT_LOCAL_TIME,0,0,NULL,&fields_used.local_time,COL_LOCAL_TIME,0,0},
113 {"earliest",SORT_START_TIME,0,0,NULL,&fields_used.earliest,COL_START_TIME,0,0},
114 {"latest",SORT_END_TIME,0,0,NULL,&fields_used.latest,COL_END_TIME,0,0},
115 {"min_date",0,SEL_MIN_DATE,SEL_DATE,NULL,NULL,0,0,0},
116 {"max_date",0,SEL_MAX_DATE,SEL_DATE,NULL,NULL,0,0,0},
117 {"min_latest",0,0,SEL_AGG_DATE,&select_sum.min_latest,NULL,0,0,0},
118 {"max_earliest",0,0,SEL_AGG_DATE,&select_sum.max_earliest,NULL,0,0,0},
119 {"continent_code_s",SORT_CONTINENT_CODE_SRC,SEL_CONTINENT_CODE_SRC,SEL_REGEX,NULL,&fields_used.continent_code_s,COL_CONTINENT_CODE_SRC,0,GEOIP_USE_SRC},
120 {"continent_name_s",SORT_CONTINENT_NAME_SRC,SEL_CONTINENT_NAME_SRC,SEL_REGEX,NULL,&fields_used.continent_name_s,COL_CONTINENT_NAME_SRC,0,GEOIP_USE_SRC},
121 {"country_iso_code_s",SORT_COUNTRY_ISO_CODE_SRC,SEL_COUNTRY_ISO_CODE_SRC,SEL_REGEX,NULL,&fields_used.country_iso_code_s,COL_COUNTRY_ISO_CODE_SRC,0,GEOIP_USE_SRC},
122 {"country_name_s",SORT_COUNTRY_NAME_SRC,SEL_COUNTRY_NAME_SRC,SEL_REGEX,NULL,&fields_used.country_name_s,COL_COUNTRY_NAME_SRC,0,GEOIP_USE_SRC},
123 {"subdivision_1_iso_code_s",SORT_SUBDIVISION_1_ISO_CODE_SRC,SEL_SUBDIVISION_1_ISO_CODE_SRC,SEL_REGEX,NULL,&fields_used.subdivision_1_iso_code_s,COL_SUBDIVISION_1_ISO_CODE_SRC,0,GEOIP_USE_SRC},
124 {"subdivision_1_name_s",SORT_SUBDIVISION_1_NAME_SRC,SEL_SUBDIVISION_1_NAME_SRC,SEL_REGEX,NULL,&fields_used.subdivision_1_name_s,COL_SUBDIVISION_1_NAME_SRC,0,GEOIP_USE_SRC},
125 {"subdivision_2_iso_code_s",SORT_SUBDIVISION_2_ISO_CODE_SRC,SEL_SUBDIVISION_2_ISO_CODE_SRC,SEL_REGEX,NULL,&fields_used.subdivision_2_iso_code_s,COL_SUBDIVISION_2_ISO_CODE_SRC,0,GEOIP_USE_SRC},
126 {"subdivision_2_name_s",SORT_SUBDIVISION_2_NAME_SRC,SEL_SUBDIVISION_2_NAME_SRC,SEL_REGEX,NULL,&fields_used.subdivision_2_name_s,COL_SUBDIVISION_2_NAME_SRC,0,GEOIP_USE_SRC},
127 {"city_name_s",SORT_CITY_NAME_SRC,SEL_CITY_NAME_SRC,SEL_REGEX,NULL,&fields_used.city_name_s,COL_CITY_NAME_SRC,0,GEOIP_USE_SRC},
128 {"metro_code_s",SORT_METRO_CODE_SRC,SEL_METRO_CODE_SRC,SEL_NUM,NULL,&fields_used.metro_code_s,COL_METRO_CODE_SRC,0,GEOIP_USE_SRC},
129 {"accuracy_radius_s",SORT_ACCURACY_RADIUS_SRC,SEL_ACCURACY_RADIUS_SRC,SEL_NUM,NULL,&fields_used.accuracy_radius_s,COL_ACCURACY_RADIUS_SRC,0,GEOIP_USE_SRC},
130 {"time_zone_s",SORT_TIME_ZONE_SRC,SEL_TIME_ZONE_SRC,SEL_REGEX,NULL,&fields_used.time_zone_s,COL_TIME_ZONE_SRC,0,GEOIP_USE_SRC},
131 {"registered_country_geoname_id_s",SORT_REGISTERED_COUNTRY_GEONAME_ID_SRC,SEL_REGISTERED_COUNTRY_GEONAME_ID_SRC,SEL_REGEX,NULL,&fields_used.registered_country_geoname_id_s,COL_REGISTERED_COUNTRY_GEONAME_ID_SRC,0,GEOIP_USE_SRC},
132 {"represented_country_geoname_id_s",SORT_REPRESENTED_COUNTRY_GEONAME_ID_SRC,SEL_REPRESENTED_COUNTRY_GEONAME_ID_SRC,SEL_REGEX,NULL,&fields_used.represented_country_geoname_id_s,COL_REPRESENTED_COUNTRY_GEONAME_ID_SRC,0,GEOIP_USE_SRC},
133 {"is_anonymous_proxy_s",SORT_IS_ANONYMOUS_PROXY_SRC,SEL_IS_ANONYMOUS_PROXY_SRC,SEL_BOOLEAN,NULL,&fields_used.is_anonymous_proxy_s,COL_IS_ANONYMOUS_PROXY_SRC,0,GEOIP_USE_SRC},
134 {"is_satellite_provider_s",SORT_IS_SATELLITE_PROVIDER_SRC,SEL_IS_SATELLITE_PROVIDER_SRC,SEL_BOOLEAN,NULL,&fields_used.is_satellite_provider_s,COL_IS_SATELLITE_PROVIDER_SRC,0,GEOIP_USE_SRC},
135 {"postal_code_s",SORT_POSTAL_CODE_SRC,SEL_POSTAL_CODE_SRC,SEL_REGEX,NULL,&fields_used.postal_code_s,COL_POSTAL_CODE_SRC,0,GEOIP_USE_SRC},
136 {"latitude_s",SORT_LATITUDE_SRC,SEL_LATITUDE_SRC,SEL_DOUBLE,NULL,&fields_used.latitude_s,COL_LATITUDE_SRC,0,GEOIP_USE_SRC},
137 {"longitude_s",SORT_LONGITUDE_SRC,SEL_LONGITUDE_SRC,SEL_DOUBLE,NULL,&fields_used.longitude_s,COL_LONGITUDE_SRC,0,GEOIP_USE_SRC},
138 {"continent_code_d",SORT_CONTINENT_CODE_DST,SEL_CONTINENT_CODE_DST,SEL_REGEX,NULL,&fields_used.continent_code_d,COL_CONTINENT_CODE_DST,0,GEOIP_USE_DST},
139 {"continent_name_d",SORT_CONTINENT_NAME_DST,SEL_CONTINENT_NAME_DST,SEL_REGEX,NULL,&fields_used.continent_name_d,COL_CONTINENT_NAME_DST,0,GEOIP_USE_DST},
140 {"country_iso_code_d",SORT_COUNTRY_ISO_CODE_DST,SEL_COUNTRY_ISO_CODE_DST,SEL_REGEX,NULL,&fields_used.country_iso_code_d,COL_COUNTRY_ISO_CODE_DST,0,GEOIP_USE_DST},
141 {"country_name_d",SORT_COUNTRY_NAME_DST,SEL_COUNTRY_NAME_DST,SEL_REGEX,NULL,&fields_used.country_name_d,COL_COUNTRY_NAME_DST,0,GEOIP_USE_DST},
142 {"subdivision_1_iso_code_d",SORT_SUBDIVISION_1_ISO_CODE_DST,SEL_SUBDIVISION_1_ISO_CODE_DST,SEL_REGEX,NULL,&fields_used.subdivision_1_iso_code_d,COL_SUBDIVISION_1_ISO_CODE_DST,0,GEOIP_USE_DST},
143 {"subdivision_1_name_d",SORT_SUBDIVISION_1_NAME_DST,SEL_SUBDIVISION_1_NAME_DST,SEL_REGEX,NULL,&fields_used.subdivision_1_name_d,COL_SUBDIVISION_1_NAME_DST,0,GEOIP_USE_DST},
144 {"subdivision_2_iso_code_d",SORT_SUBDIVISION_2_ISO_CODE_DST,SEL_SUBDIVISION_2_ISO_CODE_DST,SEL_REGEX,NULL,&fields_used.subdivision_2_iso_code_d,COL_SUBDIVISION_2_ISO_CODE_DST,0,GEOIP_USE_DST},
145 {"subdivision_2_name_d",SORT_SUBDIVISION_2_NAME_DST,SEL_SUBDIVISION_2_NAME_DST,SEL_REGEX,NULL,&fields_used.subdivision_2_name_d,COL_SUBDIVISION_2_NAME_DST,0,GEOIP_USE_DST},
146 {"city_name_d",SORT_CITY_NAME_DST,SEL_CITY_NAME_DST,SEL_REGEX,NULL,&fields_used.city_name_d,COL_CITY_NAME_DST,0,GEOIP_USE_DST},
147 {"metro_code_d",SORT_METRO_CODE_DST,SEL_METRO_CODE_DST,SEL_NUM,NULL,&fields_used.metro_code_d,COL_METRO_CODE_DST,0,GEOIP_USE_DST},
148 {"accuracy_radius_d",SORT_ACCURACY_RADIUS_DST,SEL_ACCURACY_RADIUS_DST,SEL_NUM,NULL,&fields_used.accuracy_radius_d,COL_ACCURACY_RADIUS_DST,0,GEOIP_USE_DST},
149 {"time_zone_d",SORT_TIME_ZONE_DST,SEL_TIME_ZONE_DST,SEL_REGEX,NULL,&fields_used.time_zone_d,COL_TIME_ZONE_DST,0,GEOIP_USE_DST},
150 {"registered_country_geoname_id_d",SORT_REGISTERED_COUNTRY_GEONAME_ID_DST,SEL_REGISTERED_COUNTRY_GEONAME_ID_DST,SEL_REGEX,NULL,&fields_used.registered_country_geoname_id_d,COL_REGISTERED_COUNTRY_GEONAME_ID_DST,0,GEOIP_USE_DST},
151 {"represented_country_geoname_id_d",SORT_REPRESENTED_COUNTRY_GEONAME_ID_DST,SEL_REPRESENTED_COUNTRY_GEONAME_ID_DST,SEL_REGEX,NULL,&fields_used.represented_country_geoname_id_d,COL_REPRESENTED_COUNTRY_GEONAME_ID_DST,0,GEOIP_USE_DST},
152 {"is_anonymous_proxy_d",SORT_IS_ANONYMOUS_PROXY_DST,SEL_IS_ANONYMOUS_PROXY_DST,SEL_BOOLEAN,NULL,&fields_used.is_anonymous_proxy_d,COL_IS_ANONYMOUS_PROXY_DST,0,GEOIP_USE_DST},
153 {"is_satellite_provider_d",SORT_IS_SATELLITE_PROVIDER_DST,SEL_IS_SATELLITE_PROVIDER_DST,SEL_BOOLEAN,NULL,&fields_used.is_satellite_provider_d,COL_IS_SATELLITE_PROVIDER_DST,0,GEOIP_USE_DST},
154 {"postal_code_d",SORT_POSTAL_CODE_DST,SEL_POSTAL_CODE_DST,SEL_REGEX,NULL,&fields_used.postal_code_d,COL_POSTAL_CODE_DST,0,GEOIP_USE_DST},
155 {"latitude_d",SORT_LATITUDE_DST,SEL_LATITUDE_DST,SEL_DOUBLE,NULL,&fields_used.latitude_d,COL_LATITUDE_DST,0,GEOIP_USE_DST},
156 {"longitude_d",SORT_LONGITUDE_DST,SEL_LONGITUDE_DST,SEL_DOUBLE,NULL,&fields_used.longitude_d,COL_LONGITUDE_DST,0,GEOIP_USE_DST},
157 {"extra",0,0,0,NULL,NULL,0,0,0},
158 {"extra_value",0,0,0,NULL,NULL,0,0,0},
159 {"oob_earliest",0,0,0,NULL,NULL,0,0,0},
160 {"oob_latest",0,0,0,NULL,NULL,0,0,0},
161 {"oob_time_sec",0,0,0,NULL,NULL,0,0,0},
162 {"oob_time_usec",0,0,0,NULL,NULL,0,0,0},
163 {"oob_max_date",0,0,0,NULL,NULL,0,0,0},
164 {"oob_min_date",0,0,0,NULL,NULL,0,0,0},
165 {"oob_max_earliest",0,0,0,NULL,NULL,0,0,0},
166 {"oob_min_latest",0,0,0,NULL,NULL,0,0,0},
167 {NULL,0,0,0,NULL,NULL,0,0,0}
168 };
169
170 /* Function to get string parameter.
171 *
172 * Leading whitespace is discarded. If the next character is a
173 * single or double quote, then line is taken until last matching
174 * quote is encountered, with embedded quotes left intact.
175 * Anything trailing the last matching quote is discarded.
176 * If no matching quote is found, then the rest of the line is
177 * returned including the first quote character, but with trailing
178 * whitespace discarded. Leading and trailing whitespace is
179 * included if within matching quotes.
180 */
181
str_parameter(char * string)182 char * str_parameter(char *string)
183 {
184 char *quote, *startquote = NULL, *endquote, *pnt, *ret;
185
186 ret = string;
187
188 while (*ret == ' ' || *ret == '\t')
189 ++ret;
190
191 quote = strdup(ret);
192 if ( *ret == '"' || *ret == '\'') {
193 startquote = ret;
194 xstrncpy(quote, ret, 1 + 1);
195 } else {
196 *quote = '\0';
197 startquote = ret;
198 }
199
200 ++ret;
201 endquote = strrchr(ret, *quote);
202 pnt = ret;
203 while ((endquote == NULL || *endquote == '\0' || endquote != pnt) && *pnt != '\n' && *pnt != '\0')
204 ++pnt;
205
206 /* When pnt reaches matching end quote, or end of string, terminator is *
207 * written over current character. If matching quote was found, opening *
208 * quote is overwritten with space. Trailing whitespace, if any, is *
209 * discarded */
210
211 *pnt = '\0';
212
213 if ((endquote != NULL && (*quote == '"' || *quote == '\'') && endquote == pnt)) {
214 *startquote = ' ';
215 } else {
216 --ret;
217 }
218
219 if (*endquote == '\0' || endquote != pnt) {
220 --pnt;
221 while (*pnt == ' ' || *pnt == '\t' || *pnt == '\n') {
222 *pnt = '\0';
223 --pnt;
224 }
225 }
226
227 free(quote);
228 return ret;
229 }
230
double_parameter(char * string,int linenum)231 double double_parameter(char *string, int linenum)
232 {
233 char *pnt, *para;
234
235 if (string == NULL) return 0;
236
237 para = string;
238
239 while (*para == ' ' || *para == '\t' || *para == '"')
240 ++para;
241
242 pnt = para;
243 while (*pnt != '\n' && *pnt != ' ' && *pnt != '"' && *pnt != ':'
244 && *pnt != '#' && *pnt != ',' && *pnt != '\t' && *pnt != '\0') {
245 if(!isxdigit((int)*pnt) && strncasecmp(pnt, "x", 1) != 0 && strncmp(pnt, ".", 1) != 0 && strncmp(pnt, "-", 1) != 0) {
246 if (opt.verbose >= VERBOSE_INFO)
247 fprintf(stderr, "Error in report definition, line %d: %s not a double\n", linenum, pnt);
248 return 0;
249 }
250
251 ++pnt;
252 }
253 *pnt = '\0';
254
255 return strtod (para, NULL);
256 }
257
num_parameter(char * string,int linenum)258 unsigned long int num_parameter(char *string, int linenum)
259 {
260 char *pnt, *para, *retptr;
261 unsigned long ret;
262
263 if (string == NULL) return 0;
264
265 para = string;
266
267 while (*para == ' ' || *para == '\t' || *para == '"')
268 ++para;
269
270 pnt = para;
271 while (*pnt != '\n' && *pnt != ' ' && *pnt != '"' && *pnt != ':'
272 && *pnt != '#' && *pnt != ',' && *pnt != '\t' && *pnt != '\0') {
273 if(!isxdigit((int)*pnt) && strncasecmp(pnt, "x", 1) != 0 && strncasecmp(pnt, "b", 1) != 0) {
274 if (opt.verbose >= VERBOSE_INFO)
275 fprintf(stderr, "Error in report definition, line %d: %s not a number\n", linenum, pnt);
276 return 0;
277 }
278
279 ++pnt;
280 }
281 *pnt = '\0';
282
283 ret = strtoul (para, &retptr, 0);
284
285 if (*retptr == '\0')
286 return ret;
287 else if (strncasecmp(retptr, "b", 1) == 0)
288 ret = strtoul (++retptr, NULL, 2);
289 else
290 ret = 0;
291
292 return ret;
293 }
294
yes_or_no(char * string,int linenum)295 unsigned char yes_or_no(char *string, int linenum)
296 {
297 char *pnt, *orig;
298
299 orig = strdup(string);
300
301 while (*string == ' ' || *string == '\t' || *string == '"')
302 ++string;
303
304 pnt = string;
305
306 while (*pnt != '\n' && *pnt != ' ' && *pnt != '"' && *pnt != '#' && *pnt != '\t' && *pnt != '\0')
307 ++pnt;
308 *pnt = '\0';
309
310 if((strncasecmp(string, "yes", 3) == 0)
311 || (strncasecmp(string, "1", 1) == 0)
312 || (strncasecmp(string, "on", 2) == 0)
313 || (strncasecmp(string, "true", 4) == 0)) {
314 if (opt.verbose >= VERBOSE_DEBUG)
315 fprintf(stderr, "%s was parsed to %s and evaluated to true\n", orig, string);
316
317 free(orig);
318 return true;
319 } else if((strlen(string) == 0)
320 || (strncasecmp(string, "0", 1) == 0)
321 || (strncasecmp(string, "no", 2) == 0)
322 || (strncasecmp(string, "off", 3) == 0)
323 || (strncasecmp(string, "false", 5) == 0)) {
324 if (opt.verbose >= VERBOSE_DEBUG)
325 fprintf(stderr, "%s was parsed to %s and evaluated to false\n", orig, string);
326
327 free(orig);
328 return false;
329 } else {
330 if (opt.verbose >= VERBOSE_DEBUG)
331 fprintf(stderr, "Error in report definition, line %d, assuming 'true'\n", linenum);
332
333 free(orig);
334 return true;
335 }
336 }
337
resolve_protobyname(char * proto)338 int resolve_protobyname(char *proto)
339 {
340 struct protoent *protoent;
341
342 proto = str_parameter(proto);
343 protoent = getprotobyname(proto);
344 if (protoent != NULL) {
345 return (protoent->p_proto);
346 } else {
347 return 0;
348 }
349 }
350
351 /* Adds an item to the fields list. */
add_column(struct field_order * new,char * key,char * parm,int linenum)352 struct field_order * add_column(struct field_order *new, char *key, char *parm, int linenum)
353 {
354 struct field_order *col, *list = NULL, *last = NULL, *this = NULL, *next = NULL;
355 int j;
356
357 for (j=0; keys[j].key != NULL; j++) {
358 if(strcmp(keys[j].key, key) == 0)
359 break;
360 }
361
362 list = new;
363
364 if (keys[j].key == NULL) {
365 if (opt.verbose >= VERBOSE_ALERT)
366 fprintf(stderr, "Skipping unrecognized column: %s\n", strip_nl(key));
367
368 return list;
369 }
370
371 if (!keys[j].col_key) {
372 if (opt.verbose >= VERBOSE_ERROR)
373 fprintf(stderr, "ignoring key = %s\n", key);
374
375 return list;
376 }
377
378 col = xmalloc(sizeof(struct field_order));
379 col->next = NULL;
380 xstrncpy(col->keyname, keys[j].key, SHORTLEN);
381 col->position = num_parameter(parm, linenum);
382 if (keys[j].field_used != NULL) *keys[j].field_used = 1;
383 col->field = keys[j].col_key;
384 if (keys[j].cache_resolve)
385 opt.resolve_hosts |= keys[j].cache_resolve;
386 opt.use_geoip |= keys[j].use_geoip;
387
388 column_count++;
389 last = list;
390 this = list;
391 next = NULL;
392 if (this != NULL) next = this->next;
393
394 while (this != NULL) {
395 if (opt.verbose >= VERBOSE_ERROR) {
396 fprintf(stderr, "Inserting column %s into list: this->position = %i\n", key, this->position);
397 }
398 if (col->position > this->position) {
399 last = this;
400 this = last->next;
401 if (this != NULL) next = this->next;
402 continue;
403 } else {
404 break;
405 }
406 }
407
408 if (opt.verbose >= VERBOSE_DEBUG) {
409 if (last != NULL) fprintf(stderr, "Last->position: %i\n", last->position);
410 if (this != NULL) fprintf(stderr, "This->position: %i\n", this->position);
411 if (next != NULL) fprintf(stderr, "Next->position: %i\n", next->position);
412 }
413
414 if (list == NULL) {
415 if (opt.verbose >= VERBOSE_DEBUG) {
416 fprintf(stderr, "First item seen; position: %i\n", col->position);
417 }
418 list = col;
419 } else { /* not first item seen */
420 if (list->next == NULL) {
421 if (opt.verbose >= VERBOSE_DEBUG) {
422 fprintf(stderr, "Second item seen; position: %i\n", col->position);
423 }
424 if (col->position > list->position) {
425 list->next = col;
426 } else {
427 this = list;
428 list = col;
429 list->next = this;
430 }
431 } else { /* not second item seen */
432 if (opt.verbose >= VERBOSE_DEBUG) {
433 fprintf(stderr, "Not first or second item; position: %i\n", col->position);
434 }
435 if (this == NULL) {
436 if (opt.verbose >= VERBOSE_DEBUG) {
437 fprintf(stderr, "this->position = NULL = place item last\n");
438 }
439 last->next = col;
440 col->next = NULL;
441 } else { /* not last */
442 if (this->position == last->position) {
443 if (opt.verbose >= VERBOSE_DEBUG) {
444 fprintf(stderr, "this->position = last->position = place item first\n");
445 }
446 col->next = list;
447 list = col;
448 } else { /* not first */
449 if (opt.verbose >= VERBOSE_DEBUG) {
450 fprintf(stderr, "this->position > last->position = insert item\n");
451 }
452 last->next = col;
453 col->next = this;
454 } /* end: else clause of test to place item first */
455 } /* end: else clause of test to place item last */
456 } /* end: else clause of test for second item seen */
457 } /* end: else clause of test for first item seen */
458
459 if (opt.verbose >= VERBOSE_WARNING)
460 fprintf(stderr, "Added column %s at position %i\n", key, col->position);
461
462 return list;
463 }
464
465 /* Adds an item to the criteria list. *
466 * If selection->have_value = -1, then only invert flag was *
467 * present and entry should not be used for selection */
add_selection(char * key,char * parm,int linenum,int mode)468 void add_selection(char *key, char *parm, int linenum, int mode)
469 {
470 struct selection *sel = NULL, *addl = NULL, *prior = NULL;
471 int seen, bits, res, skip = 0;
472 static int fragoff_flags = 0;
473 char *ptr = NULL, *ptrr, *parms;
474 struct in_addr inp;
475 #if HAVE_INET_NTOP
476 struct in6_addr inp6;
477 #endif
478 char buf[INET6_ADDRSTRLEN], re_err[SHORTLEN], delim;
479 char stime[SHORTLEN];
480 char addr[16], mask[16];
481 int j;
482
483 *buf = '\0';
484
485 for (j=0; keys[j].key != NULL; j++) {
486 if(strcmp(keys[j].key, key) == 0)
487 break;
488 }
489
490 /* skip any unrecognized criterion */
491 if (keys[j].key == NULL) {
492 if (opt.verbose >= VERBOSE_ALERT)
493 fprintf(stderr, "Skipping unrecognized criterion: %s\n", strip_nl(key));
494
495 return;
496 }
497
498 if (!keys[j].sel_type) {
499 if (opt.verbose >= VERBOSE_ERROR)
500 fprintf(stderr, "ignoring key = %s\n", key);
501
502 return;
503 }
504
505 sel = xmalloc(sizeof(struct selection));
506 sel->value = 0;
507 sel->max_value = 0;
508 sel->double_value = 0;
509 sel->max_double_value = 0;
510 *sel->svalue = '\0';
511 sel->in_addr = 0;
512 sel->netmask = -1;
513 #if HAVE_INET_NTOP
514 memset(sel->in6_addr.s6_addr, 0x00, sizeof(struct in6_addr));
515 #endif
516 sel->in6_bits = 128;
517 sel->family = AF_INET;
518 regcomp(&sel->buf, ".", REG_NOSUB);
519 sel->invert = 0;
520 sel->field = -1;
521 sel->type = 0;
522 sel->next = NULL;
523 xstrncpy(sel->keyname, key, SHORTLEN);
524 parms = strdup(parm);
525
526 switch(keys[j].sel_type) {
527 case SEL_DATE:
528 case SEL_BOOLEAN:
529 case SEL_DFMF:
530 if (mode != DEF_WHERE) {
531 if (opt.verbose >= VERBOSE_ALERT)
532 fprintf(stderr, "Skipping invert flag for criterion: %s\n", key);
533
534 free(sel);
535 return;
536 }
537 /* fall through */
538 case SEL_NUM:
539 case SEL_DOUBLE:
540 case SEL_IPADDR:
541 case SEL_REGEX:
542 case SEL_PROTO:
543 sel->field = keys[j].sel_key;
544 if (keys[j].sel_type == SEL_DFMF)
545 sel->type = SEL_NUM;
546 else
547 sel->type = keys[j].sel_type;
548 break;
549 case SEL_AGG_COUNT:
550 *keys[j].aggregate_value = num_parameter(parm, linenum);
551 free(sel);
552 return;
553 case SEL_AGG_DATE:
554 *keys[j].aggregate_value = num_parameter(parm, linenum);
555 free(sel);
556 return;
557 case SEL_ID:
558 opt.packet = num_parameter(parm, linenum);
559 free(sel);
560 return;
561 default:
562 break;
563 }
564
565 switch (mode) {
566 case DEF_INVERT:
567 sel->invert = yes_or_no(parm, linenum);
568 break;
569 case DEF_WHERE:
570 switch (sel->type) {
571 case SEL_PROTO:
572 xstrncpy(sel->svalue, str_parameter(parm), SHORTLEN);
573 ptr = strpbrk((char *)&sel->svalue, ",");
574 if (ptr != NULL)
575 *ptr = '\0';
576 if(isdigit((unsigned char)*sel->svalue)) {
577 sel->value = num_parameter(parm, linenum);
578 ptrr = strpbrk((char *)&sel->svalue, ":");
579 if (ptrr == NULL) {
580 sel->max_value = sel->value;
581 } else {
582 sel->max_value = num_parameter(++ptrr, linenum);
583 }
584 } else {
585 sel->value = resolve_protobyname(sel->svalue);
586 sel->max_value = sel->value;
587 }
588 if (ptr != NULL)
589 parm = ++ptr;
590 break;
591 case SEL_NUM:
592 xstrncpy((char *)&sel->svalue, str_parameter(parm), SHORTLEN);
593 sel->value = num_parameter(parm, linenum);
594 ptr = strpbrk((char *)&sel->svalue, ",");
595 if (ptr != NULL)
596 *ptr = '\0';
597 ptrr = strpbrk((char *)&sel->svalue, ":");
598 if (ptrr == NULL) {
599 sel->max_value = sel->value;
600 } else {
601 sel->max_value = num_parameter(++ptrr, linenum);
602 }
603 if (ptr != NULL)
604 parm = ++ptr;
605 break;
606 case SEL_DOUBLE:
607 xstrncpy((char *)&sel->svalue, str_parameter(parm), SHORTLEN);
608 sel->double_value = double_parameter(parm, linenum);
609 ptr = strpbrk((char *)&sel->svalue, ",");
610 if (ptr != NULL)
611 *ptr = '\0';
612 ptrr = strpbrk((char *)&sel->svalue, ":");
613 if (ptrr == NULL) {
614 sel->max_double_value = sel->double_value;
615 } else {
616 sel->max_double_value = double_parameter(++ptrr, linenum);
617 }
618 if (ptr != NULL)
619 parm = ++ptr;
620 break;
621 case SEL_IPADDR:
622 xstrncpy(sel->svalue, str_parameter(parm), SHORTLEN);
623 ptr = strpbrk((char *)&sel->svalue, ",");
624 if (ptr != NULL)
625 *ptr = '\0';
626 #if HAVE_INET_NTOP
627 if (strpbrk((char *)&sel->svalue, ":"))
628 sel->family = AF_INET6;
629 #endif
630 ptrr = strpbrk((char *)&sel->svalue, "/");
631 if (ptrr != NULL) {
632 strncpy(&delim, ptrr, 1);
633 *ptrr = '\0';
634 }
635 if (sel->family == AF_INET) {
636 if (convert_ip(AF_INET, sel->svalue, &inp, NULL, NULL)) { /* error */
637 if (opt.verbose >= VERBOSE_NOTICE)
638 fprintf(stderr, "Couldn't convert %s\n", sel->svalue);
639 break;
640 }
641 sel->in_addr = ntohl(inp.s_addr);
642 #if HAVE_INET_NTOP
643 } else {
644 if (convert_ip(AF_INET6, sel->svalue, NULL, &inp6, NULL)) { /* error */
645 if (opt.verbose >= VERBOSE_NOTICE)
646 fprintf(stderr, "Couldn't convert %s\n", sel->svalue);
647 break;
648 }
649 memcpy(sel->in6_addr.s6_addr, inp6.s6_addr, sizeof(struct in6_addr));
650 #endif
651 }
652 if (ptrr != NULL) {
653 strncpy(ptrr, &delim, 1);
654 if (sel->family == AF_INET) {
655 if (strpbrk(++ptrr, ".") == NULL) {
656 sel->netmask = ~(uint32_t)(pow(2, 32 - num_parameter(ptrr, linenum)) - 1);
657 } else {
658 sel->netmask = inet_network(str_parameter(ptrr));
659 }
660 sel->in_addr = sel->in_addr & sel->netmask;
661 } else {
662 bits = atoi(++ptrr);
663 if (bits >= 0 && bits <= 128)
664 sel->in6_bits = bits;
665 }
666 }
667 if (ptr != NULL)
668 parm = ++ptr;
669 break;
670 case SEL_REGEX:
671 xstrncpy(sel->svalue, str_parameter(parm), SHORTLEN);
672 res = regcomp(&sel->buf, sel->svalue, REG_NOSUB||REG_EXTENDED);
673 if (res) { /* error */
674 if (opt.verbose >= VERBOSE_NOTICE) {
675 regerror(res, &sel->buf, re_err, SHORTLEN);
676 fprintf(stderr, "Error in regular expression \"%s\" for key %s, skipping:\n %s\n", sel->svalue, key, re_err);
677 }
678 regcomp(&sel->buf, ".", REG_NOSUB);
679 skip++;
680 }
681 break;
682 case SEL_DATE:
683 sel->value = num_parameter(parm, linenum);
684 if (strftime((char *)&stime,SHORTLEN,"%c %Z",localtime((time_t *)&sel->value)))
685 xstrncpy(sel->svalue, (char *)&stime, SHORTLEN);
686 break;
687 case SEL_BOOLEAN:
688 sel->value = yes_or_no(parm, linenum);
689 break;
690 default:
691 /* error */
692 break;
693 } /* end switch (sel->type) */
694 opt.use_geoip |= keys[j].use_geoip;
695 break;
696 default:
697 /* error */
698 break;
699 } /* end switch (mode) */
700
701
702 if (sel->field == SEL_TCP_FLAGS) {
703 sel->value = 0;
704 strcpy(sel->keyname, "tcp_flags");
705 }
706
707 if (sel->field == SEL_TCP_SYN) {
708 sel->value = TCP_SYN;
709 strcpy(sel->keyname, "tcp_flags");
710 sel->field = SEL_TCP_FLAGS;
711 }
712
713 if (sel->field == SEL_TCP_ACK) {
714 sel->value = TCP_ACK;
715 strcpy(sel->keyname, "tcp_flags");
716 sel->field = SEL_TCP_FLAGS;
717 }
718
719 if (sel->field == SEL_TCP_FIN) {
720 sel->value = TCP_FIN;
721 strcpy(sel->keyname, "tcp_flags");
722 sel->field = SEL_TCP_FLAGS;
723 }
724
725 if (sel->field == SEL_TCP_RST) {
726 sel->value = TCP_RST;
727 strcpy(sel->keyname, "tcp_flags");
728 sel->field = SEL_TCP_FLAGS;
729 }
730
731 if (sel->field == SEL_TCP_URG) {
732 sel->value = TCP_URG;
733 strcpy(sel->keyname, "tcp_flags");
734 sel->field = SEL_TCP_FLAGS;
735 }
736
737 if (sel->field == SEL_TCP_PSH) {
738 sel->value = TCP_PSH;
739 strcpy(sel->keyname, "tcp_flags");
740 sel->field = SEL_TCP_FLAGS;
741 }
742
743 if (sel->field == SEL_TCP_OPTS_EXACT) {
744 sel->value = TCP_OPTS_EXACT;
745 strcpy(sel->keyname, "tcp_flags");
746 sel->field = SEL_TCP_FLAGS;
747 }
748
749 if (sel->field == SEL_IP_DF || sel->field == SEL_IP_MF) {
750 fragoff_flags |= sel->value;
751 sel->field = SEL_IP_FRAGOFF;
752 strcpy(sel->keyname, "ip_fragoff");
753 }
754
755 prior = selection;
756 seen = 0;
757 while (prior != NULL) {
758 if (prior->field == sel->field) {
759 seen = 1;
760 if (mode == DEF_INVERT) {
761 prior->invert = sel->invert;
762 }
763
764 if (sel->field == SEL_TCP_FLAGS)
765 sel->value = sel->value | prior->value;
766
767 if (sel->field == SEL_IP_FRAGOFF) {
768 sel->value |= prior->value;
769 sel->max_value |= prior->max_value;
770 }
771
772 if (mode == DEF_WHERE) {
773 prior->have_value = 0;
774 prior->value = sel->value;
775 prior->max_value = sel->max_value;
776 xstrncpy(prior->svalue, sel->svalue, SHORTLEN);
777 sel->invert = prior->invert; /* for multiple add */
778 break;
779 }
780 }
781 /* not seen */
782 prior = prior->next;
783 }
784
785 if (!seen && !skip) {
786 selection_count++;
787 }
788
789 if (!skip &&(!seen && mode == DEF_INVERT)) {
790 sel->have_value = -1;
791 } else {
792 sel->have_value = 0;
793 }
794
795 if (!seen && !skip) {
796 sel->next = selection;
797 selection= sel;
798 }
799
800 if (opt.verbose >= VERBOSE_WARNING && !skip) {
801 switch (mode) {
802 case DEF_INVERT:
803 fprintf(stderr, "Added invert flag for criterion: %s\n", key);
804 break;
805 case DEF_WHERE:
806 if (sel->field == SEL_TCP_FLAGS) {
807 fprintf(stderr, "Added criterion: %s\n", key);
808 } else {
809 inp.s_addr = htonl(sel->in_addr);
810 xstrncpy(addr, inet_ntoa(inp), SHORTLEN);
811 inp.s_addr = htonl(sel->netmask);
812 xstrncpy(mask, inet_ntoa(inp), SHORTLEN);
813 fprintf(stderr, "Added criterion: %s; Value: %lu; Max value: %lu; Svalue: %s; Family: %i; Addr: %s; Netmask: %s;"
814 #if HAVE_INET_NTOP
815 " In6_addr: %s; In6_bits: %u"
816 #endif
817 "\n",
818 key, sel->value, sel->max_value, sel->svalue, sel->family, addr, mask
819 #if HAVE_INET_NTOP
820 ,inet_ntop(AF_INET6, sel->in6_addr.s6_addr, buf, INET6_ADDRSTRLEN), sel->in6_bits
821 #endif
822 );
823 }
824 break;
825 default:
826 break;
827 }
828 }
829
830 /* If multiple values are specified, add new selection criterion for each */
831 str_parameter(parms); /* drop quotes */
832 if (mode == DEF_WHERE && (sel->type == SEL_NUM || sel->type == SEL_DOUBLE || sel->type == SEL_IPADDR || sel->type == SEL_PROTO) && ptr != NULL ) {
833
834 while (ptr != NULL) {
835
836 addl = xmalloc(sizeof(struct selection));
837 addl->field = sel->field;
838 xstrncpy(addl->keyname, sel->keyname, SHORTLEN);
839 addl->type = sel->type;
840 #if HAVE_INET_NTOP
841 memset(addl->in6_addr.s6_addr, 0x00, sizeof(struct in6_addr));
842 #endif
843 addl->in6_bits = 128;
844 addl->family = AF_INET;
845 regcomp(&addl->buf, ".", REG_NOSUB);
846 addl->invert = sel->invert;
847 addl->have_value = sel->have_value;
848 addl->in_addr = 0;
849 addl->netmask = -1;
850
851 xstrncpy((char *)&addl->svalue, str_parameter(parm), SHORTLEN);
852 ptr = strpbrk((char *)&addl->svalue, ",");
853 if (ptr != NULL)
854 *ptr = '\0';
855 if (sel-> type == SEL_NUM) {
856 addl->value = num_parameter(parm, linenum);
857 ptrr = strpbrk((char *)&addl->svalue, ":");
858 if (ptrr == NULL) {
859 addl->max_value = addl->value;
860 } else {
861 addl->max_value = num_parameter(++ptrr, linenum);
862 }
863 if (sel->field == SEL_IP_FRAGOFF) {
864 addl->value |= fragoff_flags;
865 addl->max_value |= fragoff_flags;
866 }
867 } else if (sel-> type == SEL_DOUBLE) {
868 addl->double_value = double_parameter(parm, linenum);
869 ptrr = strpbrk((char *)&addl->svalue, ":");
870 if (ptrr == NULL) {
871 addl->max_double_value = addl->double_value;
872 } else {
873 addl->max_double_value = double_parameter(++ptrr, linenum);
874 }
875 } else if (sel->type == SEL_IPADDR) {
876 if (strpbrk((char *)&addl->svalue, ":") == NULL) {
877 addl->family = AF_INET;
878 #if HAVE_INET_NTOP
879 } else {
880 addl->family = AF_INET6;
881 #endif
882 }
883 ptrr = strpbrk((char *)&addl->svalue, "/");
884 if (ptrr != NULL) {
885 strncpy(&delim, ptrr, 1);
886 *ptrr = '\0';
887 }
888 if (addl->family == AF_INET) {
889 if (convert_ip(AF_INET, addl->svalue, &inp, NULL, NULL)) { /* error */
890 if (opt.verbose >= VERBOSE_NOTICE)
891 fprintf(stderr, "Couldn't convert %s\n", addl->svalue);
892 break;
893 }
894 addl->in_addr = ntohl(inp.s_addr);
895 #if HAVE_INET_NTOP
896 } else {
897 if (convert_ip(AF_INET6, addl->svalue, NULL, &inp6, NULL)) { /* error */
898 if (opt.verbose >= VERBOSE_NOTICE)
899 fprintf(stderr, "Couldn't convert %s\n", addl->svalue);
900 break;
901 }
902 memcpy(addl->in6_addr.s6_addr, inp6.s6_addr, sizeof(struct in6_addr));
903 #endif
904 }
905 if (ptrr != NULL) {
906 strncpy(ptrr, &delim, 1);
907 if (addl->family == AF_INET) {
908 if (strpbrk(++ptrr, ".") == NULL) {
909 addl->netmask = ~(uint32_t)(pow(2, 32 - num_parameter(ptrr, linenum)) - 1);
910 } else {
911 addl->netmask = inet_network(str_parameter(ptrr));
912 }
913 addl->in_addr = addl->in_addr & addl->netmask;
914 } else {
915 bits = atoi(++ptrr);
916 if (bits >= 0 && bits <= 128)
917 addl->in6_bits = bits;
918 }
919 }
920 } else if (sel->type == SEL_PROTO) {
921 if(isdigit((unsigned char)*addl->svalue)) {
922 addl->value = num_parameter(parm, linenum);
923 ptrr = strpbrk((char *)&addl->svalue, ":");
924 if (ptrr == NULL) {
925 addl->max_value = addl->value;
926 } else {
927 addl->max_value = num_parameter(++ptrr, linenum);
928 }
929 } else {
930 addl->value = resolve_protobyname(addl->svalue);
931 addl->max_value = addl->value;
932 }
933 }
934
935 if (ptr != NULL)
936 parm = ++ptr;
937
938 if (opt.verbose >= VERBOSE_WARNING) {
939 inp.s_addr = htonl(addl->in_addr);
940 xstrncpy(addr, inet_ntoa(inp), SHORTLEN);
941 inp.s_addr = htonl(addl->netmask);
942 xstrncpy(mask, inet_ntoa(inp), SHORTLEN);
943 fprintf(stderr, "Added criterion: %s; Value: %lu; Max value %lu; Svalue: %s; Family: %i; Addr: %s; Netmask: %s;"
944 #if HAVE_INET_NTOP
945 " In6_addr: %s; In6_bits: %u"
946 #endif
947 "\n",
948 key, addl->value, addl->max_value, addl->svalue, addl->family, addr, mask
949 #if HAVE_INET_NTOP
950 ,inet_ntop(AF_INET6, addl->in6_addr.s6_addr, buf, INET6_ADDRSTRLEN), addl->in6_bits
951 #endif
952 );
953 }
954
955 addl->next = selection;
956 selection = addl;
957
958 selection_count++;
959
960 }
961
962 }
963
964 free(parms);
965
966 if (seen) {
967 free(sel);
968 }
969
970 return;
971 }
972
973 /* Adds an item to the sort list. *
974 * If sort_order->position = -35768, then only order flag *
975 * was present and entry should not be used for sorting */
add_sort(struct sort_order * new,char * key,char * parm,int linenum,int mode)976 struct sort_order * add_sort(struct sort_order *new, char *key, char *parm, int linenum, int mode)
977 {
978 struct sort_order *srt = NULL, *have = NULL, *last = NULL, *this = NULL, *prev = NULL, *next = NULL, *list = NULL, *old = NULL;
979 int seen, j;
980
981 for (j=0; keys[j].key != NULL; j++) {
982 if(strcmp(keys[j].key, key) == 0)
983 break;
984 }
985
986 list = new;
987
988 if (keys[j].key == NULL) {
989 if (opt.verbose >= VERBOSE_ALERT)
990 fprintf(stderr, "Skipping unrecognized sort field: %s\n", strip_nl(key));
991
992 return list;
993 }
994
995 if (!keys[j].sort_key) {
996 if (opt.verbose >= VERBOSE_ERROR)
997 fprintf(stderr, "ignoring key = %s\n", key);
998
999 return list;
1000 }
1001
1002 srt = xmalloc(sizeof(struct sort_order));
1003 srt->next = NULL;
1004 xstrncpy(srt->keyname, key, SHORTLEN);
1005 srt->order = 0;
1006 srt->position = 0;
1007 srt->field = keys[j].sort_key;
1008
1009 switch (mode) {
1010 case DEF_SORT:
1011 srt->position = num_parameter(parm, linenum);
1012 opt.use_geoip |= keys[j].use_geoip;
1013 break;
1014 case DEF_ORDER:
1015 if (yes_or_no(parm, linenum)){
1016 srt->order = ORDER_DESCENDING;
1017 }
1018 break;
1019 default:
1020 /* error */
1021 break;
1022 }
1023
1024 have = list;
1025 seen = 0;
1026 while (have != NULL) {
1027 if (have->field == srt->field) {
1028 seen = 1;
1029 break;
1030 } else {
1031 prev = have;
1032 have = have->next;
1033 }
1034 }
1035
1036 if (seen) {
1037 if (mode == DEF_SORT) {
1038 /* If we have seen key before and are doing sort position now,
1039 * break it out of list and treat it as new item to be inserted */
1040 have->position = srt->position;
1041 /* if item is currently first in list, make second item first */
1042 if (list == have) list = list->next;
1043 old = srt;
1044 srt = have;
1045 free(old);
1046 if (prev != NULL) {
1047 prev->next = have->next;
1048 }
1049 srt->next = NULL;
1050 } else {
1051 if (mode == DEF_ORDER) {
1052 have->order = srt->order;
1053 } else {;} /* error */
1054 }
1055 } else if (mode == DEF_ORDER) {
1056 srt->position = SORT_INV_NO_SORT;
1057 srt->next = list;
1058 list = srt;
1059 free(have);
1060 }
1061
1062 if (mode == DEF_SORT) {
1063 sort_count++;
1064 last = list;
1065 this = list;
1066 next = NULL;
1067 if (this != NULL) next = this->next;
1068
1069 while (this != NULL) {
1070 if (opt.verbose >= VERBOSE_ERROR) {
1071 fprintf(stderr, "Inserting sort field %s into list: this->position = %i\n", key, this->position);
1072 }
1073 if (srt->position < this->position) {
1074 last = this;
1075 this = last->next;
1076 if (this != NULL) next = this->next;
1077 continue;
1078 } else {
1079 break;
1080 }
1081 }
1082
1083 if (opt.verbose >= VERBOSE_DEBUG) {
1084 if (last != NULL) fprintf(stderr, "Last->position: %i\n", last->position);
1085 if (this != NULL) fprintf(stderr, "This->position: %i\n", this->position);
1086 if (next != NULL) fprintf(stderr, "Next->position: %i\n", next->position);
1087 }
1088
1089 if (list == NULL || (list->position == SORT_INV_NO_SORT && last->position == SORT_INV_NO_SORT)) {
1090 if (opt.verbose >= VERBOSE_DEBUG) {
1091 fprintf(stderr, "First item seen; position: %i\n", srt->position);
1092 }
1093 if (list != NULL)
1094 srt->next = list;
1095 list = srt;
1096 } else { /* not first item seen */
1097 if (list->next == NULL || (this == NULL && list->next->position == SORT_INV_NO_SORT \
1098 && last != NULL && srt->position > last->position)) {
1099 if (opt.verbose >= VERBOSE_DEBUG) {
1100 fprintf(stderr, "Second item seen; position: %i\n", srt->position);
1101 }
1102 if (srt->position < list->position) {
1103 if (list->next != NULL)
1104 srt->next = list->next;
1105 list->next = srt;
1106 } else {
1107 this = list;
1108 list = srt;
1109 list->next = this;
1110 }
1111 } else { /* not second item seen */
1112 if (opt.verbose >= VERBOSE_DEBUG) {
1113 fprintf(stderr, "Not first or second item; position: %i\n", srt->position);
1114 }
1115 if (this == NULL) {
1116 if (opt.verbose >= VERBOSE_DEBUG) {
1117 fprintf(stderr, "this->position = NULL = place item last\n");
1118 }
1119 last->next = srt;
1120 srt->next = NULL;
1121 } else { /* not last */
1122 if (this->position == last->position) {
1123 if (opt.verbose >= VERBOSE_DEBUG) {
1124 fprintf(stderr, "this->position = last->position = place item first\n");
1125 }
1126 srt->next = list;
1127 list = srt;
1128 } else { /* not first */
1129 if (opt.verbose >= VERBOSE_DEBUG) {
1130 fprintf(stderr, "this->position < last->position = insert item\n");
1131 }
1132 last->next = srt;
1133 srt->next = this;
1134 } /* end: else clause of test to place item first */
1135 } /* end: else clause of test to place item last */
1136 } /* end: else clause of test for second item seen */
1137 } /* end: else clause of test for first item seen */
1138 } /* end: if(mode == DEF_SORT} */
1139
1140 if (opt.verbose >= VERBOSE_WARNING) {
1141 switch (mode) {
1142 case DEF_ORDER:
1143 fprintf(stderr, "Added descending flag for sort field %s\n", key);
1144 break;
1145 case DEF_SORT:
1146 fprintf(stderr, "Added sort field %s at position %i\n", key, srt->position);
1147 break;
1148 default:
1149 break;
1150 }
1151 }
1152
1153 return list;
1154 }
1155
1156 /* parses single line from reportdef */
1157 /* called with (linebuf, linenum) */
parse_reportdef(char * input,int linenum)1158 void parse_reportdef(char *input, int linenum)
1159 {
1160 char *command, *key, *parm, *ptr;
1161 unsigned int type, len = 0;
1162
1163 while (*input == ' ' || *input == '\t')
1164 ++input;
1165
1166 if (*input == '#' || *input == '\n')
1167 return;
1168
1169 command = strdup(input);
1170 key = strdup(input);
1171 ptr = key;
1172
1173 len = strcspn(command, " =");
1174 xstrncpy(key, command, len + 1);
1175
1176 parm = strpbrk(command, "=");
1177 if (!(parm == NULL))
1178 parm++;
1179
1180 type = DEF_NONE;
1181
1182 if (strncmp(key, "w_", 2) == 0)
1183 type = DEF_WHERE;
1184
1185 if (strncmp(key, "i_", 2) == 0)
1186 type = DEF_INVERT;
1187
1188 if (strncmp(key, "s_", 2) == 0)
1189 type = DEF_SORT;
1190
1191 if (strncmp(key, "o_", 2) == 0)
1192 type = DEF_ORDER;
1193
1194 if (strncmp(key, "c_", 2) == 0)
1195 type = DEF_COLUMN;
1196
1197 /* Ignore these */
1198 if (strncmp(key, "h_", 2) == 0)
1199 type = DEF_NONE;
1200
1201 if (strncmp(key, "l_", 2) == 0)
1202 type = DEF_NONE;
1203
1204 if (type != DEF_NONE) {
1205 key++; key++;
1206 }
1207
1208 /* Other options */
1209 if (strncmp(key, "summarize", 9) == 0)
1210 type = DEF_SUM;
1211
1212 if (strncmp(key, "populate_cache", 14) == 0) {
1213 opt.resolve_hosts |= CACHE_POPULATE;
1214 type = DEF_OPTION;
1215 }
1216
1217 if (strncmp(key, "upd_hosts", 9) == 0) {
1218 opt.resolve_hosts |= CACHE_UPDATE;
1219 type = DEF_OPTION;
1220 }
1221
1222 if (strncmp(key, "populate_cache_full", 19) == 0) {
1223 opt.resolve_hosts |= CACHE_POPULATE_FULL;
1224 type = DEF_OPTION;
1225 }
1226
1227 if (strncmp(key, "syslog_dir", 10) == 0) {
1228 xstrncpy(opt.pathname, str_parameter(parm), SHORTLEN);
1229 type = DEF_OPTION;
1230 }
1231
1232 if (strncmp(key, "db", 2) == 0) {
1233 xstrncpy(opt.db, str_parameter(parm), SHORTLEN);
1234 type = DEF_OPTION;
1235 }
1236
1237 if (strncmp(key, "mysql_server", 12) == 0) {
1238 xstrncpy(opt.mysql_server, str_parameter(parm), SHORTLEN);
1239 type = DEF_OPTION;
1240 }
1241
1242 if (strncmp(key, "mysql_wfwl_db", 13) == 0) {
1243 xstrncpy(opt.mysql_wfwl_db, str_parameter(parm), SHORTLEN);
1244 type = DEF_OPTION;
1245 }
1246
1247 if (strncmp(key, "mysql_user", 10) == 0) {
1248 xstrncpy(opt.mysql_user, str_parameter(parm), SHORTLEN);
1249 type = DEF_OPTION;
1250 }
1251
1252 if (strncmp(key, "mysql_pass", 10) == 0) {
1253 xstrncpy(opt.mysql_pass, str_parameter(parm), SHORTLEN);
1254 type = DEF_OPTION;
1255 }
1256
1257 if (strncmp(key, "pgsql_server", 12) == 0) {
1258 xstrncpy(opt.pgsql_server, str_parameter(parm), SHORTLEN);
1259 type = DEF_OPTION;
1260 }
1261
1262 if (strncmp(key, "pgsql_db", 8) == 0) {
1263 xstrncpy(opt.pgsql_db, str_parameter(parm), SHORTLEN);
1264 type = DEF_OPTION;
1265 }
1266
1267 if (strncmp(key, "pgsql_user", 10) == 0) {
1268 xstrncpy(opt.pgsql_user, str_parameter(parm), SHORTLEN);
1269 type = DEF_OPTION;
1270 }
1271
1272 if (strncmp(key, "pgsql_pass", 10) == 0) {
1273 xstrncpy(opt.pgsql_pass, str_parameter(parm), SHORTLEN);
1274 type = DEF_OPTION;
1275 }
1276
1277 if (strncmp(key, "pgsql_wfwl_schema", 17) == 0) {
1278 xstrncpy(opt.pgsql_wfwl_schema, str_parameter(parm), SHORTLEN - 1);
1279 type = DEF_OPTION;
1280 }
1281
1282 if (strncmp(key, "pgsql_have_namespace", 20) == 0) {
1283 opt.pgsql_have_namespace = 1;
1284 type = DEF_OPTION;
1285 }
1286
1287 if (strncmp(key, "geoip2_locale", 11) == 0) {
1288 xstrncpy(opt.geoip2_locale, str_parameter(parm), BUFSIZE);
1289 type = DEF_OPTION;
1290 }
1291
1292 if (strncmp(key, "geoip2_file", 11) == 0) {
1293 xstrncpy(opt.geoip2_file, str_parameter(parm), BUFSIZE);
1294 type = DEF_OPTION;
1295 }
1296
1297 if (strncmp(key, "geoip_php_lookup", 16) == 0) {
1298 if(yes_or_no(parm, linenum))
1299 opt.use_geoip |= GEOIP_OFF;
1300 type = DEF_OPTION;
1301 }
1302
1303 if (type == DEF_OPTION) {
1304 if (opt.verbose >= VERBOSE_ALERT) {
1305 if (strncmp(key,"mysql_pass", 10) == 0||strncmp(key,"pgsql_pass", 10) == 0) {
1306 fprintf(stderr, "Added option: %s; Value: %s\n", key, "************");
1307 } else {
1308 fprintf(stderr, "Added option: %s; Value: %s\n", key, strip_nl(str_parameter(parm)));
1309 }
1310 }
1311 } else if (type != DEF_NONE) {
1312 if (opt.verbose >= VERBOSE_ERROR) {
1313 fprintf(stderr, "Processing report definition line Type: %u; Key: %s; Parameter: %s", type, key, parm);
1314 }
1315 } else { /* type == DEF_NONE */
1316 if (opt.verbose >= VERBOSE_ERROR) {
1317 fprintf(stderr, "Ignoring report definition line: %s", command);
1318 }
1319 }
1320
1321 if (!(parm == NULL))
1322 switch (type) {
1323 case DEF_SUM:
1324 if (yes_or_no(parm, linenum)) {
1325 opt.mode = LOG_SUMMARY;
1326 } else {
1327 opt.mode = LOG_DETAIL;
1328 }
1329 break;
1330 case DEF_WHERE:
1331 add_selection(key, parm, linenum, DEF_WHERE);
1332 break;
1333 case DEF_INVERT:
1334 add_selection(key, parm, linenum, DEF_INVERT);
1335 break;
1336 case DEF_SORT:
1337 sort = add_sort(sort, key, parm, linenum, DEF_SORT);
1338 break;
1339 case DEF_ORDER:
1340 sort = add_sort(sort, key, parm, linenum, DEF_ORDER);
1341 break;
1342 case DEF_COLUMN:
1343 fields = add_column(fields, key, parm, linenum);
1344 break;
1345 case DEF_OPTION:
1346 case DEF_NONE:
1347 break;
1348 default:
1349 /* error */
1350 break;
1351 }
1352
1353 free(ptr);
1354 free(command);
1355
1356 return;
1357 }
1358
1359 /* Entry point; called from main.c */
read_reportdef(char * reportdef)1360 unsigned char read_reportdef(char *reportdef)
1361 {
1362 char buf[BUFSIZE], *name;
1363 FILE *fd;
1364 int linenum = 1, retval;
1365 char keyname[SHORTLEN];
1366 char position[SHORTLEN];
1367 char addr[16], mask[16];
1368 char stime[SHORTLEN];
1369 struct stat info;
1370 struct sort_order *srt;
1371 struct field_order *col;
1372 struct selection *sel;
1373 struct in_addr in;
1374
1375 name = strdup(reportdef);
1376
1377 /* validate reportdef file */
1378 if (strcmp(reportdef, "-")) {
1379 retval = stat(reportdef, &info);
1380 if (retval == -1) {
1381 fprintf(stderr, "Cannot open report definition file %s, exiting.\n", reportdef);
1382 return EXIT_FAILURE;
1383 }
1384 if (!S_ISREG(info.st_mode)) {
1385 fprintf(stderr, "%s is not a regular file, exiting.\n", reportdef);
1386 return EXIT_FAILURE;
1387 }
1388
1389 if(opt.verbose >= VERBOSE_INFO)
1390 fprintf(stderr, "Processing report definition file '%s'\n", name);
1391
1392 fd = fopen(name, "r");
1393 if (fd == NULL) {
1394 fprintf(stderr, "fopen %s: %s\n", name, strerror(errno));
1395 exit(EXIT_FAILURE);
1396 }
1397 } else {
1398
1399 if(opt.verbose >= VERBOSE_INFO)
1400 fprintf(stderr, "Processing report definition from stdin\n");
1401
1402 fd = stdin;
1403 }
1404
1405 /* initialize fields_used */
1406 /* this is used for summarization testing. *
1407 * tests done against this static data are faster by a factor of at *
1408 * least two over iterating though field_order linked list for each line. */
1409 fields_used.count = 0;
1410 fields_used.sname = 0;
1411 fields_used.local_time = 0;
1412 fields_used.earliest = 0;
1413 fields_used.latest = 0;
1414 fields_used.hostname = 0;
1415 fields_used.log_label = 0;
1416 fields_used.protocol = 0;
1417 fields_used.family = 0;
1418 fields_used.totlen = 0;
1419 fields_used.shost = 0;
1420 fields_used.sport = 0;
1421 fields_used.dhost = 0;
1422 fields_used.dport = 0;
1423 fields_used.shost_name = 0;
1424 fields_used.dhost_name = 0;
1425 fields_used.src_service = 0;
1426 fields_used.dst_service = 0;
1427 fields_used.flags = 0;
1428 fields_used.oob_protocol = 0;
1429 fields_used.mac_saddr_str = 0;
1430 fields_used.mac_daddr_str = 0;
1431 fields_used.raw_mac = 0;
1432 fields_used.fwmark = 0;
1433 fields_used.inif = 0;
1434 fields_used.outif = 0;
1435 fields_used.tos = 0;
1436 fields_used.ttl = 0;
1437 fields_used.ihl = 0;
1438 fields_used.csum = 0;
1439 fields_used.ipid = 0;
1440 fields_used.fragoff = 0;
1441 fields_used.pay_len = 0;
1442 fields_used.flowlabel = 0;
1443 fields_used.tcp_seq = 0;
1444 fields_used.tcp_ack_seq = 0;
1445 fields_used.tcp_window = 0;
1446 fields_used.tcp_urgp = 0;
1447 fields_used.udp_len = 0;
1448 fields_used.icmp_type = 0;
1449 fields_used.icmp_code = 0;
1450 fields_used.icmp_echoid = 0;
1451 fields_used.icmp_echoseq = 0;
1452 fields_used.icmp_gw = 0;
1453 fields_used.icmp_mtu = 0;
1454 fields_used.ahesp_spi = 0;
1455 fields_used.continent_code_s = 0;
1456 fields_used.continent_name_s = 0;
1457 fields_used.country_iso_code_s = 0;
1458 fields_used.country_name_s = 0;
1459 fields_used.subdivision_1_iso_code_s = 0;
1460 fields_used.subdivision_1_name_s = 0;
1461 fields_used.subdivision_2_iso_code_s = 0;
1462 fields_used.subdivision_2_name_s = 0;
1463 fields_used.city_name_s = 0;
1464 fields_used.metro_code_s = 0;
1465 fields_used.accuracy_radius_s = 0;
1466 fields_used.time_zone_s = 0;
1467 fields_used.registered_country_geoname_id_s = 0;
1468 fields_used.represented_country_geoname_id_s = 0;
1469 fields_used.is_anonymous_proxy_s = 0;
1470 fields_used.is_satellite_provider_s = 0;
1471 fields_used.postal_code_s = 0;
1472 fields_used.latitude_s = 0;
1473 fields_used.longitude_s = 0;
1474 fields_used.continent_code_d = 0;
1475 fields_used.continent_name_d = 0;
1476 fields_used.country_iso_code_d = 0;
1477 fields_used.country_name_d = 0;
1478 fields_used.subdivision_1_iso_code_d = 0;
1479 fields_used.subdivision_1_name_d = 0;
1480 fields_used.subdivision_2_iso_code_d = 0;
1481 fields_used.subdivision_2_name_d = 0;
1482 fields_used.city_name_d = 0;
1483 fields_used.metro_code_d = 0;
1484 fields_used.accuracy_radius_d = 0;
1485 fields_used.time_zone_d = 0;
1486 fields_used.registered_country_geoname_id_d = 0;
1487 fields_used.represented_country_geoname_id_d = 0;
1488 fields_used.is_anonymous_proxy_d = 0;
1489 fields_used.is_satellite_provider_d = 0;
1490 fields_used.postal_code_d = 0;
1491 fields_used.latitude_d = 0;
1492 fields_used.longitude_d = 0;
1493
1494 /* initialize select_sum */
1495 select_sum.min_count = 0;
1496 select_sum.max_count = 0;
1497 select_sum.max_earliest = 0;
1498 select_sum.min_latest = 0;
1499
1500 while (fgets(buf, BUFSIZE, fd)) {
1501 if (opt.verbose >= VERBOSE_DEBUG)
1502 fprintf(stderr, "Input line is: %s", buf);
1503
1504 parse_reportdef(buf, linenum);
1505 linenum++;
1506 }
1507
1508 if (opt.mode == LOG_DETAIL && fields_used.sname == 0) {
1509 strcpy(keyname, "sname");
1510 strcpy(position, "99");
1511 fields = add_column(fields, keyname, position, 999);
1512 }
1513
1514 if (opt.verbose >= VERBOSE_INFO) {
1515 fprintf(stderr, "Number of columns: %u\n", column_count);
1516 }
1517
1518 if (opt.verbose >= VERBOSE_NOTICE) {
1519 col = fields;
1520 while (col != NULL) {
1521 fprintf(stderr, "COLUMNS: Key: %s; Field %i; Position: %i\n", col->keyname, col->field, col->position);
1522 col = col->next;
1523 }
1524 }
1525
1526 if (opt.verbose >= VERBOSE_INFO) {
1527 fprintf(stderr, "Number of criteria: %u\n", selection_count);
1528 }
1529
1530 if (opt.verbose >= VERBOSE_NOTICE) {
1531 sel = selection;
1532 while (sel != NULL) {
1533 in.s_addr = htonl(sel->in_addr);
1534 xstrncpy(addr, inet_ntoa(in), SHORTLEN);
1535 in.s_addr = htonl(sel->netmask);
1536 xstrncpy(mask, inet_ntoa(in), SHORTLEN);
1537 fprintf(stderr, "SELECTION: Key: %s; Field %i; Value: %lu Max value: %lu; Double: %.7g; Max double: %.7g; Svalue: %s; Family: %i; Addr: %s; Netmask: %s;"
1538 #if HAVE_INET_NTOP
1539 " In6_addr: %s; In6_bits: %u;"
1540 #endif
1541 " Invert: %i; Have Value: %i\n",
1542 sel->keyname, sel->field, sel->value, sel->max_value, sel->double_value, sel->max_double_value, sel->svalue, sel->family, addr, mask,
1543 #if HAVE_INET_NTOP
1544 inet_ntop(AF_INET6, sel->in6_addr.s6_addr, buf, INET6_ADDRSTRLEN), sel->in6_bits,
1545 #endif
1546 sel->invert, sel->have_value);
1547
1548 sel = sel->next;
1549 }
1550 if (select_sum.min_count !=0)
1551 fprintf(stderr, "SELECTION: Key: min_count; Value: %lu\n", select_sum.min_count);
1552 if (select_sum.max_count !=0)
1553 fprintf(stderr, "SELECTION: Key: max_count; Value: %lu\n", select_sum.max_count);
1554 if (select_sum.max_earliest !=0) {
1555 if (strftime((char *)&stime,SHORTLEN,"%c %Z",localtime((time_t *)&select_sum.max_earliest)))
1556 fprintf(stderr, "SELECTION: Key: max_earliest; Value: %lu; Svalue: %s\n", (unsigned long int)select_sum.max_earliest,(char *)&stime);
1557 }
1558 if (select_sum.min_latest !=0) {
1559 if (strftime((char *)&stime,SHORTLEN,"%c %Z",localtime((time_t *)&select_sum.min_latest)))
1560 fprintf(stderr, "SELECTION: Key: min_latest; Value: %lu; Svalue: %s\n", (unsigned long int)select_sum.min_latest,(char *)&stime);
1561 }
1562 }
1563
1564 if (opt.verbose >= VERBOSE_INFO) {
1565 fprintf(stderr, "Number of sorts: %u\n", sort_count);
1566 }
1567
1568 if (opt.verbose >= VERBOSE_NOTICE) {
1569 srt = sort;
1570 while (srt != NULL) {
1571 fprintf(stderr, "SORT: Key: %s; Field %i; Position: %i Order: %i\n",
1572 srt->keyname, srt->field, srt->position, srt->order);
1573 srt = srt->next;
1574 }
1575 }
1576
1577 if ((strcmp(reportdef, "-"))) {
1578 if(opt.verbose >= VERBOSE_WARNING)
1579 fprintf(stderr, "Done processing report definition file '%s'\n", name);
1580 } else {
1581 if(opt.verbose >= VERBOSE_WARNING)
1582 fprintf(stderr, "Done processing report definition from stdin\n");
1583 }
1584
1585 free(name);
1586
1587 retval = fclose(fd);
1588 if (retval == EOF) {
1589 perror("fclose");
1590 exit(EXIT_FAILURE);
1591 }
1592
1593 return EXIT_SUCCESS;
1594 }
1595