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
26 #include "jprocessor.h"
27 #include "jresolver.h"
31 jconfig_settings jconfig_Settings
;
33 static int parse_boolean(GScanner
*s
) {
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"))) {
39 return strcmp(s
->value
.v_identifier
, "off")?TRUE
:FALSE
;
42 static int parse_aggregation(GScanner
*s
) {
44 tt
= g_scanner_get_next_token(s
);
45 if (tt
!= G_TOKEN_IDENTIFIER
) {
48 return jutil_ParseAggregation(s
->value
.v_identifier
);
51 static int parse_resolvertype(GScanner
*s
) {
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
) {
69 tt
= g_scanner_get_next_token(s
);
70 if (tt
!= G_TOKEN_STRING
) {
73 if (jutil_String2Address(s
->value
.v_string
, dest
, af
)) {
79 static gboolean
parse_ip_with_netmask(GScanner
*s
, jbase_mutableaddress
*dest
, jbase_mutableaddress
*netmask
, int *af
) {
82 tt
= g_scanner_peek_next_token(s
);
83 if (tt
!= G_TOKEN_STRING
) {
86 if (jutil_String2AddressAndNetmask(s
->next_value
.v_string
, dest
, netmask
, af
)) {
87 g_scanner_get_next_token(s
);
90 if (!parse_ip(s
, dest
, af
)) {
93 if (!parse_ip(s
, netmask
, &oaf
) || oaf
!= *af
)
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
;
113 gboolean
jconfig_ParseFile(char *configFileName
) {
116 GHashTable
*variables
;
119 variables
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, g_free
);
121 if (!configFileName
) {
122 homeDir
= getenv("HOME");
124 configFileName
= ".jnettop";
126 configFileName
= g_new0(char, strlen(homeDir
) + 10);
127 sprintf(configFileName
, "%s/.jnettop", homeDir
);
131 f
= fopen(configFileName
, "r");
133 fprintf(stderr
, "Could not read/find config file %s: %s.\n", configFileName
, strerror(errno
));
137 s
= g_scanner_new(NULL
);
138 g_scanner_input_file(s
, fileno(f
));
139 while (!g_scanner_eof(s
)) {
144 tt
= g_scanner_get_next_token(s
);
145 if (tt
== G_TOKEN_EOF
) {
148 if (tt
!= G_TOKEN_IDENTIFIER
) {
149 fprintf(stderr
, "Parse error on line %d: identifier expected.\n", line
);
152 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "variable")) {
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
);
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
);
167 str
= g_string_new("");
168 for (c
=s
->value
.v_string
; *c
; c
++) {
170 char * variableValue
;
171 if (*c
== '$' && *(c
+1) == '{') {
172 rightBracket
= strchr(c
, '}');
175 fprintf(stderr
, "Wrong variable substitution on line %d!\n", line
);
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
);
184 g_string_append(str
, variableValue
);
187 g_string_append_c(str
, *c
);
190 g_hash_table_insert(variables
, variableName
, str
->str
);
191 g_string_free(str
, FALSE
);
194 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "rule")) {
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
);
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
);
209 str
= g_string_new("");
210 for (c
=s
->value
.v_string
; *c
; c
++) {
212 char * variableValue
;
213 if (*c
== '$' && *(c
+1) == '{') {
214 rightBracket
= strchr(c
, '}');
217 fprintf(stderr
, "Wrong variable substitution on line %d!\n", line
);
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
);
226 g_string_append(str
, variableValue
);
229 g_string_append_c(str
, *c
);
232 jconfig_AddBpfFilter(ruleName
, str
->str
);
233 g_string_free(str
, FALSE
);
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
);
242 if (jconfig_Settings
.deviceName
== NULL
)
243 jconfig_Settings
.deviceName
= g_strdup(s
->value
.v_string
);
246 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "promisc")) {
247 int val
= parse_boolean(s
);
249 fprintf(stderr
, "Parse error on line %d: expecting on or off value.\n", line
);
252 if (jconfig_Settings
.onoffPromisc
== -1)
253 jconfig_Settings
.onoffPromisc
= val
;
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
);
262 if (jconfig_Settings
.localAggregation
== AGG_UNKNOWN
)
263 jconfig_Settings
.localAggregation
= val
;
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
);
272 if (jconfig_Settings
.remoteAggregation
== AGG_UNKNOWN
)
273 jconfig_Settings
.remoteAggregation
= val
;
276 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "select_rule")) {
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
);
283 if (JCONFIG_BPFFILTERS_SELECTEDISNONE
) {
284 i
= jconfig_FindBpfFilterByName(s
->value
.v_string
);
286 fprintf(stderr
, "Parse error on line %d: rule %s not defined so far.\n", line
, s
->value
.v_string
);
289 JCONFIG_BPFFILTERS_SETSELECTEDFILTER(i
);
293 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "resolve")) {
294 int val
= parse_boolean(s
);
296 fprintf(stderr
, "Parse error on line %d: expecting on or off value.\n", line
);
299 if (jconfig_Settings
.onoffResolver
== -1)
300 jconfig_Settings
.onoffResolver
= val
;
302 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "resolve_rule")) {
304 jbase_mutableaddress mask
;
305 jbase_mutableaddress value
;
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
);
311 if ((resolvertype
= parse_resolvertype(s
)) == LOOKUPTYPE_UNKNOWN
) {
312 fprintf(stderr
, "Parse error on line %d: expecint resolver type.\n", line
);
315 switch (resolvertype
) {
316 case LOOKUPTYPE_NORMAL
:
317 jresolver_AddNormalLookup(af
, &mask
, &value
);
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
);
325 jresolver_AddExternalLookupScript(af
, &mask
, &value
, g_strdup(s
->value
.v_string
));
330 if (!g_ascii_strcasecmp(s
->value
.v_identifier
, "local_network")) {
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
);
339 jconfig_AddLocalNetwork(&value
, &mask
, af
);
344 g_hash_table_destroy(variables
);
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)
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)
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
) {
392 for (i
=0; i
<JCONFIG_BPFFILTERS_LEN
; i
++) {
393 if (!strcmp(JCONFIG_BPFFILTERS_GETNAME(i
), filterName
)) {
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(¤t
->network
, network
, sizeof(jbase_mutableaddress
));
404 memcpy(¤t
->netmask
, netmask
, sizeof(jbase_mutableaddress
));
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
;
418 if (jutil_IsInNetwork(network
, af
, ¤t
->network
, ¤t
->netmask
, current
->af
)) {
422 current
= current
->next
;
428 void jconfig_SelectDevice(const char *deviceName
) {
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
;
440 if (i
>= jdevice_DevicesCount
) {
441 jconfig_Settings
.device
= jdevice_CreateSingleDevice(jconfig_Settings
.deviceName
);