The Appletalk ARP opcode, like other AARP fields, is big-endian, not
[obnox/wireshark/wip.git] / packet-aarp.c
1 /* packet-aarp.c
2  * Routines for Appletalk ARP packet disassembly
3  *
4  * Simon Wilkinson <sxw@dcs.ed.ac.uk>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <gtk/gtk.h>
26
27 #include <stdio.h>
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
35 #endif
36
37 #include "ethereal.h"
38 #include "packet.h"
39 #include "etypes.h"
40
41 typedef struct _e_ether_aarp {
42         guint16 htype, ptype;
43         guint8  halen, palen;
44         guint16 op;
45         guint8  hsaddr[6];
46         guint8  psaddr[4];
47         guint8  hdaddr[6];
48         guint8  pdaddr[4];
49 } e_ether_aarp;
50
51 #ifndef AARP_REQUEST
52 #define AARP_REQUEST    0x0001
53 #endif
54 #ifndef AARP_REPLY
55 #define AARP_REPLY      0x0002
56 #endif
57 #ifndef AARP_PROBE      
58 #define AARP_PROBE      0x0003
59 #endif
60
61 gchar *
62 atalkid_to_str(guint8 *ad) {
63   gint node;
64   static gchar  str[3][16];
65   static gchar *cur;
66   
67   if (cur == &str[0][0]) {
68     cur = &str[1][0];
69   } else if (cur == &str[1][0]) {  
70     cur = &str[2][0];
71   } else {  
72     cur = &str[0][0];
73   }
74   
75   node=ad[1]<<8|ad[2];
76   sprintf(cur, "%d.%d",node,ad[3]);
77   return cur;
78 }
79     
80 void
81 dissect_aarp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
82   e_ether_aarp  ea;
83   GtkWidget   *aarp_tree, *ti;
84   gchar       *op_str;
85   value_string op_vals[] = { {AARP_REQUEST,  "AARP request" },
86                              {AARP_REPLY,    "AARP reply"   },
87                              {AARP_PROBE,    "AARP probe"   },
88                              {0,             NULL           } };
89
90   ea.htype = pntohs(&pd[offset]);
91   ea.ptype = pntohs(&pd[offset + 2]);
92   ea.halen = (guint8) pd[offset + 4];
93   ea.palen = (guint8) pd[offset + 5];
94   ea.op  = pntohs(&pd[offset + 6]);
95   memcpy(&ea.hsaddr, &pd[offset +  8], 6);
96   memcpy(&ea.psaddr, &pd[offset + 14], 4);
97   memcpy(&ea.hdaddr, &pd[offset + 18], 6);
98   memcpy(&ea.pdaddr, &pd[offset + 24], 4);
99   
100   if(check_col(fd, COL_PROTOCOL))
101     col_add_str(fd, COL_PROTOCOL, "AARP");
102   
103   if (tree) {
104     if ((op_str = match_strval(ea.op, op_vals)))
105       ti = add_item_to_tree(GTK_WIDGET(tree), offset, 28, op_str);
106     else
107       ti = add_item_to_tree(GTK_WIDGET(tree), offset, 28,
108         "Unknown AARP (opcode 0x%04x)", ea.op);
109     aarp_tree = gtk_tree_new();
110     add_subtree(ti, aarp_tree, ETT_AARP);
111     add_item_to_tree(aarp_tree, offset,      2,
112       "Hardware type: 0x%04x", ea.htype);
113     add_item_to_tree(aarp_tree, offset +  2, 2,
114       "Protocol type: 0x%04x", ea.ptype);
115     add_item_to_tree(aarp_tree, offset +  4, 1,
116       "Hardware size: 0x%02x", ea.halen);
117     add_item_to_tree(aarp_tree, offset +  5, 1,
118       "Protocol size: 0x%02x", ea.palen);
119     add_item_to_tree(aarp_tree, offset +  6, 2,
120       "Opcode: 0x%04x (%s)", ea.op, op_str ? op_str : "Unknown");
121     add_item_to_tree(aarp_tree, offset +  8, 6,
122       "Sender ether: %s", ether_to_str((guint8 *) ea.hsaddr));
123     add_item_to_tree(aarp_tree, offset + 14, 4,
124       "Sender ID: %s", atalkid_to_str((guint8 *) ea.psaddr));
125     add_item_to_tree(aarp_tree, offset + 18, 6,
126       "Target ether: %s", ether_to_str((guint8 *) ea.hdaddr));
127     add_item_to_tree(aarp_tree, offset + 24, 4,
128       "Target ID: %s", atalkid_to_str((guint8 *) ea.pdaddr));
129   }
130
131   if (ea.ptype != ETHERTYPE_AARP && ea.ptype != ETHERTYPE_ATALK && 
132       check_col(fd, COL_INFO)) {
133     col_add_fstr(fd, COL_INFO, "h/w %d (%d) prot %d (%d) op 0x%04x",
134       ea.htype, ea.halen, ea.ptype, ea.palen, ea.op);
135     return;
136   }
137   if (check_col(fd, COL_INFO)) {
138     switch (ea.op) {
139       case AARP_REQUEST:
140         col_add_fstr(fd, COL_INFO, "Who has %s?  Tell %s",
141           atalkid_to_str((guint8 *) ea.pdaddr), atalkid_to_str((guint8 *) ea.psaddr));
142         break;
143       case AARP_REPLY:
144         col_add_fstr(fd, COL_INFO, "%s is at %s",
145           atalkid_to_str((guint8 *) ea.psaddr),
146           ether_to_str((guint8 *) ea.hsaddr));
147         break;
148       case AARP_PROBE:
149         col_add_fstr(fd, COL_INFO, "Is there a %s",
150           atalkid_to_str((guint8 *) ea.pdaddr));
151         break;
152     }
153   }
154 }