A Dynamic Host Configuration Protocol () client with no Internet Protocol (IP) address yet sends its request to 255.255.255.255, which "means 'broadcast on the local cable, (I don't know my net number)'" (RFC 951, section 3). Its server is often elsewhere: "In many cases, BOOTP clients and their associated BOOTP server(s) do not reside on the same IP network or subnet. In such cases, some kind of third-party agent is required to transfer BOOTP messages between clients and servers" (RFC 1542, section 4). That agent is the relay agent, inherited from the Bootstrap Protocol (BOOTP) with the message format of the previous part. One request, followed through the router and back, shows what the relay writes, how the server picks a pool, what option 82 adds, how switches it on, and what to check when a remote subnet gets no address.

Why a relay exists, and why it is not a forwarder

Before it has an address the client cannot even name itself: its broadcast carries an IP source of 0 (RFC 2131, section 4.1). 1542 does not put the problem as "routers do not forward broadcasts"; it states it as a matter of where the two ends sit, in the sentence quoted above. RFC 2131 kept the design because "Using BOOTP relay agents eliminates the necessity of having a DHCP server on each physical network segment" (RFC 2131, section 1) and uses "the same relay agent behavior as specified in the BOOTP protocol specification" (RFC 2131, section 1.5); RFC 1542 applies to DHCP by its own terms (RFC 1542, section 1).

RFC 951 had called the function a "BOOTP forwarding agent" (RFC 951, section 8). RFC 1542 renamed it to avoid confusion with IP forwarding and drew the line: "a BOOTP relay agent may more properly be thought to receive BOOTP messages as a final destination and then generate new BOOTP messages as a result. It is incorrect for a relay agent implementation to simply forward a BOOTP message "straight through like a regular packet."" (RFC 1542, section 4). The intake is a User Datagram Protocol (UDP) port: locally delivered datagrams, broadcasts included, addressed to BOOTPS (67); messages to BOOTPC (68) are silently discarded (RFC 1542, section 4.1). And "Relaying MUST be disabled by default" (RFC 1542, section 4.1.1).

The request on its way to the server

Three header fields carry the work: 'hops' (one octet), 'giaddr' (four octets, the "Relay agent IP address, used in booting via a relay agent") (RFC 2131, Table 1), and the two-octet 'flags' field, whose most significant bit is the BROADCAST (B) flag (RFC 1542, section 2.2). The rules are in RFC 1542, section 4.1.1 unless another source is named.

  1. Hops. "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 desired by the network manager. The default setting for a configurable threshold SHOULD be 4." The familiar "limit of 4" is the default; the hard rule is 16.
  2. giaddr. "If this field is zero, the relay agent MUST fill this field with the IP address of the interface on which the request was received." A non-zero value is left alone, and a broadcast address is forbidden. Then "The value of the 'hops' field MUST be incremented." and "All other BOOTP fields MUST be preserved intact."
  3. Destination. "This destination MUST be configurable": unicast, multicast, broadcast or a mix, never back out of the arrival interface, and always the same for a given client, because varying it "reacts badly with DHCP". RFC 1542 never says the relay unicasts to the server; RFC 3993 does (section 1), as does Cisco: "The helper address must specify the address of the BOOTP or DHCP server." (Cisco, ip helper-address)

The reply on its way back

The server answers the relay, not the client: "If the 'giaddr' field in a DHCP message from a client is non-zero, the server sends any return messages to the 'DHCP server' port on the BOOTP relay agent whose address appears in 'giaddr'" (RFC 2131, section 4.1). That unicast to port 67 reaches "the BOOTP relay agent closest to the client", which performs the final delivery (RFC 1542, section 5.4). RFC 1542's own table, X standing for any value (same section):

'ciaddr''giaddr'B flagUDP destinationIP destinationLink-layer destination
non-zeroXXBOOTPC (68)'ciaddr'normal
0.0.0.0non-zeroXBOOTPS (67)'giaddr'normal
0.0.0.00.0.0.00BOOTPC (68)'yiaddr''chaddr'
0.0.0.00.0.0.01BOOTPC (68)255.255.255.255broadcast

The relay discards a reply whose 'giaddr' is not one of its own directly connected interfaces. The BROADCAST flag then decides the last hop: set, the reply is broadcast to 255.255.255.255 at the link-layer broadcast address; clear, it is unicast to 'yiaddr' at 'chaddr'; either way to BOOTPC (68), and the relay "MUST NOT modify any BOOTP field of the BOOTREPLY message" (RFC 1542, section 4.1.2). The flag is a workaround for clients that cannot receive unicast "until they know their own IP address", and its use "is discouraged" (RFC 1542, section 3.1.1); such a client sets it in its DHCPDISCOVER and DHCPREQUEST, and a DHCPNAK sent through a relay always carries it (RFC 2131, section 4.3.2).

"The 'giaddr' field is rather poorly named." RFC 1542 admits: "In no case does it represent a general IP router to be used by the client." Clients set it to zero in every request and never read a router address out of it (RFC 1542, section 3.4). The client's default gateway is not in this field; the "gateway" of the name is the router that relayed.

How the server chooses the pool

RFC 2131 orders the server's choice: the client's current binding, a previous one, the 'Requested IP Address' option, and finally "A new address allocated from the server's pool of available addresses; the address is selected based on the subnet from which the message was received (if 'giaddr' is 0) or on the address of the relay agent that forwarded the message ('giaddr' when not 0)" (RFC 2131, section 4.3.1). The relay's address on the receiving interface is what lets the server recognise the client's subnet (see IPv4 addressing), though for segments carrying several subnets "A server is free to choose some other subnet" (same section).

Not every message of the lease lifecycle passes through the relay. The DHCPREQUEST that accepts an offer is broadcast and relayed, reusing the DHCPDISCOVER's 'secs' value and broadcast address so that relays forward it "to the same set of DHCP servers that received the original DHCPDISCOVER message" (RFC 2131, section 3.1). The renewing DHCPREQUEST "will be unicast, so no relay agents will be involved in its transmission" (RFC 2131, section 4.3.2).

Option 82: what the relay knows and the client does not

RFC 3046 (January 2001) gives the relay a voice. Its option "is inserted by the when forwarding client-originated DHCP packets to a DHCP server", and the server "echoes the option back verbatim to the relay agent in server-to-client replies, and the relay agent strips the option before forwarding the reply to the client" (RFC 3046, Abstract).

Option 82 is "a "container" option for specific agent-supplied sub-options" (RFC 3046, section 2.0):

FieldSizeMeaning
Code1 octet82, "Relay Agent Information" (IANA)
Len1 octetN, the bytes of all sub-option tuples; the minimum is "two (2)"
Agent Information FieldN octetsSub-options, each a code, a length (the value's octets, possibly zero) and a value; no pad, no 255 terminator, any order

The relay adds it "as the last option (but before 'End Option' 255, if present)", never in 'sname' or 'file'; insertion SHOULD be configurable and "disabled by default"; and the packet SHALL NOT grow past the maximum transmission unit () of the outgoing interface (RFC 3046, section 2.1). The Circuit ID (code 1) is "an agent-local identifier of the circuit from which a DHCP client-to-server packet was received" (RFC 3046, section 3.1). The Remote ID (code 2) identifies "the remote host end of the circuit" and "MUST be globally unique" (RFC 3046, section 3.2).

A server that knows the option "SHALL echo the entire contents of the Relay Agent Information option in all replies"; one that does not ignores it (RFC 3046, section 2.2). On the way down it "MUST be removed by either the relay agent or the trusted downstream network element which added it" (RFC 3046, section 2.1). Trust decides the rest: a first-hop relay (giaddr zero) that receives a packet "from an untrusted circuit" with option 82 already present "SHALL discard the packet and increment an error count", while on a trusted circuit a downstream bridge may have added it and the relay "does NOT add a "second" relay agent option" (same section); a second relay, seeing a non-zero giaddr, forwards "WITHOUT adding any relay agent options" and leaves giaddr alone (RFC 3046, section 2.1.1).

The Internet Assigned Numbers Authority () assigns the codes under " Review" (RFC 3046 had written "IETF Consensus", section 6.0). The registry, last updated 2026-02-02, lists (IANA, DHCP Relay Agent Sub-Option Codes):

CodeSub-optionReference
1Agent Circuit ID Sub-optionRFC 3046
2Agent Remote ID Sub-optionRFC 3046
3Reserved ("proprietary and incompatible usages" seen)Ralph Droms
4 Device Class SuboptionRFC 3256
5Link selection Sub-optionRFC 3527
6Subscriber-ID SuboptionRFC 3993
7 (Remote Authentication Dial-In User Service) Attributes Sub-optionRFC 4014
8Authentication SuboptionRFC 4030
9-Specific Information SuboptionRFC 4243
10Relay Agent FlagsRFC 5010
11Server Identifier Override SuboptionRFC 5107
12Relay Agent Identifier Sub-optionRFC 6925
13 to 18Access-Technology-Type, Access-Network-Name, Access-Point-Name, Access-Point-, Operator-Identifier and Operator-Realm Sub-optionsRFC 7839
19DHCPv4 Relay Source Port Sub-OptionRFC 8357
20 to 150Unassigned
151DHCPv4 Virtual Subnet Selection Sub-OptionRFC 6607
152DHCPv4 Virtual Subnet Selection Control Sub-OptionRFC 6607

RFC 3046 is a Proposed Standard updated by RFC 6607, the source of codes 151 and 152 (RFC 3046 information page).

The relay on Cisco IOS

On Cisco IOS the switch is one interface command:

Router(config)# interface ethernet 1
Router(config-if)# ip helper-address 10.24.43.2

Its default is "UDP broadcasts are not forwarded." "The helper address must specify the address of the BOOTP or DHCP server", and "The service dhcp command must be configured on the router to enable IP helper statements to work with DHCP." (Cisco, ip helper-address) Relaying therefore stays off until an interface has a helper address, as RFC 1542 requires. "If an IP helper address is defined, UDP forwarding is enabled on default ports" (Cisco, ip forward-protocol), listed as:

ServiceUDP port
Trivial File Transfer Protocol ()69
Domain Naming System53
Time service37
NetBIOS Name Server137
NetBIOS Datagram Server138
Boot Protocol (BOOTP) client and server packets67 and 68
TACACS service49
IEN-116 Name Service42

The BOOTP row needs the same entry's footnote: "If UDP port 68 is used as the destination port number, it is not forwarded by default." That is what RFC 1542 requires.

For option 82 the relay "will automatically add the circuit identifier suboption and the remote ID suboption" and strips them "while forwarding the packet to the client" (Cisco, Configuring the Cisco IOS DHCP Relay Agent). The global commands, with per-interface forms that take precedence:

CommandWhat it doesDefault
ip dhcp relay information optionInserts option 82 into forwarded requestsDisabled
ip dhcp relay information checkChecks the option in forwarded replies; an invalid reply is droppedEnabled
ip dhcp relay information policy (drop, keep or replace)Handles relay information already present in a message from another relayReplace
ip dhcp relay information trust-all (global) or trusted (interface)Accepts a packet with giaddr zero that already carries option 82Discard

The policy default is where Cisco and RFC 3046 part: "By default, the relay information from the previous relay agent is replaced." (Cisco, same guide), where RFC 3046 forwards "WITHOUT adding any relay agent options" (RFC 3046, section 2.1.1); keep is the RFC behaviour, and both leave giaddr untouched. The trust commands cover RFC 3046's downstream bridge: trust-all "is useful if there is a switch placed between the client and the relay agent that may insert option 82" (Cisco, same guide).

When a client on a remote subnet gets no address

Work along the path in the order the messages travel.

  1. Is the relay on, on the right interface? Relaying is off by default (RFC 1542, section 4.1.1); on Cisco IOS, ip helper-address must name the server on the interface the client's broadcast arrives on, with service dhcp not removed.
  2. Does the request survive the relay's checks? 'hops' above the threshold (default 4, hard limit 16) means a silent discard; option 82 already present with 'giaddr' zero means a discard on an untrusted circuit (RFC 3046, section 2.1), Cisco's default without trust-all or trusted.
  3. Does the server have a pool for 'giaddr'? The pool follows the relay's address (RFC 2131, section 4.3.1), which is the receiving interface's.
  4. Does the reply reach, and pass, the relay? The server unicasts to 'giaddr' on UDP port 67 (RFC 1542, section 5.4); the relay drops a reply whose 'giaddr' is not its own (RFC 1542, section 4.1.2) or, with the default ip dhcp relay information check, whose option 82 is invalid.
  5. Can the client receive the last hop? Unicast to 'yiaddr' at 'chaddr' unless the BROADCAST flag is set; a client that cannot receive unicast before it is configured must set the flag itself (RFC 2131, section 4.1).

What to remember

  • A relay agent receives a BOOTREQUEST "as a final destination" and generates a new message; it is not IP forwarding, which is why RFC 1542 renamed it.
  • The relay writes the receiving interface's address into giaddr, increments hops and sends the request to a configured destination, in practice the server's unicast address.
  • The server answers the relay at giaddr on UDP port 67 and picks the pool from giaddr; the relay delivers on port 68, by broadcast when the BROADCAST flag is set.
  • A request is discarded above 16 hops (MUST) or above a configurable threshold whose default is 4; "the limit is 4" names the default, not the hard rule.
  • giaddr is "rather poorly named": it is never the client's router, and clients set it to zero.
  • Option 82 is inserted by the relay, echoed verbatim by the server and removed before the client sees it; a first-hop relay drops a request that already carries it on an untrusted circuit.
  • On Cisco IOS nothing is relayed until ip helper-address is set on the interface, port 68 is not forwarded by default, and the option 82 policy default (replace) departs from RFC 3046.

Sources