コード例 #1
0
/* cleanup IP pools and sync them with radacct */
static int nvp_cleanup(rlm_sqlhpwippool_t *data)
{
	rlm_sql_handle_t *sqlsock;

	/* initialize the SQL socket */
	sqlsock = sql_get_socket(data->sqlinst);
	if (!sqlsock) {
		nvp_log(__LINE__, data, L_ERR, "nvp_cleanup(): error while "
					       "requesting new SQL connection");
		return 0;
	}

	/* free IPs of closed sessions */
	if (!nvp_freeclosed(data, sqlsock)) {
		sql_release_socket(data->sqlinst, sqlsock);
		return 0;
	}

	/* add sessions opened in the meantime */
	if (!nvp_query(__LINE__, data, sqlsock,
	    "UPDATE `%s`.`ips`, `radacct` "
	    	"SET "
	    		"`ips`.`pid` = 0, "
	    		"`ips`.`rsv_by` = `radacct`.`acctuniqueid`, "
	    		"`ips`.`rsv_since` = `radacct`.`acctstarttime`, "
	    		"`ips`.`rsv_until` = 0 "
	    	"WHERE "
	    		"`radacct`.`acctstoptime` IS NULL AND "     /* session is opened */
	    		"`ips`.`ip` = INET_ATON(`radacct`.`framedipaddress`) AND "
	    		"("
	    			"`ips`.`pid` IS NULL OR "
/*	    			"(`ips`.`rsv_until` > 0 AND `ips.`rsv_until` < NOW()) " */
	    			"`ips`.`rsv_until` != 0"   /* no acct pkt received yet */
	    		")",
	    data->db_name)) {
		sql_release_socket(data->sqlinst, sqlsock);
		return 0;
	}
	else {
		nvp_finish(data, sqlsock);
	}

	/* count number of free IP addresses in IP pools */
	if (!nvp_syncfree(data, sqlsock)) {
		sql_release_socket(data->sqlinst, sqlsock);
		return 0;
	}

	sql_release_socket(data->sqlinst, sqlsock);
	return 1;
}
コード例 #2
0
/* assign new IP address, if required */
static rlm_rcode_t mod_post_auth(void *instance, REQUEST *request)
{
	VALUE_PAIR *vp;
	char const *pname;       /* name of requested IP pool */
	uint32_t nasip;	     /* NAS IP in host byte order */
	struct in_addr ip = {0};    /* reserved IP for client (net. byte order) */
	rlm_sql_handle_t *sqlsock;
	unsigned long s_gid,	/* _s_elected in sql result set */
		      s_prio,       /* as above */
		      s_pid,	/* as above */
		      gid,	  /* real integer value */
		      pid,	  /* as above */
		      weights_sum, used_sum, ip_start, ip_stop, connid;
	long prio;

	rlm_sqlhpwippool_t *inst = (rlm_sqlhpwippool_t *) instance;

	/* if IP is already there, then nothing to do */
	vp = pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS, 0, TAG_ANY);
	if (vp) {
		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): IP address "
			"already in the reply packet - exiting");
		return RLM_MODULE_NOOP;
	}

	/* if no pool name, we don't need to do anything */
	vp = pairfind(request->reply->vps, ASN_IP_POOL_NAME, VENDORPEC_ASN, TAG_ANY);
	if (vp) {
		pname = vp->vp_strvalue;
		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): pool name = '%s'",
			pname);
	}
	else {
		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): no IP pool name - exiting");
		return RLM_MODULE_NOOP;
	}

	/* if no NAS IP address, assign 0 */
	vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS, 0, TAG_ANY);
	if (vp) {
		nasip = ntohl(vp->vp_ipaddr);
	}
	else {
		nasip = 0;
		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): no NAS IP address in "
			"the request packet - using \"0.0.0.0/0\" (any)");
	}

	/* get our database connection */
	sqlsock = sql_get_socket(inst->sqlinst);
	if (!sqlsock) {
		nvp_log(__LINE__, inst, L_ERR,
			"mod_post_auth(): error while requesting an SQL socket");
		return RLM_MODULE_FAIL;
	}

	/* get connection id as temporary unique integer */
	if (nvp_select(__LINE__, inst, sqlsock, "SELECT CONNECTION_ID()") < 1) {
		nvp_log(__LINE__, inst, L_ERR, "mod_post_auth(): WTF ;-)!");
		nvp_select_finish(inst, sqlsock);
		sql_release_socket(inst->sqlinst, sqlsock);
		return RLM_MODULE_FAIL;
	}

	connid = strtoul(sqlsock->row[0], (char **) NULL, 10);
	nvp_select_finish(inst, sqlsock);

	/* synchronize with radacct db, if needed */
	if (++inst->sincesync >= inst->sync_after
#ifdef HAVE_PTHREAD_D
	    && (pthread_mutex_trylock(&inst->mutex)) == 0
#endif
	   ) {
		int r;

		inst->sincesync = 0;

		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): syncing with radacct table");

		r = (nvp_freeclosed(inst, sqlsock) && nvp_syncfree(inst, sqlsock));

#ifdef HAVE_PTHREAD_D
		pthread_mutex_unlock(&inst->mutex);
#endif

		if (!r) {
			nvp_log(__LINE__, inst, L_ERR,
				"mod_post_auth(): synchronization failed");
			sql_release_socket(inst->sqlinst, sqlsock);
			return RLM_MODULE_FAIL;
		}
	}

	for (s_gid = 0; s_gid < RLM_NETVIM_MAX_ROWS && !(ip.s_addr); s_gid++) {
		nvp_log(__LINE__, inst, L_DBG,
			"mod_post_auth(): selecting gid on position %lu",
			s_gid);

		/* find the most specific group which NAS belongs to */
		switch (nvp_select(__LINE__, inst, sqlsock,
		       "SELECT `host_groups`.`gid` "
		       	"FROM "
		       		"`%s`.`host_groups`, "
		       		"`%1$s`.`gid_ip`, "
		       		"`%1$s`.`ids` "
		       	"WHERE "
		       		"`host_groups`.`gid` = `ids`.`id` AND "
		       		"`ids`.`enabled` = 1 AND "
		       		"`host_groups`.`gid` = `gid_ip`.`gid` AND "
		       		"%lu BETWEEN `gid_ip`.`ip_start` AND `gid_ip`.`ip_stop` "
		       	"ORDER BY (`gid_ip`.`ip_stop` - `gid_ip`.`ip_start`) ASC "
		       	"LIMIT %lu, 1",
		       inst->db_name, nasip, s_gid)) {
			case -1:
				nvp_log(__LINE__, inst, L_ERR,
					"mod_post_auth(): couldn't find "
					"any more matching host groups");
				goto end_gid;		  /* exit the main loop */
			case 0:
				sql_release_socket(inst->sqlinst, sqlsock);
				return RLM_MODULE_FAIL;
		}

		/* store the group ID and free memory occupied by results */
		gid = strtoul(sqlsock->row[0], (char **) NULL, 10);
		nvp_select_finish(inst, sqlsock);

		for (s_prio = 0; s_prio < RLM_NETVIM_MAX_ROWS && !(ip.s_addr); s_prio++) {
			nvp_log(__LINE__, inst, L_DBG,
				"mod_post_auth(): selecting prio on position %lu",
				s_prio);

			/* prepare to search for best fit pool */
			switch (nvp_select(__LINE__, inst, sqlsock,
				"SELECT "
					"`ip_pools`.`prio`, "
					"SUM(`ip_pools`.`weight`) AS `weights_sum`, "
					"(SUM(`ip_pools`.`total`) - "
						"SUM(`ip_pools`.`free`)) AS `used_sum` "
					"FROM "
						"`%s`.`ip_pools`, "
						"`%1$s`.`ids`, "
					 	"`%1$s`.`pool_names` "
					"WHERE "
						"`ip_pools`.`gid` = %lu AND "
						"`ids`.`id` = `ip_pools`.`pid` AND "
						"`ids`.`enabled` = 1 AND "
						"`pool_names`.`pnid` = `ip_pools`.`pnid` AND "
						"`pool_names`.`name` = '%s' AND "
						"`ip_pools`.`free` > 0 "
					"GROUP BY `prio` "
					"ORDER BY `prio` ASC "
					"LIMIT %lu, 1",
				inst->db_name, gid, pname, s_prio)) {
				case -1:
					nvp_log(__LINE__, inst, L_DBG,
						"mod_post_auth(): couldn't find "
						"any more matching pools for gid = %u",
						gid);
					goto end_prio;	       /* select next gid */
				case 0:
					sql_release_socket(inst->sqlinst, sqlsock);
					return RLM_MODULE_FAIL;
			}

			/* store the prio and weights sum */
			prio = strtol(sqlsock->row[0], (char **) NULL, 10);
			weights_sum = strtoul(sqlsock->row[1], (char **) NULL, 10);
			used_sum = strtoul(sqlsock->row[2], (char **) NULL, 10);

			/* free memory */
			nvp_select_finish(inst, sqlsock);

			for (s_pid = 0; s_pid < RLM_NETVIM_MAX_ROWS && !(ip.s_addr); s_pid++) {
				nvp_log(__LINE__, inst, L_DBG,
					"mod_post_auth(): selecting PID on position %lu",
					s_pid);

				/* search for best fit pool */
				switch (nvp_select(__LINE__, inst, sqlsock,
					"SELECT "
						"`ip_pools`.`pid`, "
						"`ip_pools`.`ip_start`, "
						"`ip_pools`.`ip_stop` "
						"FROM "
							"`%s`.`ip_pools`, "
							"`%1$s`.`ids`, "
							"`%1$s`.`pool_names` "
						"WHERE "
							"`ip_pools`.`gid` = %lu AND "
							"`ids`.`id` = `ip_pools`.`pid` AND "
							"`ids`.`enabled` = 1 AND "
							"`pool_names`.`pnid` = `ip_pools`.`pnid` AND "
							"`pool_names`.`name` = '%s' AND "
							"`ip_pools`.`free` > 0 AND "
							"`prio` = %ld "
						"ORDER BY (`weight`/%lu.0000 - (`total` - `free`)/%lu) DESC "
						"LIMIT %lu, 1",
					inst->db_name, gid, pname, prio,
					weights_sum, used_sum, s_pid)) {
					case -1:
						nvp_log(__LINE__, inst, L_DBG,
							"mod_post_auth(): couldn't find any more "
							"matching pools of prio = %ld for gid = %lu",
							prio, gid);
						goto end_pid;	      /* select next prio */
					case 0:
						sql_release_socket(inst->sqlinst, sqlsock);
						return RLM_MODULE_FAIL;
				}

				/* store the inst and free memory occupied by results */
				pid = strtoul(sqlsock->row[0], (char **) NULL, 10);
				ip_start = strtoul(sqlsock->row[1], (char **) NULL, 10);
				ip_stop = strtoul(sqlsock->row[2], (char **) NULL, 10);
				nvp_select_finish(inst, sqlsock);

				/* reserve an IP address */
				if (!nvp_query(__LINE__, inst, sqlsock,
				    "UPDATE `%s`.`ips` "
				    	"SET "
				    		"`pid` = %lu, "
				    		"`rsv_since` = NOW(), "
				    		"`rsv_by` = '" RLM_NETVIM_TMP_PREFIX "%lu', "
				    		"`rsv_until` = NOW() + INTERVAL %d SECOND "
				    	"WHERE "
				    		"`ip` BETWEEN %lu AND %lu AND "
				    		"("
				    			"`pid` IS NULL OR "
				    			"(`rsv_until` > 0 AND `rsv_until` < NOW())"
				    		") "
				    	"ORDER BY RAND() "
				    	"LIMIT 1",
				    inst->db_name, pid, connid, inst->free_after, ip_start, ip_stop)) {
					sql_release_socket(inst->sqlinst, sqlsock);
					return RLM_MODULE_FAIL;
				}
				else {
					nvp_finish(inst, sqlsock);
				}

				/* select assigned IP address */
				switch (nvp_select(__LINE__, inst, sqlsock,
					"SELECT `ip` "
						"FROM `%s`.`ips` "
						"WHERE `rsv_by` = '" RLM_NETVIM_TMP_PREFIX "%lu' "
						"ORDER BY `rsv_since` DESC "
						"LIMIT 1",
					inst->db_name, connid)) {
					case -1:
						nvp_log(__LINE__, inst, L_ERR,
							"mod_post_auth(): couldn't reserve an IP address "
							"from pool of pid = %lu (prio = %ld, gid = %lu)",
							pid, prio, gid);
						continue;			    /* select next pid */
					case 0:
						sql_release_socket(inst->sqlinst, sqlsock);
						return RLM_MODULE_FAIL;
				}

				/* update free IPs count */
				if (!nvp_query(__LINE__, inst, sqlsock,
				    "UPDATE `%s`.`ip_pools` "
				    	"SET "
				    		"`free` = `free` - 1 "
				    	"WHERE "
				    		"`pid` = %lu "
			    	"LIMIT 1",
				    inst->db_name, pid)) {
					sql_release_socket(inst->sqlinst, sqlsock);
					return RLM_MODULE_FAIL;
				}
				else {
					nvp_finish(inst, sqlsock);
				}

				/* get assigned IP and free memory */
				ip.s_addr = htonl(strtoul(sqlsock->row[0], (char **) NULL, 10));
				nvp_select_finish(inst, sqlsock);
			} /* pid */
end_pid: continue;	   /* stupid */
		} /* prio */
end_prio: continue;	  /* stupid */
	} /* gid */
end_gid:

	/* release SQL socket */
	sql_release_socket(inst->sqlinst, sqlsock);

	/* no free IP address found */
	if (!ip.s_addr) {
		nvp_log(__LINE__, inst, L_INFO,
			"mod_post_auth(): no free IP address found!");

		if (inst->no_free_fail) {
			nvp_log(__LINE__, inst, L_DBG, "mod_post_auth(): rejecting user");
			return RLM_MODULE_REJECT;
		}
		else {
			nvp_log(__LINE__, inst, L_DBG, "mod_post_auth(): exiting");
			return RLM_MODULE_NOOP;
		}
	}

	/* add IP address to reply packet */
	vp = radius_paircreate(request, &request->reply->vps,
			       PW_FRAMED_IP_ADDRESS, 0);
	vp->vp_ipaddr = ip.s_addr;

	nvp_log(__LINE__, inst, L_DBG, "mod_post_auth(): returning %s",
		inet_ntoa(ip));
	return RLM_MODULE_OK;
}
コード例 #3
0
ファイル: example16.c プロジェクト: flaviommedeiros/cprojects
if (++inst->sincesync >= inst->sync_after
#ifdef HAVE_PTHREAD_D
	    && (pthread_mutex_trylock(&inst->mutex)) == 0
#endif
	   ) {
		int r;

		inst->sincesync = 0;

		radlog(L_DBG,
			"mod_post_auth(): syncing with radacct table");

		r = (nvp_freeclosed(inst, sqlsock) && nvp_syncfree(inst, sqlsock));

#ifdef HAVE_PTHREAD_D
		pthread_mutex_unlock(&inst->mutex);
#endif

		if (!r) {
			radlog(L_ERR,
				"mod_post_auth(): synchronization failed");
			fr_connection_release(inst->sql_inst->pool, sqlsock);
			return RLM_MODULE_FAIL;
		}
	}