mod_quotatab_sql
mod_quotatab
mod_quotatab_sql.c
contrib/
This submodule provides the SQL database "driver" for storing quota table information in SQL tables.
Please contact TJ Saunders <tj at castaglia.org> with any questions, concerns, or suggestions regarding this module.
2002-04-01: Thanks to Tomasz Konefal <tomk at compt.com> for his great feedback and support in developing this module.
2002-04-03: Thanks to Noah <sitz at onastick.net> for suggesting the better form of the UPDATE query.
2004-01-20: Thanks to Alex Ursu <alex.ursu at wapda.com> for supplying SQL Server FREEFORM query syntax.
QuotaLimitTable
QuotaTallyTable
mod_sql
mod_quotatab_sql requires five SQL-related configuration directives: SQLConnectInfo, and four SQLNamedQuery directives. The SQLConnectInfo is needed to allow the module to connect to the SQL database. The other four directives define the SQL queries that will be used by mod_quotatab for its storage/retrieval operations involving quota data.
SQLConnectInfo
SQLNamedQuery
When using SQL tables and mod_sql, the quota tables should appear in the database named by the SQLConnectInfo directive, which will probably also contain the authentication information tables. This way your proftpd-specific tables are kept together. Also, it is probably better to use a connection policy of PERSESSION, otherwise there will be more overhead associated with each new connection made to the database for each transaction; mod_quotatab makes a lot of reads and writes to its tables, each of which will require mod_quotatab_sql to use a database connection.
proftpd
One SQLNamedQuery is needed to SELECT quota information from the limit table. The defined SQL statement for this must return ten values, in the following order:
SELECT
UPDATE
INSERT
For SQL tables, the format for the QuotaLimitTable directive is:
QuotaLimitTable sql:/SELECT-SQLNamedQuery
QuotaTallyTable sql:/SELECT-SQLNamedQuery/UPDATE-SQLNamedQuery/INSERT-SQLNamedQuery
Also note that SQL-based tally tables have an issue with proper synchronization of updates, especially when multiple sessions involving the same tally are ocurring. In order to prevent the tally table from becoming out of sync, you are strongly encouraged to define a QuotaLock file.
QuotaLock
SQL Quota Tables Example Here are example SQLNamedQuery directives to help demonstrate how the mod_sql hooks are used by mod_quotatab. These example SQL statements assume the existence of two tables: a quotalimits table that defines limit records, and a quotatallies table that holds the current tally records. Note that these queries would appear all on a single line in your proftpd.conf.
quotalimits
quotatallies
proftpd.conf
SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, \ bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM quotalimits \ WHERE name = '%{0}' AND quota_type = '%{1}'"
%{0}
%{1}
SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, \ bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM quotatallies \ WHERE name = '%{0}' AND quota_type = '%{1}'"
SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, \ bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, \ files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, \ files_xfer_used = files_xfer_used + %{5} \ WHERE name = '%{6}' AND quota_type = '%{7}'" quotatallies
SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" quotatallies
Note: SQL Server uses a slightly different INSERT syntax. This means that if you are using mod_quotatab_sql in conjunction with the mod_sql_tds module to speak to a SQL Server, your INSERT query may need to look like:
mod_sql_tds
SQLNamedQuery insert-quota-tally FREEFORM \ "INSERT INTO quotatallies VALUES ('%{0}','%{1}','%{2}','%{3}','%{4}','%{5}','%{6}','%{7}')"
Now, using the above defined queries, the table configuration directives would be:
QuotaLock /var/run/ftpd/tally.lock QuotaLimitTable sql:/get-quota-limit QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally
Example Schema Here are some example table schema for SQL-based quota tables:
CREATE TABLE quotalimits ( name VARCHAR(30), quota_type ENUM("user", "group", "class", "all") NOT NULL, per_session ENUM("false", "true") NOT NULL, limit_type ENUM("soft", "hard") NOT NULL, bytes_in_avail FLOAT NOT NULL, bytes_out_avail FLOAT NOT NULL, bytes_xfer_avail FLOAT NOT NULL, files_in_avail INT UNSIGNED NOT NULL, files_out_avail INT UNSIGNED NOT NULL, files_xfer_avail INT UNSIGNED NOT NULL );
CREATE TABLE quotalimits ( name VARCHAR(32) NOT NULL, quota_type VARCHAR(8) NOT NULL CHECK (quota_type IN ('user', 'group', 'class', 'all')), per_session BOOLEAN NOT NULL, limit_type VARCHAR(4) NOT NULL CHECK (limit_type IN ('soft', 'hard')), bytes_in_avail FLOAT NOT NULL, bytes_out_avail FLOAT NOT NULL, bytes_xfer_avail FLOAT NOT NULL, files_in_avail INT8 NOT NULL, files_out_avail INT8 NOT NULL, files_xfer_avail INT8 NOT NULL );
CREATE TABLE quotatallies ( name VARCHAR(30) NOT NULL, quota_type ENUM("user", "group", "class", "all") NOT NULL, bytes_in_used FLOAT NOT NULL, bytes_out_used FLOAT NOT NULL, bytes_xfer_used FLOAT NOT NULL, files_in_used INT UNSIGNED NOT NULL, files_out_used INT UNSIGNED NOT NULL, files_xfer_used INT UNSIGNED NOT NULL );
CREATE TABLE quotatallies ( name VARCHAR(32) NOT NULL, quota_type VARCHAR(8) NOT NULL CHECK (quota_type IN ('user','group','class','all')), bytes_in_used FLOAT NOT NULL, bytes_out_used FLOAT NOT NULL, bytes_xfer_used FLOAT NOT NULL, files_in_used INT8 NOT NULL, files_out_used INT8 NOT NULL, files_xfer_used INT8 NOT NULL );
mod_quotatab_sql treats any number zero or less for a bytes limit as "unlimited". Similarly, it treats a value of zero for any of the files limits as "unlimited". "Unlimited" values are ignored, in that any limit that is "unlimited" is not used in any of mod_quotatab's calculations. NULL values should be avoided whenever possible.