dhcp integrated in rlm_sql

Stephen R. van den Berg srb at cuci.nl
Tue Aug 23 12:18:20 CEST 2011


---
 src/include/modules.h          |   11 +++----
 src/include/radius.h           |    1 +
 src/lib/dhcp.c                 |   23 ++++++++++----
 src/main/dhcpd.c               |    6 +++-
 src/main/modules.c             |   23 +++++++++------
 src/modules/rlm_policy/parse.c |    3 +-
 src/modules/rlm_sql/conf.h     |    1 +
 src/modules/rlm_sql/rlm_sql.c  |   61 ++++++++++++++++++++++++++++++++++++++--
 8 files changed, 101 insertions(+), 28 deletions(-)

diff --git a/src/include/modules.h b/src/include/modules.h
index dbb17f3..2dff528 100644
--- a/src/include/modules.h
+++ b/src/include/modules.h
@@ -28,11 +28,10 @@ enum {
   RLM_COMPONENT_PRE_PROXY,	/* 5 */
   RLM_COMPONENT_POST_PROXY,	/* 6 */
   RLM_COMPONENT_POST_AUTH,	/* 7 */
-#ifdef WITH_COA
   RLM_COMPONENT_RECV_COA,	/* 8 */
   RLM_COMPONENT_SEND_COA,	/* 9 */
-#endif
-  RLM_COMPONENT_COUNT		/* 8 / 10: How many components are there */
+  RLM_COMPONENT_DHCP,		/* 10 */
+  RLM_COMPONENT_COUNT		/* 11: the number of components */
 };
 
 #define RLM_TYPE_THREAD_SAFE		(0 << 0)
@@ -79,9 +78,9 @@ int module_post_auth(int type, REQUEST *request);
 #ifdef WITH_COA
 int module_recv_coa(int type, REQUEST *request);
 int module_send_coa(int type, REQUEST *request);
-#define MODULE_NULL_COA_FUNCS ,NULL,NULL
-#else
-#define MODULE_NULL_COA_FUNCS
+#endif
+#ifdef WITH_DHCP
+int module_dhcp(int type, REQUEST *request);
 #endif
 int indexed_modcall(int comp, int idx, REQUEST *request);
 
diff --git a/src/include/radius.h b/src/include/radius.h
index 3d9c221..76e4dcb 100644
--- a/src/include/radius.h
+++ b/src/include/radius.h
@@ -239,6 +239,7 @@
 #define PW_MSCHAP_PASSWORD		1133
 #define PW_PACKET_TRANSMIT_COUNTER     	1134
 #define PW_CACHED_SESSION_POLICY     	1135
+#define PW_DHCP_TYPE 	  		1136
 
 /*
  *	Integer Translations
diff --git a/src/lib/dhcp.c b/src/lib/dhcp.c
index 1bcaf44..971fac7 100644
--- a/src/lib/dhcp.c
+++ b/src/lib/dhcp.c
@@ -1022,18 +1022,26 @@ int fr_dhcp_encode(RADIUS_PACKET *packet, RADIUS_PACKET *original)
 			}
 			
 		} else if ((packet->code == PW_DHCP_NAK) ||
-			   ((dhcp->flags & 0x8000) != 0) ||
-			   (dhcp->ciaddr == htonl(INADDR_ANY))) {
+			   ((dhcp->flags & 0x8000) != 0)) {
 			/*
 			 *	The kernel will take care of sending it to
 			 *	the broadcast MAC.
 			 */
-			packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
-			
+			packet->dst_ipaddr.ipaddr.ip4addr.s_addr = lvalue;
+		} else if (dhcp->ciaddr == htonl(INADDR_ANY))) {
+
+			vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR); /* Your IP address */
+			if (vp) {
+				lvalue = vp->vp_ipaddr;
+				packet->offset = 0;
+			} else {
+				lvalue = htonl(INADDR_BROADCAST);
+			}
+			packet->dst_ipaddr.ipaddr.ip4addr.s_addr = lvalue;
 		} else {
 			/*
-			 *	It was broadcast to us: we need to
-			 *	broadcast the response.
+			 *	It was unicast to us: we need to
+			 *	unicast the response.
 			 */
 			if (packet->src_ipaddr.ipaddr.ip4addr.s_addr != dhcp->ciaddr) {
 				packet->offset = 0;
@@ -1286,7 +1294,8 @@ int fr_dhcp_encode(RADIUS_PACKET *packet, RADIUS_PACKET *original)
 		for (i = 0; i < 14; i++) {
 			vp = pairmake(dhcp_header_names[i], NULL, T_OP_EQ);
 			if (!vp) {
-				fr_strerror_printf("Parse error %s", fr_strerror());
+				fr_strerror_printf("%s Parse error %s",
+				 fr_strerror(), dhcp_header_names[i]);
 				return -1;
 			}
 			
diff --git a/src/main/dhcpd.c b/src/main/dhcpd.c
index 975f159..7247e42 100644
--- a/src/main/dhcpd.c
+++ b/src/main/dhcpd.c
@@ -52,7 +52,11 @@ static int dhcp_process(REQUEST *request)
 		DICT_VALUE *dv = dict_valbyattr(53, DHCP_MAGIC_VENDOR, vp->vp_integer);
 		DEBUG("Trying sub-section dhcp %s {...}",
 		      dv->name ? dv->name : "<unknown>");
-		rcode = module_post_auth(vp->vp_integer, request);
+		rcode = module_dhcp(vp->vp_integer, request);
+		if (rcode == RLM_MODULE_REJECT) {
+			DEBUG("Fallback, trying sub-section dhcp {...}");
+			rcode = module_dhcp(0, request);
+		}
 	} else {
 		DEBUG("DHCP: Failed to find DHCP-Message-Type in packet!");
 		rcode = RLM_MODULE_FAIL;
diff --git a/src/main/modules.c b/src/main/modules.c
index 8984f92..7f0fa9b 100644
--- a/src/main/modules.c
+++ b/src/main/modules.c
@@ -84,12 +84,10 @@ static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
 	{ "session",      "Session-Type",    PW_SESSION_TYPE },
 	{ "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
 	{ "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
-	{ "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE }
-#ifdef WITH_COA
-	,
+	{ "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
 	{ "recv-coa",     "Recv-CoA-Type",   PW_RECV_COA_TYPE },
-	{ "send-coa",     "Send-CoA-Type",   PW_SEND_COA_TYPE }
-#endif
+	{ "send-coa",     "Send-CoA-Type",   PW_SEND_COA_TYPE },
+	{ "dhcp",	  "DHCP-Type",       PW_DHCP_TYPE },
 };
 
 
@@ -804,7 +802,7 @@ static int load_subcomponent_section(modcallable *parent, CONF_SECTION *cs,
 	DICT_VALUE *dval;
 	const char *name2 = cf_section_name2(cs);
 
-	rad_assert(comp >= RLM_COMPONENT_AUTH);
+	rad_assert(comp >= 0);
 	rad_assert(comp < RLM_COMPONENT_COUNT);
 
 	/*
@@ -1209,12 +1207,12 @@ static int load_byserver(CONF_SECTION *cs)
 				if (!load_subcomponent_section(NULL, subcs,
 							       components,
 							       dattr->attr,
-							       RLM_COMPONENT_POST_AUTH)) {
+							       RLM_COMPONENT_DHCP)) {
 					goto error; /* FIXME: memleak? */
 				}
 				c = lookup_by_index(components,
-						    RLM_COMPONENT_POST_AUTH, 0);
-				if (c) server->mc[RLM_COMPONENT_POST_AUTH] = c->modulelist;
+						    RLM_COMPONENT_DHCP, 0);
+				if (c) server->mc[RLM_COMPONENT_DHCP] = c->modulelist;
 				flag = 1;
 			}
 		}
@@ -1714,3 +1712,10 @@ int module_send_coa(int send_coa_type, REQUEST *request)
 	return indexed_modcall(RLM_COMPONENT_SEND_COA, send_coa_type, request);
 }
 #endif
+
+#ifdef WITH_DHCP
+int module_dhcp(int dhcp_type, REQUEST *request)
+{
+	return indexed_modcall(RLM_COMPONENT_DHCP, dhcp_type, request);
+}
+#endif
diff --git a/src/modules/rlm_policy/parse.c b/src/modules/rlm_policy/parse.c
index 2992ab4..a6db9d7 100644
--- a/src/modules/rlm_policy/parse.c
+++ b/src/modules/rlm_policy/parse.c
@@ -1094,10 +1094,9 @@ const FR_NAME_NUMBER policy_component_names[] = {
 	{ "pre-proxy", RLM_COMPONENT_PRE_PROXY },
 	{ "post-proxy", RLM_COMPONENT_POST_PROXY },
 	{ "post-auth", RLM_COMPONENT_POST_AUTH },
-#ifdef WITH_COA
 	{ "recv-coa", RLM_COMPONENT_RECV_COA },
 	{ "send-coa", RLM_COMPONENT_SEND_COA },
-#endif
+	{ "dhcp", RLM_COMPONENT_DHCP },
 	{ NULL, RLM_COMPONENT_COUNT }
 };
 
diff --git a/src/modules/rlm_sql/conf.h b/src/modules/rlm_sql/conf.h
index d1faae0..aac2084 100644
--- a/src/modules/rlm_sql/conf.h
+++ b/src/modules/rlm_sql/conf.h
@@ -47,6 +47,7 @@ typedef struct sql_config {
 	int     max_queries;
 	int     connect_failure_retry_delay;
 	char   *postauth_query;
+	char   *dhcp_query;
 	char   *allowed_chars;
 	int	query_timeout;
 
diff --git a/src/modules/rlm_sql/rlm_sql.c b/src/modules/rlm_sql/rlm_sql.c
index 0982363..bfe197c 100644
--- a/src/modules/rlm_sql/rlm_sql.c
+++ b/src/modules/rlm_sql/rlm_sql.c
@@ -109,6 +109,10 @@ static const CONF_PARSER module_config[] = {
 #endif
 	{"postauth_query", PW_TYPE_STRING_PTR,
 	 offsetof(SQL_CONFIG,postauth_query), NULL, ""},
+#ifdef WITH_DHCP
+	{"dhcp_query", PW_TYPE_STRING_PTR,
+	 offsetof(SQL_CONFIG,dhcp_query), NULL, ""},
+#endif
 	{"safe-characters", PW_TYPE_STRING_PTR,
 	 offsetof(SQL_CONFIG,allowed_chars), NULL,
 	"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
@@ -1097,6 +1101,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
 			pairxlatmove(request, &request->reply->vps, &reply_tmp);
 			}
 			pairxlatmove(request, &request->config_items, &check_tmp);
+			pairfree(&reply_tmp);
 		}
 	}
 
@@ -1104,7 +1109,6 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
 	 *	Clear out the pairlists
 	 */
 	pairfree(&check_tmp);
-	pairfree(&reply_tmp);
 
 	/*
 	 *	dofallthrough is set to 1 by default so that if the user information
@@ -1175,7 +1179,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
 		RDEBUG("User %s not found", sqlusername);
 		return RLM_MODULE_NOTFOUND;
 	} else {
-		return RLM_MODULE_OK;
+		return RLM_MODULE_UPDATED;
 	}
 }
 
@@ -1661,6 +1665,50 @@ static int rlm_sql_postauth(void *instance, REQUEST *request) {
 	return RLM_MODULE_OK;
 }
 
+#ifdef WITH_DHCP
+static int rlm_sql_dhcp(void *instance, REQUEST * request)
+{
+	VALUE_PAIR *reply_tmp = NULL;
+	int	rows;
+	SQLSOCK *sqlsocket;
+	SQL_INST *inst = instance;
+	char    querystr[MAX_QUERY_LEN];
+
+	/*
+	 * reserve a socket
+	 */
+	if (!(sqlsocket = sql_get_socket(inst)))
+		return RLM_MODULE_FAIL;
+
+	/*
+	 *  After this point, ALL 'return's MUST release the SQL socket!
+	 */
+
+	if (!radius_xlat(querystr, sizeof(querystr), inst->config->dhcp_query, request, sql_escape_func)) {
+		radlog_request(L_ERR, 0, request, "Error generating query; rejecting DHCP request");
+		sql_release_socket(inst, sqlsocket);
+		return RLM_MODULE_FAIL;
+	}
+	rows = sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr);
+	if (rows < 0) {
+		radlog_request(L_ERR, 0, request, "SQL query error; rejecting DHCP request");
+		sql_release_socket(inst, sqlsocket);
+		pairfree(&reply_tmp);
+		return RLM_MODULE_FAIL;
+	} else if (rows > 0)
+		pairxlatmove(request, &request->reply->vps, &reply_tmp);
+
+	sql_release_socket(inst, sqlsocket);
+	pairfree(&reply_tmp);
+
+	if (rows > 0)
+		return RLM_MODULE_UPDATED;
+
+	RDEBUG("DHCP query returned nothing");
+	return RLM_MODULE_NOTFOUND;
+}
+#endif
+
 /* globally exported name */
 module_t rlm_sql = {
 	RLM_MODULE_INIT,
@@ -1684,6 +1732,13 @@ module_t rlm_sql = {
 #endif
 		NULL,			/* pre-proxy */
 		NULL,			/* post-proxy */
-		rlm_sql_postauth	/* post-auth */
+		rlm_sql_postauth,	/* post-auth */
+		NULL,			/* recv-coa */
+		NULL,			/* send-coa */
+#ifdef WITH_DHCP
+		rlm_sql_dhcp,		/* dhcp */
+#else
+		NULL,
+#endif
 	},
 };
-- 
1.7.5.4





More information about the Freeradius-Devel mailing list