Notes on binding to interfaces for DHCP
authorAlan T. DeKok <aland@freeradius.org>
Sun, 1 Aug 2010 07:29:59 +0000 (09:29 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 2 Aug 2010 13:31:13 +0000 (15:31 +0200)
raddb/sites-available/dhcp
src/main/dhcpd.c

index ea1bd83..e1b9420 100644 (file)
@@ -73,13 +73,27 @@ server dhcp {
 #  multiple interfaces, each with a separate policy.
 #
 #  If you have multiple interfaces, it is a good idea to bind the
-#  listen section to an interface.  You will likely also need one
-#  listen section per interface.
+#  listen section to an interface.  You will also need one listen
+#  section per interface.
+#
+#  FreeBSD does *not* support binding sockets to interfaces.  Therefore,
+#  if you have multiple interfaces, broadcasts may go out of the wrong
+#  one, or even all interfaces.  The only solution is to update FreeRADIUS
+#  to use BPF sockets.
+#
 listen {
-       ipaddr = *
+       ipaddr = 127.0.0.1
        port = 6700
        type = dhcp
-       #interface = eth0
+#      interface = lo0
+
+       # The DHCP server defaults to allowing broadcast packets.
+       # Set this to "no" only when the server receives *all* packets
+       # from a relay agent.  i.e. when *no* clients are on the same
+       # LAN as the DHCP server.
+       #
+       # It's set to "no" here for testing.
+       broadcast = no
 }
 
 #  Packets received on the socket will be processed through one
index 17064a1..d9d9f40 100644 (file)
@@ -169,7 +169,7 @@ static int dhcp_process(REQUEST *request)
 
 static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
 {
-       int rcode;
+       int rcode, broadcast = 1;
        int on = 1;
        dhcp_socket_t *sock;
        RADCLIENT *client;
@@ -183,6 +183,31 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        sock = this->data;
 
        /*
+        *      See whether or not we enable broadcast packets.
+        */
+       cp = cf_pair_find(cs, "broadcast");
+       if (cp) {
+               const char *value = cf_pair_value(cp);
+               if (value && (strcmp(value, "no") == 0)) {
+                       broadcast = 0;
+               }
+       }
+
+       if (broadcast) {
+               if (setsockopt(this->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
+                       radlog(L_ERR, "Can't set broadcast option: %s\n",
+                              strerror(errno));
+                       return -1;
+               }
+       }
+
+       if (setsockopt(this->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+               radlog(L_ERR, "Can't set re-use addres option: %s\n",
+                      strerror(errno));
+               return -1;
+       }
+
+       /*
         *      Undocumented extension for testing without
         *      destroying your network!
         */