these attributes are byte, not integer. Closes #1954
[freeradius.git] / src / modules / proto_dhcp / dhcpd.c
index 861718a..218198c 100644 (file)
@@ -56,8 +56,6 @@
 #include <sys/ioctl.h>
 #endif
 
-extern bool check_config;      /* @todo globals are bad, m'kay? */
-
 /*
  *     Same contents as listen_socket_t.
  */
@@ -90,9 +88,9 @@ static int dhcprelay_process_client_request(REQUEST *request)
        /*
         * It's invalid to have giaddr=0 AND a relay option
         */
-       giaddr = pairfind(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
+       giaddr = fr_pair_find_by_num(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
        if (giaddr && (giaddr->vp_ipaddr == htonl(INADDR_ANY)) &&
-           pairfind(request->packet->vps, 82, DHCP_MAGIC_VENDOR, TAG_ANY)) { /* DHCP-Relay-Agent-Information */
+           fr_pair_find_by_num(request->packet->vps, 82, DHCP_MAGIC_VENDOR, TAG_ANY)) { /* DHCP-Relay-Agent-Information */
                DEBUG("DHCP: Received packet with giaddr = 0 and containing relay option: Discarding packet\n");
                return 1;
        }
@@ -102,17 +100,17 @@ static int dhcprelay_process_client_request(REQUEST *request)
         *
         * Drop requests if hop-count > 16 or admin specified another value
         */
-       if ((vp = pairfind(request->config_items, 271, DHCP_MAGIC_VENDOR, TAG_ANY))) { /* DHCP-Relay-Max-Hop-Count */
+       if ((vp = fr_pair_find_by_num(request->config, 271, DHCP_MAGIC_VENDOR, TAG_ANY))) { /* DHCP-Relay-Max-Hop-Count */
            maxhops = vp->vp_integer;
        }
-       vp = pairfind(request->packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Hop-Count */
+       vp = fr_pair_find_by_num(request->packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Hop-Count */
        rad_assert(vp != NULL);
-       if (vp->vp_integer > maxhops) {
+       if (vp->vp_byte > maxhops) {
                DEBUG("DHCP: Number of hops is greater than %d: not relaying\n", maxhops);
                return 1;
        } else {
-           /* Increment hop count */
-           vp->vp_integer++;
+               /* Increment hop count */
+               vp->vp_byte++;
        }
 
        sock = request->listener->data;
@@ -126,12 +124,13 @@ static int dhcprelay_process_client_request(REQUEST *request)
        request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = sock->lsock.my_ipaddr.ipaddr.ip4addr.s_addr;
        request->packet->src_port = sock->lsock.my_port;
 
-       vp = pairfind(request->config_items, 270, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-To-IP-Address */
+       vp = fr_pair_find_by_num(request->config, 270, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-To-IP-Address */
        rad_assert(vp != NULL);
 
        /* set DEST ipaddr/port to the next server ipaddr/port */
        request->packet->dst_ipaddr.af = AF_INET;
        request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+       request->packet->dst_port = sock->lsock.my_port;
 
        if (fr_dhcp_encode(request->packet) < 0) {
                DEBUG("dhcprelay_process_client_request: ERROR in fr_dhcp_encode\n");
@@ -163,7 +162,7 @@ static int dhcprelay_process_server_reply(REQUEST *request)
        /*
         * Check that packet is for us.
         */
-       giaddr = pairfind(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
+       giaddr = fr_pair_find_by_num(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
 
        /* --with-udpfromto is needed just for the following test */
        if (!giaddr || giaddr->vp_ipaddr != request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr) {
@@ -187,9 +186,9 @@ static int dhcprelay_process_server_reply(REQUEST *request)
 
        if ((request->packet->code == PW_DHCP_NAK) ||
            !sock->src_interface ||
-           ((vp = pairfind(request->packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Flags */ &&
+           ((vp = fr_pair_find_by_num(request->packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Flags */ &&
             (vp->vp_integer & 0x8000) &&
-            ((vp = pairfind(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ &&
+            ((vp = fr_pair_find_by_num(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ &&
              (vp->vp_ipaddr == htonl(INADDR_ANY))))) {
                /*
                 * RFC 2131, page 23
@@ -209,13 +208,13 @@ static int dhcprelay_process_server_reply(REQUEST *request)
                 * - ciaddr if present
                 * otherwise to yiaddr
                 */
-               if ((vp = pairfind(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ &&
+               if ((vp = fr_pair_find_by_num(request->packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) /* DHCP-Client-IP-Address */ &&
                    (vp->vp_ipaddr != htonl(INADDR_ANY))) {
                        request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
                } else {
-                       vp = pairfind(request->packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */
+                       vp = fr_pair_find_by_num(request->packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */
                        if (!vp) {
-                               DEBUG("DHCP: Failed to find IP Address for request.");
+                               DEBUG("DHCP: Failed to find IP Address for request");
                                return -1;
                        }
 
@@ -229,7 +228,7 @@ static int dhcprelay_process_server_reply(REQUEST *request)
                         * the client was requesting an IP address.
                         */
                        if (request->packet->code == PW_DHCP_OFFER) {
-                               VALUE_PAIR *hwvp = pairfind(request->packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */
+                               VALUE_PAIR *hwvp = fr_pair_find_by_num(request->packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */
                                if (hwvp == NULL) {
                                        DEBUG("DHCP: DHCP_OFFER packet received with "
                                            "no Client Hardware Address. Discarding packet");
@@ -253,13 +252,13 @@ static int dhcprelay_process_server_reply(REQUEST *request)
 #else  /* WITH_UDPFROMTO */
 static int dhcprelay_process_server_reply(UNUSED REQUEST *request)
 {
-       WDEBUG("DHCP Relaying requires the server to be configured with UDPFROMTO");
+       WARN("DHCP Relaying requires the server to be configured with UDPFROMTO");
        return -1;
 }
 
 static int dhcprelay_process_client_request(UNUSED REQUEST *request)
 {
-       WDEBUG("DHCP Relaying requires the server to be configured with UDPFROMTO");
+       WARN("DHCP Relaying requires the server to be configured with UDPFROMTO");
        return -1;
 }
 
@@ -290,30 +289,30 @@ static int dhcp_process(REQUEST *request)
         *      in the response.  That way the later code knows where
         *      to send the reply.
         */
-       vp = pairfind(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
+       vp = fr_pair_find_by_num(request->packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
        if (vp && (vp->vp_ipaddr != htonl(INADDR_ANY))) {
                VALUE_PAIR *relay;
 
                /* DHCP-Relay-IP-Address */
-               relay = radius_paircreate(request->reply, &request->reply->vps,
+               relay = radius_pair_create(request->reply, &request->reply->vps,
                                          272, DHCP_MAGIC_VENDOR);
                if (relay) relay->vp_ipaddr = vp->vp_ipaddr;
        }
 
-       vp = pairfind(request->packet->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
+       vp = fr_pair_find_by_num(request->packet->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
        if (vp) {
-               DICT_VALUE *dv = dict_valbyattr(53, DHCP_MAGIC_VENDOR, vp->vp_integer);
+               DICT_VALUE *dv = dict_valbyattr(53, DHCP_MAGIC_VENDOR, vp->vp_byte);
                DEBUG("Trying sub-section dhcp %s {...}",
-                     dv->name ? dv->name : "<unknown>");
-               rcode = process_post_auth(vp->vp_integer, request);
+                     dv ? dv->name : "<unknown>");
+               rcode = process_post_auth(vp->vp_byte, request);
        } else {
                DEBUG("DHCP: Failed to find DHCP-Message-Type in packet!");
                rcode = RLM_MODULE_FAIL;
        }
 
-       vp = pairfind(request->reply->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
+       vp = fr_pair_find_by_num(request->reply->vps, 53, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Message-Type */
        if (vp) {
-               request->reply->code = vp->vp_integer;
+               request->reply->code = vp->vp_byte;
                if ((request->reply->code != 0) &&
                    (request->reply->code < PW_DHCP_OFFSET)) {
                        request->reply->code += PW_DHCP_OFFSET;
@@ -360,24 +359,24 @@ static int dhcp_process(REQUEST *request)
        /*
         *      Handle requests when acting as a DHCP relay
         */
-       vp = pairfind(request->packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Opcode */
+       vp = fr_pair_find_by_num(request->packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Opcode */
        if (!vp) {
                RDEBUG("FAILURE: Someone deleted the DHCP-Opcode!");
                return 1;
        }
 
        /* BOOTREPLY received on port 67 (i.e. from a server) */
-       if (vp->vp_integer == 2) {
+       if (vp->vp_byte == 2) {
                return dhcprelay_process_server_reply(request);
        }
 
        /* Packet from client, and we have DHCP-Relay-To-IP-Address */
-       if (pairfind(request->config_items, 270, DHCP_MAGIC_VENDOR, TAG_ANY)) {
+       if (fr_pair_find_by_num(request->config, 270, DHCP_MAGIC_VENDOR, TAG_ANY)) {
                return dhcprelay_process_client_request(request);
        }
 
        /* else it's a packet from a client, without relaying */
-       rad_assert(vp->vp_integer == 1); /* BOOTREQUEST */
+       rad_assert(vp->vp_byte == 1); /* BOOTREQUEST */
 
        sock = request->listener->data;
 
@@ -405,28 +404,42 @@ static int dhcp_process(REQUEST *request)
        for (i = 0; i < sizeof(attrnums) / sizeof(attrnums[0]); i++) {
                uint32_t attr = attrnums[i];
 
-               if (pairfind(request->reply->vps, attr, DHCP_MAGIC_VENDOR, TAG_ANY)) continue;
+               if (fr_pair_find_by_num(request->reply->vps, attr, DHCP_MAGIC_VENDOR, TAG_ANY)) continue;
 
-               vp = pairfind(request->packet->vps, attr, DHCP_MAGIC_VENDOR, TAG_ANY);
+               vp = fr_pair_find_by_num(request->packet->vps, attr, DHCP_MAGIC_VENDOR, TAG_ANY);
                if (vp) {
-                       pairadd(&request->reply->vps, paircopyvp(request->reply, vp));
+                       fr_pair_add(&request->reply->vps, fr_pair_copy(request->reply, vp));
                }
        }
 
-       vp = pairfind(request->reply->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Opcode */
+       vp = fr_pair_find_by_num(request->reply->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Opcode */
        rad_assert(vp != NULL);
-       vp->vp_integer = 2; /* BOOTREPLY */
+       vp->vp_byte = 2; /* BOOTREPLY */
 
        /*
         *      Allow NAKs to be delayed for a short period of time.
         */
        if (request->reply->code == PW_DHCP_NAK) {
-               vp = pairfind(request->reply->vps, PW_FREERADIUS_RESPONSE_DELAY, 0, TAG_ANY);
+               vp = fr_pair_find_by_num(request->reply->vps, PW_FREERADIUS_RESPONSE_DELAY, 0, TAG_ANY);
                if (vp) {
                        if (vp->vp_integer <= 10) {
-                               request->response_delay = vp->vp_integer;
+                               request->response_delay.tv_sec = vp->vp_integer;
+                               request->response_delay.tv_usec = 0;
                        } else {
-                               request->response_delay = 10;
+                               request->response_delay.tv_sec = 10;
+                               request->response_delay.tv_usec = 0;
+                       }
+               } else {
+#define USEC 1000000
+                       vp = fr_pair_find_by_num(request->reply->vps, PW_FREERADIUS_RESPONSE_DELAY_USEC, 0, TAG_ANY);
+                       if (vp) {
+                               if (vp->vp_integer <= 10 * USEC) {
+                                       request->response_delay.tv_sec = vp->vp_integer / USEC;
+                                       request->response_delay.tv_usec = vp->vp_integer % USEC;
+                               } else {
+                                       request->response_delay.tv_sec = 10;
+                                       request->response_delay.tv_usec = 0;
+                               }
                        }
                }
        }
@@ -436,21 +449,36 @@ 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 = pairfind(request->reply->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Server-IP-Address */
-               if (!vp) vp = pairfind(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->packet->dst_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_ANY)) {
+               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;
 
@@ -461,10 +489,15 @@ static int dhcp_process(REQUEST *request)
         *      packet to the client.  i.e. the relay may have a
         *      public IP, but the gateway a private one.
         */
-       vp = pairfind(request->reply->vps, 272, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-IP-Address */
+       vp = fr_pair_find_by_num(request->reply->vps, 272, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Relay-IP-Address */
        if (vp && (vp->vp_ipaddr != ntohl(INADDR_ANY))) {
                RDEBUG("DHCP: Reply will be unicast to giaddr from original packet");
                request->reply->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+               request->reply->dst_port = request->packet->dst_port;
+
+               vp = fr_pair_find_by_num(request->reply->vps, PW_PACKET_DST_PORT, 0, TAG_ANY);
+               if (vp) request->reply->dst_port = vp->vp_integer;
+
                return 1;
        }
 
@@ -477,7 +510,7 @@ static int dhcp_process(REQUEST *request)
         *      Gateways are servers, and listen on the server port,
         *      not the client port.
         */
-       vp = pairfind(request->reply->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
+       vp = fr_pair_find_by_num(request->reply->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Gateway-IP-Address */
        if (vp && (vp->vp_ipaddr != htonl(INADDR_ANY))) {
                RDEBUG("DHCP: Reply will be unicast to giaddr");
                request->reply->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
@@ -490,9 +523,9 @@ static int dhcp_process(REQUEST *request)
         *      there's no client-ip-address, send a broadcast.
         */
        if ((request->reply->code == PW_DHCP_NAK) ||
-           ((vp = pairfind(request->reply->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Flags */
+           ((vp = fr_pair_find_by_num(request->reply->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Flags */
             (vp->vp_integer & 0x8000) &&
-            ((vp = pairfind(request->reply->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Client-IP-Address */
+            ((vp = fr_pair_find_by_num(request->reply->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Client-IP-Address */
              (vp->vp_ipaddr == htonl(INADDR_ANY))))) {
                /*
                 * RFC 2131, page 23
@@ -512,17 +545,17 @@ static int dhcp_process(REQUEST *request)
         *
         *      Unicast to ciaddr if present, otherwise to yiaddr.
         */
-       if ((vp = pairfind(request->reply->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Client-IP-Address */
+       if ((vp = fr_pair_find_by_num(request->reply->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY)) && /* DHCP-Client-IP-Address */
            (vp->vp_ipaddr != htonl(INADDR_ANY))) {
                RDEBUG("DHCP: Reply will be sent unicast to client-ip-address");
                request->reply->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
                return 1;
        }
 
-       vp = pairfind(request->reply->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */
+       vp = fr_pair_find_by_num(request->reply->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Your-IP-Address */
        if (!vp) {
                RDEBUG("DHCP: Failed to find DHCP-Client-IP-Address or DHCP-Your-IP-Address for request; "
-                      "not responding.");
+                      "not responding");
                /*
                 *      There is nowhere to send the response to, so don't bother.
                 */
@@ -561,7 +594,7 @@ static int dhcp_process(REQUEST *request)
         *      socket to send DHCP packets.
         */
        if (request->reply->code == PW_DHCP_OFFER) {
-               VALUE_PAIR *hwvp = pairfind(request->reply->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */
+               VALUE_PAIR *hwvp = fr_pair_find_by_num(request->reply->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY); /* DHCP-Client-Hardware-Address */
 
                if (!hwvp) return -1;
 
@@ -591,6 +624,12 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        RADCLIENT *client;
        CONF_PAIR *cp;
 
+       /*
+        *      Set if before parsing, so the user can forcibly turn
+        *      it off later.
+        */
+       this->nodup = true;
+
        rcode = common_socket_parse(cs, this);
        if (rcode != 0) return rcode;
 
@@ -599,7 +638,7 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        sock = this->data;
 
        if (!sock->lsock.interface) {
-               WDEBUG("No \"interface\" setting is defined.  Only unicast DHCP will work.");
+               WARN("No \"interface\" setting is defined.  Only unicast DHCP will work");
        }
 
        /*
@@ -634,14 +673,14 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        sock->suppress_responses = false;
        cp = cf_pair_find(cs, "suppress_responses");
        if (cp) {
-               cf_item_parse(cs, "suppress_responses", PW_TYPE_BOOLEAN,
-                             &sock->suppress_responses, NULL);
+               rcode = cf_item_parse(cs, "suppress_responses", FR_ITEM_POINTER(PW_TYPE_BOOLEAN, &sock->suppress_responses), NULL);
+               if (rcode < 0) return -1;
        }
 
        cp = cf_pair_find(cs, "src_interface");
        if (cp) {
-               cf_item_parse(cs, "src_interface", PW_TYPE_STRING_PTR,
-                             &sock->src_interface, NULL);
+               rcode = cf_item_parse(cs, "src_interface", FR_ITEM_POINTER(PW_TYPE_STRING, &sock->src_interface), NULL);
+               if (rcode < 0) return -1;
        } else {
                sock->src_interface = sock->lsock.interface;
        }
@@ -654,8 +693,7 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        if (cp) {
                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);
+               rcode = cf_item_parse(cs, "src_ipaddr", FR_ITEM_POINTER(PW_TYPE_IPV4_ADDR, &sock->src_ipaddr), NULL);
                if (rcode < 0) return -1;
 
                sock->src_ipaddr.af = AF_INET;
@@ -670,7 +708,7 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        memset(client, 0, sizeof(*client));
        client->ipaddr.af = AF_INET;
        client->ipaddr.ipaddr.ip4addr.s_addr = ntohl(INADDR_NONE);
-       client->prefix = 0;
+       client->ipaddr.prefix = 0;
        client->longname = client->shortname = "dhcp";
        client->secret = client->shortname;
        client->nas_type = talloc_typed_strdup(sock, "none");
@@ -697,7 +735,7 @@ static int dhcp_socket_recv(rad_listen_t *listener)
        }
 
        sock = listener->data;
-       if (!request_receive(listener, packet, &sock->dhcp_client, dhcp_process)) {
+       if (!request_receive(NULL, listener, packet, &sock->dhcp_client, dhcp_process)) {
                rad_free(&packet);
                return 0;
        }
@@ -742,12 +780,15 @@ static int dhcp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
        return fr_dhcp_decode(request->packet);
 }
 
+extern fr_protocol_t proto_dhcp;
 fr_protocol_t proto_dhcp = {
-       RLM_MODULE_INIT,
-       "dhcp",
-       sizeof(dhcp_socket_t),
-       NULL,
-       dhcp_socket_parse, NULL,
-       dhcp_socket_recv, dhcp_socket_send,
-       common_socket_print, dhcp_socket_encode, dhcp_socket_decode
+       .magic          = RLM_MODULE_INIT,
+       .name           = "dhcp",
+       .inst_size      = sizeof(dhcp_socket_t),
+       .parse          = dhcp_socket_parse,
+       .recv           = dhcp_socket_recv,
+       .send           = dhcp_socket_send,
+       .print          = common_socket_print,
+       .encode         = dhcp_socket_encode,
+       .decode         = dhcp_socket_decode
 };