Fix 'occurred' typo
[bpdyndnsd] / src / config.cpp
1 /** @file
2  * @brief Config class implementation. This class represents the actual configuration.
3  *
4  *
5  *
6  * @copyright Intra2net AG
7  * @license GPLv2
8 */
9
10 #include "config.hpp"
11
12 #include "service_dhs.hpp"
13 #include "service_ods.hpp"
14 #include "service_dyndns.hpp"
15 #include "service_dyns.hpp"
16 #include "service_easydns.hpp"
17 #include "service_tzo.hpp"
18 #include "service_zoneedit.hpp"
19 #include "service_gnudip.hpp"
20 #include "service_gnudip_fullhostname.hpp"
21
22 #include <time.h>
23 #include <iostream>
24 #include <fstream>
25
26 #include <boost/foreach.hpp>
27 #include <boost/filesystem.hpp>
28 #include <boost/regex.hpp>
29 #include <boost/algorithm/string.hpp>
30
31
32 namespace po = boost::program_options;
33 namespace fs = boost::filesystem;
34 namespace ba = boost::algorithm;
35
36 typedef boost::shared_ptr<boost::program_options::options_description> Options_descriptionPtr;
37
38 using namespace std;
39
40
41 /**
42  * Default Constructor. Available command line and config file options with their default values are defined here.
43  */
44 Config::Config()
45     : Log(new Logger)
46     , ServiceHolder(new Serviceholder)
47     , DaemonMode(false)
48     , Syslog(false)
49     , EnableIPv6(false)
50     , LogPasswords(false)
51     , Loglevel(0)
52     , ConfigPath("/etc/bpdyndnsd")
53     , WebcheckInterval(0)
54     , ProxyPort(0)
55     , ExternalWarningLog("")
56     , ExternalWarningLevel(0)
57     , StartOffline(false)
58     , WebcheckEnabled(false)
59     , ExternalLogOnlyOnce(false)
60     , DialupMode(false)
61     , DialupBurstPeriodSeconds(120)
62     , DialupSleepSeconds(10 * 60)
63 {
64     define_config_options();
65 }
66
67
68 /**
69  * Constructor with Logger and Serviceholder objects. Available command line and config file options with their default values are defined here.
70  * @todo Move the program options init code to a function used by both constructors
71  */
72 Config::Config(Logger::Ptr _log, Serviceholder::Ptr _serviceholder)
73     : Log(_log)
74     , ServiceHolder(_serviceholder)
75     , DaemonMode(false)
76     , Syslog(false)
77     , EnableIPv6(false)
78     , LogPasswords(false)
79     , Loglevel(0)
80     , ConfigPath("/etc/bpdyndnsd")
81     , WebcheckInterval(0)
82     , ProxyPort(0)
83     , ExternalWarningLog("")
84     , ExternalWarningLevel(0)
85     , StartOffline(false)
86     , WebcheckEnabled(false)
87     , ExternalLogOnlyOnce(false)
88     , DialupMode(false)
89     , DialupBurstPeriodSeconds(120)
90     , DialupSleepSeconds(10 * 60)
91 {
92     define_config_options();
93 }
94
95
96 /**
97  * Default Destructor
98  */
99 Config::~Config()
100 {
101 }
102
103
104 /**
105 * Define valid config options with default parameters.
106 */
107 void Config::define_config_options()
108 {
109     // Available service description config options
110     po::options_description opt_desc_service("Service description options");
111     opt_desc_service.add_options()
112         ("protocol",po::value<string>(),"The service protocol.")
113         ("server",po::value<string>(),"Servername needed for gnudip/dyndns protocol.")
114         ("host",po::value<string>(),"The hostname to update.")
115         ("login",po::value<string>(),"Login name.")
116         ("password",po::value<string>(),"Corresponding password.")
117         ("update_interval",po::value<int>()->default_value(-1),"Update interval in minutes.")
118         ("max_updates_within_interval",po::value<int>()->default_value(-1),"How many updates can be made in one interval.")
119         ("max_equal_updates_in_succession",po::value<int>()->default_value(-1),"How many updates with the same IP in succession should be made.")
120         ("dns_cache_ttl",po::value<int>()->default_value(-1),"How long a dns record is valid.")
121     ;
122
123     // Available command line only options
124     po::options_description opt_desc_cmd_only("Command line only options");
125     opt_desc_cmd_only.add_options()
126         ("help,?","Show help.")
127         ("version,v","Show version.")
128         ("config,c",po::value<string>()->default_value("/etc/bpdyndnsd"),"Set the config path.")
129     ;
130
131     // Available generic options. Valid on cmd or in config file.
132     po::options_description opt_desc_generic("Generic config options");
133     opt_desc_generic.add_options()
134         ("daemon_mode",po::value<bool>()->default_value(false),"Run as system daemon.")
135         ("loglevel",po::value<int>()->default_value(0),"Loglevel.")
136         ("syslog",po::value<bool>()->default_value(false),"Use syslog facility.")
137         ("log_passwords",po::value<bool>()->default_value(false),"Log passwords in cleartext.")
138         ("enable_ipv6",po::value<bool>()->default_value(false),"Try to use IPv6.")
139         ("webcheck_enabled",po::value<bool>()->default_value(false),"Use webcheck url to determine actual IP address.")
140         ("webcheck_url",po::value<string>()->default_value(""),"Use this URL to determine IP.")
141         ("webcheck_url_alt",po::value<string>()->default_value(""),"Use this alternative URL to determine IP.")
142         ("webcheck_interval",po::value<int>()->default_value(10),"The webcheck interval in minutes.")
143         ("http_proxy",po::value<string>(),"Use this proxy for all http requests.")
144         ("http_proxy_port",po::value<int>(),"Port of the proxy.")
145         ("external_warning_log",po::value<string>()->default_value(""),"External programm to pass warning log messages to.")
146         ("external_warning_level",po::value<int>()->default_value(0),"Warning messages of which loglevel should be passed to external programm.")
147         ("external_log_only_once",po::value<bool>()->default_value(false),"Log the same external message only once until next reload or restart.")
148         ("start_offline",po::value<bool>()->default_value(false),"Start in offline mode.")
149         ("dialup_mode",po::value<bool>()->default_value(false),"Enable dialup mode (sleep periods between network traffic)")
150         ("dialup_burst_period_seconds",po::value<int>()->default_value(120),"Seconds of normal operation before entering dialup mode")
151         ("dialup_sleep_seconds",po::value<int>()->default_value(10 * 60),"Seconds to sleep between network traffic")
152         ("wan_ip_override",po::value<string>(),"Manual override for automatic WAN IP detection")
153     ;
154
155     // Define valid command line parameters
156     OptDescCmd = Options_descriptionPtr(new po::options_description("Command line options"));
157     OptDescCmd->add(opt_desc_cmd_only);
158     OptDescCmd->add(opt_desc_generic);
159     OptDescCmd->add(opt_desc_service);
160
161     // Define valid config file options
162     OptDescConfMain = Options_descriptionPtr(new po::options_description("Config file options"));
163     OptDescConfMain->add(opt_desc_generic);
164
165     // Define valid service file options
166     OptDescConfService = Options_descriptionPtr(new po::options_description("Service file options"));
167     OptDescConfService->add(opt_desc_service);
168 }
169
170
171 /**
172  * Parses the command line arguments and does the needed actions.
173  * @param argc Command line argument number given to main.
174  * @param argv[] Pointer to command line argument array given to main.
175  * @return 0 if all is fine, -1 if not.
176  */
177 int Config::parse_cmd_line(int argc, char *argv[])
178 {
179     try
180     {
181         po::store(po::parse_command_line(argc, argv, *this->OptDescCmd), VariablesMap);
182         po::notify(VariablesMap);
183
184         if ( VariablesMap.count("help") )
185         {
186             Log->print_usage(OptDescCmd);
187             return -1;
188         }
189         else if ( VariablesMap.count("version") )
190         {
191             Log->print_version();
192             return -1;
193         }
194
195         // Create a service object if all needed options are set on the command line
196         if ( VariablesMap.count("protocol") && VariablesMap.count("host") && VariablesMap.count("login") && VariablesMap.count("password") )
197         {
198             // Get the cmd parameter values for protocol host login and password
199             string protocol = VariablesMap["protocol"].as<string>();
200             string host = VariablesMap["host"].as<string>();
201             string login = VariablesMap["login"].as<string>();
202             string password = VariablesMap["password"].as<string>();
203
204             protocol = ba::to_lower_copy(protocol);
205
206             string server;
207             if ( VariablesMap.count("server") )
208                 server = VariablesMap["server"].as<string>();
209
210             int update_interval = 0;
211             if ( VariablesMap.count("update_interval") )
212                 update_interval = VariablesMap["update_interval"].as<int>();
213
214             int max_updates_within_interval = 0;
215             if ( VariablesMap.count("max_updates_within_interval") )
216                 max_updates_within_interval = VariablesMap["max_updates_within_interval"].as<int>();
217
218             int max_equal_updates_in_succession = 0;
219             if ( VariablesMap.count("max_equal_updates_in_succession") )
220                 max_equal_updates_in_succession = VariablesMap["max_equal_updates_in_succession"].as<int>();
221
222             int dns_cache_ttl = 0;
223             if ( VariablesMap.count("dns_cache_ttl") )
224                 dns_cache_ttl = VariablesMap["dns_cache_ttl"].as<int>();
225
226             Service::Ptr service = create_service(protocol,server,host,login,password,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl);
227             if ( service )
228             {
229                 ServiceHolder->add_service(service);
230                 Log->print_service_object("New Service object from command line options:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_max_equal_updates_in_succession(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates(), service->get_activated());
231             }
232             else
233             {
234                 Log->print_invalid_service_config();
235             }
236         }
237         else if ( VariablesMap.count("protocol") || VariablesMap.count("host") || VariablesMap.count("login") || VariablesMap.count("password") )
238         {
239             Log->print_missing_cmd_service_option();
240             Log->print_usage(OptDescCmd);
241             return -1;
242         }
243
244         if ( VariablesMap.count("config") )
245         {
246             fs::path full_config_path = fs::system_complete(fs::path(VariablesMap["config"].as<string>()));
247             ConfigPath = full_config_path.string();
248             if ( !fs::exists(full_config_path) ||  !fs::is_directory(full_config_path) )
249             {
250                 // Config path doesn't exist or is not a directory
251                 Log->print_error_config_path(ConfigPath);
252                 return -1;
253             }
254         }
255
256         if ( VariablesMap.count("daemon_mode") )
257             DaemonMode = VariablesMap["daemon_mode"].as<bool>();
258
259         if ( VariablesMap.count("loglevel") )
260             Loglevel = VariablesMap["loglevel"].as<int>();
261
262         if ( VariablesMap.count("syslog") )
263             Syslog = VariablesMap["syslog"].as<bool>();
264
265         if ( VariablesMap.count("log_passwords") )
266             LogPasswords = VariablesMap["log_passwords"].as<bool>();
267
268         if ( VariablesMap.count("enable_ipv6") )
269             EnableIPv6 = VariablesMap["enable_ipv6"].as<bool>();
270
271         if ( VariablesMap.count("webcheck_enabled") )
272             WebcheckEnabled = VariablesMap["webcheck_enabled"].as<bool>();
273
274         if ( VariablesMap.count("webcheck_url") )
275             WebcheckIpUrl = VariablesMap["webcheck_url"].as<string>();
276
277         if ( VariablesMap.count("webcheck_url_alt") )
278             WebcheckIpUrlAlt = VariablesMap["webcheck_url_alt"].as<string>();
279
280         if ( VariablesMap.count("webcheck_interval") )
281             WebcheckInterval = VariablesMap["webcheck_interval"].as<int>();
282
283         if ( VariablesMap.count("http_proxy") && VariablesMap.count("http_proxy_port") )
284         {
285             Proxy = VariablesMap["http_proxy"].as<string>();
286             ProxyPort = VariablesMap["http_proxy_port"].as<int>();
287         }
288         else if ( VariablesMap.count("http_proxy") || VariablesMap.count("http_proxy_port") )
289         {
290             Log->print_missing_cmd_proxy_option();
291             Log->print_usage(OptDescCmd);
292             return -1;
293         }
294
295         if ( VariablesMap.count("external_warning_log") )
296             ExternalWarningLog = VariablesMap["external_warning_log"].as<string>();
297
298         if ( VariablesMap.count("external_warning_level") )
299             ExternalWarningLevel = VariablesMap["external_warning_level"].as<int>();
300
301         if ( VariablesMap.count("external_log_only_once") )
302             ExternalLogOnlyOnce = VariablesMap["external_log_only_once"].as<bool>();
303
304         if ( VariablesMap.count("start_offline") )
305             StartOffline = VariablesMap["start_offline"].as<bool>();
306
307         if ( VariablesMap.count("dialup_mode") )
308             DialupMode = VariablesMap["dialup_mode"].as<bool>();
309         if ( VariablesMap.count("dialup_burst_period_seconds") )
310             DialupBurstPeriodSeconds = VariablesMap["dialup_burst_period_seconds"].as<int>();
311         if ( VariablesMap.count("dialup_sleep_seconds") )
312             DialupSleepSeconds = VariablesMap["dialup_sleep_seconds"].as<int>();
313
314         if ( VariablesMap.count("wan_ip_override") )
315             WanIpOverride = VariablesMap["wan_ip_override"].as<string>();
316     }
317     catch( const po::unknown_option& e )
318     {
319         Log->print_unknown_cmd_option(e.what());
320         Log->print_usage(OptDescCmd);
321         return -1;
322     }
323     catch( const po::multiple_occurrences& e )
324     {
325         Log->print_multiple_cmd_option(e.what());
326         Log->print_usage(OptDescCmd);
327         return -1;
328     }
329     catch( const po::error& e )
330     {
331         Log->print_error_parsing_cmd(e.what());
332         Log->print_usage(OptDescCmd);
333         return -1;
334     }
335     return 0;
336 }
337
338
339 /**
340  * Creates a Service object from the given parameters.
341  * @param protocol Protocol to use.
342  * @param host Hostname to update.
343  * @param login Login.
344  * @param password Password.
345  * @return A pointer to the created Service object.
346  */
347 Service::Ptr Config::create_service(const string &protocol, const string& server, const string& hostname, const string& login, const string& password, const int update_interval, const int max_updates_within_interval, const int max_equal_updates_in_succession, const int dns_cache_ttl)
348 {
349     // Test for valid hostname. Must contain 3 parts minimum.
350     list<string> fqhn_parts;
351     ba::split(fqhn_parts,hostname,boost::is_any_of("."));
352     if ( fqhn_parts.size() < 3 )
353     {
354         Log->print_invalid_hostname(hostname);
355         Service::Ptr service;
356         return service;
357     }
358
359     if(protocol == "dhs")
360     {
361         Service::Ptr service_dhs(new ServiceDhs(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
362         return service_dhs;
363     }
364     else if(protocol == "ods")
365     {
366         Service::Ptr service_ods(new ServiceOds(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl));
367         return service_ods;
368     }
369     else if(protocol == "dyndns")
370     {
371         Service::Ptr service_dyndns(new ServiceDyndns(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort,server));
372         return service_dyndns;
373     }
374     else if(protocol == "dyns")
375     {
376         Service::Ptr service_dyns(new ServiceDyns(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
377         return service_dyns;
378     }
379     else if(protocol == "easydns")
380     {
381         Service::Ptr service_easydns(new ServiceEasydns(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
382         return service_easydns;
383     }
384     else if(protocol == "tzo")
385     {
386         Service::Ptr service_tzo(new ServiceTzo(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
387         return service_tzo;
388     }
389     else if(protocol == "zoneedit")
390     {
391         Service::Ptr service_zoneedit(new ServiceZoneedit(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
392         return service_zoneedit;
393     }
394     else if(protocol == "gnudip")
395     {
396         if ( !server.empty() )
397         {
398             Service::Ptr service_gnudip(new ServiceGnudip(protocol,server,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
399             return service_gnudip;
400         }
401         else
402         {
403             Log->print_gnudip_requires_servername();
404             Service::Ptr service;
405             return service;
406         }
407     }
408     else if(protocol == "gnudip-fullhostname")
409     {
410         if ( !server.empty() )
411         {
412             Service::Ptr service_gnudip_fullhostname(new ServiceGnudipFullhostname(protocol,server,hostname,login,password,Log,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl,Proxy,ProxyPort));
413             return service_gnudip_fullhostname;
414         }
415         else
416         {
417             Log->print_gnudip_requires_servername();
418             Service::Ptr service;
419             return service;
420         }
421     }
422     else
423     {
424         Log->print_unknown_protocol(protocol);
425         Service::Ptr service;
426         return service;
427     }
428 }
429
430
431 /**
432  * Loads a service config file, invoked by load_config_from_files.
433  * @param full_filename Filename of the service config file to load.
434  * @return 0 if all is fine, -1 otherwise.
435  */
436 int Config::load_service_config_file(const string& full_filename)
437 {
438     Log->print_load_service_conf(full_filename);
439
440     ifstream service_config_file(full_filename.c_str(),ifstream::in);
441     if(service_config_file.is_open())
442     {
443         try
444         {
445             po::variables_map vm;
446             po::parsed_options parsed_service_options = po::parse_config_file(service_config_file,*this->OptDescConfService,false);
447             po::store(parsed_service_options,vm);
448             po::notify(vm);
449
450             if(vm.count("protocol") && vm.count("host") && vm.count("login") && vm.count("password"))
451             {
452                 // create the corresponding service
453                 string protocol = vm["protocol"].as<string>();
454                 string host = vm["host"].as<string>();
455                 string login = vm["login"].as<string>();
456                     string password = vm["password"].as<string>();
457
458                 protocol = ba::to_lower_copy(protocol);
459
460                 string server;
461                 if ( vm.count("server") )
462                     server = vm["server"].as<string>();
463
464                 int update_interval = 0;
465                 if ( vm.count("update_interval") )
466                     update_interval = vm["update_interval"].as<int>();
467
468                 int max_updates_within_interval = 0;
469                 if ( vm.count("max_updates_within_interval") )
470                     max_updates_within_interval = vm["max_updates_within_interval"].as<int>();
471
472                 int max_equal_updates_in_succession = 0;
473                 if ( vm.count("max_equal_updates_in_succession") )
474                     max_equal_updates_in_succession = vm["max_equal_updates_in_succession"].as<int>();
475
476                 int dns_cache_ttl = 0;
477                 if ( vm.count("dns_cache_ttl") )
478                     dns_cache_ttl = vm["dns_cache_ttl"].as<int>();
479
480                 Service::Ptr service = create_service(protocol,server,host,login,password,update_interval,max_updates_within_interval,max_equal_updates_in_succession,dns_cache_ttl);
481                 if ( service )
482                 {
483                     ServiceHolder->add_service(service);
484                     Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_max_equal_updates_in_succession(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates(), service->get_activated());
485                 }
486                 else
487                 {
488                     Log->print_invalid_service_config();
489                 }
490             }
491             else if ( vm.count("protocol") || vm.count("host") || vm.count("login") || vm.count("password") )
492             {
493                 service_config_file.close();
494                 Log->print_missing_service_conf_option(full_filename);
495                 return -1;
496             }
497         }
498         catch( const po::unknown_option& e )
499         {
500             // unknown option in config file detected
501             service_config_file.close();
502             Log->print_unknown_service_conf_option(full_filename,e.what());
503             return -1;
504         }
505         catch( const po::multiple_occurrences& e )
506         {
507             service_config_file.close();
508             Log->print_multiple_service_conf_option(full_filename,e.what());
509             return -1;
510         }
511         catch( const po::error& e )
512         {
513             service_config_file.close();
514             Log->print_error_parsing_config_file(full_filename,e.what());
515             return -1;
516         }
517         service_config_file.close();
518     }
519     else
520     {
521         // error opening service config file for reading
522         Log->print_error_opening_r(full_filename);
523         return -1;
524     }
525     return 0;
526 }
527
528
529 /**
530  * Loads the main config file, invoked by load_config_from_files
531  * @param full_filename The full filename of the main config file to load
532  * @return 0 if all is fine, -1 otherwise
533  */
534 int Config::load_main_config_file(const string& full_filename)
535 {
536     Log->print_load_main_conf(full_filename);
537
538     ifstream main_config_file(full_filename.c_str(),ifstream::in);
539     if(main_config_file.is_open())
540     {
541         try
542         {
543             po::parsed_options parsed_main_options = po::parse_config_file(main_config_file,*this->OptDescConfMain,false);
544             po::store(parsed_main_options,VariablesMap);
545             po::notify(VariablesMap);
546
547             if ( VariablesMap.count("daemon_mode") )
548                 DaemonMode = VariablesMap["daemon_mode"].as<bool>();
549
550             if ( VariablesMap.count("loglevel") )
551                 Loglevel = VariablesMap["loglevel"].as<int>();
552
553             if ( VariablesMap.count("syslog") )
554                 Syslog = VariablesMap["syslog"].as<bool>();
555
556             if ( VariablesMap.count("log_passwords") )
557                 LogPasswords = VariablesMap["log_passwords"].as<bool>();
558
559             if ( VariablesMap.count("enable_ipv6") )
560                 EnableIPv6 = VariablesMap["enable_ipv6"].as<bool>();
561
562             if ( VariablesMap.count("webcheck_enabled") )
563                 WebcheckEnabled = VariablesMap["webcheck_enabled"].as<bool>();
564
565             if ( VariablesMap.count("webcheck_url") )
566                 WebcheckIpUrl = VariablesMap["webcheck_url"].as<string>();
567
568             if ( VariablesMap.count("webcheck_url_alt") )
569                 WebcheckIpUrlAlt = VariablesMap["webcheck_url_alt"].as<string>();
570
571             if ( VariablesMap.count("webcheck_interval") )
572                 WebcheckInterval = VariablesMap["webcheck_interval"].as<int>();
573
574             if ( VariablesMap.count("http_proxy") && VariablesMap.count("http_proxy_port") )
575             {
576                 Proxy = VariablesMap["http_proxy"].as<string>();
577                 ProxyPort = VariablesMap["http_proxy_port"].as<int>();
578             }
579             else if ( VariablesMap.count("http_proxy") || VariablesMap.count("http_proxy_port") )
580             {
581                 main_config_file.close();
582                 Log->print_missing_conf_proxy_option(full_filename);
583                 return -1;
584             }
585
586             if ( VariablesMap.count("external_warning_log") )
587                 ExternalWarningLog = VariablesMap["external_warning_log"].as<string>();
588
589             if ( VariablesMap.count("external_warning_level") )
590                 ExternalWarningLevel = VariablesMap["external_warning_level"].as<int>();
591
592             if ( VariablesMap.count("external_log_only_once") )
593                 ExternalLogOnlyOnce = VariablesMap["external_log_only_once"].as<bool>();
594
595             if ( VariablesMap.count("start_offline") )
596                 StartOffline = VariablesMap["start_offline"].as<bool>();
597
598             if ( VariablesMap.count("dialup_mode") )
599                 DialupMode = VariablesMap["dialup_mode"].as<bool>();
600             if ( VariablesMap.count("dialup_burst_period_seconds") )
601                 DialupBurstPeriodSeconds = VariablesMap["dialup_burst_period_seconds"].as<int>();
602             if ( VariablesMap.count("dialup_sleep_seconds") )
603                 DialupSleepSeconds = VariablesMap["dialup_sleep_seconds"].as<int>();
604
605             if ( VariablesMap.count("wan_ip_override") )
606                 WanIpOverride = VariablesMap["wan_ip_override"].as<string>();
607         }
608         catch( const po::unknown_option& e )
609         {
610             // unknown option in main config file detected
611             main_config_file.close();
612             Log->print_unknown_main_conf_option(e.what());
613             return -1;
614         }
615         catch( const po::multiple_occurrences& e )
616         {
617             main_config_file.close();
618             Log->print_multiple_main_conf_option(full_filename,e.what());
619             return -1;
620         }
621         main_config_file.close();
622     }
623     else
624     {
625         // error opening main config file for reading
626         Log->print_error_opening_r(full_filename);
627         return -1;
628     }
629     return 0;
630 }
631
632
633 /**
634  * Loads the main and the service config file and does the needed action.
635  * @param config_path The path to the config directory.
636  * @return 0 if all is fine, -1 otherwise
637  */
638 int Config::load_config_from_files()
639 {
640     fs::path full_config_path = fs::path(ConfigPath);
641
642     fs::directory_iterator end_iter;
643     for ( fs::directory_iterator dir_itr(full_config_path) ; dir_itr != end_iter ; ++dir_itr )
644     {
645         if( fs::is_regular_file( dir_itr->status() ) )
646         {
647 #if BOOST_FILESYSTEM_VERSION >= 3
648             string actual_file = dir_itr->path().filename().string();
649 #else
650             string actual_file = dir_itr->path().filename();
651 #endif
652             boost::regex expr(".*\\.conf$");
653              // If it is the main config file do the following
654             if ( actual_file == "bpdyndnsd.conf" )
655             {
656                 // Load the main config file
657                 string full_filename = dir_itr->path().string();
658                 if ( load_main_config_file(full_filename) != 0 )
659                     return -1;
660             }
661             // If it is a service definition file *.conf, parse it and generate the corresponding service
662             else if ( boost::regex_search( actual_file,expr ) )
663             {
664                 string full_filename = dir_itr->path().string();
665                 if ( load_service_config_file(full_filename) != 0 )
666                     return -1;
667             }
668         }
669     }
670     // Config file successfully loaded
671     Log->print_conf_loaded(ConfigPath);
672     return 0;
673 }
674
675
676 /**
677  * Getter method for member OptDescCmd.
678  * @return options_description*.
679  */
680 Options_descriptionPtr Config::get_opt_desc_cmd() const
681 {
682     return OptDescCmd;
683 }
684
685
686 /**
687  * Getter method for member OptDescConfMain.
688  * @return options_description*.
689  */
690 Options_descriptionPtr Config::get_opt_desc_conf_main() const
691 {
692     return OptDescConfMain;
693 }
694
695
696 /**
697  * Getter method for member OptDescConfService.
698  * @return options_description*.
699  */
700 Options_descriptionPtr Config::get_opt_desc_conf_service() const
701 {
702     return OptDescConfService;
703 }
704
705
706 /**
707  * Getter for member Loglevel.
708  * @return Member Loglevel.
709  */
710 int Config::get_loglevel() const
711 {
712     return Loglevel;
713 }
714
715
716 /**
717  * Getter for member DaemonMode.
718  * @return TRUE if enabled, FALSE if disabled.
719  */
720 bool Config::get_daemon_mode() const
721 {
722     return DaemonMode;
723 }
724
725
726 /**
727  * Deletes the map with the previously parsed options.
728  * This is needed in case we reload the config and don't want the old cmd options to overwrite new config file options.
729  */
730 void Config::delete_variables_map()
731 {
732     VariablesMap.clear();
733
734     po::variables_map _variables_map;
735     VariablesMap = _variables_map;
736 }
737
738
739 /**
740  * Getter for member Syslog.
741  * @return True if logging through syslog is enabled, false otherwise.
742  */
743 bool Config::get_syslog() const
744 {
745     return Syslog;
746 }
747
748
749 /**
750  * Getter for member LogPasswords.
751  * @return True if we want to log passwords in cleartext.
752  */
753 bool Config::get_log_passwords() const
754 {
755     return LogPasswords;
756 }
757
758
759 /**
760  * Getter for member EnableIPv6
761  * @return Wether IPv6 should be used or not.
762  */
763 bool Config::get_enable_ipv6() const
764 {
765     return EnableIPv6;
766 }
767
768
769 /**
770  * Getter for member WebcheckEnabled
771  * @return Is webcheck enabled by default.
772  */
773 bool Config::get_webcheck_enabled() const
774 {
775     return WebcheckEnabled;
776 }
777
778
779 /**
780  * Setter for member WebcheckEnabled
781  * @return Is webcheck enabled by default.
782  */
783 void Config::set_webcheck_enabled( bool webcheck_enabled )
784 {
785     WebcheckEnabled = webcheck_enabled;
786 }
787
788
789 /**
790  * Getter for member WebcheckIpUrl
791  * @return The primary IP Webcheck URL
792  */
793 string Config::get_webcheck_ip_url() const
794 {
795     return WebcheckIpUrl;
796 }
797
798
799 /**
800  * Getter for member WebcheckIpUrlAlt
801  * @return The alternative IP Webcheck URL
802  */
803 string Config::get_webcheck_ip_url_alt() const
804 {
805     return WebcheckIpUrlAlt;
806 }
807
808
809 /**
810  * Get member WebcheckInterval
811  * @return WebcheckInterval
812  */
813 int Config::get_webcheck_interval() const
814 {
815     return WebcheckInterval;
816 }
817
818
819 /**
820  * Get member Proxy
821  * @return Proxy
822  */
823 string Config::get_proxy() const
824 {
825     return Proxy;
826 }
827
828
829 /**
830  * Get member ProxyPort
831  * @return ProxyPort
832  */
833 int Config::get_proxy_port() const
834 {
835     return ProxyPort;
836 }
837
838
839 /**
840  * Get member ExternalWarningLog
841  * @return ExternalWarningLog
842  */
843 string Config::get_external_warning_log() const
844 {
845     return ExternalWarningLog;
846 }
847
848
849 /**
850  * Get member ExternalWarningLevel
851  * @return ExternalWaringLevel
852  */
853 int Config::get_external_warning_level() const
854 {
855     return ExternalWarningLevel;
856 }
857
858
859 /**
860  * Get member StartOffline
861  * @return StartOffline
862  */
863 bool Config::get_start_offline() const
864 {
865     return StartOffline;
866 }
867
868
869 /**
870  * Get member ExternalLogOnlyOnce
871  * @return StartOffline
872  */
873 bool Config::get_external_log_only_once() const
874 {
875     return ExternalLogOnlyOnce;
876 }
877
878
879 /**
880  * Get member DialupMode
881  * @return DIalupMode
882 */
883 bool Config::get_dialup_mode() const
884 {
885     return DialupMode;
886 }
887
888 /**
889  * Get member DialupBurstPeriodSeconds
890  * @return DialupBurstPeriodSeconds
891 */
892 int Config::get_dialup_burst_period_seconds() const
893 {
894     return DialupBurstPeriodSeconds;
895 }
896
897 /**
898  * Get member DialupSleepSeconds
899  * @return DialupSleepSeconds
900 */
901 int Config::get_dialup_sleep_seconds() const
902 {
903     return DialupSleepSeconds;
904 }
905
906 /**
907  * Get WAN override IP (if present)
908  * @return WanIpOverride
909 */
910 std::string Config::get_wan_ip_override() const
911 {
912     return WanIpOverride;
913 }