2 * Routines for syslog message dissection
4 * Copyright 2000, Gerald Combs <gerald[AT]wireshark.org>
6 * Support for passing SS7 MSUs (from the Cisco ITP Packet Logging
7 * facility) to the MTP3 dissector by Abhik Sarkar <sarkar.abhik[AT]gmail.com>
8 * with some rework by Jeff Morriss <jeff.morriss.ws [AT] gmail.com>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald[AT]wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 #include <epan/packet.h>
39 #include <epan/strutil.h>
41 #define UDP_PORT_SYSLOG 514
43 #define PRIORITY_MASK 0x0007 /* 0000 0111 */
44 #define FACILITY_MASK 0x03f8 /* 1111 1000 */
46 /* The maximum number if priority digits to read in. */
53 #define LEVEL_WARNING 4
54 #define LEVEL_NOTICE 5
57 static const value_string short_lev
[] = {
58 { LEVEL_EMERG
, "EMERG" },
59 { LEVEL_ALERT
, "ALERT" },
60 { LEVEL_CRIT
, "CRIT" },
62 { LEVEL_WARNING
, "WARNING" },
63 { LEVEL_NOTICE
, "NOTICE" },
64 { LEVEL_INFO
, "INFO" },
65 { LEVEL_DEBUG
, "DEBUG" },
79 #define FAC_AUTHPRIV 10
82 #define FAC_LOGAUDIT 13
83 #define FAC_LOGALERT 14
84 #define FAC_CRON_SOL 15
93 static const value_string short_fac
[] = {
97 { FAC_DAEMON
, "DAEMON" },
99 { FAC_SYSLOG
, "SYSLOG" },
101 { FAC_NEWS
, "NEWS" },
102 { FAC_UUCP
, "UUCP" },
103 { FAC_CRON
, "CRON" }, /* The BSDs, Linux, and others */
104 { FAC_AUTHPRIV
, "AUTHPRIV" },
107 { FAC_LOGAUDIT
, "LOGAUDIT" },
108 { FAC_LOGALERT
, "LOGALERT" },
109 { FAC_CRON_SOL
, "CRON" }, /* Solaris */
110 { FAC_LOCAL0
, "LOCAL0" },
111 { FAC_LOCAL1
, "LOCAL1" },
112 { FAC_LOCAL2
, "LOCAL2" },
113 { FAC_LOCAL3
, "LOCAL3" },
114 { FAC_LOCAL4
, "LOCAL4" },
115 { FAC_LOCAL5
, "LOCAL5" },
116 { FAC_LOCAL6
, "LOCAL6" },
117 { FAC_LOCAL7
, "LOCAL7" },
121 static const value_string long_lev
[] = {
122 { LEVEL_EMERG
, "EMERG - system is unusable" },
123 { LEVEL_ALERT
, "ALERT - action must be taken immediately" },
124 { LEVEL_CRIT
, "CRIT - critical conditions" },
125 { LEVEL_ERR
, "ERR - error conditions" },
126 { LEVEL_WARNING
, "WARNING - warning conditions" },
127 { LEVEL_NOTICE
, "NOTICE - normal but significant condition" },
128 { LEVEL_INFO
, "INFO - informational" },
129 { LEVEL_DEBUG
, "DEBUG - debug-level messages" },
133 static const value_string long_fac
[] = {
134 { FAC_KERN
, "KERN - kernel messages" },
135 { FAC_USER
, "USER - random user-level messages" },
136 { FAC_MAIL
, "MAIL - mail system" },
137 { FAC_DAEMON
, "DAEMON - system daemons" },
138 { FAC_AUTH
, "AUTH - security/authorization messages" },
139 { FAC_SYSLOG
, "SYSLOG - messages generated internally by syslogd" },
140 { FAC_LPR
, "LPR - line printer subsystem" },
141 { FAC_NEWS
, "NEWS - network news subsystem" },
142 { FAC_UUCP
, "UUCP - UUCP subsystem" },
143 { FAC_CRON
, "CRON - clock daemon (BSD, Linux)" },
144 { FAC_AUTHPRIV
, "AUTHPRIV - security/authorization messages (private)" },
145 { FAC_FTP
, "FTP - ftp daemon" },
146 { FAC_NTP
, "NTP - ntp subsystem" },
147 { FAC_LOGAUDIT
, "LOGAUDIT - log audit" },
148 { FAC_LOGALERT
, "LOGALERT - log alert" },
149 { FAC_CRON_SOL
, "CRON - clock daemon (Solaris)" },
150 { FAC_LOCAL0
, "LOCAL0 - reserved for local use" },
151 { FAC_LOCAL1
, "LOCAL1 - reserved for local use" },
152 { FAC_LOCAL2
, "LOCAL2 - reserved for local use" },
153 { FAC_LOCAL3
, "LOCAL3 - reserved for local use" },
154 { FAC_LOCAL4
, "LOCAL4 - reserved for local use" },
155 { FAC_LOCAL5
, "LOCAL5 - reserved for local use" },
156 { FAC_LOCAL6
, "LOCAL6 - reserved for local use" },
157 { FAC_LOCAL7
, "LOCAL7 - reserved for local use" },
161 static gint proto_syslog
= -1;
162 static gint hf_syslog_level
= -1;
163 static gint hf_syslog_facility
= -1;
164 static gint hf_syslog_msg
= -1;
165 static gint hf_syslog_msu_present
= -1;
167 static gint ett_syslog
= -1;
169 static dissector_handle_t syslog_handle
;
171 static dissector_handle_t mtp_handle
;
173 /* The Cisco ITP's packet logging facility allows selected (SS7) MSUs to be
174 * to be encapsulated in syslog UDP datagrams and sent to a monitoring tool.
175 * However, no actual tool to monitor/decode the MSUs is provided. The aim
176 * of this routine is to extract the hex dump of the MSU from the syslog
177 * packet so that it can be passed on to the mtp3 dissector for decoding.
180 mtp3_msu_present(tvbuff_t
*tvb
, packet_info
*pinfo
, gint fac
, gint level
, const char *msg_str
, gint chars_truncated
)
184 gchar
**split_string
, *msu_hex_dump
;
185 tvbuff_t
*mtp3_tvb
= NULL
;
188 /* In the sample capture I have, all MSUs are LOCAL0.DEBUG.
189 * Try to optimize this routine for most syslog users by short-cutting
192 if (!(fac
== FAC_LOCAL0
&& level
== LEVEL_DEBUG
))
195 if (strstr(msg_str
, "msu=") == NULL
)
198 split_string
= g_strsplit(msg_str
, "msu=", 2);
199 msu_hex_dump
= split_string
[1];
201 if (msu_hex_dump
&& (len
= strlen(msu_hex_dump
))) {
203 /* convert_string_to_hex() will return NULL if it gets an incomplete
204 * byte. If we have an odd string length then chop off the remaining
205 * nibble so we can get at least a partial MSU (chances are the
206 * subdissector will except out, of course).
209 msu_hex_dump
[len
- 1] = '\0';
211 byte_array
= convert_string_to_hex(msu_hex_dump
, &nbytes
);
214 mtp3_tvb
= tvb_new_child_real_data(tvb
, byte_array
, (guint
)nbytes
,
215 (guint
)nbytes
+ chars_truncated
/ 2);
216 tvb_set_free_cb(mtp3_tvb
, g_free
);
217 /* ...and add the encapsulated MSU as a new data source so that it gets
218 * its own tab in the packet bytes pane.
220 add_new_data_source(pinfo
, mtp3_tvb
, "Encapsulated MSU");
224 g_strfreev(split_string
);
229 /* The message format is defined in RFC 3164 */
231 dissect_syslog(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
233 gint pri
= -1, lev
= -1, fac
= -1;
234 gint msg_off
= 0, msg_len
, reported_msg_len
;
236 proto_tree
*syslog_tree
;
240 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "Syslog");
241 col_clear(pinfo
->cinfo
, COL_INFO
);
243 if (tvb_get_guint8(tvb
, msg_off
) == '<') {
244 /* A facility and level follow. */
247 while (tvb_bytes_exist(tvb
, msg_off
, 1) &&
248 isdigit(tvb_get_guint8(tvb
, msg_off
)) && msg_off
<= MAX_DIGITS
) {
249 pri
= pri
* 10 + (tvb_get_guint8(tvb
, msg_off
) - '0');
252 if (tvb_get_guint8(tvb
, msg_off
) == '>')
254 fac
= (pri
& FACILITY_MASK
) >> 3;
255 lev
= pri
& PRIORITY_MASK
;
258 msg_len
= tvb_ensure_length_remaining(tvb
, msg_off
);
259 msg_str
= tvb_format_text(tvb
, msg_off
, msg_len
);
260 reported_msg_len
= tvb_reported_length_remaining(tvb
, msg_off
);
262 mtp3_tvb
= mtp3_msu_present(tvb
, pinfo
, fac
, lev
, msg_str
,
263 (reported_msg_len
- msg_len
));
265 if (mtp3_tvb
== NULL
) {
267 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s.%s: %s",
268 val_to_str_const(fac
, short_fac
, "UNKNOWN"),
269 val_to_str_const(lev
, short_lev
, "UNKNOWN"), msg_str
);
271 col_add_str(pinfo
->cinfo
, COL_INFO
, msg_str
);
277 ti
= proto_tree_add_protocol_format(tree
, proto_syslog
, tvb
, 0, -1,
278 "Syslog message: %s.%s: %s",
279 val_to_str_const(fac
, short_fac
, "UNKNOWN"),
280 val_to_str_const(lev
, short_lev
, "UNKNOWN"), msg_str
);
282 ti
= proto_tree_add_protocol_format(tree
, proto_syslog
, tvb
, 0, -1,
283 "Syslog message: (unknown): %s", msg_str
);
285 syslog_tree
= proto_item_add_subtree(ti
, ett_syslog
);
287 proto_tree_add_uint(syslog_tree
, hf_syslog_facility
, tvb
, 0,
289 proto_tree_add_uint(syslog_tree
, hf_syslog_level
, tvb
, 0,
292 proto_tree_add_item(syslog_tree
, hf_syslog_msg
, tvb
, msg_off
,
293 msg_len
, ENC_ASCII
|ENC_NA
);
296 proto_item
*mtp3_item
;
297 mtp3_item
= proto_tree_add_boolean(syslog_tree
, hf_syslog_msu_present
,
298 tvb
, msg_off
, msg_len
, TRUE
);
299 PROTO_ITEM_SET_GENERATED(mtp3_item
);
303 /* Call MTP dissector if encapsulated MSU was found... */
305 call_dissector(mtp_handle
, mtp3_tvb
, pinfo
, tree
);
311 /* Register the protocol with Wireshark */
312 void proto_register_syslog(void)
315 /* Setup list of header fields */
316 static hf_register_info hf
[] = {
317 { &hf_syslog_facility
,
318 { "Facility", "syslog.facility",
319 FT_UINT8
, BASE_DEC
, VALS(long_fac
), FACILITY_MASK
,
320 "Message facility", HFILL
}
323 { "Level", "syslog.level",
324 FT_UINT8
, BASE_DEC
, VALS(long_lev
), PRIORITY_MASK
,
325 "Message level", HFILL
}
328 { "Message", "syslog.msg",
329 FT_STRING
, BASE_NONE
, NULL
, 0x0,
330 "Message Text", HFILL
}
332 { &hf_syslog_msu_present
,
333 { "SS7 MSU present", "syslog.msu_present",
334 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
335 "True if an SS7 MSU was detected in the syslog message",
340 /* Setup protocol subtree array */
341 static gint
*ett
[] = {
345 /* Register the protocol name and description */
346 proto_syslog
= proto_register_protocol("Syslog message", "Syslog", "syslog");
348 /* Required function calls to register the header fields and subtrees used */
349 proto_register_field_array(proto_syslog
, hf
, array_length(hf
));
350 proto_register_subtree_array(ett
, array_length(ett
));
352 syslog_handle
= register_dissector("syslog", dissect_syslog
, proto_syslog
);
356 proto_reg_handoff_syslog(void)
358 dissector_add_uint("udp.port", UDP_PORT_SYSLOG
, syslog_handle
);
359 dissector_add_handle("tcp.port", syslog_handle
);
361 /* Find the mtp3 dissector */
362 mtp_handle
= find_dissector("mtp3");