1 /* Copyright (c) 2011, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_host_cache.cc
25 Table HOST_CACHE (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "table_host_cache.h"
31 #include "hostname.h"
32 #include "field.h"
33 #include "sql_class.h"
34
35 THR_LOCK table_host_cache::m_table_lock;
36
37 static const TABLE_FIELD_TYPE field_types[]=
38 {
39 {
40 { C_STRING_WITH_LEN("IP") },
41 { C_STRING_WITH_LEN("varchar(64)") },
42 { NULL, 0}
43 },
44 {
45 { C_STRING_WITH_LEN("HOST") },
46 { C_STRING_WITH_LEN("varchar(255)") },
47 { NULL, 0}
48 },
49 {
50 { C_STRING_WITH_LEN("HOST_VALIDATED") },
51 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
52 { NULL, 0}
53 },
54 {
55 { C_STRING_WITH_LEN("SUM_CONNECT_ERRORS") },
56 { C_STRING_WITH_LEN("bigint(20)") },
57 { NULL, 0}
58 },
59 {
60 { C_STRING_WITH_LEN("COUNT_HOST_BLOCKED_ERRORS") },
61 { C_STRING_WITH_LEN("bigint(20)") },
62 { NULL, 0}
63 },
64 {
65 { C_STRING_WITH_LEN("COUNT_NAMEINFO_TRANSIENT_ERRORS") },
66 { C_STRING_WITH_LEN("bigint(20)") },
67 { NULL, 0}
68 },
69 {
70 { C_STRING_WITH_LEN("COUNT_NAMEINFO_PERMANENT_ERRORS") },
71 { C_STRING_WITH_LEN("bigint(20)") },
72 { NULL, 0}
73 },
74 {
75 { C_STRING_WITH_LEN("COUNT_FORMAT_ERRORS") },
76 { C_STRING_WITH_LEN("bigint(20)") },
77 { NULL, 0}
78 },
79 {
80 { C_STRING_WITH_LEN("COUNT_ADDRINFO_TRANSIENT_ERRORS") },
81 { C_STRING_WITH_LEN("bigint(20)") },
82 { NULL, 0}
83 },
84 {
85 { C_STRING_WITH_LEN("COUNT_ADDRINFO_PERMANENT_ERRORS") },
86 { C_STRING_WITH_LEN("bigint(20)") },
87 { NULL, 0}
88 },
89 {
90 { C_STRING_WITH_LEN("COUNT_FCRDNS_ERRORS") },
91 { C_STRING_WITH_LEN("bigint(20)") },
92 { NULL, 0}
93 },
94 {
95 { C_STRING_WITH_LEN("COUNT_HOST_ACL_ERRORS") },
96 { C_STRING_WITH_LEN("bigint(20)") },
97 { NULL, 0}
98 },
99 {
100 { C_STRING_WITH_LEN("COUNT_NO_AUTH_PLUGIN_ERRORS") },
101 { C_STRING_WITH_LEN("bigint(20)") },
102 { NULL, 0}
103 },
104 {
105 { C_STRING_WITH_LEN("COUNT_AUTH_PLUGIN_ERRORS") },
106 { C_STRING_WITH_LEN("bigint(20)") },
107 { NULL, 0}
108 },
109 {
110 { C_STRING_WITH_LEN("COUNT_HANDSHAKE_ERRORS") },
111 { C_STRING_WITH_LEN("bigint(20)") },
112 { NULL, 0}
113 },
114 {
115 { C_STRING_WITH_LEN("COUNT_PROXY_USER_ERRORS") },
116 { C_STRING_WITH_LEN("bigint(20)") },
117 { NULL, 0}
118 },
119 {
120 { C_STRING_WITH_LEN("COUNT_PROXY_USER_ACL_ERRORS") },
121 { C_STRING_WITH_LEN("bigint(20)") },
122 { NULL, 0}
123 },
124 {
125 { C_STRING_WITH_LEN("COUNT_AUTHENTICATION_ERRORS") },
126 { C_STRING_WITH_LEN("bigint(20)") },
127 { NULL, 0}
128 },
129 {
130 { C_STRING_WITH_LEN("COUNT_SSL_ERRORS") },
131 { C_STRING_WITH_LEN("bigint(20)") },
132 { NULL, 0}
133 },
134 {
135 { C_STRING_WITH_LEN("COUNT_MAX_USER_CONNECTIONS_ERRORS") },
136 { C_STRING_WITH_LEN("bigint(20)") },
137 { NULL, 0}
138 },
139 {
140 { C_STRING_WITH_LEN("COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS") },
141 { C_STRING_WITH_LEN("bigint(20)") },
142 { NULL, 0}
143 },
144 {
145 { C_STRING_WITH_LEN("COUNT_DEFAULT_DATABASE_ERRORS") },
146 { C_STRING_WITH_LEN("bigint(20)") },
147 { NULL, 0}
148 },
149 {
150 { C_STRING_WITH_LEN("COUNT_INIT_CONNECT_ERRORS") },
151 { C_STRING_WITH_LEN("bigint(20)") },
152 { NULL, 0}
153 },
154 {
155 { C_STRING_WITH_LEN("COUNT_LOCAL_ERRORS") },
156 { C_STRING_WITH_LEN("bigint(20)") },
157 { NULL, 0}
158 },
159 {
160 { C_STRING_WITH_LEN("COUNT_UNKNOWN_ERRORS") },
161 { C_STRING_WITH_LEN("bigint(20)") },
162 { NULL, 0}
163 },
164 {
165 { C_STRING_WITH_LEN("FIRST_SEEN") },
166 { C_STRING_WITH_LEN("timestamp") },
167 { NULL, 0}
168 },
169 {
170 { C_STRING_WITH_LEN("LAST_SEEN") },
171 { C_STRING_WITH_LEN("timestamp") },
172 { NULL, 0}
173 },
174 {
175 { C_STRING_WITH_LEN("FIRST_ERROR_SEEN") },
176 { C_STRING_WITH_LEN("timestamp") },
177 { NULL, 0}
178 },
179 {
180 { C_STRING_WITH_LEN("LAST_ERROR_SEEN") },
181 { C_STRING_WITH_LEN("timestamp") },
182 { NULL, 0}
183 }
184 };
185
186 TABLE_FIELD_DEF
187 table_host_cache::m_field_def=
188 { 29, field_types };
189
190 PFS_engine_table_share
191 table_host_cache::m_share=
192 {
193 { C_STRING_WITH_LEN("host_cache") },
194 &pfs_truncatable_acl,
195 table_host_cache::create,
196 NULL, /* write_row */
197 table_host_cache::delete_all_rows,
198 table_host_cache::get_row_count,
199 sizeof(PFS_simple_index), /* ref length */
200 &m_table_lock,
201 &m_field_def,
202 false, /* checked */
203 false /* perpetual */
204 };
205
create(void)206 PFS_engine_table* table_host_cache::create(void)
207 {
208 table_host_cache *t= new table_host_cache();
209 if (t != NULL)
210 {
211 THD *thd= current_thd;
212 assert(thd != NULL);
213 t->materialize(thd);
214 }
215 return t;
216 }
217
218 int
delete_all_rows(void)219 table_host_cache::delete_all_rows(void)
220 {
221 /*
222 TRUNCATE TABLE performance_schema.host_cache
223 is an alternate syntax for
224 FLUSH HOSTS
225 */
226 hostname_cache_refresh();
227 return 0;
228 }
229
230 ha_rows
get_row_count(void)231 table_host_cache::get_row_count(void)
232 {
233 ha_rows count;
234 hostname_cache_lock();
235 count= hostname_cache_size();
236 hostname_cache_unlock();
237 return count;
238 }
239
table_host_cache()240 table_host_cache::table_host_cache()
241 : PFS_engine_table(&m_share, &m_pos),
242 m_all_rows(NULL), m_row_count(0),
243 m_row(NULL), m_pos(0), m_next_pos(0)
244 {}
245
materialize(THD * thd)246 void table_host_cache::materialize(THD *thd)
247 {
248 Host_entry *current;
249 Host_entry *first;
250 uint size;
251 uint index;
252 row_host_cache *rows;
253 row_host_cache *row;
254
255 assert(m_all_rows == NULL);
256 assert(m_row_count == 0);
257
258 hostname_cache_lock();
259
260 size= hostname_cache_size();
261 if (size == 0)
262 {
263 /* Normal case, the cache is empty. */
264 goto end;
265 }
266
267 rows= (row_host_cache*) thd->alloc(size * sizeof(row_host_cache));
268 if (rows == NULL)
269 {
270 /* Out of memory, this thread will error out. */
271 goto end;
272 }
273
274 index= 0;
275 row= rows;
276
277 first= hostname_cache_first();
278 current= first;
279
280 while ((current != NULL) && (index < size))
281 {
282 make_row(current, row);
283 index++;
284 row++;
285 current= current->next();
286 }
287
288 m_all_rows= rows;
289 m_row_count= index;
290
291 end:
292 hostname_cache_unlock();
293 }
294
make_row(Host_entry * entry,row_host_cache * row)295 void table_host_cache::make_row(Host_entry *entry, row_host_cache *row)
296 {
297 row->m_ip_length= strlen(entry->ip_key);
298 strcpy(row->m_ip, entry->ip_key);
299 row->m_hostname_length= entry->m_hostname_length;
300 if (row->m_hostname_length > 0)
301 strncpy(row->m_hostname, entry->m_hostname, row->m_hostname_length);
302 row->m_host_validated= entry->m_host_validated;
303 row->m_sum_connect_errors= entry->m_errors.m_connect;
304 row->m_count_host_blocked_errors= entry->m_errors.m_host_blocked;
305 row->m_count_nameinfo_transient_errors= entry->m_errors.m_nameinfo_transient;
306 row->m_count_nameinfo_permanent_errors= entry->m_errors.m_nameinfo_permanent;
307 row->m_count_format_errors= entry->m_errors.m_format;
308 row->m_count_addrinfo_transient_errors= entry->m_errors.m_addrinfo_transient;
309 row->m_count_addrinfo_permanent_errors= entry->m_errors.m_addrinfo_permanent;
310 row->m_count_fcrdns_errors= entry->m_errors.m_FCrDNS;
311 row->m_count_host_acl_errors= entry->m_errors.m_host_acl;
312 row->m_count_no_auth_plugin_errors= entry->m_errors.m_no_auth_plugin;
313 row->m_count_auth_plugin_errors= entry->m_errors.m_auth_plugin;
314 row->m_count_handshake_errors= entry->m_errors.m_handshake;
315 row->m_count_proxy_user_errors= entry->m_errors.m_proxy_user;
316 row->m_count_proxy_user_acl_errors= entry->m_errors.m_proxy_user_acl;
317 row->m_count_authentication_errors= entry->m_errors.m_authentication;
318 row->m_count_ssl_errors= entry->m_errors.m_ssl;
319 row->m_count_max_user_connection_errors= entry->m_errors.m_max_user_connection;
320 row->m_count_max_user_connection_per_hour_errors= entry->m_errors.m_max_user_connection_per_hour;
321 row->m_count_default_database_errors= entry->m_errors.m_default_database;
322 row->m_count_init_connect_errors= entry->m_errors.m_init_connect;
323 row->m_count_local_errors= entry->m_errors.m_local;
324
325 /*
326 Reserved for future use, to help with backward compatibility.
327 When new errors are added in entry->m_errors.m_xxx,
328 report them in this column (GA releases),
329 until the table HOST_CACHE structure can be extended (next development version).
330 */
331 row->m_count_unknown_errors= 0;
332
333 row->m_first_seen= entry->m_first_seen;
334 row->m_last_seen= entry->m_last_seen;
335 row->m_first_error_seen= entry->m_first_error_seen;
336 row->m_last_error_seen= entry->m_last_error_seen;
337 }
338
reset_position(void)339 void table_host_cache::reset_position(void)
340 {
341 m_pos.m_index= 0;
342 m_next_pos.m_index= 0;
343 }
344
rnd_next(void)345 int table_host_cache::rnd_next(void)
346 {
347 int result;
348
349 m_pos.set_at(&m_next_pos);
350
351 if (m_pos.m_index < m_row_count)
352 {
353 m_row= &m_all_rows[m_pos.m_index];
354 m_next_pos.set_after(&m_pos);
355 result= 0;
356 }
357 else
358 {
359 m_row= NULL;
360 result= HA_ERR_END_OF_FILE;
361 }
362
363 return result;
364 }
365
rnd_pos(const void * pos)366 int table_host_cache::rnd_pos(const void *pos)
367 {
368 set_position(pos);
369 assert(m_pos.m_index < m_row_count);
370 m_row= &m_all_rows[m_pos.m_index];
371 return 0;
372 }
373
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)374 int table_host_cache::read_row_values(TABLE *table,
375 unsigned char *buf,
376 Field **fields,
377 bool read_all)
378 {
379 Field *f;
380
381 assert(m_row);
382
383 /* Set the null bits */
384 assert(table->s->null_bytes == 1);
385 buf[0]= 0;
386
387 for (; (f= *fields) ; fields++)
388 {
389 if (read_all || bitmap_is_set(table->read_set, f->field_index))
390 {
391 switch(f->field_index)
392 {
393 case 0: /* IP */
394 set_field_varchar_utf8(f, m_row->m_ip, m_row->m_ip_length);
395 break;
396 case 1: /* HOST */
397 if (m_row->m_hostname_length > 0)
398 set_field_varchar_utf8(f, m_row->m_hostname, m_row->m_hostname_length);
399 else
400 f->set_null();
401 break;
402 case 2: /* HOST_VALIDATED */
403 set_field_enum(f, m_row->m_host_validated ? ENUM_YES : ENUM_NO);
404 break;
405 case 3: /* SUM_CONNECT_ERRORS */
406 set_field_ulonglong(f, m_row->m_sum_connect_errors);
407 break;
408 case 4: /* COUNT_HOST_BLOCKED_ERRORS. */
409 set_field_ulonglong(f, m_row->m_count_host_blocked_errors);
410 break;
411 case 5: /* COUNT_NAMEINFO_TRANSIENT_ERRORS */
412 set_field_ulonglong(f, m_row->m_count_nameinfo_transient_errors);
413 break;
414 case 6: /* COUNT_NAMEINFO_PERSISTENT_ERRORS */
415 set_field_ulonglong(f, m_row->m_count_nameinfo_permanent_errors);
416 break;
417 case 7: /* COUNT_FORMAT_ERRORS */
418 set_field_ulonglong(f, m_row->m_count_format_errors);
419 break;
420 case 8: /* COUNT_ADDRINFO_TRANSIENT_ERRORS */
421 set_field_ulonglong(f, m_row->m_count_addrinfo_transient_errors);
422 break;
423 case 9: /* COUNT_ADDRINFO_PERSISTENT_ERRORS */
424 set_field_ulonglong(f, m_row->m_count_addrinfo_permanent_errors);
425 break;
426 case 10: /* COUNT_FCRDNS_ERRORS */
427 set_field_ulonglong(f, m_row->m_count_fcrdns_errors);
428 break;
429 case 11: /* COUNT_HOST_ACL_ERRORS */
430 set_field_ulonglong(f, m_row->m_count_host_acl_errors);
431 break;
432 case 12: /* COUNT_NO_AUTH_PLUGIN_ERRORS */
433 set_field_ulonglong(f, m_row->m_count_no_auth_plugin_errors);
434 break;
435 case 13: /* COUNT_AUTH_PLUGIN_ERRORS */
436 set_field_ulonglong(f, m_row->m_count_auth_plugin_errors);
437 break;
438 case 14: /* COUNT_HANDSHAKE_ERRORS */
439 set_field_ulonglong(f, m_row->m_count_handshake_errors);
440 break;
441 case 15: /* COUNT_PROXY_USER_ERRORS */
442 set_field_ulonglong(f, m_row->m_count_proxy_user_errors);
443 break;
444 case 16: /* COUNT_PROXY_USER_ACL_ERRORS */
445 set_field_ulonglong(f, m_row->m_count_proxy_user_acl_errors);
446 break;
447 case 17: /* COUNT_AUTHENTICATION_ERRORS */
448 set_field_ulonglong(f, m_row->m_count_authentication_errors);
449 break;
450 case 18: /* COUNT_SSL_ERRORS */
451 set_field_ulonglong(f, m_row->m_count_ssl_errors);
452 break;
453 case 19: /* COUNT_MAX_USER_CONNECTION_ERRORS */
454 set_field_ulonglong(f, m_row->m_count_max_user_connection_errors);
455 break;
456 case 20: /* COUNT_MAX_USER_CONNECTION_PER_HOUR_ERRORS */
457 set_field_ulonglong(f, m_row->m_count_max_user_connection_per_hour_errors);
458 break;
459 case 21: /* COUNT_DEFAULT_DATABASE_ERRORS */
460 set_field_ulonglong(f, m_row->m_count_default_database_errors);
461 break;
462 case 22: /* COUNT_INIT_CONNECT_ERRORS */
463 set_field_ulonglong(f, m_row->m_count_init_connect_errors);
464 break;
465 case 23: /* COUNT_LOCAL_ERRORS */
466 set_field_ulonglong(f, m_row->m_count_local_errors);
467 break;
468 case 24: /* COUNT_UNKNOWN_ERRORS */
469 set_field_ulonglong(f, m_row->m_count_unknown_errors);
470 break;
471 case 25: /* FIRST_SEEN */
472 set_field_timestamp(f, m_row->m_first_seen);
473 break;
474 case 26: /* LAST_SEEN */
475 set_field_timestamp(f, m_row->m_last_seen);
476 break;
477 case 27: /* FIRST_ERROR_SEEN */
478 if (m_row->m_first_error_seen != 0)
479 set_field_timestamp(f, m_row->m_first_error_seen);
480 else
481 f->set_null();
482 break;
483 case 28: /* LAST_ERROR_SEEN */
484 if (m_row->m_last_error_seen != 0)
485 set_field_timestamp(f, m_row->m_last_error_seen);
486 else
487 f->set_null();
488 break;
489 default:
490 assert(false);
491 }
492 }
493 }
494
495 return 0;
496 }
497
498