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>
34 * Define a structure for our module configuration.
36 * These variables do not need to be in a structure, but it's
37 * a lot cleaner to do so, and a pointer to the structure can
38 * be used as the instance handle.
40 typedef struct rlm_dhcp_t {
46 * Allow single attribute values to be retrieved from the dhcp.
48 static ssize_t dhcp_options_xlat(UNUSED void *instance, REQUEST *request,
49 char const *fmt, char *out, size_t freespace)
52 VALUE_PAIR *vp, *head = NULL;
55 while (isspace((int) *fmt)) fmt++;
57 if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
62 if ((fr_dhcp_decode_options(request->packet,
63 vp->vp_octets, vp->length, &head) < 0) || (!head)) {
64 RWDEBUG("DHCP option decoding failed: %s", fr_strerror());
70 for (vp = fr_cursor_init(&cursor, &head);
72 vp = fr_cursor_next(&cursor)) {
76 pairmove(request->packet, &(request->packet->vps), &head);
78 /* Free any unmoved pairs */
81 snprintf(out, freespace, "%i", decoded);
86 static ssize_t dhcp_xlat(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace)
93 while (isspace((int) *fmt)) fmt++;
95 if ((radius_copy_vp(&vp, request, fmt) < 0) || !vp) {
99 fr_cursor_init(&cursor, &vp);
101 len = fr_dhcp_encode_option(binbuf, sizeof(binbuf), request, &cursor);
104 REDEBUG("DHCP option encoding failed: %s", fr_strerror());
109 if ((size_t)((len * 2) + 1) > freespace) {
110 REDEBUG("DHCP option encoding failed: Output buffer exhausted, needed %zd bytes, have %zd bytes",
111 (len * 2) + 1, freespace);
116 return fr_bin2hex(out, binbuf, len);
120 * Only free memory we allocated. The strings allocated via
121 * cf_section_parse() do not need to be freed.
123 static int mod_detach(void *instance)
125 xlat_unregister("dhcp_options", dhcp_options_xlat, instance);
126 xlat_unregister("dhcp", dhcp_xlat, instance);
132 * Instantiate the module.
134 static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
136 rlm_dhcp_t *inst = instance;
138 xlat_register("dhcp_options", dhcp_options_xlat, NULL, inst);
139 xlat_register("dhcp", dhcp_xlat, NULL, inst);
146 * The module name should be the only globally exported symbol.
147 * That is, everything else should be 'static'.
149 * If the module needs to temporarily modify it's instantiation
150 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
151 * The server will then take care of ensuring that the module
152 * is single-threaded.
154 module_t rlm_dhcp = {
159 NULL, /* CONF_PARSER */
160 mod_instantiate, /* instantiation */
161 mod_detach, /* detach */
163 NULL, /* authentication */
164 NULL, /* authorization */
165 NULL, /* preaccounting */
166 NULL, /* accounting */
167 NULL, /* checksimul */
168 NULL, /* pre-proxy */
169 NULL, /* post-proxy */
170 NULL, /* post-auth */