Correct precedence for determining src ip of DHCP packet
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 23 Sep 2015 20:18:59 +0000 (16:18 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 23 Sep 2015 20:20:45 +0000 (16:20 -0400)
src/modules/proto_dhcp/dhcpd.c

index a74346b..9c8085d 100644 (file)
@@ -449,22 +449,35 @@ static int dhcp_process(REQUEST *request)
         */
        request->reply->dst_ipaddr.af = AF_INET;
        request->reply->src_ipaddr.af = AF_INET;
-       request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = sock->src_ipaddr.ipaddr.ip4addr.s_addr;
        request->reply->src_ipaddr.prefix = 32;
 
        /*
-        *      They didn't set a proper src_ipaddr, but we want to
-        *      send the packet with a source IP.  If there's a server
-        *      identifier, use it.
+        *      Packet-Src-IP-Address has highest precedence
         */
-       if (request->reply->src_ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY) {
-               vp = fr_pair_find_by_num(request->reply->vps, PW_PACKET_SRC_IP_ADDRESS, 0, TAG_ANY);
-               if (!vp) vp = fr_pair_find_by_num(request->reply->vps, 54, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-DHCP-Server-Identifier */
-               if (vp) {
-                       request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
-               }
+       vp = fr_pair_find_by_num(request->reply->vps, PW_PACKET_SRC_IP_ADDRESS, 0, TAG_ANY);
+       if (vp) {
+               request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+       /*
+        *      The request was unicast (via a relay)
+        */
+       } else if (request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_BROADCAST)) {
+               request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
+       /*
+        *      The listener was bound to an IP address, or we determined
+        *      the address automatically, as it was the only address bound
+        *      to the interface, and we bound to the interface.
+        */
+       } else if (sock->src_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_ANY)) {
+               request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = sock->src_ipaddr.ipaddr.ip4addr.s_addr;
+       /*
+        *      There's a Server-Identification attribute
+        */
+       } else if ((vp = fr_pair_find_by_num(request->reply->vps, 54, DHCP_MAGIC_VENDOR, TAG_ANY))) {
+               request->reply->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+       } else {
+               REDEBUG("Unable to determine correct src_ipaddr for response");
+               return -1;
        }
-
        request->reply->dst_port = request->packet->src_port;
        request->reply->src_port = request->packet->dst_port;