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