2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2 if the
4 * License as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * @brief Will contain dhcp listener code.
21 * @copyright 2012 The FreeRADIUS server project
25 #include <freeradius-devel/libradius.h>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/dhcp.h>
33 #define PW_DHCP_PARAMETER_REQUEST_LIST 55
36 * Define a structure for our module configuration.
38 * These variables do not need to be in a structure, but it's
39 * a lot cleaner to do so, and a pointer to the structure can
40 * be used as the instance handle.
42 typedef struct rlm_dhcp_t {
48 * Allow single attribute values to be retrieved from the dhcp.
50 static ssize_t dhcp_options_xlat(UNUSED void *instance, REQUEST *request,
51 char const *fmt, char *out, size_t freespace)
54 VALUE_PAIR *vp, *head = NULL;
57 while (isspace((int) *fmt)) fmt++;
59 if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
64 if ((fr_dhcp_decode_options(&head, request->packet, vp->vp_octets, vp->length) < 0) || (!head)) {
65 RWDEBUG("DHCP option decoding failed: %s", fr_strerror());
71 for (vp = fr_cursor_init(&cursor, &head);
73 vp = fr_cursor_next(&cursor)) {
77 pairmove(request->packet, &(request->packet->vps), &head);
79 /* Free any unmoved pairs */
82 snprintf(out, freespace, "%i", decoded);
87 static ssize_t dhcp_xlat(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace)
94 while (isspace((int) *fmt)) fmt++;
96 if ((radius_copy_vp(&vp, request, fmt) < 0) || !vp) {
100 fr_cursor_init(&cursor, &vp);
102 len = fr_dhcp_encode_option(binbuf, sizeof(binbuf), request, &cursor);
105 REDEBUG("DHCP option encoding failed: %s", fr_strerror());
110 if ((size_t)((len * 2) + 1) > freespace) {
111 REDEBUG("DHCP option encoding failed: Output buffer exhausted, needed %zd bytes, have %zd bytes",
112 (len * 2) + 1, freespace);
117 return fr_bin2hex(out, binbuf, len);
121 * Only free memory we allocated. The strings allocated via
122 * cf_section_parse() do not need to be freed.
124 static int mod_detach(void *instance)
126 xlat_unregister("dhcp_options", dhcp_options_xlat, instance);
127 xlat_unregister("dhcp", dhcp_xlat, instance);
133 * Instantiate the module.
135 static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
137 rlm_dhcp_t *inst = instance;
140 xlat_register("dhcp_options", dhcp_options_xlat, NULL, inst);
141 xlat_register("dhcp", dhcp_xlat, NULL, inst);
144 * Fixup dictionary entry for DHCP-Paramter-Request-List adding all the options
146 da = dict_attrbyvalue(PW_DHCP_PARAMETER_REQUEST_LIST, DHCP_MAGIC_VENDOR);
148 DICT_ATTR const *value;
151 /* No padding or termination options */
152 DEBUG3("Adding values for %s", da->name);
153 for (i = 1; i < 255; i++) {
154 value = dict_attrbyvalue(i, DHCP_MAGIC_VENDOR);
156 DEBUG3("No DHCP RFC space attribute at %i", i);
160 DEBUG3("Adding %s value %i %s", da->name, i, value->name);
161 if (dict_addvalue(value->name, da->name, i) < 0) {
162 DEBUG3("Failed adding value: %s", fr_strerror());
172 * The module name should be the only globally exported symbol.
173 * That is, everything else should be 'static'.
175 * If the module needs to temporarily modify it's instantiation
176 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
177 * The server will then take care of ensuring that the module
178 * is single-threaded.
180 module_t rlm_dhcp = {
185 NULL, /* CONF_PARSER */
186 mod_instantiate, /* instantiation */
187 mod_detach, /* detach */
189 NULL, /* authentication */
190 NULL, /* authorization */
191 NULL, /* preaccounting */
192 NULL, /* accounting */
193 NULL, /* checksimul */
194 NULL, /* pre-proxy */
195 NULL, /* post-proxy */
196 NULL, /* post-auth */