Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-who.c
1 /* packet-who.c
2  * Routines for who protocol (see man rwhod)
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * $Id: packet-who.c,v 1.24 2002/08/02 23:36:04 jmayer Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31 #include <time.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34
35
36 /*
37  *
38 RWHOD(8)                 UNIX System Manager's Manual                 RWHOD(8)
39
40
41      The messages sent and received, are of the form:
42
43            struct  outmp {
44 0                   char    out_line[8];             tty name 
45 8                   char    out_name[8];             user id 
46 16                   long    out_time;               time on 
47            };
48
49            struct  whod {
50  0                   char    wd_vers;
51  1                   char    wd_type;
52  2                   char    wd_fill[2];
53  4                   int     wd_sendtime;
54  8                   int     wd_recvtime;
55 12                   char    wd_hostname[32];
56 44                   int     wd_loadav[3];
57 56                   int     wd_boottime;
58 60                   struct  whoent {
59                            struct  outmp we_utmp;
60 (20 each)                  int     we_idle;
61                    } wd_we[1024 / sizeof (struct whoent)];
62            };
63
64  Linux 2.0                       May 13, 1997                                2
65
66  *
67  */
68
69 static int proto_who = -1;
70 static int hf_who_vers = -1;
71 static int hf_who_type = -1;
72 static int hf_who_sendtime = -1;
73 static int hf_who_recvtime = -1;
74 static int hf_who_hostname = -1;
75 static int hf_who_loadav_5 = -1;
76 static int hf_who_loadav_10 = -1;
77 static int hf_who_loadav_15 = -1;
78 static int hf_who_boottime = -1;
79 static int hf_who_whoent = -1;
80 static int hf_who_tty = -1;
81 static int hf_who_uid = -1;
82 static int hf_who_timeon = -1;
83 static int hf_who_idle = -1;
84
85 static gint ett_who = -1;
86 static gint ett_whoent = -1;
87
88 #define UDP_PORT_WHO    513
89
90 static void dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree);
91
92 static void
93 dissect_who(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
94 {
95         int             offset = 0;
96         proto_tree      *who_tree = NULL;
97         proto_item      *who_ti = NULL;
98         gchar           server_name[33];
99         double          loadav_5 = 0.0, loadav_10 = 0.0, loadav_15 = 0.0;
100         nstime_t        ts;
101
102         /* Summary information */
103         if (check_col(pinfo->cinfo, COL_PROTOCOL))
104                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WHO");
105         if (check_col(pinfo->cinfo, COL_INFO))
106                 col_clear(pinfo->cinfo, COL_INFO);
107
108         ts.nsecs = 0;
109
110         if (tree) {
111                 who_ti = proto_tree_add_item(tree, proto_who, tvb, offset, -1,
112                     FALSE);
113                 who_tree = proto_item_add_subtree(who_ti, ett_who);
114         }
115
116         if (tree)
117                 proto_tree_add_item(who_tree, hf_who_vers, tvb, offset, 1, FALSE);
118         offset += 1;
119
120         if (tree)
121                 proto_tree_add_item(who_tree, hf_who_type, tvb, offset, 1, FALSE);
122         offset += 1;
123
124         /* 2 filler bytes */
125         offset += 2;
126
127         if (tree) {
128                 ts.secs = tvb_get_ntohl(tvb, offset);
129                 proto_tree_add_time(who_tree, hf_who_sendtime, tvb, offset, 4,
130                     &ts);
131         }
132         offset += 4;
133
134         if (tree) {
135                 ts.secs = tvb_get_ntohl(tvb, offset);
136                 proto_tree_add_time(who_tree, hf_who_recvtime, tvb, offset, 4,
137                     &ts);
138         }
139         offset += 4;
140
141         tvb_get_nstringz0(tvb, offset, 32, server_name);
142         if (tree)
143                 proto_tree_add_string(who_tree, hf_who_hostname, tvb, offset,
144                     32, server_name);
145         offset += 32;
146
147         loadav_5  = (double) tvb_get_ntohl(tvb, offset) / 100.0;
148         if (tree)
149                 proto_tree_add_double(who_tree, hf_who_loadav_5, tvb, offset,
150                     4, loadav_5);
151         offset += 4;
152
153         loadav_10 = (double) tvb_get_ntohl(tvb, offset) / 100.0;
154         if (tree)
155                 proto_tree_add_double(who_tree, hf_who_loadav_10, tvb, offset,
156                     4, loadav_10);
157         offset += 4;
158
159         loadav_15 = (double) tvb_get_ntohl(tvb, offset) / 100.0;
160         if (tree)
161                 proto_tree_add_double(who_tree, hf_who_loadav_15, tvb, offset,
162                     4, loadav_15);
163         offset += 4;
164
165         /* Summary information */
166         if (check_col(pinfo->cinfo, COL_INFO))
167                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %.02f %.02f %.02f",
168                                 server_name, loadav_5, loadav_10, loadav_15);
169
170         if (tree) {
171                 ts.secs = tvb_get_ntohl(tvb, offset);
172                 proto_tree_add_time(who_tree, hf_who_boottime, tvb, offset, 4,
173                     &ts);
174                 offset += 4;
175
176                 dissect_whoent(tvb, offset, who_tree);
177         }
178 }
179
180 /* The man page says that (1024 / sizeof(struct whoent)) is the maximum number
181  * of whoent structures in the packet. */
182 #define SIZE_OF_WHOENT  24
183 #define MAX_NUM_WHOENTS (1024 / SIZE_OF_WHOENT)
184
185 static void
186 dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree)
187 {
188         proto_tree      *whoent_tree = NULL;
189         proto_item      *whoent_ti = NULL;
190         int             line_offset = offset;
191         gchar           out_line[9];    
192         gchar           out_name[9];    
193         nstime_t        ts;
194         int             whoent_num = 0;
195         guint32         idle_secs; /* say that out loud... */
196
197         ts.nsecs = 0;
198
199         while (tvb_reported_length_remaining(tvb, line_offset) > 0
200             && whoent_num < MAX_NUM_WHOENTS) {
201                 whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb,
202                     line_offset, SIZE_OF_WHOENT, FALSE);
203                 whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent);
204
205                 tvb_get_nstringz0(tvb, line_offset, 8, out_line);
206                 proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset,
207                     8, out_line);
208                 line_offset += 8;
209
210                 tvb_get_nstringz0(tvb, line_offset, 8, out_name);
211                 proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset,
212                     8, out_name);
213                 line_offset += 8;
214
215                 ts.secs = tvb_get_ntohl(tvb, line_offset);
216                 proto_tree_add_time(whoent_tree, hf_who_timeon, tvb,
217                     line_offset, 4, &ts);
218                 line_offset += 4;
219
220                 idle_secs = tvb_get_ntohl(tvb, line_offset);
221                 proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb,
222                     line_offset, 4, idle_secs, "Idle: %s",
223                     time_secs_to_str(idle_secs));
224                 line_offset += 4;
225
226                 whoent_num++;
227         }
228 }
229
230 void
231 proto_register_who(void)
232 {
233         static hf_register_info hf[] = {
234                 { &hf_who_vers,
235                 { "Version",    "who.vers", FT_UINT8, BASE_DEC, NULL, 0x0,
236                         "", HFILL }},
237
238                 { &hf_who_type,
239                 { "Type",       "who.type", FT_UINT8, BASE_DEC, NULL, 0x0,
240                         "", HFILL }},
241
242                 { &hf_who_sendtime,
243                 { "Send Time",  "who.sendtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
244                         "", HFILL }},
245
246                 { &hf_who_recvtime,
247                 { "Receive Time", "who.recvtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
248                         "", HFILL }},
249
250                 { &hf_who_hostname,
251                 { "Hostname", "who.hostname", FT_STRING, BASE_NONE, NULL, 0x0,
252                         "", HFILL }},
253
254                 { &hf_who_loadav_5,
255                 { "Load Average Over Past  5 Minutes", "who.loadav_5", FT_DOUBLE, BASE_NONE, NULL, 0x0,
256                         "", HFILL }},
257
258                 { &hf_who_loadav_10,
259                 { "Load Average Over Past 10 Minutes", "who.loadav_10", FT_DOUBLE, BASE_NONE, NULL, 0x0,
260                         "", HFILL }},
261
262                 { &hf_who_loadav_15,
263                 { "Load Average Over Past 15 Minutes", "who.loadav_15", FT_DOUBLE, BASE_NONE, NULL, 0x0,
264                         "", HFILL }},
265
266                 { &hf_who_boottime,
267                 { "Boot Time", "who.boottime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
268                         "", HFILL }},
269
270                 { &hf_who_whoent,
271                 { "Who utmp Entry", "who.whoent", FT_NONE, BASE_NONE, NULL, 0x0,
272                         "", HFILL }},
273
274                 { &hf_who_tty,
275                 { "TTY Name", "who.tty", FT_STRING, BASE_NONE, NULL, 0x0,
276                         "", HFILL }},
277
278                 { &hf_who_uid,
279                 { "User ID", "who.uid", FT_STRING, BASE_NONE, NULL, 0x0,
280                         "", HFILL }},
281
282                 { &hf_who_timeon,
283                 { "Time On", "who.timeon", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
284                         "", HFILL }},
285
286                 { &hf_who_idle,
287                 { "Time Idle", "who.idle", FT_UINT32, BASE_DEC, NULL, 0x0,
288                         "", HFILL }},
289         };
290
291         static gint *ett[] = {
292                 &ett_who,
293                 &ett_whoent,
294         };
295
296         proto_who = proto_register_protocol("Who", "WHO", "who");
297         proto_register_field_array(proto_who, hf, array_length(hf));
298         proto_register_subtree_array(ett, array_length(ett));
299 }
300
301 void
302 proto_reg_handoff_who(void)
303 {
304         dissector_handle_t who_handle;
305
306         who_handle = create_dissector_handle(dissect_who, proto_who);
307         dissector_add("udp.port", UDP_PORT_WHO, who_handle);
308 }