]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fixed DHCP relay when residing on a gateway on Linux
authorRenaud Métrich <renaud.metrich@mancalanetworks.com>
Wed, 23 Nov 2011 15:17:26 +0000 (16:17 +0100)
committerRenaud Métrich <renaud.metrich@mancalanetworks.com>
Wed, 23 Nov 2011 15:17:26 +0000 (16:17 +0100)
Updated template to reflect the changes

raddb/sites-available/dhcp.relay
src/main/dhcpd.c

index 737cc5d5d69096c44efac181f93d8a4475c869a0..c78b15d85faf9e895a5d127639fd57d9597a1b01 100644 (file)
@@ -9,12 +9,33 @@
 ######################################################################
 
 server dhcp.eth1 {
+       # When the machine is not Linux, or has only one network interface, use
+       # the following listener:
        listen {
+               # Listen for broadcasts + unicast on eth1
                ipaddr = *
                port = 67
                type = dhcp
                interface = eth1
        }
+       # When the machine is Linux and has multiple network interfaces, use
+       # the following listeners instead:
+       listen {
+               # Listen for broadcasts on eth1
+               ipaddr = 255.255.255.255
+               port = 67
+               type = dhcp
+               interface = eth1
+       }
+       listen {
+               # Listen for unicast on our IP address, not bound to any
+               # interface but telling on which interface to forward the
+               # packets to.
+               ipaddr = 192.0.100.2
+               port = 67
+               type = dhcp
+               arp_interface = eth1
+       }
 
        #  Packets received on the socket will be processed through one
        #  of the following sections, named after the DHCP packet type.
@@ -22,11 +43,11 @@ server dhcp.eth1 {
        dhcp DHCP-Discover {
                update config {
                        # IP Address of the DHCP server
-                       DHCP-Relay-To-IP-Address := 192.0.2.2
+                       DHCP-Relay-To-IP-Address := 192.0.1.2
                }
                update request {
-                       # IP Address of the DHCP relay (ourselves)
-                       DHCP-Gateway-IP-Address := 192.0.2.1
+                       # IP Address of the DHCP relay (eth1)
+                       DHCP-Gateway-IP-Address := 192.0.100.2
                }
                ok
        }
@@ -34,10 +55,10 @@ server dhcp.eth1 {
        dhcp DHCP-Request {
                update config {
                        # IP Address of the DHCP server
-                       DHCP-Relay-To-IP-Address := 192.0.2.2
+                       DHCP-Relay-To-IP-Address := 192.0.1.2
                }
                update request {
-                       DHCP-Gateway-IP-Address := 192.0.2.2
+                       DHCP-Gateway-IP-Address := 192.0.100.2
                }
                ok
        }
index f7d42fa143808453f11b9f5abc5cd9fe04dc2e97..9042712aab3f678711cd74b92b8473e95d9ba419 100644 (file)
@@ -63,12 +63,13 @@ typedef struct dhcp_socket_t {
         */
        int             suppress_responses;
        RADCLIENT       dhcp_client;
+       const char      *arp_interface;
 } dhcp_socket_t;
 
 static int dhcprelay_process_client_request(REQUEST *request)
 {
        uint8_t maxhops = 16;
-       VALUE_PAIR *vp;
+       VALUE_PAIR *vp, *giaddrvp;
        dhcp_socket_t *sock;
 
        rad_assert(request->packet->data[0] == 1);
@@ -81,7 +82,7 @@ static int dhcprelay_process_client_request(REQUEST *request)
        /*
         * It's invalid to have giaddr=0 AND a relay option
         */
-       vp = pairfind(request->packet->vps, DHCP2ATTR(266)); /* DHCP-Gateway-IP-Address */
+       giaddrvp = vp = pairfind(request->packet->vps, DHCP2ATTR(266)); /* DHCP-Gateway-IP-Address */
        if ((vp && (vp->vp_ipaddr == htonl(INADDR_ANY))) &&
            pairfind(request->packet->vps, DHCP2ATTR(82))) { /* DHCP-Relay-Agent-Information */
                DEBUG("DHCP: Received packet with giaddr = 0 and containing relay option: Discarding packet\n");
@@ -114,8 +115,7 @@ static int dhcprelay_process_client_request(REQUEST *request)
         */
        /* set SRC ipaddr/port to the listener ipaddr/port */
        request->packet->src_ipaddr.af = AF_INET;
-       /* XXX sock->ipaddr == 0 (listening on '*') */
-       request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = sock->ipaddr.ipaddr.ip4addr.s_addr;
+       request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = giaddrvp->vp_ipaddr;
        request->packet->src_port = sock->port;
 
        vp = pairfind(request->config_items, DHCP2ATTR(270)); /* DHCP-Relay-To-IP-Address */
@@ -136,7 +136,7 @@ static int dhcprelay_process_client_request(REQUEST *request)
 
 static int dhcprelay_process_server_reply(REQUEST *request)
 {
-       VALUE_PAIR *vp;
+       VALUE_PAIR *vp, *giaddrvp;
        dhcp_socket_t *sock;
 
        rad_assert(request->packet->data[0] == 2);
@@ -151,7 +151,7 @@ static int dhcprelay_process_server_reply(REQUEST *request)
        /*
         * Check that packet is for us.
         */
-       vp = pairfind(request->packet->vps, DHCP2ATTR(266)); /* DHCP-Gateway-IP-Address */
+       giaddrvp = vp = pairfind(request->packet->vps, DHCP2ATTR(266)); /* DHCP-Gateway-IP-Address */
        rad_assert(vp != NULL);
 
 #ifndef WITH_UDPFROMTO
@@ -166,8 +166,7 @@ static int dhcprelay_process_server_reply(REQUEST *request)
 
        /* set SRC ipaddr/port to the listener ipaddr/port */
        request->packet->src_ipaddr.af = AF_INET;
-       /* XXX sock->ipaddr == 0 (listening on '*') */
-       request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = sock->ipaddr.ipaddr.ip4addr.s_addr;
+       request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = giaddrvp->vp_ipaddr;
        request->packet->src_port = sock->port;
 
        /* set DEST ipaddr/port to clientip/68 or broadcast in specific cases */
@@ -217,7 +216,9 @@ static int dhcprelay_process_server_reply(REQUEST *request)
                                            "no Client Hardware Address. Discarding packet");
                                        return 1;
                                }
-                               if (fr_dhcp_add_arp_entry(request->packet->sockfd, sock->interface, hwvp, vp) < 0) {
+                               if (sock->arp_interface == NULL)
+                                       sock->arp_interface = sock->interface;
+                               if (fr_dhcp_add_arp_entry(request->packet->sockfd, sock->arp_interface, hwvp, vp) < 0) {
                                        return -1;
                                }
                        }
@@ -330,6 +331,7 @@ static int dhcp_process(REQUEST *request)
 
        /* else it's a packet from a client, without relaying */
        rad_assert(vp->vp_integer == 1); /* BOOTREQUEST */
+
        sock = request->listener->data;
 
        /*
@@ -420,7 +422,9 @@ static int dhcp_process(REQUEST *request)
                        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->interface, hwvp, vp) < 0) {
+                               if (sock->arp_interface == NULL)
+                                       sock->arp_interface = sock->interface;
+                               if (fr_dhcp_add_arp_entry(request->reply->sockfd, sock->arp_interface, hwvp, vp) < 0) {
                                        return -1;
                                }
                        }
@@ -486,6 +490,13 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
                }
        }
 
+       cp = cf_pair_find(cs, "arp_interface");
+       if (cp) {
+               const char *value;
+               value = cf_pair_value(cp);
+               sock->arp_interface = value;
+       }
+
        /*
         *      Initialize the fake client.
         */