EXPERIMENTAL

Errata Exist

Internet Engineering Task Force (IETF) M. Wasserman Request for Comments: 6296 Painless Security Category: Experimental F. Baker ISSN: 2070-1721 Cisco Systems June 2011 IPv6-to-IPv6 Network Prefix Translation Abstract This document describes a stateless, transport-agnostic IPv6-to-IPv6 Network Prefix Translation (NPTv6) function that provides the address-independence benefit associated with IPv4-to-IPv4 NAT (NAPT44) and provides a 1:1 relationship between addresses in the "inside" and "outside" prefixes, preserving end-to-end reachability at the network layer. Status of This Memo This document is not an Internet Standards Track specification; it is published for examination, experimental implementation, and evaluation. This document defines an Experimental Protocol for the Internet community. This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Not all documents approved by the IESG are a candidate for any level of Internet Standard; see Section 2 of RFC 5741. Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc6296. Copyright Notice Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must Wasserman & Baker Experimental [Page 1]

RFC 6296 NPTv6 June 2011 1 . Introduction RFC1071]. For reasons discussed in [RFC2993] and Section 5, the IETF does not recommend the use of Network Address Translation technology for IPv6. Where translation is implemented, however, this specification provides a mechanism that has fewer architectural problems than merely implementing a traditional stateful Network Address Translator in an IPv6 environment. It also provides a useful alternative to the complexities and costs imposed by multihoming using provider- independent addressing and the routing and network management issues of overlaid ISP address space. Some problems remain, however. The reader should consider the alternatives suggested in [RFC4864] and the considerations of [RFC5902] for improved approaches. The stateless approach described in this document has several ramifications: o Any security benefit that NAPT44 might offer is not present in NPTv6, necessitating the use of a firewall to obtain those benefits if desired. An example of such a firewall is described in [RFC6092]. o End-to-end reachability is preserved, although the address used "inside" the edge network differs from the address used "outside" the edge network. This has implications for application referrals and other uses of Internet layer addresses. o If there are multiple identically configured prefix translators between two networks, there is no need for them to exchange dynamic state, as there is no dynamic state -- the algorithmic translation will be identical across each of them. The network can therefore asymmetrically route, load share, and fail-over among them without issue. o Since translation is 1:1 at the network layer, there is no need to modify port numbers or other transport parameters. o TCP sessions that authenticate peers using the TCP Authentication Option [RFC5925] cannot have their addresses translated, as the addresses are used in the calculation of the Message Authentication Code. This consideration applies in general to any Wasserman & Baker Experimental [Page 3]

RFC 6296 NPTv6 June 2011 RFC3424] Protocol, which the IAB recommends against the deployment of in an environment that changes Internet addresses. o Applications using the Internet Key Exchange Protocol Version 2 (IKEv2) [RFC5996] should, at least in theory, detect the presence of the translator; while no NAT traversal solution is required, [RFC5996] would require such sessions to use UDP. 1.1 . What is Address Independence? BCP 38 [RFC2827] ingress filtering and the advertisement of customer-specific prefixes. Thus, address independence has ramifications for the edge network, networks it directly connects with (especially its upstream networks), and the Internet as a whole. The desire for address independence has been a primary driver for IPv4 NAT deployment in medium- to large-sized enterprise networks, including NAT deployments Wasserman & Baker Experimental [Page 4]

RFC 6296 NPTv6 June 2011 RFC4864] document discusses a related concept called "Address Autonomy" as a benefit of NAPT44. [RFC4864] indicates that address autonomy can be achieved by the simultaneous use of global addresses on all nodes within a site that need external connectivity and Unique Local Addresses (ULAs) [RFC4193] for all internal communication. However, this solution fails to meet the requirement for address independence, because if an ISP renumbering event occurs, all of the hosts, routers, DHCP servers, Access Control Lists (ACLs), firewalls, and other internal systems that are configured with global addresses from the ISP will need to be renumbered before global connectivity is fully restored. The use of IPv6 provider-independent (PI) addresses has also been suggested as a means to fulfill the address-independence requirement. However, this solution requires that an enterprise qualify to receive a PI assignment and persuade its ISP to install specific routes for the enterprise's PI addresses. There are a number of practical issues with this approach, especially if there is a desire to route to a number of geographically and topologically diverse sites, which can sometimes involve coordinating with several ISPs to route portions of a single PI prefix. These problems have caused numerous enterprises with plenty of IPv4 swamp space to choose to use IPv4 NAT for part, or substantially all, of their internal network instead of using their provider-independent address space. 1.2 . NPTv6 Applicability Wasserman & Baker Experimental [Page 5]

RFC 6296 NPTv6 June 2011 RFC2993]. NPTv6 involves modifying IP headers in transit, so it is not compatible with security mechanisms, such as the IPsec Authentication Header, that provide integrity protection for the IP header. NPTv6 may interfere with the use of application protocols that transmit IP addresses in the application-specific portion of the IP datagram. These applications currently require Application Layer Gateways (ALGs) to work correctly through NAPT44 devices, and similar ALGs may be required for these applications to work through NPTv6 Translators. The use of separate internal and external prefixes creates complexity for DNS deployment, due to the desire for internal nodes to communicate with other internal nodes using internal addresses, while external nodes need to obtain external addresses to communicate with the same nodes. This frequently results in the deployment of "split DNS", which may add complexity to network configuration. The choice of address within the edge network bears consideration. One could use a ULA, which maximizes address independence. That could also be considered a misuse of the ULA; if the expectation is that a ULA prevents access to a system from outside the range of the ULA, NPTv6 overrides that. On the other hand, the administration is aware that it has made that choice and could deploy a second ULA for the purpose of privacy if it desired; the only prefix that will be translated is one that has an NPTv6 Translator configured to translate to or from it. Also, using any other global-scope address format makes one either obtain a PI prefix or be at the mercy of the agency from which it was allocated. There are significant technical impacts associated with the deployment of any prefix translation mechanism, including NPTv6, and we strongly encourage anyone who is considering the implementation or Wasserman & Baker Experimental [Page 6]

RFC 6296 NPTv6 June 2011 RFC4193] to represent the internal IPv6 nodes, and the external network uses globally routable IPv6 addresses to represent the same nodes. When an NPTv6 Translator forwards datagrams in the "outbound" direction, from the internal network to the external network, NPTv6 overwrites the IPv6 source prefix (in the IPv6 header) with a corresponding external prefix. When datagrams are forwarded in the "inbound" direction, from the external network to the internal network, the IPv6 destination prefix is overwritten with a corresponding internal prefix. Using the prefixes shown in the diagram above, as an IP datagram passes through the NPTv6 Translator in the outbound direction, the source prefix (FD01:0203:0405:/48) will be overwritten with the external prefix (2001:0DB8:0001:/48). In an inbound datagram, the destination prefix (2001:0DB8:0001:/48) will be overwritten with the internal prefix (FD01:0203:0405:/48). In both cases, it is the local IPv6 prefix that is overwritten; the remote IPv6 prefix remains unchanged. Nodes on the internal network are said to be "behind" the NPTv6 Translator. 2.2 . NPTv6 between Peer Networks Wasserman & Baker Experimental [Page 8]

RFC 6296 NPTv6 June 2011 2.3 . NPTv6 Redundancy and Load Sharing 2.4 . NPTv6 Multihoming Wasserman & Baker Experimental [Page 9]

RFC 6296 NPTv6 June 2011 RFC5389]. Multihoming in this sense has one negative feature as compared with multihoming with a provider-independent address: when routes change between NPTv6 Translators, the translated prefix can change since the upstream network changes. This causes sessions and referrals dependent on it to fail as well. This is not expected to be a major issue, however, in networks where routing is generally stable. 2.5 . Mapping with No Per-Flow State Section 7. 2.6 . Checksum-Neutral Mapping RFC1071] will result in a well-defined change to the checksum value [RFC1624]. So, a checksum change caused by modifying part of the area covered by the checksum can be corrected by making a complementary change to a different 16-bit field covered by the same checksum. The NPTv6 mapping mechanisms described in this document are checksum- neutral, which means that they result in IP headers that will generate the same IPv6 pseudo-header checksum when the checksum is calculated using the standard Internet checksum algorithm [RFC1071]. Any changes that are made during translation of the IPv6 prefix are offset by changes to other parts of the IPv6 address. This results in transport layers that use the Internet checksum (such as TCP and UDP) calculating the same IPv6 pseudo-header checksum for both the internal and external forms of the same datagram, which avoids the need for the NPTv6 Translator to modify those transport layer headers to correct the checksum value. Wasserman & Baker Experimental [Page 10]

RFC 6296 NPTv6 June 2011 Section 4.2, this mapping results in an edge network using a /48 external prefix to be unable to use subnet 0xFFFF. 3 . NPTv6 Algorithmic Specification RFC4291] IPv6 Address is reproduced for clarity in Figure 5. 0 15 16 31 32 47 48 63 64 79 80 95 96 111 112 127 +-------+-------+-------+-------+-------+-------+-------+-------+ | Routing Prefix | Subnet| Interface Identifier (IID) | +-------+-------+-------+-------+-------+-------+-------+-------+ Figure 5: Enumeration of the IPv6 Address [RFC4291] 3.1 . NPTv6 Configuration Calculations 3.2 and 3.3. They are then zero-extended to /64 for the purposes of a calculation. The translation function calculates the one's complement sum of the 16-bit words of the /64 external prefix and the /64 internal prefix. It then calculates the difference between these values: internal Wasserman & Baker Experimental [Page 11]

RFC 6296 NPTv6 June 2011 3.5 . NPTv6 with a /49 or Longer Prefix 3.6 . /48 Prefix Mapping Example Wasserman & Baker Experimental [Page 13]

RFC 6296 NPTv6 June 2011 3.7 . Address Mapping for Longer Prefixes Section 3.1 for the purposes of overwriting the prefix. Then, they are both zero-extended to 64 bits to facilitate one's complement arithmetic. The "adjustment" is calculated using those 64-bit prefixes. For example, if the internal prefix is a /48 ULA and the external prefix is a /56 provider-allocated prefix, the ULA becomes a /56 with zeros in bits 48..55. For purposes of one's complement arithmetic, they are then both zero-extended to 64 bits. A side effect of this is that a subset of the subnets possible in the shorter prefix is untranslatable. While the security value of this is debatable, the administration may choose to use them for subnets that it knows need no external accessibility. We then find the first word in the IID that does not have the value 0xFFFF, trying bits 64..79, and then 80..95, 96..111, and finally 112..127. We perform the same calculation (with the same proof of correctness) as in Section 3.6 but apply it to that word. Although any 16-bit portion of an IPv6 IID could contain 0xFFFF, an IID of all-ones is a reserved anycast identifier that should not be used on the network [RFC2526]. If an NPTv6 Translator discovers a datagram with an IID of all-zeros while performing address mapping, that datagram MUST be dropped, and an ICMPv6 Parameter Problem error SHOULD be generated [RFC4443]. Wasserman & Baker Experimental [Page 14]

RFC 6296 NPTv6 June 2011 4 . Implications of Network Address Translator Behavioral Requirements 4.1 . Prefix Configuration and Generation RFC4291]. They MAY also support random generation of ULA addresses on command. Since the most common place anticipated for the implementation of an NPTv6 Translator is a Customer Premises Equipment (CPE) router, the reader is urged to consider the requirements of [RFC6204]. 4.2 . Subnet Numbering Appendix B, a network using NPTv6 Translation and a /48 external prefix MUST NOT use the value 0xFFFF to designate a subnet that it expects to be translated. 4.3 . NAT Behavioral Requirements RFC4787]. This means that when an NPTv6 Translator receives a datagram on the internal interface that has a destination address that matches the site's external prefix, it will translate the datagram and forward it internally. This allows internal nodes to reach other internal nodes using their external, global addresses when necessary. Conceptually, the datagram leaves the domain (is translated as described in Section 3.2) and returns (is again translated as described in Section 3.3). As a result, the datagram exchange will be through the NPTv6 Translator in both directions for the lifetime of the session. The alternative would be to require the NPTv6 Translator to drop the datagram, forcing the sender to use the correct internal prefix for its peer. Performing only the external- to-internal translation results in the datagram being sent from the untranslated internal address of the source to the translated and therefore internal address of its peer, which would enable the session to bypass the NPTv6 Translator for future datagrams. It would also mean that the original sender would be unlikely to recognize the response when it arrived. Wasserman & Baker Experimental [Page 15]

RFC 6296 NPTv6 June 2011 5 . Implications for Applications RFC2993]. In particular, NPTv6 Translation is stateless, so a "reset" or brief outage of an NPTv6 Translator does not break connections that traverse the translation function, and if multiple NPTv6 Translators exist between the same two networks, the load can shift or be dynamically load shared among them. Also, an NPTv6 Translator does not aggregate traffic for several hosts/interfaces behind a fewer number of external addresses, so there is no inherent expectation for an NPTv6 Translator to block new inbound flows from external hosts and no issue with a filter or blacklist associated with one prefix within the domain affecting another. A firewall can, of course, be used in conjunction with an NPTv6 Translator; this would allow the network administrator more flexibility to specify security policy than would be possible with a traditional NAT. However, NPTv6 Translation does create difficulties for some kinds of applications. Some examples include: o An application instance "behind" an NPTv6 Translator will see a different address for its connections than its peers "outside" the NPTv6 Translator. o An application instance "outside" an NPTv6 Translator will see a different address for its connections than any peer "inside" an NPTv6 Translator. o An application instance wishing to establish communication with a peer "behind" an NPTv6 Translator may need to use a different address to reach that peer depending on whether the instance is behind the same NPTv6 Translator or external to it. Since an NPTv6 Translator implements hairpinning (Section 4.3), it suffices for applications to always use their external addresses. However, this creates inefficiencies in the local network and may also complicate implementation of the NPTv6 Translator. [RFC3484] also would prefer the private address in such a case in order to reduce those inefficiencies. o An application instance that moves from a realm "behind" an NPTv6 Translator to a realm that is "outside" the network, or vice versa, may find that it is no longer able to reach its peers at the same addresses it was previously able to use. Wasserman & Baker Experimental [Page 16]

RFC 6296 NPTv6 June 2011 5.1 . Recommendation for Network Planners Considering Use of NPTv6 Translation In light of the above, network planners considering the use of NPTv6 translation should carefully consider the kinds of applications that they will need to run in the future and determine whether the address-stability and provider-independence benefits are consistent with their application requirements. Wasserman & Baker Experimental [Page 17]

RFC 6296 NPTv6 June 2011 5.2 . Recommendations for Application Writers RFC5389], Traversal Using Relays around NAT (TURN) [RFC5766], and Interactive Connectivity Establishment (ICE) [RFC5245]) have been used with traditional IPv4 NAT to circumvent some of the limitations of such devices. Similar mechanisms could also be applied to circumvent some of the issues with an NPTv6 Translator. However, all of these require the assistance of an external server or a function co-located with the translator that can tell an "internal" host what its "external" addresses are. 5.3 . Recommendation for Future Work RFC6144] [RFC6147] [RFC6145] [RFC6146] [RFC6052]. For this and other reasons, such a mechanism is beyond the scope of this document. 6 . A Note on Port Mapping RFC1918] private address spaces) can be mapped into a single external, globally routable IPv4 address, with the local port number used to identify which internal node should receive each inbound datagram. This address- amplification feature is not generally foreseen as a necessity at this time. Since port mapping requires rewriting a portion of the transport layer header, it requires NAPT44 devices to be aware of all of the transport protocols that they forward, thus stifling the development of new and improved transport protocols and preventing the use of IPsec encryption. Modifying the transport layer header is incompatible with security mechanisms that encrypt the full IP payload and restricts the NAPT44 to forwarding transport layers that use weak checksum algorithms that are easily recalculated in routers. Wasserman & Baker Experimental [Page 18]

RFC 6296 NPTv6 June 2011 7 . Security Considerations RFC6092], with appropriate configuration options including turning it on or off. When [RFC4864] talks about randomizing the subnet identifier, the idea is to make it harder for worms to guess a valid subnet identifier at an advertised network prefix. This should not be interpreted as endorsing concealment of the subnet identifier behind the obfuscating function of a translator such as NPTv6. [RFC4864] specifically talks about how to obtain the desired properties of concealment without using a translator. Topology hiding when using NAT is often ineffective in environments where the topology is visible in application layer messaging protocols such as DNS, SIP, SMTP, etc. If the information were not available through the application layer, [RFC2993] would not be valid. Due to the potential interactions with IKEv2/IPsec NAT traversal, it would be valuable to test interactions of NPTv6 with various aspects of current-day IKEv2/IPsec NAT traversal. 8 . Acknowledgements Wasserman & Baker Experimental [Page 19]

RFC 6296 NPTv6 June 2011 Appendix A . Why GSE? GSE] proposal, and as a result this proposal (which is similar to GSE in most respects and inspired by it), responds directly to current concerns in the RIR communities. Edge networks are used to an environment in IPv4 in which their addressing is disjoint from that of their upstream transit networks; it is either provider independent, or a network prefix translator makes their external address distinct from their internal address, and they like the distinction. In IPv6, there is a mantra that edge network addresses should be derived from their upstream, and if they have multiple upstreams, edge networks are expected to design their networks to use all of those prefixes equivalently. They see this as unnecessary and unwanted operational complexity and, as a result, are pushing very hard in the RIR communities for provider-independent addressing. Widespread use of provider-independent addressing has a natural and perhaps unavoidable side effect that is likely to be very expensive in the long term. With widespread PI addressing, the routing table will enumerate the networks at the edge of the transit domain, the edge networks, rather than enumerate the transit domain. Per the BGP Update Report of 17 December 2010, there are currently over 36,000 Autonomous Systems being advertised in BGP, of which over 15,000 advertise only one prefix. There are in the neighborhood of 5000 ASs that show up in a non-final position in AS paths, and perhaps another 5000 networks whose AS numbers are terminal in more than one AS path. In other words, we have prefixes for some 36,000 transit and edge networks in the route table now, many of which arguably need an Autonomous System number only for multihoming. The vast majority of networks (2/3) having the tools necessary to multihome are not Wasserman & Baker Experimental [Page 23]

RFC 6296 NPTv6 June 2011 NIST] is that "...the network should provide the capability to enable an application in a particular domain to communicate with an application in any other domain over the information network, with proper management control as to who and where applications can be inter-connected." In other words, the structure of the network should allow for and enable appropriate access control, but the structure of the network should not inherently limit access. The GSE model, by statelessly translating the prefix between an edge network and its upstream transit network, accomplishes that with a minimum of fuss and bother. Stated in the simplest terms, it enables the edge network to behave as if it has a provider-independent prefix from a multihoming and renumbering perspective without the overhead of RIR membership or maintenance of BGP connectivity, and it enables Wasserman & Baker Experimental [Page 24]

RFC 6296 NPTv6 June 2011 Appendix B . Verification Code RFC1071], the word the checksum is adjusted in cannot be initially 0xFFFF, as on the return it will be forced to 0. If 0xFFFF results are not forced to the value 0x0000 as is recommended in [RFC1071], the word the checksum is adjusted in cannot be initially 0, as on the return it will be calculated as 0+(~0) = 0xFFFF. We chose to follow [RFC1071]'s recommendations, which implies a requirement to not use 0xFFFF as a subnet number in networks with a /48 external prefix. /* * Copyright (c) 2011 IETF Trust and the persons identified as * authors of the code. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. Wasserman & Baker Experimental [Page 25]

RFC 6296 NPTv6 June 2011 Wasserman & Baker Experimental [Page 26]

RFC 6296 NPTv6 June 2011 Wasserman & Baker Experimental [Page 27]

RFC 6296 NPTv6 June 2011 Section 3.1 assuming Section 3.4 * * Create the /48, a source address in internal format, and a * source address in external format. Calculate the adjustment * if one /48 is overwritten with the other. */ void nptv6_initialization(subnet) unsigned short subnet; { int i; unsigned short inner48; unsigned short outer48; /* Initialize the internal and external prefixes. */ for (i = 0; i < 8; i++) { inner[i] = inner_init[i]; outer[i] = outer_init[i]; } inner[3] = subnet; outer[3] = subnet; /* Calculate the checksum adjustment. */ inner48 = sum1(inner, 3); outer48 = sum1(outer, 3); adjustment = sub1(inner48, outer48); } /* Wasserman & Baker Experimental [Page 28]

RFC 6296 NPTv6 June 2011 Section 3.2 assuming * Section 3.4 * * Overwrite the prefix in the source address with the outer * prefix and adjust the checksum. */ void nptv6_inner_to_outer() { int i; /* Let's get the source address into the datagram. */ for (i = 0; i < 8; i++) { datagram[i] = inner[i]; } /* Overwrite the prefix with the outer prefix. */ for (i = 0; i < 3; i++) { datagram[i] = outer[i]; } /* Adjust the checksum. */ datagram[3] = add1(datagram[3], adjustment); } /* * NPTv6 datagram from transit to edge: Section 3.3 assuming * Section 3.4 * * Overwrite the prefix in the destination address with the * inner prefix and adjust the checksum. */ void nptv6_outer_to_inner() { int i; /* Overwrite the prefix with the outer prefix. */ for (i = 0; i < 3; i++) { datagram[i] = inner[i]; } /* Adjust the checksum. */ datagram[3] = sub1(datagram[3], adjustment); } /* * Main program Wasserman & Baker Experimental [Page 29]

RFC 6296 NPTv6 June 2011 Section 3.1: initialize the system */ nptv6_initialization(subnet); /* Section 3.2: take a datagram from inside to outside */ nptv6_inner_to_outer(); /* The resulting checksum value should be unique. */ if (checksum[subnet]) { printf("inner->outer duplicated checksum: " "inner: %x:%x:%x:%x:%x:%x:%x:%x(%x) " "calculated: %x:%x:%x:%x:%x:%x:%x:%x(%x)

", inner[0], inner[1], inner[2], inner[3], inner[4], inner[5], inner[6], inner[7], sum1(inner, 8), datagram[0], datagram[1], datagram[2], datagram[3], datagram[4], datagram[5], datagram[6], datagram[7], sum1(datagram, 8)); } checksum[subnet] = 1; /* * The resulting checksum should be the same as the inner * address's checksum. */ if (sum1(datagram, 8) != sum1(inner, 8)) { printf("inner->outer incorrect: " "inner: %x:%x:%x:%x:%x:%x:%x:%x(%x) " "calculated: %x:%x:%x:%x:%x:%x:%x:%x(%x)

", inner[0], inner[1], inner[2], inner[3], inner[4], inner[5], inner[6], inner[7], sum1(inner, 8), Wasserman & Baker Experimental [Page 30]

RFC 6296 NPTv6 June 2011 Section 3.3: take a datagram from outside to inside */ nptv6_outer_to_inner(); /* * The returning datagram should have the same checksum it * left with. */ if (sum1(datagram, 8) != sum1(inner, 8)) { printf("outer->inner checksum incorrect: " "calculated: %x:%x:%x:%x:%x:%x:%x:%x(%x) " "inner: %x:%x:%x:%x:%x:%x:%x:%x(%x)

", datagram[0], datagram[1], datagram[2], datagram[3], datagram[4], datagram[5], datagram[6], datagram[7], sum1(datagram, 8), inner[0], inner[1], inner[2], inner[3], inner[4], inner[5], inner[6], inner[7], sum1(inner, 8)); } /* * And every octet should calculate back to the same inner * value. */ for (i = 0; i < 8; i++) { if (inner[i] != datagram[i]) { printf("outer->inner different: " "calculated: %x:%x:%x:%x:%x:%x:%x:%x " "inner: %x:%x:%x:%x:%x:%x:%x:%x

", datagram[0], datagram[1], datagram[2], datagram[3], datagram[4], datagram[5], datagram[6], datagram[7], inner[0], inner[1], inner[2], inner[3], inner[4], inner[5], inner[6], inner[7]); break; } } } } Wasserman & Baker Experimental [Page 31]

RFC 6296 NPTv6 June 2011 http://www.painless-security.com Fred Baker Cisco Systems Santa Barbara, California 93117 USA Phone: +1-408-526-4257 EMail: fred@cisco.com Wasserman & Baker Experimental [Page 32]