Add "class" that understands IPv4 addresses and subnet masks.
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 15 Nov 1999 06:32:38 +0000 (06:32 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 15 Nov 1999 06:32:38 +0000 (06:32 +0000)
We now store IPv4 addresses in host order, allowing non-equivalence
comparisons. That is, display filters with lt, le, gt, and ge will work
on big-endian and little-endian machines.

CIDR notation is now supported for IPv4 addresses in display filters.
You can test to see if an IPv4 address is on a certain subnet by using
this notation. For example, to test for IPv4 packets on a Class-C network:

ip.addr == 192.168.1.0/24

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@1032 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.am
dfilter-grammar.y
dfilter-int.h
dfilter.c
doc/ethereal.pod.template
ipv4.c [new file with mode: 0644]
ipv4.h [new file with mode: 0644]
proto.c
proto.h

index b7920d2ff45bfad97543bce0a2cd2062c73ba8ca..ff7d85943a080e5d64d9be4d19a8aa28a544e338 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.106 1999/11/11 23:13:42 nneul Exp $
+# $Id: Makefile.am,v 1.107 1999/11/15 06:32:10 gram Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@zing.org>
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@zing.org>
@@ -161,6 +161,8 @@ ethereal_SOURCES = \
        globals.h      \
        inet_v6defs.h  \
        ipproto.c      \
        globals.h      \
        inet_v6defs.h  \
        ipproto.c      \
+       ipv4.c         \
+       ipv4.h         \
        packet.c       \
        packet.h       \
        prefs.c        \
        packet.c       \
        packet.h       \
        prefs.c        \
index 7b3c7839fafe801da0f29bf116591d12413b9c80..55a05cbb7a7c7b14aaf53479d9d51068e9a0462c 100644 (file)
@@ -3,7 +3,7 @@
 /* dfilter-grammar.y
  * Parser for display filters
  *
 /* dfilter-grammar.y
  * Parser for display filters
  *
- * $Id: dfilter-grammar.y,v 1.36 1999/10/19 05:31:12 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.37 1999/11/15 06:32:11 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -86,7 +86,7 @@ static GNode* dfilter_mknode_ether_value(gchar*);
 static GNode* dfilter_mknode_ether_variable(gint id);
 static GNode* dfilter_mknode_ipxnet_value(guint32);
 static GNode* dfilter_mknode_ipxnet_variable(gint id);
 static GNode* dfilter_mknode_ether_variable(gint id);
 static GNode* dfilter_mknode_ipxnet_value(guint32);
 static GNode* dfilter_mknode_ipxnet_variable(gint id);
-static GNode* dfilter_mknode_ipv4_value(char *host);
+static GNode* dfilter_mknode_ipv4_value(char *host, int nmask_bits);
 static GNode* dfilter_mknode_ipv4_variable(gint id);
 static GNode* dfilter_mknode_ipv6_value(char *host);
 static GNode* dfilter_mknode_ipv6_variable(gint id);
 static GNode* dfilter_mknode_ipv4_variable(gint id);
 static GNode* dfilter_mknode_ipv6_value(char *host);
 static GNode* dfilter_mknode_ipv6_variable(gint id);
@@ -358,22 +358,77 @@ floating_value:   T_VAL_UNQUOTED_STRING
        ;
 
 ipv4_value:    T_VAL_UNQUOTED_STRING
        ;
 
 ipv4_value:    T_VAL_UNQUOTED_STRING
-               {
-                       $$ = dfilter_mknode_ipv4_value($1);
-                       g_free($1);
-                       if ($$ == NULL) {
-                               YYERROR;
-                       }
+       {
+               $$ = dfilter_mknode_ipv4_value($1, 32);
+               g_free($1);
+               if ($$ == NULL) {
+                       YYERROR;
                }
                }
+       }
 
        |       T_VAL_BYTE_STRING
 
        |       T_VAL_BYTE_STRING
-               {
-                       $$ = dfilter_mknode_ipv4_value($1);
+       {
+               $$ = dfilter_mknode_ipv4_value($1, 32);
+               g_free($1);
+               if ($$ == NULL) {
+                       YYERROR;
+               }
+       }
+
+       |       T_VAL_UNQUOTED_STRING '/' T_VAL_UNQUOTED_STRING
+       {
+               gboolean        success;
+               guint32         nmask_bits;
+
+               nmask_bits = string_to_guint32($3, &success);
+               if (!success) {
                        g_free($1);
                        g_free($1);
-                       if ($$ == NULL) {
-                               YYERROR;
-                       }
+                       g_free($3);
+                       YYERROR;
+               }
+
+               if (nmask_bits > 32) {
+                       dfilter_fail("The number of netmask bits in \"%s/%s\" should "
+                               "be between 0 and 32.", $1, $3);
+                       g_free($1);
+                       g_free($3);
+                       YYERROR;
                }
                }
+
+               $$ = dfilter_mknode_ipv4_value($1, nmask_bits);
+               g_free($1);
+               g_free($3);
+               if ($$ == NULL) {
+                       YYERROR;
+               }
+       }
+
+       |       T_VAL_BYTE_STRING '/' T_VAL_UNQUOTED_STRING
+       {
+               gboolean        success;
+               guint32         nmask_bits;
+
+               nmask_bits = string_to_guint32($3, &success);
+               if (!success) {
+                       g_free($1);
+                       g_free($3);
+                       YYERROR;
+               }
+
+               if (nmask_bits > 32) {
+                       dfilter_fail("The number of netmask bits in \"%s/%s\" should "
+                               "be between 0 and 32.", $1, $3);
+                       g_free($1);
+                       g_free($3);
+                       YYERROR;
+               }
+               $$ = dfilter_mknode_ipv4_value($1, nmask_bits);
+               g_free($1);
+               g_free($3);
+               if ($$ == NULL) {
+                       YYERROR;
+               }
+       }
        ;
 
 ipv6_value:    T_VAL_UNQUOTED_STRING
        ;
 
 ipv6_value:    T_VAL_UNQUOTED_STRING
@@ -640,9 +695,9 @@ dfilter_mknode_ipv4_variable(gint id)
 
        node = g_mem_chunk_alloc(global_df->node_memchunk);
        node->ntype = variable;
 
        node = g_mem_chunk_alloc(global_df->node_memchunk);
        node->ntype = variable;
-       node->elem_size = sizeof(guint32);
-       node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
-       node->check_relation_func = check_relation_numeric; /* cheating ! */
+       node->elem_size = sizeof(ipv4_addr);
+       node->fill_array_func = fill_array_ipv4_variable;
+       node->check_relation_func = check_relation_ipv4;
        node->value.variable = id;
        gnode = g_node_new(node);
 
        node->value.variable = id;
        gnode = g_node_new(node);
 
@@ -820,17 +875,18 @@ dfilter_mknode_ipxnet_value(guint32 ipx_net_val)
 
 /* Returns NULL on bad parse of IP value */
 static GNode*
 
 /* Returns NULL on bad parse of IP value */
 static GNode*
-dfilter_mknode_ipv4_value(char *host)
+dfilter_mknode_ipv4_value(char *host, int nmask_bits)
 {
        dfilter_node    *node;
        GNode           *gnode;
 {
        dfilter_node    *node;
        GNode           *gnode;
+       guint32         addr;
 
        node = g_mem_chunk_alloc(global_df->node_memchunk);
        node->ntype = numeric;
 
        node = g_mem_chunk_alloc(global_df->node_memchunk);
        node->ntype = numeric;
-       node->elem_size = sizeof(guint32);
-       node->fill_array_func = fill_array_numeric_value; /* cheating ! */
-       node->check_relation_func = check_relation_numeric; /* cheating ! */
-       if (!get_host_ipaddr(host, &node->value.numeric)) {
+       node->elem_size = sizeof(ipv4_addr);
+       node->fill_array_func = fill_array_ipv4_value;
+       node->check_relation_func = check_relation_ipv4;
+       if (!get_host_ipaddr(host, &addr)) {
                /* Rather than free the mem_chunk allocation, let it
                 * stay. It will be cleaned up when "dfilter_compile()"
                 * calls "dfilter_destroy()". */
                /* Rather than free the mem_chunk allocation, let it
                 * stay. It will be cleaned up when "dfilter_compile()"
                 * calls "dfilter_destroy()". */
@@ -838,7 +894,8 @@ dfilter_mknode_ipv4_value(char *host)
                    host);
                return NULL;
        }
                    host);
                return NULL;
        }
-       node->value.numeric = htonl(node->value.numeric);
+       ipv4_addr_set_host_order_addr(&node->value.ipv4, addr);
+       ipv4_addr_set_netmask_bits(&node->value.ipv4, nmask_bits);
 
        gnode = g_node_new(node);
        return gnode;
 
        gnode = g_node_new(node);
        return gnode;
index 05ad062d44b06a339b8282adfad748af28524a5d..f2d0f8b5508527e87ae23e9861667b721f86a6b5 100644 (file)
@@ -2,7 +2,7 @@
  * Definitions for routines common to multiple modules in the display
  * filter code, but not used outside that code.
  *
  * Definitions for routines common to multiple modules in the display
  * filter code, but not used outside that code.
  *
- * $Id: dfilter-int.h,v 1.10 1999/10/19 05:31:13 gram Exp $
+ * $Id: dfilter-int.h,v 1.11 1999/11/15 06:32:12 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #ifndef __DFILTER_INT_H__
 #define __DFILTER_INT_H__
 
 #ifndef __DFILTER_INT_H__
 #define __DFILTER_INT_H__
 
+#ifndef __IPV4_H__
+#include "ipv4.h"
+#endif
+
 /* in dfilter-scanner.l */
 GByteArray *byte_str_to_guint8_array(const char *s);
 void dfilter_scanner_text(char*);
 /* in dfilter-scanner.l */
 GByteArray *byte_str_to_guint8_array(const char *s);
 void dfilter_scanner_text(char*);
@@ -55,6 +59,7 @@ void dfilter_fail(char *fmt, ...);
 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b);
 gboolean check_relation_floating(gint operand, GArray *a, GArray *b);
 gboolean check_relation_ether(gint operand, GArray *a, GArray *b);
 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b);
 gboolean check_relation_floating(gint operand, GArray *a, GArray *b);
 gboolean check_relation_ether(gint operand, GArray *a, GArray *b);
+gboolean check_relation_ipv4(gint operand, GArray *a, GArray *b);
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b);
 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b);
 
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b);
 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b);
 
@@ -64,6 +69,8 @@ gboolean fill_array_floating_value(GNode *gnode, gpointer data);
 gboolean fill_array_floating_variable(GNode *gnode, gpointer data);
 gboolean fill_array_ether_value(GNode *gnode, gpointer data);
 gboolean fill_array_ether_variable(GNode *gnode, gpointer data);
 gboolean fill_array_floating_variable(GNode *gnode, gpointer data);
 gboolean fill_array_ether_value(GNode *gnode, gpointer data);
 gboolean fill_array_ether_variable(GNode *gnode, gpointer data);
+gboolean fill_array_ipv4_value(GNode *gnode, gpointer data);
+gboolean fill_array_ipv4_variable(GNode *gnode, gpointer data);
 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data);
 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data);
 gboolean fill_array_bytes_value(GNode *gnode, gpointer data);
 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data);
 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data);
 gboolean fill_array_bytes_value(GNode *gnode, gpointer data);
@@ -113,9 +120,10 @@ typedef struct dfilter_node {
 
                guint32         numeric;
                double          floating;
 
                guint32         numeric;
                double          floating;
-               struct timeval  abs_time; /* the whole struct, not a pointer */
+               struct timeval  abs_time;       /* the whole struct, not a pointer */
                gchar           *string;
                guint8          ether[6];
                gchar           *string;
                guint8          ether[6];
+               ipv4_addr       ipv4;           /* the whole struct, not a pointer */
                guint8          ipv6[16];
                GByteArray      *bytes;
        }                               value;
                guint8          ipv6[16];
                GByteArray      *bytes;
        }                               value;
index ef4aa7257d1bbe38f6cc8faa77d96ac36f7c7cb8..f948246535d7a1321caa941fb5e3c3963945c4e3 100644 (file)
--- a/dfilter.c
+++ b/dfilter.c
@@ -1,7 +1,7 @@
 /* dfilter.c
  * Routines for display filters
  *
 /* dfilter.c
  * Routines for display filters
  *
- * $Id: dfilter.c,v 1.31 1999/10/19 05:31:14 gram Exp $
+ * $Id: dfilter.c,v 1.32 1999/11/15 06:32:13 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -520,6 +520,17 @@ gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
+gboolean fill_array_ipv4_variable(GNode *gnode, gpointer data)
+{
+       proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
+       field_info              *fi = (field_info*) (gnode->data);
+
+       if (fi->hfinfo->id == sinfo->target) {
+               g_array_append_val(sinfo->result.array, fi->value.ipv4);
+       }
+
+       return FALSE; /* FALSE = do not end traversal of GNode tree */
+}
 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data)
 {
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data)
 {
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
@@ -598,6 +609,16 @@ gboolean fill_array_ether_value(GNode *gnode, gpointer data)
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
+gboolean fill_array_ipv4_value(GNode *gnode, gpointer data)
+{
+       GArray          *array = (GArray*)data;
+       dfilter_node    *dnode = (dfilter_node*) (gnode->data);
+
+       g_array_append_val(array, dnode->value.ipv4);
+
+       return FALSE; /* FALSE = do not end traversal of GNode tree */
+}
+
 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data)
 {
        GArray          *array = (GArray*)data;
 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data)
 {
        GArray          *array = (GArray*)data;
@@ -775,6 +796,87 @@ gboolean check_relation_floating(gint operand, GArray *a, GArray *b)
        return FALSE;
 }
 
        return FALSE;
 }
 
+gboolean check_relation_ipv4(gint operand, GArray *a, GArray *b)
+{
+       int             i, j, len_a, len_b;
+       ipv4_addr       *ptr_a, *ptr_b;
+
+       len_a = a->len;
+       len_b = b->len;
+
+
+       switch(operand) {
+       case TOK_EQ:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (ipv4_addr_eq(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_NE:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (!ipv4_addr_eq(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_GT:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (ipv4_addr_gt(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_GE:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (ipv4_addr_ge(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_LT:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (ipv4_addr_lt(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_LE:
+               for(i = 0; i < len_a; i++) {
+                       ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
+                       for (j = 0; j < len_b; j++) {
+                               ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
+                               if (ipv4_addr_le(ptr_a, ptr_b))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+       }
+
+       g_assert_not_reached();
+       return FALSE;
+}
+
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b)
 {
        int     i, j, len_a, len_b;
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b)
 {
        int     i, j, len_a, len_b;
index 4f747639c4acbc5755a93243820de231b8d7b3c3..2e333f563e97db1cbe636bd35f58c4170896f9d3 100644 (file)
@@ -509,6 +509,25 @@ IPv4 addresses can be represented in either dotted decimal notation, or by using
     ip.dst eq www.mit.edu
     ip.src == 192.168.1.1
 
     ip.dst eq www.mit.edu
     ip.src == 192.168.1.1
 
+IPv4 address can be compared with the same logical relations as numbers: eq, ne, gt,
+ge, lt, and le. The IPv4 address is stored in host order, so you do not have to worry
+about how the endianness of an IPv4 address when using it in a display filter.
+
+Classless InterDomain Routing (CIDR) notation can be used to test if an IPv4 address
+is in a certain subnet. For example, this display filter will find all packets
+in the 129.111 Class-B network:
+
+    ip.addr == 129.111.0.0/16
+
+Remember, the number after the slash represents the number of bits used to represent
+the network. CIDR notation can also be used with hostnames, in this example of finding
+IP addresses on the same Class C network as 'sneezy'
+
+    ip.addr eq sneezy/24
+
+The CIDR notation can only be used on IP addresses or hostnames, not in variable names.
+So, a display filter like "ip.src/24 == ip.dst/24" is not valid. (yet)
+
 IPX networks are represented by unsigned 32-bit integers. Most likely you will be using
 hexadecimal when testing for IPX network values:
 
 IPX networks are represented by unsigned 32-bit integers. Most likely you will be using
 hexadecimal when testing for IPX network values:
 
diff --git a/ipv4.c b/ipv4.c
new file mode 100644 (file)
index 0000000..1a7cd4b
--- /dev/null
+++ b/ipv4.c
@@ -0,0 +1,177 @@
+/* ipv4.c
+ *
+ * IPv4 address class. They understand how to take netmasks into consideration
+ * during equivalence testing.
+ *
+ * Gilbert Ramirez <gram@xiexie.org>
+ *
+ * $Id: ipv4.c,v 1.1 1999/11/15 06:32:14 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * Copyright 1998 Gerald Combs
+ *
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <stdio.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include "ipv4.h"
+
+static guint32 create_nmask(gint net_bits);
+
+ipv4_addr*
+ipv4_addr_new(void)
+{
+       ipv4_addr       *ipv4;
+
+       ipv4 = g_new(ipv4_addr, 1);
+       return ipv4;
+}
+
+void
+ipv4_addr_free(ipv4_addr *ipv4)
+{
+       if (ipv4)
+               g_free(ipv4);
+}
+
+void
+ipv4_addr_set_host_order_addr(ipv4_addr *ipv4, guint32 new_addr)
+{
+       ipv4->addr = new_addr;
+}
+
+void
+ipv4_addr_set_net_order_addr(ipv4_addr *ipv4, guint32 new_addr)
+{
+       ipv4->addr = ntohl(new_addr);
+}
+
+void
+ipv4_addr_set_netmask_bits(ipv4_addr *ipv4, guint new_nmask_bits)
+{
+/*     ipv4->nmask_bits = new_nmask_bits;*/
+       ipv4->nmask = create_nmask(new_nmask_bits);
+}
+
+guint32
+ipv4_get_net_order_addr(ipv4_addr *ipv4)
+{
+       return htonl(ipv4->addr);
+}
+
+guint32
+ipv4_get_host_order_addr(ipv4_addr *ipv4)
+{
+       return ipv4->addr;
+}
+
+
+static guint32
+create_nmask(gint net_bits)
+{
+       static guint32 bitmasks[33] = {
+               0x00000000,
+               0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
+               0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
+               0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
+               0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
+               0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
+               0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
+               0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
+               0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff,
+       };
+
+       g_assert(net_bits <= 32);
+
+       return bitmasks[net_bits];
+}
+
+
+
+/*
+ * w.x.y.z/32 eq w.x.y.0/24    TRUE
+ */
+
+/* Returns TRUE if equal, FALSE if not */
+gboolean
+ipv4_addr_eq(ipv4_addr *a, ipv4_addr *b)
+{
+       guint32 val_a, val_b, nmask;
+
+       nmask = MIN(a->nmask, b->nmask);
+       val_a = a->addr & nmask;
+       val_b = b->addr & nmask;
+       return (val_a == val_b);
+}
+
+gboolean
+ipv4_addr_gt(ipv4_addr *a, ipv4_addr *b)
+{
+       guint32 val_a, val_b, nmask;
+
+       nmask = MIN(a->nmask, b->nmask);
+       val_a = a->addr & nmask;
+       val_b = b->addr & nmask;
+
+       return (val_a > val_b);
+}
+
+gboolean
+ipv4_addr_ge(ipv4_addr *a, ipv4_addr *b)
+{
+       guint32 val_a, val_b, nmask;
+
+       nmask = MIN(a->nmask, b->nmask);
+       val_a = a->addr & nmask;
+       val_b = b->addr & nmask;
+
+       return (val_a >= val_b);
+}
+
+gboolean
+ipv4_addr_lt(ipv4_addr *a, ipv4_addr *b)
+{
+       guint32 val_a, val_b, nmask;
+
+       nmask = MIN(a->nmask, b->nmask);
+       val_a = a->addr & nmask;
+       val_b = b->addr & nmask;
+
+       return (val_a < val_b);
+}
+
+gboolean
+ipv4_addr_le(ipv4_addr *a, ipv4_addr *b)
+{
+       guint32 val_a, val_b, nmask;
+
+       nmask = MIN(a->nmask, b->nmask);
+       val_a = a->addr & nmask;
+       val_b = b->addr & nmask;
+
+       return (val_a <= val_b);
+}
diff --git a/ipv4.h b/ipv4.h
new file mode 100644 (file)
index 0000000..c6f4da9
--- /dev/null
+++ b/ipv4.h
@@ -0,0 +1,60 @@
+/* ip4.h
+ *
+ * IPv4 address class. They understand how to take netmasks into consideration
+ * during equivalence testing.
+ *
+ * Gilbert Ramirez <gramirez@tivoli.cm>
+ *
+ * $Id: ipv4.h,v 1.1 1999/11/15 06:32:14 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * Copyright 1998 Gerald Combs
+ *
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __IPV4_H__
+#define __IPV4_H__
+
+typedef struct {
+       guint32 addr;   /* stored in host order */
+       guint32 nmask;  /* stored in host order */
+} ipv4_addr;
+
+/* Allocate a new ipv4_addr struct, initialize it, and return pointer */
+ipv4_addr* ipv4_addr_new(void);
+
+/* Frees an ipv4 struct */
+void ipv4_addr_free(ipv4_addr *ipv4);
+
+void ipv4_addr_set_host_order_addr(ipv4_addr *ipv4, guint32 new_addr);
+void ipv4_addr_set_net_order_addr(ipv4_addr *ipv4, guint32 new_addr);
+void ipv4_addr_set_netmask_bits(ipv4_addr *ipv4, guint new_nmask_bits);
+
+guint32 ipv4_get_net_order_addr(ipv4_addr *ipv4);
+guint32 ipv4_get_host_order_addr(ipv4_addr *ipv4);
+
+/* Compares two ipv4_addrs, taking into account the less restrictive of the
+ * two netmasks, applying that netmask to both addrs.
+ */
+gboolean ipv4_addr_eq(ipv4_addr *a, ipv4_addr *b);
+gboolean ipv4_addr_gt(ipv4_addr *a, ipv4_addr *b);
+gboolean ipv4_addr_ge(ipv4_addr *a, ipv4_addr *b);
+gboolean ipv4_addr_lt(ipv4_addr *a, ipv4_addr *b);
+gboolean ipv4_addr_le(ipv4_addr *a, ipv4_addr *b);
+
+#endif
diff --git a/proto.c b/proto.c
index 1848a5648c05797135b2d5d2f055d96e0c910655..9e802035787d0e0d58929db7d36e82abae3fab13 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -1,7 +1,7 @@
 /* proto.c
  * Routines for protocol tree
  *
 /* proto.c
  * Routines for protocol tree
  *
- * $Id: proto.c,v 1.47 1999/11/11 16:20:25 nneul Exp $
+ * $Id: proto.c,v 1.48 1999/11/15 06:32:14 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -340,6 +340,10 @@ NOTES
                        break;
 
                case FT_IPv4:
                        break;
 
                case FT_IPv4:
+                       ipv4_addr_set_net_order_addr(&(fi->value.ipv4), va_arg(ap, unsigned int));
+                       ipv4_addr_set_netmask_bits(&(fi->value.ipv4), 32);
+                       break;
+
                case FT_IPXNET:
                        fi->value.numeric = va_arg(ap, unsigned int);
                        break;
                case FT_IPXNET:
                        fi->value.numeric = va_arg(ap, unsigned int);
                        break;
@@ -480,6 +484,7 @@ void
 proto_item_fill_label(field_info *fi, gchar *label_str)
 {
        struct header_field_info        *hfinfo = fi->hfinfo;
 proto_item_fill_label(field_info *fi, gchar *label_str)
 {
        struct header_field_info        *hfinfo = fi->hfinfo;
+       guint32                         n_addr; /* network-order IPv4 address */
 
        switch(hfinfo->type) {
                case FT_NONE:
 
        switch(hfinfo->type) {
                case FT_NONE:
@@ -569,10 +574,11 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        break;
 
                case FT_IPv4:
                        break;
 
                case FT_IPv4:
+                       n_addr = ipv4_get_net_order_addr(&fi->value.ipv4);
                        snprintf(label_str, ITEM_LABEL_LENGTH,
                                "%s: %s (%s)", fi->hfinfo->name,
                        snprintf(label_str, ITEM_LABEL_LENGTH,
                                "%s: %s (%s)", fi->hfinfo->name,
-                               get_hostname(fi->value.numeric),
-                               ip_to_str((guint8*)&fi->value.numeric));
+                               get_hostname(n_addr),
+                               ip_to_str((guint8*)&n_addr));
                        break;
 
                case FT_IPv6:
                        break;
 
                case FT_IPv6:
@@ -1009,7 +1015,8 @@ proto_registrar_is_protocol(int n)
                return FALSE;
 }
 
                return FALSE;
 }
 
-/* Returns length of field.
+/* Returns length of field in packet (not necessarily the length
+ * in our internal representation, as in the case of IPv4).
  * 0 means undeterminable at time of registration
  * -1 means the field is not registered. */
 gint
  * 0 means undeterminable at time of registration
  * -1 means the field is not registered. */
 gint
diff --git a/proto.h b/proto.h
index 23c6d9c22c9749f3f380338409f619d60d46ee7a..1dc7f5c1e3638ed6abc421ef90194e1b5397097f 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1,7 +1,7 @@
 /* proto.h
  * Definitions for protocol display
  *
 /* proto.h
  * Definitions for protocol display
  *
- * $Id: proto.h,v 1.18 1999/11/11 16:20:25 nneul Exp $
+ * $Id: proto.h,v 1.19 1999/11/15 06:32:15 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 # include <winsock.h>
 #endif
 
 # include <winsock.h>
 #endif
 
+#ifndef __IPV4_H__
+#include "ipv4.h"
+#endif
+
 /* needs glib.h */
 typedef struct GNode proto_tree;
 typedef struct GNode proto_item;
 /* needs glib.h */
 typedef struct GNode proto_tree;
 typedef struct GNode proto_item;
@@ -122,6 +126,7 @@ typedef struct field_info {
                gchar           *string;
                guint8          *bytes;
                guint8          ether[6];
                gchar           *string;
                guint8          *bytes;
                guint8          ether[6];
+               ipv4_addr       ipv4;
                guint8          ipv6[16];
        }                               value;
 } field_info;
                guint8          ipv6[16];
        }                               value;
 } field_info;