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 | |