Added user agent info to curl operations.
Added access to CurlWritedataBuff.
Bug fix: Do not append IP to member BaseUrl.
#include "dhs.h"
#include "ods.h"
+#include "dyndns.h"
#include <time.h>
#include <iostream>
Service::Ptr service_ods(new ODS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,dns_cache_ttl));
return service_ods;
}
+ else if(protocol == "dyndns")
+ {
+ Service::Ptr service_dyndns(new DYNDNS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,dns_cache_ttl,Proxy,ProxyPort));
+ return service_dyndns;
+ }
else
{
Log->print_unknown_protocol(protocol);
#include "logger.h"
#include "serviceholder.h"
#include "httphelper.h"
+#include "service.h"
#include <boost/program_options.hpp>
#include <boost/shared_ptr.hpp>
*/
int DHS::perform_update(const std::string& ip)
{
- int ret_val = 0;
+ int ret_val = -1;
- BaseUrl.append(ip);
+ string url = BaseUrl;
+ url.append(ip);
- long output = HTTPHelp->http_get(BaseUrl);
+ long output = HTTPHelp->http_get(url);
- get_logger()->print_http_status_code(BaseUrl,output);
+ get_logger()->print_http_status_code(url,output);
if ( output == 200 )
{
}
else if ( output == 401 )
{
- get_logger()->print_http_not_authorized(BaseUrl,get_login(),get_password());
+ get_logger()->print_http_not_authorized(url,get_login(),get_password());
// not authorized
ret_val = -1;
}
--- /dev/null
+/** @file
+ * @brief DYNDNS Service class implementation. This class represents the DYNDNS service.
+ *
+ *
+ *
+ * @copyright Intra2net AG
+ * @license GPLv2
+*/
+
+#include "dyndns.h"
+
+#include <time.h>
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+
+/**
+ * Default Constructor, needed for object serialization.
+ */
+DYNDNS::DYNDNS()
+{
+}
+
+
+/**
+ * Constructor.
+ * @param _hostname The hostname to update
+ * @param _login The login name.
+ * @param _password The corresponding password.
+ */
+DYNDNS::DYNDNS(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, const string& _proxy, const int _proxy_port)
+{
+ if ( _update_interval == -1 ) // If _update_interval is default po::option_desc (not specified via config)
+ set_update_interval(0); // use default protocol value
+ else
+ set_update_interval(_update_interval);
+
+ if ( _max_updates_within_interval == -1 )
+ set_max_updates_within_interval(0);
+ else
+ set_max_updates_within_interval(_max_updates_within_interval);
+
+ if ( _dns_cache_ttl == -1 )
+ set_dns_cache_ttl(60);
+ else
+ set_dns_cache_ttl(_dns_cache_ttl);
+
+ set_protocol(_protocol);
+ set_hostname(_hostname);
+ set_login(_login);
+ set_password(_password);
+ set_logger(_logger);
+
+ // create http helper class
+ HTTPHelper::Ptr _http_help(new HTTPHelper(_logger,_proxy,_proxy_port,_login,_password));
+ HTTPHelp = _http_help;
+ _http_help.reset();
+
+ BaseUrl = assemble_base_url(get_hostname());
+}
+
+
+/**
+ * Default destructor
+ */
+DYNDNS::~DYNDNS()
+{
+}
+
+
+/**
+ * Assemble the dhs update url from the given fqhn
+ * @param hostname The fqhn hostname to update IP for.
+ * @return The assembled update url without IP.
+ */
+string DYNDNS::assemble_base_url(const string& fqhn) const
+{
+ string base_url;
+
+ base_url = "https://members.dyndns.org";
+ base_url.append("/nic/update?hostname=");
+ base_url.append(fqhn);
+ base_url.append("&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=");
+
+ return base_url;
+}
+
+
+/**
+ * Performs the Service update.
+ * @param ip IP Address to set.
+ * @return 0 if all is fine, -1 otherwise.
+ */
+int DYNDNS::perform_update(const std::string& ip)
+{
+ int ret_val = -1;
+
+ // the result string if update was successful
+ string good = "good ";
+ good.append(ip);
+
+ string url = BaseUrl;
+ url.append(ip);
+
+ long output = HTTPHelp->http_get(url);
+
+ get_logger()->print_http_status_code(url,output);
+
+ // HTTP operation completed successful, now we have to parse the data received by curl cause http status code is not significant for dyndns update errors
+ if ( output == 200 )
+ {
+ string curl_data = HTTPHelp->get_curl_data();
+
+ if ( curl_data == good )
+ ret_val = 0;
+ else if ( curl_data == "badauth" )
+ get_logger()->print_http_not_authorized(url,get_login(),get_password());
+ else
+ get_logger()->print_update_failure(url, curl_data);
+ }
+
+ return ret_val;
+}
+
+
+/**
+ * Serialize function needed by boost/serialization to define which members should be stored as the object state.
+ * @param ar Archive
+ * @param version Version
+ */
+template<class Archive>
+void DYNDNS::serialize(Archive & ar, const unsigned int version)
+{
+ ar & boost::serialization::base_object<Service>(*this);
+}
--- /dev/null
+/** @file
+ * @brief DYNDNS Service class header. This class represents the DYNDNS service.
+ *
+ *
+ *
+ * @copyright Intra2net AG
+ * @license GPLv2
+*/
+
+#ifndef DYNDNS_H
+#define DYNDNS_H
+
+#include <string>
+
+#include "service.h"
+#include "logger.h"
+
+#include <boost/serialization/array.hpp>
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+class DYNDNS : public Service
+{
+
+private:
+
+ friend class boost::serialization::access;
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version);
+
+ std::string BaseUrl;
+
+ HTTPHelper::Ptr HTTPHelp;
+
+ std::string assemble_base_url(const std::string& fqhn) const;
+
+public:
+
+ typedef boost::shared_ptr<DYNDNS> Ptr;
+
+ DYNDNS();
+
+ DYNDNS(const std::string& _protocol, const std::string& _hostname, const std::string& _login, const std::string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval, const int dns_cache_ttl, const std::string& proxy, const int proxy_port);
+
+ ~DYNDNS();
+
+ int perform_update(const std::string& ip);
+
+};
+
+#endif
/**
+ * Getter for member CurlWritedataBuff
+ * @return CurlWritedataBuff
+ */
+string HTTPHelper::get_curl_data() const
+{
+ return CurlWritedataBuff;
+}
+
+
+/**
* Initialized curl easy handle with a few options.
* @param curl_writedata_buff Reference to a string wich will be filled with the curl result
* @param curl_err_buff A pointer to an char array which will be filled with error message.
*/
CURL* HTTPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff) const
{
+ string user_agent = "bpdyndnsd Intra2net AG 2009";
+
CURL *curl_easy_handle = curl_easy_init();
curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
+ curl_easy_setopt(curl_easy_handle,CURLOPT_USERAGENT,&user_agent);
if ( !Proxy.empty() )
{
long http_get(const std::string& ip);
+ std::string get_curl_data() const;
+
// libcurl is a C library, so we have to make the callback member function static :-(
static int http_receive(char *inBuffer, size_t size, size_t nmemb, std::string *outBuffer);
};
if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
{
ostringstream msg;
- msg << "Data received by curl:\n" << curl_writedata_buff << endl;
+ msg << "Data received by curl: " << curl_writedata_buff << endl;
log_notice(msg.str(),level);
}
}
if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
{
ostringstream msg;
- msg << "Not authorized to perform update operation on url: " << url << "\n Please check username and password: " << username << ":" << password << endl;
+ msg << "Not authorized to perform update operation on url: " << url << " Please check username and password: " << username << ":" << password << endl;
log_warning(msg.str(),level);
}
}
log_notice(msg.str(),level);
}
}
+
+
+/**
+ * Generic failure while trying to update service
+ * @param url The requested URL
+ * @param curl_data The received curl_data from the server
+ */
+void Logger::print_update_failure(const string& url, const string& curl_data) const
+{
+ int level = 0;
+ if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+ {
+ ostringstream msg;
+ msg << "Problem while trying to updating service. Requested URL: " << url << " Error Code from Server: " << curl_data << endl;
+ log_warning(msg.str(),level);
+ }
+}
void print_http_not_authorized(const std::string& url, const std::string& username, const std::string& password) const;
void print_http_status_code(const std::string& url, const long http_code) const;
+
+ void print_update_failure(const std::string& url, const std::string& curl_data) const;
};
#endif
#include "iphelper.cpp"
#include "httphelper.cpp"
#include "serializeservicecontainer.cpp"
+#include "dyndns.cpp"
using namespace std;
// Following boost macros are needed for serialization of derived classes through a base class pointer (Service *).
BOOST_CLASS_EXPORT_GUID(ODS, "ODS")
BOOST_CLASS_EXPORT_GUID(DHS, "DHS")
+BOOST_CLASS_EXPORT_GUID(DYNDNS, "DYNDNS")
namespace fs = boost::filesystem;