netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeremy Sowden <jeremy@azazel.net>
To: Netfilter Devel <netfilter-devel@vger.kernel.org>
Subject: [PATCH ulogd2 v2 v2 29/34] output: mysql: add prep & exec support
Date: Tue, 29 Nov 2022 21:47:44 +0000	[thread overview]
Message-ID: <20221129214749.247878-30-jeremy@azazel.net> (raw)
In-Reply-To: <20221129214749.247878-1-jeremy@azazel.net>

Now that the common DB API offers prep & exec support, update the MySQL
plug-in to use it.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 output/mysql/ulogd_output_MYSQL.c | 163 ++++++++++++++++++++++++------
 1 file changed, 131 insertions(+), 32 deletions(-)

diff --git a/output/mysql/ulogd_output_MYSQL.c b/output/mysql/ulogd_output_MYSQL.c
index bed1d7488019..d64da85a418a 100644
--- a/output/mysql/ulogd_output_MYSQL.c
+++ b/output/mysql/ulogd_output_MYSQL.c
@@ -37,11 +37,12 @@
  * 	Port to ulogd2 (@ 0sec conference, Bern, Suisse)
  */
 
+#include <assert.h>
+#ifdef DEBUG_MYSQL
+#include <stdio.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <arpa/inet.h>
 #include <mysql/mysql.h>
 #include <ulogd/ulogd.h>
 #include <ulogd/conffile.h>
@@ -56,6 +57,12 @@
 struct mysql_instance {
 	struct db_instance db_inst;
 	MYSQL *dbh; /* the database handle we are using */
+	MYSQL_STMT *sth;
+};
+
+struct mysql_buffer {
+	unsigned long length;
+	my_bool is_null;
 };
 
 /* our configuration directives */
@@ -193,46 +200,138 @@ static int open_db_mysql(struct ulogd_pluginstance *upi)
 	return 0;
 }
 
-static int escape_string_mysql(struct ulogd_pluginstance *upi,
-				char *dst, const char *src, unsigned int len)
+static int prepare_mysql(struct ulogd_pluginstance *upi,
+			 const struct db_stmt *stmt)
 {
 	struct mysql_instance *mi = (struct mysql_instance *) upi->private;
 
-#ifdef OLD_MYSQL
-	return mysql_escape_string(dst, src, len);
-#else
-	return mysql_real_escape_string(mi->dbh, dst, src, len);
-#endif /* OLD_MYSQL */
+	if (mi->sth)
+		mysql_stmt_close(mi->sth);
+
+	if (!(mi->sth = mysql_stmt_init(mi->dbh))) {
+		ulogd_log(ULOGD_ERROR,
+			  "Failed to initialize statement: %s\n",
+			  mysql_error(mi->dbh));
+		return -1;
+	}
+
+	if (mysql_stmt_prepare(mi->sth, stmt->sql, stmt->len) != 0) {
+		ulogd_log(ULOGD_ERROR,
+			  "Failed to prepare statement: %s\n",
+			  mysql_stmt_error(mi->sth));
+		return -1;
+	}
+
+	return 0;
 }
 
 static int execute_mysql(struct ulogd_pluginstance *upi,
 			 const struct db_stmt *stmt)
 {
 	struct mysql_instance *mi = (struct mysql_instance *) upi->private;
-	int ret;
-	MYSQL_RES * result;
+	struct mysql_buffer *buffers;
+	MYSQL_BIND *bindings;
+	unsigned int i;
+	int rv = -1;
 
-	ret = mysql_real_query(mi->dbh, stmt->sql, stmt->len);
-	if (ret) {
-		ulogd_log(ULOGD_ERROR, "execute failed (%s)\n",
-			  mysql_error(mi->dbh));
-		return -1;
+	if (!(bindings = calloc(stmt->nr_params, sizeof(*bindings))))
+		goto err_return;
+
+	if (!(buffers = calloc(stmt->nr_params, sizeof(*buffers))))
+		goto err_free_bindings;
+
+	for (i = 0; i < stmt->nr_params; i++) {
+		struct db_stmt_arg *arg = &stmt->args[i];
+		union db_stmt_arg_value *val = &arg->value;
+
+		if (arg->null) {
+			bindings[i++].buffer_type = MYSQL_TYPE_NULL;
+			continue;
+		}
+
+		switch (arg->type) {
+		case ULOGD_RET_BOOL:
+		case ULOGD_RET_INT8:
+		case ULOGD_RET_UINT8:
+			bindings[i].buffer_type = MYSQL_TYPE_TINY;
+			bindings[i].buffer = val;
+			bindings[i].is_unsigned = arg->type != ULOGD_RET_INT8;
+			break;
+		case ULOGD_RET_INT16:
+		case ULOGD_RET_UINT16:
+			bindings[i].buffer_type = MYSQL_TYPE_SHORT;
+			bindings[i].buffer = val;
+			bindings[i].is_unsigned = arg->type != ULOGD_RET_INT16;
+			break;
+		case ULOGD_RET_INT32:
+		case ULOGD_RET_UINT32:
+		case ULOGD_RET_IPADDR:
+			bindings[i].buffer_type = MYSQL_TYPE_LONG;
+			bindings[i].buffer = val;
+			bindings[i].is_unsigned = arg->type != ULOGD_RET_INT32;
+			break;
+		case ULOGD_RET_INT64:
+		case ULOGD_RET_UINT64:
+			bindings[i].buffer_type = MYSQL_TYPE_LONGLONG;
+			bindings[i].buffer = val;
+			bindings[i].is_unsigned = arg->type != ULOGD_RET_INT64;
+			break;
+		case ULOGD_RET_STRING:
+			bindings[i].buffer_type = MYSQL_TYPE_STRING;
+			bindings[i].is_null = &buffers[i].is_null;
+			bindings[i].length = &buffers[i].length;
+			if (val->ptr) {
+				bindings[i].buffer = val->ptr;
+				bindings[i].buffer_length = arg->len + 1;
+				buffers[i].length = arg->len;
+			} else
+				buffers[i].is_null = 1;
+			break;
+		case ULOGD_RET_RAWSTR:
+			bindings[i].buffer_type = MYSQL_TYPE_BLOB;
+			bindings[i].is_null = &buffers[i].is_null;
+			bindings[i].length = &buffers[i].length;
+			if (val->ptr) {
+				bindings[i].buffer = val->ptr;
+				bindings[i].buffer_length = arg->len;
+				buffers[i].length = arg->len;
+			} else
+				buffers[i].is_null = 1;
+			break;
+		}
 	}
-	result = mysql_use_result(mi->dbh);
-	if (result) {
-		mysql_free_result(result);
+
+	if (mysql_stmt_bind_param(mi->sth, bindings) != 0) {
+		ulogd_log(ULOGD_ERROR,
+			  "Failed to bind statement parameters: %s\n",
+			  mysql_stmt_error(mi->sth));
+		goto err_free_buffers;
 	}
 
-	return 0;
+	if (mysql_stmt_execute(mi->sth) != 0) {
+		ulogd_log(ULOGD_ERROR,
+			  "Failed to execute statement: %s\n",
+			  mysql_stmt_error(mi->sth));
+		goto err_free_buffers;
+	}
+
+	rv = 0;
+
+err_free_buffers:
+	free (buffers);
+err_free_bindings:
+	free (bindings);
+err_return:
+	return rv;
 }
 
 static struct db_driver db_driver_mysql = {
-	.get_columns	= &get_columns_mysql,
-	.get_column	= &get_column_mysql,
-	.open_db	= &open_db_mysql,
-	.close_db	= &close_db_mysql,
-	.escape_string	= &escape_string_mysql,
-	.execute	= &execute_mysql,
+	.get_columns	= get_columns_mysql,
+	.get_column	= get_column_mysql,
+	.open_db	= open_db_mysql,
+	.close_db	= close_db_mysql,
+	.prepare	= prepare_mysql,
+	.execute	= execute_mysql,
 };
 
 static int configure_mysql(struct ulogd_pluginstance *upi,
@@ -254,11 +353,11 @@ static struct ulogd_plugin plugin_mysql = {
 	},
 	.config_kset = &kset_mysql,
 	.priv_size   = sizeof(struct mysql_instance),
-	.configure   = &configure_mysql,
-	.start	     = &ulogd_db_start,
-	.stop	     = &ulogd_db_stop,
-	.signal	     = &ulogd_db_signal,
-	.interp	     = &ulogd_db_interp,
+	.configure   = configure_mysql,
+	.start	     = ulogd_db_start,
+	.stop	     = ulogd_db_stop,
+	.signal	     = ulogd_db_signal,
+	.interp	     = ulogd_db_interp,
 	.version     = VERSION,
 };
 
-- 
2.35.1


  parent reply	other threads:[~2022-11-29 21:59 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-29 21:47 [PATCH ulogd2 v2 v2 00/34] Refactor of the DB output plug-ins Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 01/34] ulogd: fix parse-error check Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 02/34] filter: fix buffer sizes in filter plug-ins Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 03/34] output: JSON: remove incorrect config value check Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 04/34] db: fix back-log capacity checks Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 05/34] build: add checks to configure.ac Jeremy Sowden
2022-11-30 10:04   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 06/34] src: remove some trailing white space Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 07/34] src: remove zero-valued config-key fields Jeremy Sowden
2022-11-30 10:21   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 08/34] src: parenthesize config-entry macro arguments Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 09/34] src: define constructors and destructors consistently Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 10/34] src: remove `TIME_ERR` macro Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 11/34] src: remove superfluous casts Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 12/34] conffile: replace malloc+strcpy with strdup Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 13/34] output: remove zero-initialized `struct ulogd_plugin` members Jeremy Sowden
2022-11-30 10:26   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 14/34] output: de-duplicate allocation of input keys Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 15/34] db: reorganize source Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 16/34] db: use consistent integer return values to indicate errors Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 17/34] db: change return type of two functions to `void` Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 18/34] db: open-code `_loop_reconnect_db` Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 19/34] db: improve calculation of sql statement length Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 20/34] db: refactor configuration Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 21/34] db: refactor ring-buffer initialization Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 22/34] db: refactor ring-buffer Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 23/34] db: refactor backlog Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 24/34] db: use `struct db_stmt` objects more widely Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 25/34] db: synchronize access to ring-buffer Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 26/34] db: avoid cancelling ring-buffer thread Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 27/34] db, IP2BIN: defer formatting of raw strings Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 28/34] db: add prep & exec support Jeremy Sowden
2022-11-29 21:47 ` Jeremy Sowden [this message]
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 30/34] output: pgsql: remove a couple of struct members Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 31/34] output: pgsql: remove variable-length arrays Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 32/34] output: pgsql: tidy up `open_db_pgsql` and fix memory leak Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 33/34] output: pgsql: add prep & exec support Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 34/34] output: sqlite3: reimplement using the common DB API Jeremy Sowden
2022-11-30 10:27 ` [PATCH ulogd2 v2 v2 00/34] Refactor of the DB output plug-ins Pablo Neira Ayuso
2022-11-30 16:03   ` Jeremy Sowden

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221129214749.247878-30-jeremy@azazel.net \
    --to=jeremy@azazel.net \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).