| 1 | /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. |
| 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 as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 15 | |
| 16 | #ifndef HOSTNAME_INCLUDED |
| 17 | #define HOSTNAME_INCLUDED |
| 18 | |
| 19 | #include "my_net.h" |
| 20 | #include "hash_filo.h" |
| 21 | |
| 22 | struct Host_errors |
| 23 | { |
| 24 | public: |
| 25 | Host_errors(); |
| 26 | ~Host_errors(); |
| 27 | |
| 28 | void reset(); |
| 29 | void aggregate(const Host_errors *errors); |
| 30 | |
| 31 | /** Number of connect errors. */ |
| 32 | ulong m_connect; |
| 33 | |
| 34 | /** Number of host blocked errors. */ |
| 35 | ulong m_host_blocked; |
| 36 | /** Number of transient errors from getnameinfo(). */ |
| 37 | ulong m_nameinfo_transient; |
| 38 | /** Number of permanent errors from getnameinfo(). */ |
| 39 | ulong m_nameinfo_permanent; |
| 40 | /** Number of errors from is_hostname_valid(). */ |
| 41 | ulong m_format; |
| 42 | /** Number of transient errors from getaddrinfo(). */ |
| 43 | ulong m_addrinfo_transient; |
| 44 | /** Number of permanent errors from getaddrinfo(). */ |
| 45 | ulong m_addrinfo_permanent; |
| 46 | /** Number of errors from Forward-Confirmed reverse DNS checks. */ |
| 47 | ulong m_FCrDNS; |
| 48 | /** Number of errors from host grants. */ |
| 49 | ulong m_host_acl; |
| 50 | /** Number of errors from missing auth plugin. */ |
| 51 | ulong m_no_auth_plugin; |
| 52 | /** Number of errors from auth plugin. */ |
| 53 | ulong m_auth_plugin; |
| 54 | /** Number of errors from authentication plugins. */ |
| 55 | ulong m_handshake; |
| 56 | /** Number of errors from proxy user. */ |
| 57 | ulong m_proxy_user; |
| 58 | /** Number of errors from proxy user acl. */ |
| 59 | ulong m_proxy_user_acl; |
| 60 | /** Number of errors from authentication. */ |
| 61 | ulong m_authentication; |
| 62 | /** Number of errors from ssl. */ |
| 63 | ulong m_ssl; |
| 64 | /** Number of errors from max user connection. */ |
| 65 | ulong m_max_user_connection; |
| 66 | /** Number of errors from max user connection per hour. */ |
| 67 | ulong m_max_user_connection_per_hour; |
| 68 | /** Number of errors from the default database. */ |
| 69 | ulong m_default_database; |
| 70 | /** Number of errors from init_connect. */ |
| 71 | ulong m_init_connect; |
| 72 | /** Number of errors from the server itself. */ |
| 73 | ulong m_local; |
| 74 | |
| 75 | bool has_error() const |
| 76 | { |
| 77 | return ((m_host_blocked != 0) |
| 78 | || (m_nameinfo_transient != 0) |
| 79 | || (m_nameinfo_permanent != 0) |
| 80 | || (m_format != 0) |
| 81 | || (m_addrinfo_transient != 0) |
| 82 | || (m_addrinfo_permanent != 0) |
| 83 | || (m_FCrDNS != 0) |
| 84 | || (m_host_acl != 0) |
| 85 | || (m_no_auth_plugin != 0) |
| 86 | || (m_auth_plugin != 0) |
| 87 | || (m_handshake != 0) |
| 88 | || (m_proxy_user != 0) |
| 89 | || (m_proxy_user_acl != 0) |
| 90 | || (m_authentication != 0) |
| 91 | || (m_ssl != 0) |
| 92 | || (m_max_user_connection != 0) |
| 93 | || (m_max_user_connection_per_hour != 0) |
| 94 | || (m_default_database != 0) |
| 95 | || (m_init_connect != 0) |
| 96 | || (m_local != 0)); |
| 97 | } |
| 98 | |
| 99 | void sum_connect_errors() |
| 100 | { |
| 101 | /* Current (historical) behavior: */ |
| 102 | m_connect= m_handshake; |
| 103 | } |
| 104 | |
| 105 | void clear_connect_errors() |
| 106 | { |
| 107 | m_connect= 0; |
| 108 | } |
| 109 | }; |
| 110 | |
| 111 | /** Size of IP address string in the hash cache. */ |
| 112 | #define HOST_ENTRY_KEY_SIZE INET6_ADDRSTRLEN |
| 113 | |
| 114 | /** |
| 115 | An entry in the hostname hash table cache. |
| 116 | |
| 117 | Host name cache does two things: |
| 118 | - caches host names to save DNS look ups; |
| 119 | - counts errors from IP. |
| 120 | |
| 121 | Host name can be empty (that means DNS look up failed), |
| 122 | but errors still are counted. |
| 123 | */ |
| 124 | class Host_entry : public hash_filo_element |
| 125 | { |
| 126 | public: |
| 127 | Host_entry *next() |
| 128 | { return (Host_entry*) hash_filo_element::next(); } |
| 129 | |
| 130 | /** |
| 131 | Client IP address. This is the key used with the hash table. |
| 132 | |
| 133 | The client IP address is always expressed in IPv6, even when the |
| 134 | network IPv6 stack is not present. |
| 135 | |
| 136 | This IP address is never used to connect to a socket. |
| 137 | */ |
| 138 | char ip_key[HOST_ENTRY_KEY_SIZE]; |
| 139 | |
| 140 | /** |
| 141 | One of the host names for the IP address. May be a zero length string. |
| 142 | */ |
| 143 | char m_hostname[HOSTNAME_LENGTH + 1]; |
| 144 | /** Length in bytes of @c m_hostname. */ |
| 145 | uint m_hostname_length; |
| 146 | /** The hostname is validated and used for authorization. */ |
| 147 | bool m_host_validated; |
| 148 | ulonglong m_first_seen; |
| 149 | ulonglong m_last_seen; |
| 150 | ulonglong m_first_error_seen; |
| 151 | ulonglong m_last_error_seen; |
| 152 | /** Error statistics. */ |
| 153 | Host_errors m_errors; |
| 154 | |
| 155 | void set_error_timestamps(ulonglong now) |
| 156 | { |
| 157 | if (m_first_error_seen == 0) |
| 158 | m_first_error_seen= now; |
| 159 | m_last_error_seen= now; |
| 160 | } |
| 161 | }; |
| 162 | |
| 163 | /** The size of the host_cache. */ |
| 164 | extern ulong host_cache_size; |
| 165 | |
| 166 | #define RC_OK 0 |
| 167 | #define RC_BLOCKED_HOST 1 |
| 168 | int ip_to_hostname(struct sockaddr_storage *ip_storage, |
| 169 | const char *ip_string, |
| 170 | const char **hostname, uint *connect_errors); |
| 171 | |
| 172 | void inc_host_errors(const char *ip_string, Host_errors *errors); |
| 173 | void reset_host_connect_errors(const char *ip_string); |
| 174 | bool hostname_cache_init(); |
| 175 | void hostname_cache_free(); |
| 176 | void hostname_cache_refresh(void); |
| 177 | uint hostname_cache_size(); |
| 178 | void hostname_cache_resize(uint size); |
| 179 | void hostname_cache_lock(); |
| 180 | void hostname_cache_unlock(); |
| 181 | Host_entry *hostname_cache_first(); |
| 182 | |
| 183 | #endif /* HOSTNAME_INCLUDED */ |
| 184 | |