2 * Routines for who protocol (see man rwhod)
3 * Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/to_str.h>
20 RWHOD(8) UNIX System Manager's Manual RWHOD(8)
23 The messages sent and received, are of the form:
26 0 char out_line[8]; tty name
27 8 char out_name[8]; user id
28 16 long out_time; time on
37 12 char wd_hostname[32];
42 (20 each) int we_idle;
43 } wd_we[1024 / sizeof (struct whoent)];
48 void proto_register_who(void);
49 void proto_reg_handoff_who(void);
51 static dissector_handle_t who_handle
;
54 static int hf_who_vers
;
55 static int hf_who_type
;
56 static int hf_who_sendtime
;
57 static int hf_who_recvtime
;
58 static int hf_who_hostname
;
59 static int hf_who_loadav_5
;
60 static int hf_who_loadav_10
;
61 static int hf_who_loadav_15
;
62 static int hf_who_boottime
;
63 static int hf_who_whoent
;
64 static int hf_who_tty
;
65 static int hf_who_uid
;
66 static int hf_who_timeon
;
67 static int hf_who_idle
;
70 static int ett_whoent
;
72 #define UDP_PORT_WHO 513
74 static void dissect_whoent(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
77 dissect_who(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
83 double loadav_5
= 0.0, loadav_10
= 0.0, loadav_15
= 0.0;
85 /* Summary information */
86 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "WHO");
87 col_clear(pinfo
->cinfo
, COL_INFO
);
89 who_ti
= proto_tree_add_item(tree
, proto_who
, tvb
, offset
, -1, ENC_NA
);
90 who_tree
= proto_item_add_subtree(who_ti
, ett_who
);
92 proto_tree_add_item(who_tree
, hf_who_vers
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
95 proto_tree_add_item(who_tree
, hf_who_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
102 proto_tree_add_item(who_tree
, hf_who_sendtime
, tvb
, offset
, 4,
103 ENC_TIME_SECS
|ENC_BIG_ENDIAN
);
108 proto_tree_add_item(who_tree
, hf_who_recvtime
, tvb
, offset
, 4,
109 ENC_TIME_SECS
|ENC_BIG_ENDIAN
);
113 server_name
= tvb_get_stringzpad(pinfo
->pool
, tvb
, offset
, 32, ENC_ASCII
|ENC_NA
);
114 proto_tree_add_string(who_tree
, hf_who_hostname
, tvb
, offset
, 32, server_name
);
117 loadav_5
= tvb_get_ntohl(tvb
, offset
) / 100.0;
118 proto_tree_add_double(who_tree
, hf_who_loadav_5
, tvb
, offset
,
122 loadav_10
= tvb_get_ntohl(tvb
, offset
) / 100.0;
123 proto_tree_add_double(who_tree
, hf_who_loadav_10
, tvb
, offset
,
127 loadav_15
= tvb_get_ntohl(tvb
, offset
) / 100.0;
128 proto_tree_add_double(who_tree
, hf_who_loadav_15
, tvb
, offset
,
132 /* Summary information */
133 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s: %.02f %.02f %.02f",
134 server_name
, loadav_5
, loadav_10
, loadav_15
);
137 proto_tree_add_item(who_tree
, hf_who_boottime
, tvb
, offset
, 4,
138 ENC_TIME_SECS
|ENC_BIG_ENDIAN
);
141 dissect_whoent(pinfo
, tvb
, offset
, who_tree
);
144 return tvb_captured_length(tvb
);
147 /* The man page says that (1024 / sizeof(struct whoent)) is the maximum number
148 * of whoent structures in the packet. */
149 #define SIZE_OF_WHOENT 24
150 #define MAX_NUM_WHOENTS (1024 / SIZE_OF_WHOENT)
153 dissect_whoent(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
155 proto_tree
*whoent_tree
= NULL
;
156 proto_item
*whoent_ti
= NULL
;
157 int line_offset
= offset
;
161 uint32_t idle_secs
; /* say that out loud... */
163 while (tvb_reported_length_remaining(tvb
, line_offset
) > 0
164 && whoent_num
< MAX_NUM_WHOENTS
) {
165 whoent_ti
= proto_tree_add_item(tree
, hf_who_whoent
, tvb
,
166 line_offset
, SIZE_OF_WHOENT
, ENC_NA
);
167 whoent_tree
= proto_item_add_subtree(whoent_ti
, ett_whoent
);
169 out_line
= tvb_get_stringzpad(pinfo
->pool
, tvb
, line_offset
, 8, ENC_ASCII
|ENC_NA
);
170 proto_tree_add_string(whoent_tree
, hf_who_tty
, tvb
, line_offset
,
174 out_name
= tvb_get_stringzpad(pinfo
->pool
, tvb
, line_offset
, 8, ENC_ASCII
|ENC_NA
);
175 proto_tree_add_string(whoent_tree
, hf_who_uid
, tvb
, line_offset
,
179 proto_tree_add_item(whoent_tree
, hf_who_timeon
, tvb
,
180 line_offset
, 4, ENC_TIME_SECS
|ENC_BIG_ENDIAN
);
183 idle_secs
= tvb_get_ntohl(tvb
, line_offset
);
184 proto_tree_add_uint_format(whoent_tree
, hf_who_idle
, tvb
,
185 line_offset
, 4, idle_secs
, "Idle: %s",
186 signed_time_secs_to_str(pinfo
->pool
, idle_secs
));
194 proto_register_who(void)
196 static hf_register_info hf
[] = {
198 { "Version", "who.vers", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
202 { "Type", "who.type", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
206 { "Send Time", "who.sendtime", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0,
210 { "Receive Time", "who.recvtime", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0,
214 { "Hostname", "who.hostname", FT_STRING
, BASE_NONE
, NULL
, 0x0,
218 { "Load Average Over Past 5 Minutes", "who.loadav_5", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
222 { "Load Average Over Past 10 Minutes", "who.loadav_10", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
226 { "Load Average Over Past 15 Minutes", "who.loadav_15", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
230 { "Boot Time", "who.boottime", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0,
234 { "Who utmp Entry", "who.entry", FT_NONE
, BASE_NONE
, NULL
, 0x0,
238 { "TTY Name", "who.tty", FT_STRING
, BASE_NONE
, NULL
, 0x0,
242 { "User ID", "who.uid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
246 { "Time On", "who.timeon", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x0,
250 { "Time Idle", "who.idle", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
254 static int *ett
[] = {
259 proto_who
= proto_register_protocol("Who", "WHO", "who");
260 who_handle
= register_dissector("who", dissect_who
, proto_who
);
261 proto_register_field_array(proto_who
, hf
, array_length(hf
));
262 proto_register_subtree_array(ett
, array_length(ett
));
266 proto_reg_handoff_who(void)
268 dissector_add_uint_with_preference("udp.port", UDP_PORT_WHO
, who_handle
);
272 * Editor modelines - https://www.wireshark.org/tools/modelines.html
277 * indent-tabs-mode: t
280 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
281 * :indentSize=8:tabSize=8:noTabs=false: