Corrected implementation of GnuDIP HTTP update protocol.
[bpdyndnsd] / src / service_ods.cpp
CommitLineData
089a7152
BS
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
4de6a9b8
BS
10#include "service_ods.hpp"
11#include "net_helper.hpp"
12#include "util.hpp"
089a7152 13
089a7152
BS
14using namespace std;
15
16
17/**
18 * Default Constructor, needed for object serialization.
19 */
629d8110 20ServiceOds::ServiceOds()
089a7152
BS
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 */
629d8110 31ServiceOds::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 _dns_cache_ttl)
6650af14
BS
32 : UpdateServer("update.ods.org")
33 , Port("7071")
089a7152
BS
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 ( _dns_cache_ttl == -1 )
46 set_dns_cache_ttl(180);
47 else
48 set_dns_cache_ttl(_dns_cache_ttl);
49
50 set_protocol(_protocol);
51 set_hostname(_hostname);
52 set_login(_login);
53 set_password(_password);
54 set_logger(_logger);
55}
56
57
58/**
59 * Default destructor.
60 */
629d8110 61ServiceOds::~ServiceOds()
089a7152
BS
62{
63}
64
65
66/**
67 * Performs the Service update.
68 * @param ip IP Address to set.
69 * @return 0 if all is fine, -1 otherwise.
70 */
629d8110 71int ServiceOds::perform_update(const std::string& ip)
089a7152 72{
6650af14
BS
73 // First of all create a boost shared pointer to the NetHelper.
74 NetHelper::Ptr connection(new NetHelper(get_logger()));
75
76 // Then open the connection to the ODS update server.
77 if (connection->open_connection(UpdateServer,Port) != 0)
78 return -1;
79
80 // Receive the server greeting.
81 string server_greeting = connection->receive_data();
82 if ( server_greeting.empty() )
c730deea 83 {
557b6f56 84 connection->close_connection(); /*lint !e534 */
6650af14 85 return -1;
c730deea 86 }
6650af14
BS
87
88 // Send login command
89 ostringstream login;
90 login << "LOGIN " << get_login() << " " << get_password() << endl;
c730deea
BS
91 if (connection->send_data(login.str()) != 0)
92 {
557b6f56 93 connection->close_connection(); /*lint !e534 */
6650af14 94 return -1;
c730deea 95 }
6650af14
BS
96
97 // Receive login reply
98 string login_reply = connection->receive_data();
99 if ( login_reply.empty() )
c730deea 100 {
557b6f56 101 connection->close_connection(); /*lint !e534 */
6650af14 102 return -1;
c730deea 103 }
6650af14
BS
104 else
105 {
106 // Get the return code out of the received data
107 string status_code = Util::parse_status_code(login_reply);
108 if ( status_code == "520" )
109 {
110 // Login failed
111 get_logger()->print_service_not_authorized(UpdateServer,get_login(),get_password());
557b6f56 112 connection->close_connection(); /*lint !e534 */
6650af14
BS
113 return -1;
114 }
115 else if ( status_code != "225" )
116 {
117 // Undefined protocol error, Log login_reply
118 get_logger()->print_undefined_protocol_error("ODS",login_reply);
557b6f56 119 connection->close_connection(); /*lint !e534 */
6650af14
BS
120 return -1;
121 }
122 }
123
124 // Successfully loged in, status_code should be 225
125
c1247537 126 // Perform delete operation until there is no RR or we have performed it 10 times.
c730deea 127 int del_count = 0;
c1247537
BS
128 string delete_reply, reply_code;
129 ostringstream delete_request;
130 delete_request << "DELRR " << get_hostname() << " A " << endl;
131 do
132 {
133 // Send delete request
c730deea
BS
134 if (connection->send_data(delete_request.str()) != 0)
135 {
557b6f56 136 connection->close_connection(); /*lint !e534 */
c1247537 137 return -1;
c730deea 138 }
c1247537
BS
139 // Get delete reply
140 delete_reply = connection->receive_data();
141 if ( delete_reply.empty() )
c730deea 142 {
557b6f56 143 connection->close_connection(); /*lint !e534 */
c1247537 144 return -1;
c730deea
BS
145 }
146 del_count++;
c1247537 147 reply_code = Util::parse_status_code(delete_reply);
c730deea 148 }while ( (del_count < 10) && (reply_code != "300") );
c1247537
BS
149
150
6650af14
BS
151 // Send update request
152 ostringstream update_request;
c1247537 153 update_request << "ADDRR " << get_hostname() << " A " << ip << endl;
c730deea
BS
154 if (connection->send_data(update_request.str()) != 0)
155 {
557b6f56 156 connection->close_connection(); /*lint !e534 */
6650af14 157 return -1;
c730deea 158 }
6650af14
BS
159
160 // Receive update request server reply
161 string update_reply = connection->receive_data();
c1247537 162 if ( update_reply.empty() )
c730deea 163 {
557b6f56 164 connection->close_connection(); /*lint !e534 */
6650af14 165 return -1;
c730deea 166 }
6650af14
BS
167 else
168 {
169 // Get the return code out of the received data
c1247537 170 string status_code = Util::parse_status_code(update_reply);
6650af14
BS
171 if ( status_code != "795" )
172 {
173 get_logger()->print_undefined_protocol_error("ODS",update_reply);
557b6f56 174 connection->close_connection(); /*lint !e534 */
6650af14
BS
175 return -1;
176 }
177 }
178
179 // Successfully updated host
557b6f56 180 connection->close_connection(); /*lint !e534 */
089a7152
BS
181 return 0;
182}