SourceForge: etherape/etherape: changeset 720:a43a8301dd51
unified node id extraction with protocol decoding. Added experimental wlan/radiotap support
authorR.Ghetta <bchiara@users.sf.net>
Sun Oct 18 01:44:24 2009 +0200 (2 months ago)
changeset 720a43a8301dd51
parent 719 ae26f4abac47
child 721 f9371ed70402
unified node id extraction with protocol decoding. Added experimental wlan/radiotap support

This change fixes a long standing problem on node ids, namely the need to have fixed positions for node addresses. While protocol decoding had most of the machinery to properly follow variable length protocols, node ids (used as internal keys for nodes) where attributed only on static information.
Variable lenght decoding made possibile to support wlan. Decoding is still limited, to basic data, though.
TODO
src/capture.c
src/capture.h
src/common.h
src/decode_proto.c
src/decode_proto.h
src/menus.c
src/names.c
src/node_id.c
src/node_id.h
src/preferences.c
     1.1 --- a/TODO	Sat Oct 17 21:50:43 2009 +0200
     1.2 +++ b/TODO	Sun Oct 18 01:44:24 2009 +0200
     1.3 @@ -20,13 +20,6 @@
     1.4  Issues in the source code
     1.5  -------------------------
     1.6  
     1.7 -  * unify node_id and packet decoding. Right now ip/tcp nodes can get useless
     1.8 -    ids, leading to incorrect node splitting for multiproto networks.
     1.9 -    Node id should be attributed only after packet decoding, by choosing a
    1.10 -    suitable numeric name.
    1.11 -    This problem can happen only when default packet filters are disabled, 
    1.12 -    though, something the user can do only on purpose :-)
    1.13 -
    1.14    * rewrite names handling. Do only packet extraction at capture time, name
    1.15      resolution only at display time for the chosen name.
    1.16  
     2.1 --- a/src/capture.c	Sat Oct 17 21:50:43 2009 +0200
     2.2 +++ b/src/capture.c	Sun Oct 18 01:44:24 2009 +0200
     2.3 @@ -26,7 +26,6 @@
     2.4  #include "globals.h"
     2.5  #include "capture.h"
     2.6  #include "names.h"
     2.7 -#include "node.h"
     2.8  #include "conversations.h"
     2.9  #include "dns.h"
    2.10  #include "decode_proto.h"
    2.11 @@ -35,15 +34,6 @@
    2.12  #define MAXSIZE 200
    2.13  #define PCAP_TIMEOUT 250
    2.14  
    2.15 -/* Used on some functions to indicate how to operate on the node info
    2.16 - * depending on what side of the comm the node was at */
    2.17 -typedef enum
    2.18 -{
    2.19 -  SRC = 0,
    2.20 -  DST = 1
    2.21 -}
    2.22 -create_node_type_t;
    2.23 -
    2.24  static pcap_t *pch_struct;		/* pcap structure */
    2.25  static gint pcap_fd;			/* The file descriptor used by libpcap */
    2.26  static gint capture_source;		/* It's the input tag or the timeout tag,
    2.27 @@ -58,326 +48,13 @@
    2.28  static void cap_t_o_destroy (gpointer data);
    2.29  static void read_packet_live(gpointer dummy, gint source,
    2.30  			 GdkInputCondition condition);
    2.31 -static void packet_acquired(guint8 * packet, guint raw_size, guint pkt_size);
    2.32 -
    2.33 -static void add_node_packet (const guint8 * packet,
    2.34 -                             guint raw_size,
    2.35 -			     packet_info_t * packet_info,
    2.36 -                             const node_id_t *node_id,
    2.37 -			     packet_direction direction);
    2.38 -
    2.39  
    2.40  static void dns_ready (gpointer data, gint fd, GdkInputCondition cond);
    2.41  
    2.42 -/* requested address types */
    2.43 -typedef enum
    2.44 -{
    2.45 -  LOFS_L2_DST,  /* requested L2 dst */
    2.46 -  LOFS_L2_SRC,  /* requested L2 src */
    2.47 -  LOFS_L3,      /* requested L3 src */
    2.48 -} linktype_ofs_t;
    2.49 -
    2.50 -/* function to calculate offsets from packet data. Returns -1 on error or if
    2.51 - * requested address type can't be found */
    2.52 -typedef  short (*linktype_func_t)(linktype_ofs_t type,
    2.53 -                                  const guint8 *packet, 
    2.54 -                                  guint raw_size,
    2.55 -                                  guint curofs);
    2.56 -
    2.57 -/* etherape has to handle several data link layer (OSI L2) packet types.
    2.58 - * The following table tries to make easier adding new types.
    2.59 - * End of table is signaled by an entry with lt_desc NULL */
    2.60 -typedef struct linktype_data_tag
    2.61 -{
    2.62 -  const gchar *lt_desc; /* linktype description */
    2.63 -  int dlt_linktype; /* pcap link type (DLT_xxxx defines) */
    2.64 -  apemode_t l2_idtype;   /* link level address slot in node_id_t */
    2.65 -  short l2_dst_ofs; /* offset of level 2 dst addr. -1 if no l2 data */
    2.66 -  short l2_src_ofs; /* offset of level 2 src addr. -1 if no l2 data */
    2.67 -  short l3_ofs;     /* offset of level 3 layer */
    2.68 -  linktype_func_t fun; /* optional offset calculation function */      
    2.69 -} linktype_data_t;
    2.70 -
    2.71 -
    2.72 -/* linktype decoding functions */
    2.73 -static short default_ofs(linktype_ofs_t type, const guint8 *packet, 
    2.74 -                          guint raw_size, guint curofs);
    2.75 -static short radiotap_ofs(linktype_ofs_t type, const guint8 *packet, 
    2.76 -                          guint raw_size, guint curofs);
    2.77 -static short wlan_ofs(linktype_ofs_t type, const guint8 *packet, 
    2.78 -                          guint raw_size, guint curofs);
    2.79 -
    2.80 -
    2.81 -/* current link type entry */
    2.82 -const linktype_data_t *lkentry = NULL;
    2.83 -
    2.84 -static linktype_data_t linktypes[] = {
    2.85 - {"Ethernet",     DLT_EN10MB,  LINK6, 0,  6, 14, default_ofs },
    2.86 - {"RAW",          DLT_RAW,     IP,    -1, -1,  0, default_ofs }, /* raw IP, like PPP o SLIP */
    2.87 -#ifdef DLT_LINUX_SLL
    2.88 - {"LINUX_SLL",    DLT_LINUX_SLL, IP, -1, -1, 16, default_ofs }, /* Linux cooked */
    2.89 -#endif  
    2.90 - {"BSD Loopback", DLT_NULL,    IP,   -1, -1,  4, default_ofs }, /* we ignore l2 data */
    2.91 - {"OpenBSD Loopback", DLT_LOOP,    IP,   -1, -1,  4, default_ofs }, /* we ignore l2 data */
    2.92 - {"FDDI",         DLT_FDDI,    LINK6, 1,  7, 21, default_ofs },
    2.93 - {"IEEE802",      DLT_IEEE802, LINK6, 2,  8, 22, default_ofs }, /* Token Ring */
    2.94 -
    2.95 - /* plain wireless data frame perhaps 22bytesTODO: handle non-data frames */
    2.96 - {"WLAN",   DLT_IEEE802_11, LINK6, 4,  10, 38, wlan_ofs }, 
    2.97 - /* Wireless with radiotap header */
    2.98 - {"WLAN+RTAP",   DLT_IEEE802_11_RADIO, LINK6, -1,  -1, -1, radiotap_ofs }, 
    2.99 -  
   2.100 - {NULL,   0, 0, 0,  0, 0, NULL } /* terminating entry, must be last */
   2.101 -};
   2.102 -
   2.103 -
   2.104  /* 
   2.105   * FUNCTION DEFINITIONS
   2.106   */
   2.107  
   2.108 -/* handles standard packet types */
   2.109 -static short default_ofs(linktype_ofs_t type, const guint8 *packet, 
   2.110 -                                      guint raw_size, guint curofs)
   2.111 -{
   2.112 -  short ofs = -1;
   2.113 -  if (!lkentry)
   2.114 -    return -1;
   2.115 -  
   2.116 -  switch (type)
   2.117 -    {
   2.118 -      case LOFS_L2_DST:
   2.119 -        if (lkentry->l2_dst_ofs >= 0 )
   2.120 -          ofs = curofs + lkentry->l2_dst_ofs; 
   2.121 -        break;
   2.122 -      case LOFS_L2_SRC:
   2.123 -        if (lkentry->l2_src_ofs >= 0 )
   2.124 -          ofs = curofs + lkentry->l2_src_ofs; 
   2.125 -        break;
   2.126 -      case LOFS_L3:
   2.127 -        if (lkentry->l3_ofs >= 0 )
   2.128 -          ofs = curofs + lkentry->l3_ofs; 
   2.129 -        break;
   2.130 -    }
   2.131 -
   2.132 -  if (raw_size < ofs + 6)
   2.133 -    {
   2.134 -      g_warning (_("captured size too small, packet discarded"));
   2.135 -      return -1;
   2.136 -    }
   2.137 -  
   2.138 -  return ofs;
   2.139 -}
   2.140 -
   2.141 -/* handles radiotap header */
   2.142 -static short radiotap_ofs(linktype_ofs_t type, const guint8 *packet, 
   2.143 -                                      guint raw_size, guint curofs)
   2.144 -{
   2.145 -  guint16 rtlen;
   2.146 -
   2.147 -  g_assert(lkentry && lkentry->l2_idtype == DLT_IEEE802_11_RADIO);
   2.148 -  g_assert(packet);
   2.149 -
   2.150 -  if (raw_size < 32)
   2.151 -    {
   2.152 -      g_warning (_("Radiotap:captured size too small, packet discarded"));
   2.153 -      return -1;
   2.154 -    }
   2.155 -
   2.156 -  /* radiotap hdr has 8 bit of version, plus 8bit of padding, followed by
   2.157 -   * 16bit len field. We don't need to parse the header, just skip it 
   2.158 -   * Note: header is in host order */
   2.159 -  rtlen = *(guint16 *)(packet+2);
   2.160 -  if (raw_size <= rtlen)
   2.161 -    {
   2.162 -      g_warning (_("Radiotap:captured size too small, packet discarded"));
   2.163 -      return -1;
   2.164 -    }
   2.165 -    
   2.166 -  return wlan_ofs(type, packet+rtlen, raw_size-rtlen, rtlen);
   2.167 -}
   2.168 -
   2.169 -/* ieee802.11 wlans */
   2.170 -static short wlan_ofs(linktype_ofs_t type, const guint8 *packet, 
   2.171 -                                      guint raw_size, guint curofs)
   2.172 -{
   2.173 -  uint16_t fc;
   2.174 -  short ofs;
   2.175 -  g_assert(ofs && packet && raw_size);
   2.176 -
   2.177 -  if (raw_size < 10)
   2.178 -    {
   2.179 -      g_warning (_("wlan:captured size too small, packet discarded"));
   2.180 -      return -1;
   2.181 -    }
   2.182 -  
   2.183 -  ofs = -1;
   2.184 -
   2.185 -  /* frame control: two bytes */
   2.186 -  fc = ntohs(*packet);
   2.187 - 
   2.188 -  /* frame type is in bits 13-14 */
   2.189 -  switch ( (fc >> 12 ) & 0xff )
   2.190 -    {
   2.191 -      case 0x10:
   2.192 -        /* data frame */
   2.193 -        switch (type)
   2.194 -          {
   2.195 -            case LOFS_L2_DST:
   2.196 -              ofs = curofs + 4; 
   2.197 -              break;
   2.198 -            case LOFS_L2_SRC:
   2.199 -              ofs = curofs + 10; 
   2.200 -              break;
   2.201 -            case LOFS_L3:
   2.202 -              /* L3 offset depends on LLC/SNAP hdr. For now, just assume ip
   2.203 -               * payload */
   2.204 -              ofs = curofs + 30 + 8; 
   2.205 -              break;
   2.206 -          }
   2.207 -        break;
   2.208 -      case 0x00: /* mgmt frame */
   2.209 -      case 0x01: /* control frame */
   2.210 -        if (type == LOFS_L2_DST)
   2.211 -           ofs = curofs + 4; 
   2.212 -        break;
   2.213 -      default:
   2.214 -        g_warning (_("wlan:captured size too small, packet discarded"));
   2.215 -        break;
   2.216 -    }
   2.217 -
   2.218 -  if (raw_size < ofs + 8)
   2.219 -    {
   2.220 -      g_warning (_("wlan:captured size too small, packet discarded"));
   2.221 -      return -1;
   2.222 -    }
   2.223 -        
   2.224 -  return ofs;
   2.225 -}
   2.226 -
   2.227 -/* Sets the correct linktype entry. Returns false if not found */
   2.228 -static gboolean setup_linktype(int linktype)
   2.229 -{
   2.230 -  int i;
   2.231 -
   2.232 -  lkentry = NULL;
   2.233 -  for (i = 0; linktypes[i].lt_desc != NULL ; ++i)
   2.234 -    {
   2.235 -      if (linktypes[i].dlt_linktype == linktype)
   2.236 -        {
   2.237 -          lkentry = linktypes + i;
   2.238 -          return TRUE;
   2.239 -        }
   2.240 -    }
   2.241 -  
   2.242 -  return FALSE; /* link type not supported */
   2.243 -}
   2.244 -
   2.245 -/* true if current device captures l2 data */ 
   2.246 -gboolean has_linklevel(void)
   2.247 -{
   2.248 -  if (lkentry)
   2.249 -    return lkentry->l2_idtype == LINK6;
   2.250 -  else
   2.251 -    return FALSE;
   2.252 -}
   2.253 -
   2.254 -/* Returns the node id for the current mode in this particular packet */
   2.255 -static node_id_t get_node_id (const guint8 * raw_packet, size_t raw_size, 
   2.256 -                              create_node_type_t node_type)
   2.257 -{
   2.258 -  node_id_t node_id;
   2.259 -  short ofs;
   2.260 -
   2.261 -  memset( &node_id, 0, sizeof(node_id));
   2.262 -  node_id.node_type = pref.mode;
   2.263 -
   2.264 -  if (!lkentry || !lkentry->fun)
   2.265 -    {
   2.266 -      g_error (_("Unsupported link type"));
   2.267 -      return;  /* g_error() aborts, but just to be sure ... */
   2.268 -    }
   2.269 -
   2.270 -  switch (pref.mode)
   2.271 -    {
   2.272 -    case LINK6:
   2.273 -      if (lkentry->l2_idtype == LINK6)
   2.274 -        {
   2.275 -          if (node_type == SRC)
   2.276 -             ofs = lkentry->fun(LOFS_L2_SRC, raw_packet, raw_size, 0);
   2.277 -          else
   2.278 -             ofs = lkentry->fun(LOFS_L2_DST, raw_packet, raw_size, 0);
   2.279 -              
   2.280 -          if (ofs < 0)
   2.281 -            break; 
   2.282 -          if (raw_size < ofs + sizeof(node_id.addr.eth))
   2.283 -            {
   2.284 -              g_critical(_("Received subsize %s packet! Forged ?"), 
   2.285 -                         lkentry->lt_desc);
   2.286 -              break;
   2.287 -            }
   2.288 -          if (node_type == SRC)
   2.289 -            g_memmove(node_id.addr.eth, raw_packet + ofs, 
   2.290 -                      sizeof(node_id.addr.eth));
   2.291 -          else
   2.292 -            g_memmove(node_id.addr.eth, raw_packet + ofs, 
   2.293 -                      sizeof(node_id.addr.eth));
   2.294 -        }
   2.295 -      else
   2.296 -        {
   2.297 -          g_critical(_("Can't handle linktype %d (%s) at link layer level. "
   2.298 -                       "Please select IP or above"), lkentry->l2_idtype, 
   2.299 -                                                     lkentry->lt_desc);
   2.300 -        }
   2.301 -      break;
   2.302 -    case IP:
   2.303 -      ofs = lkentry->fun(LOFS_L3, raw_packet, raw_size, 0);
   2.304 -      if (ofs < 0)
   2.305 -          break; /* no ip data found */
   2.306 -      if (raw_size >= ofs + 16 + sizeof(node_id.addr.ip4))
   2.307 -        {
   2.308 -          if (node_type == SRC)
   2.309 -            g_memmove(node_id.addr.ip4, raw_packet + ofs + 12, 
   2.310 -                      sizeof(node_id.addr.ip4));
   2.311 -          else
   2.312 -            g_memmove(node_id.addr.ip4, raw_packet + ofs + 16, 
   2.313 -                      sizeof(node_id.addr.ip4));
   2.314 -        }
   2.315 -        else
   2.316 -          g_critical(_("Received subsize IP packet! Forged ?"));
   2.317 -      break;
   2.318 -    case TCP:
   2.319 -      ofs = lkentry->fun(LOFS_L3, raw_packet, raw_size, 0);
   2.320 -      if (ofs < 0)
   2.321 -          break; /* no tcp data found */
   2.322 -      if (raw_size >= ofs + 24)
   2.323 -        {
   2.324 -          if (node_type == SRC)
   2.325 -            {
   2.326 -              guint16 port;
   2.327 -              g_memmove (node_id.addr.tcp4.host, raw_packet + 
   2.328 -                         ofs + 12, 4);
   2.329 -              port = ntohs (*(guint16 *) (raw_packet + ofs + 20));
   2.330 -              g_memmove (node_id.addr.tcp4.port, &port, 2);
   2.331 -            }
   2.332 -          else
   2.333 -            {
   2.334 -              guint16 port;
   2.335 -              g_memmove (node_id.addr.tcp4.host, 
   2.336 -                         raw_packet + ofs + 16, 4);
   2.337 -              port = ntohs (*(guint16 *) (raw_packet + ofs + 22));
   2.338 -              g_memmove (node_id.addr.tcp4.port, &port, 2);
   2.339 -            }
   2.340 -        }
   2.341 -        else
   2.342 -          g_critical(_("Received subsize TCP/UDP packet! Forged ?"));
   2.343 -      break;
   2.344 -    default:
   2.345 -      g_error (_("Reached default in get_node_id"));
   2.346 -    }
   2.347 -
   2.348 -  return node_id;
   2.349 -}				/* get_node_id */
   2.350 -
   2.351  enum status_t get_capture_status(void)
   2.352  {
   2.353    return capture_status;
   2.354 @@ -470,18 +147,16 @@
   2.355      }
   2.356  
   2.357    linktype = pcap_datalink(pch_struct);
   2.358 -  if (!setup_linktype(linktype))
   2.359 +  if (!setup_link_type(linktype))
   2.360      {
   2.361          snprintf (errorbuf, sizeof(errorbuf), _("Link type %d not supported"), 
   2.362                    linktype);
   2.363          return errorbuf;
   2.364      }
   2.365    
   2.366 -  g_my_info (_("Link type is %s"), lkentry->lt_desc);
   2.367 -
   2.368 -  if (pref.mode == DEFAULT)
   2.369 +  if (pref.mode == APEMODE_DEFAULT)
   2.370      pref.mode = IP;
   2.371 -  if (pref.mode == LINK6 && lkentry->l2_idtype != pref.mode)
   2.372 +  if (pref.mode == LINK6 && !has_linklevel())
   2.373      {
   2.374        snprintf (errorbuf, sizeof(errorbuf), _("Mode not available in this device"));
   2.375        return errorbuf;
   2.376 @@ -510,7 +185,7 @@
   2.377  	  str = g_strdup ("tcp");
   2.378  	}
   2.379        break;
   2.380 -    case DEFAULT:
   2.381 +    case APEMODE_DEFAULT:
   2.382      case LINK6:
   2.383        if (pref.filter)
   2.384  	str = g_strdup (pref.filter);
   2.385 @@ -778,91 +453,6 @@
   2.386      packet_acquired( (guint8 *)pkt_data, pkt_header->caplen, pkt_header->len);
   2.387  }
   2.388  
   2.389 -/* This function is called everytime there is a new packet in
   2.390 - * the network interface. It then updates traffic information
   2.391 - * for the appropriate nodes and links 
   2.392 - * Receives both the captured (raw) size and the real packet size */
   2.393 -static void
   2.394 -packet_acquired(guint8 * raw_packet, guint raw_size, guint pkt_size)
   2.395 -{
   2.396 -  packet_info_t *packet;
   2.397 -  node_id_t src_node_id;
   2.398 -  node_id_t dst_node_id;
   2.399 -  link_id_t link_id;
   2.400 -
   2.401 -  if (!lkentry || !lkentry->fun)
   2.402 -    {
   2.403 -      g_error(_("Data link entry not initialized"));
   2.404 -      return;  /* g_error() should abort, but just to be sure ... */
   2.405 -    }
   2.406 -  
   2.407 -  /* We create a packet structure to hold data */
   2.408 -  packet = g_malloc (sizeof (packet_info_t));
   2.409 -  g_assert(packet);
   2.410 -  
   2.411 -  packet->size = pkt_size;
   2.412 -  packet->timestamp = now;
   2.413 -  packet->ref_count = 0;
   2.414 -
   2.415 -  /* Get a string with the protocol tree */
   2.416 -  packet->prot_desc = get_packet_prot (raw_packet, raw_size, 
   2.417 -                                       lkentry->dlt_linktype);
   2.418 -
   2.419 -  src_node_id = get_node_id (raw_packet, raw_size, SRC);
   2.420 -  dst_node_id = get_node_id (raw_packet, raw_size, DST);
   2.421 -
   2.422 -  n_packets++;
   2.423 -  total_mem_packets++;
   2.424 -
   2.425 -  /* Add this packet information to the src and dst nodes. If they
   2.426 -   * don't exist, create them */
   2.427 -  add_node_packet (raw_packet, raw_size, packet, &src_node_id, OUTBOUND);
   2.428 -  add_node_packet (raw_packet, raw_size, packet, &dst_node_id, INBOUND);
   2.429 -
   2.430 -  /* And now we update link traffic information for this packet */
   2.431 -  link_id.src = src_node_id;
   2.432 -  link_id.dst = dst_node_id;
   2.433 -  links_catalog_add_packet(&link_id, packet);
   2.434 -
   2.435 -  /* finally, update global protocol stats */
   2.436 -  protocol_summary_add_packet(packet);
   2.437 -}
   2.438 -
   2.439 -
   2.440 -/* We update node information for each new packet that arrives in the
   2.441 - * network. If the node the packet refers to is unknown, we
   2.442 - * create it. */
   2.443 -static void
   2.444 -add_node_packet (const guint8 * raw_packet,
   2.445 -                 guint raw_size,
   2.446 -		 packet_info_t * packet,
   2.447 -                 const node_id_t *node_id,
   2.448 -		 packet_direction direction)
   2.449 -{
   2.450 -  node_t *node;
   2.451 -
   2.452 -  node = nodes_catalog_find(node_id);
   2.453 -  if (node == NULL)
   2.454 -    {
   2.455 -      /* creates the new node, adding it to the catalog */
   2.456 -      node = nodes_catalog_new(node_id);
   2.457 -      g_assert(node);
   2.458 -    }
   2.459 -
   2.460 -  traffic_stats_add_packet(&node->node_stats, packet, direction);
   2.461 -
   2.462 -  /* If this is the first packet we've heard from the node in a while, 
   2.463 -   * we add it to the list of new nodes so that the main app know this 
   2.464 -   * node is active again */
   2.465 -  if (node->node_stats.n_packets == 1)
   2.466 -    new_nodes_add(node);
   2.467 -
   2.468 -  /* Update names list for this node */
   2.469 -  get_packet_names (&node->node_stats.stats_protos, raw_packet, raw_size,
   2.470 -		    packet->prot_desc, direction, lkentry->dlt_linktype);
   2.471 -
   2.472 -}				/* add_node_packet */
   2.473 -
   2.474  /* Callback function everytime a dns_lookup function is finished */
   2.475  static void
   2.476  dns_ready (gpointer data, gint fd, GdkInputCondition cond)
     3.1 --- a/src/capture.h	Sat Oct 17 21:50:43 2009 +0200
     3.2 +++ b/src/capture.h	Sun Oct 18 01:44:24 2009 +0200
     3.3 @@ -19,8 +19,6 @@
     3.4  #ifndef ETHERAPE_CAPTURE_H
     3.5  #define ETHERAPE_CAPTURE_H
     3.6  
     3.7 -#include "links.h"
     3.8 -
     3.9  /* Possible states of capture status */
    3.10  enum status_t
    3.11  {
    3.12 @@ -38,6 +36,5 @@
    3.13  gboolean stop_capture (void);
    3.14  void cleanup_capture (void);
    3.15  gint set_filter (gchar * filter, gchar * device);
    3.16 -gboolean has_linklevel(void); /* true if current device captures l2 data */ 
    3.17  
    3.18  #endif
     4.1 --- a/src/common.h	Sat Oct 17 21:50:43 2009 +0200
     4.2 +++ b/src/common.h	Sun Oct 18 01:44:24 2009 +0200
     4.3 @@ -74,7 +74,7 @@
     4.4  
     4.5  typedef enum
     4.6  {
     4.7 -  DEFAULT = -1,
     4.8 +  APEMODE_DEFAULT = -1,
     4.9    LINK6 = 0,        /* data link level with 6 bits of address */
    4.10    IP,
    4.11    TCP
     5.1 --- a/src/decode_proto.c	Sat Oct 17 21:50:43 2009 +0200
     5.2 +++ b/src/decode_proto.c	Sun Oct 18 01:44:24 2009 +0200
     5.3 @@ -23,12 +23,17 @@
     5.4  #include "globals.h"
     5.5  #include <ctype.h>
     5.6  #include <string.h>
     5.7 +#ifdef HAVE_ARPA_INET_H
     5.8 +#include <arpa/inet.h>
     5.9 +#endif
    5.10  #include "prot_types.h"
    5.11  #include "util.h"
    5.12  #include "decode_proto.h"
    5.13  #include "protocols.h"
    5.14  #include "conversations.h"
    5.15  #include "datastructs.h"
    5.16 +#include "node.h"
    5.17 +#include "links.h"
    5.18  
    5.19  #define TCP_FTP 21
    5.20  #define TCP_NETBIOS_SSN 139
    5.21 @@ -66,6 +71,10 @@
    5.22    packet_protos_t *pr; /* detected protocol stack */
    5.23    guint cur_level;      /* current protocol depth on stack */
    5.24  
    5.25 +  /* node ids */
    5.26 +  node_id_t dst_node_id; 
    5.27 +  node_id_t src_node_id;
    5.28 +  
    5.29    /* These are used for conversations */
    5.30    guint32 global_src_address;
    5.31    guint32 global_dst_address;
    5.32 @@ -74,22 +83,38 @@
    5.33  
    5.34  } decode_proto_t;
    5.35  
    5.36 +/* extracts the protocol stack from packet */
    5.37 +static void get_packet_prot (decode_proto_t *dp);
    5.38 +
    5.39  /* starts a new decode, allocating a new packet_protos_t */
    5.40 -void decode_proto_start(decode_proto_t *dp, const guint8 *pkt, guint caplen);
    5.41 +static void decode_proto_start(decode_proto_t *dp, 
    5.42 +                               const guint8 *pkt, guint caplen);
    5.43  
    5.44  /* sets protoname at current level, and passes at next level */
    5.45 -void decode_proto_add(decode_proto_t *dp, const gchar *fmt, ...);
    5.46 +static void decode_proto_add(decode_proto_t *dp, const gchar *fmt, ...);
    5.47  
    5.48  /* advances current packet start to prepare for next protocol */
    5.49  static void add_offset(decode_proto_t *dp, guint offset);
    5.50  
    5.51 +static void add_node_packet (const guint8 * packet,
    5.52 +                             guint raw_size,
    5.53 +			     packet_info_t * packet_info,
    5.54 +                             const node_id_t *node_id,
    5.55 +			     packet_direction direction);
    5.56 +
    5.57 +/* decoder func proto */
    5.58 +typedef void (*get_fun)(decode_proto_t *dp);
    5.59 +
    5.60  /* specific decoders declarations */
    5.61 +static void get_loop(decode_proto_t *dp);
    5.62  static void get_eth_type (decode_proto_t *dp);
    5.63  static void get_fddi_type (decode_proto_t *dp);
    5.64 -static void get_ieee802_type (decode_proto_t *dp);
    5.65 +static void get_ieee802_5_type (decode_proto_t *dp);
    5.66  static void get_eth_II (decode_proto_t *dp, etype_t etype);
    5.67  static void get_eth_802_3 (decode_proto_t *dp, ethhdrtype_t ethhdr_type);
    5.68 -static void get_linux_sll_type (decode_proto_t *dp);
    5.69 +static void get_radiotap (decode_proto_t *dp);
    5.70 +static void get_wlan (decode_proto_t *dp);
    5.71 +static void get_linux_sll (decode_proto_t *dp);
    5.72  
    5.73  static void get_llc (decode_proto_t *dp);
    5.74  static void get_ip (decode_proto_t *dp);
    5.75 @@ -100,12 +125,78 @@
    5.76  static void get_netbios (decode_proto_t *dp);
    5.77  static void get_netbios_ssn (decode_proto_t *dp);
    5.78  static void get_netbios_dgm (decode_proto_t *dp);
    5.79 +static void get_ftp (decode_proto_t *dp);
    5.80  
    5.81 -static void get_ftp (decode_proto_t *dp);
    5.82  static gboolean get_rpc (decode_proto_t *dp, gboolean is_udp);
    5.83  static guint16 choose_port (guint16 a, guint16 b);
    5.84  static void append_etype_prot (decode_proto_t *dp, etype_t etype);
    5.85  
    5.86 +/* etherape has to handle several data link layer (OSI L2) packet types.
    5.87 + * The following table tries to make easier adding new types.
    5.88 + * End of table is signaled by an entry with lt_desc NULL */
    5.89 +typedef struct linktype_data_tag
    5.90 +{
    5.91 +  const gchar *lt_desc; /* linktype description */
    5.92 +  int dlt_linktype; /* pcap link type (DLT_xxxx defines) */
    5.93 +  apemode_t l2_idtype;   /* link level address slot in node_id_t */
    5.94 +  get_fun fun;  /* linktype base decoder function */
    5.95 +    
    5.96 +} linktype_data_t;
    5.97 +
    5.98 +
    5.99 +
   5.100 +/* current link type entry */
   5.101 +const linktype_data_t *lkentry = NULL;
   5.102 +
   5.103 +static linktype_data_t linktypes[] = {
   5.104 + {"Ethernet",     DLT_EN10MB,    LINK6, get_eth_type },
   5.105 + {"RAW",          DLT_RAW,       IP,    get_ip    }, /* raw IP like PPP,SLIP */
   5.106 +#ifdef DLT_LINUX_SLL
   5.107 + {"LINUX_SLL",    DLT_LINUX_SLL, IP,    get_linux_sll }, /* Linux cooked */
   5.108 +#endif  
   5.109 + {"BSD Loopback", DLT_NULL,      IP,    get_loop }, /* ignore l2 data */
   5.110 + {"OpenBSD Loopback", DLT_LOOP,  IP,    get_loop }, /* ignore l2 data */
   5.111 + {"FDDI",         DLT_FDDI,    LINK6,   get_fddi_type },
   5.112 + {"IEEE802.5",    DLT_IEEE802, LINK6,   get_ieee802_5_type  }, /* Token Ring */
   5.113 + {"WLAN",   DLT_IEEE802_11,    LINK6,   get_wlan }, 
   5.114 + /* Wireless with radiotap header */
   5.115 + {"WLAN+RTAP",  DLT_IEEE802_11_RADIO, LINK6, get_radiotap }, 
   5.116 +  
   5.117 + {NULL,   0, 0 } /* terminating entry, must be last */
   5.118 +};
   5.119 +
   5.120 +/* ------------------------------------------------------------
   5.121 + * L2 offset decoders
   5.122 + * ------------------------------------------------------------*/
   5.123 +
   5.124 +/* Sets the correct linktype entry. Returns false if not found */
   5.125 +gboolean setup_link_type(int linktype)
   5.126 +{
   5.127 +  int i;
   5.128 +
   5.129 +  lkentry = NULL;
   5.130 +  for (i = 0; linktypes[i].lt_desc != NULL ; ++i)
   5.131 +    {
   5.132 +      if (linktypes[i].dlt_linktype == linktype)
   5.133 +        {
   5.134 +          lkentry = linktypes + i;
   5.135 +          g_my_info (_("Link type is %s"), lkentry->lt_desc);
   5.136 +          return TRUE;
   5.137 +        }
   5.138 +    }
   5.139 +  
   5.140 +  return FALSE; /* link type not supported */
   5.141 +}
   5.142 +
   5.143 +/* true if current device captures l2 data */ 
   5.144 +gboolean has_linklevel(void)
   5.145 +{
   5.146 +  if (lkentry)
   5.147 +    return lkentry->l2_idtype == LINK6;
   5.148 +  else
   5.149 +    return FALSE;
   5.150 +}
   5.151 +
   5.152  /* ------------------------------------------------------------
   5.153   * Implementation
   5.154   * ------------------------------------------------------------*/
   5.155 @@ -118,6 +209,8 @@
   5.156    dp->cur_len = caplen;
   5.157    dp->pr = packet_protos_init();
   5.158    dp->cur_level = 1; /* level zero is topmost protocol, will be filled later */
   5.159 +  node_id_clear(&dp->dst_node_id);
   5.160 +  node_id_clear(&dp->src_node_id);
   5.161    dp->global_src_address = 0;
   5.162    dp->global_dst_address = 0;
   5.163    dp->global_src_port = 0;
   5.164 @@ -148,76 +241,129 @@
   5.165      }
   5.166  }
   5.167  
   5.168 -packet_protos_t *get_packet_prot (const guint8 * p, guint raw_size, 
   5.169 -                                  int link_type)
   5.170 +/* This function is called everytime there is a new packet in
   5.171 + * the network interface. It then updates traffic information
   5.172 + * for the appropriate nodes and links 
   5.173 + * Receives both the captured (raw) size and the real packet size */
   5.174 +void packet_acquired(guint8 * raw_packet, guint raw_size, guint pkt_size)
   5.175  {
   5.176 +  packet_info_t *packet;
   5.177 +  link_id_t link_id;
   5.178    decode_proto_t decp;
   5.179 +
   5.180 +  g_assert (raw_packet != NULL);
   5.181 +  if (!lkentry || !lkentry->fun)
   5.182 +    {
   5.183 +      g_error(_("Data link entry not initialized"));
   5.184 +      return;  /* g_error() should abort, but just to be sure ... */
   5.185 +    }
   5.186 +
   5.187 +  decode_proto_start(&decp, raw_packet, raw_size);
   5.188 +                                       
   5.189 +  /* create a packet structure to hold data */
   5.190 +  packet = g_malloc (sizeof (packet_info_t));
   5.191 +  g_assert(packet);
   5.192 +  
   5.193 +  packet->size = pkt_size;
   5.194 +  packet->timestamp = now;
   5.195 +  packet->ref_count = 0;
   5.196 +
   5.197 +  /* Get the protocol tree */
   5.198 +  get_packet_prot (&decp);
   5.199 +  if (!decp.pr)
   5.200 +    {
   5.201 +      /* fatal error, discard packet */
   5.202 +      g_free(packet); 
   5.203 +      return;
   5.204 +    }
   5.205 +  packet->prot_desc = decp.pr;
   5.206 +
   5.207 +  n_packets++;
   5.208 +  total_mem_packets++;
   5.209 +
   5.210 +  /* Add this packet information to the src and dst nodes. If they
   5.211 +   * don't exist, create them */
   5.212 +  add_node_packet (raw_packet, raw_size, packet, &decp.src_node_id, OUTBOUND);
   5.213 +  add_node_packet (raw_packet, raw_size, packet, &decp.dst_node_id, INBOUND);
   5.214 +
   5.215 +  /* And now we update link traffic information for this packet */
   5.216 +  link_id.src = decp.src_node_id;
   5.217 +  link_id.dst = decp.dst_node_id;
   5.218 +  links_catalog_add_packet(&link_id, packet);
   5.219 +
   5.220 +  /* finally, update global protocol stats */
   5.221 +  protocol_summary_add_packet(packet);
   5.222 +}
   5.223 +
   5.224 +
   5.225 +/* We update node information for each new packet that arrives in the
   5.226 + * network. If the node the packet refers to is unknown, we
   5.227 + * create it. */
   5.228 +static void
   5.229 +add_node_packet (const guint8 * raw_packet,
   5.230 +                 guint raw_size,
   5.231 +		 packet_info_t * packet,
   5.232 +                 const node_id_t *node_id,
   5.233 +		 packet_direction direction)
   5.234 +{
   5.235 +  node_t *node;
   5.236 +
   5.237 +  node = nodes_catalog_find(node_id);
   5.238 +  if (node == NULL)
   5.239 +    {
   5.240 +      /* creates the new node, adding it to the catalog */
   5.241 +      node = nodes_catalog_new(node_id);
   5.242 +      g_assert(node);
   5.243 +    }
   5.244 +
   5.245 +  traffic_stats_add_packet(&node->node_stats, packet, direction);
   5.246 +
   5.247 +  /* If this is the first packet we've heard from the node in a while, 
   5.248 +   * we add it to the list of new nodes so that the main app know this 
   5.249 +   * node is active again */
   5.250 +  if (node->node_stats.n_packets == 1)
   5.251 +    new_nodes_add(node);
   5.252 +
   5.253 +  /* Update names list for this node */
   5.254 +  get_packet_names (&node->node_stats.stats_protos, raw_packet, raw_size,
   5.255 +		    packet->prot_desc, direction, lkentry->dlt_linktype);
   5.256 +
   5.257 +}				/* add_node_packet */
   5.258 +
   5.259 +static void get_packet_prot (decode_proto_t *dp)
   5.260 +{
   5.261    guint i;
   5.262 -  gchar *prot;
   5.263  
   5.264 -  g_assert (p != NULL);
   5.265 -
   5.266 -  decode_proto_start(&decp, p, raw_size);
   5.267 -
   5.268 -  switch (link_type)
   5.269 -    {
   5.270 -    case DLT_EN10MB:
   5.271 -      get_eth_type (&decp);
   5.272 -      break;
   5.273 -    case DLT_IEEE802_11:
   5.274 -    case DLT_IEEE802_11_RADIO:
   5.275 -      decode_proto_add(&decp, "IEE802.11/LLC"); /* experimental */
   5.276 -      get_llc (&decp); 
   5.277 -      break;
   5.278 -    case DLT_FDDI:
   5.279 -      decode_proto_add(&decp, "FDDI");
   5.280 -      get_fddi_type (&decp);
   5.281 -      break;
   5.282 -    case DLT_IEEE802:
   5.283 -      decode_proto_add(&decp, "Token Ring");
   5.284 -      get_ieee802_type (&decp);
   5.285 -      break;
   5.286 -    case DLT_RAW:		/* Both for PPP and SLIP */
   5.287 -      decode_proto_add(&decp, "RAW/IP");
   5.288 -      get_ip (&decp);
   5.289 -      break;
   5.290 -    case DLT_NULL:
   5.291 -      decode_proto_add(&decp, "NULL/IP");
   5.292 -      add_offset(&decp, 4);
   5.293 -      get_ip (&decp);
   5.294 -      break;
   5.295 -    case DLT_LOOP:
   5.296 -      decode_proto_add(&decp, "LOOP/IP");
   5.297 -      add_offset(&decp, 4);
   5.298 -      get_ip (&decp);
   5.299 -      break;
   5.300 -#ifdef DLT_LINUX_SLL
   5.301 -    case DLT_LINUX_SLL:
   5.302 -      decode_proto_add(&decp, "LINUX-SLL");
   5.303 -      get_linux_sll_type (&decp);
   5.304 -      break;
   5.305 -#endif
   5.306 -    default:
   5.307 -      break;
   5.308 -    }
   5.309 +  g_assert(lkentry && lkentry->fun);
   5.310 +  lkentry->fun(dp);
   5.311  
   5.312    /* first position is top proto */
   5.313    for (i = STACK_SIZE ; i>0 ; --i)
   5.314      {
   5.315 -      if (decp.pr->protonames[i])
   5.316 +      if (dp->pr->protonames[i])
   5.317          {
   5.318 -          decp.pr->protonames[0] = g_strdup(decp.pr->protonames[i]);
   5.319 +          dp->pr->protonames[0] = g_strdup(dp->pr->protonames[i]);
   5.320            break;
   5.321          }
   5.322      }
   5.323 -
   5.324 -  return decp.pr;
   5.325  }				/* get_packet_prot */
   5.326  
   5.327  /* ------------------------------------------------------------
   5.328   * Private functions
   5.329   * ------------------------------------------------------------*/
   5.330  
   5.331 +/* bsd loopback */
   5.332 +static void get_loop(decode_proto_t *dp)
   5.333 +{
   5.334 +  if (lkentry->dlt_linktype == DLT_LOOP)
   5.335 +    decode_proto_add(dp, "LOOP");
   5.336 +  else
   5.337 +    decode_proto_add(dp, "NULL");
   5.338 +  
   5.339 +  add_offset(dp, 4);
   5.340 +  get_ip(dp);
   5.341 +}
   5.342 +
   5.343  static void get_eth_type (decode_proto_t *dp)
   5.344  {
   5.345    etype_t etype;
   5.346 @@ -260,6 +406,14 @@
   5.347  	}
   5.348      }
   5.349  
   5.350 +  /* node ids */
   5.351 +  dp->dst_node_id.node_type = LINK6;
   5.352 +  g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 0, 
   5.353 +            sizeof(dp->dst_node_id.addr.eth));
   5.354 +  dp->src_node_id.node_type = LINK6;
   5.355 +  g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 6, 
   5.356 +            sizeof(dp->src_node_id.addr.eth));
   5.357 +  
   5.358    add_offset(dp, 14);
   5.359  
   5.360    if (ethhdr_type == ETHERNET_802_3)
   5.361 @@ -286,7 +440,6 @@
   5.362    switch (ethhdr_type)
   5.363      {
   5.364      case ETHERNET_802_2:
   5.365 -      decode_proto_add(dp, "LLC");
   5.366        get_llc (dp);
   5.367        break;
   5.368      case ETHERNET_802_3:
   5.369 @@ -300,27 +453,57 @@
   5.370  static void
   5.371  get_fddi_type (decode_proto_t *dp)
   5.372  {
   5.373 +  decode_proto_add(dp, "FDDI");
   5.374 +
   5.375 +  if (dp->cur_len < 14)
   5.376 +    return; /* not big enough */
   5.377 +
   5.378    decode_proto_add(dp, "LLC");
   5.379  
   5.380 +  /* node ids */
   5.381 +  dp->dst_node_id.node_type = LINK6;
   5.382 +  g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 1, 
   5.383 +            sizeof(dp->dst_node_id.addr.eth));
   5.384 +  dp->src_node_id.node_type = LINK6;
   5.385 +  g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 7, 
   5.386 +            sizeof(dp->src_node_id.addr.eth));
   5.387 +  
   5.388    /* Ok, this is only temporary while I truly dissect LLC 
   5.389     * and fddi */
   5.390 +  if (dp->cur_len < 21)
   5.391 +    return; /* not big enough */
   5.392 +
   5.393    if ((dp->cur_packet[19] == 0x08) && (dp->cur_packet[20] == 0x00))
   5.394     {
   5.395 -      decode_proto_add(dp, "IP");
   5.396        add_offset(dp, 21);
   5.397        get_ip (dp);
   5.398      }
   5.399  }				/* get_fddi_type */
   5.400  
   5.401  static void
   5.402 -get_ieee802_type (decode_proto_t *dp)
   5.403 +get_ieee802_5_type (decode_proto_t *dp)
   5.404  {
   5.405 +  decode_proto_add(dp, "Token Ring");
   5.406 +
   5.407 +  if (dp->cur_len < 15)
   5.408 +    return; /* not big enough */
   5.409 +
   5.410 +  /* node ids */
   5.411 +  dp->dst_node_id.node_type = LINK6;
   5.412 +  g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 2, 
   5.413 +            sizeof(dp->dst_node_id.addr.eth));
   5.414 +  dp->src_node_id.node_type = LINK6;
   5.415 +  g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 8, 
   5.416 +            sizeof(dp->src_node_id.addr.eth));
   5.417 +
   5.418 +  if (dp->cur_len < 22)
   5.419 +    return; /* not big enough */
   5.420 +
   5.421    /* As with FDDI, we only support LLC by now */
   5.422    decode_proto_add(dp, "LLC");
   5.423  
   5.424    if ((dp->cur_packet[20] == 0x08) && (dp->cur_packet[21] == 0x00))
   5.425      {
   5.426 -      decode_proto_add(dp, "IP");
   5.427        add_offset(dp, 22);
   5.428        get_ip (dp);
   5.429      }
   5.430 @@ -330,30 +513,156 @@
   5.431  static void
   5.432  get_eth_II (decode_proto_t *dp, etype_t etype)
   5.433  {
   5.434 -  append_etype_prot (dp, etype);
   5.435 -
   5.436    if (etype == ETHERTYPE_IP)
   5.437      get_ip (dp);
   5.438 -  if (etype == ETHERTYPE_IPX)
   5.439 +  else if (etype == ETHERTYPE_IPX)
   5.440      get_ipx (dp);
   5.441 +  else
   5.442 +    append_etype_prot (dp, etype);
   5.443 +    
   5.444  }				/* get_eth_II */
   5.445  
   5.446 +/* handles radiotap header */
   5.447 +static void get_radiotap(decode_proto_t *dp)
   5.448 +{
   5.449 +  guint16 rtlen;
   5.450 +
   5.451 +  decode_proto_add(dp, "RADIOTAP");
   5.452 +  if (dp->cur_len < 32)
   5.453 +    {
   5.454 +      g_warning (_("Radiotap:captured size too small, packet discarded"));
   5.455 +      return;
   5.456 +    }
   5.457 +
   5.458 +  /* radiotap hdr has 8 bit of version, plus 8bit of padding, followed by
   5.459 +   * 16bit len field. We don't need to parse the header, just skip it 
   5.460 +   * Note: header is in host order */
   5.461 +  rtlen = *(guint16 *)(dp->cur_packet+2);
   5.462 +
   5.463 +  add_offset(dp, rtlen);
   5.464 +  get_wlan(dp);
   5.465 +}
   5.466 +
   5.467 +static void decode_wlan_mgmt(decode_proto_t *dp, uint8_t subtype)
   5.468 +{
   5.469 +  switch (subtype)
   5.470 +    {
   5.471 +      case 0: /* association request */
   5.472 +      case 1: /* association response */
   5.473 +      case 2: /* REassociation request */
   5.474 +      case 3: /* REassociation response */
   5.475 +        decode_proto_add(dp, "WLAN-ASSOC");
   5.476 +        break;
   5.477 +      case 4: /* probe req */
   5.478 +      case 5: /* probe resp */
   5.479 +        decode_proto_add(dp, "WLAN-PROBE");
   5.480 +        break;
   5.481 +      case 8: 
   5.482 +        decode_proto_add(dp, "WLAN-BEACON");
   5.483 +        break;
   5.484 +      case 9: 
   5.485 +        decode_proto_add(dp, "WLAN-ATIM");
   5.486 +        break;
   5.487 +      case 10: /* deassociation */
   5.488 +        decode_proto_add(dp, "WLAN-DEASSOC");
   5.489 +        break;
   5.490 +      case 11: /* authentication */
   5.491 +      case 12: /* DEauthentication */
   5.492 +        decode_proto_add(dp, "WLAN-AUTH");
   5.493 +        break;
   5.494 +      default:
   5.495 +        decode_proto_add(dp, "WLAN-MGMT-UNKN");
   5.496 +        break;
   5.497 +    }
   5.498 +}
   5.499 +
   5.500 +/* ieee802.11 wlans */
   5.501 +static void get_wlan(decode_proto_t *dp)
   5.502 +{
   5.503 +  uint16_t fc;
   5.504 +  uint8_t type;
   5.505 +  uint8_t subtype;
   5.506 +  uint8_t wep; 
   5.507 +
   5.508 +  decode_proto_add(dp, "IEE802.11"); /* experimental */
   5.509 +  if (dp->cur_len < 10)
   5.510 +    {
   5.511 +      g_warning (_("wlan:captured size too small, packet discarded"));
   5.512 +      return;
   5.513 +    }
   5.514 +  
   5.515 +  /* frame control: two bytes */
   5.516 +  fc = ntohs(*(guint16 *)(dp->cur_packet));
   5.517 + 
   5.518 +  /* dst node id is always present */
   5.519 +
   5.520 +  /* frame type is in bits 13-14 */
   5.521 +  type = (fc >> 10 ) & 0x03;
   5.522 +  subtype = (fc >> 12 ) & 0xff;
   5.523 +  wep = fc & 0x2;
   5.524 +  switch ( type )
   5.525 +    {
   5.526 +      case 2:
   5.527 +        /* data frame */
   5.528 +        dp->dst_node_id.node_type = LINK6;
   5.529 +        g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 4, 
   5.530 +                  sizeof(dp->dst_node_id.addr.eth));
   5.531 +        dp->src_node_id.node_type = LINK6;
   5.532 +        g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 10, 
   5.533 +                  sizeof(dp->src_node_id.addr.eth));
   5.534 +        add_offset(dp, 30);
   5.535 +        if (!wep)
   5.536 +          get_llc(dp);
   5.537 +        else
   5.538 +          decode_proto_add(dp, "WLAN-CRYPTED");
   5.539 +        break;
   5.540 +      case 0: /* mgmt frame */
   5.541 +        dp->dst_node_id.node_type = LINK6;
   5.542 +        g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 4, 
   5.543 +                  sizeof(dp->dst_node_id.addr.eth));
   5.544 +        dp->src_node_id.node_type = LINK6;
   5.545 +        g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 10, 
   5.546 +                  sizeof(dp->src_node_id.addr.eth));
   5.547 +        decode_wlan_mgmt(dp, subtype);
   5.548 +        break;
   5.549 +      case 1: /* control frame */
   5.550 +        /* these frames may have only a dst addr */
   5.551 +        dp->dst_node_id.node_type = LINK6;
   5.552 +        g_memmove(dp->dst_node_id.addr.eth, dp->cur_packet + 4, 
   5.553 +                  sizeof(dp->dst_node_id.addr.eth));
   5.554 +        if (subtype == 12)
   5.555 +          {
   5.556 +            dp->src_node_id.node_type = LINK6;
   5.557 +            g_memmove(dp->src_node_id.addr.eth, dp->cur_packet + 10, 
   5.558 +                      sizeof(dp->src_node_id.addr.eth));
   5.559 +          }
   5.560 +        decode_proto_add(dp, "WLAN-CTRL");
   5.561 +        break;
   5.562 +      default:
   5.563 +        g_warning (_("wlan:unknown frame type 0x%x, decode aborted"), type);
   5.564 +        return;
   5.565 +    }
   5.566 +}
   5.567 +
   5.568  /* Gets the protocol type out of the linux-sll header.
   5.569   * I have no real idea of what can be there, but since IP
   5.570   * is 0x800 I guess it follows ethernet specifications */
   5.571  static void
   5.572 -get_linux_sll_type (decode_proto_t *dp)
   5.573 +get_linux_sll (decode_proto_t *dp)
   5.574  {
   5.575    etype_t etype;
   5.576  
   5.577 +  decode_proto_add(dp, "LINUX-SLL");
   5.578 +
   5.579    etype = pntohs (&dp->cur_packet[14]);
   5.580 -  append_etype_prot (dp, etype);
   5.581  
   5.582    add_offset(dp, 16);
   5.583    if (etype == ETHERTYPE_IP)
   5.584      get_ip (dp);
   5.585 -  if (etype == ETHERTYPE_IPX)
   5.586 +  else if (etype == ETHERTYPE_IPX)
   5.587      get_ipx (dp);
   5.588 +  else
   5.589 +    append_etype_prot (dp, etype);
   5.590  }				/* get_linux_sll_type */
   5.591  
   5.592  static void
   5.593 @@ -370,6 +679,7 @@
   5.594    gboolean is_snap;
   5.595    guint16 control;
   5.596  
   5.597 +  decode_proto_add(dp, "LLC");
   5.598    if (dp->cur_len < 4)
   5.599      return;
   5.600    
   5.601 @@ -405,7 +715,7 @@
   5.602        decode_proto_add(dp, "PATHCTRL");
   5.603        break;
   5.604      case SAP_IP:
   5.605 -      decode_proto_add(dp, "IP");
   5.606 +      get_ip(dp);
   5.607        break;
   5.608      case SAP_SNA1:
   5.609        decode_proto_add(dp, "SNA1");
   5.610 @@ -486,6 +796,7 @@
   5.611    guint16 fragment_offset;
   5.612    iptype_t ip_type;
   5.613  
   5.614 +  decode_proto_add(dp, "IP");
   5.615    if (dp->cur_len < 20)
   5.616      return; 
   5.617    
   5.618 @@ -493,6 +804,17 @@
   5.619    fragment_offset = pntohs (dp->cur_packet + 6);
   5.620    fragment_offset &= 0x0fff;
   5.621  
   5.622 +  if (pref.mode !=  LINK6)
   5.623 +    {
   5.624 +      /* we want node higher level node ids */
   5.625 +      dp->dst_node_id.node_type = IP;
   5.626 +      g_memmove(dp->dst_node_id.addr.ip4, dp->cur_packet + 16, 
   5.627 +                sizeof(dp->dst_node_id.addr.ip4));
   5.628 +      dp->src_node_id.node_type = IP;
   5.629 +      g_memmove(dp->src_node_id.addr.ip4, dp->cur_packet + 12, 
   5.630 +                sizeof(dp->src_node_id.addr.ip4));
   5.631 +    }
   5.632 +
   5.633    /*This is used for conversations */
   5.634    dp->global_src_address = pntohl (dp->cur_packet + 12);
   5.635    dp->global_dst_address = pntohl (dp->cur_packet + 16);
   5.636 @@ -508,19 +830,13 @@
   5.637        if (fragment_offset)
   5.638  	decode_proto_add(dp, "TCP_FRAGMENT");
   5.639        else
   5.640 -	{
   5.641 -	  decode_proto_add(dp, "TCP");
   5.642 -	  get_tcp (dp);
   5.643 -	}
   5.644 +        get_tcp (dp);
   5.645        break;
   5.646      case IP_PROTO_UDP:
   5.647        if (fragment_offset)
   5.648  	decode_proto_add(dp, "UDP_FRAGMENT");
   5.649        else
   5.650 -	{
   5.651 -	  decode_proto_add(dp, "UDP");
   5.652 -	  get_udp (dp);
   5.653 -	}
   5.654 +        get_udp (dp);
   5.655        break;
   5.656      case IP_PROTO_IGMP:
   5.657        decode_proto_add(dp, "IGMP");
   5.658 @@ -715,7 +1031,6 @@
   5.659  static void
   5.660  get_tcp (decode_proto_t *dp)
   5.661  {
   5.662 -
   5.663    const port_service_t *src_service, *dst_service, *chosen_service;
   5.664    port_type_t src_port, dst_port, chosen_port;
   5.665    guint8 th_off_x2;
   5.666 @@ -724,8 +1039,27 @@
   5.667    gboolean src_pref = FALSE;
   5.668    gboolean dst_pref = FALSE;
   5.669  
   5.670 +  decode_proto_add(dp, "TCP");
   5.671    dp->global_src_port = src_port = pntohs (dp->cur_packet);
   5.672    dp->global_dst_port = dst_port = pntohs (dp->cur_packet + 2);
   5.673 +
   5.674 +  if (pref.mode ==  TCP)
   5.675 +    {
   5.676 +      /* tcp mode node ids have both addr and port - to work we need 
   5.677 +       * to already have an IP node id */
   5.678 +      g_assert(dp->dst_node_id.node_type == IP);
   5.679 +      dp->dst_node_id.node_type = TCP;
   5.680 +      g_memmove(dp->dst_node_id.addr.tcp4.host, dp->dst_node_id.addr.ip4, 
   5.681 +                sizeof(dp->dst_node_id.addr.tcp4.host));
   5.682 +      dp->dst_node_id.addr.tcp4.port = dp->global_dst_port;
   5.683 +
   5.684 +      g_assert(dp->src_node_id.node_type == IP);
   5.685 +      dp->src_node_id.node_type = TCP;
   5.686 +      g_memmove(dp->src_node_id.addr.tcp4.host, dp->src_node_id.addr.ip4, 
   5.687 +                sizeof(dp->src_node_id.addr.tcp4.host));
   5.688 +      dp->src_node_id.addr.tcp4.port = dp->global_src_port;
   5.689 +    }
   5.690 +
   5.691    th_off_x2 = *(guint8 *) (dp->cur_packet + 12);
   5.692    tcp_len = hi_nibble (th_off_x2) * 4;	/* TCP header length, in bytes */
   5.693  
   5.694 @@ -801,9 +1135,27 @@
   5.695    gboolean src_pref = FALSE;
   5.696    gboolean dst_pref = FALSE;
   5.697  
   5.698 +  decode_proto_add(dp, "UDP");
   5.699    dp->global_src_port = src_port = pntohs (dp->cur_packet);
   5.700    dp->global_dst_port = dst_port = pntohs (dp->cur_packet + 2);
   5.701  
   5.702 +  if (pref.mode ==  TCP)
   5.703 +    {
   5.704 +      /* tcp/udp mode node ids have both addr and port - to work we need 
   5.705 +       * to already have an IP node id */
   5.706 +      g_assert(dp->dst_node_id.node_type == IP);
   5.707 +      dp->dst_node_id.node_type = TCP;
   5.708 +      g_memmove(dp->dst_node_id.addr.tcp4.host, dp->dst_node_id.addr.ip4, 
   5.709 +                sizeof(dp->dst_node_id.addr.tcp4.host));
   5.710 +      dp->dst_node_id.addr.tcp4.port = dp->global_dst_port;
   5.711 +
   5.712 +      g_assert(dp->src_node_id.node_type == IP);
   5.713 +      dp->src_node_id.node_type = TCP;
   5.714 +      g_memmove(dp->src_node_id.addr.tcp4.host, dp->src_node_id.addr.ip4, 
   5.715 +                sizeof(dp->src_node_id.addr.tcp4.host));
   5.716 +      dp->src_node_id.addr.tcp4.port = dp->global_src_port;
   5.717 +    }
   5.718 +
   5.719    add_offset(dp, 8);
   5.720  
   5.721    /* It's not possible to know in advance whether an UDP
     6.1 --- a/src/decode_proto.h	Sat Oct 17 21:50:43 2009 +0200
     6.2 +++ b/src/decode_proto.h	Sun Oct 18 01:44:24 2009 +0200
     6.3 @@ -22,11 +22,10 @@
     6.4  #define DECODE_PROTO_H
     6.5  
     6.6  #include "pkt_info.h"
     6.7 +#include "node_id.h"
     6.8  
     6.9 -/* extracts the protocol stack from packet, and returs it as a newly allocated
    6.10 - * packet_protos_t */
    6.11 -packet_protos_t *get_packet_prot (const guint8 * packet, guint raw_size, 
    6.12 -                                  int link_type);
    6.13 -
    6.14 +gboolean has_linklevel(void); /* true if current device captures l2 data */ 
    6.15 +gboolean setup_link_type(int linktype);
    6.16 +void packet_acquired(guint8 * packet, guint raw_size, guint pkt_size);
    6.17  
    6.18  #endif
     7.1 --- a/src/menus.c	Sat Oct 17 21:50:43 2009 +0200
     7.2 +++ b/src/menus.c	Sun Oct 18 01:44:24 2009 +0200
     7.3 @@ -156,7 +156,7 @@
     7.4  void
     7.5  on_mode_radio_activate (GtkMenuItem * menuitem, gpointer user_data)
     7.6  {
     7.7 -  apemode_t new_mode = DEFAULT;
     7.8 +  apemode_t new_mode = APEMODE_DEFAULT;
     7.9    const gchar *menuname = NULL;
    7.10  
    7.11  
     8.1 --- a/src/names.c	Sat Oct 17 21:50:43 2009 +0200
     8.2 +++ b/src/names.c	Sun Oct 18 01:44:24 2009 +0200
     8.3 @@ -416,14 +416,13 @@
     8.4  
     8.5        numeric_name = g_strdup_printf("%s:%d",
     8.6                                       ip_to_str(nt->node_id.addr.tcp4.host),
     8.7 -                                     *(guint16 *) (nt->node_id.addr.tcp4.port));
     8.8 +                                     nt->node_id.addr.tcp4.port);
     8.9  
    8.10        resolved_name = g_strdup_printf("%s:%s",
    8.11                                        dns_lookup (
    8.12                                                    pntohl (nt->node_id.addr.tcp4.host), 
    8.13                                                    TRUE),
    8.14 -                                      get_tcp_port
    8.15 -                                         (*(guint16 *)(nt->node_id.addr.tcp4.port))
    8.16 +                                      get_tcp_port(nt->node_id.addr.tcp4.port)
    8.17                                       );
    8.18  
    8.19        add_name (numeric_name, resolved_name, TRUE, &nt->node_id, nt);
     9.1 --- a/src/node_id.c	Sat Oct 17 21:50:43 2009 +0200
     9.2 +++ b/src/node_id.c	Sun Oct 18 01:44:24 2009 +0200
     9.3 @@ -27,6 +27,12 @@
     9.4   *
     9.5   **************************************************************************/
     9.6  
     9.7 +void node_id_clear(node_id_t *a)
     9.8 +{
     9.9 +  memset(&a->addr, 0, sizeof(node_addr_t));
    9.10 +  a->node_type = APEMODE_DEFAULT;
    9.11 +}
    9.12 +
    9.13  /* Comparison function used to order the (GTree *) nodes
    9.14   * and canvas_nodes heard on the network */
    9.15  gint
    9.16 @@ -46,6 +52,8 @@
    9.17    /* same node type, compare */
    9.18    switch (na->node_type)
    9.19      {
    9.20 +    case APEMODE_DEFAULT:
    9.21 +      return 0; /* default has only one value */
    9.22      case LINK6:
    9.23        ga = na->addr.eth;
    9.24        gb = nb->addr.eth;
    9.25 @@ -85,6 +93,9 @@
    9.26    
    9.27    switch (id->node_type)
    9.28      {
    9.29 +    case APEMODE_DEFAULT:      
    9.30 +      msg = g_strdup("00:00:00:00:00:00");
    9.31 +      break;
    9.32      case LINK6:      
    9.33        msg = g_strdup(ether_to_str(id->addr.eth));
    9.34        break;
    9.35 @@ -93,7 +104,7 @@
    9.36        break;
    9.37      case TCP:
    9.38        msg = g_strdup_printf("%s:%d", ip_to_str (id->addr.tcp4.host), 
    9.39 -                            *(guint16 *) (id->addr.tcp4.port));
    9.40 +                            id->addr.tcp4.port);
    9.41        break;
    9.42      default:
    9.43        g_error("node_id_type %d unknown", (int) (id->node_type));
    9.44 @@ -110,6 +121,9 @@
    9.45    g_assert(id);
    9.46    switch (id->node_type)
    9.47      {
    9.48 +    case APEMODE_DEFAULT:
    9.49 +      msg = g_strdup_printf("NONE: 00:00:00:00:00:00");
    9.50 +      break;
    9.51      case LINK6:
    9.52        msg = g_strdup_printf("LINK: %s", ether_to_str(id->addr.eth));
    9.53        break;
    9.54 @@ -118,7 +132,7 @@
    9.55        break;
    9.56      case TCP:
    9.57        msg = g_strdup_printf("TCP/UDP: %s:%d", ip_to_str (id->addr.tcp4.host), 
    9.58 -                            *(guint16 *) (id->addr.tcp4.port));
    9.59 +                            id->addr.tcp4.port);
    9.60        break;
    9.61      default:
    9.62        msg = g_strdup_printf("node_id_type %d unknown", (int)(id->node_type));
    10.1 --- a/src/node_id.h	Sat Oct 17 21:50:43 2009 +0200
    10.2 +++ b/src/node_id.h	Sun Oct 18 01:44:24 2009 +0200
    10.3 @@ -28,7 +28,7 @@
    10.4    struct __attribute__ ((packed))
    10.5    {
    10.6        guint8 host[4];            /* tcp/udp address */
    10.7 -      guint8 port[2];            /* port number */
    10.8 +      guint16 port;            /* port number */
    10.9    } tcp4;
   10.10  
   10.11  } 
   10.12 @@ -40,6 +40,7 @@
   10.13    apemode_t node_type;
   10.14    node_addr_t addr;
   10.15  } node_id_t;
   10.16 +void node_id_clear(node_id_t *a);
   10.17  gint node_id_compare (const node_id_t *a, const node_id_t *b);
   10.18  /* returns a newly allocated string with a human-readable id */
   10.19  gchar *node_id_str(const node_id_t *id); 
    11.1 --- a/src/preferences.c	Sat Oct 17 21:50:43 2009 +0200
    11.2 +++ b/src/preferences.c	Sun Oct 18 01:44:24 2009 +0200
    11.3 @@ -135,7 +135,7 @@
    11.4      ("Diagram/link_node_ratio=1.0", &u);
    11.5    if (u)
    11.6      pref.link_node_ratio = 1.0;
    11.7 -  pref.mode = gnome_config_get_int_with_default ("General/mode=-1", &u);	/* DEFAULT */
    11.8 +  pref.mode = gnome_config_get_int_with_default ("General/mode=-1", &u);	/* APEMODE_DEFAULT */
    11.9    pref.refresh_period =
   11.10        gnome_config_get_int_with_default ("Diagram/refresh_period=100", &u);
   11.11