# The DHCP relay agent: one server for many subnets

> A DHCP client that has no address yet broadcasts its request, and the server it needs is usually on another network. The relay agent receives that broadcast, marks it with the address of the subnet it came from, sends a new message to the server and carries the reply back. After reading you can follow both messages step by step, explain giaddr, the hops field, the BROADCAST flag and option 82, configure ip helper-address on Cisco IOS, and work through a remote subnet that gets no lease.

Source: https://ronutz.com/en/learn/dhcp-relay-agent  
Updated: 2026-10-13

---

A Dynamic Host Configuration Protocol (DHCP) 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](https://www.rfc-editor.org/rfc/rfc951#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](https://www.rfc-editor.org/rfc/rfc1542#section-4)). That agent is the **relay agent**, inherited from the Bootstrap Protocol (BOOTP) with the message format of [the previous part](https://ronutz.com/en/learn/bootp-and-dhcp-options). One request, followed through the router and back, shows what the relay writes, how the server picks a pool, what option 82 adds, how Cisco IOS 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](https://www.rfc-editor.org/rfc/rfc2131#section-4.1)). RFC 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](https://www.rfc-editor.org/rfc/rfc2131#section-1)) and uses "the same relay agent behavior as specified in the BOOTP protocol specification" ([RFC 2131, section 1.5](https://www.rfc-editor.org/rfc/rfc2131#section-1.5)); RFC 1542 applies to DHCP by its own terms ([RFC 1542, section 1](https://www.rfc-editor.org/rfc/rfc1542#section-1)).

RFC 951 had called the function a "BOOTP forwarding agent" ([RFC 951, section 8](https://www.rfc-editor.org/rfc/rfc951#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](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc1542#section-4.1)). And "Relaying MUST be disabled by default" ([RFC 1542, section 4.1.1](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc2131#section-2)), and the two-octet 'flags' field, whose most significant bit is the BROADCAST (B) flag ([RFC 1542, section 2.2](https://www.rfc-editor.org/rfc/rfc1542#section-2.2)). The rules are in [RFC 1542, section 4.1.1](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc3993#section-1)), as does Cisco: "The helper address must specify the address of the BOOTP or DHCP server." ([Cisco, ip helper-address](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipapp/command/iap-cr-book/iap-i1.html))

## 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](https://www.rfc-editor.org/rfc/rfc2131#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](https://www.rfc-editor.org/rfc/rfc1542#section-5.4)). RFC 1542's own table, X standing for any value (same section):

| 'ciaddr' | 'giaddr' | B flag | UDP destination | IP destination | Link-layer destination |
|---|---|---|---|---|---|
| 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 |

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](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc2131#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](https://www.rfc-editor.org/rfc/rfc1542#section-3.4)). The client's [default gateway](https://ronutz.com/en/learn/routing-tables-and-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](https://www.rfc-editor.org/rfc/rfc2131#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](https://ronutz.com/en/learn/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](https://ronutz.com/en/learn/dhcp-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](https://www.rfc-editor.org/rfc/rfc2131#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](https://www.rfc-editor.org/rfc/rfc2131#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 DHCP relay agent 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](https://www.rfc-editor.org/rfc/rfc3046)).

**Option 82** is "a "container" option for specific agent-supplied sub-options" ([RFC 3046, section 2.0](https://www.rfc-editor.org/rfc/rfc3046#section-2)):

| Field | Size | Meaning |
|---|---|---|
| Code | 1 octet | 82, "Relay Agent Information" ([IANA](https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml)) |
| Len | 1 octet | N, the bytes of all sub-option tuples; the minimum is "two (2)" |
| Agent Information Field | N octets | Sub-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 (MTU) of the outgoing interface ([RFC 3046, section 2.1](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc3046#section-2.1.1)).

The Internet Assigned Numbers Authority (IANA) assigns the codes under "IETF Review" (RFC 3046 had written "IETF Consensus", [section 6.0](https://www.rfc-editor.org/rfc/rfc3046#section-6)). The registry, last updated 2026-02-02, lists ([IANA, DHCP Relay Agent Sub-Option Codes](https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml)):

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

RFC 3046 is a Proposed Standard updated by RFC 6607, the source of codes 151 and 152 ([RFC 3046 information page](https://www.rfc-editor.org/info/rfc3046)).

## 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](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipapp/command/iap-cr-book/iap-i1.html)) 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](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipapp/command/iap-cr-book/iap-i1.html)), listed as:

| Service | UDP port |
|---|---|
| Trivial File Transfer Protocol (TFTP) | 69 |
| Domain Naming System | 53 |
| Time service | 37 |
| NetBIOS Name Server | 137 |
| NetBIOS Datagram Server | 138 |
| Boot Protocol (BOOTP) client and server packets | 67 and 68 |
| TACACS service | 49 |
| IEN-116 Name Service | 42 |

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](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_dhcp/configuration/15-mt/dhcp-15-mt-book/config-dhcp-relay-agent.html)). The global commands, with per-interface forms that take precedence:

| Command | What it does | Default |
|---|---|---|
| `ip dhcp relay information option` | Inserts option 82 into forwarded requests | Disabled |
| `ip dhcp relay information check` | Checks the option in forwarded replies; an invalid reply is dropped | Enabled |
| `ip dhcp relay information policy` (`drop`, `keep` or `replace`) | Handles relay information already present in a message from another relay | Replace |
| `ip dhcp relay information trust-all` (global) or `trusted` (interface) | Accepts a packet with giaddr zero that already carries option 82 | Discard |

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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc3046#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](https://www.rfc-editor.org/rfc/rfc2131#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](https://www.rfc-editor.org/rfc/rfc1542#section-5.4)); the relay drops a reply whose 'giaddr' is not its own ([RFC 1542, section 4.1.2](https://www.rfc-editor.org/rfc/rfc1542#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](https://www.rfc-editor.org/rfc/rfc2131#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

- [RFC 951, BOOTSTRAP PROTOCOL (BOOTP), September 1985: sections 3 and 8 (read 2026-10-13)](https://www.rfc-editor.org/rfc/rfc951)
- [RFC 1542, Clarifications and Extensions for the Bootstrap Protocol, October 1993: sections 1, 2.2, 3.1.1, 3.4, 4, 4.1, 4.1.1, 4.1.2 and 5.4 (read 2026-10-13)](https://www.rfc-editor.org/rfc/rfc1542)
- [RFC 2131, Dynamic Host Configuration Protocol, March 1997: sections 1, 1.5, 2 (Table 1), 3.1, 4.1, 4.3.1 and 4.3.2 (read 2026-10-13)](https://www.rfc-editor.org/rfc/rfc2131)
- [RFC 3046, DHCP Relay Agent Information Option, January 2001: Abstract and sections 2.0, 2.1, 2.1.1, 2.2, 3.1, 3.2 and 6.0 (read 2026-10-13)](https://www.rfc-editor.org/rfc/rfc3046)
- [RFC 3046 information page at the RFC Editor: status and Updated by (read 2026-10-13)](https://www.rfc-editor.org/info/rfc3046)
- [RFC 3993, Subscriber-ID Suboption for the Dynamic Host Configuration Protocol (DHCP) Relay Agent Option, March 2005: section 1 (read 2026-10-13)](https://www.rfc-editor.org/rfc/rfc3993)
- [IANA, Dynamic Host Configuration Protocol (DHCP) and Bootstrap Protocol (BOOTP) Parameters: option 82 row and sub-registry DHCP Relay Agent Sub-Option Codes, last updated 2026-02-02 (read 2026-10-13)](https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml)
- [Cisco, IP Addressing: DHCP Configuration Guide, Cisco IOS Release 15M&T, chapter Configuring the Cisco IOS DHCP Relay Agent, updated December 3, 2012 (read 2026-10-13)](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_dhcp/configuration/15-mt/dhcp-15-mt-book/config-dhcp-relay-agent.html)
- [Cisco, Cisco IOS IP Application Services Command Reference, entries ip forward-protocol and ip helper-address, updated July 19, 2011 (read 2026-10-13)](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipapp/command/iap-cr-book/iap-i1.html)
