setting svn:exports
[jnettop.git] / jnettop / jconfig.c
blobb6be6d860dcca96c1b05dffc8af446bc43ab4819
1 /*
2 * jnettop, network online traffic visualiser
3 * Copyright (C) 2002-2005 Jakub Skopal
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * $Header$
23 #include "jbase.h"
24 #include "jutil.h"
25 #include "jcapture.h"
26 #include "jprocessor.h"
27 #include "jresolver.h"
28 #include "jconfig.h"
29 #include "jdevice.h"
31 jconfig_settings jconfig_Settings;
33 static int parse_boolean(GScanner *s) {
34 GTokenType tt;
35 tt = g_scanner_get_next_token(s);
36 if (tt != G_TOKEN_IDENTIFIER || (strcmp(s->value.v_identifier, "on") && strcmp(s->value.v_identifier,"off"))) {
37 return -1;
39 return strcmp(s->value.v_identifier, "off")?TRUE:FALSE;
42 static int parse_aggregation(GScanner *s) {
43 GTokenType tt;
44 tt = g_scanner_get_next_token(s);
45 if (tt != G_TOKEN_IDENTIFIER) {
46 return AGG_UNKNOWN;
48 return jutil_ParseAggregation(s->value.v_identifier);
51 static int parse_resolvertype(GScanner *s) {
52 GTokenType tt;
53 tt = g_scanner_get_next_token(s);
54 if (tt != G_TOKEN_IDENTIFIER) {
55 return LOOKUPTYPE_UNKNOWN;
57 if (strcmp(s->value.v_identifier, "normal") && strcmp(s->value.v_identifier, "external")) {
58 return LOOKUPTYPE_UNKNOWN;
60 switch (s->value.v_identifier[0]) {
61 case 'n': return LOOKUPTYPE_NORMAL;
62 case 'e': return LOOKUPTYPE_EXTERNAL;
64 return LOOKUPTYPE_UNKNOWN;
67 static gboolean parse_ip(GScanner *s, jbase_mutableaddress *dest, int *af) {
68 GTokenType tt;
69 tt = g_scanner_get_next_token(s);
70 if (tt != G_TOKEN_STRING) {
71 return FALSE;
73 if (jutil_String2Address(s->value.v_string, dest, af)) {
74 return TRUE;
76 return FALSE;
79 static gboolean parse_ip_with_netmask(GScanner *s, jbase_mutableaddress *dest, jbase_mutableaddress *netmask, int *af) {
80 int oaf;
81 GTokenType tt;
82 tt = g_scanner_peek_next_token(s);
83 if (tt != G_TOKEN_STRING) {
84 return FALSE;
86 if (jutil_String2AddressAndNetmask(s->next_value.v_string, dest, netmask, af)) {
87 g_scanner_get_next_token(s);
88 return TRUE;
90 if (!parse_ip(s, dest, af)) {
91 return FALSE;
93 if (!parse_ip(s, netmask, &oaf) || oaf != *af)
94 return FALSE;
95 return TRUE;
99 gboolean jconfig_Setup() {
100 jconfig_Settings.deviceName = NULL;
101 jconfig_Settings._bpfFilters = g_ptr_array_new();
102 jconfig_Settings.onoffContentFiltering = -1;
103 jconfig_Settings.onoffPromisc = -1;
104 jconfig_Settings.onoffResolver = -1;
105 jconfig_Settings.localAggregation = AGG_UNKNOWN;
106 jconfig_Settings.remoteAggregation = AGG_UNKNOWN;
107 jconfig_Settings._selectedBpfFilter = -1;
108 jconfig_Settings._adHocBpfFilter = NULL;
109 jconfig_Settings._networkMaskList = NULL;
110 return TRUE;
113 gboolean jconfig_ParseFile(char *configFileName) {
114 FILE *f;
115 GScanner *s;
116 GHashTable *variables;
117 char *homeDir;
119 variables = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
121 if (!configFileName) {
122 homeDir = getenv("HOME");
123 if (!homeDir) {
124 configFileName = ".jnettop";
125 } else {
126 configFileName = g_new0(char, strlen(homeDir) + 10);
127 sprintf(configFileName, "%s/.jnettop", homeDir);
131 f = fopen(configFileName, "r");
132 if (!f) {
133 fprintf(stderr, "Could not read/find config file %s: %s.\n", configFileName, strerror(errno));
134 return TRUE;
137 s = g_scanner_new(NULL);
138 g_scanner_input_file(s, fileno(f));
139 while (!g_scanner_eof(s)) {
140 GTokenType tt;
141 int line;
143 line = s->line;
144 tt = g_scanner_get_next_token(s);
145 if (tt == G_TOKEN_EOF) {
146 break;
148 if (tt != G_TOKEN_IDENTIFIER) {
149 fprintf(stderr, "Parse error on line %d: identifier expected.\n", line);
150 return FALSE;
152 if (!g_ascii_strcasecmp(s->value.v_identifier, "variable")) {
153 char * variableName;
154 char *c;
155 GString *str;
156 tt = g_scanner_get_next_token(s);
157 if (tt != G_TOKEN_STRING) {
158 fprintf(stderr, "Parse error on line %d: variable name as string expected.\n", line);
159 return FALSE;
161 variableName = g_strdup(s->value.v_string);
162 tt = g_scanner_get_next_token(s);
163 if (tt != G_TOKEN_STRING) {
164 fprintf(stderr, "Parse error on line %d: variable value as string expected.\n", line);
165 return FALSE;
167 str = g_string_new("");
168 for (c=s->value.v_string; *c; c++) {
169 char * rightBracket;
170 char * variableValue;
171 if (*c == '$' && *(c+1) == '{') {
172 rightBracket = strchr(c, '}');
173 c += 2;
174 if (!rightBracket) {
175 fprintf(stderr, "Wrong variable substitution on line %d!\n", line);
176 return FALSE;
178 *rightBracket = '\0';
179 variableValue = g_hash_table_lookup(variables, c);
180 if (!variableValue) {
181 fprintf(stderr, "Undefined variable %s on line %d!\n", c, line);
182 return FALSE;
184 g_string_append(str, variableValue);
185 c = rightBracket;
186 } else {
187 g_string_append_c(str, *c);
190 g_hash_table_insert(variables, variableName, str->str);
191 g_string_free(str, FALSE);
192 continue;
194 if (!g_ascii_strcasecmp(s->value.v_identifier, "rule")) {
195 char * ruleName;
196 char * c;
197 GString *str;
198 tt = g_scanner_get_next_token(s);
199 if (tt != G_TOKEN_STRING) {
200 fprintf(stderr, "Parse error on line %d: rule name as string expected.\n", line);
201 return FALSE;
203 ruleName = g_strdup(s->value.v_string);
204 tt = g_scanner_get_next_token(s);
205 if (tt != G_TOKEN_STRING) {
206 fprintf(stderr, "Parse error on line %d: rule expression as string expected.\n", line);
207 return FALSE;
209 str = g_string_new("");
210 for (c=s->value.v_string; *c; c++) {
211 char * rightBracket;
212 char * variableValue;
213 if (*c == '$' && *(c+1) == '{') {
214 rightBracket = strchr(c, '}');
215 c += 2;
216 if (!rightBracket) {
217 fprintf(stderr, "Wrong variable substitution on line %d!\n", line);
218 return FALSE;
220 *rightBracket = '\0';
221 variableValue = g_hash_table_lookup(variables, c);
222 if (!variableValue) {
223 fprintf(stderr, "Undefined variable %s on line %d!\n", c, line);
224 return FALSE;
226 g_string_append(str, variableValue);
227 c = rightBracket;
228 } else {
229 g_string_append_c(str, *c);
232 jconfig_AddBpfFilter(ruleName, str->str);
233 g_string_free(str, FALSE);
234 continue;
236 if (!g_ascii_strcasecmp(s->value.v_identifier, "interface")) {
237 tt = g_scanner_get_next_token(s);
238 if (tt != G_TOKEN_STRING) {
239 fprintf(stderr, "Parse error on line %d: interface name as string expected.\n", line);
240 return FALSE;
242 if (jconfig_Settings.deviceName == NULL)
243 jconfig_Settings.deviceName = g_strdup(s->value.v_string);
244 continue;
246 if (!g_ascii_strcasecmp(s->value.v_identifier, "promisc")) {
247 int val = parse_boolean(s);
248 if (val == -1) {
249 fprintf(stderr, "Parse error on line %d: expecting on or off value.\n", line);
250 return FALSE;
252 if (jconfig_Settings.onoffPromisc == -1)
253 jconfig_Settings.onoffPromisc = val;
254 continue;
256 if (!g_ascii_strcasecmp(s->value.v_identifier, "local_aggregation")) {
257 int val = parse_aggregation(s);
258 if (val == AGG_UNKNOWN) {
259 fprintf(stderr, "Parse error on line %d: expecting none or host or port.\n", line);
260 return FALSE;
262 if (jconfig_Settings.localAggregation == AGG_UNKNOWN)
263 jconfig_Settings.localAggregation = val;
264 continue;
266 if (!g_ascii_strcasecmp(s->value.v_identifier, "remote_aggregation")) {
267 int val = parse_aggregation(s);
268 if (val == AGG_UNKNOWN) {
269 fprintf(stderr, "Parse error on line %d: expecting none or host or port.\n", line);
270 return FALSE;
272 if (jconfig_Settings.remoteAggregation == AGG_UNKNOWN)
273 jconfig_Settings.remoteAggregation = val;
274 continue;
276 if (!g_ascii_strcasecmp(s->value.v_identifier, "select_rule")) {
277 int i;
278 tt = g_scanner_get_next_token(s);
279 if (tt != G_TOKEN_STRING) {
280 fprintf(stderr, "Parse error on line %d: rule name as string expected.\n", line);
281 return FALSE;
283 if (JCONFIG_BPFFILTERS_SELECTEDISNONE) {
284 i = jconfig_FindBpfFilterByName(s->value.v_string);
285 if (i==-1) {
286 fprintf(stderr, "Parse error on line %d: rule %s not defined so far.\n", line, s->value.v_string);
287 return FALSE;
289 JCONFIG_BPFFILTERS_SETSELECTEDFILTER(i);
291 continue;
293 if (!g_ascii_strcasecmp(s->value.v_identifier, "resolve")) {
294 int val = parse_boolean(s);
295 if (val == -1) {
296 fprintf(stderr, "Parse error on line %d: expecting on or off value.\n", line);
297 return FALSE;
299 if (jconfig_Settings.onoffResolver == -1)
300 jconfig_Settings.onoffResolver = val;
302 if (!g_ascii_strcasecmp(s->value.v_identifier, "resolve_rule")) {
303 int af;
304 jbase_mutableaddress mask;
305 jbase_mutableaddress value;
306 int resolvertype;
307 if (!parse_ip_with_netmask(s, &value, &mask, &af)) {
308 fprintf(stderr, "Parse error on line %d: expecting ip address and mask.\n", line);
309 return FALSE;
311 if ((resolvertype = parse_resolvertype(s)) == LOOKUPTYPE_UNKNOWN) {
312 fprintf(stderr, "Parse error on line %d: expecint resolver type.\n", line);
313 return FALSE;
315 switch (resolvertype) {
316 case LOOKUPTYPE_NORMAL:
317 jresolver_AddNormalLookup(af, &mask, &value);
318 break;
319 case LOOKUPTYPE_EXTERNAL:
320 tt = g_scanner_get_next_token(s);
321 if (tt != G_TOKEN_STRING) {
322 fprintf(stderr, "Parse error on line %d: expecting external resolver path.\n", line);
323 return FALSE;
325 jresolver_AddExternalLookupScript(af, &mask, &value, g_strdup(s->value.v_string));
326 break;
328 continue;
330 if (!g_ascii_strcasecmp(s->value.v_identifier, "local_network")) {
331 int af;
332 jbase_mutableaddress mask;
333 jbase_mutableaddress value;
334 if (!parse_ip_with_netmask(s, &value, &mask, &af)) {
335 fprintf(stderr, "Parse error on line %d: expecting ip address and mask.\n", line);
336 return FALSE;
339 jconfig_AddLocalNetwork(&value, &mask, af);
340 continue;
344 g_hash_table_destroy(variables);
345 return TRUE;
348 void jconfig_SetDefaults() {
349 if (jconfig_Settings.onoffContentFiltering == -1)
350 jconfig_Settings.onoffContentFiltering = TRUE;
351 if (jconfig_Settings.onoffPromisc == -1)
352 jconfig_Settings.onoffPromisc = FALSE;
353 if (jconfig_Settings.onoffResolver == -1)
354 jconfig_Settings.onoffResolver = TRUE;
355 if (jconfig_Settings.localAggregation == AGG_UNKNOWN)
356 jconfig_Settings.localAggregation = AGG_NONE;
357 if (jconfig_Settings.remoteAggregation == AGG_UNKNOWN)
358 jconfig_Settings.remoteAggregation = AGG_NONE;
361 void jconfig_ConfigureModules() {
362 jcapture_SetPromisc(jconfig_Settings.onoffPromisc);
363 jprocessor_SetLocalAggregation(jconfig_Settings.localAggregation);
364 jprocessor_SetRemoteAggregation(jconfig_Settings.remoteAggregation);
365 jprocessor_SetContentFiltering(jconfig_Settings.onoffContentFiltering);
366 jresolver_SetEnabled(jconfig_Settings.onoffResolver);
369 const char * jconfig_GetSelectedBpfFilterText() {
370 if (jconfig_Settings._selectedBpfFilter == -2 && jconfig_Settings._adHocBpfFilter)
371 return jconfig_Settings._adHocBpfFilter;
372 if (jconfig_Settings._selectedBpfFilter <= -1)
373 return NULL;
374 return (const char *) g_ptr_array_index(jconfig_Settings._bpfFilters, jconfig_Settings._selectedBpfFilter*2+1);
377 const char * jconfig_GetSelectedBpfFilterName() {
378 if (jconfig_Settings._selectedBpfFilter == -2 && jconfig_Settings._adHocBpfFilter)
379 return jconfig_Settings._adHocBpfFilter;
380 if (jconfig_Settings._selectedBpfFilter <= -1)
381 return "none";
382 return (const char *) g_ptr_array_index(jconfig_Settings._bpfFilters, jconfig_Settings._selectedBpfFilter*2);
385 void jconfig_AddBpfFilter(char *filterName, char *filterText) {
386 g_ptr_array_add(jconfig_Settings._bpfFilters, filterName);
387 g_ptr_array_add(jconfig_Settings._bpfFilters, filterText);
390 int jconfig_FindBpfFilterByName(char *filterName) {
391 int i;
392 for (i=0; i<JCONFIG_BPFFILTERS_LEN; i++) {
393 if (!strcmp(JCONFIG_BPFFILTERS_GETNAME(i), filterName)) {
394 return i;
397 return -1;
400 void jconfig_AddLocalNetwork(const jbase_mutableaddress *network, const jbase_mutableaddress *netmask, int af) {
401 jbase_network_mask_list * current = NULL;
402 current = g_new0(jbase_network_mask_list, 1);
403 memcpy(&current->network, network, sizeof(jbase_mutableaddress));
404 memcpy(&current->netmask, netmask, sizeof(jbase_mutableaddress));
405 current->af = af;
406 current->next = jconfig_Settings._networkMaskList;
407 jconfig_Settings._networkMaskList = current;
410 int jconfig_FindMatchingLocalNetworkIndex(const jbase_mutableaddress *network, int af) {
411 jbase_network_mask_list * current;
412 int priority = 64000;
414 current = jconfig_Settings._networkMaskList;
415 while (current) {
416 priority --;
418 if (jutil_IsInNetwork(network, af, &current->network, &current->netmask, current->af)) {
419 return priority;
422 current = current->next;
425 return 64000;
428 void jconfig_SelectDevice(const char *deviceName) {
429 int i;
431 jconfig_Settings.deviceName = deviceName;
433 for (i=0; i<jdevice_DevicesCount; i++) {
434 if (!strcmp(jdevice_Devices[i].name, jconfig_Settings.deviceName)) {
435 jconfig_Settings.device = jdevice_Devices + i;
436 break;
440 if (i >= jdevice_DevicesCount) {
441 jconfig_Settings.device = jdevice_CreateSingleDevice(jconfig_Settings.deviceName);