diff options
-rw-r--r-- | capture_info.c | 4 | ||||
-rw-r--r-- | epan/address.h | 3 | ||||
-rw-r--r-- | epan/address_to_str.c | 7 | ||||
-rw-r--r-- | epan/column-utils.c | 8 | ||||
-rw-r--r-- | epan/dfilter/semcheck.c | 5 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-ax25-kiss.c | 20 | ||||
-rw-r--r-- | epan/dissectors/packet-ax25.c | 630 | ||||
-rw-r--r-- | epan/dissectors/packet-ax25.h | 32 | ||||
-rw-r--r-- | epan/ftypes/ftype-bytes.c | 82 | ||||
-rw-r--r-- | epan/ftypes/ftypes.h | 2 | ||||
-rw-r--r-- | epan/libwireshark.def | 1 | ||||
-rw-r--r-- | epan/proto.c | 54 | ||||
-rw-r--r-- | epan/proto.h | 12 | ||||
-rw-r--r-- | epan/to_str.c | 24 | ||||
-rw-r--r-- | epan/to_str.h | 2 | ||||
-rw-r--r-- | wiretap/pcap-common.c | 1 | ||||
-rw-r--r-- | wiretap/wtap.c | 3 | ||||
-rw-r--r-- | wiretap/wtap.h | 1 |
19 files changed, 886 insertions, 7 deletions
diff --git a/capture_info.c b/capture_info.c index 9e7e584573..27fd1a6581 100644 --- a/capture_info.c +++ b/capture_info.c @@ -41,6 +41,7 @@ #include <epan/dissectors/packet-ap1394.h> #include <epan/dissectors/packet-atalk.h> #include <epan/dissectors/packet-atm.h> +#include <epan/dissectors/packet-ax25.h> #include <epan/dissectors/packet-clip.h> #include <epan/dissectors/packet-eth.h> #include <epan/dissectors/packet-fddi.h> @@ -355,6 +356,9 @@ capture_info_packet(packet_counts *counts, gint wtap_linktype, const guchar *pd, case WTAP_ENCAP_AX25_KISS: capture_ax25_kiss(pd, 0, caplen, counts); break; + case WTAP_ENCAP_AX25: + capture_ax25(pd, 0, caplen, counts); + break; /* XXX - some ATM drivers on FreeBSD might prepend a 4-byte ATM pseudo-header to DLT_ATM_RFC1483, with LLC header following; we might have to implement that at some point. */ diff --git a/epan/address.h b/epan/address.h index 7c6911e87a..9c87a9dfcb 100644 --- a/epan/address.h +++ b/epan/address.h @@ -55,8 +55,9 @@ typedef enum { AT_URI, /* URI/URL/URN */ AT_TIPC, /* TIPC Address Zone,Subnetwork,Processor */ AT_IB, /* Infiniband GID/LID */ - AT_USB /* USB Device address + AT_USB, /* USB Device address * (0xffffffff represents the host) */ + AT_AX25 /* AX.25 */ } address_type; typedef struct _address { diff --git a/epan/address_to_str.c b/epan/address_to_str.c index 9bd344e9f0..1965d88cee 100644 --- a/epan/address_to_str.c +++ b/epan/address_to_str.c @@ -586,6 +586,13 @@ address_to_str_buf(const address *addr, gchar *buf, int buf_len) case AT_IB: ib_addr_to_str_buf(addr, buf, buf_len); break; + case AT_AX25: + addrdata = addr->data; + g_snprintf(buf, buf_len, "%c%c%c%c%c%c-%02d", + (addrdata[0] >> 1) & 0x7f, (addrdata[1] >> 1) & 0x7f, (addrdata[2] >> 1) & 0x7f, + (addrdata[3] >> 1) & 0x7f, (addrdata[4] >> 1) & 0x7f, (addrdata[5] >> 1) & 0x7f, + (addrdata[6] >> 1) & 0x0f ); + break; default: g_assert_not_reached(); } diff --git a/epan/column-utils.c b/epan/column-utils.c index 59b2dae902..cffe5c5a12 100644 --- a/epan/column-utils.c +++ b/epan/column-utils.c @@ -1388,6 +1388,14 @@ col_set_addr(packet_info *pinfo, const int col, const address *addr, const gbool switch (addr->type) { + case AT_AX25: + if (is_src) + pinfo->cinfo->col_expr.col_expr[col] = "ax25.src"; + else + pinfo->cinfo->col_expr.col_expr[col] = "ax25.dst"; + g_strlcpy(pinfo->cinfo->col_expr.col_expr_val[col], ax25_to_str(addr->data), COL_MAX_LEN); + break; + case AT_ETHER: if (is_src) pinfo->cinfo->col_expr.col_expr[col] = "eth.src"; diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 2e27978892..3db5873c13 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -83,8 +83,9 @@ compatible_ftypes(ftenum_t a, ftenum_t b) case FT_UINT_BYTES: case FT_GUID: case FT_OID: + case FT_AX25: - return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID); + return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID || b == FT_AX25); case FT_BOOLEAN: case FT_FRAMENUM: @@ -165,6 +166,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) case FT_IPv4: case FT_IPv6: case FT_IPXNET: + case FT_AX25: case FT_ETHER: case FT_BYTES: case FT_UINT_BYTES: @@ -262,6 +264,7 @@ static gboolean is_bytes_type(enum ftenum type) { switch(type) { + case FT_AX25: case FT_ETHER: case FT_BYTES: case FT_UINT_BYTES: diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index a1a2ba2952..348b8a95f3 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -278,6 +278,7 @@ DISSECTOR_SRC = \ packet-atm.c \ packet-atmtcp.c \ packet-auto_rp.c \ + packet-ax25.c \ packet-ax25-kiss.c \ packet-ax4000.c \ packet-ayiya.c \ @@ -1194,6 +1195,7 @@ DISSECTOR_INCLUDES = \ packet-arp.h \ packet-atalk.h \ packet-atm.h \ + packet-ax25.h \ packet-ax25-kiss.h \ packet-bacapp.h \ packet-ber.h \ diff --git a/epan/dissectors/packet-ax25-kiss.c b/epan/dissectors/packet-ax25-kiss.c index ac0d3019aa..00c8b85708 100644 --- a/epan/dissectors/packet-ax25-kiss.c +++ b/epan/dissectors/packet-ax25-kiss.c @@ -118,6 +118,7 @@ #include <epan/etypes.h> #include "packet-ax25-kiss.h" +#include "packet-ax25.h" #define STRLEN 80 @@ -140,6 +141,8 @@ void proto_reg_handoff_ax25_kiss(void); /* Dissector handles - all the possibles are listed */ +static dissector_handle_t ax25_handle; + /* Initialize the protocol and registered fields */ static int proto_ax25_kiss = -1; @@ -174,17 +177,14 @@ dissect_ax25_kiss( tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree ) int kiss_param_len; char *frame_type_text; char *info_buffer; -#if 0 void *saved_private_data; tvbuff_t *next_tvb = NULL; -#endif info_buffer = ep_alloc( STRLEN ); info_buffer[0]='\0'; - if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) - col_set_str( pinfo->cinfo, COL_PROTOCOL, "KISS" ); + col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25 KISS" ); col_clear( pinfo->cinfo, COL_INFO ); @@ -280,6 +280,13 @@ dissect_ax25_kiss( tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree ) } /* Call sub-dissectors here */ + if ( kiss_type == KISS_DATA_FRAME ) + { + saved_private_data = pinfo->private_data; + next_tvb = tvb_new_subset( tvb, offset, -1, -1 ); + call_dissector( ax25_handle, next_tvb, pinfo, parent_tree ); + pinfo->private_data = saved_private_data; + } } void @@ -370,6 +377,9 @@ proto_reg_handoff_ax25_kiss(void) kiss_handle = create_dissector_handle( dissect_ax25_kiss, proto_ax25_kiss ); dissector_add_uint( "wtap_encap", WTAP_ENCAP_AX25_KISS, kiss_handle ); + /* only currently implemented for AX.25 */ + ax25_handle = find_dissector( "ax25" ); + inited = TRUE; } } @@ -390,7 +400,7 @@ capture_ax25_kiss( const guchar *pd, int offset, int len, packet_counts *ld) l_offset += KISS_HEADER_SIZE; /* step over kiss header */ switch ( kiss_cmd & KISS_CMD_MASK ) { - case KISS_DATA_FRAME : break; + case KISS_DATA_FRAME : capture_ax25( pd, l_offset, len, ld ); break; case KISS_TXDELAY : l_offset += 1; break; case KISS_PERSISTENCE : l_offset += 1; break; case KISS_SLOT_TIME : l_offset += 1; break; diff --git a/epan/dissectors/packet-ax25.c b/epan/dissectors/packet-ax25.c new file mode 100644 index 0000000000..dc42f02e82 --- /dev/null +++ b/epan/dissectors/packet-ax25.c @@ -0,0 +1,630 @@ +/* packet-ax25.c + * + * Routines for Amateur Packet Radio protocol dissection + * Copyright 2005,2006,2007,2008,2009,2010,2012 R.W. Stearn <richard@rns-stearn.demon.co.uk> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * 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. + */ + +/* + * This dissector is for: + * AX.25 Amateur Packet-Radio Link-Layer Protocol, Version 2.0, October 1984 + * + * At the time of writing the specification could be found here: + * http://www.tapr.org/pub_ax25.html + * + * Inspiration on how to build the dissector drawn from + * packet-sdlc.c + * packet-x25.c + * packet-lapb.c + * paket-gprs-llc.c + * xdlc.c + * with the base file built from README.developers. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/strutil.h> +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/emem.h> +#include <epan/xdlc.h> +#include <epan/etypes.h> +#include <epan/ipproto.h> +#include <packet-ip.h> + +#include "packet-ax25.h" + +#define STRLEN 80 + +#define AX25_ADDR_LEN 7 /* length of an AX.25 address */ +#define AX25_HEADER_SIZE 15 /* length of src_addr + dst_addr + cntl */ +#define AX25_MAX_DIGIS 8 + +/* Layer 3 Protocol ID's (pid) */ +#define AX25_P_ROSE 0x01 /* ISO 8208 / CCITT X.25 PLP */ +#define AX25_P_RFC1144C 0x06 /* Compressed TCP/IP packet. Van Jacobson RFC1144 */ +#define AX25_P_RFC1144 0x07 /* Uncompressed TCP/IP packet. Van Jacobson RFC1144 */ +#define AX25_P_SEGMENT 0x08 /* segmentation fragment */ +#define AX25_P_TEXNET 0xC3 /* TEXNET datagram */ +#define AX25_P_LCP 0xC4 /* Link Quality Protocol */ +#define AX25_P_ATALK 0xCA /* AppleTalk */ +#define AX25_P_ATALKARP 0xCB /* AppleTalk ARP */ +#define AX25_P_IP 0xCC /* ARPA Internet Protocol */ +#define AX25_P_ARP 0xCD /* ARPA Address Resolution Protocol */ +#define AX25_P_FLEXNET 0xCE /* FlexNet */ +#define AX25_P_NETROM 0xCF /* NET/ROM */ +#define AX25_P_NO_L3 0xF0 /* No layer 3 protocol */ +#define AX25_P_L3_ESC 0xFF /* Escape character. Next octet contains more layer 3 protocol info */ + +#define I_FRAME( control ) ( ( control & 0x01) == 0 ) +#define UI_FRAME( control ) ( ( ( control & 0x03) == 3 ) && ( ( ( ( ( control >> 5 ) & 0x07) << 2) | ( ( control >> 2 ) & 0x03) ) == 0 ) ) + +/* Forward declaration we need below */ +void proto_reg_handoff_ax25(void); + +/* Dissector handles - all the possibles are listed */ +static dissector_handle_t rose_handle; +static dissector_handle_t rfc1144c_handle; +static dissector_handle_t rfc1144_handle; +static dissector_handle_t segment_handle; +static dissector_handle_t texnet_handle; +static dissector_handle_t lcp_handle; +static dissector_handle_t atalk_handle; +static dissector_handle_t atalkarp_handle; +static dissector_handle_t ip_handle; +static dissector_handle_t arp_handle; +static dissector_handle_t flexnet_handle; +static dissector_handle_t netrom_handle; +static dissector_handle_t no_l3_handle; +static dissector_handle_t l3_esc_handle; +static dissector_handle_t default_handle; + +/* Initialize the protocol and registered fields */ +static int proto_ax25 = -1; +static int hf_ax25_dst = -1; +static int hf_ax25_src = -1; +static int hf_ax25_via[ AX25_MAX_DIGIS ] = { -1,-1,-1,-1,-1,-1,-1,-1 }; + +static int hf_ax25_ctl = -1; + +static int hf_ax25_n_r = -1; +static int hf_ax25_n_s = -1; + +static int hf_ax25_p = -1; +static int hf_ax25_f = -1; + +static int hf_ax25_ftype_s = -1; +static int hf_ax25_ftype_i = -1; +static int hf_ax25_ftype_su = -1; + +static int hf_ax25_u_cmd = -1; +static int hf_ax25_u_resp = -1; + +static int hf_ax25_pid = -1; + +static const xdlc_cf_items ax25_cf_items = { + &hf_ax25_n_r, + &hf_ax25_n_s, + &hf_ax25_p, + &hf_ax25_f, + &hf_ax25_ftype_s, + &hf_ax25_u_cmd, + &hf_ax25_u_resp, + &hf_ax25_ftype_i, + &hf_ax25_ftype_su +}; + +/* Global preference ("controls" display of numbers) */ +/* +static gboolean gPREF_HEX = FALSE; +*/ + +/* Initialize the subtree pointers */ +static gint ett_ax25 = -1; +static gint ett_ax25_ctl = -1; + +/* Code to actually dissect the packets */ +static void +dissect_ax25( tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree ) +{ + proto_item *ti; + proto_tree *ax25_tree; + int offset; + int control_offset; + int hdr_len; + int via_index; + char *info_buffer; + char v2cmdresp; + char *ax25_version; + int is_response; + char *text_ptr; + const guint8 *src_addr; + const guint8 *dst_addr; + const guint8 *via_addr; + guint8 control; + guint8 pid = AX25_P_NO_L3; + char *pid_text = NULL; + guint8 src_ssid; + guint8 dst_ssid; + void *saved_private_data; + tvbuff_t *next_tvb = NULL; + + + info_buffer = ep_alloc( STRLEN ); + info_buffer[0]='\0'; + + col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25" ); + + col_clear( pinfo->cinfo, COL_INFO ); + + /* protocol offset for an AX.25 packet */ + /* start at the dst addr */ + offset = 0; + + dst_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); + SET_ADDRESS( &pinfo->dl_dst, AT_AX25, AX25_ADDR_LEN, dst_addr ); + SET_ADDRESS( &pinfo->dst, AT_AX25, AX25_ADDR_LEN, dst_addr ); + dst_ssid = *(dst_addr + 6); + offset += AX25_ADDR_LEN; /* step over dst addr point at src addr */ + + src_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); + SET_ADDRESS( &pinfo->dl_src, AT_AX25, AX25_ADDR_LEN, src_addr ); + SET_ADDRESS( &pinfo->src, AT_AX25, AX25_ADDR_LEN, src_addr ); + src_ssid = *(src_addr + 6); + offset += AX25_ADDR_LEN; /* step over src addr point at either 1st via addr or control byte */ + + /* step over any vias */ + while ( ( tvb_get_guint8( tvb, offset - 1 ) & 0x01 ) == 0 ) + offset += AX25_ADDR_LEN; /* step over a via addr */ + + /* decode the cmd/resp field */ + v2cmdresp = '.'; + switch ( ( (dst_ssid >> 6) & 0x02) | ( (src_ssid >> 7) & 0x01 ) ) + { + case 1 : /* V2.0 Response */ + ax25_version = "V2.0+"; + v2cmdresp = 'R'; + is_response = TRUE; + break; + case 2 : /* V2.0 Command */ + ax25_version = "V2.0+"; + v2cmdresp = 'C'; + is_response = FALSE; + break; + default : + ax25_version = "V?.?"; + v2cmdresp = '?'; + is_response = FALSE; + break; + } + + /* decode the control field */ + control_offset = offset; + control = tvb_get_guint8( tvb, control_offset ); + + text_ptr = "????"; + switch ( control & 0x03 ) + { + case 1 : + switch ( ( control >> 2 ) & 0x03 ) + { + case 0 : text_ptr = "RR"; break; + case 1 : text_ptr = "RNR"; break; + case 2 : text_ptr = "REJ"; break; + case 3 : text_ptr = "SREJ"; break; + } + break; + case 3 : + switch ( ( ( ( control >> 5 ) & 0x07) << 2) | ( ( control >> 2 ) & 0x03) ) + { + case 0 : text_ptr = "UI"; break; + case 3 : text_ptr = "DM"; break; + case 7 : text_ptr = "SABM"; break; + case 8 : text_ptr = "DISC"; break; + case 12 : text_ptr = "UA"; break; + case 15 : text_ptr = "SABME"; break; + case 17 : text_ptr = "FRMR"; break; + case 23 : text_ptr = "XID"; break; + case 28 : text_ptr = "TEST"; break; + default : text_ptr = "????"; break; + } + break; + default : + text_ptr = "I"; + break; + } + g_snprintf( info_buffer, STRLEN, "%s", text_ptr ); + + /* decode the pid field (if appropriate) */ + if ( I_FRAME( control ) || UI_FRAME( control ) ) + { + offset += 1; /* step over control byte point at pid */ + pid = tvb_get_guint8( tvb, offset ); + switch ( pid ) + { + case AX25_P_ROSE : pid_text = "Rose" ; break; + case AX25_P_RFC1144C : pid_text = "RFC1144 (compressed)" ; break; + case AX25_P_RFC1144 : pid_text = "RFC1144 (uncompressed)" ; break; + case AX25_P_SEGMENT : pid_text = "Segment" ; break; + case AX25_P_TEXNET : pid_text = "Texnet" ; break; + case AX25_P_LCP : pid_text = "Link Quality protocol" ; break; + case AX25_P_ATALK : pid_text = "AppleTalk" ; break; + case AX25_P_ATALKARP : pid_text = "AppleTalk ARP" ; break; + case AX25_P_IP : pid_text = "IP" ; break; + case AX25_P_ARP : pid_text = "ARP" ; break; + case AX25_P_FLEXNET : pid_text = "FlexNet" ; break; + case AX25_P_NETROM : pid_text = "NetRom" ; break; + case AX25_P_NO_L3 : pid_text = "No L3" ; break; + case AX25_P_L3_ESC : pid_text = "L3 esc" ; break; + default : pid_text = "Unknown" ; break; + } + g_snprintf( info_buffer, STRLEN, "%s (%s)", info_buffer, pid_text ); + } + + col_add_str( pinfo->cinfo, COL_INFO, info_buffer ); + + if ( parent_tree ) + { + /* start at the dst addr */ + offset = 0; + + /* create display subtree for the protocol */ + hdr_len = AX25_HEADER_SIZE; + if ( I_FRAME( control ) || UI_FRAME( control ) ) + hdr_len += 1; + + ti = proto_tree_add_protocol_format( parent_tree, proto_ax25, tvb, offset, hdr_len, + "AX.25, Src: %s (%s), Dst: %s (%s), Ver: %s", + get_ax25_name( src_addr ), + ax25_to_str( src_addr ), + get_ax25_name( dst_addr ), + ax25_to_str( dst_addr ), + ax25_version + ); + + ax25_tree = proto_item_add_subtree( ti, ett_ax25 ); + + proto_tree_add_ax25( ax25_tree, hf_ax25_dst, tvb, offset, AX25_ADDR_LEN, dst_addr ); + + /* step over dst addr point at src addr */ + offset += AX25_ADDR_LEN; + proto_tree_add_ax25( ax25_tree, hf_ax25_src, tvb, offset, AX25_ADDR_LEN, src_addr ); + + /* step over src addr point at either 1st via addr or control byte */ + offset += AX25_ADDR_LEN; + + /* handle the vias, if any */ + via_index = 0; + while ( ( tvb_get_guint8( tvb, offset - 1 ) & 0x01 ) == 0 ) + { + if ( via_index < AX25_MAX_DIGIS ) + { + via_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); + proto_tree_add_ax25( ax25_tree, hf_ax25_via[ via_index ], tvb, offset, AX25_ADDR_LEN, via_addr ); + via_index++; + } + /* step over a via addr */ + offset += AX25_ADDR_LEN; + } + + dissect_xdlc_control( tvb, + control_offset, + pinfo, + ax25_tree, + hf_ax25_ctl, + ett_ax25_ctl, + &ax25_cf_items, + NULL, + NULL, + NULL, + is_response, + FALSE, + FALSE ); + + if ( I_FRAME( control ) || UI_FRAME( control ) ) + { + char *s; + + offset += 1; /* step over control byte point at pid */ + + s = ep_alloc( STRLEN ); + g_snprintf( s, STRLEN, "%s (0x%0x)", pid_text, pid ); + proto_tree_add_string( ax25_tree, hf_ax25_pid, tvb, offset, 1, s ); + } + } + + /* Call sub-dissectors here */ + + if ( I_FRAME( control ) || UI_FRAME( control ) ) + { + offset += 1; /* step over pid to the 1st byte of the payload */ + + saved_private_data = pinfo->private_data; + + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + + switch ( pid ) + { + case AX25_P_ROSE : call_dissector( rose_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_RFC1144C : call_dissector( rfc1144c_handle, next_tvb, pinfo, parent_tree ); break; + case AX25_P_RFC1144 : call_dissector( rfc1144_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_SEGMENT : call_dissector( segment_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_TEXNET : call_dissector( texnet_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_LCP : call_dissector( lcp_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_ATALK : call_dissector( atalk_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_ATALKARP : call_dissector( atalkarp_handle, next_tvb, pinfo, parent_tree ); break; + case AX25_P_IP : call_dissector( ip_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_ARP : call_dissector( arp_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_FLEXNET : call_dissector( flexnet_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_NETROM : call_dissector( netrom_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_NO_L3 : call_dissector( no_l3_handle , next_tvb, pinfo, parent_tree ); break; + case AX25_P_L3_ESC : call_dissector( l3_esc_handle , next_tvb, pinfo, parent_tree ); break; + default : call_dissector( default_handle , next_tvb, pinfo, parent_tree ); break; + } + pinfo->private_data = saved_private_data; + } +} + +void +proto_register_ax25(void) +{ + module_t *ax25_module; + static const true_false_string flags_set_truth = + { + "Set", + "Not set" + }; + + + /* Setup list of header fields */ + static hf_register_info hf[] = { + { &hf_ax25_dst, + { "Destination", "ax25.dst", + FT_AX25, BASE_NONE, NULL, 0x0, + "Destination callsign", HFILL } + }, + { &hf_ax25_src, + { "Source", "ax25.src", + FT_AX25, BASE_NONE, NULL, 0x0, + "Source callsign", HFILL } + }, + { &(hf_ax25_via[ 0 ]), + { "Via 1", "ax25.via1", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 1", HFILL } + }, + { &(hf_ax25_via[ 1 ]), + { "Via 2", "ax25.via2", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 2", HFILL } + }, + { &(hf_ax25_via[ 2 ]), + { "Via 3", "ax25.via3", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 3", HFILL } + }, + { &(hf_ax25_via[ 3 ]), + { "Via 4", "ax25.via4", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 4", HFILL } + }, + { &(hf_ax25_via[ 4 ]), + { "Via 5", "ax25.via5", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 5", HFILL } + }, + { &(hf_ax25_via[ 5 ]), + { "Via 6", "ax25.via6", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 6", HFILL } + }, + { &(hf_ax25_via[ 6 ]), + { "Via 7", "ax25.via7", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 7", HFILL } + }, + { &(hf_ax25_via[ 7 ]), + { "Via 8", "ax25.via8", + FT_AX25, BASE_NONE, NULL, 0x0, + "Via callsign 8", HFILL } + }, + { &hf_ax25_ctl, + { "Control", "ax25.ctl", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Control field", HFILL } + }, + { &hf_ax25_n_r, + { "n(r)", "ax25.ctl.n_r", + FT_UINT8, BASE_DEC, NULL, XDLC_N_R_MASK, + "", HFILL } + }, + { &hf_ax25_n_s, + { "n(s)", "ax25.ctl.n_s", + FT_UINT8, BASE_DEC, NULL, XDLC_N_S_MASK, + "", HFILL } + }, + { &hf_ax25_p, + { "Poll", "ax25.ctl.p", + FT_BOOLEAN, 8, TFS(&flags_set_truth), XDLC_P_F, + "", HFILL } + }, + { &hf_ax25_f, + { "Final", "ax25.ctl.f", + FT_BOOLEAN, 8, TFS(&flags_set_truth), XDLC_P_F, + "", HFILL } + }, + { &hf_ax25_ftype_s, + { "Frame type", "ax25.ctl.ftype_s", + FT_UINT8, BASE_HEX, VALS(stype_vals), XDLC_S_FTYPE_MASK, + "", HFILL } + }, + { &hf_ax25_ftype_i, + { "Frame type", "ax25.ctl.ftype_i", + FT_UINT8, BASE_HEX, VALS(ftype_vals), XDLC_I_MASK, + "", HFILL } + }, + { &hf_ax25_ftype_su, + { "Frame type", "ax25.ctl.ftype_su", + FT_UINT8, BASE_HEX, VALS(ftype_vals), XDLC_S_U_MASK, + "", HFILL } + }, + { &hf_ax25_u_cmd, + { "Frame type", "ax25.ctl.u_cmd", + FT_UINT8, BASE_HEX, VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, + "", HFILL } + }, + { &hf_ax25_u_resp, + { "Frame type", "ax25.ctl.u_resp", + FT_UINT8, BASE_HEX, VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, + "", HFILL } + }, + { &hf_ax25_pid, + { "Packet ID", "ax25.pid", + FT_STRING, BASE_NONE, NULL, 0x0, + "Packet identifier", HFILL } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_ax25, + &ett_ax25_ctl, + }; + + /* Register the protocol name and description */ + proto_ax25 = proto_register_protocol("Amateur Radio AX.25", "AX25", "ax25"); + + /* Register the dissector */ + register_dissector( "ax25", dissect_ax25, proto_ax25 ); + + /* Required function calls to register the header fields and subtrees used */ + proto_register_field_array( proto_ax25, hf, array_length(hf ) ); + proto_register_subtree_array(ett, array_length(ett ) ); + + /* Register preferences module */ + ax25_module = prefs_register_protocol( proto_ax25, proto_reg_handoff_ax25); + + /* Register any preference */ +/* + prefs_register_bool_preference(ax25_module, "showhex", + "Display numbers in Hex", + "Enable to display numerical values in hexadecimal.", + &gPREF_HEX ); +*/ +} + +void +proto_reg_handoff_ax25(void) +{ + static gboolean inited = FALSE; + + if( !inited ) { + + dissector_handle_t ax25_handle; + + ax25_handle = create_dissector_handle( dissect_ax25, proto_ax25 ); + dissector_add( "wtap_encap", WTAP_ENCAP_AX25, ax25_handle ); + dissector_add("ip.proto", IP_PROTO_AX25, ax25_handle); + + /* + I have added the "data" dissector for all the currently known PID's + This is so at least we have an entry in the tree that allows the + payload to be hightlighted. + When a new dissector is available all that needs to be done is to + replace the current dissector name "data" with the new dissector name. + */ + rose_handle = find_dissector( "data" /* "x.25" */ ); + rfc1144c_handle = find_dissector( "data" /* "rfc1144c" */ ); + rfc1144_handle = find_dissector( "data" /* "rfc1144" */ ); + segment_handle = find_dissector( "data" /* "segment" */ ); + texnet_handle = find_dissector( "data" /* "texnet" */ ); + lcp_handle = find_dissector( "data" /* "lcp" */ ); + atalk_handle = find_dissector( "data" /* "atalk" */ ); + atalkarp_handle = find_dissector( "data" /* "atalkarp" */ ); + ip_handle = find_dissector( "data" /* "ip" */ ); + arp_handle = find_dissector( "data" /* "arp" */ ); + flexnet_handle = find_dissector( "data" /* "flexnet" */ ); + netrom_handle = find_dissector( "data" /* "netrom" */ ); + no_l3_handle = find_dissector( "data" /* "ax25_nol3" */ ); + l3_esc_handle = find_dissector( "data" /* "l3_esc" */ ); + default_handle = find_dissector( "data" ); + + inited = TRUE; + } +} + +void +capture_ax25( const guchar *pd, int offset, int len, packet_counts *ld) +{ + guint8 control; + guint8 pid; + int l_offset; + +if ( ! BYTES_ARE_IN_FRAME( offset, len, AX25_HEADER_SIZE ) ) + { + ld->other++; + return; + } + +l_offset = offset; +l_offset += AX25_ADDR_LEN; /* step over dst addr point at src addr */ +l_offset += AX25_ADDR_LEN; /* step over src addr point at either 1st via addr or control byte */ +while ( ( pd[ l_offset - 1 ] & 0x01 ) == 0 ) + l_offset += AX25_ADDR_LEN; /* step over a via addr */ + +control = pd[ l_offset ]; + +/* decode the pid field (if appropriate) */ +if ( I_FRAME( control ) || UI_FRAME( control ) ) + { + l_offset += 1; /* step over control byte point at pid */ + pid = pd[ l_offset ]; + + l_offset += 1; /* step over the pid and point to the first byte of the payload */ + switch ( pid & 0x0ff ) + { + case AX25_P_ROSE : break; + case AX25_P_RFC1144C : break; + case AX25_P_RFC1144 : break; + case AX25_P_SEGMENT : break; + case AX25_P_TEXNET : break; + case AX25_P_LCP : break; + case AX25_P_ATALK : break; + case AX25_P_ATALKARP : break; + case AX25_P_IP : break; + case AX25_P_ARP : break; + case AX25_P_FLEXNET : break; + case AX25_P_NETROM : break; + case AX25_P_NO_L3 : break; + case AX25_P_L3_ESC : break; + default : break; + } + } +} diff --git a/epan/dissectors/packet-ax25.h b/epan/dissectors/packet-ax25.h new file mode 100644 index 0000000000..92aa652bfd --- /dev/null +++ b/epan/dissectors/packet-ax25.h @@ -0,0 +1,32 @@ +/* packet-ax25.h + * + * Routines for Amateur Packet Radio protocol dissection + * Copyright 2005,2006,2007,2008,2009,2010,2012 R.W. Stearn <richard@rns-stearn.demon.co.uk> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * 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 __PACKET_AX25_H__ +#define __PACKET_AX25_H__ + +void capture_ax25(const guchar *, int, int, packet_counts *); + +#endif diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c index 77712c71ba..4f5ab8ea3b 100644 --- a/epan/ftypes/ftype-bytes.c +++ b/epan/ftypes/ftype-bytes.c @@ -144,6 +144,13 @@ common_fvalue_set(fvalue_t *fv, guint8* data, guint len) } static void +ax25_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(!already_copied); + common_fvalue_set(fv, value, FT_AX25_ADDR_LEN); +} + +static void ether_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) { g_assert(!already_copied); @@ -210,6 +217,42 @@ bytes_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, Log } static gboolean +ax25_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc) +{ + gchar *mac; + + /* + * Don't log a message if this fails; we'll try looking it + * up as another way if it does, and if that fails, + * we'll log a message. + */ + if (bytes_from_unparsed(fv, s, TRUE, NULL)) { + if (fv->value.bytes->len > FT_AX25_ADDR_LEN) { + logfunc("\"%s\" contains too many bytes to be a valid AX.25 address.", + s); + return FALSE; + } + else if (fv->value.bytes->len < FT_AX25_ADDR_LEN && !allow_partial_value) { + logfunc("\"%s\" contains too few bytes to be a valid AX.25 address.", + s); + return FALSE; + } + + return TRUE; + } + + mac = get_ax25_name(s); + if (!mac) { + logfunc("\"%s\" is not a valid AX.25 address.", + s); + return FALSE; + } + + ax25_fvalue_set(fv, mac, FALSE); + return TRUE; +} + +static gboolean ether_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc) { guint8 *mac; @@ -536,6 +579,44 @@ ftype_register_bytes(void) slice, }; + static ftype_t ax25_type = { + FT_AX25, /* ftype */ + "FT_AX25", /* name */ + "AX.25 address", /* pretty_name */ + FT_AX25_ADDR_LEN, /* wire_size */ + bytes_fvalue_new, /* new_value */ + bytes_fvalue_free, /* free_value */ + ax25_from_unparsed, /* val_from_unparsed */ + NULL, /* val_from_string */ + bytes_to_repr, /* val_to_string_repr */ + bytes_repr_len, /* len_string_repr */ + + ax25_fvalue_set, /* set_value */ + NULL, /* set_value_uinteger */ + NULL, /* set_value_integer */ + NULL, /* set_value_integer64 */ + NULL, /* set_value_floating */ + + value_get, /* get_value */ + NULL, /* set_value_uinteger */ + NULL, /* get_value_integer */ + NULL, /* get_value_integer64 */ + NULL, /* get_value_floating */ + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + cmp_bitwise_and, + cmp_contains, + CMP_MATCHES, + + len, + slice, + }; + static ftype_t ether_type = { FT_ETHER, /* ftype */ "FT_ETHER", /* name */ @@ -614,6 +695,7 @@ ftype_register_bytes(void) ftype_register(FT_BYTES, &bytes_type); ftype_register(FT_UINT_BYTES, &uint_bytes_type); + ftype_register(FT_AX25, &ax25_type); ftype_register(FT_ETHER, ðer_type); ftype_register(FT_OID, &oid_type); } diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index 3b41664640..2b883908bb 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -63,6 +63,7 @@ enum ftenum { FT_GUID, /* GUID, UUID */ FT_OID, /* OBJECT IDENTIFIER */ FT_EUI64, + FT_AX25, FT_NUM_TYPES /* last item number plus one */ }; @@ -78,6 +79,7 @@ enum ftenum { #define FT_IPv6_LEN 16 #define FT_IPXNET_LEN 4 #define FT_EUI64_LEN 8 +#define FT_AX25_ADDR_LEN 7 typedef enum ftenum ftenum_t; typedef struct _ftype_t ftype_t; diff --git a/epan/libwireshark.def b/epan/libwireshark.def index f3ea4522ee..1b12e8c91e 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -49,6 +49,7 @@ camelSRTtype_naming DATA capture_ap1394 capture_arcnet capture_atm +capture_ax25 capture_ax25_kiss capture_chdlc capture_clip diff --git a/epan/proto.c b/epan/proto.c index d79c10b09a..2871f42061 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -198,6 +198,10 @@ proto_tree_set_string(field_info *fi, const char* value); static void proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding); static void +proto_tree_set_ax25(field_info *fi, const guint8* value); +static void +proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start); +static void proto_tree_set_ether(field_info *fi, const guint8* value); static void proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start); @@ -1342,6 +1346,11 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, proto_tree_set_ipv6_tvb(new_fi, tvb, start, length); break; + case FT_AX25: + DISSECTOR_ASSERT(length == 7); + proto_tree_set_ax25_tvb(new_fi, tvb, start); + break; + case FT_ETHER: DISSECTOR_ASSERT(length == FT_ETHER_LEN); proto_tree_set_ether_tvb(new_fi, tvb, start); @@ -2609,6 +2618,44 @@ proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length proto_tree_set_string(fi, string); } + +/* Add a FT_AX25 to a proto_tree */ +proto_item * +proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, + const guint8* value) +{ + proto_item *pi; + field_info *new_fi; + header_field_info *hfinfo; + + if (!tree) + return (NULL); + + TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo); + + PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); + DISSECTOR_ASSERT(hfinfo->type == FT_AX25); + + pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi); + proto_tree_set_ax25(new_fi, value); + + return pi; +} + +/* Set the FT_AX25 value */ +static void +proto_tree_set_ax25(field_info *fi, const guint8* value) +{ + fvalue_set(&fi->value, (gpointer) value, FALSE); +} + +static void +proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start) +{ + proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7)); +} + + /* Add a FT_ETHER to a proto_tree */ proto_item * proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, @@ -5330,6 +5377,13 @@ proto_item_fill_label(field_info *fi, gchar *label_str) get_ipxnet_name(integer), integer); break; + case FT_AX25: + bytes = fvalue_get(&fi->value); + label_fill_descr(label_str, hfinfo, + get_ax25_name(bytes), + ax25_to_str(bytes)); + break; + case FT_ETHER: bytes = fvalue_get(&fi->value); label_fill_descr(label_str, hfinfo, diff --git a/epan/proto.h b/epan/proto.h index 91e4d04f92..5412125279 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -1039,6 +1039,18 @@ extern proto_item * proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const guint8* value_ptr, const char *format, ...) G_GNUC_PRINTF(7,8); +/** Add a FT_AX25 to a proto_tree. + @param tree the tree to append this item to + @param hfindex field index + @param tvb the tv buffer of the current data + @param start start of data in tvb + @param length length of data in tvb + @param value data to display + @return the newly created item */ +extern proto_item * +proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, + gint length, const guint8* value); + /** Add a FT_ETHER to a proto_tree. @param tree the tree to append this item to @param hfindex field index diff --git a/epan/to_str.c b/epan/to_str.c index cda834f11c..f173816b65 100644 --- a/epan/to_str.c +++ b/epan/to_str.c @@ -1024,6 +1024,30 @@ decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width, return buf; } +/* XXX FIXME +remove this one later when every call has been converted to address_to_str() +*/ +gchar * +ax25_to_str(const guint8 *ad) +{ + return bytestring_to_str(ad, 7, ':'); +} + +/* XXX FIXME +remove this one later when every call has been converted to address_to_str() +*/ +gchar * +get_ax25_name(const guint8 *ad) +{ + address addr; + + addr.type = AT_AX25; + addr.len = 7; + addr.data = ad; + + return address_to_str( &addr ); +} + /* This function is very fast and this function is called a lot. XXX update the ep_address_to_str stuff to use this function. diff --git a/epan/to_str.h b/epan/to_str.h index 2dd0d100e2..cf1dae30d8 100644 --- a/epan/to_str.h +++ b/epan/to_str.h @@ -53,6 +53,8 @@ extern void address_to_str_buf(const address *addr, gchar *buf, int buf_len) extern gchar* bytestring_to_str(const guint8 *, const guint32, const char); extern gchar* ether_to_str(const guint8 *); extern gchar* tvb_ether_to_str(tvbuff_t *tvb, const gint offset); +extern gchar* ax25_to_str(const guint8 *); +extern gchar* get_ax25_name(const guint8 *); extern const gchar* ip_to_str(const guint8 *); extern const gchar* tvb_ip_to_str(tvbuff_t *tvb, const gint offset); extern void ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len); diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c index b43a504326..f1655020d6 100644 --- a/wiretap/pcap-common.c +++ b/wiretap/pcap-common.c @@ -87,6 +87,7 @@ static const struct { */ { 0, WTAP_ENCAP_NULL }, /* null encapsulation */ { 1, WTAP_ENCAP_ETHERNET }, + { 3, WTAP_ENCAP_AX25 }, { 6, WTAP_ENCAP_TOKEN_RING }, /* IEEE 802 Networks - assume token ring */ { 7, WTAP_ENCAP_ARCNET }, { 8, WTAP_ENCAP_SLIP }, diff --git a/wiretap/wtap.c b/wiretap/wtap.c index 9431af403b..204c1e2b00 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -595,6 +595,9 @@ static struct encap_type_info encap_table_base[] = { /* WTAP_ENCAP_AX25_KISS */ { "AX.25 with KISS header", "ax25-kiss" }, + + /* WTAP_ENCAP_AX25 */ + { "Amateur Radio AX.25", "ax25" }, }; gint wtap_num_encap_types = sizeof(encap_table_base) / sizeof(struct encap_type_info); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 9a55ce543f..9e0397af17 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -238,6 +238,7 @@ extern "C" { #define WTAP_ENCAP_SDH 146 #define WTAP_ENCAP_DBUS 147 #define WTAP_ENCAP_AX25_KISS 148 +#define WTAP_ENCAP_AX25 149 #define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types() |