RFC 1542

Clarifications and Extensions for the Bootstrap Protocol

๐Ÿ“… published October 1993, from ietf

Clarifications and Extensions for the Bootstrap Protocol ๐ŸŽ€

okay bestie, this is RFC 1542 ๐Ÿ’… It was written by W. Wimer at Carnegie Mellon University, it's dated October 1993, it's a Standards Track doc in the Network Working Group, and it updates RFC 951 and obsoletes RFC 1532 ๐Ÿฆ‹ The RFC 1532 thing is a whole story (more on that in the Abstract โœจ)

Status of this Memo ๐Ÿ“œ

This RFC specifies an Internet standards track protocol for the Internet community, and it's asking everyone for discussion and suggestions for improvements ๐Ÿซถ For the current standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards." And distribution of this memo is unlimited, so share away ๐ŸŒˆ

Abstract โœจ

so BOOTP was kinda loosely defined in its original spec ๐Ÿ’€ The behavior of "BOOTP relay agents" (which were originally called "BOOTP forwarding agents") only got a general description, and the client side was a little messy too. This memo is here to clarify and strengthen all of that ๐Ÿ’ช It's being reissued as RFC 1542 because some errors slipped into RFC 1532 during editing ๐Ÿ˜ญ

New issues have also popped up since the original spec was written, and this memo tries to handle some of those too ๐Ÿ”ฅ

Table of Contents ๐ŸŒธ

   1. Introduction.................................................  2
   1.1 Requirements................................................  3
   1.2 Terminology.................................................  3
   1.3 Data Transmission Order.....................................  4
   2. General Issues...............................................  5
   2.1 General BOOTP Processing....................................  5
   2.2 Definition of the 'flags' Field.............................  5
   2.3 Bit Ordering of Hardware Addresses..........................  7
   2.4 BOOTP Over IEEE 802.5 Token Ring Networks...................  8
   3. BOOTP Client Behavior........................................  9
   3.1 Client use of the 'flags' field.............................  9
   3.1.1 The BROADCAST flag........................................  9
   3.1.2 The remainder of the 'flags' field........................  9
   3.2 Definition of the 'secs' field.............................. 10
   3.3 Use of the 'ciaddr' and 'yiaddr' fields..................... 10
   3.4 Interpretation of the 'giaddr' field........................ 11
   3.5 Vendor information "magic cookie"........................... 12
   4. BOOTP Relay Agents........................................... 13
   4.1 General BOOTP Processing for Relay Agents................... 14
   4.1.1 BOOTREQUEST Messages...................................... 14
   4.1.2 BOOTREPLY Messages........................................ 17
   5. BOOTP Server Behavior........................................ 18
   5.1 Reception of BOOTREQUEST Messages........................... 18
   5.2 Use of the 'secs' field..................................... 19
   5.3 Use of the 'ciaddr' field................................... 19
   5.4 Strategy for Delivery of BOOTREPLY Messages................. 20
   Acknowledgements................................................ 21
   References...................................................... 22
   Security Considerations......................................... 23
   Author's Address................................................ 23

1. Introduction ๐ŸŒธ

the Bootstrap Protocol (BOOTP) is a UDP/IP-based protocol that lets a host boot up and configure itself dynamically, no babysitting required ๐Ÿงš It tells a host its assigned IP address, the IP address of a boot server host, and the name of a file to load into memory and run [1]. It can also pass along other config stuff like the local subnet mask, the local time offset, the addresses of default routers, and the addresses of various Internet servers [2].

the problem is the original BOOTP spec [1] left a bunch of stuff up for debate ๐Ÿ™ˆ How BOOTP relay agents (formerly called "BOOTP forwarding agents") were supposed to behave wasn't clearly specified. Some parts of the spec actually conflict with each other, and other parts got misinterpreted, so clarification was needed. This memo handles those issues ๐Ÿ’…

then the IEEE 802.5 Token Ring Network came along, and it creates a unique problem for BOOTP's message-transfer paradigm ๐Ÿ‘€ This memo also suggests a solution for that ๐Ÿฆ‹

NOTE: Unless otherwise specified in this document or a later document, the information and requirements specified throughout this document also apply to extensions to BOOTP such as the Dynamic Host Configuration Protocol (DHCP) [3]. (so yes, this applies to DHCP too unless something says otherwise ๐Ÿซถ)

1.1 Requirements ๐Ÿ’œ

in this memo, the words that define how important a requirement is get capitalized. Here they are, and yes, they're serious ๐Ÿซก

  • "MUST"

This word or the adjective "REQUIRED" means that the item is an absolute requirement of the specification. ๐Ÿ”ฅ

  • "MUST NOT"

This phrase means that the item is an absolute prohibition of the specification. ๐Ÿšซ

  • "SHOULD"

This word or the adjective "RECOMMENDED" means that there may exist valid reasons in particular circumstances to ignore this item, but the full implications should be understood and the case carefully weighed before choosing a different course. ๐Ÿค”

  • "SHOULD NOT"

This phrase means that there may exist valid reasons in particular circumstances when the listed behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label. ๐Ÿง

  • "MAY"

This word or the adjective "OPTIONAL" means that this item is truly optional. One vendor may choose to include the item because a particular marketplace requires it or because it enhances the product, for example; another vendor may omit the same item. ๐ŸŒˆ

1.2 Terminology ๐Ÿ“–

this memo uses the following terms:

  • BOOTREQUEST

A BOOTREQUEST message is a BOOTP message sent from a BOOTP client to a BOOTP server, requesting configuration information. ๐Ÿ™‹โ€โ™€๏ธ

  • BOOTREPLY

A BOOTREPLY message is a BOOTP message sent from a BOOTP server to a BOOTP client, providing configuration information. ๐ŸŽ

  • Silently discard

This memo specifies several cases where a BOOTP entity is to "silently discard" a received BOOTP message. That means the entity discards the message without further processing, and it won't send any ICMP error message as a result ๐Ÿคซ But for diagnosing problems, the entity SHOULD provide the capability of logging the error, including the contents of the silently-discarded message, and SHOULD record the event in a statistics counter ๐Ÿ“Š

1.3 Data Transmission Order ๐Ÿ”ข

the order of transmission for the header and data in this document is resolved all the way down to the octet level. Whenever a diagram shows a group of octets, they're transmitted in the normal order you'd read them in English. For example, in this diagram the octets go out in the order they're numbered ๐Ÿ‘‡

                     0                   1
                     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     |       1       |       2       |
                     +-------------------------------+
                     |       3       |       4       |
                     +-------------------------------+
                     |       5       |       6       |
                     +-------------------------------+

whenever an octet represents a number, the leftmost bit in the diagram is the high order (most significant) bit. So the bit labeled 0 is the most significant one. For example, this diagram shows the value 170 in decimal ๐Ÿงฎ

                               0 1 2 3 4 5 6 7
                              +-+-+-+-+-+-+-+-+
                              |1 0 1 0 1 0 1 0|
                              +---------------+

same vibe for multi-octet fields: the leftmost bit of the whole field is the most significant bit, and when a multi-octet number gets sent, the most significant octet goes first ๐Ÿ’–

2. General Issues ๐Ÿงฉ

this section covers stuff that matters to all BOOTP entities: clients, servers, and relay agents ๐Ÿค

2.1 General BOOTP Processing โœ…

the following consistency checks SHOULD be performed on BOOTP messages:

  • The IP Total Length and UDP Length must be large enough to contain the minimal BOOTP header of 300 octets (in the UDP data field) specified in [1].

NOTE: Future extensions to the BOOTP protocol may increase the size of BOOTP messages. Therefore, BOOTP messages which, according to the IP Total Length and UDP Length fields, are larger than the minimum size specified by [1] MUST also be accepted. (so bigger messages are totally welcome, no drama ๐ŸŒธ)

  • The 'op' (opcode) field of the message must contain either the code for a BOOTREQUEST (1) or the code for a BOOTREPLY (2).

BOOTP messages that don't pass these consistency checks MUST be silently discarded. ๐Ÿ—‘๏ธ no cap, that's the rule ๐Ÿ’…

(to be continued โœจ๐Ÿฆ‹)

2.2 Definition of the 'flags' Field โœจ

okay so the standard BOOTP message format from [1] has this two-octet field chilling between secs and ciaddr ๐Ÿฆ‹. it's literally just labeled "unused" and nobody said what goes in it ๐Ÿ’€. Section 7.1 of [1] does give this lowkey good advice:

"Before setting up the packet for the first time, it is a good idea to clear the entire packet buffer to all zeros; this will place all fields in their default state."

so this memo is like "bet, we're officially naming this field flags" ๐Ÿ’…

the most significant bit gets to be the BROADCAST (B) flag ๐Ÿ“ฃ. we talk about what it actually does in Sections 3.1.1 and 4.1.2.

the rest of the bits are reserved for future use ๐Ÿ”ฎ. they MUST be set to zero by clients and ignored by servers and relay agents. no exceptions, bestie ๐Ÿ™…

here's the layout ๐ŸŽ€

                     0                   1
                     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     |B|             MBZ             |
                     +-+-----------------------------+

and the key ๐Ÿ”‘

where:

   B    BROADCAST flag (discussed in Sections 3.1.1 and 4.1.2)

   MBZ  MUST BE ZERO (reserved for future use)

now for the full BOOTP message format ๐Ÿงš the numbers in parentheses are how many octets each field takes up:

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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
+---------------+---------------+---------------+---------------+
|                            xid (4)                            |
+-------------------------------+-------------------------------+
|           secs (2)            |           flags (2)           |
+-------------------------------+-------------------------------+
|                           ciaddr (4)                          |
+---------------------------------------------------------------+
|                           yiaddr (4)                          |
+---------------------------------------------------------------+
|                           siaddr (4)                          |
+---------------------------------------------------------------+
|                           giaddr (4)                          |
+---------------------------------------------------------------+
|                                                               |
|                           chaddr (16)                         |
|                                                               |
|                                                               |
+---------------------------------------------------------------+
|                                                               |
|                           sname  (64)                         |
+---------------------------------------------------------------+
|                                                               |
|                           file   (128)                        |
+---------------------------------------------------------------+
|                                                               |
|                           vend   (64)                         |
+---------------------------------------------------------------+

2.3 Bit Ordering of Hardware Addresses ๐Ÿงฒ

the bit ordering for link-level hardware addresses in the chaddr field SHOULD match the ordering ARP [4] uses on the client's link-level network (assuming ARP is defined for that network) ๐Ÿ”—

the chaddr field MUST be kept exactly as the BOOTP client wrote it. a relay agent MUST NOT flip the bit ordering of chaddr, even if it's relaying a BOOTREQUEST between two networks that order bits differently ๐Ÿ™…โ€โ™€๏ธ

DISCUSSION:

the whole reason chaddr exists is so BOOTP servers and relay agents can talk straight to clients without broadcasting ๐Ÿ“ก. in practice, the chaddr contents often get used to make an ARP-cache entry, the same way normal ARP would ๐Ÿ—‚๏ธ. so yeah, interoperability only works if everyone reads chaddr the same way ๐Ÿซถ

for example, a BOOTP client on an IEEE 802.5 Token Ring network uses the opposite bit ordering from a BOOTP client on a DIX ethernet network. wild, right? ๐Ÿคฏ

2.4 BOOTP Over IEEE 802.5 Token Ring Networks ๐Ÿ’

client/server and client/relay agent interactions need extra care on IEEE 802.5 networks, because of non-transparent bridging ๐ŸŒ‰

the client SHOULD send its broadcast BOOTREQUEST with an All Routes Explorer RIF ๐Ÿ—บ๏ธ. that lets servers and relay agents cache the return route, if they want to. for the ones that can't cache the return route (because they're stateless, for example), the BOOTREPLY SHOULD be sent to the client's hardware address, taken from the BOOTP message, with a Spanning Tree Rooted RIF ๐ŸŒณ. the actual bridge route then gets recorded by the client and the server or relay agent through normal ARP processing ๐Ÿ“

DISCUSSION:

in the simplest case, an unbridged, single ring network, BOOTP broadcasting works exactly like it does on Ethernet ๐Ÿฅฐ. the problem is that a BOOTP client can't know, ahead of time, that its 802.5 network isn't bridged. the server or relay agent probably won't know either ๐Ÿคทโ€โ™€๏ธ

there are four possible scenarios, but only two are actually interesting ๐Ÿ‘€:

  • the assumption is "not bridged" and the network IS bridged. then the RIF won't be used, so if the server or relay agent sits on another segment of the ring, the client can't reach it ๐Ÿ’€
  • the assumption is "bridged" and the network is NOT. then the RIF gets used, which adds a few extra bytes on the ring ๐Ÿงƒ

the second one is totally the lesser evil. a tiny inefficiency beats a complete failure to communicate ๐Ÿซ 

since we're assuming RIF fields will be needed, we have to figure out the optimum way for the client to reach the server or relay agent, AND the optimum way for the response to come back ๐ŸŽฏ

3. BOOTP Client Behavior ๐ŸŽ€

this section clears up a few things about how BOOTP clients behave ๐Ÿ’…

3.1 Client use of the 'flags' field

3.1.1 The BROADCAST flag ๐Ÿ“ฃ

normally, BOOTP servers and relay agents try to deliver BOOTREPLY messages straight to the client using unicast. the IP destination address (in the IP header) is set to the BOOTP yiaddr address, and the link-layer destination address is set to the BOOTP chaddr address. the catch is that some clients can't receive unicast IP datagrams until they already know their own IP address. it's a total "chicken and egg" situation ๐Ÿ”๐Ÿฅš still, a lot of them can receive broadcast IP datagrams (ones with a valid IP broadcast address as the IP destination and the link-layer broadcast address as the link-layer destination) ๐Ÿ“ข

if a client is in that boat, it SHOULD set (to 1) the newly-defined BROADCAST flag in the flags field of the BOOTREPLY messages it generates ๐Ÿšฉ. that's a hint telling servers and relay agents to broadcast their BOOTREPLY messages to the client ๐Ÿ™Œ

if a client doesn't have that limitation (it can totally receive unicast BOOTREPLY messages), it SHOULD NOT set the BROADCAST flag (it SHOULD clear the BROADCAST flag to 0) ๐Ÿงน

DISCUSSION:

this addition is a workaround for old host implementations ๐Ÿ› ๏ธ. those implementations SHOULD be modified so they can receive unicast BOOTREPLY messages, which would make this workaround unnecessary. in general, this mechanism is discouraged ๐Ÿ™ˆ

3.1.2 The remainder of the 'flags' field ๐Ÿ”ฎ

the remaining bits of the flags field are reserved for future use. a client MUST set these bits to zero in every BOOTREQUEST it generates. a client MUST ignore these bits in every BOOTREPLY it receives ๐Ÿซถ

3.2 Definition of the 'secs' field โฑ๏ธ

the secs field of a BOOTREQUEST message SHOULD represent the number of seconds elapsed since the client sent its first BOOTREQUEST message โณ. which means the secs field of that very first BOOTREQUEST SHOULD be set to zero 0๏ธโƒฃ

clients SHOULD NOT set secs to a value that stays constant across all BOOTREQUEST messages ๐Ÿšซ

DISCUSSION:

the original definition of secs was super vague ๐Ÿ˜ตโ€๐Ÿ’ซ. it wasn't clear whether it counted from the first BOOTREQUEST or from something else, like when the client machine was powered up. that made it pretty useless as a policy control mechanism for BOOTP servers and relay agents ๐Ÿ“‰. on top of that, some client implementations have been known to just set this field to a constant value, or to use the wrong byte ordering. the wrong byte ordering makes it look like a client has been waiting way longer than it really has, so a relay agent ends up relaying the BOOTREQUEST sooner than intended (usually immediately) ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ. these implementation errors made secs even less useful ๐Ÿ˜ค. those incorrect implementations SHOULD be corrected ๐Ÿ”งโœจ

3.3. Use of the 'ciaddr' and 'yiaddr' fields ๐ŸŽ€

okay so if a BOOTP client doesn't know what IP address it should be using, it SHOULD set the 'ciaddr' field to 0.0.0.0 ๐Ÿซถ. If the client can remember the last IP address it was given, or it was preconfigured with one some other way, it MAY fill 'ciaddr' with that address. But if it DOES put a non-zero address in 'ciaddr', it MUST be prepared to accept incoming unicast datagrams sent to that address AND answer ARP requests for it (if ARP is used on that network) ๐Ÿ’…โœจ.

The BOOTP server is totally free to hand out a different IP address (in 'yiaddr') than the one the client put in 'ciaddr' ๐Ÿฆ‹. The client SHOULD adopt the address in 'yiaddr' and start using it as soon as possible ๐ŸŒธ.

DISCUSSION: ๐Ÿ’ฌ

ngl this part is a whole debate ๐Ÿ™ˆ. People have different takes on what 'ciaddr' is even for, and there's no agreed single correct answer. One take is that if a client is happy to accept whatever address the server assigns, it should always put 0.0.0.0 in 'ciaddr', even if it remembers an old address. The flip side is that if the client needs a specific IP address (say the admin hand-configured it and BOOTP is only being used to grab a boot file and/or info from the 'vend' field), then it fills 'ciaddr' with the address it wants and ignores whatever 'yiaddr' says ๐Ÿ˜ค.

Another take says the client always fills 'ciaddr' with its most recently assigned IP address (if it knows one), even if that address might be wrong. This client still accepts and uses the address in 'yiaddr'. The reason people like this one is that it helps the server identify the client and/or deliver the BOOTREPLY to it ๐Ÿงš.

Then there's a third (mis)interpretation, where the client uses 'ciaddr' to ask for whatever IP it wants, even if it's never used that address before or isn't using it right now. Honestly, this one is giving chaos ๐Ÿ’€.

That last one is just incorrect, because it can stop the BOOTREPLY from ever reaching the client. The server will usually unicast the reply to the address in 'ciaddr', but the client might not be listening on that address yet, or it might be plugged into the wrong subnet, so normal IP routing (correctly!) sends the reply somewhere else ๐Ÿ˜ญ.

The second take also has the "incorrect subnet" problem ๐Ÿ™ƒ.

The first interpretation seems to be the safest and the most likely to keep everyone interoperable ๐Ÿ‘‘.


3.4. Interpretation of the 'giaddr' field ๐Ÿ“

The 'giaddr' field is kinda poorly named, not gonna lie ๐Ÿ™ˆ. Its whole job is to help BOOTREQUEST messages get from a client, through BOOTP relay agents, to servers on different networks than the client. Likewise, it helps BOOTREPLY messages travel from the servers, through relay agents, back to the client. It is NEVER a general IP router for the client to use ๐Ÿšซ. A BOOTP client MUST set 'giaddr' to zero (0.0.0.0) in all BOOTREQUEST messages it generates ๐Ÿ’–.

A BOOTP client MUST NOT interpret the 'giaddr' field of a BOOTREPLY message as the IP address of an IP router ๐Ÿ™…โ€โ™€๏ธ. A BOOTP client SHOULD completely ignore the contents of the 'giaddr' field in BOOTREPLY messages ๐Ÿซถ.

DISCUSSION: ๐Ÿ’ฌ

The semantics of 'giaddr' were honestly not well defined. Section 7.5 of [1] says:

"If 'giaddr' (gateway address) is nonzero, then the packets should be forwarded there first, in order to get to the server."

In that sentence, "get to" is about the communication from the client to the server after the BOOTP exchange, like a TFTP session ๐Ÿฆ‹. The problem is that 'giaddr' might hold the address of a BOOTP relay agent that isn't actually an IP router (according to [1], Section 8, fifth paragraph). In that case it's useless as a first hop for TFTP packets going to the server, because by definition non-routers don't forward datagrams at the IP layer ๐Ÿ˜ฉ.

Even though Section 4.1.1 of this memo now prohibits it, 'giaddr' might contain a broadcast address according to Section 8, sixth paragraph of [1]. That's not only useless as a router address, it could also make the client ARP for the broadcast address. (If the client didn't get a subnet mask in the BOOTREPLY, it wouldn't be able to recognize a subnet broadcast address.) This is clearly undesirable, bestie ๐Ÿ™…โ€โ™€๏ธ.

To reach a server that isn't local, clients can get a first-hop router address from the "Gateway" subfield of the "Vendor Information Extensions" [2] (if it's there), or through the ICMP router discovery protocol [5] or some other similar mechanism ๐Ÿงญ.


It is RECOMMENDED that a BOOTP client always fill the first four octets of the 'vend' (vendor information) field of a BOOTREQUEST with a four-octet identifier called a "magic cookie" โœจ. A BOOTP client SHOULD do this even if it has no special info to send to the BOOTP server through the 'vend' field ๐Ÿซถ. It helps the server figure out which vendor information format to use in its BOOTREPLY messages ๐Ÿ’œ.

If a special vendor-specific magic cookie isn't being used, a BOOTP client SHOULD use the dotted decimal value 99.130.83.99 as specified in [2] ๐ŸŒˆ. In this case, if the client has no info to send to the server, the octet right after the magic cookie SHOULD be set to the "End" tag (255), and the remaining octets of the 'vend' field SHOULD be set to zero ๐Ÿ“.

DISCUSSION: ๐Ÿ’ฌ

Sometimes different operating systems or networking packages run on the same machine at different times (or even at the same time!) ๐Ÿคฏ. The hardware address in the 'chaddr' field will probably be the same every time, so BOOTREQUESTs from totally different BOOTP clients on the same machine will be super hard for a BOOTP server to tell apart ๐Ÿ˜ต. If the client includes a magic cookie in its BOOTREQUESTs, though, the server will at least know what format the client expects and can understand in the matching BOOTREPLY messages ๐ŸŽ€.


4. BOOTP Relay Agents โœจ

In a lot of cases, BOOTP clients and their BOOTP server(s) don't live on the same IP network or subnet ๐Ÿ—บ๏ธ. When that happens, some kind of third-party agent is needed to carry BOOTP messages between clients and servers. This agent was originally called a "BOOTP forwarding agent." But to avoid mixing it up with the IP forwarding function of an IP router, the name "BOOTP relay agent" is hereby adopted instead ๐Ÿ’….

DISCUSSION: ๐Ÿ’ฌ

A BOOTP relay agent does a different job from an IP router's normal IP forwarding ๐Ÿฆ‹. A router normally switches IP datagrams between networks more or less transparently. A BOOTP relay agent is better thought of as receiving BOOTP messages as their final destination, and then generating brand-new BOOTP messages as a result ๐Ÿง . It's incorrect for a relay agent implementation to just forward a BOOTP message "straight through like a regular packet" ๐Ÿ™…โ€โ™€๏ธ.

This relay-agent functionality is most conveniently put in the routers that connect the clients and servers, but it can also live in a host that's directly connected to the client subnet ๐Ÿ .

Any Internet host or router that provides BOOTP relay-agent capability MUST conform to the specifications in this memo ๐Ÿ‘‘.

4.1. General BOOTP Processing for Relay Agents ๐ŸŒธ

All locally delivered UDP messages whose UDP destination port number is BOOTPS (67) get considered for special processing by the host or router's logical BOOTP relay agent ๐Ÿงš.

For a host, locally delivered datagrams are simply all the datagrams that host normally receives, i.e., broadcast and multicast datagrams as well as unicast datagrams addressed to IP addresses of that host ๐Ÿ’–.

For a router, locally delivered datagrams are broadcast and multicast datagrams as well as unicast datagrams addressed to IP addresses of that router ๐ŸŒˆ. These are datagrams where the router should count as the end destination, not just an intermediate switching node. So a unicast datagram with an IP destination that doesn't match any of the router's IP addresses doesn't get considered for processing by the router's logical BOOTP relay agent ๐Ÿ™…โ€โ™€๏ธ.

Hosts and routers are usually required to silently discard incoming datagrams that contain illegal IP source addresses. This is generally known as "Martian address filtering" ๐Ÿ‘ป. One of those illegal addresses is 0.0.0.0 (or really anything on network 0). But hosts or routers that support a BOOTP relay agent MUST accept BOOTREQUEST messages whose IP source address is 0.0.0.0 for local delivery to the relay agent ๐Ÿซถ. BOOTREQUEST messages from legal IP source addresses MUST also be accepted ๐Ÿ’….

A relay agent MUST silently discard any received UDP messages whose UDP destination port number is BOOTPC (68) ๐Ÿšซ.

DISCUSSION: ๐Ÿ’ฌ

There shouldn't be any need for a relay agent to process messages addressed to the BOOTPC port. If you read the original BOOTP specification [1] carefully, you'll see this ๐Ÿ“–. Still, some relay agent implementations incorrectly relay those messages anyway ๐Ÿ˜ญ.

The consistency checks specified in Section 2.1 SHOULD be performed by the relay agent ๐Ÿ”. BOOTP messages that don't pass these consistency checks MUST be silently discarded ๐Ÿ—‘๏ธ.

4.1.1 BOOTREQUEST Messages

okay so ๐ŸŽ€ some configuration mechanism MUST exist to turn the relaying of BOOTREQUEST messages on or off. And relaying MUST be disabled by default, no cap ๐Ÿ™ˆ

When the BOOTP relay agent gets a BOOTREQUEST message, it MAY use the value of the 'secs' (seconds since client began booting) field of the request as a factor in deciding whether to relay it ๐Ÿฆ‹. If a policy mechanism like that is implemented, its threshold SHOULD be configurable โœจ.

DISCUSSION: To date, this feature of the BOOTP protocol has not necessarily been shown to be useful ๐Ÿ’€. See Section 3.2 for a discussion.

The relay agent MUST silently discard BOOTREQUEST messages whose 'hops' field exceeds the value 16 ๐Ÿšซ. A configuration option SHOULD be provided to set this threshold to a smaller value if the network manager wants that ๐Ÿ“. The default setting for a configurable threshold SHOULD be 4.

If the relay agent does decide to relay the request, it MUST examine the 'giaddr' ("gateway" IP address) field ๐Ÿ‘€. If this field is zero, the relay agent MUST fill it with the IP address of the interface the request was received on. If that interface has more than one IP address logically associated with it, the relay agent SHOULD choose one of them and use it consistently for all BOOTP messages it relays ๐Ÿ’…. If the 'giaddr' field contains some non-zero value, the 'giaddr' field MUST NOT be modified. The relay agent MUST NOT, under any circumstances, fill the 'giaddr' field with a broadcast address, even though [1] (Section 8, sixth paragraph) kinda suggests it ๐Ÿ™…โ€โ™€๏ธ.

The value of the 'hops' field MUST be incremented โœจ. All other BOOTP fields MUST be preserved intact ๐Ÿซถ.

At this point the request gets relayed to its new destination (or destinations). This destination MUST be configurable. Further, this destination configuration SHOULD be independent of the destination configuration for any other so-called "broadcast forwarders" (e.g., for the UDP-based TFTP, DNS, Time, etc. protocols) ๐ŸŒˆ.

DISCUSSION: The network manager might want the relay destination to be an IP unicast, multicast, broadcast, or some combo ๐Ÿฐ. A configurable list of destination IP addresses gives you lots of flexibility, and more flexible configuration schemes are super encouraged ๐Ÿ™Œ. For example, it might be nice to send to the limited broadcast address (255.255.255.255) on specific physical interfaces. However, if the BOOTREQUEST message was received as a broadcast, the relay agent MUST NOT rebroadcast the BOOTREQUEST on the physical interface it came from ๐Ÿšซ. A relay agent MUST use the same destination (or set of destinations) for all BOOTREQUEST messages it relays from a given client ๐Ÿ’–.
DISCUSSION: At least one known relay agent implementation uses a round-robin scheme to balance load across multiple BOOTP servers ๐ŸŽก. Each time it gets a new BOOTREQUEST message, it relays it to the next BOOTP server in a list of servers. So with this relay agent, multiple consecutive BOOTREQUEST messages from a given client end up at different servers ๐Ÿ˜ญ. Unfortunately, this well-intentioned scheme reacts badly with DHCP [3] and maybe other variations of the BOOTP protocol that depend on multiple exchanges of BOOTREQUEST and BOOTREPLY messages between clients and servers ๐Ÿ’€. Therefore, all BOOTREQUEST messages from a given client MUST be relayed to the same destination (or set of destinations). One way to meet this requirement while still getting some load-balancing benefit is to hash the client's link-layer address (or some other reliable client-identifying information) and use the hash value to pick the relay destination (or set of destinations) ๐Ÿง . The simplest solution, of course, is to skip load balancing and just relay ALL received BOOTREQUEST messages to the same destination (or set of destinations) ๐Ÿซ . When transmitting the request to its next destination, the relay agent may set the IP Time-To-Live field to either the default value for new datagrams originated by the relay agent, or to the TTL of the original BOOTREQUEST decremented by (at least) one ๐Ÿฆ‹. As an extra precaution against BOOTREQUEST loops, it is preferable to use the decremented TTL from the original BOOTREQUEST ๐Ÿ›ก๏ธ. Unfortunately, this may be difficult to do in some implementations ๐Ÿ˜ฉ.

If the BOOTREQUEST has a UDP checksum (i.e., the UDP checksum is non-zero), the checksum must be recalculated before transmitting the request ๐Ÿ”.

4.1.2 BOOTREPLY Messages

BOOTP relay agents relay BOOTREPLY messages only to BOOTP clients ๐ŸŽฏ. It's the responsibility of BOOTP servers to send BOOTREPLY messages directly to the relay agent identified in the 'giaddr' field. So a relay agent can assume that every BOOTREPLY message it receives is meant for BOOTP clients on its directly-connected networks ๐Ÿฅฐ.

When a relay agent receives a BOOTREPLY message, it should examine the BOOTP 'giaddr', 'yiaddr', 'chaddr', 'htype', and 'hlen' fields ๐Ÿ”. These fields should give it enough info to deliver the BOOTREPLY message to the client.

The 'giaddr' field can be used to identify the logical interface the reply must be sent from (i.e., the host or router interface connected to the same network as the BOOTP client) ๐Ÿ›ฃ๏ธ. If the content of the 'giaddr' field doesn't match one of the relay agent's directly-connected logical interfaces, the BOOTREPLY message MUST be silently discarded ๐Ÿ—‘๏ธ.

The 'htype', 'hlen', and 'chaddr' fields supply the link-layer hardware type, hardware address length, and hardware address of the client, as defined in the ARP protocol [4] and the Assigned Numbers document [6] ๐Ÿ“‡. The 'yiaddr' field is the IP address of the client, as assigned by the BOOTP server ๐Ÿก.

The relay agent SHOULD examine the newly-defined BROADCAST flag (see Sections 2.2 and 3.1.1 for more info) ๐Ÿšฉ. If this flag is set to 1, the reply SHOULD be sent as an IP broadcast, using the IP limited broadcast address 255.255.255.255 as the IP destination address and the link-layer broadcast address as the link-layer destination address ๐Ÿ“ข. If the BROADCAST flag is cleared (0), the reply SHOULD be sent as an IP unicast to the IP address specified by the 'yiaddr' field and the link-layer address specified in the 'chaddr' field ๐ŸŽฏ. If unicasting isn't possible, the reply MAY be sent as a broadcast, in which case it SHOULD be sent to the link-layer broadcast address using the IP limited broadcast address 255.255.255.255 as the IP destination address ๐Ÿ”Š.

DISCUSSION: The BROADCAST flag got added to the protocol as a workaround to help with interoperability with certain client implementations ๐Ÿฉน. Note that since the 'flags' field was previously defined in [1] simply as an "unused" field, it's possible that old client or server implementations may accidentally and unknowingly set the new BROADCAST flag ๐Ÿ‘€. It's actually expected that this will be rare (most implementations seem to zero out this field), but interactions with such implementations still have to be considered. If an old client or server sets the BROADCAST flag to 1 by mistake, conforming relay agents will generate broadcast BOOTREPLY messages to the corresponding client. The BOOTREPLY messages should still properly reach the client, at the cost of one (otherwise unnecessary) extra broadcast. This is no worse than a server or relay agent that always broadcasts its BOOTREPLY messages ๐Ÿคทโ€โ™€๏ธ. Older client or server implementations that accidentally set the BROADCAST flag SHOULD be corrected to properly comply with this newer specification ๐Ÿ› ๏ธ.

All BOOTP fields MUST be preserved intact. The relay agent MUST NOT modify any BOOTP field of the BOOTREPLY message when relaying it to the client ๐Ÿ™Œ.

The reply MUST have its UDP destination port set to BOOTPC (68) ๐ŸŽ€.

If the BOOTREPLY has a UDP checksum (i.e., the UDP checksum is non-zero), the checksum must be recalculated before transmitting the reply โ™ป๏ธ.


5. BOOTP Server Behavior

This section clarifies the behavior of BOOTP servers ๐Ÿ“.

5.1 Reception of BOOTREQUEST Messages

All received UDP messages whose UDP destination port number is BOOTPS (67) are considered for processing by the BOOTP server ๐Ÿ‘‘.

Hosts and routers are usually required to silently discard incoming datagrams containing illegal IP source addresses. This is generally known as "Martian address filtering." One of these illegal addresses is 0.0.0.0 (or actually anything on network 0). However, hosts or routers that support a BOOTP server MUST accept for local delivery to the server BOOTREQUEST messages whose IP source address is 0.0.0.0. BOOTREQUEST messages from legal IP source addresses MUST also be accepted ๐Ÿ›Ž๏ธ.

A BOOTP server MUST silently discard any received UDP messages whose UDP destination port number is BOOTPC (68) ๐Ÿ™…โ€โ™€๏ธ.

DISCUSSION: There should be no need for a BOOTP server to process messages addressed to the BOOTPC port. Careful reading of the original BOOTP specification [1] will show this ๐Ÿ“–. The consistency checks specified in Section 2.1 SHOULD be performed by the BOOTP server ๐Ÿง. BOOTP messages that don't meet these consistency checks MUST be silently discarded ๐Ÿ—‘๏ธ.

5.2 Use of the 'secs' field

When the BOOTP server receives a BOOTREQUEST message, it MAY use the value of the 'secs' (seconds since client began booting) field of the request as a factor in deciding whether and/or how to reply to the request โฑ๏ธ.

DISCUSSION: To date, this feature of the BOOTP protocol has not necessarily been shown to be useful ๐Ÿ’€. See Section 3.2 for a discussion.

5.3 Use of the 'ciaddr' field

There have been various client interpretations of the 'ciaddr' field, so Section 3.3 should be consulted ๐Ÿค”. A BOOTP server SHOULD be prepared to deal with these varying interpretations ๐Ÿซก. In general, the 'ciaddr' field SHOULD NOT be trusted as a sole key for identifying a client. The contents of the 'ciaddr', 'chaddr', 'htype', and 'hlen' fields, and probably other info (perhaps in the 'file' and 'vend' fields), SHOULD all be considered together when deciding how to respond to a given client ๐Ÿงฉ.

BOOTP servers SHOULD preserve the contents of the 'ciaddr' field in BOOTREPLY messages. The contents of 'ciaddr' in a BOOTREPLY message SHOULD exactly match the contents of 'ciaddr' in the corresponding BOOTREQUEST message ๐Ÿ’….

DISCUSSION: It's been suggested that a client may want to use the contents of 'ciaddr' to double-check that a particular BOOTREPLY message was really meant for it ๐Ÿ•ต๏ธโ€โ™€๏ธโœจ.

5.4. Strategy for Delivery of BOOTREPLY Messages ๐Ÿ“ฌ

Okay bestie, so once the BOOTP server has cooked up a shiny BOOTREPLY message ๐Ÿณ, that message must be properly delivered to the client. No skipping this step, it's giving main character stakes โœจ

The server SHOULD first check the 'ciaddr' field ๐Ÿ‘€. If the 'ciaddr' field is non-zero, the BOOTREPLY message SHOULD be sent as an IP unicast to the IP address identified in the 'ciaddr' field. The UDP destination port MUST be set to BOOTPC (68). But ngl, the server MUST be aware of the problems identified in Section 3.3 ๐Ÿ™ˆ. The server MAY choose to ignore the 'ciaddr' field and act as if the 'ciaddr' field contains 0.0.0.0 (and thus continue with the rest of the delivery algorithm below) ๐Ÿฆ‹.

Next up, the server SHOULD check the 'giaddr' field ๐Ÿ’–. If this field is non-zero, the server SHOULD send the BOOTREPLY as an IP unicast to the IP address identified in the 'giaddr' field. The UDP destination port MUST be set to BOOTPS (67). This action delivers the BOOTREPLY message directly to the BOOTP relay agent closest to the client, and then the relay agent handles the final delivery to the client ๐Ÿงš. If the BOOTP server has prior knowledge that a particular client cannot receive unicast BOOTREPLY messages (for example, the network manager has explicitly configured the server with that knowledge), the server MAY set the newly-defined BROADCAST flag to indicate that relay agents SHOULD broadcast the BOOTREPLY message to the client. Otherwise, the server MUST preserve the state of the BROADCAST flag so that the relay agent can correctly act upon it ๐Ÿซถ.

If the 'giaddr' field is set to 0.0.0.0, then the client lives on one of the same networks as the BOOTP server ๐Ÿ . The server SHOULD examine the newly-defined BROADCAST flag (see Sections 2.2, 3.1.1 and 4.1.2 for more information). If this flag is set to 1, or the server has prior knowledge that the client is unable to receive unicast BOOTREPLY messages, the reply SHOULD be sent as an IP broadcast using the IP limited broadcast address 255.255.255.255 as the IP destination address and the link-layer broadcast address as the link-layer destination address. If the BROADCAST flag is cleared (0), the reply SHOULD be sent as an IP unicast to the IP address specified by the 'yiaddr' field and the link-layer address specified in the 'chaddr' field. If unicasting is not possible, the reply MAY be sent as a broadcast, in which case it SHOULD be sent to the link-layer broadcast address using the IP limited broadcast address 255.255.255.255 as the IP destination address. In any case, the UDP destination port MUST be set to BOOTPC (68) ๐Ÿ’….

Discussion:

Adding the BROADCAST flag was a little workaround ๐Ÿ› ๏ธ to help promote interoperability with certain client implementations ๐Ÿค. Here's the cheat sheet for how the server picks delivery based on what's in the BOOTREQUEST ๐Ÿ“‹:

   BOOTREQUEST fields     BOOTREPLY values for UDP, IP, link-layer
+-----------------------+-----------------------------------------+
| 'ciaddr'  'giaddr'  B | UDP dest     IP destination   link dest |
+-----------------------+-----------------------------------------+
| non-zero     X      X | BOOTPC (68)  'ciaddr'         normal    |
| 0.0.0.0   non-zero  X | BOOTPS (67)  'giaddr'         normal    |
| 0.0.0.0   0.0.0.0   0 | BOOTPC (68)  'yiaddr'         'chaddr'  |
| 0.0.0.0   0.0.0.0   1 | BOOTPC (68)  255.255.255.255  broadcast |
+-----------------------+-----------------------------------------+
     B = BROADCAST flag

     X = Don't care

normal = determine from the given IP destination using normal
         IP routing mechanisms and/or ARP as for any other
         normal datagram

Acknowledgements ๐Ÿซถ

Huge thanks to Gary Malkin for his contribution of the "BOOTP over IEEE 802.5 Token Ring Networks" section, and to Steve Deering for his observations on the problems associated with the 'giaddr' field ๐Ÿ™Œ.

Ralph Droms and the many members of the IETF Dynamic Host Configuration and Router Requirements working groups provided ideas for this memo, as well as encouragement to write it ๐Ÿ’œ.

Philip Almquist and David Piscitello offered many helpful suggestions for improving the clarity, accuracy, and organization of this memo. These contributions are graciously acknowledged ๐ŸŒธ.

References ๐Ÿ“š

[1] Croft, B., and J. Gilmore, "Bootstrap Protocol (BOOTP)", RFC 951, Stanford University and Sun Microsystems, September 1985.

[2] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497, USC/Information Sciences Institute, August 1993. This RFC is occasionally reissued with a new number. Please be sure to consult the latest version.

[3] Droms, R., "Dynamic Host Configuration Protocol", RFC 1541, Bucknell University, October 1993.

[4] Plummer, D., "An Ethernet Address Resolution Protocol", STD 37, RFC 826, MIT, November 1982.

[5] Deering, S., "ICMP Router Discovery Messages", RFC 1256, Xerox PARC, September 1991.

[6] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1340, USC/Information Sciences Institute, July, 1992. This RFC is periodically reissued with a new number. Please be sure to consult the latest version.

Security Considerations ๐Ÿ”

Okay, this is the scary part ๐Ÿ˜ฌ. BOOTP in its current form is quite insecure, for a bunch of reasons. It's built directly upon UDP and IP, which are as yet inherently insecure themselves. Furthermore, BOOTP is generally intended to make maintenance of remote and/or diskless hosts easier. While perhaps not impossible, configuring such hosts with passwords or keys may be difficult and inconvenient. So it's hard to provide any form of reasonable authentication between servers and clients ๐Ÿฅบ.

Unauthorized BOOTP servers are super easy to set up ๐Ÿ’€. They can then send false and potentially disruptive information to clients, like incorrect or duplicate IP addresses, incorrect routing information (including spoof routers, etc.), incorrect domain nameserver addresses (such as spoof nameservers), and so on. Clearly, once this "seed" mis-information is planted, an attacker can further compromise the affected systems ๐Ÿšจ.

Unauthorized BOOTP relay agents may present some of the same problems as unauthorized BOOTP servers ๐Ÿ™….

Malicious BOOTP clients could masquerade as legitimate clients and retrieve information intended for those legitimate clients ๐ŸŽญ. Where dynamic allocation of resources is used, a malicious client could claim all resources for itself, thereby denying resources to legitimate clients ๐Ÿ‘ฟ.

Author's Address ๐Ÿ–‹๏ธ

   Walt Wimer
   Network Development
   Carnegie Mellon University
   5000 Forbes Avenue
   Pittsburgh, PA  15213-3890

   Phone: (412) 268-6252
   EMail:  Walter.Wimer@CMU.EDU
๐Ÿ“ฆ where this page comes from