| 1 | /** @file |
| 2 | * @brief ODS Service class implementation. This class represents the ODS service. |
| 3 | * |
| 4 | * |
| 5 | * |
| 6 | * @copyright Intra2net AG |
| 7 | * @license GPLv2 |
| 8 | */ |
| 9 | |
| 10 | #include "service_ods.hpp" |
| 11 | #include "net_helper.hpp" |
| 12 | #include "util.hpp" |
| 13 | |
| 14 | using namespace std; |
| 15 | |
| 16 | |
| 17 | /** |
| 18 | * Default Constructor, needed for object serialization. |
| 19 | */ |
| 20 | ServiceOds::ServiceOds() |
| 21 | { |
| 22 | } |
| 23 | |
| 24 | |
| 25 | /** |
| 26 | * Constructor. |
| 27 | * @param _hostname The hostname to update |
| 28 | * @param _login The login name. |
| 29 | * @param _password The corresponding password. |
| 30 | */ |
| 31 | ServiceOds::ServiceOds(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval, const int _max_equal_updates_in_succession, const int _dns_cache_ttl) |
| 32 | : UpdateServer("update.ods.org") |
| 33 | , Port("7071") |
| 34 | { |
| 35 | if ( _update_interval == -1 ) // If _update_interval is default po::option_desc (not specified via config) |
| 36 | set_update_interval(15); // use default protocol value |
| 37 | else |
| 38 | set_update_interval(_update_interval); |
| 39 | |
| 40 | if ( _max_updates_within_interval == -1 ) |
| 41 | set_max_updates_within_interval(3); |
| 42 | else |
| 43 | set_max_updates_within_interval(_max_updates_within_interval); |
| 44 | |
| 45 | if ( _max_equal_updates_in_succession == -1 ) |
| 46 | set_max_equal_updates_in_succession(2); |
| 47 | else |
| 48 | set_max_equal_updates_in_succession(_max_equal_updates_in_succession); |
| 49 | |
| 50 | if ( _dns_cache_ttl == -1 ) |
| 51 | set_dns_cache_ttl(180); |
| 52 | else |
| 53 | set_dns_cache_ttl(_dns_cache_ttl); |
| 54 | |
| 55 | set_protocol(_protocol); |
| 56 | set_hostname(_hostname); |
| 57 | set_login(_login); |
| 58 | set_password(_password); |
| 59 | set_logger(_logger); |
| 60 | } |
| 61 | |
| 62 | |
| 63 | /** |
| 64 | * Default destructor. |
| 65 | */ |
| 66 | ServiceOds::~ServiceOds() |
| 67 | { |
| 68 | } |
| 69 | |
| 70 | |
| 71 | /** |
| 72 | * Performs the Service update. |
| 73 | * @param ip IP Address to set. |
| 74 | * @return 0 if all is fine, -1 otherwise. |
| 75 | */ |
| 76 | Service::UpdateErrorCode ServiceOds::perform_update(const std::string& ip) |
| 77 | { |
| 78 | // First of all create a boost shared pointer to the NetHelper. |
| 79 | NetHelper::Ptr connection(new NetHelper(get_logger())); |
| 80 | |
| 81 | // Then open the connection to the ODS update server. |
| 82 | if (connection->open_connection(UpdateServer,Port) != 0) |
| 83 | return GenericError; |
| 84 | |
| 85 | // Receive the server greeting. |
| 86 | string server_greeting = connection->receive_data(); |
| 87 | if ( server_greeting.empty() ) |
| 88 | { |
| 89 | connection->close_connection(); /*lint !e534 */ |
| 90 | return GenericError; |
| 91 | } |
| 92 | |
| 93 | // Send login command |
| 94 | ostringstream login; |
| 95 | login << "LOGIN " << get_login() << " " << get_password() << endl; |
| 96 | if (connection->send_data(login.str()) != 0) |
| 97 | { |
| 98 | connection->close_connection(); /*lint !e534 */ |
| 99 | return GenericError; |
| 100 | } |
| 101 | |
| 102 | // Receive login reply |
| 103 | string login_reply = connection->receive_data(); |
| 104 | if ( login_reply.empty() ) |
| 105 | { |
| 106 | connection->close_connection(); /*lint !e534 */ |
| 107 | return GenericError; |
| 108 | } |
| 109 | else |
| 110 | { |
| 111 | // Get the return code out of the received data |
| 112 | string status_code = Util::parse_status_code(login_reply); |
| 113 | if ( status_code == "520" ) |
| 114 | { |
| 115 | // Login failed |
| 116 | get_logger()->print_service_not_authorized(UpdateServer,get_login(),get_password()); |
| 117 | connection->close_connection(); /*lint !e534 */ |
| 118 | return NotAuth; |
| 119 | } |
| 120 | else if ( status_code != "225" ) |
| 121 | { |
| 122 | // Undefined protocol error, Log login_reply |
| 123 | get_logger()->print_undefined_protocol_error("ODS",login_reply); |
| 124 | connection->close_connection(); /*lint !e534 */ |
| 125 | return GenericError; |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Successfully loged in, status_code should be 225 |
| 130 | |
| 131 | // Perform delete operation until there is no RR or we have performed it 10 times. |
| 132 | int del_count = 0; |
| 133 | string delete_reply, reply_code; |
| 134 | ostringstream delete_request; |
| 135 | delete_request << "DELRR " << get_hostname() << " A " << endl; |
| 136 | do |
| 137 | { |
| 138 | // Send delete request |
| 139 | if (connection->send_data(delete_request.str()) != 0) |
| 140 | { |
| 141 | connection->close_connection(); /*lint !e534 */ |
| 142 | return GenericError; |
| 143 | } |
| 144 | // Get delete reply |
| 145 | delete_reply = connection->receive_data(); |
| 146 | if ( delete_reply.empty() ) |
| 147 | { |
| 148 | connection->close_connection(); /*lint !e534 */ |
| 149 | return GenericError; |
| 150 | } |
| 151 | del_count++; |
| 152 | reply_code = Util::parse_status_code(delete_reply); |
| 153 | }while ( (del_count < 10) && (reply_code != "300") ); |
| 154 | |
| 155 | |
| 156 | // Send update request |
| 157 | ostringstream update_request; |
| 158 | update_request << "ADDRR " << get_hostname() << " A " << ip << endl; |
| 159 | if (connection->send_data(update_request.str()) != 0) |
| 160 | { |
| 161 | connection->close_connection(); /*lint !e534 */ |
| 162 | return GenericError; |
| 163 | } |
| 164 | |
| 165 | // Receive update request server reply |
| 166 | string update_reply = connection->receive_data(); |
| 167 | if ( update_reply.empty() ) |
| 168 | { |
| 169 | connection->close_connection(); /*lint !e534 */ |
| 170 | return GenericError; |
| 171 | } |
| 172 | else |
| 173 | { |
| 174 | // Get the return code out of the received data |
| 175 | string status_code = Util::parse_status_code(update_reply); |
| 176 | if ( status_code != "795" ) |
| 177 | { |
| 178 | get_logger()->print_undefined_protocol_error("ODS",update_reply); |
| 179 | connection->close_connection(); /*lint !e534 */ |
| 180 | return UpdateError; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Successfully updated host |
| 185 | connection->close_connection(); /*lint !e534 */ |
| 186 | return UpdateOk; |
| 187 | } |