1 /* EtherApe
2  * Copyright (C) 2001 Juan Toledo, Riccardo Ghetta
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include "appdata.h"
23 #include "node_id.h"
24 #include "util.h"
25 
26 /***************************************************************************
27  *
28  * node_id_t implementation
29  *
30  **************************************************************************/
31 
node_id_clear(node_id_t * a)32 void node_id_clear(node_id_t *a)
33 {
34   memset(a, 0, sizeof(*a));
35   a->node_type = APEMODE_DEFAULT;
36 }
37 
38 /* Comparison function used to order the (GTree *) nodes
39  * and canvas_nodes heard on the network */
node_id_compare(const node_id_t * na,const node_id_t * nb)40 gint node_id_compare(const node_id_t *na, const node_id_t *nb)
41 {
42   const guint8 *ga;
43   const guint8 *gb;
44   int i;
45 
46   g_assert(na != NULL);
47   g_assert(nb != NULL);
48   if (na->node_type < nb->node_type)
49     return -1;
50   else if (na->node_type > nb->node_type)
51     return 1;
52 
53   /* same node type, compare */
54   switch (na->node_type)
55   {
56       case APEMODE_DEFAULT:
57         return 0; /* default has only one value */
58       case IP:
59         ga = na->addr.ip.all8;
60         gb = nb->addr.ip.all8;
61         i = sizeof(na->addr.ip.all8);
62         break;
63       case TCP:
64         ga = na->addr.tcp.host.all8;
65         gb = nb->addr.tcp.host.all8;
66         i = sizeof(na->addr.tcp.host.all8)+sizeof(na->addr.tcp.port);
67         break;
68       default:
69         g_error(_("Unsupported ape mode in node_id_compare"));
70       /* Fallthrough, default to compare-by-MAC */
71       case LINK6:
72         ga = na->addr.eth;
73         gb = nb->addr.eth;
74         i = sizeof(na->addr.eth);
75         break;
76   }
77 
78   i = memcmp(ga, gb, i);
79   if (i > 1)
80     i = 1;
81   else if (i < -1)
82     i = -1;
83   return i;
84 }                               /* node_id_compare */
85 
86 /* returns a newly allocated string with a human-readable id */
node_id_str(const node_id_t * id)87 gchar *node_id_str(const node_id_t *id)
88 {
89   gchar *msg;
90   g_assert(id);
91 
92   switch (id->node_type)
93   {
94       case APEMODE_DEFAULT:
95         msg = g_strdup("00:00:00:00:00:00");
96         break;
97       case LINK6:
98         msg = g_strdup(ether_to_str(id->addr.eth));
99         break;
100       case IP:
101         msg = g_strdup(address_to_str(&id->addr.ip));
102         break;
103       case TCP:
104         msg = g_strdup_printf("%s:%u", address_to_str(&id->addr.tcp.host),
105                               id->addr.tcp.port);
106         break;
107       default:
108         g_error("node_id_type %d unknown", (int)(id->node_type));
109         break;
110   }
111 
112   return msg;
113 }
114 
115 
node_id_dump(const node_id_t * id)116 gchar *node_id_dump(const node_id_t *id)
117 {
118   gchar *msg;
119   g_assert(id);
120   switch (id->node_type)
121   {
122       case APEMODE_DEFAULT:
123         msg = g_strdup_printf("NONE: 00:00:00:00:00:00");
124         break;
125       case LINK6:
126         msg = g_strdup_printf("LINK: %s", ether_to_str(id->addr.eth));
127         break;
128       case IP:
129         msg = g_strdup_printf("%s: %s", type_to_str(&id->addr.ip),
130                               address_to_str(&id->addr.ip));
131         break;
132       case TCP:
133         msg = g_strdup_printf("TCP/UDP: %s:%u",
134                               address_to_str(&id->addr.tcp.host),
135                               id->addr.tcp.port);
136         break;
137       default:
138         msg = g_strdup_printf("node_id_type %d unknown", (int)(id->node_type));
139         break;
140   }
141 
142   return msg;
143 }
144 
node_id_xml(const node_id_t * id)145 gchar *node_id_xml(const node_id_t *id)
146 {
147   gchar *msg;
148   gchar *msgb;
149   gchar *xml;
150   g_assert(id);
151   switch (id->node_type)
152   {
153       case APEMODE_DEFAULT:
154         msg = g_strdup_printf(" ");
155         break;
156       case LINK6:
157         msg = xmltag_escaped("link-id", "%s", ether_to_str(id->addr.eth));
158         break;
159       case IP:
160         msg = xmltag_escaped(type_to_str(&id->addr.ip), "%s", address_to_str(&id->addr.ip));
161         break;
162       case TCP:
163         xml = xmltag_escaped(type_to_str(&id->addr.tcp.host),
164                      "%s",
165                      address_to_str(&id->addr.tcp.host));
166         msgb = xmltag_escaped("port", "%u", id->addr.tcp.port);
167         msg = g_strdup_printf("%s %s", xml, msgb);
168         g_free(xml);
169         g_free(msgb);
170         break;
171       default:
172         msg = xmltag("unknown", "node_id_type %d unknown", (int)(id->node_type));
173         break;
174   }
175   xml = xmltag("id", "\n%s", msg);
176   g_free(msg);
177 
178   return xml;
179 }
180 
181 /***************************************************************************
182  *
183  * name_t implementation
184  *
185  **************************************************************************/
186 static long node_name_count = 0;
187 
active_names(void)188 long active_names(void)
189 {
190   return node_name_count;
191 }
192 
node_name_create(const node_id_t * node_id)193 name_t *node_name_create(const node_id_t *node_id)
194 {
195   name_t *name;
196 
197   g_assert(node_id);
198 
199   name = g_malloc(sizeof(name_t));
200   g_assert(name);
201 
202   name->node_id = *node_id;
203   name->accumulated = 0;
204   name->numeric_name = NULL;
205   name->res_name = NULL;
206   ++node_name_count;
207   {
208     gchar *gg = node_id_dump(node_id);
209     g_my_debug("node name created (%p): >%s<, total %ld", name,
210                gg, node_name_count);
211     g_free(gg);
212   }
213   return name;
214 }
215 
node_name_delete(name_t * name)216 void node_name_delete(name_t *name)
217 {
218   if (name) {
219     {
220       gchar *gg = node_id_dump(&name->node_id);
221       g_my_debug("node name delete (%p): >%s<, total %ld", name,
222                  gg, node_name_count-1);
223       g_free(gg);
224     }
225     if (name->res_name)
226       g_string_free(name->res_name, TRUE);
227     if (name->numeric_name)
228       g_string_free(name->numeric_name, TRUE);
229     g_free(name);
230     --node_name_count;
231   }
232 }
233 
node_name_assign(name_t * name,const gchar * nm,const gchar * num_nm,gdouble sz)234 void node_name_assign(name_t *name, const gchar *nm, const gchar *num_nm,
235                       gdouble sz)
236 {
237   if (DEBUG_ENABLED) {
238     gchar *msgid = node_id_dump(&name->node_id);
239     g_my_debug(" node_name_assign: id %s, name %s, num.name %s\n",
240                msgid, (nm) ? nm : "<none>", num_nm);
241     g_free(msgid);
242   }
243   g_assert(name);
244   if (!name->numeric_name)
245     name->numeric_name = g_string_new(num_nm);
246   else
247     g_string_assign(name->numeric_name, num_nm);
248 
249   if (nm) {
250     if (!name->res_name)
251       name->res_name = g_string_new(nm);
252     else
253       g_string_assign(name->res_name, nm);
254   }
255   name->accumulated += sz;
256 }
257 
node_name_dump(const name_t * name)258 gchar *node_name_dump(const name_t *name)
259 {
260   gchar *msg;
261   gchar *nid;
262   if (!name)
263     return g_strdup("name_t NULL");
264 
265   nid = node_id_dump(&name->node_id);
266   msg = g_strdup_printf("node id: %s, name: %s, numeric_name: %s, solved: %d, "
267                         "accumulated %f",
268                         nid,
269                         (name->res_name) ? name->res_name->str : "<none>",
270                         name->numeric_name->str,
271                         name->res_name != NULL,
272                         name->accumulated);
273   g_free(nid);
274   return msg;
275 }
276 
node_name_xml(const name_t * name)277 gchar *node_name_xml(const name_t *name)
278 {
279   gchar *msg;
280   gchar *nid;
281   gchar *nres;
282 
283   if (!name)
284     return xmltag("name", "");
285 
286   nid = node_id_xml(&name->node_id);
287   if (name->res_name)
288     nres = xmltag_escaped("resolved_name", "%s", name->res_name->str);
289   else
290     nres = g_strdup("");
291   msg = xmltag("name",
292                "\n%s%s<numeric_name>%s</numeric_name>\n"
293                "<accumulated>%.0f</accumulated>",
294                nid,
295                nres,
296                name->numeric_name->str,
297                name->accumulated);
298   g_free(nid);
299   g_free(nres);
300   return msg;
301 }
302 
303 /* compares by node id */
node_name_id_compare(const name_t * a,const name_t * b)304 gint node_name_id_compare(const name_t *a, const name_t *b)
305 {
306   g_assert(a != NULL);
307   g_assert(b != NULL);
308   return node_id_compare(&a->node_id, &b->node_id);
309 }
310 
311 /* Comparison function to sort protocols by their accumulated traffic */
node_name_freq_compare(gconstpointer a,gconstpointer b)312 gint node_name_freq_compare(gconstpointer a, gconstpointer b)
313 {
314   const name_t *name_a, *name_b;
315 
316   g_assert(a != NULL);
317   g_assert(b != NULL);
318 
319   name_a = (const name_t *)a;
320   name_b = (const name_t *)b;
321 
322   if (name_a->accumulated > name_b->accumulated)
323     return -1;
324   if (name_a->accumulated < name_b->accumulated)
325     return 1;
326   return 0;
327 }
328