ipaddr = 255.255.255.255
port = ${..port}
interface = ${..interface}
- interface_ipaddr = ${..ipaddr}
+
+ #
+ # When running as a DHCP relay, or sending unicast
+ # responses, this IP address is used as the source
+ # IP. If unset, the value is taken from the "ipaddr"
+ # field in this section. Since this might be
+ # broadcast, it can be wrong.
+ #
+ # This example uses the "ipaddr = 127.0.0.1" line above.
+ # It doesn't use the "ipaddr = 255.255.255.255" in this
+ # section.
+ #
+ src_ipaddr = ${..ipaddr}
}
# Listen for unicasts on an IP, but not bound to any interface.
# when the IP is associated with interface Y.
#
# Then, define which interface the packets go out of, via
- # "arp_interface". This means that the outbound packets
+ # "src_interface". This means that the outbound packets
# get sent via the correct interface.
listen {
type = dhcp
ipaddr = ${..ipaddr}
port = ${..port}
- arp_interface = ${..interface}
+
+ #
+ # When sending unicast responses, this interface is
+ # used as the source interface. If unset, the value
+ # is taken from the "interface" field in this
+ # section.
+ #
+ # This interface is also used when adding ARP entries.
+ # FreeRADIUS doesn't open "raw" network sockets to send
+ # unicast DHCP responses on the local network. Instead,
+ # it updates the ARP table for this interface with the
+ # MAX and IP of the DHCP client. The server can then
+ # send a normal UDP unicast socket.
+ #
+ src_interface = ${..interface}
}
# Packets received on the socket will be processed through one
*/
int suppress_responses;
RADCLIENT dhcp_client;
- const char *arp_interface;
- fr_ipaddr_t interface_ipaddr;
+ const char *src_interface;
+ fr_ipaddr_t src_ipaddr;
} dhcp_socket_t;
static int dhcprelay_process_client_request(REQUEST *request)
"no Client Hardware Address. Discarding packet");
return 1;
}
- if (fr_dhcp_add_arp_entry(request->packet->sockfd, sock->arp_interface, hwvp, vp) < 0) {
+ if (fr_dhcp_add_arp_entry(request->packet->sockfd, sock->src_interface, hwvp, vp) < 0) {
return -1;
}
}
*/
request->reply->dst_ipaddr.af = AF_INET;
request->reply->src_ipaddr.af = AF_INET;
- request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = sock->interface_ipaddr.ipaddr.ip4addr.s_addr;
+ request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = sock->src_ipaddr.ipaddr.ip4addr.s_addr;
request->reply->dst_port = request->packet->src_port;
request->reply->src_port = request->packet->dst_port;
if (request->reply->code == PW_DHCP_OFFER) {
VALUE_PAIR *hwvp = pairfind(request->reply->vps, DHCP2ATTR(267)); /* DHCP-Client-Hardware-Address */
rad_assert(hwvp != NULL);
- if (fr_dhcp_add_arp_entry(request->reply->sockfd, sock->arp_interface, hwvp, vp) < 0) {
+ if (fr_dhcp_add_arp_entry(request->reply->sockfd, sock->src_interface, hwvp, vp) < 0) {
return -1;
}
}
}
}
- cp = cf_pair_find(cs, "arp_interface");
+ cp = cf_pair_find(cs, "src_interface");
if (cp) {
const char *value;
value = cf_pair_value(cp);
- sock->arp_interface = value;
+ sock->src_interface = value;
} else {
- sock->arp_interface = sock->interface;
+ sock->src_interface = sock->interface;
}
- cp = cf_pair_find(cs, "interface_ipaddr");
+ cp = cf_pair_find(cs, "src_ipaddr");
if (cp) {
- memset(&sock->interface_ipaddr, 0, sizeof(sock->interface_ipaddr));
- sock->interface_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
- rcode = cf_item_parse(cs, "interface_ipaddr", PW_TYPE_IPADDR,
- &sock->interface_ipaddr.ipaddr.ip4addr, NULL);
+ memset(&sock->src_ipaddr, 0, sizeof(sock->src_ipaddr));
+ sock->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
+ rcode = cf_item_parse(cs, "src_ipaddr", PW_TYPE_IPADDR,
+ &sock->src_ipaddr.ipaddr.ip4addr, NULL);
if (rcode < 0) return -1;
- sock->interface_ipaddr.af = AF_INET;
+ sock->src_ipaddr.af = AF_INET;
} else {
- memcpy(&sock->interface_ipaddr, &sock->ipaddr, sizeof(sock->interface_ipaddr));
+ memcpy(&sock->src_ipaddr, &sock->ipaddr, sizeof(sock->src_ipaddr));
}
/*