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