Hi Hervé and Willy,

Le Jeudi 14 Janvier 2010 09:31:29, Hervé COMMOWICK a écrit :
> I will try your "start of reflection" on "old" mysql server, stay up

Today I had a mysql 4.0.30 available so I could try the current git code.
I got all the elements I wanted so I took a little time this evening to get a 
more "stable" code than my previous test :

1. I think the packet is now compatible with Mysql 4.0 and over at least 
(tested whith mysql 4.0.30, 4.1.20 and 5.1.42)
2. The length verification has been modified (mysql 4.0 handshake 
initialization packet can be shorter than 52 bytes). Now, the length of the 
incoming data is compared to the packet length given in the header.

It could be still enhanced, for example to allow a configurable username, a 
password (bad idea I believe), SSL mysql connections (more complicated), ...

Please find the patch in attachment if you're interested.

-- 
Cyril Bonté
--- haproxy-HEAD/src/checks.c	2010-01-14 11:41:31.000000000 +0100
+++ haproxy-ss-20100113-mysql/src/checks.c	2010-01-14 22:15:08.000000000 +0100
@@ -47,6 +47,15 @@
 #include <proto/server.h>
 #include <proto/task.h>
 
+const char MYSQL40_HANDSHAKE_ACK[] =
+	"\x0F\x00\x00"	/* packet length */
+	"\x01"		/* packet number */
+	"\x00\x00"	/* client capabilities */
+	"\x00\x00\x01"	/* max packet */
+	"\x00"		/* username (null terminated string) */
+	"\x00\x00\x00\x00\x00\x00\x00\x00" /* scramble buff */
+	"\x00";		/* filler (always 0x00) */
+
 const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
 	[HCHK_STATUS_UNKNOWN]	= { SRV_CHK_UNKNOWN,                   "UNK",     "Unknown" },
 	[HCHK_STATUS_INI]	= { SRV_CHK_UNKNOWN,                   "INI",     "Initializing" },
@@ -867,11 +876,19 @@
 		/* MySQL Error packet always begin with field_count = 0xff
 		 * contrary to OK Packet who always begin whith 0x00 */
 		if (trash[4] != '\xff') {
+			unsigned int packet_len;
+			
+			/* Sends immediatly an authentication packet.
+			 * This will prevent haproxy to be blocked by the mysql server.
+			 */
+			send(fd, MYSQL40_HANDSHAKE_ACK, sizeof(MYSQL40_HANDSHAKE_ACK), MSG_DONTWAIT | MSG_NOSIGNAL);			
+				
 			/* We set the MySQL Version in description for information purpose
 			 * FIXME : it can be cool to use MySQL Version for other purpose,
 			 * like mark as down old MySQL server.
 			 */
-			if (len > 51) {
+			packet_len = ((unsigned int) trash[0]) + (((unsigned int) trash[1]) << 8) + (((unsigned int) trash[2]) << 16);
+			if (len == packet_len + 4) {
 				desc = ltrim(&trash[5], ' ');
 				set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
 			}

Reply via email to