<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc2119 PUBLIC "" ".//reference.RFC.2119.xml">
]>
<!-- WK: Set category, IPR, docName -->
<rfc category="info" docName="draft-wkumari-capport-icmp-unreach-02"
     ipr="trust200902">
  <?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
  <?rfc toc="yes" ?>
  <?rfc symrefs="yes" ?>
  <?rfc sortrefs="yes"?>
  <?rfc iprnotified="no" ?>
  <?rfc strict="yes"?>
  <?rfc compact="yes" ?>
  <front>
    <!-- WK: Set long title. -->

    <title abbrev="draft-wkumari-capport-icmp-unreach">Captive Portal
    ICMP Messages</title>

    <author fullname="David Bird" initials="D." surname="Bird">
      <organization>Google</organization>
      <address>
        <postal>
          <street>1600 Amphitheatre Parkway</street>
          <city>Mountain View, CA</city>
          <code>94043</code>
          <country>US</country>
        </postal>
        <email>dbird@google.com</email>
      </address>
    </author>

    <author fullname="Warren Kumari" initials="W." surname="Kumari">
      <organization>Google</organization>
      <address>
        <postal>
          <street>1600 Amphitheatre Parkway</street>
          <city>Mountain View, CA</city>
          <code>94043</code>
          <country>US</country>
        </postal>
        <email>warren@kumari.net</email>
      </address>
    </author>

    <date day="2" month="April" year="2017"/>

    <area>template</area>
    <workgroup>template</workgroup>

    <abstract>
      <t>This document defines a new ICMP Type for Captive Portal
      Messages. The ICMP Type will only be known to clients supporting
      this specification and provides both generic and flow 5-tuple
      specific notifications from the Captive Portal NAS.</t>

      <t>Further, This document defines a multi-part ICMP extension to
      ICMP Destination Unreachable messages to signal, not only that
      the packet was dropped, but that it was dropped due to an Access
      Policy requiring Captive Portal interaction. Legacy clients
      will only be processing the ICMP Destination Unreachable.</t>

      <t>[ Editor note: The IETF is currently discussing improvements in
      captive portal interactions and user experience improvements. See:
      https://www.ietf.org/mailman/listinfo/captive-portals ]</t>

      <t>[RFC Editor: Please remove this before publication. This document is
      being stored in github at
      https://github.com/wlanmac/draft-wkumari-capport-icmp-unreach . Authors
      gratefully accept pull requests, and keep the latest (edit buffer)
      versions there, so commenters can follow along at home.]</t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">
      <t>Captive Portals work by blocking (or redirecting)
      communications outside of a "walled garden" until the user has
      either authenticated, acknowledged an Acceptable Use Policy
      (AUP), or otherwise satisfied the requirements of the Captive
      Portal. Depending on the captive portal implementation,
      connections other than HTTP will either timeout (silently
      packets dropped) or meet with a different, inaccurate, error
      condition (like a TCP reset, for TCP connections, or ICMP
      Destination Unreachable with existing codes).</t>

      <t>A current option for captive portal networks is to reject
      traffic not in the walled garden by returning the Destination
      Unreachable either Host or Network Administratively
      Prohibited. However, these codes are typically permanent
      policies and do not specifically indicate a captive portal is in
      use.</t>

      <t>This document defines a new ICMP Type for Captive Portal. The
      Captive Portal ICMP Type can be used to send flow 5-tuple
      specific or general notifications to user devices. As a new ICMP
      type, it is expected to be ignored by legacy devices.</t>

      <t>This document also defines an Extension Object that can be
      appended to selected multi-part ICMP messages to inform the user
      device that they are behind a captive portal, in addition to the
      underlying ICMP information. Devices able to understand the
      extension get extra information about the captive portal access
      policy, whereas legacy devices just understand the underlying
      ICMP message.</t>

      <t>The Captive Portal and Destination Unreachable types provide
      the Captive Portal NAS options in terms of what notifications
      legacy devices can and should understand.</t>

      <t>The Captive Portal ICMP Messages only provide
      notification. They do not provide any configuration. For that,
      we use <xref target="RFC7710"/> and the Captive Portal
      URI it provides.</t>

      <section title="Requirements notation">
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
        "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
        document are to be interpreted as described in <xref
        target="RFC2119"/>.</t>
      </section>

      <section title="Terminology">
	<t><list style="hanging">
          <t hangText="Capport ICMP device">Device or operating system
          compliant to this specification.</t>
          <t hangText="CP-NAS">Network Access Server implementing
          Captive Portal enforcement.</t>
          <t hangText="Legacy device">Device or operating system not
          compliant to this specification.</t>
	</list></t>
      </section>
    </section>

    <section title="Captive Portal ICMP">
      <t>Captive Portal ICMP messages come in two flavors. Messages
      can be sent using the Captive Portal ICMP Type or they can be
      sent as an ICMP Extension to an existing ICMP Type, such as
      Destination Unreachable. Data is encoded into the packet slightly
      differently in each case, however, the field formats remain
      consistent. All fields are in network byte order.</t>
      
      <t>Capport ICMP devices MUST support <xref
      target="RFC7710"/>.</t>

      <section title="Session-ID">
        <t>An unsigned short session identifier that groups ICMP
        messages. ICMP messages containing the same value MUST be
        assumed to be part of the same access policy. Any change in
        this value between ICMP messages from the same source IP
        address MUST be considered by the client to mean a change in
        access policy has occurred and previous notifications are no
        longer valid.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1           
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |          Session-ID           |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>
	
      </section>
      <section title="Flags">
	<t>In Captive Portal ICMP Messages, a flags field contains bit
	flags for optional payload data fields. All data fields are
	unsigned 32bit integers.</t>
	
	<t>Bit flags and their (optional) respective data fields:</t>
	
	<figure>
          <artwork><![CDATA[
	   0 1 2 3 4 5 6 7 
	  +-+-+-+-+-+-+-+-+
	  |V|D|P|   zero  |
	  +-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

	<t><list style="hanging">
          <t hangText="V - 1 bit">Validity</t>
          <t hangText="D - 1 bit">Delay</t>
          <t hangText="P - 1 bit">Policy Class</t>
	</list></t>
	
	<t>Optional fields included in flags appear in the ICMP
	payload in the same order as the respective bits.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                        Validity (optional)                    |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                         Delay (optional)                      |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                     Policy-Class (optional)                   |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

      </section>
      <section title="Validity">
        <t>The Validity time, in seconds, that this result should be
        considered valid and the OS SHOULD not attempt to access the
        same resource in the meantime. During the Validity time, the
        NAS MAY chose to silently drop the packets of the same flow
        5-tuple to selectively cause legacy clients to time-out
        connections.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                 Validity (seconds as uint32)                  |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

      </section>
      <section title="Delay">
        <t>The Delay time, in seconds, is the time in future when this
        result should be considered valid. This is used to give
        advanced notice that a change in access policy is about to
        happen.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                   Delay (seconds as uint32)                   |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

      </section>
      <section title="Policy Class">
        <t>The Policy Class is an unsigned integer that provides a
        "hint" to the captive portal. When a client is specifically
        responding to a Captive Portal ICMP message and is launching a
        browser, the Policy Class is given to the portal as a reason
        for the visitor to visit the portal.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                      Policy Class (uint32)                    |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

      </section>
      <section title="Message Code/C-Type">
        <t>Captive Portal Message Code and C-Types:
	<list style="hanging">
          <t hangText="0">General Change of Authorization (change in policy)</t>
          <t hangText="1">Packet/flow Error (dropped)</t>
          <t hangText="2">Packet/flow Overflow (dropped)</t>
          <t hangText="3">Packet/flow Warning (not dropped)</t>
        </list></t>
      </section>
      <section title="Message Type">
	<t>The Captive Portal ICMP Type message is specifically for
	Capport ICMP Compliant devices. It is expected that Legacy
	devices will ignore such messages.</t>

	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |      Type     |      Code     |          Checksum             |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |V|D|P|  zero   |     Length    |          Session-ID           |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |      Internet Header + leading octets of original datagram    |
	  |                                                               |
	  |                           //                                  |
	  |                                                               |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                        Validity (optional)                    |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                         Delay (optional)                      |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                     Policy-Class (optional)                   |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>

	<t>As shown in the figure above, the Captive Portal Flags and
	Session-ID and part of the ICMP header. The optional fields
	are in the ICMP payload, past the (optional) original datagram
	headers of a length defined by Length.</t>

	<t><list style="hanging">
          <t hangText="Length">Number of 4 byte words of original datagram.</t>
	</list></t>
      </section>
      <section title="Extension Object">
	<t>This document defines an extension object that can be
	appended to selected multi-part ICMP messages (<xref
	target="RFC4884"/>). This extension permits the CP-NAS to
	inform Capport ICMP Compliant devices that their connection
	has been blocked due to an Access Policy requiring interaction
	with the Captive Portal.</t>
	
	<t>The Captive Portal Extension Object can be appended to the
	ICMP Destination Unreachable messages. When Legacy devices
	receive such messages, they will only understand the
	Destination Unreachable, ignoring the extensions.</t>

	<t>When used in an Extension Object, the Captive Portal ICMP
	data fields are packed into an extension structure as shown
	below.</t>
	
	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |V|D|P|       Reserved          |         Session-ID            |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                        Validity (optional)                    |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                         Delay (optional)                      |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                     Policy-Class (optional)                   |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>
	
	<t>The following figure depicts the Destination Unreachable
	message with Captive Portal Extension. It must be preceded by
	an ICMP Extension Structure Header and an ICMP Object
	Header. Both are defined in <xref target="RFC4884"/>.</t>
	
	<figure>
          <artwork><![CDATA[
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |     Type      |      Code     |          Checksum             |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |     unused    |    Length-A   |         Next-Hop MTU*         |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |      Internet Header + leading octets of original datagram    |
	  |                                                               |
	  |                           //                                  |
	  |                                                               |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |Version|      (Reserved)       |           Checksum            |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |             Length-B          |   Class-Num   |   C-Type      |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |V|D|P|       Reserved          |         Session-ID            |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                        Validity (optional)                    |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                         Delay (optional)                      |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  |                     Policy-Class (optional)                   |
	  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	  ]]></artwork>
	</figure>
	
	<t><list style="hanging">
          <t hangText="Type">Set to 3 for Destination Unreachable.</t>
          <t hangText="Code">Can be any value Code value for Type.</t>
          <t hangText="Length-A">Length, in 4 byte words, of original datagram.</t>
          <t hangText="Version">Set to version 2, per RFC 4884.</t>
          <t hangText="Length-B">Length of extension.</t>
          <t hangText="Class-Num">Set to Captive Portal Class-Num.</t>
          <t hangText="C-Type">See section 2.6.</t>
	</list></t>
	
      </section>
    </section>
    <section title="Captive Portal URL Formatting">
      <t>The Session-ID and Policy Class is used along with the RFC
      7710 URI received from DHCP or IPv6 RA to send the user to the
      captive portal.</t>
      
      <figure>
        <artwork><![CDATA[
	RFC_7710_URI . SEP .
	      'icmp_session=' . SESSION_ID . '&' .
	      'policy_class=' . [POLICY_CLASS[,POLICY_CLASS]]
	]]></artwork>
      </figure>
      <t><list style="hanging">
          <t hangText="RFC_7710_URI">The URI received from DHCP or
          IPv6 RA per RFC 7710.</t>
	  <t hangText="SEP">If the RFC_7710_URI contains a '?', then
	  SEP equals ampersand, otherwise a question mark.</t>
	  <t hangText="SESSION_ID">The Session-ID value in integer
	  format.</t>
	  <t hangText="POLICY_CLASS">Zero or more Policy Class values
	  gathers for the same Session-ID leading to the user
	  notification..</t>
      </list></t>
      
      <t>Examples:</t>
      <figure>
        <artwork><![CDATA[
	https://wifi.domain.com/portal?icmp_session=10&policy_class=100
	https://my.domain.com/?do=login&icmp_session=10&policy_class=100,20
	]]></artwork>
      </figure>
      
    </section>
    <section title="IANA Considerations">
      <t>The IANA is requested to assign a Captive Portal ICMP Message
      Type, as well as Code values defined in section 2.6..</t>

      <t>The IANA is also requested to assign a Class-Num identifier
      for the Captive Portal Extension Object from the ICMP Extension
      Object Classes and Class Sub-types registry.</t>

      <t>The IANA is also requested to form and administer the corresponding
      class sub-type (C-Type) space per section 2.6.</t>
    </section>

    <section anchor="security" title="Security Considerations">
      <t>This method simply annotates existing ICMP Destination Unreachable
      messages to inform users why their connection was blocked. This
      technique can be used to inform captive portal detection probe software
      that there is a captive portal present (and potentially to connect to
      the URL handed out using draft-wkumari-dhc-capport. We anticipate that
      there will be a new solution devised (such as a well known URL / URI on
      captive portals) to allow the user / captive portal probe to do
      something more useful with this information.</t>
    </section>

    <section title="Acknowledgements">
      <t>The authors wish to thank the authors of RFC4950 (especially Ron
      Bonica ) - I stole much of his text when writing the extension
      definition.</t>
    </section>
  </middle>

  <back>
    <references title="Normative References">
      <?rfc include='reference.RFC.2119'?>
      <?rfc include='reference.RFC.1122'?>
      <?rfc include='reference.RFC.0792'?>
      <?rfc include='reference.RFC.4884'?>
      <?rfc include='reference.RFC.3986'?>
      <?rfc include='reference.RFC.7710'?>
    </references>

    <references title="Informative References">
      <?rfc include='reference.I-D.draft-ietf-sidr-iana-objects-03.xml'?>
    </references>

    <section title="Changes / Author Notes.">
      <t>[RFC Editor: Please remove this section before publication ]</t>

      <t>From -01 to 02.</t>

      <t><list style="symbols">
          <t>Added a new ICMP Type, redefined message payload and
          flags, and introduces Codes/C-Types.</t>
        </list></t>

      <t>From -00 to 01.</t>

      <t><list style="symbols">
          <t>Changed the Captive Portal URL to a URI, and specificed that this
          can ONLY contain a path element, which is appended to
          http://&lt;gateway_ip&gt;. This is to prevent hijacking connections
          to other addresses.</t>

          <t>Then removed the entire URL / URI scheme entirely.</t>
        </list></t>

      <t>From -genesis to -00.</t>

      <t><list style="symbols">
          <t>Initial text.</t>
        </list></t>
    </section>
  </back>
</rfc>
