<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <start>
    <ref name="filter"/>
  </start>
  <define name="filter">
    <element name="filter">
      <ref name="filter-node-attributes"/>
      <optional>
        <element name="uuid">
          <ref name="UUID"/>
        </element>
      </optional>
      <zeroOrMore>
        <choice>
          <element name="filterref">
            <ref name="filterref-node-attributes"/>
          </element>
          <element name="rule">
          <ref name="rule-node-attributes"/>
            <optional>
              <zeroOrMore>
                <element name="mac">
                  <ref name="match-attribute"/>
                  <ref name="common-l2-attributes"/>
                  <ref name="mac-attributes"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="arp">
                  <ref name="match-attribute"/>
                  <ref name="common-l2-attributes"/>
                  <ref name="arp-attributes"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="rarp">
                  <ref name="match-attribute"/>
                  <ref name="common-l2-attributes"/>
                  <ref name="arp-attributes"/> <!-- same as arp -->
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="ip">
                  <ref name="match-attribute"/>
                  <ref name="common-l2-attributes"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-port-attributes"/>
                  <ref name="ip-attributes"/>
                  <ref name="dscp-attribute"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="ipv6">
                  <ref name="match-attribute"/>
                  <ref name="common-l2-attributes"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-port-attributes"/>
                  <ref name="ip-attributes"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="tcp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="udp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="sctp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="icmp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="icmp-attributes"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="igmp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="all">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="esp">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="ah">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="udplite">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ip-attributes-p1"/>
                  <ref name="common-ip-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="tcp-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="udp-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="sctp-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-port-attributes"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="icmpv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="icmp-attributes"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="all-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="esp-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="ah-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
            <optional>
              <zeroOrMore>
                <element name="udplite-ipv6">
                  <ref name="match-attribute"/>
                  <ref name="srcmac-attribute"/>
                  <ref name="common-ipv6-attributes-p1"/>
                  <ref name="common-ipv6-attributes-p2"/>
                  <ref name="comment-attribute"/>
                </element>
              </zeroOrMore>
            </optional>
          </element>
        </choice>
      </zeroOrMore>
    </element>
  </define>

  <!-- ########### attributes of XML nodes ############ -->

  <define name="filter-node-attributes">
    <attribute name="name">
      <data type="NCName"/>
    </attribute>
    <optional>
      <attribute name="chain">
        <choice>
          <value>root</value>
          <value>arp</value>
          <value>rarp</value>
          <value>ipv4</value>
          <value>ipv6</value>
        </choice>
      </attribute>
    </optional>
  </define>

  <define name="filterref-node-attributes">
    <attribute name="filter">
      <data type="NCName"/>
    </attribute>
    <optional>
      <element name="parameter">
        <attribute name="name">
          <ref name="filter-param-name"/>
        </attribute>
        <attribute name="value">
          <ref name="filter-param-value"/>
        </attribute>
      </element>
    </optional>
  </define>

  <define name="rule-node-attributes">
    <attribute name="action">
      <ref name='action-type'/>
    </attribute>
    <attribute name="direction">
       <ref name='direction-type'/>
    </attribute>
    <optional>
      <attribute name="priority">
        <ref name='priority-type'/>
      </attribute>
    </optional>
    <optional>
      <attribute name="statematch">
        <ref name='statematch-type'/>
      </attribute>
    </optional>
  </define>

  <define name="match-attribute">
    <interleave>
      <optional>
         <attribute name="match">
           <choice>
             <value>yes</value>
             <value>no</value>
           </choice>
         </attribute>
      </optional>
    </interleave>
  </define>

  <define name="srcmac-attribute">
    <interleave>
      <optional>
         <attribute name="srcmacaddr">
           <ref name="addrMAC"/>
         </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-l2-attributes">
    <interleave>
      <ref name="srcmac-attribute"/>
      <optional>
         <attribute name="srcmacmask">
           <ref name="addrMAC"/>
         </attribute>
      </optional>
      <optional>
         <attribute name="dstmacaddr">
           <ref name="addrMAC"/>
         </attribute>
      </optional>
      <optional>
         <attribute name="dstmacmask">
           <ref name="addrMAC"/>
         </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-ip-attributes-p1">
    <interleave>
      <optional>
        <attribute name="srcipaddr">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="srcipmask">
          <ref name="addrMask"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipaddr">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipmask">
          <ref name="addrMask"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-ip-attributes-p2">
    <interleave>
      <optional>
        <attribute name="srcipfrom">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="srcipto">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipfrom">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipto">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dscp">
          <ref name="sixbitrange"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="connlimit-above">
          <ref name="uint16range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="state">
          <ref name="stateflags-type"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-ipv6-attributes-p1">
    <interleave>
      <optional>
        <attribute name="srcipaddr">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="srcipmask">
          <ref name="addrMaskv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipaddr">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipmask">
          <ref name="addrMaskv6"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-ipv6-attributes-p2">
    <interleave>
      <optional>
        <attribute name="srcipfrom">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="srcipto">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipfrom">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstipto">
          <ref name="addrIPv6"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dscp">
          <ref name="sixbitrange"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="common-port-attributes">
    <interleave>
      <optional>
        <attribute name="srcportstart">
          <ref name="uint16range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="srcportend">
          <ref name="uint16range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstportstart">
          <ref name="uint16range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="dstportend">
          <ref name="uint16range"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="icmp-attributes">
    <interleave>
      <optional>
        <attribute name="type">
          <ref name="uint8range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="code">
          <ref name="uint8range"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="mac-attributes">
    <interleave>
      <optional>
        <attribute name="protocolid">
          <ref name="mac-protocolid"/>
        </attribute>
      </optional>
    </interleave>
  </define>

  <define name="arp-attributes">
    <interleave>
      <optional>
        <attribute name="arpsrcmacaddr">
          <ref name="addrMAC"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="arpsrcipaddr">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="arpdstmacaddr">
          <ref name="addrMAC"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="arpdstipaddr">
          <ref name="addrIP"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="hwtype">
          <ref name="uint16range"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="opcode">
          <ref name="arpOpcodeType"/>
        </attribute>
      </optional>
      <optional>
        <attribute name="protocoltype">
          <ref name="uint16range"/>
        </attribute>
      </optional>
   </interleave>
  </define>

  <define name="ip-attributes">
    <optional>
      <attribute name="protocol">
          <ref name="ipProtocolType"/>
      </attribute>
    </optional>
  </define>

  <define name="dscp-attribute">
    <optional>
      <attribute name="dscp">
        <ref name="sixbitrange"/>
      </attribute>
    </optional>
  </define>

  <define name="comment-attribute">
    <optional>
      <attribute name="comment">
        <ref name="comment-type"/>
      </attribute>
    </optional>
  </define>

  <!-- ################  type library ################ -->

  <define name="UUID">
    <choice>
      <data type="string">
        <param name="pattern">[a-fA-F0-9]{32}</param>
      </data>

      <data type="string">
        <param name="pattern">[a-fA-F0-9]{8}\-([a-fA-F0-9]{4}\-){3}[a-fA-F0-9]{12}</param>
      </data>
    </choice>
  </define>

  <define name="addrMAC">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">([a-fA-F0-9]{1,2}:){5}[a-fA-F0-9]{1,2}</param>
      </data>
    </choice>
  </define>

  <define name="addrIP">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param>
      </data>
   </choice>
  </define>

  <define name="addrIPv6">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">([a-fA-F0-9]{0,4}:){2,7}([a-fA-F0-9]*)(([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9])?</param>
      </data>
   </choice>
  </define>

  <define name="addrMask">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">32</param>
      </data>

      <data type="string">
        <param name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param>
      </data>
   </choice>
  </define>

  <define name="addrMaskv6">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">128</param>
      </data>

      <data type="string">
        <param name="pattern">([a-fA-F0-9]{0,4}:){2,7}([a-fA-F0-9]*)</param>
      </data>
   </choice>
  </define>

  <define name="sixbitrange">
    <choice>
      <data type="string">
        <param name="pattern">0x([0-3][0-9a-fA-F]|[0-9a-fA-F])</param>
      </data>

      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">63</param>
      </data>
    </choice>
  </define>

  <define name="mac-protocolid">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">0x([6-9a-fA-F][0-9a-fA-F]{2}|[0-9a-fA-F]{4})</param>
      </data>

      <data type="int">
        <param name="minInclusive">1536</param>
        <param name="maxInclusive">65535</param>
      </data>

      <choice>
        <value>arp</value>
        <value>rarp</value>
        <value>ipv4</value>
        <value>ipv6</value>
      </choice>
    </choice>
  </define>

  <define name="uint8range">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">0x[0-9a-fA-F]{1,2}</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">255</param>
      </data>
    </choice>
  </define>

  <define name="uint16range">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">0x[0-9a-fA-F]{1,4}</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">65535</param>
      </data>
    </choice>
  </define>

  <define name="arpOpcodeType">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">65535</param>
      </data>

      <data type="string">
        <param name="pattern">([Rr]eply|[Rr]equest|[Rr]equest_[Rr]everse|[Rr]eply_[Rr]everse|DRARP_[Rr]equest|DRARP_[Rr]eply|DRARP_[Ee]rror|InARP_[Rr]equest|ARP_NAK)</param>
      </data>

    </choice>
  </define>

  <define name="ipProtocolType">
    <choice>
      <!-- variable -->
      <data type="string">
        <param name="pattern">$[a-zA-Z0-9_]+</param>
      </data>

      <data type="string">
        <param name="pattern">0x[0-9a-fA-F]{1,2}</param>
      </data>

      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">255</param>
      </data>

      <choice>
        <value>tcp</value>
        <value>udp</value>
        <value>udplite</value>
        <value>esp</value>
        <value>ah</value>
        <value>icmp</value>
        <value>igmp</value>
        <value>sctp</value>
        <value>icmpv6</value>
      </choice>
    </choice>
  </define>

  <define name="filter-param-name">
    <data type="string">
      <param name="pattern">[a-zA-Z0-9_]+</param>
    </data>
  </define>

  <define name="filter-param-value">
    <data type="string">
      <param name="pattern">[a-zA-Z0-9_\.:]+</param>
    </data>
  </define>

  <define name='action-type'>
    <choice>
      <value>drop</value>
      <value>accept</value>
    </choice>
  </define>

  <define name='direction-type'>
    <choice>
      <value>in</value>
      <value>out</value>
      <value>inout</value>
    </choice>
  </define>

  <define name='priority-type'>
      <data type="int">
        <param name="minInclusive">0</param>
        <param name="maxInclusive">1000</param>
      </data>
  </define>
  <define name='statematch-type'>
    <data type="string">
      <param name="pattern">([Ff][Aa][Ll][Ss][Ee]|0)</param>
    </data>
  </define>

  <define name='comment-type'>
    <data type="string"/>
  </define>

  <define name='stateflags-type'>
    <data type="string">
      <param name="pattern">((NEW|ESTABLISHED|RELATED|INVALID)(,(NEW|ESTABLISHED|RELATED|INVALID))*|NONE)</param>
    </data>
  </define>
</grammar>
