1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2006-2017 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Andrey Hristov <andrey@php.net>                             |
16   |          Ulf Wendel <uw@php.net>                                     |
17   |          Georg Richter <georg@php.net>                               |
18   +----------------------------------------------------------------------+
19 */
20 
21 #ifndef MYSQLND_WIREPROTOCOL_H
22 #define MYSQLND_WIREPROTOCOL_H
23 
24 #include "mysqlnd_net.h"
25 
26 #define MYSQLND_HEADER_SIZE 4
27 #define COMPRESSED_HEADER_SIZE 3
28 
29 #define MYSQLND_NULL_LENGTH	(zend_ulong) ~0
30 
31 /* Used in mysqlnd_debug.c */
32 PHPAPI extern const char mysqlnd_read_header_name[];
33 PHPAPI extern const char mysqlnd_read_body_name[];
34 
35 
36 /* Packet handling */
37 #define PACKET_WRITE(packet, conn)	((packet)->header.m->write_to_net((packet), (conn)))
38 #define PACKET_READ(packet, conn)	((packet)->header.m->read_from_net((packet), (conn)))
39 #define PACKET_FREE(packet) \
40 	do { \
41 		DBG_INF_FMT("PACKET_FREE(%p)", packet); \
42 		if ((packet)) { \
43 			((packet)->header.m->free_mem((packet), FALSE)); \
44 		} \
45 	} while (0);
46 
47 PHPAPI extern const char * const mysqlnd_command_to_text[COM_END];
48 
49 /* Low-level extraction functionality */
50 typedef struct st_mysqlnd_packet_methods {
51 	size_t				struct_size;
52 	enum_func_status	(*read_from_net)(void * packet, MYSQLND_CONN_DATA * conn);
53 	size_t				(*write_to_net)(void * packet, MYSQLND_CONN_DATA * conn);
54 	void				(*free_mem)(void *packet, zend_bool stack_allocation);
55 } mysqlnd_packet_methods;
56 
57 
58 typedef struct st_mysqlnd_packet_header {
59 	size_t		size;
60 	mysqlnd_packet_methods *m;
61 	zend_uchar	packet_no;
62 	zend_bool	persistent;
63 } MYSQLND_PACKET_HEADER;
64 
65 /* Server greets the client */
66 typedef struct st_mysqlnd_packet_greet {
67 	MYSQLND_PACKET_HEADER		header;
68 	uint8_t		protocol_version;
69 	char		*server_version;
70 	uint32_t	thread_id;
71 	zend_uchar	intern_auth_plugin_data[SCRAMBLE_LENGTH];
72 	zend_uchar	* auth_plugin_data;
73 	size_t		auth_plugin_data_len;
74 	/* 1 byte pad */
75 	uint32_t	server_capabilities;
76 	uint8_t		charset_no;
77 	uint16_t	server_status;
78 	/* 13 byte pad, in 5.5 first 2 bytes are more capabilities followed by 1 byte scramble_length */
79 	zend_bool	pre41;
80 	/* If error packet, we use these */
81 	char 		error[MYSQLND_ERRMSG_SIZE+1];
82 	char 		sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
83 	unsigned int	error_no;
84 	char		*auth_protocol;
85 } MYSQLND_PACKET_GREET;
86 
87 
88 /* Client authenticates */
89 typedef struct st_mysqlnd_packet_auth {
90 	MYSQLND_PACKET_HEADER		header;
91 	const char	*user;
92 	const zend_uchar	*auth_data;
93 	size_t		auth_data_len;
94 	const char	*db;
95 	const char	*auth_plugin_name;
96 	uint32_t	client_flags;
97 	uint32_t	max_packet_size;
98 	uint8_t		charset_no;
99 	/* Here the packet ends. This is user supplied data */
100 	zend_bool	send_auth_data;
101 	zend_bool	is_change_user_packet;
102 	zend_bool	silent;
103 	HashTable	*connect_attr;
104 	size_t		db_len;
105 } MYSQLND_PACKET_AUTH;
106 
107 /* Auth response packet */
108 typedef struct st_mysqlnd_packet_auth_response {
109 	MYSQLND_PACKET_HEADER		header;
110 	uint8_t		response_code;
111 	uint64_t	affected_rows;
112 	uint64_t	last_insert_id;
113 	uint16_t	server_status;
114 	uint16_t	warning_count;
115 	char		*message;
116 	size_t		message_len;
117 	/* If error packet, we use these */
118 	char 		error[MYSQLND_ERRMSG_SIZE+1];
119 	char 		sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
120 	unsigned int 	error_no;
121 
122 	char		*new_auth_protocol;
123 	size_t		new_auth_protocol_len;
124 	zend_uchar	*new_auth_protocol_data;
125 	size_t		new_auth_protocol_data_len;
126 } MYSQLND_PACKET_AUTH_RESPONSE;
127 
128 
129 /* Auth response packet */
130 typedef struct st_mysqlnd_packet_change_auth_response {
131 	MYSQLND_PACKET_HEADER		header;
132 	const zend_uchar	*auth_data;
133 	size_t				auth_data_len;
134 } MYSQLND_PACKET_CHANGE_AUTH_RESPONSE;
135 
136 
137 /* OK packet */
138 typedef struct st_mysqlnd_packet_ok {
139 	MYSQLND_PACKET_HEADER		header;
140 	uint8_t		field_count; /* always 0x0 */
141 	uint64_t	affected_rows;
142 	uint64_t	last_insert_id;
143 	uint16_t	server_status;
144 	uint16_t	warning_count;
145 	char		*message;
146 	size_t		message_len;
147 	/* If error packet, we use these */
148 	char 		error[MYSQLND_ERRMSG_SIZE+1];
149 	char 		sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
150 	unsigned int 	error_no;
151 } MYSQLND_PACKET_OK;
152 
153 
154 /* Command packet */
155 typedef struct st_mysqlnd_packet_command {
156 	MYSQLND_PACKET_HEADER			header;
157 	enum php_mysqlnd_server_command	command;
158 	const zend_uchar				*argument;
159 	size_t							arg_len;
160 } MYSQLND_PACKET_COMMAND;
161 
162 
163 /* EOF packet */
164 typedef struct st_mysqlnd_packet_eof {
165 	MYSQLND_PACKET_HEADER		header;
166 	uint8_t		field_count; /* 0xFE */
167 	uint16_t	warning_count;
168 	uint16_t	server_status;
169 	/* If error packet, we use these */
170 	char 		error[MYSQLND_ERRMSG_SIZE+1];
171 	char 		sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
172 	unsigned int 	error_no;
173 } MYSQLND_PACKET_EOF;
174 /* EOF packet */
175 
176 
177 /* Result Set header*/
178 typedef struct st_mysqlnd_packet_rset_header {
179 	MYSQLND_PACKET_HEADER		header;
180 	/*
181 	  0x00 => ok
182 	  ~0   => LOAD DATA LOCAL
183 	  error_no != 0 => error
184 	  others => result set -> Read res_field packets up to field_count
185 	*/
186 	zend_ulong		field_count;
187 	/*
188 	  These are filled if no SELECT query. For SELECT warning_count
189 	  and server status are in the last row packet, the EOF packet.
190 	*/
191 	uint16_t	warning_count;
192 	uint16_t	server_status;
193 	uint64_t	affected_rows;
194 	uint64_t	last_insert_id;
195 	/* This is for both LOAD DATA or info, when no result set */
196 	char		*info_or_local_file;
197 	size_t		info_or_local_file_len;
198 	/* If error packet, we use these */
199 	MYSQLND_ERROR_INFO	error_info;
200 } MYSQLND_PACKET_RSET_HEADER;
201 
202 
203 /* Result set field packet */
204 typedef struct st_mysqlnd_packet_res_field {
205 	MYSQLND_PACKET_HEADER	header;
206 	MYSQLND_FIELD			*metadata;
207 	/* For table definitions, empty for result sets */
208 	zend_bool				skip_parsing;
209 	zend_bool				stupid_list_fields_eof;
210 	zend_bool				persistent_alloc;
211 
212 	MYSQLND_ERROR_INFO		error_info;
213 } MYSQLND_PACKET_RES_FIELD;
214 
215 
216 /* Row packet */
217 typedef struct st_mysqlnd_packet_row {
218 	MYSQLND_PACKET_HEADER	header;
219 	zval		*fields;
220 	uint32_t	field_count;
221 	zend_bool	eof;
222 	/*
223 	  These are, of course, only for SELECT in the EOF packet,
224 	  which is detected by this packet
225 	*/
226 	uint16_t	warning_count;
227 	uint16_t	server_status;
228 
229 	struct st_mysqlnd_memory_pool_chunk	*row_buffer;
230 	MYSQLND_MEMORY_POOL * result_set_memory_pool;
231 
232 	zend_bool		skip_extraction;
233 	zend_bool		binary_protocol;
234 	zend_bool		persistent_alloc;
235 	MYSQLND_FIELD	*fields_metadata;
236 	/* We need this to alloc bigger bufs in non-PS mode */
237 	unsigned int	bit_fields_count;
238 	size_t			bit_fields_total_len; /* trailing \0 not counted */
239 
240 	/* If error packet, we use these */
241 	MYSQLND_ERROR_INFO	error_info;
242 } MYSQLND_PACKET_ROW;
243 
244 
245 /* Statistics packet */
246 typedef struct st_mysqlnd_packet_stats {
247 	MYSQLND_PACKET_HEADER	header;
248 	char *message;
249 	/* message_len is not part of the packet*/
250 	size_t message_len;
251 } MYSQLND_PACKET_STATS;
252 
253 
254 /* COM_PREPARE response packet */
255 typedef struct st_mysqlnd_packet_prepare_response {
256 	MYSQLND_PACKET_HEADER	header;
257 	/* also known as field_count 0x00=OK , 0xFF=error */
258 	unsigned char	error_code;
259 	zend_ulong	stmt_id;
260 	unsigned int	field_count;
261 	unsigned int	param_count;
262 	unsigned int	warning_count;
263 
264 	/* present in case of error */
265 	MYSQLND_ERROR_INFO	error_info;
266 } MYSQLND_PACKET_PREPARE_RESPONSE;
267 
268 
269 /* Statistics packet */
270 typedef struct st_mysqlnd_packet_chg_user_resp {
271 	MYSQLND_PACKET_HEADER	header;
272 	uint32_t			response_code;
273 
274 	/* message_len is not part of the packet*/
275 	uint16_t			server_capabilities;
276 	/* If error packet, we use these */
277 	MYSQLND_ERROR_INFO	error_info;
278 	zend_bool			server_asked_323_auth;
279 
280 	char		*new_auth_protocol;
281 	size_t		new_auth_protocol_len;
282 	zend_uchar	*new_auth_protocol_data;
283 	size_t		new_auth_protocol_data_len;
284 } MYSQLND_PACKET_CHG_USER_RESPONSE;
285 
286 
287 /* Command packet */
288 typedef struct st_mysqlnd_packet_sha256_pk_request {
289 	MYSQLND_PACKET_HEADER			header;
290 } MYSQLND_PACKET_SHA256_PK_REQUEST;
291 
292 typedef struct  st_mysqlnd_packet_sha256_pk_request_response {
293 	MYSQLND_PACKET_HEADER	header;
294 	zend_uchar 				*public_key;
295 	size_t					public_key_len;
296 } MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE;
297 
298 
299 PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
300 
301 zend_ulong	php_mysqlnd_net_field_length(zend_uchar **packet);
302 zend_uchar *	php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
303 size_t			php_mysqlnd_net_store_length_size(uint64_t length);
304 
305 PHPAPI const extern char * const mysqlnd_empty_string;
306 
307 enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
308 										 unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
309 										 zend_bool as_int_or_float, MYSQLND_STATS * stats);
310 
311 
312 enum_func_status php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
313 										 unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
314 										 zend_bool as_int_or_float, MYSQLND_STATS * stats);
315 
316 enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
317 										 unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
318 										 zend_bool as_int_or_float, MYSQLND_STATS * stats);
319 
320 
321 PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent);
322 PHPAPI void mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol);
323 
324 #endif /* MYSQLND_WIREPROTOCOL_H */
325 
326 /*
327  * Local variables:
328  * tab-width: 4
329  * c-basic-offset: 4
330  * End:
331  * vim600: noet sw=4 ts=4 fdm=marker
332  * vim<600: noet sw=4 ts=4
333  */
334