1 /* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
2 /* gnome-netinfo - A GUI Interface for network utilities
3 * Copyright (C) 2002 by German Poo-Caaman~o
4 *
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.
9 *
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.
14 *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <strings.h>
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
27 #include "netstat.h"
28 #include "utils.h"
29
30 static gint strip_protocol_line (gchar * line, netstat_protocol_data *data);
31 void netstat_create_protocol_model (GtkTreeView *widget);
32 void netstat_protocol_tree_insert (GtkTreeView *widget, gchar *line);
33
34 static gint strip_route_line (gchar * line, netstat_route_data *data);
35 void netstat_route_tree_insert (GtkTreeView *widget, gchar *line);
36 void netstat_create_route_model (GtkTreeView *widget);
37
38 void netstat_multicast_tree_insert (GtkTreeView *widget, gchar *line);
39 static gint strip_multicast_line (gchar * line, netstat_multicast_data *data);
40 void netstat_create_multicast_model (GtkTreeView *widget);
41
42 static NetstatOption netstat_get_active_option2 (Netinfo * netinfo);
43 static gchar * netstat_get_active_option (Netinfo * netinfo);
44
45 static GtkTreeModel *protocol_model, *route_model, *multicast_model;
46
47 void clean_gtk_tree_view (GtkTreeView *widget);
48
49 /* Check the ToggleButton active to show the GtkTreeView with
50 * the right GtkTreeModel
51 */
52 void
on_protocol_button_toggled(GtkToggleButton * togglebutton,gpointer user_data)53 on_protocol_button_toggled (GtkToggleButton *togglebutton, gpointer user_data)
54 {
55 Netinfo *netinfo = user_data;
56 /* GtkWidget *parent, *child, *widget; */
57
58 g_return_if_fail (GTK_IS_TREE_VIEW (netinfo->output));
59
60 /*
61 widget = GTK_TREE_VIEW (netinfo->output);
62
63 parent = gtk_widget_get_parent (GTK_WIDGET (widget));
64 g_print ("name: %s\n", gtk_widget_get_name (parent));
65 child = gtk_bin_get_child (GTK_BIN (parent));
66
67 g_object_ref (child);
68
69 gtk_container_remove (GTK_CONTAINER (parent), child);
70 */
71 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->routing))) {
72 g_print ("routing set\n");
73 /*gtk_container_add (GTK_CONTAINER (parent), route_tree);
74 gtk_tree_view_set_model (widget, route_model); */
75 }
76 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->protocol))) {
77 g_print ("protocol\n");
78 /* gtk_container_add (GTK_CONTAINER (parent), protocol_tree);
79 gtk_tree_view_set_model (widget, protocol_model); */
80 }
81 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->multicast))) {
82 g_print ("multicast\n");
83 /* gtk_container_add (GTK_CONTAINER (parent), multicast_tree);
84 gtk_tree_view_set_model (widget, multicast_model); */
85 }
86
87 /* g_object_unref (child); */
88 }
89
90 static NetstatOption
netstat_get_active_option2(Netinfo * netinfo)91 netstat_get_active_option2 (Netinfo * netinfo)
92 {
93 NetstatOption option = NONE;
94
95 g_return_val_if_fail (netinfo != NULL, ROUTE);
96
97 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->routing))) {
98 option = ROUTE;
99 }
100 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->protocol))) {
101 option = PROTOCOL;
102 }
103 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->multicast))) {
104 option = MULTICAST;
105 }
106 return option;
107 }
108
109 static gchar *
netstat_get_active_option(Netinfo * netinfo)110 netstat_get_active_option (Netinfo * netinfo)
111 {
112 gchar *option = NULL;
113
114 g_return_val_if_fail (netinfo != NULL, NULL);
115
116 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->routing))) {
117 #if defined (__OpenBSD__) || defined (__FreeBSD__)
118 if (netinfo_is_ipv6_enable ()) {
119 option = g_strdup ("-rn");
120 } else {
121 option = g_strdup ("-rn -f inet");
122 }
123 #else
124 /* Works for Solaris and Linux */
125 if (netinfo_is_ipv6_enable ()) {
126 option = g_strdup ("-rn -A inet -A inet6");
127 } else {
128 option = g_strdup ("-rn -A inet");
129 }
130 #endif
131
132 if (netinfo->stbar_text)
133 g_free (netinfo->stbar_text);
134 netinfo->stbar_text = g_strdup (_("Getting routing table"));
135 }
136 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->protocol))) {
137 /* Only works for Solaris */
138 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
139 option = g_strdup ("-a -f inet -ln");
140 #else
141 if (netinfo_is_ipv6_enable ()) {
142 option = g_strdup ("-A inet -A inet6 -ln");
143 } else {
144 option = g_strdup ("-A inet -ln");
145 }
146
147 if (netinfo->stbar_text)
148 g_free (netinfo->stbar_text);
149 netinfo->stbar_text = g_strdup (_("Getting active Internet connections"));
150 #endif
151 }
152 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (netinfo->multicast))) {
153 /* It works for Solaris and Linux */
154 option = g_strdup ("-g");
155
156 if (netinfo->stbar_text)
157 g_free (netinfo->stbar_text);
158 netinfo->stbar_text = g_strdup (_("Getting group memberships"));
159 }
160 return option;
161 }
162
163 void
netstat_stop(Netinfo * netinfo)164 netstat_stop (Netinfo * netinfo)
165 {
166 g_return_if_fail (netinfo != NULL);
167
168 netinfo_stop_process_command (netinfo);
169 }
170
171 void
netstat_do(Netinfo * netinfo)172 netstat_do (Netinfo * netinfo)
173 {
174 gboolean toggle;
175 gchar *command = NULL;
176 gchar *option = NULL;
177 gchar *program = NULL;
178 GtkTreeModel *model;
179 GtkWidget *parent;
180 NetstatOption noption;
181
182 g_return_if_fail (netinfo != NULL);
183
184 toggle = netinfo->toggle;
185 option = netstat_get_active_option (netinfo);
186 noption = netstat_get_active_option2 (netinfo);
187
188 if (noption == ROUTE || noption == PROTOCOL) {
189 netinfo->toggle = FALSE;
190 }
191
192 model = gtk_tree_view_get_model (GTK_TREE_VIEW (netinfo->output));
193 if (GTK_IS_LIST_STORE (model)) {
194 gtk_list_store_clear (GTK_LIST_STORE (model));
195 }
196
197 parent = gtk_widget_get_toplevel (netinfo->output);
198
199 program = util_find_program_dialog ("netstat", parent);
200
201 if (program != NULL) {
202 command =
203 g_strdup_printf ("%s netstat %s", program, option);
204
205 g_strfreev (netinfo->command_line);
206 netinfo->command_line = g_strsplit (command, " ", -1);
207
208 netinfo_process_command (netinfo);
209 }
210
211 /* Restore previous state */
212 netinfo->toggle = toggle;
213
214 g_free (command);
215 g_free (option);
216 g_free (program);
217 }
218
219 /* Process each line from netstat command */
220 void
netstat_foreach(Netinfo * netinfo,gchar * line,gsize len,gpointer user_data)221 netstat_foreach (Netinfo * netinfo, gchar * line, gsize len, gpointer user_data)
222 {
223 gchar *text_utf8;
224 gsize bytes_written;
225 GtkTextBuffer *buffer = NULL;
226 GtkTextIter iter;
227
228 g_return_if_fail (netinfo != NULL);
229 /*g_return_if_fail (line != NULL);*/
230
231 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (netinfo->output));
232 gtk_text_buffer_get_end_iter (buffer, &iter);
233
234 #ifdef DEBUG
235 if (netstat_get_active_option2 (netinfo) == PROTOCOL) {
236 netstat_protocol_data data;
237 gint count;
238
239 count = strip_protocol_line (line, &data);
240 if (count == 7 || count == 8) {
241
242 g_print ("%s\t%s:%s\t%s\n", data.protocol,
243 data.ip_src, data.port_src, data.state);
244 }
245 }
246 #endif /* DEBUG */
247
248 if (len > 0) {
249 text_utf8 = g_locale_to_utf8 (line, len,
250 NULL, &bytes_written,
251 NULL);
252
253 gtk_text_buffer_insert
254 (GTK_TEXT_BUFFER (buffer), &iter, text_utf8,
255 bytes_written);
256 g_free (text_utf8);
257 }
258 }
259
260 /* Collect data from netstat command and insert them in a GtkTreeView.
261
262 Basically it consist on receive each line, divide it in fields
263 and insert each value in a tree if belong. The function strip_line
264 divide the lines and return the number of fields. To distinguish
265 header and data from the output is useful to know then right number
266 of fields.
267
268 It could be avoid with a helper with two options: with/without
269 headers. To execute on a shell or just to process its output as
270 this program.
271 */
272 void
netstat_foreach_with_tree(Netinfo * netinfo,gchar * line,gint len,gpointer user_data)273 netstat_foreach_with_tree (Netinfo * netinfo, gchar * line, gint len,
274 gpointer user_data)
275 {
276 GtkTreeView *widget;
277
278 g_return_if_fail (netinfo != NULL);
279
280 widget = (GTK_TREE_VIEW (netinfo->output));
281
282 if (len > 0) { /* there are data to show */
283 g_return_if_fail (line != NULL);
284 switch (netstat_get_active_option2 (netinfo)) {
285 case PROTOCOL:
286 netstat_protocol_tree_insert (widget, line);
287 break;
288 case ROUTE:
289 netstat_route_tree_insert (widget, line);
290 break;
291 case MULTICAST:
292 netstat_multicast_tree_insert (widget, line);
293 break;
294 case NONE:
295 default:
296 break;
297 }
298 }
299 }
300
301 /* PROTOCOL */
302 void
netstat_protocol_tree_insert(GtkTreeView * widget,gchar * line)303 netstat_protocol_tree_insert (GtkTreeView *widget, gchar *line)
304 {
305 GtkTreeIter iter, sibling;
306 /*GList *columns;*/
307 GtkTreePath *path;
308 GtkTreeModel *model;
309 gint count;
310 netstat_protocol_data data;
311
312 g_return_if_fail (GTK_IS_TREE_VIEW (widget));
313 g_return_if_fail (line != NULL);
314
315 count = strip_protocol_line (line, &data);
316 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
317 if (count == 5 || count == 6 || count == 9 || count == 10) {
318 #else
319 if (count == 5 || count == 6) {
320 #endif
321 #ifdef DEBUG
322 g_print ("%s\t%s:%s\t%s\n", data.protocol,
323 data.ip_src, data.port_src, data.state);
324 #endif /* DEBUG */
325
326 /* Creation of GtkTreeView */
327 gtk_tree_view_set_rules_hint (widget, TRUE);
328 /* columns = gtk_tree_view_get_columns (widget);
329
330 if (g_list_length (columns) == 0) {
331 model = netstat_create_protocol_model (widget);
332 gtk_tree_view_set_model (widget, model);
333 }
334 g_list_free (columns);*/
335
336 model = gtk_tree_view_get_model (widget);
337
338 if (protocol_model == NULL || protocol_model != model) {
339 clean_gtk_tree_view (widget);
340
341 protocol_model = GTK_TREE_MODEL (gtk_list_store_new
342 (4,
343 G_TYPE_STRING,
344 G_TYPE_STRING,
345 G_TYPE_STRING,
346 G_TYPE_STRING));
347 netstat_create_protocol_model (widget);
348
349 gtk_tree_view_set_model (widget, protocol_model);
350 }
351
352 model = gtk_tree_view_get_model (widget);
353
354 gtk_tree_view_get_cursor (widget, &path, NULL);
355
356 if (path != NULL) {
357 gtk_tree_model_get_iter (model, &sibling, path);
358 gtk_list_store_insert_after (GTK_LIST_STORE
359 (model),
360 &iter,
361 &sibling);
362 } else {
363 gtk_list_store_append (GTK_LIST_STORE
364 (model), &iter);
365 }
366
367 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
368 0, data.protocol,
369 1, data.ip_src,
370 2, data.port_src,
371 3, data.state, -1);
372
373 gtk_tree_view_set_model (widget, model);
374 path = gtk_tree_model_get_path (model, &iter);
375 gtk_tree_view_set_cursor (widget, path, NULL, FALSE);
376 gtk_tree_path_free (path);
377 }
378 }
379
380 static gint
381 strip_protocol_line (gchar * line, netstat_protocol_data *data)
382 {
383 gint count = 0;
384 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
385 gint a1, a2, a3, a4;
386 gchar s9[30];
387 #else
388 gchar s6[30], laddr[50];
389 gchar *port;
390 #endif
391 gint n2, n3;
392
393 /*line = g_strdelimit (line, ":", ' ');*/
394
395 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
396 line = g_strdelimit (line, ":", ' ');
397
398 count = sscanf (line, NETSTAT_PROTOCOL_FORMAT,
399 data->protocol, &n2, &n3,
400 &a1, &a2, &a3, &a4, data->port_src,
401 s9, data->state);
402 g_snprintf (data->ip_src, 30, "%d.%d.%d.%d", a1, a2, a3, a4);
403
404 if (count == 9) {
405 bzero (&(data)->state, 30);
406 }
407
408 if (count == 3) {
409 /* Handle the *.* entries. */
410 gchar s5[30];
411 count = sscanf (line, ALT_NETSTAT_PROTOCOL_FORMAT,
412 data->protocol, &n2, &n3,
413 data->port_src, s5,
414 data->state);
415 g_snprintf (data->ip_src, 30, "*");
416
417 if (count == 5) {
418 bzero (&(data)->state, 30);
419 }
420 }
421
422 #else
423 /*count = sscanf (line, NETSTAT_PROTOCOL_FORMAT,
424 data->protocol, &n2, &n3,
425 data->ip_src, data->port_src,
426 s6, s7, data->state);
427
428 if (count == 7) {
429 bzero (&(data)->state, 30);
430 }*/
431 count = sscanf (line, NETSTAT_PROTOCOL_FORMAT,
432 data->protocol, &n2, &n3,
433 laddr, s6, data->state);
434
435 port = g_strrstr (laddr, ":");
436
437 if (port != NULL) {
438 g_strlcpy (data->ip_src, laddr, 50 * sizeof (gchar));
439 data->ip_src[strlen (laddr) - strlen (port)] = '\0';
440 port ++;
441 g_strlcpy (data->port_src, port, 30 * sizeof (gchar));
442 }
443
444 if (count == 5) {
445 bzero (&(data)->state, 30);
446 }
447 #endif
448
449 return count;
450 }
451
452 void
453 netstat_create_protocol_model (GtkTreeView *widget)
454 {
455 GtkCellRenderer *renderer;
456 GtkTreeViewColumn *column;
457
458 /*clean_gtk_tree_view (widget);*/
459
460 renderer = gtk_cell_renderer_text_new ();
461 /* Transport Protocol that runs over */
462 column =
463 gtk_tree_view_column_new_with_attributes
464 (_("Protocol"), renderer, "text", 0, NULL);
465 gtk_tree_view_append_column (widget, column);
466
467 renderer = gtk_cell_renderer_text_new ();
468 /* IP address where to accept connections */
469 column =
470 gtk_tree_view_column_new_with_attributes
471 (_("IP Source"), renderer, "text", 1, NULL);
472 gtk_tree_view_column_set_alignment (column, 0.5);
473 gtk_tree_view_append_column (widget, column);
474
475 renderer = gtk_cell_renderer_text_new ();
476 /* Number of port where the service is listening */
477 column =
478 gtk_tree_view_column_new_with_attributes
479 (_("Port/Service"), renderer, "text", 2, NULL);
480 g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
481 gtk_tree_view_append_column (widget, column);
482
483 renderer = gtk_cell_renderer_text_new ();
484 /* State of the service (commonly LISTEN) */
485 column =
486 gtk_tree_view_column_new_with_attributes
487 (_("State"), renderer, "text", 3, NULL);
488 gtk_tree_view_append_column (widget, column);
489
490 /* return model;*/
491 }
492 /* END PROTOCOL */
493
494 /* ROUTE */
495 void
496 netstat_route_tree_insert (GtkTreeView *widget, gchar *line)
497 {
498 GtkTreeIter iter, sibling;
499 /*GList *columns;*/
500 GtkTreePath *path;
501 GtkTreeModel *model;
502 gint count;
503 netstat_route_data data;
504
505 g_return_if_fail (GTK_IS_TREE_VIEW (widget));
506 g_return_if_fail (line != NULL);
507
508 count = strip_route_line (line, &data);
509 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__DragonFly__)
510 if (count == 6) {
511 #elif defined(__OpenBSD__)
512 if (count == 8) {
513 #else
514 if ((count == 8) || (count == 7)) {
515 #endif
516 #ifdef DEBUG
517 g_print ("%s\t%s:%s\t%d\t%s\n", data.destination,
518 data.gateway, data.netmask, data.metric,
519 data.iface);
520 #endif /* DEBUG */
521
522 /* Creation of GtkTreeView */
523 gtk_tree_view_set_rules_hint (widget, TRUE);
524 /* columns = gtk_tree_view_get_columns (widget);
525
526 if (g_list_length (columns) == 0) {
527 model = netstat_create_route_model (widget);
528 gtk_tree_view_set_model (widget, model);
529 }
530 g_list_free (columns);*/
531
532 model = gtk_tree_view_get_model (widget);
533
534 if (route_model == NULL || route_model != model) {
535 clean_gtk_tree_view (widget);
536
537 route_model = GTK_TREE_MODEL (gtk_list_store_new
538 (4,
539 G_TYPE_STRING,
540 G_TYPE_STRING,
541 G_TYPE_STRING,
542 G_TYPE_STRING));
543 netstat_create_route_model (widget);
544
545 gtk_tree_view_set_model (widget, route_model);
546 }
547
548 model = gtk_tree_view_get_model (widget);
549
550 gtk_tree_view_get_cursor (widget, &path, NULL);
551
552 if (path != NULL) {
553 gtk_tree_model_get_iter (model, &sibling, path);
554 gtk_list_store_insert_after (GTK_LIST_STORE
555 (model),
556 &iter,
557 &sibling);
558 gtk_tree_path_free (path);
559 } else {
560 gtk_list_store_append (GTK_LIST_STORE
561 (model), &iter);
562 }
563
564 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
565 0, data.destination,
566 1, data.gateway,
567 2, data.netmask,
568 3, data.iface, -1);
569
570 gtk_tree_view_set_model (widget, model);
571 path = gtk_tree_model_get_path (model, &iter);
572 gtk_tree_view_set_cursor (widget, path, NULL, FALSE);
573 gtk_tree_path_free (path);
574 }
575 }
576
577 static gint
578 strip_route_line (gchar * line, netstat_route_data *data)
579 {
580 gint count = 0;
581 gchar flags[30];
582 gint ref, use;
583 #if !defined (__FreeBSD__) && !defined(__OpenBSD__)
584 gchar dest[50];
585 gchar **items;
586 #endif
587 #if defined(__OpenBSD__)
588 gint mtu, prio;
589 #endif
590
591 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__DragonFly__)
592 count = sscanf (line, NETSTAT_ROUTE_FORMAT,
593 data->destination,
594 data->gateway, flags,
595 &ref, &use, data->iface);
596 #elif defined(__OpenBSD__)
597 count = sscanf (line, NETSTAT_ROUTE_FORMAT,
598 data->destination,
599 data->gateway, flags,
600 &ref, &use, &mtu, &prio,
601 data->iface);
602 #else
603 count = sscanf (line, NETSTAT_ROUTE_FORMAT,
604 data->destination,
605 data->gateway, data->netmask,
606 flags, &(data)->metric, &ref, &use,
607 data->iface);
608
609 if (count == 6) {
610 count = sscanf (line, NETSTAT_ROUTE6_FORMAT,
611 dest, data->netmask,
612 flags, &(data)->metric,
613 &ref, &use, data->iface);
614
615 items = NULL;
616
617 items = g_strsplit (dest, "/", 2);
618 if (items != NULL) {
619 g_strlcpy (data->destination, items[0], 50 * sizeof (gchar));
620 g_strlcpy (data->netmask, items[1], 50 * sizeof (gchar));
621
622 g_strfreev (items);
623 }
624 }
625
626 #endif
627 return count;
628 }
629
630 void
631 netstat_create_route_model (GtkTreeView *widget)
632 {
633 GtkCellRenderer *renderer;
634 GtkTreeViewColumn *column;
635
636 renderer = gtk_cell_renderer_text_new ();
637 column =
638 gtk_tree_view_column_new_with_attributes
639 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
640 (_("Destination/Prefix"), renderer, "text", 0, NULL);
641 #else
642 (_("Destination"), renderer, "text", 0, NULL);
643 #endif
644 gtk_tree_view_append_column (widget, column);
645
646 renderer = gtk_cell_renderer_text_new ();
647 column =
648 gtk_tree_view_column_new_with_attributes
649 (_("Gateway"), renderer, "text", 1, NULL);
650 gtk_tree_view_column_set_alignment (column, 0.5);
651 gtk_tree_view_append_column (widget, column);
652
653 #if ! (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)) || defined(__NetBSD__) || defined(__DragonFly__)
654 renderer = gtk_cell_renderer_text_new ();
655 column =
656 gtk_tree_view_column_new_with_attributes
657 (_("Netmask"), renderer, "text", 2, NULL);
658
659 gtk_tree_view_append_column (widget, column);
660 #endif
661
662 renderer = gtk_cell_renderer_text_new ();
663 column =
664 gtk_tree_view_column_new_with_attributes
665 (_("Interface"), renderer, "text", 3, NULL);
666 gtk_tree_view_append_column (widget, column);
667 }
668 /* END ROUTE */
669
670 /* MULTICAST */
671 void
672 netstat_multicast_tree_insert (GtkTreeView *widget, gchar *line)
673 {
674 GtkTreeIter iter, sibling;
675 GtkTreePath *path;
676 GtkTreeModel *model;
677 gint count;
678 netstat_multicast_data data;
679
680 g_return_if_fail (GTK_IS_TREE_VIEW (widget));
681 g_return_if_fail (line != NULL);
682
683 count = strip_multicast_line (line, &data);
684
685 if (count == 3) {
686 #ifdef DEBUG
687 g_print ("%s\t%s\t%s\n", data.iface,
688 data.members, data.group);
689 #endif /* DEBUG */
690
691 /* Creation of GtkTreeView */
692
693 /*columns = gtk_tree_view_get_columns (widget);
694
695 if (g_list_length (columns) == 0) {
696 model = netstat_create_multicast_model (widget);
697 gtk_tree_view_set_model (widget, model);
698 }
699 g_list_free (columns);*/
700
701 model = gtk_tree_view_get_model (widget);
702
703 if (multicast_model == NULL || multicast_model != model) {
704 clean_gtk_tree_view (widget);
705
706 multicast_model = GTK_TREE_MODEL (gtk_list_store_new
707 (3,
708 G_TYPE_STRING,
709 G_TYPE_STRING,
710 G_TYPE_STRING));
711 netstat_create_multicast_model (widget);
712
713 gtk_tree_view_set_model (widget, multicast_model);
714 }
715
716 model = gtk_tree_view_get_model (widget);
717
718 gtk_tree_view_set_rules_hint (widget, TRUE);
719
720 gtk_tree_view_get_cursor (widget, &path, NULL);
721
722 if (path != NULL) {
723 gtk_tree_model_get_iter (model, &sibling, path);
724 gtk_list_store_insert_after (GTK_LIST_STORE
725 (model),
726 &iter,
727 &sibling);
728 gtk_tree_path_free (path);
729 } else {
730 gtk_list_store_append (GTK_LIST_STORE
731 (model), &iter);
732 }
733
734 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
735 0, data.iface,
736 1, data.members,
737 2, data.group, -1);
738
739 gtk_tree_view_set_model (widget, model);
740 path = gtk_tree_model_get_path (model, &iter);
741 gtk_tree_view_set_cursor (widget, path, NULL, FALSE);
742 gtk_tree_path_free (path);
743 }
744 }
745
746 static gint
747 strip_multicast_line (gchar * line, netstat_multicast_data *data)
748 {
749 gint count = 0;
750 gint members;
751
752 count = sscanf (line, NETSTAT_MULTICAST_FORMAT,
753 data->iface,
754 &members, data->group);
755
756 g_snprintf ((data)->members, 30, "%d", members);
757
758 return count;
759 }
760
761 void
762 netstat_create_multicast_model (GtkTreeView *widget)
763 {
764 GtkCellRenderer *renderer;
765 GtkTreeViewColumn *column;
766
767 renderer = gtk_cell_renderer_text_new ();
768 /* Interface of multicast group associated */
769 column =
770 gtk_tree_view_column_new_with_attributes
771 (_("Interface"), renderer, "text", 0, NULL);
772 gtk_tree_view_append_column (widget, column);
773
774 renderer = gtk_cell_renderer_text_new ();
775 /* Members of multicast group */
776 column =
777 gtk_tree_view_column_new_with_attributes
778 (_("Member"), renderer, "text", 1, NULL);
779 g_object_set (G_OBJECT (renderer), "xalign", 0.5, NULL);
780 gtk_tree_view_append_column (widget, column);
781
782 renderer = gtk_cell_renderer_text_new ();
783 /* Multicast group */
784 column =
785 gtk_tree_view_column_new_with_attributes
786 (_("Group"), renderer, "text", 2, NULL);
787 gtk_tree_view_append_column (widget, column);
788 }
789 /* END MULTICAST */
790
791 /* Remove all columns from a GtkTreeView */
792 void
793 clean_gtk_tree_view (GtkTreeView *widget)
794 {
795 GList *columns;
796 gint n, i;
797 GtkTreeViewColumn *column;
798
799 columns = gtk_tree_view_get_columns (widget);
800
801 n = g_list_length (columns);
802
803 for (i = n; i > 0; i--) {
804 column = gtk_tree_view_get_column (widget, i-1);
805 gtk_tree_view_remove_column (widget, column);
806 }
807
808 g_list_free (columns);
809 }
810
811 /* Copy on clipboard */
812 void
813 netstat_copy_to_clipboard (Netinfo * netinfo, gpointer user_data)
814 {
815 GString *result, *content;
816
817 g_return_if_fail (netinfo != NULL);
818
819 result = g_string_new ("");
820
821 switch (netstat_get_active_option2 (netinfo)) {
822 case PROTOCOL:
823 /* The netstat "Display active network services" output in
824 text format.
825 It's a tabular output, and these belongs to the column titles */
826 result = g_string_new (_("Protocol\tIP Source\tPort/Service\tState\n"));
827 break;
828 case ROUTE:
829 /* The netstat "Display routing" output in text format.
830 This seems as a route table.
831 It's a tabular output, and these belongs to the column titles */
832 result = g_string_new (_("Destination\tGateway\tNetmask\tInterface\n"));
833 break;
834 case MULTICAST:
835 /* The netstat "Multicast information" output in text format.
836 It's a tabular output, and these belongs to the column titles */
837 result = g_string_new (_("Interface\tMember\tGroup\n"));
838 break;
839 case NONE:
840 default:
841 break;
842 }
843
844 content = util_tree_model_to_string (GTK_TREE_VIEW (netinfo->output));
845
846 g_string_append_printf (result, "%s", content->str);
847
848 gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), result->str,
849 result->len);
850
851 g_string_free (content, TRUE);
852 g_string_free (result, TRUE);
853 }
854