Embedded Syslog Manager

The Embedded Syslog Manager (ESM), new in Cisco IOS 12.3(2)T, enables you to filter, change the severity level of, route, and customize logging messages on your router. ESM allows logging messages to be logged independently as standard messages, messages formatted using XML, and ESM filtered messages. These messages then can be forwarded to the standard logging destinations: console, internal buffer, and syslog server. By using a separate logging process, ESM ensures that if there is a problem with the ESM filtering modules, the standard logging process will be unaffected.

ESM Overview

As I mentioned in the introduction, ESM is an enhancement, not a replacement, to the existing logging mechanism, including syslog. Both simultaneously can be running on your router. ESM, however, provides enhanced services above and beyond the normal syslog functions of a router.

ESM gives you complete control over the logging process on the router. Before this feature was introduced, if you wanted to perform extra processing on logging events, such as filtering, or have the router take an action for a specific event, you had to write your own scripts and run them against syslog files on a syslog server. With ESM, you can do these tasks on the router itself. Here are some benefits that ESM provides you:

  • You can limit the number of syslog messages to prevent a flood of messages in a time of duress or attack.

  • You can customize processing of logging messages, such as forwarding specific messages to specific syslog servers.

  • You can send e-mail notifications based on a specific log message or message type being generated.

  • You can change the security levels for logging messages instead of using the ones that Cisco assigns to the messages.

To perform these functions, ESM uses filter modules, which are scripts written in the Tcl language. Cisco has some predefined scripts that you can use, but you easily can modify these or create your own (assuming that you know Tcl). These scripts can be stored locally on the router, such as in Flash, or on a remote server. The scripts can be stored in plain text or can be precompiled; the latter increases your security because they cannot be edited directly (you can use the tool TclPro to precompile scripts, but other tools are available).

ESM requires Tcl 8.3.4 support, which is available only in Cisco IOS 12.3(2)T and later. Because only Tcl is supported for scripting, you must be proficient in using the Tcl coding language to create your own custom scripts. One limitation with ESM is that it cannot be applied to SNMP logging, such as log messages related to the snmp-server enable traps syslog and logging history commands.

ESM Filter Modules

Before you can use ESM, you must either create or obtain filtering modules. When you enable ESM, all logging messages first are processed through the referenced ESM filter modules. You can have the router use multiple filter modules, where the modules are processed by the position tag associated with the logging filter command. This enables you to enter your logging filter commands in any order, but it has the Cisco IOS process them based on the position tag values. When multiple modules are referenced, the output of the first filter module is passed as the input to the second module. If you had a third module, the output of the second module would be passed to the third one.

One component always passed from filter module to filter module is the original logging message. When all filter modules have been processed, the original logging message can be directed to one of three locations: standard, XML, or ESM. With the router's standard logging process, the logging message is directed to the normal destinations: console, buffered, or syslog.

Input Process

Normally, a logging message contains the following variables: facility, severity level, mnemonic, message text, and, optionally, a sequence number and time stamp. However, ESM, preappends a syslog count number to each message. The logging message itself is passed as a Tcl global namespace variable to the filter module. Each component in a logging message is a Tcl global variable, and each of these is prefixed with a double colon (::) when referencing them in the script module. Table 18-5 lists the valid variables that you have access to within a filter module.

Table 18-5. ESM Filter Module Variables




This is the sequence number of the error message, which can be added to logging messages with the service sequence-numbers command.


This variable contains either event cleared or NULL values.


This is the name of the facility that generates the message.


This is the string to create the original message text. For example, an original message text would be "Configured from %x by %y," where the %x and %y are message arguments. The format string can be passed to the format command in Tcl.


This is the router's name configured with the hostname command. You can add this name to logging messages with the logging origin-id hostname command.


This is the message abbreviation name, such as CONFIG_I or UPDOWN.


This is the position number of the filter module in the list of modules. This can be determined by the order of the scripts referenced in the logging filter commands.


These are the list of arguments in the format string of the logging message. For example, if the logging message was "%SYS-5-CONFIG_I: Configured from console by console," the format string would be "Configured from %x by %y," where %x and %y are the msg_args.


This is the original logging message. If you do not want to send the message, have the filter module return a NULL value; otherwise, return this variable ($::orig_msg).


This is the process ID contained in certain logging messages. Look at the ::process variable for more information.


This is the name of the process and interrupt level, which certain logging messages contain, describing traceback information and internal errors?for example: "-Process= 'Net Background,' ipl= 2, pid= 88."


This is the severity level of the message, which is from 0 to 7. Within the filter module, you can change this value.


This is the message stream number and is always set to 2 before the first filter is executed. Here is a standard use of stream numbers:

0? Default message

1? XML tagged message

2? Filtered message

3 to 9? Reserved

10 to 65,535? Available for your use


This is the syslog facility that will be used when sending a syslog message to a server. This is a number from 0 to 184, where the default is 184 (local7). You can change this value with the logging facility command.


This is the time stamp of the logging message, assuming that time stamps have been enabled with the service timestamps command.


This is the traceback information in certain logging messages that contain internal errors or tracebacks. See the ::process variable for more information.


This is the Cisco IOS software version of the router, in this format: "SYS_MAJORVERSION.SYS_MINORVERSION."

Filtering Process

After you have set up ESM, each time the router generates a logging message, the filter modules are processed in the order in which they are referenced, (that is, configured). As each module is processed, it passes its output as input to the next module. Because the Tcl variables in Table 18-5 are global namespace variables, each of these can be changed within your filters and can be used by other filters.

return Statement

Two Tcl global variables automatically are updated by ESM based on the execution of filtering modules: ::orig_msg and ::cli_args (the latter is the arguments passed into the filter module). The ::origin_msg value is set automatically to the return value of the filter module. This is done with the return command. For example, if you had a one-line filter module and wanted to pass a value of "This is my new value" to the next filter module, your return statement in your first filter module would look like this:

return "This is my new value"

With this example, the filter module ignores any parameters passed to it and passes the previous text string to the next filter module in the chain.

Here are some other return statement examples. With this return statement, all syslog messages are blocked to the ESM stream process:

return ""

This example sends the value in ::orig_msg to the next module:

return $::orig_msg

Cisco IOS Commands

You can add Cisco IOS commands to your filter modules by using the Tcl config and exec commands. For example, assume that you want to add the inbound ACL applied to an interface to your logging message. Assume that the ACL is the one applied to ethernet1, which is also the source address for logging statements to a syslog server. This could be done with the following:

set acl_info [exec show ip interface e1 | inc Outbound access list]

puts $acl_info

"  Outgoing access list is not set"

In this example, the last line is the output passed to the syslog message.


More information on TCL scripting can be found on the Cisco website in the "Cisco IOS Scripting with Tcl" guide. Just do a search for this string.

Example Filter Modules

Cisco provides some sample Tcl scripts on its website for ESM filter modules; however, Cisco does not support all of these scripts. The phrase "buyer beware" applies. Some of the example scripts include the following:

  • Escalating the severity level of a message

  • Counting messages

  • Creating XML tags

  • Associating logging messages to a stream ID

  • Sending an e-mail alert

As I mentioned at the beginning of this section on ESM, this chapter does not provide an in-depth study of the configuration of Tcl scripts. To give you a flavor of scripting, however, I look at two scripts included on the Cisco website: email.txt and email_guts.txt.

The email.txt script creates an e-mail message with the logging message. Here are the guts of this script:

# Usage:  Provide email address as CLI argument.  Set email server IP in

#         email_guts.tcl

# Namespace: email

if { [info exists email::init] == 0 } {

   source flash:/email_guts.tcl


# Check for null message

if { [string length $::orig_msg] == 0} {

      return ""


if { [info exists ::msg_args] } {

    if { [string compare -nocase CONFIG_I $::mnemonic ] == 0 } {

                email::sendmessage $::cli_args $::mnemonic \

                [string trim $::orig_msg]



return $::orig_msg

One argument that you must pass to this script is the e-mail address where you want e-mail messages sent.

The email_guts.txt script specifies the e-mail server's IP address, as well as the from and friendly strings:

# Usage: Set email host IP, from, and friendly strings below.


namespace eval email {

    set sendmail(smtphost)

    set sendmail(from) $::hostname

    set sendmail(friendly) $::hostname

    proc sendmessage {toList subject body} {

        variable sendmail

        set smtphost $sendmail(smtphost)

        set from $sendmail(from)

        set friendly $sendmail(friendly)

        set sockid [socket $smtphost 25]


set status [catch {

        puts $sockid "HELO $smtphost"

        flush $sockid

        set result [gets $sockid]

        puts $sockid "MAIL From:<$from>"

        flush $sockid

        set result [gets $sockid]

        foreach to $toList {

            puts $sockid "RCPT To:<$to>"

            flush $sockid


        set result [gets $sockid]

        puts  $sockid "DATA "

        flush $sockid

        set result [gets  $sockid]

        puts  $sockid "From: $friendly <$from>"

        foreach to $toList {

            puts $sockid "To:<$to>"


        puts  $sockid "Subject: $subject"

        puts  $sockid "\n"

        foreach line [split $body "\n"] {

            puts  $sockid " $line"


        puts  $sockid "."

        puts  $sockid "QUIT"

        flush $sockid

        set result [gets  $sockid]

} result]

        catch {close $sockid }

    if {$status} then {

        return -code error $result



} ;# end namespace email

set email::init 1

Introduction to ESM Setup and Configuration

After you have created your filter modules for ESM, put them in a place where the router can locate them through a URL-style syntax. I recommend that you put the Tcl scripts (filter modules) in the router's Flash. When this is done, you need to perform the following steps:

Step 1. Reference each filter module with a separate logging filter command.

Step 2. Use the logging {console | buffered | monitor | host} filtered command to use your ESM filter modules. Optionally, configure other logging commands, such as logging source-interface and logging origin-id.

Step 3. Verify your configuration with the show logging command.

The following sections cover the configuration in more depth.

Specifying Filter Modules

The first thing that you must do is reference your filter modules. This is done using the logging filter command:

Router(config)# logging filter filter_url [position_#]

  [args filter_arguments]

The filter_url parameter specifies the location of the filter module. If the module is stored locally in the router's Flash, use flash: or slot0: as the source. If it is stored remotely, use either ftp:, rcp:, or tftp:. For a remote location, the filter URL should also contain the IP address of the module, as well as the directory in which the module is located. For locally and remotely stored modules, you need to specify the name of the module. The extension of these scripts is either .txt for a plain, noncompiled Tcl script or .tcl for a precompiled Tcl script.

Following the URL specification is the position number of the filter module during the filtering process. If you omit the position number, the router processes filter modules in the order in which you configure them. For each filter module that you have, you need a separate logging filter command. Finally, the optional args parameter specifies any arguments that you want to pass to the filter (in the filter, you need to reference these arguments if you want to use them). For example, you could pass an e-mail address to a script by using this syntax: args richard@quizware.com. If you have multiple arguments, separate the arguments by a space. Note that if the script is set up to accept an argument already, you do not need to preface the argument with the args parameter.

Here is a simple example of referencing a compiled script stored in the router's Flash:

Router(config)# logging filter flash:/email.tcl richard@quizware.com

Using Filter Modules

Next, you must tell your router to use the filter modules that you specified with the logging filter command. This is done using the following commands:

Router(config)# logging [console | buffered | monitor] filtered


Router(config)# logging host {IP_address | hostname} filtered

  [stream stream_ID]

In the first logging command, the optional severity_level parameter specifies that logging messages at that severity level or higher (lower number) will be processed by the filter modules. Note that the severity level specified in the logging console, logging buffered, and logging monitored commands takes precedence over the severity level specified in this command.

In the second command, the optional stream parameter can be used to direct logging messages to a specific syslog host. As an example, you could specify that all severity level 5 messages should have a stream ID of 7 associated with them; then, with the stream parameter, you could have the appropriate logging host command process these logging messages.

Example 18-16 shows a simple example that e-mails a message for any messages logged to the console with a severity level of 0 to 3.

Example 18-16. Sending an E-mail Message Based on Logging Severity Levels

Router(config)# logging filter slot0:/email.tcl richard@quizware.com

Router(config)# logging filter slot0:/email_guts.tcl

Router(config)# logging console filtered 3

Verifying Your ESM Configuration

After you have configured your ESM filters, you can use the show logging command to verify your configuration. Example 18-17 shows a sample output of this command based on Example 18-16.

Example 18-17. Using the show logging Command to Verify Your ESM Configuration

Router# show logging

Syslog logging: enabled(0 messages dropped, 12 messages rate-limited,

  0 flushes, 0 overruns, xml disabled, filtering enabled)

  Console logging: level debugging, 32 messages logged, xml disabled,

    filtering enabled

  Monitor logging: level warnings , 0 messages logged, xml disabled,

    filtering disabled

  Buffer logging: level debugging, 839 messages logged, xml disabled,

    filtering disabled

  Logging Exception size (8192 bytes)

  Count and timestamp logging messages: disabled

Filter modules:

     slot0:/email.tcl richard@quizware.com


Log  Buffer (8192 bytes):

*Jan 5 12:49:02.513: %SYS-5-CONFIG_I: Configured from console

  by console

<--output omitted-->