<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<article lang="en" status="">
  <!--$Id$-->

  <articleinfo>
    <title>Macros</title>

    <authorgroup>
      <author>
        <firstname>Tom</firstname>

        <surname>Eastep</surname>
      </author>

      <author>
        <firstname>Cristian</firstname>

        <surname>Rodríguez</surname>
      </author>
    </authorgroup>

    <pubdate><?dbtimestamp format="Y/m/d"?></pubdate>

    <copyright>
      <year>2005</year>

      <holder>Thomas M. Eastep</holder>
    </copyright>

    <legalnotice>
      <para>Permission is granted to copy, distribute and/or modify this
      document under the terms of the GNU Free Documentation License, Version
      1.2 or any later version published by the Free Software Foundation; with
      no Invariant Sections, with no Front-Cover, and with no Back-Cover
      Texts. A copy of the license is included in the section entitled
      <quote><ulink url="GnuCopyright.htm">GNU Free Documentation
      License</ulink></quote>.</para>
    </legalnotice>
  </articleinfo>

  <caution>
    <para><emphasis role="bold">This article applies to Shorewall 4.3 and
    later. If you are running a version of Shorewall earlier than Shorewall
    4.3.5 then please see the documentation for that
    release.</emphasis></para>
  </caution>

  <section id="Overview">
    <title>Overview of Shorewall Macros?</title>

    <para>Shorewall macros allow a symbolic name to be associated with a
    series of one or more iptables rules. The symbolic name may appear in the
    ACTION column of an <filename><ulink
    url="manpages/shorewall-rules.html">/etc/shorewall/rules</ulink></filename>
    file entry and in the TARGET column of an action in which case, the
    traffic matching that rules file entry will be passed to the series of
    iptables rules named by the macro.</para>

    <para>Macros can be thought of as templates. When a macro is invoked in an
    <filename>/etc/shorewall/rules</filename> entry, it may be qualified by a
    logging specification (log level and optionally a log tag). The presence
    of the log level/tag causes a modified series of rules to be generated in
    which each packet/rule match within the macro causes a log message to be
    generated.</para>

    <para>There are two types of Shorewall macros:</para>

    <orderedlist>
      <listitem>
        <para>Standard Macros. These macros are released as part of Shorewall.
        They are defined in macro.* files in <filename
        class="directory">/usr/share/shorewall</filename>. Each
        <filename>macro.*</filename> file has a comment at the beginning of
        the file that describes what the macro does. As an example, here is
        the definition of the <firstterm>SMB</firstterm> standard
        macro.</para>

        <programlisting>#
# Shorewall 3.0 /usr/share/shorewall/macro.SMB
#
#       Handle Microsoft SMB traffic. You need to invoke this macro in
#       both directions.
#
######################################################################################
#TARGET  SOURCE         DEST            PROTO   DEST    SOURCE          RATE    USER/
#                                               PORT    PORT(S)         LIMIT   GROUP
PARAM    -              -               udp     135,445
PARAM    -              -               udp     137:139
PARAM    -              -               udp     1024:   137
PARAM    -              -               tcp     135,139,445
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE</programlisting>

        <para>If you wish to modify one of the standard macros, do not modify
        the definition in <filename
        class="directory">/usr/share/shorewal</filename>l. Rather, copy the
        file to <filename class="directory">/etc/shorewall</filename> (or
        somewhere else on your CONFIG_PATH) and modify the copy.</para>
      </listitem>

      <listitem>
        <para>User-defined Macros. These macros are created by end-users. They
        are defined in macro.* files in /etc/shorewall or in another directory
        listed in your CONFIG_PATH (defined in <ulink
        url="manpages/shorewall.conf.html">/etc/shorewall/shorewall.conf</ulink>).</para>
      </listitem>
    </orderedlist>

    <para>Most Standard Macros are <firstterm>parameterized</firstterm>. That
    means that you specify what you want to do (ACCEPT, DROP, REJECT, etc.)
    when you invoke the macro. The SMB macro shown above is parameterized
    (note PARAM in the TARGET column).</para>

    <para>When invoking a parameterized macro, you follow the name of the
    macro with the action that you want to substitute for PARAM enclosed in
    parentheses.</para>

    <para>Example:</para>

    <blockquote>
      <para>/etc/shorewall/rules:</para>

      <programlisting>#ACTION      SOURCE        DEST         PROTO   DEST PORT(S)
SMB(ACCEPT)  loc           fw         </programlisting>

      <para>The above is equivalent to coding the following series of
      rules:</para>

      <programlisting>#TARGET      SOURCE        DEST         PROTO   DEST PORT(s)
ACCEPT       loc           fw           udp     135,445
ACCEPT       loc           fw           udp     137:139
ACCEPT       loc           fw           udp     1024:   137
ACCEPT       loc           fw           tcp     135,139,445</programlisting>
    </blockquote>

    <para>Logging is covered in <link linkend="Logging">a following
    section</link>. The other columns are treated as follows:</para>

    <variablelist>
      <varlistentry>
        <term>SOURCE and DEST</term>

        <listitem>
          <para>If a value other than "-" appears in both the macro body and
          in the invocation of the macro, then the value in the invocation is
          examined and the appropriate action is taken. If the value in the
          invocation appears to be an address (IP or MAC) or the name of an
          ipset, then it is placed after the value in the macro body.
          Otherwise, it is placed before the value in the macro body.</para>

          <para>Example 1:</para>

          <blockquote>
            <para>/etc/shorewall/macro.SMTP</para>

            <programlisting>#TARGET          SOURCE   DEST            PROTO    DEST PORT(S)
PARAM            -        loc             tcp      25</programlisting>

            <para>/etc/shorewall/rules (Shorewall 4.0):</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
SMTP(DNAT):info  net      192.168.1.5</programlisting>

            <para>/etc/shorewall/rules (Shorewall 4.2.0 and later):</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
SMTP(DNAT):info   net      192.168.1.5</programlisting>

            <para>This would be equivalent to coding the following directly in
            /etc/shorewall/rules</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
DNAT:info        net      loc:192.168.1.5 tcp      25</programlisting>
          </blockquote>

          <para>Example 2:</para>

          <blockquote>
            <para>/etc/shorewall/macro.SMTP</para>

            <programlisting>#TARGET          SOURCE   DEST            PROTO    DEST PORT(S)
PARAM            -        192.168.1.5     tcp      25</programlisting>

            <para>/etc/shorewall/rules</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
SMTP(DNAT):info   net      loc</programlisting>

            <para>This would be equivalent to coding the following directly in
            /etc/shorewall/rules</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
DNAT:info        net      loc:192.168.1.5 tcp      25</programlisting>
          </blockquote>

          <para>You may also specify SOURCE or DEST in the SOURCE and DEST
          columns. This allows you to define macros that work in both
          directions.</para>

          <para>Example 3:</para>

          <blockquote>
            <para><filename>/etc/shorewall/macro.SMBBI</filename> (Note: there
            is already a standard macro like this released as part of
            Shorewall):</para>

            <programlisting>#ACTION SOURCE  DEST    PROTO   DEST    SOURCE  ORIGINAL        RATE    USER/
#                               PORT    PORT(S) DEST            LIMIT   GROUP
PARAM   -       -       udp     135,445
PARAM   -       -       udp     137:139
PARAM   -       -       udp     1024:   137
PARAM   -       -       tcp     135,139,445
PARAM   DEST    SOURCE  udp     135,445
PARAM   DEST    SOURCE  udp     137:139
PARAM   DEST    SOURCE  udp     1024:   137
PARAM   DEST    SOURCE  tcp     135,139,445
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE</programlisting>

            <para>/etc/shorewall/rules:</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
SMBBI(ACCEPT)     loc      fw</programlisting>

            <para>This would be equivalent to coding the following directly in
            /etc/shorewall/rules</para>

            <programlisting>#ACTION          SOURCE   DEST            PROTO    DEST PORT(S)
ACCEPT           loc      fw              udp      135,445
ACCEPT           loc      fw              udp      137:139
ACCEPT           loc      fw              udp      1024:   137
ACCEPT           loc      fw              tcp      135,139,445
ACCEPT           fw       loc             udp      135,445
ACCEPT           fw       loc             udp      137:139
ACCEPT           fw       loc             udp      1024:   137
ACCEPT           fw       loc             tcp      135,139,445</programlisting>
          </blockquote>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Remaining columns</term>

        <listitem>
          <para>Any value in the invocation replaces the value in the rule in
          the macro.</para>
        </listitem>
      </varlistentry>
    </variablelist>

    <para>One additional restriction should be noted: macros that are invoked
    from actions cannot themselves invoke other actions.</para>
  </section>

  <section id="Defining">
    <title>Defining your own Macros</title>

    <para>To define a new macro:</para>

    <orderedlist>
      <listitem>
        <para>Macro names must be valid shell variable names ((must begin with
        a letter and be composed of letters, digits and underscore characters)
        as well as valid Netfilter chain names.</para>
      </listitem>

      <listitem>
        <para>Copy /usr/share/shorewall/macro.template to
        <filename>/etc/shorewall/macro.MacroName</filename> (for example, if
        your new macro name is <quote>Foo</quote> then copy
        <filename>/usr/share/shorewall/macro.template</filename> to
        <filename>/etc/shorewall/macro.Foo</filename>).</para>
      </listitem>

      <listitem>
        <para>Now modify the new file to define the new macro.</para>
      </listitem>
    </orderedlist>

    <section>
      <title>Shorewall 4.4.16 and Later</title>

      <para>Beginning with Shorewall 4.4.16, the columns in macro.template are
      the same as those in shorewall-rules (5). The first non-commentary line
      in the template must be</para>

      <programlisting>FORMAT 2</programlisting>

      <para>There are no restrictions regarding the ACTIONs that can be
      performed in a macro.</para>
    </section>

    <section>
      <title>Shorewall 4.4.15 and Earlier</title>

      <para>Before 4.4.16, columns in the macro.template file were as
      follows:</para>

      <itemizedlist>
        <listitem>
          <para>ACTION - ACCEPT, DROP, REJECT, DNAT, DNAT-, REDIRECT,
          CONTINUE, LOG, QUEUE, PARAM or an action name. Note that a macro may
          not invoke another macro.</para>

          <simplelist>
            <member>ACCEPT - allow the connection request</member>

            <member>ACCEPT+ - like ACCEPT but also excludes the connection
            from any subsequent DNAT[-] or REDIRECT[-] rules.</member>

            <member>NONAT - Excludes the connection from any subsequent
            DNAT[-] or REDIRECT[-] rules but doesn't generate a rule to accept
            the traffic.</member>

            <member>DROP - ignore the request</member>

            <member>REJECT - disallow the request and return an icmp
            unreachable or an RST packet.</member>

            <member>DNAT - Forward the request to another address (and
            optionally another port).</member>

            <member>DNAT- - Advanced users only. Like DNAT but only generates
            the DNAT iptables rule and not the companion ACCEPT rule.</member>

            <member>SAME - Similar to DNAT except that the port may not be
            remapped and when multiple server addresses are listed, all
            requests from a given remote system go to the same
            server.</member>

            <member>SAME- - Advanced users only. Like SAME but only generates
            the SAME iptables rule and not the companion ACCEPT rule.</member>

            <member>REDIRECT - Redirect the request to a local port on the
            firewall.</member>

            <member>REDIRECT- - Advanced users only. Like REDIRECT but only
            generates the REDIRECT iptables rule and not the companion ACCEPT
            rule.</member>

            <member>CONTINUE - (For experts only). Do not process any of the
            following rules for this (source zone,destination zone). If The
            source and/or destination If the address falls into a zone defined
            later in /etc/shorewall/zones, this connection request will be
            passed to the rules defined for that (those) zone(s).</member>

            <member>LOG - Simply log the packet and continue.</member>

            <member>QUEUE - Queue the packet to a user-space application such
            as ftwall (http://p2pwall.sf.net).</member>
          </simplelist>

          <para>The ACTION may optionally be followed by ":" and a syslog log
          level (e.g, REJECT:info or DNAT:debug). This causes the packet to be
          logged at the specified level.</para>
        </listitem>

        <listitem>
          <para>SOURCE - Source hosts to which the rule applies. A
          comma-separated list of subnets and/or hosts. Hosts may be specified
          by IP or MAC address; mac addresses must begin with <quote>~</quote>
          and must use <quote>-</quote> as a separator.</para>

          <para>Alternatively, clients may be specified by interface name. For
          example, eth1 specifies a client that communicates with the firewall
          system through eth1. This may be optionally followed by another
          colon (<quote>:</quote>) and an IP/MAC/subnet address as described
          above (e.g. eth1:192.168.1.5).</para>

          <para>May also contain 'DEST' as described above.</para>
        </listitem>

        <listitem>
          <para>DEST - Location of Server. Same as above with the exception
          that MAC addresses are not allowed.</para>

          <para>Unlike in the SOURCE column, you may specify a range of up to
          256 IP addresses using the syntax &lt;<emphasis>first
          ip</emphasis>&gt;-&lt;<emphasis>last ip</emphasis>&gt;.</para>

          <para>May also contain 'SOURCE' as described above.</para>
        </listitem>

        <listitem>
          <para>PROTO - Protocol - Must be <quote>tcp</quote>,
          <quote>udp</quote>, <quote>icmp</quote>, a number, or
          <quote>all</quote>.</para>
        </listitem>

        <listitem>
          <para>DEST PORT(S) - Destination Ports. A comma-separated list of
          Port names (from <filename>/etc/services</filename>), port numbers
          or port ranges; if the protocol is <quote>icmp</quote>, this column
          is interpreted as the destination icmp-type(s).</para>

          <para>A port range is expressed as &lt;<emphasis>low
          port</emphasis>&gt;:&lt;<emphasis>high port</emphasis>&gt;.</para>

          <para>This column is ignored if PROTOCOL = all but must be entered
          if any of the following fields are supplied. In that case, it is
          suggested that this field contain <quote>-</quote>.</para>

          <para>If your kernel contains multi-port match support, then only a
          single Netfilter rule will be generated if in this list and in the
          CLIENT PORT(S) list below:</para>

          <orderedlist>
            <listitem>
              <para>There are 15 or less ports listed.</para>
            </listitem>

            <listitem>
              <para>No port ranges are included.</para>
            </listitem>
          </orderedlist>

          <para>Otherwise, a separate rule will be generated for each
          port.</para>
        </listitem>

        <listitem>
          <para>SOURCE PORT(S) - Port(s) used by the client. If omitted, any
          source port is acceptable. Specified as a comma-separated list of
          port names, port numbers or port ranges.</para>

          <para>If you don't want to restrict client ports but need to specify
          an ADDRESS in the next column, then place "-" in this column.</para>

          <para>If your kernel contains multi-port match support, then only a
          single Netfilter rule will be generated if in this list and in the
          DEST PORT(S) list above:</para>

          <orderedlist>
            <listitem>
              <para>There are 15 or less ports listed.</para>
            </listitem>

            <listitem>
              <para>No port ranges are included.</para>
            </listitem>
          </orderedlist>

          <para>Otherwise, a separate rule will be generated for each
          port.</para>
        </listitem>

        <listitem>
          <para>ORIGINAL DEST (Shorewall-perl 4.2.0 and later)</para>

          <para>To use this column, you must include 'FORMAT 2' as the first
          non-comment line in your macro file.</para>

          <para>If ACTION is DNAT[-] or REDIRECT[-] then if this column is
          included and is different from the IP address given in the DEST
          column, then connections destined for that address will be forwarded
          to the IP and port specified in the DEST column.</para>

          <para>A comma-separated list of addresses may also be used. This is
          most useful with the REDIRECT target where you want to redirect
          traffic destined for particular set of hosts. Finally, if the list
          of addresses begins with "!" (exclusion) then the rule will be
          followed only if the original destination address in the connection
          request does not match any of the addresses listed.</para>

          <para>For other actions, this column may be included and may contain
          one or more addresses (host or network) separated by commas. Address
          ranges are not allowed. When this column is supplied, rules are
          generated that require that the original destination address matches
          one of the listed addresses. This feature is most useful when you
          want to generate a filter rule that corresponds to a DNAT- or
          REDIRECT- rule. In this usage, the list of addresses should not
          begin with "!".</para>

          <para>It is also possible to specify a set of addresses then exclude
          part of those addresses. For example, 192.168.1.0/24!192.168.1.16/28
          specifies the addresses 192.168.1.0-182.168.1.15 and
          192.168.1.32-192.168.1.255. See <ulink
          url="manpages/shorewall_exclusion.html">shorewall-exclusion</ulink>(5).</para>

          <para>See <ulink
          url="http://shorewall.net/PortKnocking.html">http://shorewall.net/PortKnocking.html</ulink>
          for an example of using an entry in this column with a user-defined
          action rule.</para>
        </listitem>

        <listitem>
          <para>RATE LIMIT - You may rate-limit the rule by placing a value in
          this column:</para>

          <para><programlisting>     &lt;<emphasis>rate</emphasis>&gt;/&lt;<emphasis>interval</emphasis>&gt;[:&lt;<emphasis>burst</emphasis>&gt;]</programlisting>where
          &lt;<emphasis>rate</emphasis>&gt; is the number of connections per
          &lt;<emphasis>interval</emphasis>&gt; (<quote>sec</quote> or
          <quote>min</quote>) and &lt;<emphasis>burst</emphasis>&gt; is the
          largest burst permitted. If no &lt;<emphasis>burst</emphasis>&gt; is
          given, a value of 5 is assumed. There may be no whitespace embedded
          in the specification.</para>

          <para><programlisting>     Example: 10/sec:20</programlisting></para>
        </listitem>

        <listitem>
          <para>USER/GROUP - For output rules (those with the firewall as
          their source), you may control connections based on the effective
          UID and/or GID of the process requesting the connection. This column
          can contain any of the following:</para>

          <simplelist>
            <member>[!]&lt;<emphasis>user number</emphasis>&gt;[:]</member>

            <member>[!]&lt;<emphasis>user name</emphasis>&gt;[:]</member>

            <member>[!]:&lt;<emphasis>group number</emphasis>&gt;</member>

            <member>[!]:&lt;<emphasis>group name</emphasis>&gt;</member>

            <member>[!]&lt;<emphasis>user
            number</emphasis>&gt;:&lt;<emphasis>group
            number</emphasis>&gt;</member>

            <member>[!]&lt;<emphasis>user
            name</emphasis>&gt;:&lt;<emphasis>group
            number</emphasis>&gt;</member>

            <member>[!]&lt;<emphasis>user
            inumber</emphasis>&gt;:&lt;<emphasis>group
            name</emphasis>&gt;</member>

            <member>[!]&lt;<emphasis>user
            name</emphasis>&gt;:&lt;<emphasis>group
            name</emphasis>&gt;</member>

            <member>[!]+&lt;<emphasis>program name</emphasis>&gt; (Note:
            support for this form was removed from Netfilter in kernel version
            2.6.14).</member>
          </simplelist>
        </listitem>

        <listitem>
          <para>MARK - (Added in Shorewall-4.4.2) Defines a test on the
          existing packet or connection mark. The rule will match only if the
          test returns true. Must be empty or '-' if the macro is to be used
          within an action.</para>

          <programlisting>     [!]<replaceable>value</replaceable>[/<replaceable>mask</replaceable>][:C]</programlisting>

          <variablelist>
            <varlistentry>
              <term>!</term>

              <listitem>
                <para>Inverts the test (not equal)</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>value</replaceable></term>

              <listitem>
                <para>Value of the packet or connection mark.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term><replaceable>mask</replaceable></term>

              <listitem>
                <para>A mask to be applied to the mark before testing.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>:C</term>

              <listitem>
                <para>Designates a connection mark. If omitted, the # packet
                mark's value is tested.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>

        <listitem>
          <para>CONNLIMIT - (Added in Shorewall-4.4.2) Must be empty or '-' if
          the macro is to be used within an action.</para>

          <programlisting>     [!]<replaceable>limit</replaceable>[:<replaceable>mask</replaceable>]</programlisting>

          <para>May be used to limit the number of simultaneous connections
          from each individual host to limit connections. Requires connlimit
          match in your kernel and iptables. While the limit is only checked
          on rules specifying CONNLIMIT, the number of current connections is
          calculated over all current connections from the SOURCE host. By
          default, the <replaceable>limit</replaceable> is applied to each
          host but can be made to apply to networks of hosts by specifying a
          <replaceable>mask</replaceable>. The mask specifies the width of a
          VLSM mask to be applied to the source address; the number of current
          connections is then taken over all hosts in the subnet
          <replaceable>source-address</replaceable>/<replaceable>mask</replaceable>.
          When ! is specified, the rule matches when the number of connection
          exceeds the limit.</para>
        </listitem>

        <listitem>
          <para>TIME - (Added in Shorewall-4.4.2) Must be empty or '-' if the
          macro is to be used within an action.</para>

          <programlisting>     &lt;timeelement&gt;[&amp;...]</programlisting>

          <para><replaceable>timeelement</replaceable> may be:</para>

          <variablelist>
            <varlistentry>
              <term>timestart=<replaceable>hh</replaceable>:<replaceable>mm</replaceable>[:<replaceable>ss</replaceable>]</term>

              <listitem>
                <para>Defines the starting time of day.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>timestop=<replaceable>hh</replaceable>:<replaceable>mm</replaceable>[:<replaceable>ss</replaceable>]</term>

              <listitem>
                <para>Defines the ending time of day.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>utc</term>

              <listitem>
                <para>Times are expressed in Greenwich Mean Time.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>localtz</term>

              <listitem>
                <para>Times are expressed in Local Civil Time
                (default).</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>weekdays=ddd[,ddd]...</term>

              <listitem>
                <para>where <replaceable>ddd</replaceable> is one of
                <option>Mon</option>, <option>Tue</option>,
                <option>Wed</option>, <option>Thu</option>,
                <option>Fri</option>, <option>Sat</option> or
                <option>Sun</option></para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>monthdays=dd[,dd],...</term>

              <listitem>
                <para>where <replaceable>dd</replaceable> is an ordinal day of
                the month</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>datestart=<replaceable>yyyy</replaceable>[-<replaceable>mm</replaceable>[-<replaceable>dd</replaceable>[<option>T</option><replaceable>hh</replaceable>[:<replaceable>mm</replaceable>[:<replaceable>ss</replaceable>]]]]]</term>

              <listitem>
                <para>Defines the starting date and time.</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>datestop=<replaceable>yyyy</replaceable>[-<replaceable>mm</replaceable>[-<replaceable>dd</replaceable>[<option>T</option><replaceable>hh</replaceable>[:<replaceable>mm</replaceable>[:<replaceable>ss</replaceable>]]]]]</term>

              <listitem>
                <para>Defines the ending date and time.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </itemizedlist>

      <para>Omitted column entries should be entered using a dash
      ("-:).</para>

      <para>Example:</para>

      <para><phrase><filename>/etc/shorewall/macro.LogAndAccept</filename></phrase><programlisting>     LOG:info
     ACCEPT</programlisting></para>

      <para>To use your macro, in <filename>/etc/shorewall/rules</filename>
      you might do something like:</para>

      <programlisting>#ACTION      SOURCE      DEST        PROTO    DEST PORT(S)
LogAndAccept loc         $FW         tcp      22</programlisting>
    </section>
  </section>

  <section id="Logging">
    <title>Macros and Logging</title>

    <para>Specifying a log level in a rule that invokes a user- or
    Shorewall-defined action will cause each rule in the macro to be logged
    with the specified level (and tag).</para>

    <para>The extent to which logging of macro rules occur is governed by the
    following:</para>

    <orderedlist>
      <listitem>
        <para>When you invoke a macro and specify a log level, only those
        rules in the macro that have no log level will be changed to log at
        the level specified at the action invocation.</para>

        <para>Example:</para>

        <para>/etc/shorewall/macro.foo</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
ACCEPT       -          -        tcp      22
bar:info</programlisting>

        <para>/etc/shorewall/rules:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
foo:debug    $FW        net</programlisting>

        <para>Logging in the invoked 'foo' macro will be as if foo had been
        defined as:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
ACCEPT:debug -          -        tcp      22
bar:info</programlisting>
      </listitem>

      <listitem>
        <para>If you follow the log level with "!" then logging will be at
        that level for all rules recursively invoked by the macro.</para>

        <para>Example:</para>

        <para>/etc/shorewall/macro.foo</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
ACCEPT       -          -        tcp      22
bar:info</programlisting>

        <para>/etc/shorewall/rules:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
foo:debug!   $FW        net</programlisting>

        <para>Logging in the invoked 'foo' macro will be as if foo had been
        defined as:</para>

        <programlisting>#ACTION      SOURCE     DEST     PROTO    DEST PORT(S)
ACCEPT:debug -          -        tcp      22
bar:debug</programlisting>
      </listitem>
    </orderedlist>
  </section>

  <section id="ActionOrMacro">
    <title>How do I know if I should create an Action or a Macro?</title>

    <para>While actions and macros perform similar functions, in any given
    case you will generally find that one is more appropriate than the
    other.</para>

    <orderedlist>
      <listitem>
        <para>You can not associate an Extension Script with a macro <ulink
        url="Actions.html#Extension">the way that you can with an
        Action</ulink>. So if you need access to iptables features not
        directly supported by Shorewall then you must use an action.</para>
      </listitem>

      <listitem>
        <para>Macros are expanded in-line while each action is its own chain.
        So if there are a lot of rules involved in your new action/macro then
        it is generally better to use an action than a macro. Only the packets
        selected when you invoke the action are directed to the corresponding
        chain. On the other hand, if there are only one or two rules involved
        in what you want to do then a macro is more efficient.</para>
      </listitem>
    </orderedlist>
  </section>
</article>
