RFC 7959

Block-Wise Transfers in the Constrained Application Protocol (CoAP)

3. Examples
This section gives a number of short examples with message flows for
a block-wise GET, and for a PUT or POST. These examples demonstrate
the basic operation, the operation in the presence of
retransmissions, and examples for the operation of the block size
negotiation.

In all these examples, a Block option is shown in a decomposed way
indicating the kind of Block option (1 or 2) followed by a colon, and
then the block number (NUM), more bit (M), and block size exponent
(2**(SZX+4)) separated by slashes. For example, a Block2 Option
value of 33 would be shown as 2:2/0/32) and a Block1 Option value of
59 would be shown as 1:3/1/128.
As in [RFC7252], "MID" is used as an abbreviation for "Message ID".
3.1. Block2 Examples
The first example (Figure 2) shows a GET request that is split into
three blocks. The server proposes a block size of 128, and the
client agrees. The first two ACKs contain a payload of 128 bytes
each, and the third ACK contains a payload between 1 and 128 bytes.
CLIENT SERVER
| |
| CON [MID=1234], GET, /status ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128 |
| |
| CON [MID=1235], GET, /status, 2:1/0/128 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:1/1/128 |
| |
| CON [MID=1236], GET, /status, 2:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.05 Content, 2:2/0/128 |
Figure 2: Simple Block-Wise GET

3.2. Block1 Examples
The following examples demonstrate a PUT exchange; a POST exchange
looks the same, with different requirements on atomicity/idempotence.
Note that, similar to GET, the responses to the requests that have a
more bit in the request Block1 Option are provisional and carry the
response code 2.31 (Continue); only the final response tells the
client that the PUT succeeded.
CLIENT SERVER
| |
| CON [MID=1234], PUT, /options, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.31 Continue, 1:0/1/128 |
| |
| CON [MID=1235], PUT, /options, 1:1/1/128 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:1/1/128 |
| |
| CON [MID=1236], PUT, /options, 1:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 1:2/0/128 |
Figure 7: Simple Atomic Block-Wise PUT
A stateless server that simply builds/updates the resource in place
(statelessly) may indicate this by not setting the more bit in the
response (Figure 8); in this case, the response codes are valid
separately for each block being updated. This is of course only an
acceptable behavior of the server if the potential inconsistency
present during the run of the message exchange sequence does not lead
to problems, e.g., because the resource being created or changed is
not yet or not currently in use.

The Size2 Option may be used for two purposes:
o In a request, to ask the server to provide a size estimate along
with the usual response ("size request"). For this usage, the
value MUST be set to 0.
o In a response carrying a Block2 Option, to indicate the current
estimate the server has of the total size of the resource
representation, measured in bytes ("size indication").
Similarly, the Size1 Option may be used for two purposes:
o In a request carrying a Block1 Option, to indicate the current
estimate the client has of the total size of the resource
representation, measured in bytes ("size indication").
o In a 4.13 response, to indicate the maximum size that would have
been acceptable [RFC7252], measured in bytes.
Apart from conveying/asking for size information, the Size options
have no other effect on the processing of the request or response.
If the client wants to minimize the size of the payload in the
resulting response, it should add a Block2 Option to the request with
a small block size (e.g., setting SZX=0).
The Size options are "elective", i.e., a client MUST be prepared for
the server to ignore the size estimate request. Either Size option
MUST NOT occur more than once in a single message.
+-----+---+---+---+---+-------+--------+--------+---------+
| No. | C | U | N | R | Name | Format | Length | Default |
+-----+---+---+---+---+-------+--------+--------+---------+
| 60 | | | x | | Size1 | uint | 0-4 | (none) |
| | | | | | | | | |
| 28 | | | x | | Size2 | uint | 0-4 | (none) |
+-----+---+---+---+---+-------+--------+--------+---------+
Table 2: Size Option Numbers
Implementation Notes:
o As a quality of implementation consideration, block-wise transfers
for which the total size considerably exceeds the size of one
block are expected to include size indications, whenever those can
be provided without undue effort (preferably with the first block
exchanged). If the size estimate does not change, the indication
does not need to be repeated for every block.

o The end of a block-wise transfer is governed by the M bits in the
Block options, _not_ by exhausting the size estimates exchanged.
o As usual for an option of type uint, the value 0 is best expressed
as an empty option (0 bytes). There is no default value for
either Size option.
o The Size options are neither critical nor unsafe, and are marked
as No-Cache-Key.
5. HTTP-Mapping Considerations
In this subsection, we give some brief examples of the influence that
the Block options might have on intermediaries that map between CoAP
and HTTP.
For mapping CoAP requests to HTTP, the intermediary may want to map
the sequence of block-wise transfers into a single HTTP transfer.
For example, for a GET request, the intermediary could perform the
HTTP request once the first block has been requested and could then
fulfill all further block requests out of its cache. A constrained
implementation may not be able to cache the entire object and may use
a combination of TCP flow control and (in particular if timeouts
occur) HTTP range requests to obtain the information necessary for
the next block transfer at the right time.
For PUT or POST requests, historically there was more variation in
how HTTP servers might implement ranges; recently, [RFC7233] has
defined that Range header fields received with a request method other
than GET are not to be interpreted. So, in general, the CoAP-to-HTTP
intermediary will have to try sending the payload of all the blocks
of a block-wise transfer for these other methods within one HTTP
request. If enough buffering is available, this request can be
started when the last CoAP block is received. A constrained
implementation may want to relieve its buffering by already starting
to send the HTTP request at the time the first CoAP block is
received; any HTTP 408 status code that indicates that the HTTP
server became impatient with the resulting transfer can then be
mapped into a CoAP 4.08 response code (similarly, 413 maps to 4.13).
For mapping HTTP to CoAP, the intermediary may want to map a single
HTTP transfer into a sequence of block-wise transfers. If the HTTP
client is too slow delivering a request body on a PUT or POST, the
CoAP server might time out and return a 4.08 response code, which in
turn maps well to an HTTP 408 status code (again, 4.13 maps to 413).
HTTP range requests received on the HTTP side may be served out of a
cache and/or mapped to GET requests that request a sequence of blocks
that cover the range.

(Note that, while the semantics of CoAP 4.08 and HTTP 408 differ,
this difference is largely due to the different way the two protocols
are mapped to transport. HTTP has an underlying TCP connection,
which supplies connection state, so an HTTP 408 status code can
immediately be used to indicate that a timeout occurred during
transmitting a request through that active TCP connection. The CoAP
4.08 response code indicates one or more missing blocks, which may be
due to timeouts or resource constraints; as there is no connection
state, there is no way to deliver such a response immediately;
instead, it is delivered on the next block transfer. Still, HTTP 408
is probably the best mapping back to HTTP, as the timeout is the most
likely cause for a CoAP 4.08. Note that there is no way to
distinguish a timeout from a missing block for a server without
creating additional state, the need for which we want to avoid.)
6. IANA Considerations
This document adds the following option numbers to the "CoAP Option
Numbers" registry defined by [RFC7252]:
+--------+--------+-----------+
| Number | Name | Reference |
+--------+--------+-----------+
| 23 | Block2 | RFC 7959 |
| | | |
| 27 | Block1 | RFC 7959 |
| | | |
| 28 | Size2 | RFC 7959 |
+--------+--------+-----------+
Table 3: CoAP Option Numbers
This document adds the following response codes to the "CoAP Response
Codes" registry defined by [RFC7252]:
+------+---------------------------+-----------+
| Code | Description | Reference |
+------+---------------------------+-----------+
| 2.31 | Continue | RFC 7959 |
| | | |
| 4.08 | Request Entity Incomplete | RFC 7959 |
+------+---------------------------+-----------+
Table 4: CoAP Response Codes

7. Security Considerations
Providing access to blocks within a resource may lead to surprising
vulnerabilities. Where requests are not implemented atomically, an
attacker may be able to exploit a race condition or confuse a server
by inducing it to use a partially updated resource representation.
Partial transfers may also make certain problematic data invisible to
Intrusion Detection Systems (IDSs); it is RECOMMENDED that an IDS
that analyzes resource representations transferred by CoAP implement
the Block options to gain access to entire resource representations.
Still, approaches such as transferring even-numbered blocks on one
path and odd-numbered blocks on another path, or even transferring
blocks multiple times with different content and obtaining a
different interpretation of temporal order at the IDS than at the
server, may prevent an IDS from seeing the whole picture. These
kinds of attacks are well understood from IP fragmentation and TCP
segmentation; CoAP does not add fundamentally new considerations.
Where access to a resource is only granted to clients making use of
specific security associations, all blocks of that resource MUST be
subject to the same security checks; it MUST NOT be possible for
unprotected exchanges to influence blocks of an otherwise protected
resource. As a related consideration, where object security is
employed, PUT/POST should be implemented in the atomic fashion,
unless the object security operation is performed on each access and
the creation of unusable resources can be tolerated. Future end-to-
end security mechanisms that may be added to CoAP itself may have
related security considerations, this includes considerations about
caching of blocks in clients and in proxies (see Sections 2.10 and 5
for different strategies in performing this caching); these security
considerations will need to be described in the specifications of
those mechanisms.
A stateless server might be susceptible to an attack where the
adversary sends a Block1 (e.g., PUT) block with a high block number:
A naive implementation might exhaust its resources by creating a huge
resource representation.
Misleading size indications may be used by an attacker to induce
buffer overflows in poor implementations, for which the usual
considerations apply.
7.1. Mitigating Resource Exhaustion Attacks
Certain block-wise requests may induce the server to create state,
e.g., to create a snapshot for the block-wise GET of a fast-changing
resource to enable consistent access to the same version of a
resource for all blocks, or to create temporary resource

representations that are collected until pressed into service by a
final PUT or POST with the more bit unset. All mechanisms that
induce a server to create state that cannot simply be cleaned up
create opportunities for denial-of-service attacks. Servers SHOULD
avoid being subject to resource exhaustion based on state created by
untrusted sources. But even if this is done, the mitigation may
cause a denial-of-service to a legitimate request when it is drowned
out by other state-creating requests. Wherever possible, servers
should therefore minimize the opportunities to create state for
untrusted sources, e.g., by using stateless approaches.
Performing segmentation at the application layer is almost always
better in this respect than at the transport layer or lower (IP
fragmentation, adaptation-layer fragmentation), for instance, because
there are application-layer semantics that can be used for mitigation
or because lower layers provide security associations that can
prevent attacks. However, it is less common to apply timeouts and
keepalive mechanisms at the application layer than at lower layers.
Servers MAY want to clean up accumulated state by timing it out (cf.
response code 4.08), and clients SHOULD be prepared to run block-wise
transfers in an expedient way to minimize the likelihood of running
into such a timeout.
7.2. Mitigating Amplification Attacks
[RFC7252] discusses the susceptibility of CoAP endpoints for use in
amplification attacks.
A CoAP server can reduce the amount of amplification it provides to
an attacker by offering large resource representations only in
relatively small blocks. With this, e.g., for a 1000-byte resource,
a 10-byte request might result in an 80-byte response (with a 64-byte
block) instead of a 1016-byte response, considerably reducing the
amplification provided.
8. References
8.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<http://www.rfc-editor.org/info/rfc2119>.
[RFC7252] Shelby, Z., Hartke, K., and C. Bormann, "The Constrained
Application Protocol (CoAP)", RFC 7252,
DOI 10.17487/RFC7252, June 2014,
<http://www.rfc-editor.org/info/rfc7252>.

Acknowledgements
Much of the content of this document is the result of discussions
with the [RFC7252] authors, and via many CoRE WG discussions.
Charles Palmer provided extensive editorial comments to a previous
draft version of this document, some of which have been covered in
this document. Esko Dijk reviewed a more recent version, leading to
a number of further editorial improvements, a solution to the 4.13
ambiguity problem, and the section about combining Block and
multicast (Section 2.8). Markus Becker proposed getting rid of an
ill-conceived default value for the Block2 and Block1 Options. Peter
Bigot insisted on a more systematic coverage of the options and
response code. Qin Wu provided a review for the IETF Operations
directorate, and Goeran Selander commented on the security
considerations.
Kepeng Li, Linyi Tian, and Barry Leiba wrote up an early version of
the Size option, which is described in this document. Klaus Hartke
wrote some of the text describing the interaction of Block2 with
Observe. Matthias Kovatsch provided a number of significant
simplifications of the protocol.
The IESG reviewers provided very useful comments. Spencer Dawkins
even suggested new text. He and Mirja Kuehlewind insisted on more
explicit information about the layering of block-wise transfers on
top of the base protocol. Ben Campbell helped untangle some MUST/
SHOULD soup. Comments by Alexey Melnikov, as well as the Gen-ART
review by Jouni Korhonen, resulted in further improvements to the
text.