1 /*
2    Copyright (c) 2001, 2011, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 /**
18   @file
19 
20   All of the functions defined in this file which are not used (the ones to
21   handle failsafe) are not used; their code has not been updated for more
22   than one year now so should be considered as BADLY BROKEN. Do not enable
23   it. The used functions (to handle LOAD DATA FROM MASTER, plus some small
24   functions like register_slave()) are working.
25 */
26 
27 #include "mariadb.h"
28 #include "sql_priv.h"
29 #include "sql_parse.h"                          // check_access
30 #ifdef HAVE_REPLICATION
31 
32 #include "repl_failsafe.h"
33 #include "sql_acl.h"                            // REPL_SLAVE_ACL
34 #include "sql_repl.h"
35 #include "slave.h"
36 #include "rpl_mi.h"
37 #include "rpl_filter.h"
38 #include "log_event.h"
39 #include <mysql.h>
40 
41 
42 struct Slave_info
43 {
44   uint32 server_id;
45   uint32 master_id;
46   char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
47   char user[USERNAME_LENGTH+1];
48   char password[MAX_PASSWORD_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
49   uint16 port;
50 };
51 
52 
53 Atomic_counter<uint32_t> binlog_dump_thread_count;
54 ulong rpl_status=RPL_NULL;
55 mysql_mutex_t LOCK_rpl_status;
56 
57 const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
58 TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
59 			    rpl_role_type, NULL};
60 
61 const char* rpl_status_type[]=
62 {
63   "AUTH_MASTER","IDLE_SLAVE","ACTIVE_SLAVE","LOST_SOLDIER","TROOP_SOLDIER",
64   "RECOVERY_CAPTAIN","NULL",NullS
65 };
66 
67 /*
68   All of the functions defined in this file which are not used (the ones to
69   handle failsafe) are not used; their code has not been updated for more than
70   one year now so should be considered as BADLY BROKEN. Do not enable it.
71   The used functions (to handle LOAD DATA FROM MASTER, plus some small
72   functions like register_slave()) are working.
73 */
74 
change_rpl_status(ulong from_status,ulong to_status)75 void change_rpl_status(ulong from_status, ulong to_status)
76 {
77   mysql_mutex_lock(&LOCK_rpl_status);
78   if (rpl_status == from_status || rpl_status == RPL_ANY)
79     rpl_status = to_status;
80   mysql_mutex_unlock(&LOCK_rpl_status);
81 }
82 
83 
84 #define get_object(p, obj, msg) \
85 {\
86   uint len = (uint)*p++;  \
87   if (p + len > p_end || len >= sizeof(obj)) \
88   {\
89     errmsg= msg;\
90     goto err; \
91   }\
92   ::strmake(obj, (char*) p, len); \
93   p+= len; \
94 }\
95 
96 
unregister_slave()97 void THD::unregister_slave()
98 {
99   if (auto old_si= slave_info)
100   {
101     mysql_mutex_lock(&LOCK_thd_data);
102     slave_info= 0;
103     mysql_mutex_unlock(&LOCK_thd_data);
104     my_free(old_si);
105     binlog_dump_thread_count--;
106   }
107 }
108 
109 
110 /**
111   Register slave
112 
113   @return
114     0	ok
115   @return
116     1	Error.   Error message sent to client
117 */
118 
register_slave(uchar * packet,size_t packet_length)119 int THD::register_slave(uchar *packet, size_t packet_length)
120 {
121   Slave_info *si;
122   uchar *p= packet, *p_end= packet + packet_length;
123   const char *errmsg= "Wrong parameters to function register_slave";
124 
125   if (check_access(this, PRIV_COM_REGISTER_SLAVE, any_db, NULL, NULL, 0, 0))
126     return 1;
127   if (!(si= (Slave_info*)my_malloc(key_memory_SLAVE_INFO, sizeof(Slave_info),
128                                    MYF(MY_WME))))
129     return 1;
130 
131   variables.server_id= si->server_id= uint4korr(p);
132   p+= 4;
133   get_object(p,si->host, "Failed to register slave: too long 'report-host'");
134   get_object(p,si->user, "Failed to register slave: too long 'report-user'");
135   get_object(p,si->password, "Failed to register slave; too long 'report-password'");
136   if (p+10 > p_end)
137     goto err;
138   si->port= uint2korr(p);
139   p += 2;
140   /*
141      We need to by pass the bytes used in the fake rpl_recovery_rank
142      variable. It was removed in patch for BUG#13963. But this would
143      make a server with that patch unable to connect to an old master.
144      See: BUG#49259
145   */
146   // si->rpl_recovery_rank= uint4korr(p);
147   p += 4;
148   if (!(si->master_id= uint4korr(p)))
149     si->master_id= global_system_variables.server_id;
150 
151   if (!*si->host)
152     ::strmake(si->host, main_security_ctx.host_or_ip, sizeof(si->host));
153 
154   unregister_slave();
155   mysql_mutex_lock(&LOCK_thd_data);
156   slave_info= si;
157   mysql_mutex_unlock(&LOCK_thd_data);
158   binlog_dump_thread_count++;
159   return 0;
160 
161 err:
162   delete si;
163   my_message(ER_UNKNOWN_ERROR, errmsg, MYF(0)); /* purecov: inspected */
164   return 1;
165 }
166 
167 
is_binlog_dump_thread()168 bool THD::is_binlog_dump_thread()
169 {
170   mysql_mutex_lock(&LOCK_thd_data);
171   bool res= slave_info != NULL;
172   mysql_mutex_unlock(&LOCK_thd_data);
173 
174   return res;
175 }
176 
177 
show_slave_hosts_callback(THD * thd,Protocol * protocol)178 static my_bool show_slave_hosts_callback(THD *thd, Protocol *protocol)
179 {
180   my_bool res= FALSE;
181   mysql_mutex_lock(&thd->LOCK_thd_data);
182   if (auto si= thd->slave_info)
183   {
184     protocol->prepare_for_resend();
185     protocol->store(si->server_id);
186     protocol->store(si->host, &my_charset_bin);
187     if (opt_show_slave_auth_info)
188     {
189       protocol->store(si->user, &my_charset_bin);
190       protocol->store(si->password, &my_charset_bin);
191     }
192     protocol->store((uint32) si->port);
193     protocol->store(si->master_id);
194     res= protocol->write();
195   }
196   mysql_mutex_unlock(&thd->LOCK_thd_data);
197   return res;
198 }
199 
200 
201 /**
202   Execute a SHOW SLAVE HOSTS statement.
203 
204   @param thd Pointer to THD object for the client thread executing the
205   statement.
206 
207   @retval FALSE success
208   @retval TRUE failure
209 */
show_slave_hosts(THD * thd)210 bool show_slave_hosts(THD* thd)
211 {
212   List<Item> field_list;
213   Protocol *protocol= thd->protocol;
214   MEM_ROOT *mem_root= thd->mem_root;
215   DBUG_ENTER("show_slave_hosts");
216 
217   field_list.push_back(new (mem_root)
218                        Item_return_int(thd, "Server_id", 10,
219                                        MYSQL_TYPE_LONG),
220                        thd->mem_root);
221   field_list.push_back(new (mem_root)
222                        Item_empty_string(thd, "Host", 20),
223                        thd->mem_root);
224   if (opt_show_slave_auth_info)
225   {
226     field_list.push_back(new (mem_root) Item_empty_string(thd, "User", 20),
227                          thd->mem_root);
228     field_list.push_back(new (mem_root) Item_empty_string(thd, "Password", 20),
229                          thd->mem_root);
230   }
231   field_list.push_back(new (mem_root)
232                        Item_return_int(thd, "Port", 7, MYSQL_TYPE_LONG),
233                        thd->mem_root);
234   field_list.push_back(new (mem_root)
235                        Item_return_int(thd, "Master_id", 10, MYSQL_TYPE_LONG),
236                        thd->mem_root);
237 
238   if (protocol->send_result_set_metadata(&field_list,
239                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
240     DBUG_RETURN(TRUE);
241 
242   if (server_threads.iterate(show_slave_hosts_callback, protocol))
243     DBUG_RETURN(true);
244 
245   my_eof(thd);
246   DBUG_RETURN(FALSE);
247 }
248 
249 #endif /* HAVE_REPLICATION */
250 
251