]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
start of toy DHCP processor
authorAlan T. DeKok <aland@freeradius.org>
Sun, 13 May 2018 11:38:56 +0000 (07:38 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 13 May 2018 11:40:14 +0000 (07:40 -0400)
we probably still want to have different libraries for
other packet types.

And, update the encoder to set the destination IP based on
the encoded packet.  e.g. broadcast, unicast, sent to giaddr,
or forwarded to another DHCP server

src/modules/proto_dhcpv4/all.mk
src/modules/proto_dhcpv4/proto_dhcpv4_all.c [new file with mode: 0644]
src/modules/proto_dhcpv4/proto_dhcpv4_all.mk [new file with mode: 0644]

index ff72bb09977bb985cdaa19f8424ec004242ded6d..bc8f23bdd2c0268a490cf104d5acbe7155fcbdd4 100644 (file)
@@ -1 +1 @@
-SUBMAKEFILES := proto_dhcpv4.mk proto_dhcpv4_udp.mk rlm_dhcpv4.mk dhcpclient.mk
+SUBMAKEFILES := proto_dhcpv4.mk proto_dhcpv4_udp.mk rlm_dhcpv4.mk dhcpclient.mk proto_dhcpv4_all.mk
diff --git a/src/modules/proto_dhcpv4/proto_dhcpv4_all.c b/src/modules/proto_dhcpv4/proto_dhcpv4_all.c
new file mode 100644 (file)
index 0000000..a7c7ecf
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file proto_dhcpv4/proto_dhcpv4_all.c
+ * @brief DHCPV4 processing.
+ *
+ * @copyright 2018 The Freeradius server project.
+ * @copyright 2018 Alan DeKok (aland@deployingradius.com)
+ */
+#include <freeradius-devel/io/application.h>
+#include <freeradius-devel/protocol.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/unlang.h>
+#include <freeradius-devel/dict.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/dhcpv4/dhcpv4.h>
+#include <freeradius-devel/dhcpv4.h>
+
+static fr_io_final_t mod_process(REQUEST *request, UNUSED fr_io_action_t action)
+{
+       rlm_rcode_t rcode;
+       CONF_SECTION *unlang;
+       fr_dict_enum_t const *dv;
+       fr_dict_attr_t const *da = NULL;
+
+       REQUEST_VERIFY(request);
+
+       switch (request->request_state) {
+       case REQUEST_INIT:
+               radlog_request(L_DBG, L_DBG_LVL_1, request, "Received %s ID %08x",
+                              dhcp_message_types[request->packet->code], request->packet->id);
+               rdebug_proto_pair_list(L_DBG_LVL_1, request, request->packet->vps, "");
+
+               request->component = "dhcpv4";
+
+               da = fr_dict_attr_by_num(NULL, 0, FR_DHCP_MESSAGE_TYPE);
+               rad_assert(da != NULL);
+               dv = fr_dict_enum_by_value(da, fr_box_uint32(request->packet->code));
+               if (!dv) {
+                       REDEBUG("Failed to find value for &request:DHCP-Message-Type");
+                       return FR_IO_FAIL;
+               }
+
+               unlang = cf_section_find(request->server_cs, "recv", dv->alias);
+               if (!unlang) {
+                       RWDEBUG("Failed to find 'recv %s' section", dv->alias);
+                       request->reply->code = FR_DHCP_MESSAGE_TYPE_VALUE_DHCP_DO_NOT_RESPOND;
+                       goto send_reply;
+               }
+
+               RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang));
+               unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME);
+
+               request->request_state = REQUEST_RECV;
+               /* FALL-THROUGH */
+
+       case REQUEST_RECV:
+               rcode = unlang_interpret_continue(request);
+
+               if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE;
+
+               if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD;
+
+               rad_assert(request->log.unlang_indent == 0);
+
+               switch (rcode) {
+               case RLM_MODULE_NOOP:
+               case RLM_MODULE_OK:
+               case RLM_MODULE_UPDATED:
+                       if (request->packet->code == FR_DHCP_DISCOVER) {
+                               request->reply->code = FR_DHCP_OFFER;
+
+                       } else if (request->packet->code == FR_DHCP_REQUEST) {
+                               request->reply->code = FR_DHCP_ACK;
+
+                       } else {
+                               request->reply->code = FR_DHCP_NAK;
+                       }
+                       break;
+
+               default:
+               case RLM_MODULE_REJECT:
+               case RLM_MODULE_FAIL:
+               case RLM_MODULE_HANDLED:
+                       request->reply->code = FR_DHCP_MESSAGE_TYPE_VALUE_DHCP_DO_NOT_RESPOND;
+                       break;
+               }
+
+               if (!da) da = fr_dict_attr_by_num(NULL, 0, FR_DHCP_MESSAGE_TYPE);
+               rad_assert(da != NULL);
+
+               dv = fr_dict_enum_by_value(da, fr_box_uint32(request->reply->code));
+               unlang = NULL;
+               if (dv) unlang = cf_section_find(request->server_cs, "send", dv->alias);
+
+               if (!unlang) goto send_reply;
+
+       rerun_nak:
+               RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang));
+               unlang_push_section(request, unlang, RLM_MODULE_NOOP, UNLANG_TOP_FRAME);
+
+               request->request_state = REQUEST_SEND;
+               /* FALL-THROUGH */
+
+       case REQUEST_SEND:
+               rcode = unlang_interpret_continue(request);
+
+               if (request->master_state == REQUEST_STOP_PROCESSING) return FR_IO_DONE;
+
+               if (rcode == RLM_MODULE_YIELD) return FR_IO_YIELD;
+
+               rad_assert(request->log.unlang_indent == 0);
+
+               switch (rcode) {
+               case RLM_MODULE_NOOP:
+               case RLM_MODULE_OK:
+               case RLM_MODULE_UPDATED:
+               case RLM_MODULE_HANDLED:
+                       /* reply is already set */
+                       break;
+
+               default:
+                       /*
+                        *      If we over-ride an ACK with a NAK, run
+                        *      the NAK section.
+                        */
+                       if (request->reply->code != FR_DHCP_MESSAGE_TYPE_VALUE_DHCP_DO_NOT_RESPOND) {
+                               if (!da) da = fr_dict_attr_by_num(NULL, 0, FR_DHCP_MESSAGE_TYPE);
+                               rad_assert(da != NULL);
+
+                               dv = fr_dict_enum_by_value(da, fr_box_uint32(request->reply->code));
+                               RWDEBUG("Failed running 'send %s', trying 'send Do-Not-Respond'.", dv->alias);
+
+                               request->reply->code = FR_DHCP_MESSAGE_TYPE_VALUE_DHCP_DO_NOT_RESPOND;
+
+                               dv = fr_dict_enum_by_value(da, fr_box_uint32(request->reply->code));
+                               unlang = NULL;
+                               if (!dv) goto send_reply;
+
+                               unlang = cf_section_find(request->server_cs, "send", dv->alias);
+                               if (unlang) goto rerun_nak;
+
+                               RWDEBUG("Not running 'send %s' section as it does not exist", dv->alias);
+                       }
+                       break;
+               }
+
+       send_reply:
+               /*
+                *      Check for "do not respond".
+                */
+               if (request->reply->code == FR_DHCP_MESSAGE_TYPE_VALUE_DHCP_DO_NOT_RESPOND) {
+                       RDEBUG("Not sending reply to client.");
+                       return FR_IO_DONE;
+               }
+
+               if (RDEBUG_ENABLED) common_packet_debug(request, request->reply, false);
+               break;
+
+       default:
+               return FR_IO_FAIL;
+       }
+
+       return FR_IO_REPLY;
+}
+
+
+extern fr_app_process_t proto_dhcpv4_all;
+fr_app_process_t proto_dhcpv4_all = {
+       .magic          = RLM_MODULE_INIT,
+       .name           = "dhcpv4_all",
+       .process        = mod_process,
+};
diff --git a/src/modules/proto_dhcpv4/proto_dhcpv4_all.mk b/src/modules/proto_dhcpv4/proto_dhcpv4_all.mk
new file mode 100644 (file)
index 0000000..644cfaa
--- /dev/null
@@ -0,0 +1,9 @@
+TARGETNAME     := proto_dhcpv4_all
+
+ifneq "$(TARGETNAME)" ""
+TARGET         := $(TARGETNAME).a
+endif
+
+SOURCES                := proto_dhcpv4_all.c
+
+TGT_PREREQS    := libfreeradius-util.a libfreeradius-radius.a libfreeradius-dhcpv4.a