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(&head, request->packet, vp->vp_octets, vp->length) < 0) || (!head)) {
63 RWDEBUG("DHCP option decoding failed: %s", fr_strerror());
69 for (vp = fr_cursor_init(&cursor, &head);
71 vp = fr_cursor_next(&cursor)) {
75 pairmove(request->packet, &(request->packet->vps), &head);
77 /* Free any unmoved pairs */
80 snprintf(out, freespace, "%i", decoded);
85 static ssize_t dhcp_xlat(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace)
92 while (isspace((int) *fmt)) fmt++;
94 if ((radius_copy_vp(&vp, request, fmt) < 0) || !vp) {
98 fr_cursor_init(&cursor, &vp);
100 len = fr_dhcp_encode_option(binbuf, sizeof(binbuf), request, &cursor);
103 REDEBUG("DHCP option encoding failed: %s", fr_strerror());
108 if ((size_t)((len * 2) + 1) > freespace) {
109 REDEBUG("DHCP option encoding failed: Output buffer exhausted, needed %zd bytes, have %zd bytes",
110 (len * 2) + 1, freespace);
115 return fr_bin2hex(out, binbuf, len);
119 * Only free memory we allocated. The strings allocated via
120 * cf_section_parse() do not need to be freed.
122 static int mod_detach(void *instance)
124 xlat_unregister("dhcp_options", dhcp_options_xlat, instance);
125 xlat_unregister("dhcp", dhcp_xlat, instance);
131 * Instantiate the module.
133 static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
135 rlm_dhcp_t *inst = instance;
137 xlat_register("dhcp_options", dhcp_options_xlat, NULL, inst);
138 xlat_register("dhcp", dhcp_xlat, NULL, inst);
145 * The module name should be the only globally exported symbol.
146 * That is, everything else should be 'static'.
148 * If the module needs to temporarily modify it's instantiation
149 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
150 * The server will then take care of ensuring that the module
151 * is single-threaded.
153 module_t rlm_dhcp = {
158 NULL, /* CONF_PARSER */
159 mod_instantiate, /* instantiation */
160 mod_detach, /* detach */
162 NULL, /* authentication */
163 NULL, /* authorization */
164 NULL, /* preaccounting */
165 NULL, /* accounting */
166 NULL, /* checksimul */
167 NULL, /* pre-proxy */
168 NULL, /* post-proxy */
169 NULL, /* post-auth */