You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //
  2. // Created by robin on 8/9/15.
  3. //
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <fstream>
  8. #include "MySql.h"
  9. #define tmpTemplate "/tmp/pdns-slave.XXXXXX"
  10. MySql::MySql(const SqlConfiguration &masterConfig, const SqlConfiguration &slaveConfig)
  11. : AbstractSql(masterConfig, slaveConfig)
  12. {
  13. }
  14. MySql::~MySql()
  15. {
  16. if (!_dumpFilePath.empty())
  17. {
  18. unlink(_dumpFilePath.c_str());
  19. _dumpFilePath = "";
  20. }
  21. if (!_overrideFilePath.empty())
  22. {
  23. unlink(_overrideFilePath.c_str());
  24. _overrideFilePath = "";
  25. }
  26. }
  27. BResult MySql::dump()
  28. {
  29. BResult res;
  30. _dumpFilePath = getTempFile();
  31. int status = system(std::string("mysqldump '-h" + _masterConfig.getHost() + "'"
  32. + " '-u" + _masterConfig.getUser() + "'"
  33. + " '-p" + _masterConfig.getPassword() + "'"
  34. + " " + _masterConfig.getDatabase()
  35. + " > " + _dumpFilePath).c_str());
  36. if (status == 0)
  37. return res.ok(true);
  38. return res.error("mysqldump exited with code " + std::to_string(status));
  39. }
  40. const std::string MySql::getTempFile()
  41. {
  42. char tmp[sizeof(tmpTemplate)];
  43. strcpy(tmp, tmpTemplate);
  44. mkstemp(tmp);
  45. return std::string(tmp);
  46. }
  47. BResult MySql::insert()
  48. {
  49. return insertSlave(_dumpFilePath);
  50. }
  51. BResult MySql::override(const std::string &sql)
  52. {
  53. _overrideFilePath = getTempFile();
  54. std::ofstream file(_overrideFilePath);
  55. if (!file)
  56. return BResult().error("Could not open temp file " + _overrideFilePath);
  57. file << sql;
  58. file.close();
  59. return insertSlave(_overrideFilePath);
  60. }
  61. BResult MySql::insertSlave(const std::string &file)
  62. {
  63. BResult res;
  64. int status = system(std::string("cat " + file + " | mysql '-h" + _slaveConfig.getHost() + "'"
  65. + " '-u" + _slaveConfig.getUser() + "'"
  66. + " '-p" + _slaveConfig.getPassword() + "'"
  67. + " " + _slaveConfig.getDatabase()).c_str());
  68. if (status == 0)
  69. return res.ok(true);
  70. return res.error("mysql exited with code " + std::to_string(status));
  71. }
  72. std::string MySql::getAddDomainQuery(const ActionAddDomain &action)
  73. {
  74. auto soa = action.getSoaNs() + " " + action.getSoaMail() + " " + std::to_string(time(nullptr)) + " "
  75. + std::to_string(action.getSoaRefresh()) + " " + std::to_string(action.getSoaRetry()) + " "
  76. + std::to_string(action.getSoaExpire()) + " " + std::to_string(action.getSoaTtl());
  77. return "SET @domain_id=(SELECT id FROM domains WHERE name=\"" + action.getDomain() + "\");\n"
  78. "INSERT INTO domains (name, type) VALUES (\"" + action.getDomain() + "\", \"MASTER\");\n"
  79. "SET @domain_id=(SELECT id FROM domains WHERE name=\"" + action.getDomain() + "\");\n"
  80. "INSERT INTO zones (domain_id, owner, zone_templ_id) VALUES (@domain_id, "
  81. "(SELECT id FROM users ORDER BY id LIMIT 1), 0);\n"
  82. "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  83. " VALUES(@domain_id, \"" + action.getDomain() + "\", \"SOA\","
  84. " \"" + soa + "\", " + std::to_string(action.getTtl()) + ", 0, "
  85. + std::to_string(time(nullptr)) + ");\n";
  86. }
  87. std::string MySql::getAddHostQuery(const ActionAddHost &action)
  88. {
  89. auto host = action.getHost().empty() ? action.getDomain() : action.getHost() + "." + action.getDomain();
  90. auto query = "SET @domain_id=(SELECT id FROM domains WHERE name=\"" + action.getDomain() + "\");\n"
  91. "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  92. " VALUES(@domain_id, \"" + host + "\", \"" + action.getRecordType() + "\","
  93. " \"" + action.getRecordValue() + "\", " + std::to_string(action.getTtl())
  94. + ", 0, " + std::to_string(time(nullptr)) + ");\n";
  95. if (action.isReverseEnabled() && action.getRecordType() == "A")
  96. {
  97. auto reversedValue = action.getReversedValue();
  98. auto reverseDomain = action.getReverseDomain().empty() ? "in-addr.arpa" :
  99. action.getReverseDomain() + ".in-addr.arpa";
  100. query += "INSERT INTO records (domain_id, name, type, content, ttl, prio, change_date)\n"
  101. " VALUES((SELECT id FROM domains WHERE name=\"" + reverseDomain + "\"), \""
  102. + reversedValue + "." + reverseDomain + "\", \"PTR\","
  103. " \"" + action.getHost() + "." + action.getDomain() + "\", 84600, 0, "
  104. + std::to_string(time(nullptr)) + ");\n";
  105. }
  106. return query;
  107. }
  108. std::string MySql::getDelDomainQuery(const ActionDelDomain &action)
  109. {
  110. return "SET @domain_id=(SELECT id FROM domains WHERE name=\"" + action.getDomain() + "\");\n"
  111. "DELETE FROM records WHERE domain_id=@domain_id;\n"
  112. "DELETE FROM comments WHERE domain_id=@domain_id;\n"
  113. "DELETE FROM zones WHERE domain_id=@domain_id;\n"
  114. "DELETE FROM cryptokeys WHERE domain_id=@domain_id;\n"
  115. "DELETE FROM domainmetadata WHERE domain_id=@domain_id;\n"
  116. "DELETE FROM domains WHERE id=@domain_id;\n";
  117. }
  118. std::string MySql::getDelHostQuery(const ActionDelHost &action)
  119. {
  120. return "SET @domain_id=(SELECT id FROM domains WHERE name=\"" + action.getDomain() + "\");\n"
  121. "DELETE FROM records WHERE name=\"" + action.getHost() + "." + action.getDomain() + "\" AND "
  122. "domain_id=@domain_id;";
  123. }