diff --git a/ddclient b/ddclient index 697d7fd..f67becd 100755 --- a/ddclient +++ b/ddclient @@ -27,10 +27,10 @@ use IO::Socket; use Data::Validate::IP; my $version = "3.9.1"; -my $programd = $0; +my $programd = $0; $programd =~ s%^.*/%%; -my $program = $programd; -$program =~ s/d$//; +my $program = $programd; +$program =~ s/d$//; my $now = time; my $hostname = hostname(); my $etc = ($program =~ /test/i) ? './' : '/etc/ddclient/'; @@ -45,426 +45,425 @@ local $lineno = ''; $ENV{'PATH'} = (exists($ENV{PATH}) ? "$ENV{PATH}:" : "") . "/sbin:/usr/sbin:/bin:/usr/bin:/etc:/usr/lib:"; -sub T_ANY {'any'}; -sub T_STRING {'string'}; -sub T_EMAIL {'e-mail address'}; -sub T_NUMBER {'number'}; -sub T_DELAY {'time delay (ie. 1d, 1hour, 1m)'}; -sub T_LOGIN {'login'}; -sub T_PASSWD {'password'}; -sub T_BOOL {'boolean value'}; -sub T_FQDN {'fully qualified host name'}; -sub T_OFQDN {'optional fully qualified host name'}; -sub T_FILE {'file name'}; -sub T_FQDNP {'fully qualified host name and optional port number'}; -sub T_PROTO {'protocol'} -sub T_USE {'ip strategy'} -sub T_IF {'interface'} -sub T_PROG {'program name'} -sub T_IP {'ip'} -sub T_POSTS {'postscript'}; +sub T_ANY { 'any' }; +sub T_STRING { 'string' }; +sub T_EMAIL { 'e-mail address' }; +sub T_NUMBER { 'number' }; +sub T_DELAY { 'time delay (ie. 1d, 1hour, 1m)' }; +sub T_LOGIN { 'login' }; +sub T_PASSWD { 'password' }; +sub T_BOOL { 'boolean value' }; +sub T_FQDN { 'fully qualified host name' }; +sub T_OFQDN { 'optional fully qualified host name' }; +sub T_FILE { 'file name' }; +sub T_FQDNP { 'fully qualified host name and optional port number' }; +sub T_PROTO { 'protocol' } +sub T_USE { 'ip strategy' } +sub T_IF { 'interface' } +sub T_PROG { 'program name' } +sub T_IP { 'ip' } +sub T_POSTS { 'postscript' }; ## strategies for obtaining an ip address. my %builtinweb = ( - 'dyndns' => { 'url' => 'http://checkip.dyndns.org/', 'skip' => - 'Current IP Address:', }, - 'loopia' => { 'url' => 'http://dns.loopia.se/checkip/checkip.php', 'skip' => 'Current IP Address:', }, + 'dyndns' => { 'url' => 'http://checkip.dyndns.org/', 'skip' => 'Current IP Address:', }, + 'loopia' => { 'url' => 'http://dns.loopia.se/checkip/checkip.php', 'skip' => 'Current IP Address:', }, ); my %builtinfw = ( - 'watchguard-soho' => { - 'name' => 'Watchguard SOHO FW', - 'url' => '/pubnet.htm', - 'skip' => 'NAME=IPAddress VALUE=', - }, - 'netopia-r910' => { - 'name' => 'Netopia R910 FW', - 'url' => '/WanEvtLog', - 'skip' => 'local:', - }, - 'smc-barricade' => { - 'name' => 'SMC Barricade FW', - 'url' => '/status.htm', - 'skip' => 'IP Address', - }, - 'smc-barricade-alt' => { - 'name' => 'SMC Barricade FW (alternate config)', - 'url' => '/status.HTM', - 'skip' => 'WAN IP', - }, - 'smc-barricade-7401bra' => { - 'name' => 'SMC Barricade 7401BRA FW', - 'url' => '/admin/wan1.htm', - 'skip' => 'IP Address', - }, - 'netgear-rt3xx' => { - 'name' => 'Netgear FW', - 'url' => '/mtenSysStatus.html', - 'skip' => 'IP Address', - }, - 'elsa-lancom-dsl10' => { - 'name' => 'ELSA LanCom DSL/10 DSL FW', - 'url' => '/config/1/6/8/3/', - 'skip' => 'IP.Address', - }, + 'watchguard-soho' => { + 'name' => 'Watchguard SOHO FW', + 'url' => '/pubnet.htm', + 'skip' => 'NAME=IPAddress VALUE=', + }, + 'netopia-r910' => { + 'name' => 'Netopia R910 FW', + 'url' => '/WanEvtLog', + 'skip' => 'local:', + }, + 'smc-barricade' => { + 'name' => 'SMC Barricade FW', + 'url' => '/status.htm', + 'skip' => 'IP Address', + }, + 'smc-barricade-alt' => { + 'name' => 'SMC Barricade FW (alternate config)', + 'url' => '/status.HTM', + 'skip' => 'WAN IP', + }, + 'smc-barricade-7401bra' => { + 'name' => 'SMC Barricade 7401BRA FW', + 'url' => '/admin/wan1.htm', + 'skip' => 'IP Address', + }, + 'netgear-rt3xx' => { + 'name' => 'Netgear FW', + 'url' => '/mtenSysStatus.html', + 'skip' => 'IP Address', + }, + 'elsa-lancom-dsl10' => { + 'name' => 'ELSA LanCom DSL/10 DSL FW', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address', + }, 'elsa-lancom-dsl10-ch01' => { - 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', - 'url' => '/config/1/6/8/3/', - 'skip' => 'IP.Address.*?CH01', - }, + 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address.*?CH01', + }, 'elsa-lancom-dsl10-ch02' => { - 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', - 'url' => '/config/1/6/8/3/', - 'skip' => 'IP.Address.*?CH02', - }, - 'linksys' => { - 'name' => 'Linksys FW', - 'url' => '/Status.htm', - 'skip' => 'WAN.*?Address', - }, - 'linksys-ver2' => { - 'name' => 'Linksys FW version 2', - 'url' => '/RouterStatus.htm', - 'skip' => 'WAN.*?Address', - }, - 'linksys-ver3' => { - 'name' => 'Linksys FW version 3', - 'url' => '/Status_Router.htm', - 'skip' => 'WAN.*?Address', - }, - 'linksys-wrt854g' => { - 'name' => 'Linksys WRT854G FW', - 'url' => '/Status_Router.asp', - 'skip' => 'IP Address:', - }, - 'maxgate-ugate3x00' => { - 'name' => 'MaxGate UGATE-3x00 FW', - 'url' => '/Status.htm', - 'skip' => 'WAN.*?IP Address', - }, - 'netcomm-nb3' => { - 'name' => 'NetComm NB3', - 'url' => '/MainPage?id=6', - 'skip' => 'ppp-0', - }, - '3com-3c886a' => { - 'name' => '3com 3c886a 56k Lan Modem', - 'url' => '/stat3.htm', - 'skip' => 'IP address in use', - }, - 'sohoware-nbg800' => { - 'name' => 'SOHOWare BroadGuard NBG800', - 'url' => '/status.htm', - 'skip' => 'Internet IP', - }, - 'xsense-aero' => { - 'name' => 'Xsense Aero', - 'url' => '/A_SysInfo.htm', - 'skip' => 'WAN.*?IP Address', - }, - 'alcatel-stp' => { - 'name' => 'Alcatel Speed Touch Pro', - 'url' => '/cgi/router/', - 'skip' => 'Brt', - }, - 'alcatel-510' => { - 'name' => 'Alcatel Speed Touch 510', - 'url' => '/cgi/ip/', - 'skip' => 'ppp', - }, - 'allnet-1298' => { - 'name' => 'Allnet 1298', - 'url' => '/cgi/router/', - 'skip' => 'WAN', - }, - '3com-oc-remote812' => { - 'name' => '3com OfficeConnect Remote 812', - 'url' => '/callEvent', - 'skip' => '.*LOCAL', - }, - 'e-tech' => { - 'name' => 'E-tech Router', - 'url' => '/Status.htm', - 'skip' => 'Public IP Address', - }, - 'cayman-3220h' => { - 'name' => 'Cayman 3220-H DSL', - 'url' => '/shell/show+ip+interfaces', - 'skip' => '.*inet', - }, - 'vigor-2200usb' => { - 'name' => 'Vigor 2200 USB', - 'url' => '/doc/online.sht', - 'skip' => 'PPPoA', - }, - 'dlink-614' => { - 'name' => 'D-Link DI-614+', - 'url' => '/st_devic.html', - 'skip' => 'WAN', - }, - 'dlink-604' => { - 'name' => 'D-Link DI-604', - 'url' => '/st_devic.html', - 'skip' => 'WAN.*?IP.*Address', - }, - 'olitec-SX200' => { - 'name' => 'olitec-SX200', - 'url' => '/doc/wan.htm', - 'skip' => 'st_wan_ip[0] = "', - }, - 'westell-6100' => { - 'name' => 'Westell C90-610015-06 DSL Router', - 'url' => '/advstat.htm', - 'skip' => 'IP.+?Address', - }, - '2wire' => { - 'name' => '2Wire 1701HG Gateway', - 'url' => '/xslt?PAGE=B01', - 'skip' => 'Internet Address:', - }, + 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address.*?CH02', + }, + 'linksys' => { + 'name' => 'Linksys FW', + 'url' => '/Status.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-ver2' => { + 'name' => 'Linksys FW version 2', + 'url' => '/RouterStatus.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-ver3' => { + 'name' => 'Linksys FW version 3', + 'url' => '/Status_Router.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-wrt854g' => { + 'name' => 'Linksys WRT854G FW', + 'url' => '/Status_Router.asp', + 'skip' => 'IP Address:', + }, + 'maxgate-ugate3x00' => { + 'name' => 'MaxGate UGATE-3x00 FW', + 'url' => '/Status.htm', + 'skip' => 'WAN.*?IP Address', + }, + 'netcomm-nb3' => { + 'name' => 'NetComm NB3', + 'url' => '/MainPage?id=6', + 'skip' => 'ppp-0', + }, + '3com-3c886a' => { + 'name' => '3com 3c886a 56k Lan Modem', + 'url' => '/stat3.htm', + 'skip' => 'IP address in use', + }, + 'sohoware-nbg800' => { + 'name' => 'SOHOWare BroadGuard NBG800', + 'url' => '/status.htm', + 'skip' => 'Internet IP', + }, + 'xsense-aero' => { + 'name' => 'Xsense Aero', + 'url' => '/A_SysInfo.htm', + 'skip' => 'WAN.*?IP Address', + }, + 'alcatel-stp' => { + 'name' => 'Alcatel Speed Touch Pro', + 'url' => '/cgi/router/', + 'skip' => 'Brt', + }, + 'alcatel-510' => { + 'name' => 'Alcatel Speed Touch 510', + 'url' => '/cgi/ip/', + 'skip' => 'ppp', + }, + 'allnet-1298' => { + 'name' => 'Allnet 1298', + 'url' => '/cgi/router/', + 'skip' => 'WAN', + }, + '3com-oc-remote812' => { + 'name' => '3com OfficeConnect Remote 812', + 'url' => '/callEvent', + 'skip' => '.*LOCAL', + }, + 'e-tech' => { + 'name' => 'E-tech Router', + 'url' => '/Status.htm', + 'skip' => 'Public IP Address', + }, + 'cayman-3220h' => { + 'name' => 'Cayman 3220-H DSL', + 'url' => '/shell/show+ip+interfaces', + 'skip' => '.*inet', + }, + 'vigor-2200usb' => { + 'name' => 'Vigor 2200 USB', + 'url' => '/doc/online.sht', + 'skip' => 'PPPoA', + }, + 'dlink-614' => { + 'name' => 'D-Link DI-614+', + 'url' => '/st_devic.html', + 'skip' => 'WAN', + }, + 'dlink-604' => { + 'name' => 'D-Link DI-604', + 'url' => '/st_devic.html', + 'skip' => 'WAN.*?IP.*Address', + }, + 'olitec-SX200' => { + 'name' => 'olitec-SX200', + 'url' => '/doc/wan.htm', + 'skip' => 'st_wan_ip[0] = "', + }, + 'westell-6100' => { + 'name' => 'Westell C90-610015-06 DSL Router', + 'url' => '/advstat.htm', + 'skip' => 'IP.+?Address', + }, + '2wire' => { + 'name' => '2Wire 1701HG Gateway', + 'url' => '/xslt?PAGE=B01', + 'skip' => 'Internet Address:', + }, 'linksys-rv042-wan1' => { 'name' => 'Linksys RV042 Dual Homed Router WAN Port 2', - 'url' => '/home.htm', + 'url' => '/home.htm', 'skip' => 'WAN1 IP', }, 'linksys-rv042-wan2' => { 'name' => 'Linksys RV042 Dual Homed Router WAN Port 2', - 'url' => '/home.htm', + 'url' => '/home.htm', 'skip' => 'WAN2 IP', }, 'netgear-rp614' => { 'name' => 'Netgear RP614 FW', - 'url' => '/sysstatus.html', + 'url' => '/sysstatus.html', 'skip' => 'IP Address', }, 'watchguard-edge-x' => { 'name' => 'Watchguard Edge X FW', - 'url' => '/netstat.htm', + 'url' => '/netstat.htm', 'skip' => 'inet addr:', }, 'dlink-524' => { 'name' => 'D-Link DI-524', - 'url' => '/st_device.html', + 'url' => '/st_device.html', 'skip' => 'WAN.*?Addres', }, 'rtp300' => { 'name' => 'Linksys RTP300', - 'url' => '/cgi-bin/webcm?getpage=%2Fusr%2Fwww_safe%2Fhtml%2Fstatus%2FRouter.html', + 'url' => '/cgi-bin/webcm?getpage=%2Fusr%2Fwww_safe%2Fhtml%2Fstatus%2FRouter.html', 'skip' => 'Internet.*?IP Address', }, 'netgear-wpn824' => { 'name' => 'Netgear WPN824 FW', - 'url' => '/RST_status.htm', + 'url' => '/RST_status.htm', 'skip' => 'IP Address', }, 'linksys-wcg200' => { 'name' => 'Linksys WCG200 FW', - 'url' => '/RgStatus.asp', + 'url' => '/RgStatus.asp', 'skip' => 'WAN.IP.*?Address', }, 'netgear-dg834g' => { 'name' => 'netgear-dg834g', - 'url' => '/setup.cgi?next_file=s_status.htm&todo=cfg_init', + 'url' => '/setup.cgi?next_file=s_status.htm&todo=cfg_init', 'skip' => '', }, 'netgear-wgt624' => { 'name' => 'Netgear WGT624', - 'url' => '/RST_st_dhcp.htm', + 'url' => '/RST_st_dhcp.htm', 'skip' => 'IP Address', }, 'sveasoft' => { 'name' => 'Sveasoft WRT54G/WRT54GS', - 'url' => '/Status_Router.asp', + 'url' => '/Status_Router.asp', 'skip' => 'var wan_ip', }, 'smc-barricade-7004vbr' => { 'name' => 'SMC Barricade FW (7004VBR model config)', - 'url' => '/status_main.stm', + 'url' => '/status_main.stm', 'skip' => 'var wan_ip=', }, 'sitecom-dc202' => { 'name' => 'Sitecom DC-202 FW', - 'url' => '/status.htm', + 'url' => '/status.htm', 'skip' => 'Internet IP Address', }, ); my %ip_strategies = ( - 'ip' => ": obtain IP from -ip {address}", - 'web' => ": obtain IP from an IP discovery page on the web", - 'fw' => ": obtain IP from the firewall specified by -fw {type|address}", - 'if' => ": obtain IP from the -if {interface}", - 'cmd' => ": obtain IP from the -cmd {external-command}", - 'cisco' => ": obtain IP from Cisco FW at the -fw {address}", - 'cisco-asa' => ": obtain IP from Cisco ASA at the -fw {address}", - map { $_ => sprintf ": obtain IP from %s at the -fw {address}", $builtinfw{$_}->{'name'} } keys %builtinfw, + 'ip' => ": obtain IP from -ip {address}", + 'web' => ": obtain IP from an IP discovery page on the web", + 'fw' => ": obtain IP from the firewall specified by -fw {type|address}", + 'if' => ": obtain IP from the -if {interface}", + 'cmd' => ": obtain IP from the -cmd {external-command}", + 'cisco' => ": obtain IP from Cisco FW at the -fw {address}", + 'cisco-asa' => ": obtain IP from Cisco ASA at the -fw {address}", + map { $_ => sprintf ": obtain IP from %s at the -fw {address}", $builtinfw{$_}->{'name'} } keys %builtinfw, ); sub ip_strategies_usage { return map { sprintf(" -use=%-22s %s.", $_, $ip_strategies{$_}) } sort keys %ip_strategies; } my %web_strategies = ( - 'dyndns'=> 1, - 'loopia'=> 1, + 'dyndns' => 1, + 'loopia' => 1, ); sub setv { return { - 'type' => shift, - 'required' => shift, - 'cache' => shift, - 'config' => shift, - 'default' => shift, - 'minimum' => shift, + 'type' => shift, + 'required' => shift, + 'cache' => shift, + 'config' => shift, + 'default' => shift, + 'minimum' => shift, }; }; my %variables = ( - 'global-defaults' => { - 'daemon' => setv(T_DELAY, 0, 0, 1, 0, interval('60s')), - 'foreground' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'file' => setv(T_FILE, 0, 0, 1, "$etc$program.conf", undef), - 'cache' => setv(T_FILE, 0, 0, 1, "$cachedir$program.cache", undef), - 'pid' => setv(T_FILE, 0, 0, 1, "", undef), - 'proxy' => setv(T_FQDNP, 0, 0, 1, '', undef), - 'protocol' => setv(T_PROTO, 0, 0, 1, 'dyndns2', undef), + 'global-defaults' => { + 'daemon' => setv(T_DELAY, 0, 0, 1, 0, interval('60s')), + 'foreground' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'file' => setv(T_FILE, 0, 0, 1, "$etc$program.conf", undef), + 'cache' => setv(T_FILE, 0, 0, 1, "$cachedir$program.cache", undef), + 'pid' => setv(T_FILE, 0, 0, 1, "", undef), + 'proxy' => setv(T_FQDNP, 0, 0, 1, '', undef), + 'protocol' => setv(T_PROTO, 0, 0, 1, 'dyndns2', undef), - 'use' => setv(T_USE, 0, 0, 1, 'ip', undef), - 'ip' => setv(T_IP, 0, 0, 1, undef, undef), - 'if' => setv(T_IF, 0, 0, 1, 'ppp0', undef), - 'if-skip' => setv(T_STRING,1, 0, 1, '', undef), - 'web' => setv(T_STRING,0, 0, 1, 'dyndns', undef), - 'web-skip' => setv(T_STRING,1, 0, 1, '', undef), - 'fw' => setv(T_ANY, 0, 0, 1, '', undef), - 'fw-skip' => setv(T_STRING,1, 0, 1, '', undef), - 'fw-banlocal' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'fw-login' => setv(T_LOGIN, 1, 0, 1, '', undef), - 'fw-password' => setv(T_PASSWD,1, 0, 1, '', undef), - 'cmd' => setv(T_PROG, 0, 0, 1, '', undef), - 'cmd-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'use' => setv(T_USE, 0, 0, 1, 'ip', undef), + 'ip' => setv(T_IP, 0, 0, 1, undef, undef), + 'if' => setv(T_IF, 0, 0, 1, 'ppp0', undef), + 'if-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'web' => setv(T_STRING,0, 0, 1, 'dyndns', undef), + 'web-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'fw' => setv(T_ANY, 0, 0, 1, '', undef), + 'fw-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'fw-banlocal' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'fw-login' => setv(T_LOGIN, 1, 0, 1, '', undef), + 'fw-password' => setv(T_PASSWD,1, 0, 1, '', undef), + 'cmd' => setv(T_PROG, 0, 0, 1, '', undef), + 'cmd-skip' => setv(T_STRING,1, 0, 1, '', undef), - 'timeout' => setv(T_DELAY, 0, 0, 1, interval('120s'), interval('120s')), - 'retry' => setv(T_BOOL, 0, 0, 0, 0, undef), - 'force' => setv(T_BOOL, 0, 0, 0, 0, undef), - 'ssl' => setv(T_BOOL, 0, 0, 0, 0, undef), - 'ipv6' => setv(T_BOOL, 0, 0, 0, 0, undef), - 'syslog' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'facility' => setv(T_STRING,0, 0, 1, 'daemon', undef), - 'priority' => setv(T_STRING,0, 0, 1, 'notice', undef), - 'mail' => setv(T_EMAIL, 0, 0, 1, '', undef), - 'mail-failure' => setv(T_EMAIL, 0, 0, 1, '', undef), + 'timeout' => setv(T_DELAY, 0, 0, 1, interval('120s'), interval('120s')), + 'retry' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'force' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'ssl' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'ipv6' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'syslog' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'facility' => setv(T_STRING,0, 0, 1, 'daemon', undef), + 'priority' => setv(T_STRING,0, 0, 1, 'notice', undef), + 'mail' => setv(T_EMAIL, 0, 0, 1, '', undef), + 'mail-failure' => setv(T_EMAIL, 0, 0, 1, '', undef), - 'exec' => setv(T_BOOL, 0, 0, 1, 1, undef), - 'debug' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'verbose' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'quiet' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'help' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'test' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'geturl' => setv(T_STRING,0, 0, 0, '', undef), + 'exec' => setv(T_BOOL, 0, 0, 1, 1, undef), + 'debug' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'verbose' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'quiet' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'help' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'test' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'geturl' => setv(T_STRING,0, 0, 0, '', undef), - 'postscript' => setv(T_POSTS, 0, 0, 1, '', undef), + 'postscript' => setv(T_POSTS, 0, 0, 1, '', undef), }, - 'service-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'members.dyndns.org', undef), - 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), - 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), - 'host' => setv(T_STRING, 1, 1, 1, '', undef), + 'service-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'members.dyndns.org', undef), + 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), + 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), + 'host' => setv(T_STRING, 1, 1, 1, '', undef), - 'use' => setv(T_USE, 0, 0, 1, 'ip', undef), - 'if' => setv(T_IF, 0, 0, 1, 'ppp0', undef), - 'if-skip' => setv(T_STRING,0, 0, 1, '', undef), - 'web' => setv(T_STRING,0, 0, 1, 'dyndns', undef), - 'web-skip' => setv(T_STRING,0, 0, 1, '', undef), - 'fw' => setv(T_ANY, 0, 0, 1, '', undef), - 'fw-skip' => setv(T_STRING,0, 0, 1, '', undef), - 'fw-banlocal' => setv(T_BOOL, 0, 0, 1, 0, undef), - 'fw-login' => setv(T_LOGIN, 0, 0, 1, '', undef), - 'fw-password' => setv(T_PASSWD,0, 0, 1, '', undef), - 'cmd' => setv(T_PROG, 0, 0, 1, '', undef), - 'cmd-skip' => setv(T_STRING,0, 0, 1, '', undef), - 'ipv6' => setv(T_BOOL, 0, 0, 0, 0, undef), - 'ip' => setv(T_IP, 0, 1, 0, undef, undef), - 'wtime' => setv(T_DELAY, 0, 1, 1, 0, interval('30s')), - 'mtime' => setv(T_NUMBER, 0, 1, 0, 0, undef), - 'atime' => setv(T_NUMBER, 0, 1, 0, 0, undef), - 'status' => setv(T_ANY, 0, 1, 0, '', undef), - 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('30s'), 0), - 'max-interval' => setv(T_DELAY, 0, 0, 1, interval('25d'), 0), - 'min-error-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), + 'use' => setv(T_USE, 0, 0, 1, 'ip', undef), + 'if' => setv(T_IF, 0, 0, 1, 'ppp0', undef), + 'if-skip' => setv(T_STRING,0, 0, 1, '', undef), + 'web' => setv(T_STRING,0, 0, 1, 'dyndns', undef), + 'web-skip' => setv(T_STRING,0, 0, 1, '', undef), + 'fw' => setv(T_ANY, 0, 0, 1, '', undef), + 'fw-skip' => setv(T_STRING,0, 0, 1, '', undef), + 'fw-banlocal' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'fw-login' => setv(T_LOGIN, 0, 0, 1, '', undef), + 'fw-password' => setv(T_PASSWD,0, 0, 1, '', undef), + 'cmd' => setv(T_PROG, 0, 0, 1, '', undef), + 'cmd-skip' => setv(T_STRING,0, 0, 1, '', undef), + 'ipv6' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'ip' => setv(T_IP, 0, 1, 0, undef, undef), + 'wtime' => setv(T_DELAY, 0, 1, 1, 0, interval('30s')), + 'mtime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'atime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'status' => setv(T_ANY, 0, 1, 0, '', undef), + 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('30s'), 0), + 'max-interval' => setv(T_DELAY, 0, 0, 1, interval('25d'), 0), + 'min-error-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), - 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), - 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), }, - 'dyndns-common-defaults' => { - 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), - 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), - }, - 'easydns-common-defaults' => { - 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), - 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), - }, - 'noip-common-defaults' => { - 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), - }, - 'noip-service-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'dynupdate.no-ip.com', undef), - 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), - 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), - 'host' => setv(T_STRING, 1, 1, 1, '', undef), - 'ip' => setv(T_IP, 0, 1, 0, undef, undef), - 'wtime' => setv(T_DELAY, 0, 1, 1, 0, interval('30s')), - 'mtime' => setv(T_NUMBER, 0, 1, 0, 0, undef), - 'atime' => setv(T_NUMBER, 0, 1, 0, 0, undef), - 'status' => setv(T_ANY, 0, 1, 0, '', undef), - 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('30s'), 0), - 'max-interval' => setv(T_DELAY, 0, 0, 1, interval('25d'), 0), - 'min-error-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), - 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), - 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), - }, - 'zoneedit-service-common-defaults' => { - 'zone' => setv(T_OFQDN, 0, 0, 1, undef, undef), - }, - 'dtdns-common-defaults' => { - 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), - 'client' => setv(T_STRING, 0, 1, 1, $program, undef), - }, - 'nsupdate-common-defaults' => { - 'ttl' => setv(T_NUMBER, 0, 1, 0, 600, undef), - 'zone' => setv(T_STRING, 1, 1, 1, '', undef), - 'tcp' => setv(T_BOOL, 0, 1, 1, 0, undef), - }, - 'cloudflare-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', undef), - 'zone' => setv(T_FQDN, 1, 0, 1, '', undef), - 'login' => setv(T_LOGIN, 0, 0, 1, 'token', undef), - 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), - 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'ttl' => setv(T_NUMBER, 1, 0, 1, 1, undef), - }, - 'googledomains-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'domains.google.com', undef), - }, - 'duckdns-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'www.duckdns.org', undef), - 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), - }, - 'freemyip-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'freemyip.com', undef), - 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), - }, - 'woima-common-defaults' => { + 'dyndns-common-defaults' => { 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), - 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, + 'easydns-common-defaults' => { + 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, + 'noip-common-defaults' => { + 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, + 'noip-service-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'dynupdate.no-ip.com', undef), + 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), + 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), + 'host' => setv(T_STRING, 1, 1, 1, '', undef), + 'ip' => setv(T_IP, 0, 1, 0, undef, undef), + 'wtime' => setv(T_DELAY, 0, 1, 1, 0, interval('30s')), + 'mtime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'atime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'status' => setv(T_ANY, 0, 1, 0, '', undef), + 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('30s'), 0), + 'max-interval' => setv(T_DELAY, 0, 0, 1, interval('25d'), 0), + 'min-error-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), + 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + }, + 'zoneedit-service-common-defaults' => { + 'zone' => setv(T_OFQDN, 0, 0, 1, undef, undef), + }, + 'dtdns-common-defaults' => { + 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), + 'client' => setv(T_STRING, 0, 1, 1, $program, undef), + }, + 'nsupdate-common-defaults' => { + 'ttl' => setv(T_NUMBER, 0, 1, 0, 600, undef), + 'zone' => setv(T_STRING, 1, 1, 1, '', undef), + 'tcp' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, + 'cloudflare-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', undef), + 'zone' => setv(T_FQDN, 1, 0, 1, '', undef), + 'login' => setv(T_LOGIN, 0, 0, 1, 'token', undef), + 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'ttl' => setv(T_NUMBER, 1, 0, 1, 1, undef), + }, + 'googledomains-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'domains.google.com', undef), + }, + 'duckdns-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'www.duckdns.org', undef), + 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), + }, + 'freemyip-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'freemyip.com', undef), + 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), + }, + 'woima-common-defaults' => { + 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), 'script' => setv(T_STRING, 1, 1, 1, '/nic/update', undef), }, - 'woima-service-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'dyn.woima.fi', undef), + 'woima-service-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'dyn.woima.fi', undef), 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), 'ip' => setv(T_IP, 0, 1, 0, undef, undef), @@ -478,178 +477,178 @@ my %variables = ( 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), }, - 'yandex-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'pddimp.yandex.ru', undef), + 'yandex-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'pddimp.yandex.ru', undef), }, - 'dnsmadeeasy-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'cp.dnsmadeeasy.com', undef), - 'script' => setv(T_STRING, 1, 1, 1, '/servlet/updateip', undef), + 'dnsmadeeasy-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'cp.dnsmadeeasy.com', undef), + 'script' => setv(T_STRING, 1, 1, 1, '/servlet/updateip', undef), }, - 'dondominio-common-defaults' => { - 'server' => setv(T_FQDNP, 1, 0, 1, 'dondns.dondominio.com', undef), + 'dondominio-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'dondns.dondominio.com', undef), }, ); my %services = ( 'dyndns1' => { - 'updateable' => \&nic_dyndns2_updateable, - 'update' => \&nic_dyndns1_update, - 'examples' => \&nic_dyndns1_examples, - 'variables' => merge( - $variables{'dyndns-common-defaults'}, - $variables{'service-common-defaults'}, - ), + 'updateable' => \&nic_dyndns2_updateable, + 'update' => \&nic_dyndns1_update, + 'examples' => \&nic_dyndns1_examples, + 'variables' => merge( + $variables{'dyndns-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'dyndns2' => { - 'updateable' => \&nic_dyndns2_updateable, - 'update' => \&nic_dyndns2_update, - 'examples' => \&nic_dyndns2_examples, - 'variables' => merge( - { 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), }, - { 'script' => setv(T_STRING, 1, 1, 1, '/nic/update', undef), }, -# { 'offline' => setv(T_BOOL, 0, 1, 1, 0, undef), }, - $variables{'dyndns-common-defaults'}, - $variables{'service-common-defaults'}, - ), + 'updateable' => \&nic_dyndns2_updateable, + 'update' => \&nic_dyndns2_update, + 'examples' => \&nic_dyndns2_examples, + 'variables' => merge( + { 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + { 'script' => setv(T_STRING, 1, 1, 1, '/nic/update', undef), }, + #{ 'offline' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + $variables{'dyndns-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'noip' => { - 'updateable' => undef, - 'update' => \&nic_noip_update, - 'examples' => \&nic_noip_examples, - 'variables' => merge( - { 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), }, - $variables{'noip-common-defaults'}, - $variables{'noip-service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_noip_update, + 'examples' => \&nic_noip_examples, + 'variables' => merge( + { 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + $variables{'noip-common-defaults'}, + $variables{'noip-service-common-defaults'}, + ), }, 'concont' => { 'updateable' => undef, 'update' => \&nic_concont_update, 'examples' => \&nic_concont_examples, 'variables' => merge( - $variables{'service-common-defaults'}, - { 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), }, - { 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), }, - ), + $variables{'service-common-defaults'}, + { 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), }, + { 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + ), }, 'dslreports1' => { - 'updateable' => undef, - 'update' => \&nic_dslreports1_update, - 'examples' => \&nic_dslreports1_examples, - 'variables' => merge( - { 'host' => setv(T_NUMBER, 1, 1, 1, 0, undef) }, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_dslreports1_update, + 'examples' => \&nic_dslreports1_examples, + 'variables' => merge( + { 'host' => setv(T_NUMBER, 1, 1, 1, 0, undef) }, + $variables{'service-common-defaults'}, + ), }, 'hammernode1' => { - 'updateable' => undef, - 'update' => \&nic_hammernode1_update, - 'examples' => \&nic_hammernode1_examples, - 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'dup.hn.org', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_hammernode1_update, + 'examples' => \&nic_hammernode1_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'dup.hn.org', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, + $variables{'service-common-defaults'}, + ), }, 'zoneedit1' => { - 'updateable' => undef, - 'update' => \&nic_zoneedit1_update, - 'examples' => \&nic_zoneedit1_examples, - 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'dynamic.zoneedit.com', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, - $variables{'service-common-defaults'}, - $variables{'zoneedit-service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_zoneedit1_update, + 'examples' => \&nic_zoneedit1_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'dynamic.zoneedit.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, + $variables{'service-common-defaults'}, + $variables{'zoneedit-service-common-defaults'}, + ), }, 'easydns' => { - 'updateable' => undef, - 'update' => \&nic_easydns_update, - 'examples' => \&nic_easydns_examples, - 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'members.easydns.com', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, - $variables{'easydns-common-defaults'}, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_easydns_update, + 'examples' => \&nic_easydns_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'members.easydns.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, + $variables{'easydns-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'namecheap' => { 'updateable' => undef, 'update' => \&nic_namecheap_update, 'examples' => \&nic_namecheap_examples, 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'dynamicdns.park-your-domain.com', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, - $variables{'service-common-defaults'}, - ), + { 'server' => setv(T_FQDNP, 1, 0, 1, 'dynamicdns.park-your-domain.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')), }, + $variables{'service-common-defaults'}, + ), }, 'nfsn' => { - 'updateable' => undef, - 'update' => \&nic_nfsn_update, - 'examples' => \&nic_nfsn_examples, - 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'api.nearlyfreespeech.net', undef) }, - { 'min_interval' => setv(T_FQDNP, 0, 0, 1, 0, interval('5m')) }, - { 'ttl' => setv(T_NUMBER, 1, 0, 1, 300, undef) }, - { 'zone' => setv(T_FQDN, 1, 0, 1, undef, undef) }, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_nfsn_update, + 'examples' => \&nic_nfsn_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'api.nearlyfreespeech.net', undef) }, + { 'min_interval' => setv(T_FQDNP, 0, 0, 1, 0, interval('5m')) }, + { 'ttl' => setv(T_NUMBER, 1, 0, 1, 300, undef) }, + { 'zone' => setv(T_FQDN, 1, 0, 1, undef, undef) }, + $variables{'service-common-defaults'}, + ), }, 'sitelutions' => { 'updateable' => undef, 'update' => \&nic_sitelutions_update, 'examples' => \&nic_sitelutions_examples, 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.sitelutions.com', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, - $variables{'service-common-defaults'}, - ), + { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.sitelutions.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')), }, + $variables{'service-common-defaults'}, + ), }, 'freedns' => { 'updateable' => undef, 'update' => \&nic_freedns_update, 'examples' => \&nic_freedns_examples, 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'freedns.afraid.org', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, - $variables{'service-common-defaults'}, - ), + { 'server' => setv(T_FQDNP, 1, 0, 1, 'freedns.afraid.org', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')), }, + $variables{'service-common-defaults'}, + ), }, 'changeip' => { 'updateable' => undef, 'update' => \&nic_changeip_update, 'examples' => \&nic_changeip_examples, 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'nic.changeip.com', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, - $variables{'service-common-defaults'}, - ), + { 'server' => setv(T_FQDNP, 1, 0, 1, 'nic.changeip.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')), }, + $variables{'service-common-defaults'}, + ), }, 'dtdns' => { - 'updateable' => undef, - 'update' => \&nic_dtdns_update, - 'examples' => \&nic_dtdns_examples, - 'variables' => merge( - $variables{'dtdns-common-defaults'}, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_dtdns_update, + 'examples' => \&nic_dtdns_examples, + 'variables' => merge( + $variables{'dtdns-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'nsupdate' => { - 'updateable' => undef, - 'update' => \&nic_nsupdate_update, - 'examples' => \&nic_nsupdate_examples, - 'variables' => merge( - { 'login' => setv(T_LOGIN, 1, 0, 1, '/usr/bin/nsupdate', undef), }, - $variables{'nsupdate-common-defaults'}, - $variables{'service-common-defaults'}, - ), + 'updateable' => undef, + 'update' => \&nic_nsupdate_update, + 'examples' => \&nic_nsupdate_examples, + 'variables' => merge( + { 'login' => setv(T_LOGIN, 1, 0, 1, '/usr/bin/nsupdate', undef), }, + $variables{'nsupdate-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'cloudflare' => { 'updateable' => undef, 'update' => \&nic_cloudflare_update, 'examples' => \&nic_cloudflare_examples, 'variables' => merge( - { 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', undef) }, - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + { 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, $variables{'cloudflare-common-defaults'}, $variables{'service-common-defaults'}, ), @@ -659,28 +658,28 @@ my %services = ( 'update' => \&nic_googledomains_update, 'examples' => \&nic_googledomains_examples, 'variables' => merge( - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, $variables{'googledomains-common-defaults'}, $variables{'service-common-defaults'}, - ), + ), }, 'duckdns' => { 'updateable' => undef, 'update' => \&nic_duckdns_update, 'examples' => \&nic_duckdns_examples, 'variables' => merge( - $variables{'duckdns-common-defaults'}, - $variables{'service-common-defaults'}, - ), + $variables{'duckdns-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'freemyip' => { 'updateable' => undef, 'update' => \&nic_freemyip_update, 'examples' => \&nic_freemyip_examples, 'variables' => merge( - $variables{'freemyip-common-defaults'}, - $variables{'service-common-defaults'}, - ), + $variables{'freemyip-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'woima' => { 'updateable' => undef, @@ -696,19 +695,19 @@ my %services = ( 'update' => \&nic_yandex_update, 'examples' => \&nic_yandex_examples, 'variables' => merge( - { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), }, $variables{'yandex-common-defaults'}, $variables{'service-common-defaults'}, - ), + ), }, 'dnsmadeeasy' => { 'updateable' => undef, 'update' => \&nic_dnsmadeeasy_update, 'examples' => \&nic_dnsmadeeasy_examples, 'variables' => merge( - $variables{'dnsmadeeasy-common-defaults'}, - $variables{'service-common-defaults'}, - ), + $variables{'dnsmadeeasy-common-defaults'}, + $variables{'service-common-defaults'}, + ), }, 'dondominio' => { 'updateable' => undef, @@ -717,7 +716,7 @@ my %services = ( 'variables' => merge( $variables{'dondominio-common-defaults'}, $variables{'service-common-defaults'}, - ), + ), }, ); $variables{'merged'} = merge($variables{'global-defaults'}, @@ -742,7 +741,7 @@ my @opt = ( [ "pid", "=s", "-pid path : record process id in 'path'" ], "", [ "use", "=s", "-use which : how the should IP address be obtained." ], - &ip_strategies_usage(), + &ip_strategies_usage(), "", [ "ip", "=s", "-ip address : set the IP address to 'address'" ], "", @@ -754,7 +753,7 @@ my @opt = ( "", [ "fw", "=s", "-fw address|url : obtain IP address from firewall at 'address'" ], [ "fw-skip", "=s", "-fw-skip pattern : skip any IP addresses before 'pattern' on the firewall address|url" ], - [ "fw-banlocal", "!", "-fw-banlocal : ignore local IP addresses on the firewall address|url" ], + [ "fw-banlocal", "!", "-fw-banlocal : ignore local IP addresses on the firewall address|url" ], [ "fw-login", "=s", "-fw-login login : use 'login' when getting IP from fw" ], [ "fw-password", "=s", "-fw-password secret : use password 'secret' when getting IP from fw" ], "", @@ -799,7 +798,7 @@ my @opt = ( my $opt_usage = process_args(@opt); my ($result, %config, %globals, %cache); my $saved_cache = ''; -my %saved_opt = %opt; +my %saved_opt = %opt; $result = 'OK'; test_geturl(opt('geturl')) if opt('geturl'); @@ -813,7 +812,7 @@ if (opt('help')) { ## read config file because 'daemon' mode may be defined there. read_config(define($opt{'file'}, default('file')), \%config, \%globals); init_config(); -test_possible_ip() if opt('query'); +test_possible_ip() if opt('query'); if (!opt('daemon') && $programd =~ /d$/) { $opt{'daemon'} = minimum('daemon'); @@ -821,29 +820,29 @@ if (!opt('daemon') && $programd =~ /d$/) { my $caught_hup = 0; my $caught_term = 0; my $caught_int = 0; -$SIG{'HUP'} = sub { $caught_hup = 1; }; -$SIG{'TERM'} = sub { $caught_term = 1; }; -$SIG{'INT'} = sub { $caught_int = 1; }; +$SIG{'HUP'} = sub { $caught_hup = 1; }; +$SIG{'TERM'} = sub { $caught_term = 1; }; +$SIG{'INT'} = sub { $caught_int = 1; }; # don't fork() if foreground or force is on if (opt('foreground') || opt('force')) { ; } elsif (opt('daemon')) { - $SIG{'CHLD'} = 'IGNORE'; + $SIG{'CHLD'} = 'IGNORE'; my $pid = fork; if ($pid < 0) { - print STDERR "${program}: can not fork ($!)\n"; - exit -1; + print STDERR "${program}: can not fork ($!)\n"; + exit -1; } elsif ($pid) { - exit 0; + exit 0; } - $SIG{'CHLD'} = 'DEFAULT'; + $SIG{'CHLD'} = 'DEFAULT'; open(STDOUT, ">/dev/null"); open(STDERR, ">/dev/null"); open(STDIN, " 0) && !$caught_hup && !$caught_term && !$caught_int) { - my $delay = $left > 10 ? 10 : $left; + my $left = $daemon; + while (($left > 0) && !$caught_hup && !$caught_term && !$caught_int) { + my $delay = $left > 10 ? 10 : $left; - $0 = sprintf("%s - sleeping for %s seconds", $program, $left); - $left -= sleep $delay; - # preventing deep sleep - see [bugs:#46] - if ($left > $daemon) { - $left = $daemon; - } - } - $caught_hup = 0; - $result = 0; + $0 = sprintf("%s - sleeping for %s seconds", $program, $left); + $left -= sleep $delay; + # preventing deep sleep - see [bugs:#46] + if ($left > $daemon) { + $left = $daemon; + } + } + $caught_hup = 0; + $result = 0; - } elsif (! scalar(%config)) { - warning("no hosts to update.") unless !opt('quiet') || opt('verbose') || !$daemon; - $result = 1; + } elsif (!scalar(%config)) { + warning("no hosts to update.") unless !opt('quiet') || opt('verbose') || !$daemon; + $result = 1; } else { - $result = $result eq 'OK' ? 0 : 1; + $result = $result eq 'OK' ? 0 : 1; } } while ($daemon && !$result && !$caught_term && !$caught_int); @@ -912,83 +911,83 @@ exit($result); ###################################################################### sub runpostscript { - my ($ip) = @_; + my ($ip) = @_; - if ( defined $globals{postscript} ) { - if ( -x $globals{postscript}) { - system ("$globals{postscript} $ip &"); - } else { - warning ("Can not execute post script: %s", $globals{postscript}); - } - } + if (defined $globals{postscript}) { + if (-x $globals{postscript}) { + system("$globals{postscript} $ip &"); + } else { + warning("Can not execute post script: %s", $globals{postscript}); + } + } } ###################################################################### ## update_nics ###################################################################### sub update_nics { - my %examined = (); - my %iplist = (); + my %examined = (); + my %iplist = (); - foreach my $s (sort keys %services) { - my (@hosts, %ips) = (); - my $updateable = $services{$s}{'updateable'}; - my $update = $services{$s}{'update'}; + foreach my $s (sort keys %services) { + my (@hosts, %ips) = (); + my $updateable = $services{$s}{'updateable'}; + my $update = $services{$s}{'update'}; - foreach my $h (sort keys %config) { - next if $config{$h}{'protocol'} ne lc($s); - $examined{$h} = 1; - # we only do this once per 'use' and argument combination - my $use = opt('use', $h); - my $arg_ip = opt('ip', $h) || ''; - my $arg_fw = opt('fw', $h) || ''; - my $arg_if = opt('if', $h) || ''; - my $arg_web = opt('web', $h) || ''; - my $arg_cmd = opt('cmd', $h) || ''; - my $ip = ""; - if (exists $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd}) { - $ip = $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd}; - } else { - $ip = get_ip($use, $h); - if (!defined $ip || !$ip) { - warning("unable to determine IP address") - if !$daemon || opt('verbose'); - next; - } - if ($ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { - if( !ipv6_match($ip) ) { - warning("malformed IP address (%s)", $ip); - next; + foreach my $h (sort keys %config) { + next if $config{$h}{'protocol'} ne lc($s); + $examined{$h} = 1; + # we only do this once per 'use' and argument combination + my $use = opt('use', $h); + my $arg_ip = opt('ip', $h) || ''; + my $arg_fw = opt('fw', $h) || ''; + my $arg_if = opt('if', $h) || ''; + my $arg_web = opt('web', $h) || ''; + my $arg_cmd = opt('cmd', $h) || ''; + my $ip = ""; + if (exists $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd}) { + $ip = $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd}; + } else { + $ip = get_ip($use, $h); + if (!defined $ip || !$ip) { + warning("unable to determine IP address") + if !$daemon || opt('verbose'); + next; + } + if ($ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { + if (!ipv6_match($ip)) { + warning("malformed IP address (%s)", $ip); + next; } - } - $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd} = $ip; - } - $config{$h}{'wantip'} = $ip; - next if !nic_updateable($h, $updateable); - push @hosts, $h; - $ips{$ip} = $h; - } - if (@hosts) { - $0 = sprintf("%s - updating %s", $program, join(',', @hosts)); - &$update(@hosts); - runpostscript(join ' ', keys %ips); - } - } - foreach my $h (sort keys %config) { - if (!exists $examined{$h}) { - failed("%s was not updated because protocol %s is not supported.", - $h, define($config{$h}{'protocol'}, '') - ); - } - } - write_cache(opt('cache')); + } + $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd} = $ip; + } + $config{$h}{'wantip'} = $ip; + next if !nic_updateable($h, $updateable); + push @hosts, $h; + $ips{$ip} = $h; + } + if (@hosts) { + $0 = sprintf("%s - updating %s", $program, join(',', @hosts)); + &$update(@hosts); + runpostscript(join ' ', keys %ips); + } + } + foreach my $h (sort keys %config) { + if (!exists $examined{$h}) { + failed("%s was not updated because protocol %s is not supported.", + $h, define($config{$h}{'protocol'}, '') + ); + } + } + write_cache(opt('cache')); } ###################################################################### ## unlink_pid() ###################################################################### sub unlink_pid { if (opt('pid') && opt('daemon')) { - unlink opt('pid'); + unlink opt('pid'); } } @@ -1000,13 +999,13 @@ sub write_pid { if ($file && opt('daemon')) { local *FD; - if (! open(FD, "> $file")) { - warning("Cannot create file '%s'. ($!)", $file); + if (!open(FD, "> $file")) { + warning("Cannot create file '%s'. ($!)", $file); - } else { - printf FD "$$\n"; - close(FD); - } + } else { + printf FD "$$\n"; + close(FD); + } } } @@ -1018,18 +1017,18 @@ sub write_cache { ## merge the updated host entries into the cache. foreach my $h (keys %config) { - if (! exists $cache{$h} || $config{$h}{'update'}) { - map {$cache{$h}{$_} = $config{$h}{$_} } @{$config{$h}{'cacheable'}}; + if (!exists $cache{$h} || $config{$h}{'update'}) { + map { $cache{$h}{$_} = $config{$h}{$_} } @{$config{$h}{'cacheable'}}; - } else { - map {$cache{$h}{$_} = $config{$h}{$_} } qw(atime wtime status); - } + } else { + map { $cache{$h}{$_} = $config{$h}{$_} } qw(atime wtime status); + } } ## construct the cache file. my $cache = ""; foreach my $h (sort keys %cache) { - my $opt = join(',', map { "$_=".define($cache{$h}{$_},'') } sort keys %{$cache{$h}}); + my $opt = join(',', map { "$_=" . define($cache{$h}{$_},'') } sort keys %{$cache{$h}}); $cache .= sprintf "%s%s%s\n", $opt, ($opt ? ' ' : ''), $h; } @@ -1037,16 +1036,16 @@ sub write_cache { ## write the updates and other entries to the cache file. if ($file) { - $saved_cache = undef; - local *FD; - if (! open(FD, "> $file")) { - fatal("Cannot create file '%s'. ($!)", $file); - } - printf FD "## $program-$version\n"; - printf FD "## last updated at %s (%d)\n", prettytime($now), $now; - printf FD $cache; + $saved_cache = undef; + local *FD; + if (!open(FD, "> $file")) { + fatal("Cannot create file '%s'. ($!)", $file); + } + printf FD "## $program-$version\n"; + printf FD "## last updated at %s (%d)\n", prettytime($now), $now; + printf FD $cache; - close(FD); + close(FD); } } ###################################################################### @@ -1060,18 +1059,18 @@ sub read_cache { %{$config} = (); ## read the cache file ignoring anything on the command-line. if (-e $file) { - my %saved = %opt; - %opt = (); - $saved_cache = _read_config($config, $globals, "##\\s*$program-$version\\s*", $file); - %opt = %saved; + my %saved = %opt; + %opt = (); + $saved_cache = _read_config($config, $globals, "##\\s*$program-$version\\s*", $file); + %opt = %saved; - foreach my $h (keys %cache) { - if (exists $config->{$h}) { - foreach (qw(atime mtime wtime ip status)) { - $config->{$h}{$_} = $cache{$h}{$_} if exists $cache{$h}{$_}; - } - } - } + foreach my $h (keys %cache) { + if (exists $config->{$h}) { + foreach (qw(atime mtime wtime ip status)) { + $config->{$h}{$_} = $cache{$h}{$_} if exists $cache{$h}{$_}; + } + } + } } } ###################################################################### @@ -1079,48 +1078,48 @@ sub read_cache { ## parse_assignment(string) return (name, value, rest) ###################################################################### sub parse_assignments { - my $rest = shift; - my @args = @_; + my $rest = shift; + my @args = @_; my %variables = (); my ($name, $value); while (1) { - $rest =~ s/^\s+//; + $rest =~ s/^\s+//; ($name, $value, $rest) = parse_assignment($rest, @args); - if (defined $name) { - $variables{$name} = $value; - } else { - last; - } + if (defined $name) { + $variables{$name} = $value; + } else { + last; + } } return ($rest, %variables); } sub parse_assignment { - my $rest = shift; - my $stop = @_ ? shift : '[\n\s,]'; + my $rest = shift; + my $stop = @_ ? shift : '[\n\s,]'; my ($c, $name, $value); my ($escape, $quote) = (0, ''); if ($rest =~ /^\s*([a-z][0-9a-z_-]*)=(.*)/i) { - ($name, $rest, $value) = ($1, $2, ''); + ($name, $rest, $value) = ($1, $2, ''); - while (length($c = substr($rest,0,1))) { - $rest = substr($rest,1); - if ($escape) { - $value .= $c; - $escape = 0; - } elsif ($c eq "\\") { - $escape = 1; - } elsif ($quote && $c eq $quote) { - $quote = '' - } elsif (!$quote && $c =~ /[\'\"]/) { - $quote = $c; - } elsif (!$quote && $c =~ /^${stop}/) { - last; - } else { - $value .= $c; - } - } + while (length($c = substr($rest, 0, 1))) { + $rest = substr($rest,1); + if ($escape) { + $value .= $c; + $escape = 0; + } elsif ($c eq "\\") { + $escape = 1; + } elsif ($quote && $c eq $quote) { + $quote = '' + } elsif (!$quote && $c =~ /[\'\"]/) { + $quote = $c; + } elsif (!$quote && $c =~ /^${stop}/) { + last; + } else { + $value .= $c; + } + } } warning("assignment ended with an open quote") if $quote; return ($name, $value, $rest); @@ -1129,10 +1128,10 @@ sub parse_assignment { ## read_config ###################################################################### sub read_config { - my $file = shift; - my $config = shift; - my $globals = shift; - my %globals = (); + my $file = shift; + my $config = shift; + my $globals = shift; + my %globals = (); _read_config($config, $globals, '', $file, %globals); } @@ -1146,119 +1145,119 @@ sub _read_config { my $content = ''; local *FD; - if (! open(FD, "< $file")) { - # fatal("Cannot open file '%s'. ($!)", $file); - warning("Cannot open file '%s'. ($!)", $file); + if (!open(FD, "< $file")) { + # fatal("Cannot open file '%s'. ($!)", $file); + warning("Cannot open file '%s'. ($!)", $file); } # Check for only owner has any access to config file my ($dev, $ino, $mode, @statrest) = stat(FD); if ($mode & 077) { - if (-f FD && (chmod 0600, $file)) { - warning("file $file must be accessible only by its owner (fixed)."); - } else { - # fatal("file $file must be accessible only by its owner."); - warning("file $file must be accessible only by its owner."); - } + if (-f FD && (chmod 0600, $file)) { + warning("file $file must be accessible only by its owner (fixed)."); + } else { + # fatal("file $file must be accessible only by its owner."); + warning("file $file must be accessible only by its owner."); + } } - local $lineno = 0; - my $continuation = ''; - my %passwords = (); + local $lineno = 0; + my $continuation = ''; + my %passwords = (); while () { - s/[\r\n]//g; + s/[\r\n]//g; - $lineno++; + $lineno++; - ## check for the program version stamp - if (($. == 1) && $stamp && ($_ !~ /^$stamp$/i)) { - warning("program version mismatch; ignoring %s", $file); - last; - } - if (/\\\s+$/) { - warning("whitespace follows the \\ at the end-of-line.\nIf you meant to have a line continuation, remove the trailing whitespace."); - } + ## check for the program version stamp + if (($. == 1) && $stamp && ($_ !~ /^$stamp$/i)) { + warning("program version mismatch; ignoring %s", $file); + last; + } + if (/\\\s+$/) { + warning("whitespace follows the \\ at the end-of-line.\nIf you meant to have a line continuation, remove the trailing whitespace."); + } - $content .= "$_\n" unless /^#/; + $content .= "$_\n" unless /^#/; - ## parsing passwords is special - if (/^([^#]*\s)?([^#]*?password\S*?)\s*=\s*('.*'|[^']\S*)(.*)/) { - my ($head, $key, $value, $tail) = ($1 || '', $2, $3, $4); - $value = $1 if $value =~ /^'(.*)'$/; - $passwords{$key} = $value; - $_ = "${head}${key}=dummy${tail}"; - } + ## parsing passwords is special + if (/^([^#]*\s)?([^#]*?password\S*?)\s*=\s*('.*'|[^']\S*)(.*)/) { + my ($head, $key, $value, $tail) = ($1 || '', $2, $3, $4); + $value = $1 if $value =~ /^'(.*)'$/; + $passwords{$key} = $value; + $_ = "${head}${key}=dummy${tail}"; + } ## remove comments - s/#.*//; + s/#.*//; - ## handle continuation lines - $_ = "$continuation$_"; - if (/\\$/) { - chop; - $continuation = $_; - next; - } - $continuation = ''; - - s/^\s+//; # remove leading white space - s/\s+$//; # remove trailing white space - s/\s+/ /g; # canonify - next if /^$/; - - ## expected configuration line is: - ## [opt=value,opt=..] [host [login [password]]] - my %locals; - ($_, %locals) = parse_assignments($_); - s/\s*,\s*/,/g; - my @args = split; - - ## verify that keywords are valid...and check the value - foreach my $k (keys %locals) { - $locals{$k} = $passwords{$k} if defined $passwords{$k}; - if (!exists $variables{'merged'}{$k}) { - warning("unrecognized keyword '%s' (ignored)", $k); - delete $locals{$k}; - } else { - my $def = $variables{'merged'}{$k}; - my $value = check_value($locals{$k}, $def); - if (!defined($value)) { - warning("Invalid Value for keyword '%s' = '%s'", $k, $locals{$k}); - delete $locals{$k}; - } else { $locals{$k} = $value; } + ## handle continuation lines + $_ = "$continuation$_"; + if (/\\$/) { + chop; + $continuation = $_; + next; } - } - if (exists($locals{'host'})) { - $args[0] = @args ? "$args[0],$locals{host}" : "$locals{host}"; - } - ## accumulate globals - if ($#args < 0) { - map { $globals{$_} = $locals{$_} } keys %locals; - } + $continuation = ''; - ## process this host definition - if (@args) { - my ($host, $login, $password) = @args; + s/^\s+//; # remove leading white space + s/\s+$//; # remove trailing white space + s/\s+/ /g; # canonify + next if /^$/; - ## add in any globals.. - %locals = %{ merge(\%locals, \%globals) }; + ## expected configuration line is: + ## [opt=value,opt=..] [host [login [password]]] + my %locals; + ($_, %locals) = parse_assignments($_); + s/\s*,\s*/,/g; + my @args = split; - ## override login and password if specified the old way. - $locals{'login'} = $login if defined $login; - $locals{'password'} = $password if defined $password; + ## verify that keywords are valid...and check the value + foreach my $k (keys %locals) { + $locals{$k} = $passwords{$k} if defined $passwords{$k}; + if (!exists $variables{'merged'}{$k}) { + warning("unrecognized keyword '%s' (ignored)", $k); + delete $locals{$k}; + } else { + my $def = $variables{'merged'}{$k}; + my $value = check_value($locals{$k}, $def); + if (!defined($value)) { + warning("Invalid Value for keyword '%s' = '%s'", $k, $locals{$k}); + delete $locals{$k}; + } else { $locals{$k} = $value; } + } + } + if (exists($locals{'host'})) { + $args[0] = @args ? "$args[0],$locals{host}" : "$locals{host}"; + } + ## accumulate globals + if ($#args < 0) { + map { $globals{$_} = $locals{$_} } keys %locals; + } - ## allow {host} to be a comma separated list of hosts - foreach my $h (split_by_comma($host)) { - ## save a copy of the current globals - $config{$h} = { %locals }; - $config{$h}{'host'} = $h; - } - } - %passwords = (); + ## process this host definition + if (@args) { + my ($host, $login, $password) = @args; + + ## add in any globals.. + %locals = %{merge(\%locals, \%globals)}; + + ## override login and password if specified the old way. + $locals{'login'} = $login if defined $login; + $locals{'password'} = $password if defined $password; + + ## allow {host} to be a comma separated list of hosts + foreach my $h (split_by_comma($host)) { + ## save a copy of the current globals + $config{$h} = { %locals }; + $config{$h}{'host'} = $h; + } + } + %passwords = (); } close(FD); warning("file ends while expecting a continuation line.") - if $continuation; + if $continuation; %$globals = %globals; %$config = %config; @@ -1272,7 +1271,7 @@ sub init_config { %opt = %saved_opt; ## - $opt{'quiet'} = 0 if opt('verbose'); + $opt{'quiet'} = 0 if opt('verbose'); ## infer the IP strategy if possible $opt{'use'} = 'ip' if !define($opt{'use'}) && defined($opt{'ip'}); @@ -1284,67 +1283,67 @@ sub init_config { $opt{'min-interval'} = max(interval(opt('min-interval')), interval(default('min-interval'))); $opt{'min-error-interval'} = max(interval(opt('min-error-interval')), interval(default('min-error-interval'))); - $opt{'timeout'} = 0 if opt('timeout') < 0; + $opt{'timeout'} = 0 if opt('timeout') < 0; ## only set $opt{'daemon'} if it has been explicitly passed in - if (define($opt{'daemon'},$globals{'daemon'},0)) { + if (define($opt{'daemon'}, $globals{'daemon'}, 0)) { $opt{'daemon'} = interval(opt('daemon')); $opt{'daemon'} = minimum('daemon') - if ($opt{'daemon'} < minimum('daemon')); + if ($opt{'daemon'} < minimum('daemon')); } ## define or modify host options specified on the command-line if (exists $opt{'options'} && defined $opt{'options'}) { - ## collect cmdline configuration options. - my %options = (); - foreach my $opt (split_by_comma($opt{'options'})) { - my ($name,$var) = split /\s*=\s*/, $opt; - $options{$name} = $var; - } - ## determine hosts specified with -host - my @hosts = (); - if (exists $opt{'host'}) { - foreach my $h (split_by_comma($opt{'host'})) { - push @hosts, $h; - } - } - ## and those in -options=... - if (exists $options{'host'}) { - foreach my $h (split_by_comma($options{'host'})) { - push @hosts, $h; - } - delete $options{'host'}; - } - ## merge options into host definitions or globals - if (@hosts) { - foreach my $h (@hosts) { - $config{$h} = merge(\%options, $config{$h}); - } - $opt{'host'} = join(',', @hosts); - } else { - %globals = %{ merge(\%options, \%globals) }; - } + ## collect cmdline configuration options. + my %options = (); + foreach my $opt (split_by_comma($opt{'options'})) { + my ($name, $var) = split /\s*=\s*/, $opt; + $options{$name} = $var; + } + ## determine hosts specified with -host + my @hosts = (); + if (exists $opt{'host'}) { + foreach my $h (split_by_comma($opt{'host'})) { + push @hosts, $h; + } + } + ## and those in -options=... + if (exists $options{'host'}) { + foreach my $h (split_by_comma($options{'host'})) { + push @hosts, $h; + } + delete $options{'host'}; + } + ## merge options into host definitions or globals + if (@hosts) { + foreach my $h (@hosts) { + $config{$h} = merge(\%options, $config{$h}); + } + $opt{'host'} = join(',', @hosts); + } else { + %globals = %{merge(\%options, \%globals)}; + } } ## override global options with those on the command-line. foreach my $o (keys %opt) { if (defined $opt{$o} && exists $variables{'global-defaults'}{$o}) { $globals{$o} = $opt{$o}; - } + } } ## sanity check if (defined $opt{'host'} && defined $opt{'retry'}) { - usage("options -retry and -host (or -option host=..) are mutually exclusive"); + usage("options -retry and -host (or -option host=..) are mutually exclusive"); } ## determine hosts to update (those on the cmd-line, config-file, or failed cached) my @hosts = keys %config; if (opt('host')) { - @hosts = split_by_comma($opt{'host'}); + @hosts = split_by_comma($opt{'host'}); } if (opt('retry')) { - @hosts = map { $_ if $cache{$_}{'status'} ne 'good' } keys %cache; + @hosts = map { $_ if $cache{$_}{'status'} ne 'good' } keys %cache; } ## remove any other hosts @@ -1354,11 +1353,11 @@ sub init_config { ## collect the cacheable variables. foreach my $proto (keys %services) { - my @cacheable = (); - foreach my $k (keys %{$services{$proto}{'variables'}}) { - push @cacheable, $k if $services{$proto}{'variables'}{$k}{'cache'}; - } - $services{$proto}{'cacheable'} = [ @cacheable ]; + my @cacheable = (); + foreach my $k (keys %{$services{$proto}{'variables'}}) { + push @cacheable, $k if $services{$proto}{'variables'}{$k}{'cache'}; + } + $services{$proto}{'cacheable'} = [ @cacheable ]; } ## sanity check.. @@ -1366,48 +1365,48 @@ sub init_config { ## first the globals... foreach my $k (keys %globals) { my $def = $variables{'merged'}{$k}; - my $ovalue = define($globals{$k}, $def->{'default'}); - my $value = check_value($ovalue, $def); - if ($def->{'required'} && !defined $value) { - $value = default($k); - warning("'%s=%s' is an invalid %s. (using default of %s)", $k, $ovalue, $def->{'type'}, $value); - } - $globals{$k} = $value; + my $ovalue = define($globals{$k}, $def->{'default'}); + my $value = check_value($ovalue, $def); + if ($def->{'required'} && !defined $value) { + $value = default($k); + warning("'%s=%s' is an invalid %s. (using default of %s)", $k, $ovalue, $def->{'type'}, $value); + } + $globals{$k} = $value; } ## now the host definitions... HOST: foreach my $h (keys %config) { - my $proto; - $proto = $config{$h}{'protocol'}; - $proto = opt('protocol') if !defined($proto); + my $proto; + $proto = $config{$h}{'protocol'}; + $proto = opt('protocol') if !defined($proto); - load_sha1_support($proto) if (grep (/^$proto$/, ("freedns", "nfsn"))); - load_json_support($proto) if (grep (/^$proto$/, ("cloudflare","yandex","nfsn"))); + load_sha1_support($proto) if (grep (/^$proto$/, ("freedns", "nfsn"))); + load_json_support($proto) if (grep (/^$proto$/, ("cloudflare","yandex", "nfsn"))); - if (!exists($services{$proto})) { - warning("skipping host: %s: unrecognized protocol '%s'", $h, $proto); - delete $config{$h}; + if (!exists($services{$proto})) { + warning("skipping host: %s: unrecognized protocol '%s'", $h, $proto); + delete $config{$h}; - } else { - my $svars = $services{$proto}{'variables'}; - my $conf = { 'protocol' => $proto }; + } else { + my $svars = $services{$proto}{'variables'}; + my $conf = { 'protocol' => $proto }; - foreach my $k (keys %$svars) { - my $def = $svars->{$k}; - my $ovalue = define($config{$h}{$k}, $def->{'default'}); - my $value = check_value($ovalue, $def); - if ($def->{'required'} && !defined $value) { - warning("skipping host: %s: '%s=%s' is an invalid %s.", $h, $k, $ovalue, $def->{'type'}); - delete $config{$h}; - next HOST; - } - $conf->{$k} = $value; + foreach my $k (keys %$svars) { + my $def = $svars->{$k}; + my $ovalue = define($config{$h}{$k}, $def->{'default'}); + my $value = check_value($ovalue, $def); + if ($def->{'required'} && !defined $value) { + warning("skipping host: %s: '%s=%s' is an invalid %s.", $h, $k, $ovalue, $def->{'type'}); + delete $config{$h}; + next HOST; + } + $conf->{$k} = $value; - } - $config{$h} = $conf; - $config{$h}{'cacheable'} = [ @{$services{$proto}{'cacheable'}} ]; - } + } + $config{$h} = $conf; + $config{$h}{'cacheable'} = [ @{$services{$proto}{'cacheable'}} ]; + } } } @@ -1416,13 +1415,13 @@ sub init_config { ###################################################################### sub usage { my $exitcode = 1; - $exitcode = shift if @_ != 0; # use first arg if given + $exitcode = shift if @_ != 0; # use first arg if given my $msg = ''; if (@_) { - my $format = shift; - $msg .= sprintf $format, @_; - 1 while chomp($msg); - $msg .= "\n"; + my $format = shift; + $msg .= sprintf $format, @_; + 1 while chomp($msg); + $msg .= "\n"; } printf STDERR "%s%s\n", $msg, $opt_usage; sendmail(); @@ -1437,39 +1436,39 @@ sub process_args { my $usage = ""; foreach (@_) { - if (ref $_) { - my ($key, $specifier, $arg_usage) = @$_; - my $value = default($key); + if (ref $_) { + my ($key, $specifier, $arg_usage) = @$_; + my $value = default($key); - ## add a option specifier - push @spec, $key . $specifier; + ## add a option specifier + push @spec, $key . $specifier; - ## define the default value which can be overwritten later - $opt{$key} = undef; + ## define the default value which can be overwritten later + $opt{$key} = undef; - next unless $arg_usage; + next unless $arg_usage; - ## add a line to the usage; - $usage .= " $arg_usage"; - if (defined($value) && $value ne '') { - $usage .= " (default: "; - if ($specifier eq '!') { - $usage .= "no" if ($specifier eq '!') && !$value; - $usage .= $key; - } else { - $usage .= $value; - } - $usage .= ")"; - } - $usage .= "."; - } else { - $usage .= $_; - } - $usage .= "\n"; + ## add a line to the usage; + $usage .= " $arg_usage"; + if (defined($value) && $value ne '') { + $usage .= " (default: "; + if ($specifier eq '!') { + $usage .= "no" if ($specifier eq '!') && !$value; + $usage .= $key; + } else { + $usage .= $value; + } + $usage .= ")"; + } + $usage .= "."; + } else { + $usage .= $_; + } + $usage .= "\n"; } ## process the arguments - if (! GetOptions(\%opt, @spec)) { - $opt{"help"} = 1; + if (!GetOptions(\%opt, @spec)) { + $opt{"help"} = 1; } return $usage; } @@ -1480,40 +1479,40 @@ sub test_possible_ip { local $opt{'debug'} = 0; printf "use=ip, ip=%s address is %s\n", opt('ip'), define(get_ip('ip'), 'NOT FOUND') - if defined opt('ip'); + if defined opt('ip'); { - local $opt{'use'} = 'if'; - foreach my $if (grep {/^[a-zA-Z]/} `ifconfig -a`) { - $if =~ s/:?\s.*//is; - local $opt{'if'} = $if; - printf "use=if, if=%s address is %s\n", opt('if'), define(get_ip('if'), 'NOT FOUND'); - } + local $opt{'use'} = 'if'; + foreach my $if (grep {/^[a-zA-Z]/} `ifconfig -a`) { + $if =~ s/:?\s.*//is; + local $opt{'if'} = $if; + printf "use=if, if=%s address is %s\n", opt('if'), define(get_ip('if'), 'NOT FOUND'); + } } if (opt('fw')) { - if (opt('fw') !~ m%/%) { - foreach my $fw (sort keys %builtinfw) { - local $opt{'use'} = $fw; - printf "use=$fw address is %s\n", define(get_ip($fw), 'NOT FOUND'); - } - } - local $opt{'use'} = 'fw'; - printf "use=fw, fw=%s address is %s\n", opt('fw'), define(get_ip(opt('fw')), 'NOT FOUND') - if ! exists $builtinfw{opt('fw')}; + if (opt('fw') !~ m%/%) { + foreach my $fw (sort keys %builtinfw) { + local $opt{'use'} = $fw; + printf "use=$fw address is %s\n", define(get_ip($fw), 'NOT FOUND'); + } + } + local $opt{'use'} = 'fw'; + printf "use=fw, fw=%s address is %s\n", opt('fw'), define(get_ip(opt('fw')), 'NOT FOUND') + if !exists $builtinfw{opt('fw')}; } { - local $opt{'use'} = 'web'; - foreach my $web (sort keys %builtinweb) { - local $opt{'web'} = $web; - printf "use=web, web=$web address is %s\n", define(get_ip('web'), 'NOT FOUND'); - } - printf "use=web, web=%s address is %s\n", opt('web'), define(get_ip('web'), 'NOT FOUND') - if ! exists $builtinweb{opt('web')}; + local $opt{'use'} = 'web'; + foreach my $web (sort keys %builtinweb) { + local $opt{'web'} = $web; + printf "use=web, web=$web address is %s\n", define(get_ip('web'), 'NOT FOUND'); + } + printf "use=web, web=%s address is %s\n", opt('web'), define(get_ip('web'), 'NOT FOUND') + if !exists $builtinweb{opt('web')}; } if (opt('cmd')) { - local $opt{'use'} = 'cmd'; - printf "use=cmd, cmd=%s address is %s\n", opt('cmd'), define(get_ip('cmd'), 'NOT FOUND'); + local $opt{'use'} = 'cmd'; + printf "use=cmd, cmd=%s address is %s\n", opt('cmd'), define(get_ip('cmd'), 'NOT FOUND'); } exit 0 unless opt('debug'); } @@ -1536,17 +1535,17 @@ sub load_file { my $buffer = ''; if (exists($ENV{'TEST_CASE'})) { - my $try = "$file-$ENV{'TEST_CASE'}"; - $file = $try if -f $try; + my $try = "$file-$ENV{'TEST_CASE'}"; + $file = $try if -f $try; } local *FD; if (open(FD, "< $file")) { - read(FD, $buffer, -s FD); - close(FD); - debug("Loaded %d bytes from %s", length($buffer), $file); + read(FD, $buffer, -s FD); + close(FD); + debug("Loaded %d bytes from %s", length($buffer), $file); } else { - debug("Load failed from %s ($!)", $file); + debug("Load failed from %s ($!)", $file); } return $buffer } @@ -1558,16 +1557,16 @@ sub save_file { $file .= "-$ENV{'TEST_CASE'}" if exists $ENV{'TEST_CASE'}; if (defined $opt) { - my $i = 0; - while (-f "$file-$i") { - if ('unique' =~ /^$opt/i) { - my $a = join('\n', grep {!/^Date:/} split /\n/, $buffer); - my $b = join('\n', grep {!/^Date:/} split /\n/, load_file("$file-$i")); - last if $a eq $b; - } - $i++; - } - $file = "$file-$i"; + my $i = 0; + while (-f "$file-$i") { + if ('unique' =~ /^$opt/i) { + my $a = join('\n', grep {!/^Date:/} split /\n/, $buffer); + my $b = join('\n', grep {!/^Date:/} split /\n/, load_file("$file-$i")); + last if $a eq $b; + } + $i++; + } + $file = "$file-$i"; } debug("Saving to %s", $file); local *FD; @@ -1587,13 +1586,13 @@ sub _print_hash { my ($string, $ptr) = @_; my $value = $ptr; - if (! defined($ptr)) { + if (!defined($ptr)) { $value = ""; } elsif (ref $ptr eq 'HASH') { - foreach my $key (sort keys %$ptr) { - _print_hash("${string}\{$key\}", $ptr->{$key}); - } - return; + foreach my $key (sort keys %$ptr) { + _print_hash("${string}\{$key\}", $ptr->{$key}); + } + return; } printf "%-36s : %s\n", $string, $value; } @@ -1613,7 +1612,7 @@ sub print_info { print_cache(); } ###################################################################### -## pipecmd - run an external command +## pipecmd - run an external command ## logger ## sendmail ###################################################################### @@ -1630,29 +1629,29 @@ sub pipecmd { ## execute the command. local *FD; - if (! open(FD, $cmd)) { - printf STDERR "$program: cannot execute command %s.\n", $cmd; + if (!open(FD, $cmd)) { + printf STDERR "$program: cannot execute command %s.\n", $cmd; - } elsif ($stdin && (! print FD "$stdin\n")) { - printf STDERR "$program: failed writting to %s.\n", $cmd; - close(FD); + } elsif ($stdin && (!print FD "$stdin\n")) { + printf STDERR "$program: failed writting to %s.\n", $cmd; + close(FD); - } elsif (! close(FD)) { - printf STDERR "$program: failed closing %s.($@)\n", $cmd; + } elsif (!close(FD)) { + printf STDERR "$program: failed closing %s.($@)\n", $cmd; } elsif (opt('exec') && $?) { - printf STDERR "$program: failed %s. ($@)\n", $cmd; + printf STDERR "$program: failed %s. ($@)\n", $cmd; } else { - $ok = 1; + $ok = 1; } return $ok; } sub logger { - if (opt('syslog') && opt('facility') && opt('priority')) { - my $facility = opt('facility'); - my $priority = opt('priority'); - return pipecmd("logger -p$facility.$priority -t${program}\[$$\]", @_); + if (opt('syslog') && opt('facility') && opt('priority')) { + my $facility = opt('facility'); + my $priority = opt('priority'); + return pipecmd("logger -p$facility.$priority -t${program}\[$$\]", @_); } return 1; } @@ -1660,18 +1659,18 @@ sub sendmail { my $recipients = opt('mail'); if (opt('mail-failure') && ($result ne 'OK' && $result ne '0')) { - $recipients = opt('mail-failure'); + $recipients = opt('mail-failure'); } if ($msgs && $recipients && $msgs ne $last_msgs) { - pipecmd("sendmail -oi $recipients", - "To: $recipients", - "Subject: status report from $program\@$hostname", - "\r\n", - $msgs, - "", - "regards,", - " $program\@$hostname (version $version)" - ); + pipecmd("sendmail -oi $recipients", + "To: $recipients", + "Subject: status report from $program\@$hostname", + "\r\n", + $msgs, + "", + "regards,", + " $program\@$hostname (version $version)" + ); } $last_msgs = $msgs; $msgs = ''; @@ -1692,40 +1691,40 @@ sub split_by_comma { sub merge { my %merged = (); foreach my $h (@_) { - foreach my $k (keys %$h) { - $merged{$k} = $h->{$k} unless exists $merged{$k}; - } + foreach my $k (keys %$h) { + $merged{$k} = $h->{$k} unless exists $merged{$k}; + } } return \%merged; } -sub default { +sub default { my $v = shift; return $variables{'merged'}{$v}{'default'}; } -sub minimum { +sub minimum { my $v = shift; return $variables{'merged'}{$v}{'minimum'}; } sub opt { my $v = shift; my $h = shift; - return $config{$h}{$v} if defined($h && $config{$h}{$v}); - return $opt{$v} if defined $opt{$v}; - return $globals{$v} if defined $globals{$v}; - return default($v) if defined default($v); + return $config{$h}{$v} if defined($h && $config{$h}{$v}); + return $opt{$v} if defined $opt{$v}; + return $globals{$v} if defined $globals{$v}; + return default($v) if defined default($v); return undef; } sub min { my $min = shift; foreach my $arg (@_) { - $min = $arg if $arg < $min; + $min = $arg if $arg < $min; } return $min; } sub max { my $max = shift; foreach my $arg (@_) { - $max = $arg if $arg > $max; + $max = $arg if $arg > $max; } return $max; } @@ -1734,7 +1733,7 @@ sub max { ###################################################################### sub define { foreach (@_) { - return $_ if defined $_; + return $_ if defined $_; } return undef; } @@ -1744,13 +1743,13 @@ sub define { sub ynu { my ($value, $yes, $no, $undef) = @_; - return $no if !defined($value) || !$value; + return $no if !defined($value) || !$value; return $yes if $value eq '1'; foreach (qw(yes true)) { - return $yes if $_ =~ /^$value/i; + return $yes if $_ =~ /^$value/i; } foreach (qw(no false)) { - return $no if $_ =~ /^$value/i; + return $no if $_ =~ /^$value/i; } return $undef; } @@ -1769,31 +1768,31 @@ sub _msg { $prefix = sprintf "%-9s ", $prefix if $prefix; if ($file) { - $prefix .= "file $file"; - $prefix .= ", line $lineno" if $lineno; - $prefix .= ": "; + $prefix .= "file $file"; + $prefix .= ", line $lineno" if $lineno; + $prefix .= ": "; } if ($prefix) { - $buffer = "$prefix$buffer"; - $buffer =~ s/\n/\n$prefix /g; + $buffer = "$prefix$buffer"; + $buffer =~ s/\n/\n$prefix /g; } $buffer .= "\n"; print $buffer; - $msgs .= $buffer if $log; - logger($buffer) if $log; + $msgs .= $buffer if $log; + logger($buffer) if $log; } -sub msg { _msg(0, '', @_); } -sub verbose { _msg(1, @_) if opt('verbose'); } -sub info { _msg(1, 'INFO:', @_) if opt('verbose'); } -sub debug { _msg(0, 'DEBUG:', @_) if opt('debug'); } -sub debug2 { _msg(0, 'DEBUG:', @_) if opt('debug') && opt('verbose');} -sub warning { _msg(1, 'WARNING:', @_); } -sub fatal { _msg(1, 'FATAL:', @_); sendmail(); exit(1); } -sub success { _msg(1, 'SUCCESS:', @_); } -sub failed { _msg(1, 'FAILED:', @_); $result = 'FAILED'; } -sub prettytime { return scalar(localtime(shift)); } +sub msg { _msg(0, '', @_); } +sub verbose { _msg(1, @_) if opt('verbose'); } +sub info { _msg(1, 'INFO:', @_) if opt('verbose'); } +sub debug { _msg(0, 'DEBUG:', @_) if opt('debug'); } +sub debug2 { _msg(0, 'DEBUG:', @_) if opt('debug') && opt('verbose'); } +sub warning { _msg(1, 'WARNING:', @_); } +sub fatal { _msg(1, 'FATAL:', @_); sendmail(); exit(1); } +sub success { _msg(1, 'SUCCESS:', @_); } +sub failed { _msg(1, 'FAILED:', @_); $result = 'FAILED'; } +sub prettytime { return scalar(localtime(shift)); } sub prettyinterval { my $interval = shift; @@ -1820,15 +1819,15 @@ sub prettyinterval { sub interval { my $value = shift; if ($value =~ /^(\d+)(seconds|s)/i) { - $value = $1; + $value = $1; } elsif ($value =~ /^(\d+)(minutes|m)/i) { - $value = $1 * 60; + $value = $1 * 60; } elsif ($value =~ /^(\d+)(hours|h)/i) { - $value = $1 * 60*60; + $value = $1 * 60*60; } elsif ($value =~ /^(\d+)(days|d)/i) { - $value = $1 * 60*60*24; + $value = $1 * 60*60*24; } elsif ($value !~ /^\d+$/) { - $value = undef; + $value = undef; } return $value; } @@ -1854,59 +1853,59 @@ sub check_value { my $required = $def->{'required'}; if (!defined $value && !$required) { - ; + ; } elsif ($type eq T_DELAY) { - $value = interval($value); - $value = $min if defined($value) && defined($min) && $value < $min; + $value = interval($value); + $value = $min if defined($value) && defined($min) && $value < $min; } elsif ($type eq T_NUMBER) { - return undef if $value !~ /^\d+$/; - $value = $min if defined($min) && $value < $min; + return undef if $value !~ /^\d+$/; + $value = $min if defined($min) && $value < $min; } elsif ($type eq T_BOOL) { - if ($value =~ /^y(es)?$|^t(true)?$|^1$/i) { - $value = 1; - } elsif ($value =~ /^n(o)?$|^f(alse)?$|^0$/i) { - $value = 0; - } else { - return undef; - } + if ($value =~ /^y(es)?$|^t(true)?$|^1$/i) { + $value = 1; + } elsif ($value =~ /^n(o)?$|^f(alse)?$|^0$/i) { + $value = 0; + } else { + return undef; + } } elsif ($type eq T_FQDN || $type eq T_OFQDN && $value ne '') { - $value = lc $value; - return undef if $value !~ /[^.]\.[^.]/; + $value = lc $value; + return undef if $value !~ /[^.]\.[^.]/; } elsif ($type eq T_FQDNP) { - $value = lc $value; - return undef if $value !~ /[^.]\.[^.].*(:\d+)?$/; + $value = lc $value; + return undef if $value !~ /[^.]\.[^.].*(:\d+)?$/; } elsif ($type eq T_PROTO) { - $value = lc $value; - return undef if ! exists $services{$value}; + $value = lc $value; + return undef if !exists $services{$value}; } elsif ($type eq T_USE) { - $value = lc $value; - return undef if ! exists $ip_strategies{$value}; + $value = lc $value; + return undef if !exists $ip_strategies{$value}; } elsif ($type eq T_FILE) { - return undef if $value eq ""; + return undef if $value eq ""; } elsif ($type eq T_IF) { - return undef if $value !~ /^[a-zA-Z0-9:._-]+$/; + return undef if $value !~ /^[a-zA-Z0-9:._-]+$/; } elsif ($type eq T_PROG) { - return undef if $value eq ""; + return undef if $value eq ""; } elsif ($type eq T_LOGIN) { - return undef if $value eq ""; + return undef if $value eq ""; -# } elsif ($type eq T_PASSWD) { -# return undef if $value =~ /:/; + #} elsif ($type eq T_PASSWD) { + # return undef if $value =~ /:/; } elsif ($type eq T_IP) { - if( !ipv6_match($value) ) { - return undef if $value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; - } + if (!ipv6_match($value)) { + return undef if $value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + } } return $value; } @@ -1917,12 +1916,12 @@ sub encode_base64 ($;$) { my $res = ''; my $eol = $_[1]; $eol = "\n" unless defined $eol; - pos($_[0]) = 0; # ensure start at the beginning + pos($_[0]) = 0; # ensure start at the beginning while ($_[0] =~ /(.{1,45})/gs) { $res .= substr(pack('u', $1), 1); chop($res); } - $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs + $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs # fix padding at the end my $padding = (3 - length($_[0]) % 3) % 3; @@ -1933,7 +1932,7 @@ sub encode_base64 ($;$) { ## load_ssl_support ###################################################################### sub load_ssl_support { - my $ssl_loaded = eval {require IO::Socket::SSL}; + my $ssl_loaded = eval { require IO::Socket::SSL }; unless ($ssl_loaded) { fatal(<<"EOM"); Error loading the Perl module IO::Socket::SSL needed for SSL connect. @@ -1942,7 +1941,7 @@ On Red Hat, the package perl-IO-Socket-SSL must be installed. On Alpine, the package perl-io-socket-ssl must be installed. EOM } - import IO::Socket::SSL; + import IO::Socket::SSL; { no warnings; $IO::Socket::SSL::DEBUG = 0; } } @@ -1950,7 +1949,7 @@ EOM ## load_ipv6_support ###################################################################### sub load_ipv6_support { - my $ipv6_loaded = eval {require IO::Socket::INET6}; + my $ipv6_loaded = eval { require IO::Socket::INET6 }; unless ($ipv6_loaded) { fatal(<<"EOM"); Error loading the Perl module IO::Socket::INET6 needed for ipv6 connect. @@ -1967,33 +1966,33 @@ EOM ## load_sha1_support ###################################################################### sub load_sha1_support { - my $why = shift; - my $sha1_loaded = eval {require Digest::SHA1}; - my $sha_loaded = eval {require Digest::SHA}; + my $why = shift; + my $sha1_loaded = eval { require Digest::SHA1 }; + my $sha_loaded = eval { require Digest::SHA }; unless ($sha1_loaded || $sha_loaded) { fatal(<<"EOM"); Error loading the Perl module Digest::SHA1 or Digest::SHA needed for $why update. On Debian, the package libdigest-sha1-perl or libdigest-sha-perl must be installed. EOM } - if($sha1_loaded) { - import Digest::SHA1 (qw/sha1_hex/); - } elsif($sha_loaded) { - import Digest::SHA (qw/sha1_hex/); + if ($sha1_loaded) { + import Digest::SHA1 (qw/sha1_hex/); + } elsif ($sha_loaded) { + import Digest::SHA (qw/sha1_hex/); } } ###################################################################### ## load_json_support ###################################################################### sub load_json_support { - my $why = shift; - my $json_loaded = eval {require JSON::PP}; - unless ($json_loaded) { - fatal(<<"EOM"); + my $why = shift; + my $json_loaded = eval { require JSON::PP }; + unless ($json_loaded) { + fatal(<<"EOM"); Error loading the Perl module JSON::PP needed for $why update. EOM - } - import JSON::PP (qw/decode_json/); + } + import JSON::PP (qw/decode_json/); } ###################################################################### ## geturl @@ -2022,31 +2021,31 @@ sub geturl { $url =~ s%^[^/]*/%%; debug("server = $server"); - opt('fw') && debug("opt(fw = ",opt('fw'),")"); + opt('fw') && debug("opt(fw = ", opt('fw'),")"); $globals{'fw'} && debug("glo fw = $globals{'fw'}"); - #if ( $globals{'ssl'} and $server ne $globals{'fw'} ) { + #if ($globals{'ssl'} and $server ne $globals{'fw'}) { ## always omit SSL for connections to local router - if ( $force_ssl || ($globals{'ssl'} and (caller(1))[3] ne 'main::get_ip') ) { + if ($force_ssl || ($globals{'ssl'} and (caller(1))[3] ne 'main::get_ip')) { $use_ssl = 1; $default_port = 443; - load_ssl_support; + load_ssl_support; } else { $use_ssl = 0; $default_port = 80; } ## determine peer and port to use. - $peer = $proxy || $server; - $peer =~ s%/.*%%; - $port = $peer; - $port =~ s%^.*:%%; - $port = $default_port unless $port =~ /^\d+$/; - $peer =~ s%:.*$%%; + $peer = $proxy || $server; + $peer =~ s%/.*%%; + $port = $peer; + $port =~ s%^.*:%%; + $port = $default_port unless $port =~ /^\d+$/; + $peer =~ s%:.*$%%; - my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; + my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; verbose("CONNECT:", "%s", $to); - $request = "$method "; + $request = "$method "; if (!$use_ssl) { $request .= "http://$server" if $proxy; } else { @@ -2059,7 +2058,7 @@ sub geturl { $request .= "Authorization: Basic $auth\n" if $login || $password; $request .= "User-Agent: ${program}/${version}\n"; if ($data) { - $request .= "Content-Type: application/x-www-form-urlencoded\n" if ! $headers =~ /^Content-Type: /; + $request .= "Content-Type: application/x-www-form-urlencoded\n" if !$headers =~ /^Content-Type: /; $request .= "Content-Length: " . length($data) . "\n"; } $request .= "Connection: close\n"; @@ -2072,82 +2071,82 @@ sub geturl { # local $^W = 0; $0 = sprintf("%s - connecting to %s port %s", $program, $peer, $port); - if (! opt('exec')) { - debug("skipped network connection"); - verbose("SENDING:", "%s", $request); + if (!opt('exec')) { + debug("skipped network connection"); + verbose("SENDING:", "%s", $request); } elsif ($use_ssl) { - $sd = IO::Socket::SSL->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', + $sd = IO::Socket::SSL->new( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', MultiHomed => 1, - Timeout => opt('timeout'), + Timeout => opt('timeout'), ); - defined $sd or warning("cannot connect to $peer:$port socket: $@ " . IO::Socket::SSL::errstr()); + defined $sd or warning("cannot connect to $peer:$port socket: $@ " . IO::Socket::SSL::errstr()); } elsif ($globals{'ipv6'}) { load_ipv6_support; - $sd = IO::Socket::INET6->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', + $sd = IO::Socket::INET6->new( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', MultiHomed => 1, - Timeout => opt('timeout'), + Timeout => opt('timeout'), ); - defined $sd or warning("cannot connect to $peer:$port socket: $@"); + defined $sd or warning("cannot connect to $peer:$port socket: $@"); } else { - $sd = IO::Socket::INET->new( - PeerAddr => $peer, - PeerPort => $port, - Proto => 'tcp', + $sd = IO::Socket::INET->new( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', MultiHomed => 1, - Timeout => opt('timeout'), + Timeout => opt('timeout'), ); - defined $sd or warning("cannot connect to $peer:$port socket: $@"); + defined $sd or warning("cannot connect to $peer:$port socket: $@"); } - if (defined $sd) { - ## send the request to the http server - verbose("CONNECTED: ", $use_ssl ? 'using SSL' : 'using HTTP'); - verbose("SENDING:", "%s", $request); + if (defined $sd) { + ## send the request to the http server + verbose("CONNECTED: ", $use_ssl ? 'using SSL' : 'using HTTP'); + verbose("SENDING:", "%s", $request); - $0 = sprintf("%s - sending to %s port %s", $program, $peer, $port); - my $result = syswrite $sd, $rq; - if ($result != length($rq)) { - warning("cannot send to $peer:$port ($!)."); - } else { - $0 = sprintf("%s - reading from %s port %s", $program, $peer, $port); - eval { - local $SIG{'ALRM'} = sub { die "timeout";}; - alarm(opt('timeout')) if opt('timeout') > 0; - while ($_ = <$sd>) { - $0 = sprintf("%s - read from %s port %s", $program, $peer, $port); - verbose("RECEIVE:", "%s", define($_, "")); - $reply .= $_ if defined $_; - } - if (opt('timeout') > 0) { - alarm(0); - } - }; - close($sd); + $0 = sprintf("%s - sending to %s port %s", $program, $peer, $port); + my $result = syswrite $sd, $rq; + if ($result != length($rq)) { + warning("cannot send to $peer:$port ($!)."); + } else { + $0 = sprintf("%s - reading from %s port %s", $program, $peer, $port); + eval { + local $SIG{'ALRM'} = sub { die "timeout"; }; + alarm(opt('timeout')) if opt('timeout') > 0; + while ($_ = <$sd>) { + $0 = sprintf("%s - read from %s port %s", $program, $peer, $port); + verbose("RECEIVE:", "%s", define($_, "")); + $reply .= $_ if defined $_; + } + if (opt('timeout') > 0) { + alarm(0); + } + }; + close($sd); - if ($@ and $@ =~ /timeout/) { - warning("TIMEOUT: %s after %s seconds", $to, opt('timeout')); - $reply = ''; - } - $reply = '' if !defined $reply; - } - } - $0 = sprintf("%s - closed %s port %s", $program, $peer, $port); + if ($@ and $@ =~ /timeout/) { + warning("TIMEOUT: %s after %s seconds", $to, opt('timeout')); + $reply = ''; + } + $reply = '' if !defined $reply; + } + } + $0 = sprintf("%s - closed %s port %s", $program, $peer, $port); ## during testing simulate reading the URL if (opt('test')) { - my $filename = "$server/$url"; - $filename =~ s|/|%2F|g; - if (opt('exec')) { - $reply = save_file("${savedir}$filename", $reply, 'unique'); - } else { - $reply = load_file("${savedir}$filename"); - } + my $filename = "$server/$url"; + $filename =~ s|/|%2F|g; + if (opt('exec')) { + $reply = save_file("${savedir}$filename", $reply, 'unique'); + } else { + $reply = load_file("${savedir}$filename"); + } } $reply =~ s/\r//g if defined $reply; @@ -2157,82 +2156,82 @@ sub geturl { ## un_zero_pad ###################################################################### sub un_zero_pad { - my $in_str = shift(@_); - my @out_str = (); + my $in_str = shift(@_); + my @out_str = (); - if ($in_str eq '0.0.0.0') { - return $in_str; - } + if ($in_str eq '0.0.0.0') { + return $in_str; + } - foreach my $block (split /\./, $in_str) { - $block =~ s/^0+//; - if ($block eq '') { - $block = '0'; - } - push @out_str, $block; - } - return join('.', @out_str); + foreach my $block (split /\./, $in_str) { + $block =~ s/^0+//; + if ($block eq '') { + $block = '0'; + } + push @out_str, $block; + } + return join('.', @out_str); } ###################################################################### ## filter_local ###################################################################### sub filter_local { - my $in_ip = shift(@_); + my $in_ip = shift(@_); - if ($in_ip eq '0.0.0.0') { - return $in_ip; - } + if ($in_ip eq '0.0.0.0') { + return $in_ip; + } - my @guess_local = ( - '^10\.', - '^172\.(?:1[6-9]|2[0-9]|3[01])\.', - '^192\.168' - ); - foreach my $block (@guess_local) { - if ($in_ip =~ /$block/) { - return '0.0.0.0'; - } - } - return $in_ip; + my @guess_local = ( + '^10\.', + '^172\.(?:1[6-9]|2[0-9]|3[01])\.', + '^192\.168' + ); + foreach my $block (@guess_local) { + if ($in_ip =~ /$block/) { + return '0.0.0.0'; + } + } + return $in_ip; } ###################################################################### ## get_ip ###################################################################### sub get_ip { my $use = lc shift; - my $h = shift; + my $h = shift; my ($ip, $arg, $reply, $url, $skip) = (undef, opt($use, $h), ''); $arg = '' unless $arg; if ($use eq 'ip') { - $ip = opt('ip', $h); - $arg = 'ip'; + $ip = opt('ip', $h); + $arg = 'ip'; } elsif ($use eq 'if') { - $skip = opt('if-skip', $h) || ''; - $reply = `ifconfig $arg 2> /dev/null`; - $reply = `ip addr list dev $arg 2> /dev/null` if $?; - $reply = '' if $?; + $skip = opt('if-skip', $h) || ''; + $reply = `ifconfig $arg 2> /dev/null`; + $reply = `ip addr list dev $arg 2> /dev/null` if $?; + $reply = '' if $?; } elsif ($use eq 'cmd') { - if ($arg) { - $skip = opt('cmd-skip', $h) || ''; - $reply = `$arg`; - $reply = '' if $?; - } + if ($arg) { + $skip = opt('cmd-skip', $h) || ''; + $reply = `$arg`; + $reply = '' if $?; + } } elsif ($use eq 'web') { - $url = opt('web', $h) || ''; - $skip = opt('web-skip', $h) || ''; + $url = opt('web', $h) || ''; + $skip = opt('web-skip', $h) || ''; - if (exists $builtinweb{$url}) { - $skip = $builtinweb{$url}->{'skip'} unless $skip; - $url = $builtinweb{$url}->{'url'}; - } - $arg = $url; + if (exists $builtinweb{$url}) { + $skip = $builtinweb{$url}->{'skip'} unless $skip; + $url = $builtinweb{$url}->{'url'}; + } + $arg = $url; - if ($url) { - $reply = geturl(opt('proxy', $h), $url) || ''; + if ($url) { + $reply = geturl(opt('proxy', $h), $url) || ''; } } elsif (($use eq 'cisco')) { @@ -2248,7 +2247,7 @@ sub get_ip { # Protect special HTML characters (like '?') $queryif =~ s/([\?&= ])/sprintf("%%%02x",ord($1))/ge; - $url = "http://".opt('fw', $h)."/level/1/exec/show/ip/interface/brief/${queryif}/CR"; + $url = "http://" . opt('fw', $h) . "/level/1/exec/show/ip/interface/brief/${queryif}/CR"; $reply = geturl('', $url, opt('fw-login', $h), opt('fw-password', $h)) || ''; $arg = $url; @@ -2256,8 +2255,8 @@ sub get_ip { # Stuff added to support Cisco ASA ip https daemon # User fw-login should only have level 1 access to prevent # password theft. This is pretty harmless. - my $queryif = opt('if', $h); - $skip = opt('fw-skip', $h) || ''; + my $queryif = opt('if', $h); + $skip = opt('fw-skip', $h) || ''; # Convert slashes to protected value "\/" $queryif =~ s%\/%\\\/%g; @@ -2265,13 +2264,13 @@ sub get_ip { # Protect special HTML characters (like '?') $queryif =~ s/([\?&= ])/sprintf("%%%02x",ord($1))/ge; - $url = "https://".opt('fw', $h)."/exec/show%20interface%20${queryif}"; + $url = "https://" . opt('fw', $h) . "/exec/show%20interface%20${queryif}"; $reply = geturl('', $url, opt('fw-login', $h), opt('fw-password', $h)) || ''; $arg = $url; } else { - $url = opt('fw', $h) || ''; - $skip = opt('fw-skip', $h) || ''; + $url = opt('fw', $h) || ''; + $skip = opt('fw-skip', $h) || ''; if (exists $builtinfw{$use}) { $skip = $builtinfw{$use}->{'skip'} unless $skip; @@ -2281,9 +2280,9 @@ sub get_ip { if ($url) { $reply = geturl('', $url, opt('fw-login', $h), opt('fw-password', $h)) || ''; - } } - if (!defined $reply) { + } + if (!defined $reply) { $reply = ''; } if ($skip) { @@ -2291,17 +2290,17 @@ sub get_ip { $reply =~ s/^.*?${skip}//is; } if ($reply =~ /^.*?\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b.*/is) { - $ip = $1; + $ip = $1; $ip = un_zero_pad($ip); - $ip = filter_local($ip) if opt('fw-banlocal', $h); - } elsif ( $ip = ipv6_match($reply) ) { + $ip = filter_local($ip) if opt('fw-banlocal', $h); + } elsif ($ip = ipv6_match($reply)) { $ip = un_zero_pad($ip); $ip = filter_local($ip) if opt('fw-banlocal', $h); } else { - warning("found neither ipv4 nor ipv6 address"); + warning("found neither ipv4 nor ipv6 address"); } - if (($use ne 'ip') && (define($ip,'') eq '0.0.0.0')) { - $ip = undef; + if (($use ne 'ip') && (define($ip, '') eq '0.0.0.0')) { + $ip = undef; } debug("get_ip: using %s, %s reports %s", $use, $arg, define($ip, "")); @@ -2312,9 +2311,9 @@ sub get_ip { ## ipv6_match determine ipv6 address from given string and return them ###################################################################### sub ipv6_match { - my $content = shift; - my $omits; - my $ip = ""; + my $content = shift; + my $omits; + my $ip = ""; my $linenumbers = 0; my @values = split('\n', $content); @@ -2344,11 +2343,11 @@ sub group_hosts_by { my %groups = (); foreach my $h (@$hosts) { - my @keys = (@$attributes, 'wantip'); - map { $config{$h}{$_} = '' unless exists $config{$h}{$_} } @keys; - my $sig = join(',', map { "$_=$config{$h}{$_}" } @keys); + my @keys = (@$attributes, 'wantip'); + map { $config{$h}{$_} = '' unless exists $config{$h}{$_} } @keys; + my $sig = join(',', map { "$_=$config{$h}{$_}" } @keys); - push @{$groups{$sig}}, $h; + push @{$groups{$sig}}, $h; } return %groups; } @@ -2371,7 +2370,7 @@ sub encode_www_form_urlencoded { $kenc =~ s/ /+/g; $venc =~ s/ /+/g; - $encoded .= $kenc.'='.$venc; + $encoded .= $kenc . '=' . $venc; if ($i < (keys %$formdata) - 1) { $encoded .= '&'; } @@ -2387,16 +2386,16 @@ sub encode_www_form_urlencoded { sub nic_examples { my $examples = ""; my $separator = ""; - foreach my $s (sort keys %services) { - my $subr = $services{$s}{'examples'}; + foreach my $s (sort keys %services) { + my $subr = $services{$s}{'examples'}; my $example; - if (defined($subr) && ($example = &$subr())) { - chomp($example); - $examples .= $example; - $examples .= "\n\n$separator"; - $separator = "\n"; - } + if (defined($subr) && ($example = &$subr())) { + chomp($example); + $examples .= $example; + $examples .= "\n\n$separator"; + $separator = "\n"; + } } my $intro = < $now) { - warning("cannot update %s from %s to %s until after %s.", - $host, - ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, - prettytime($cache{$host}{'wtime'}) - ); + warning("cannot update %s from %s to %s until after %s.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, + prettytime($cache{$host}{'wtime'}) + ); } elsif ($cache{$host}{'mtime'} && interval_expired($host, 'mtime', 'max-interval')) { - warning("forcing update of %s from %s to %s; %s since last update on %s.", - $host, - ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, - prettyinterval($config{$host}{'max-interval'}), - prettytime($cache{$host}{'mtime'}) - ); - $update = 1; + warning("forcing update of %s from %s to %s; %s since last update on %s.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, + prettyinterval($config{$host}{'max-interval'}), + prettytime($cache{$host}{'mtime'}) + ); + $update = 1; } elsif ((!exists($cache{$host}{'ip'})) || - ("$cache{$host}{'ip'}" ne "$ip")) { - if (($cache{$host}{'status'} eq 'good') && - !interval_expired($host, 'mtime', 'min-interval')) { + ("$cache{$host}{'ip'}" ne "$ip")) { + if (($cache{$host}{'status'} eq 'good') && + !interval_expired($host, 'mtime', 'min-interval')) { - warning("skipping update of %s from %s to %s.\nlast updated %s.\nWait at least %s between update attempts.", - $host, - ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), - $ip, - ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), - prettyinterval($config{$host}{'min-interval'}) - ) - if opt('verbose') || !define($cache{$host}{'warned-min-interval'}, 0); + warning("skipping update of %s from %s to %s.\nlast updated %s.\nWait at least %s between update attempts.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), + $ip, + ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), + prettyinterval($config{$host}{'min-interval'}) + ) + if opt('verbose') || !define($cache{$host}{'warned-min-interval'}, 0); - $cache{$host}{'warned-min-interval'} = $now; + $cache{$host}{'warned-min-interval'} = $now; - } elsif (($cache{$host}{'status'} ne 'good') && !interval_expired($host, 'atime', 'min-error-interval')) { + } elsif (($cache{$host}{'status'} ne 'good') && !interval_expired($host, 'atime', 'min-error-interval')) { - warning("skipping update of %s from %s to %s.\nlast updated %s but last attempt on %s failed.\nWait at least %s between update attempts.", - $host, - ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), - $ip, - ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), - ($cache{$host}{'atime'} ? prettytime($cache{$host}{'atime'}) : ''), - prettyinterval($config{$host}{'min-error-interval'}) - ) - if opt('verbose') || !define($cache{$host}{'warned-min-error-interval'}, 0); + warning("skipping update of %s from %s to %s.\nlast updated %s but last attempt on %s failed.\nWait at least %s between update attempts.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), + $ip, + ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), + ($cache{$host}{'atime'} ? prettytime($cache{$host}{'atime'}) : ''), + prettyinterval($config{$host}{'min-error-interval'}) + ) + if opt('verbose') || !define($cache{$host}{'warned-min-error-interval'}, 0); - $cache{$host}{'warned-min-error-interval'} = $now; + $cache{$host}{'warned-min-error-interval'} = $now; - } else { - $update = 1; - } + } else { + $update = 1; + } } elsif (defined($sub) && &$sub($host)) { - $update = 1; + $update = 1; } elsif ((defined($cache{$host}{'static'}) && defined($config{$host}{'static'}) && ($cache{$host}{'static'} ne $config{$host}{'static'})) || (defined($cache{$host}{'wildcard'}) && defined($config{$host}{'wildcard'}) && @@ -2528,25 +2527,25 @@ sub nic_updateable { (defined($cache{$host}{'mx'}) && defined($config{$host}{'mx'}) && ($cache{$host}{'mx'} ne $config{$host}{'mx'})) || (defined($cache{$host}{'backupmx'}) && defined($config{$host}{'backupmx'}) && - ($cache{$host}{'backupmx'} ne $config{$host}{'backupmx'})) ) { - info("updating %s because host settings have been changed.", $host); - $update = 1; + ($cache{$host}{'backupmx'} ne $config{$host}{'backupmx'}))) { + info("updating %s because host settings have been changed.", $host); + $update = 1; } else { - success("%s: skipped: IP address was already set to %s.", $host, $ip) - if opt('verbose'); + success("%s: skipped: IP address was already set to %s.", $host, $ip) + if opt('verbose'); } - $config{$host}{'status'} = define($cache{$host}{'status'},''); + $config{$host}{'status'} = define($cache{$host}{'status'}, ''); $config{$host}{'update'} = $update; if ($update) { - $config{$host}{'status'} = 'noconnect'; - $config{$host}{'atime'} = $now; - $config{$host}{'wtime'} = 0; - $config{$host}{'warned-min-interval'} = 0; - $config{$host}{'warned-min-error-interval'} = 0; + $config{$host}{'status'} = 'noconnect'; + $config{$host}{'atime'} = $now; + $config{$host}{'wtime'} = 0; + $config{$host}{'warned-min-interval'} = 0; + $config{$host}{'warned-min-error-interval'} = 0; - delete $cache{$host}{'warned-min-interval'}; - delete $cache{$host}{'warned-min-error-interval'}; + delete $cache{$host}{'warned-min-interval'}; + delete $cache{$host}{'warned-min-error-interval'}; } return $update; @@ -2559,17 +2558,17 @@ sub header_ok { my $ok = 0; if ($line =~ m%^s*HTTP/1.*\s+(\d+)%i) { - my $result = $1; + my $result = $1; - if ($result eq '200') { - $ok = 1; + if ($result eq '200') { + $ok = 1; - } elsif ($result eq '401') { - failed("updating %s: authorization failed (%s)", $host, $line); - } + } elsif ($result eq '401') { + failed("updating %s: authorization failed (%s)", $host, $line); + } } else { - failed("updating %s: unexpected line (%s)", $host, $line); + failed("updating %s: unexpected line (%s)", $host, $line); } return $ok; } @@ -2617,50 +2616,50 @@ sub nic_dyndns1_update { debug("\nnic_dyndns1_update -------------------"); ## update each configured host foreach my $h (@_) { - my $ip = delete $config{$h}{'wantip'}; - info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + my $ip = delete $config{$h}{'wantip'}; + info("setting IP address to %s for %s", $ip, $h); + verbose("UPDATE:", "updating %s", $h); - my $url; - $url = "http://$config{$h}{'server'}/nic/"; - $url .= ynu($config{$h}{'static'}, 'statdns', 'dyndns', 'dyndns'); - $url .= "?action=edit&started=1&hostname=YES&host_id=$h"; - $url .= "&myip="; - $url .= $ip if $ip; - $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); - if ($config{$h}{'mx'}) { - $url .= "&mx=$config{$h}{'mx'}"; - $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); - } + my $url; + $url = "http://$config{$h}{'server'}/nic/"; + $url .= ynu($config{$h}{'static'}, 'statdns', 'dyndns', 'dyndns'); + $url .= "?action=edit&started=1&hostname=YES&host_id=$h"; + $url .= "&myip="; + $url .= $ip if $ip; + $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); + } - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); - next; - } - last if !header_ok($h, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); + next; + } + last if !header_ok($h, $reply); - my @reply = split /\n/, $reply; - my ($title, $return_code, $error_code) = ('','',''); - foreach my $line (@reply) { - $title = $1 if $line =~ m%\s*(.*)\s*%i; - $return_code = $1 if $line =~ m%^return\s+code\s*:\s*(.*)\s*$%i; - $error_code = $1 if $line =~ m%^error\s+code\s*:\s*(.*)\s*$%i; - } + my @reply = split /\n/, $reply; + my ($title, $return_code, $error_code) = ('', '', ''); + foreach my $line (@reply) { + $title = $1 if $line =~ m%\s*(.*)\s*%i; + $return_code = $1 if $line =~ m%^return\s+code\s*:\s*(.*)\s*$%i; + $error_code = $1 if $line =~ m%^error\s+code\s*:\s*(.*)\s*$%i; + } - if ($return_code ne 'NOERROR' || $error_code ne 'NOERROR' || !$title) { - $config{$h}{'status'} = 'failed'; - $title = "incomplete response from $config{$h}{server}" unless $title; - warning("SENT: %s", $url) unless opt('verbose'); - warning("REPLIED: %s", $reply); - failed("updating %s: %s", $h, $title); + if ($return_code ne 'NOERROR' || $error_code ne 'NOERROR' || !$title) { + $config{$h}{'status'} = 'failed'; + $title = "incomplete response from $config{$h}{server}" unless $title; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: %s", $h, $title); - } else { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: %s: IP address set to %s (%s)", $h, $return_code, $ip, $title); - } + } else { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: %s: IP address set to %s (%s)", $h, $return_code, $ip, $title); + } } } ###################################################################### @@ -2671,17 +2670,17 @@ sub nic_dyndns2_updateable { my $update = 0; if ($config{$host}{'mx'} ne $cache{$host}{'mx'}) { - info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); - $update = 1; + info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); + $update = 1; - } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'},1,2,3) ne ynu($config{$host}{'backupmx'},1,2,3))) { - info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'},"YES","NO","NO")); - $update = 1; + } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'}, 1, 2, 3) ne ynu($config{$host}{'backupmx'}, 1, 2, 3))) { + info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'}, "YES", "NO", "NO")); + $update = 1; } elsif ($config{$host}{'static'} ne $cache{$host}{'static'}) { - info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'},"YES","NO","NO")); - $update = 1; + info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'}, "YES", "NO", "NO")); + $update = 1; } return $update; @@ -2762,107 +2761,107 @@ sub nic_dyndns2_update { ## update each set of hosts that had similar configurations foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $h = $hosts[0]; - my $ip = $config{$h}{'wantip'}; - delete $config{$_}{'wantip'} foreach @hosts; + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + my $ip = $config{$h}{'wantip'}; + delete $config{$_}{'wantip'} foreach @hosts; - info("setting IP address to %s for %s", $ip, $hosts); - verbose("UPDATE:","updating %s", $hosts); + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:", "updating %s", $hosts); - ## Select the DynDNS system to update - my $url = "http://$config{$h}{'server'}$config{$h}{'script'}?system="; - if ($config{$h}{'custom'}) { - warning("updating %s: 'custom' and 'static' may not be used together. ('static' ignored)", $hosts) - if $config{$h}{'static'}; -# warning("updating %s: 'custom' and 'offline' may not be used together. ('offline' ignored)", $hosts) -# if $config{$h}{'offline'}; - $url .= 'custom'; + ## Select the DynDNS system to update + my $url = "http://$config{$h}{'server'}$config{$h}{'script'}?system="; + if ($config{$h}{'custom'}) { + warning("updating %s: 'custom' and 'static' may not be used together. ('static' ignored)", $hosts) + if $config{$h}{'static'}; + #warning("updating %s: 'custom' and 'offline' may not be used together. ('offline' ignored)", $hosts) + # if $config{$h}{'offline'}; + $url .= 'custom'; - } elsif ($config{$h}{'static'}) { -# warning("updating %s: 'static' and 'offline' may not be used together. ('offline' ignored)", $hosts) -# if $config{$h}{'offline'}; - $url .= 'statdns'; + } elsif ($config{$h}{'static'}) { + #warning("updating %s: 'static' and 'offline' may not be used together. ('offline' ignored)", $hosts) + # if $config{$h}{'offline'}; + $url .= 'statdns'; - } else { - $url .= 'dyndns'; - } + } else { + $url .= 'dyndns'; + } - $url .= "&hostname=$hosts"; - $url .= "&myip="; - $url .= $ip if $ip; + $url .= "&hostname=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; - ## some args are not valid for a custom domain. - $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); - if ($config{$h}{'mx'}) { - $url .= "&mx=$config{$h}{'mx'}"; - $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); - } + ## some args are not valid for a custom domain. + $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); + } - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); - last; - } - last if !header_ok($hosts, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); - my @reply = split /\n/, $reply; - my $state = 'header'; - my $returnedip = $ip; + my @reply = split /\n/, $reply; + my $state = 'header'; + my $returnedip = $ip; - foreach my $line (@reply) { - if ($state eq 'header') { - $state = 'body'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; - } elsif ($state eq 'body') { - $state = 'results' if $line eq ''; + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; - } elsif ($state =~ /^results/) { - $state = 'results2'; + } elsif ($state =~ /^results/) { + $state = 'results2'; - # bug #10: some dyndns providers does not return the IP so - # we can't use the returned IP - my ($status, $returnedip) = split / /, lc $line; - $ip = $returnedip if (not $ip); - my $h = shift @hosts; + # bug #10: some dyndns providers does not return the IP so + # we can't use the returned IP + my ($status, $returnedip) = split / /, lc $line; + $ip = $returnedip if (not $ip); + my $h = shift @hosts; - $config{$h}{'status'} = $status; - if ($status eq 'good') { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - success("updating %s: %s: IP address set to %s", $h, $status, $ip); + $config{$h}{'status'} = $status; + if ($status eq 'good') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); - } elsif (exists $errors{$status}) { - if ($status eq 'nochg') { - warning("updating %s: %s: %s", $h, $status, $errors{$status}); - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; + } elsif (exists $errors{$status}) { + if ($status eq 'nochg') { + warning("updating %s: %s: %s", $h, $status, $errors{$status}); + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; - } else { - failed("updating %s: %s: %s", $h, $status, $errors{$status}); - } + } else { + failed("updating %s: %s: %s", $h, $status, $errors{$status}); + } - } elsif ($status =~ /w(\d+)(.)/) { - my ($wait, $units) = ($1, lc $2); - my ($sec, $scale) = ($wait, 1); + } elsif ($status =~ /w(\d+)(.)/) { + my ($wait, $units) = ($1, lc $2); + my ($sec, $scale) = ($wait, 1); - ($scale, $units) = (1, 'seconds') if $units eq 's'; - ($scale, $units) = (60, 'minutes') if $units eq 'm'; - ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; - $sec = $wait * $scale; - $config{$h}{'wtime'} = $now + $sec; - warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + $sec = $wait * $scale; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); - } else { - failed("updating %s: %s: unexpected status (%s)", $h, $line); - } - } - } - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) - if $state ne 'results2'; + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; } } @@ -2878,91 +2877,91 @@ sub nic_noip_update { my %groups = group_hosts_by([ @_ ], [ qw(login password server static custom wildcard mx backupmx) ]); my %errors = ( - 'badauth' => 'Invalid username or password', - 'badagent' => 'Invalid user agent', - 'nohost' => 'The hostname specified does not exist in the database', - '!donator' => 'The offline setting was set, when the user is not a donator', - 'abuse', => 'The hostname specified is blocked for abuse; open a trouble ticket at http://www.no-ip.com', - 'numhost' => 'System error: Too many or too few hosts found. open a trouble ticket at http://www.no-ip.com', - 'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org', - 'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive', + 'badauth' => 'Invalid username or password', + 'badagent' => 'Invalid user agent', + 'nohost' => 'The hostname specified does not exist in the database', + '!donator' => 'The offline setting was set, when the user is not a donator', + 'abuse', => 'The hostname specified is blocked for abuse; open a trouble ticket at http://www.no-ip.com', + 'numhost' => 'System error: Too many or too few hosts found. open a trouble ticket at http://www.no-ip.com', + 'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org', + 'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive', ); ## update each set of hosts that had similar configurations foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $h = $hosts[0]; - my $ip = $config{$h}{'wantip'}; - delete $config{$_}{'wantip'} foreach @hosts; + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + my $ip = $config{$h}{'wantip'}; + delete $config{$_}{'wantip'} foreach @hosts; - info("setting IP address to %s for %s", $ip, $hosts); - verbose("UPDATE:","updating %s", $hosts); + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:", "updating %s", $hosts); - my $url = "http://$config{$h}{'server'}/nic/update?system="; - $url .= 'noip'; - $url .= "&hostname=$hosts"; - $url .= "&myip="; - $url .= $ip if $ip; + my $url = "http://$config{$h}{'server'}/nic/update?system="; + $url .= 'noip'; + $url .= "&hostname=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); - last; - } - last if !header_ok($hosts, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); - my @reply = split /\n/, $reply; - my $state = 'header'; - foreach my $line (@reply) { - if ($state eq 'header') { - $state = 'body'; + my @reply = split /\n/, $reply; + my $state = 'header'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; - } elsif ($state eq 'body') { - $state = 'results' if $line eq ''; + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; - } elsif ($state =~ /^results/) { - $state = 'results2'; + } elsif ($state =~ /^results/) { + $state = 'results2'; - my ($status, $ip) = split / /, lc $line; - my $h = shift @hosts; + my ($status, $ip) = split / /, lc $line; + my $h = shift @hosts; - $config{$h}{'status'} = $status; - if ($status eq 'good') { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - success("updating %s: %s: IP address set to %s", $h, $status, $ip); + $config{$h}{'status'} = $status; + if ($status eq 'good') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); - } elsif (exists $errors{$status}) { - if ($status eq 'nochg') { - warning("updating %s: %s: %s", $h, $status, $errors{$status}); - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; + } elsif (exists $errors{$status}) { + if ($status eq 'nochg') { + warning("updating %s: %s: %s", $h, $status, $errors{$status}); + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; - } else { - failed("updating %s: %s: %s", $h, $status, $errors{$status}); - } + } else { + failed("updating %s: %s: %s", $h, $status, $errors{$status}); + } - } elsif ($status =~ /w(\d+)(.)/) { - my ($wait, $units) = ($1, lc $2); - my ($sec, $scale) = ($wait, 1); + } elsif ($status =~ /w(\d+)(.)/) { + my ($wait, $units) = ($1, lc $2); + my ($sec, $scale) = ($wait, 1); - ($scale, $units) = (1, 'seconds') if $units eq 's'; - ($scale, $units) = (60, 'minutes') if $units eq 'm'; - ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; - $sec = $wait * $scale; - $config{$h}{'wtime'} = $now + $sec; - warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + $sec = $wait * $scale; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); - } else { - failed("updating %s: %s: unexpected status (%s)", $h, $line); - } - } - } - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) - if $state ne 'results2'; + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; } } ###################################################################### @@ -2977,7 +2976,7 @@ over an http request. Details of the protocol are outlined at: http://www.no-ip.com/integrate/ Configuration variables applicable to the 'noip' protocol are: - protocol=noip ## + protocol=noip ## server=fqdn.of.service ## defaults to dynupdate.no-ip.com login=service-login ## login name and password registered with the service password=service-password ## @@ -2985,8 +2984,8 @@ Configuration variables applicable to the 'noip' protocol are: Example ${program}.conf file entries: ## single host update - protocol=noip, \\ - login=userlogin\@domain.com, \\ + protocol=noip, \\ + login=userlogin\@domain.com, \\ password=noip-password \\ myhost.no-ip.biz @@ -3033,9 +3032,9 @@ sub nic_concont_update { ## update each configured host foreach my $h (@_) { - my $ip = delete $config{$h}{'wantip'}; + my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); # Set the URL that we're going to to update my $url; @@ -3064,20 +3063,17 @@ sub nic_concont_update { last if !header_ok($h, $reply); # Response found, just declare as success (this is ugly, we need more error checking) - if ($reply =~ /SUCCESS/) - { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: good: IP address set to %s", $h, $ip); - } - else - { - my @reply = split /\n/, $reply; - my $returned = pop(@reply); - $config{$h}{'status'} = 'failed'; - failed("updating %s: Server said: '$returned'", $h); - } + if ($reply =~ /SUCCESS/) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + my @reply = split /\n/, $reply; + my $returned = pop(@reply); + $config{$h}{'status'} = 'failed'; + failed("updating %s: Server said: '$returned'", $h); + } } } ###################################################################### @@ -3116,41 +3112,41 @@ sub nic_dslreports1_update { debug("\nnic_dslreports1_update -------------------"); ## update each configured host foreach my $h (@_) { - my $ip = delete $config{$h}{'wantip'}; - info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + my $ip = delete $config{$h}{'wantip'}; + info("setting IP address to %s for %s", $ip, $h); + verbose("UPDATE:", "updating %s", $h); - my $url; - $url = "http://$config{$h}{'server'}/nic/"; - $url .= ynu($config{$h}{'static'}, 'statdns', 'dyndns', 'dyndns'); - $url .= "?action=edit&started=1&hostname=YES&host_id=$h"; - $url .= "&myip="; - $url .= $ip if $ip; + my $url; + $url = "http://$config{$h}{'server'}/nic/"; + $url .= ynu($config{$h}{'static'}, 'statdns', 'dyndns', 'dyndns'); + $url .= "?action=edit&started=1&hostname=YES&host_id=$h"; + $url .= "&myip="; + $url .= $ip if $ip; - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); - next; - } + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); + next; + } - my @reply = split /\n/, $reply; - my $return_code = ''; - foreach my $line (@reply) { - $return_code = $1 if $line =~ m%^return\s+code\s*:\s*(.*)\s*$%i; - } + my @reply = split /\n/, $reply; + my $return_code = ''; + foreach my $line (@reply) { + $return_code = $1 if $line =~ m%^return\s+code\s*:\s*(.*)\s*$%i; + } - if ($return_code !~ /NOERROR/) { - $config{$h}{'status'} = 'failed'; - warning("SENT: %s", $url) unless opt('verbose'); - warning("REPLIED: %s", $reply); - failed("updating %s", $h); + if ($return_code !~ /NOERROR/) { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s", $h); - } else { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: %s: IP address set to %s", $h, $return_code, $ip); - } + } else { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: %s: IP address set to %s", $h, $return_code, $ip); + } } } ###################################################################### @@ -3192,35 +3188,35 @@ sub nic_hammernode1_update { ## update each configured host foreach my $h (@_) { - my $ip = delete $config{$h}{'wantip'}; - info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + my $ip = delete $config{$h}{'wantip'}; + info("setting IP address to %s for %s", $ip, $h); + verbose("UPDATE:", "updating %s", $h); - my $url; - $url = "http://$config{$h}{'server'}/vanity/update"; - $url .= "?ver=1"; - $url .= "&ip="; - $url .= $ip if $ip; + my $url; + $url = "http://$config{$h}{'server'}/vanity/update"; + $url .= "?ver=1"; + $url .= "&ip="; + $url .= $ip if $ip; - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); - last; - } - last if !header_ok($h, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); + last; + } + last if !header_ok($h, $reply); - my @reply = split /\n/, $reply; - if (grep //i, @reply) { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: good: IP address set to %s", $h, $ip); - } else { - $config{$h}{'status'} = 'failed'; - warning("SENT: %s", $url) unless opt('verbose'); - warning("REPLIED: %s", $reply); - failed("updating %s: Invalid reply.", $h); - } + my @reply = split /\n/, $reply; + if (grep //i, @reply) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: Invalid reply.", $h); + } } } ###################################################################### @@ -3277,61 +3273,61 @@ sub nic_zoneedit1_update { ## update each set of hosts that had similar configurations foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $h = $hosts[0]; - my $ip = $config{$h}{'wantip'}; - delete $config{$_}{'wantip'} foreach @hosts; + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + my $ip = $config{$h}{'wantip'}; + delete $config{$_}{'wantip'} foreach @hosts; - info("setting IP address to %s for %s", $ip, $hosts); - verbose("UPDATE:","updating %s", $hosts); + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:", "updating %s", $hosts); - my $url = ''; - $url .= "http://$config{$h}{'server'}/auth/dynamic.html"; - $url .= "?host=$hosts"; - $url .= "&dnsto=$ip" if $ip; - $url .= "&zone=$config{$h}{'zone'}" if defined $config{$h}{'zone'}; + my $url = ''; + $url .= "http://$config{$h}{'server'}/auth/dynamic.html"; + $url .= "?host=$hosts"; + $url .= "&dnsto=$ip" if $ip; + $url .= "&zone=$config{$h}{'zone'}" if defined $config{$h}{'zone'}; - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); - last; - } - last if !header_ok($hosts, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); - my @reply = split /\n/, $reply; - foreach my $line (@reply) { - if ($line =~ /^[^<]*<(SUCCESS|ERROR)\s+([^>]+)>(.*)/) { - my ($status, $assignments, $rest) = ($1, $2, $3); - my ($left, %var) = parse_assignments($assignments); + my @reply = split /\n/, $reply; + foreach my $line (@reply) { + if ($line =~ /^[^<]*<(SUCCESS|ERROR)\s+([^>]+)>(.*)/) { + my ($status, $assignments, $rest) = ($1, $2, $3); + my ($left, %var) = parse_assignments($assignments); - if (keys %var) { - my ($status_code, $status_text, $status_ip) = ('999', '', $ip); - $status_code = $var{'CODE'} if exists $var{'CODE'}; - $status_text = $var{'TEXT'} if exists $var{'TEXT'}; - $status_ip = $var{'IP'} if exists $var{'IP'}; + if (keys %var) { + my ($status_code, $status_text, $status_ip) = ('999', '', $ip); + $status_code = $var{'CODE'} if exists $var{'CODE'}; + $status_text = $var{'TEXT'} if exists $var{'TEXT'}; + $status_ip = $var{'IP'} if exists $var{'IP'}; - if ($status eq 'SUCCESS' || ($status eq 'ERROR' && $var{'CODE'} eq '707')) { - $config{$h}{'ip'} = $status_ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; + if ($status eq 'SUCCESS' || ($status eq 'ERROR' && $var{'CODE'} eq '707')) { + $config{$h}{'ip'} = $status_ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; - success("updating %s: IP address set to %s (%s: %s)", $h, $ip, $status_code, $status_text); + success("updating %s: IP address set to %s (%s: %s)", $h, $ip, $status_code, $status_text); - } else { - $config{$h}{'status'} = 'failed'; - failed("updating %s: %s: %s", $h, $status_code, $status_text); - } - shift @hosts; - $h = $hosts[0]; - $hosts = join(',', @hosts); - } - $line = $rest; - redo if $line; - } - } - failed("updating %s: no response from %s", $hosts, $config{$h}{'server'}) - if @hosts; + } else { + $config{$h}{'status'} = 'failed'; + failed("updating %s: %s: %s", $h, $status_code, $status_text); + } + shift @hosts; + $h = $hosts[0]; + $hosts = join(',', @hosts); + } + $line = $rest; + redo if $line; + } + } + failed("updating %s: no response from %s", $hosts, $config{$h}{'server'}) + if @hosts; } } ###################################################################### @@ -3342,17 +3338,17 @@ sub nic_easydns_updateable { my $update = 0; if ($config{$host}{'mx'} ne $cache{$host}{'mx'}) { - info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); - $update = 1; + info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); + $update = 1; - } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'},1,2,3) ne ynu($config{$host}{'backupmx'},1,2,3))) { - info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'},"YES","NO","NO")); - $update = 1; + } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'}, 1, 2, 3) ne ynu($config{$host}{'backupmx'}, 1, 2, 3))) { + info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'}, "YES", "NO", "NO")); + $update = 1; } elsif ($config{$host}{'static'} ne $cache{$host}{'static'}) { - info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'},"YES","NO","NO")); - $update = 1; + info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'}, "YES", "NO", "NO")); + $update = 1; } return $update; @@ -3414,87 +3410,87 @@ sub nic_easydns_update { my %groups = map { $_ => [ $_ ] } @_; my %errors = ( - 'NOACCESS' => 'Authentication failed. This happens if the username/password OR host or domain are wrong.', - 'NOSERVICE'=> 'Dynamic DNS is not turned on for this domain.', - 'ILLEGAL' => 'Client sent data that is not allowed in a dynamic DNS update.', - 'TOOSOON' => 'Update frequency is too short.', + 'NOACCESS' => 'Authentication failed. This happens if the username/password OR host or domain are wrong.', + 'NOSERVICE' => 'Dynamic DNS is not turned on for this domain.', + 'ILLEGAL' => 'Client sent data that is not allowed in a dynamic DNS update.', + 'TOOSOON' => 'Update frequency is too short.', ); ## update each set of hosts that had similar configurations foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $h = $hosts[0]; - my $ip = $config{$h}{'wantip'}; - delete $config{$_}{'wantip'} foreach @hosts; + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + my $ip = $config{$h}{'wantip'}; + delete $config{$_}{'wantip'} foreach @hosts; - info("setting IP address to %s for %s", $ip, $hosts); - verbose("UPDATE:","updating %s", $hosts); + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:", "updating %s", $hosts); - #'http://members.easydns.com/dyn/dyndns.php?hostname=test.burry.ca&myip=10.20.30.40&wildcard=ON' + #'http://members.easydns.com/dyn/dyndns.php?hostname=test.burry.ca&myip=10.20.30.40&wildcard=ON' - my $url; - $url = "http://$config{$h}{'server'}/dyn/dyndns.php?"; - $url .= "hostname=$hosts"; - $url .= "&myip="; - $url .= $ip if $ip; - $url .= "&wildcard=" . ynu($config{$h}{'wildcard'}, 'ON', 'OFF', 'OFF') if defined $config{$h}{'wildcard'}; + my $url; + $url = "http://$config{$h}{'server'}/dyn/dyndns.php?"; + $url .= "hostname=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; + $url .= "&wildcard=" . ynu($config{$h}{'wildcard'}, 'ON', 'OFF', 'OFF') if defined $config{$h}{'wildcard'}; - if ($config{$h}{'mx'}) { - $url .= "&mx=$config{$h}{'mx'}"; - $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); - } + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); + } - my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); - last; - } - last if !header_ok($hosts, $reply); + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); - my @reply = split /\n/, $reply; - my $state = 'header'; - foreach my $line (@reply) { - if ($state eq 'header') { - $state = 'body'; + my @reply = split /\n/, $reply; + my $state = 'header'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; - } elsif ($state eq 'body') { - $state = 'results' if $line eq ''; + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; - } elsif ($state =~ /^results/) { - $state = 'results2'; + } elsif ($state =~ /^results/) { + $state = 'results2'; - my ($status) = $line =~ /^(\S*)\b.*/; - my $h = shift @hosts; + my ($status) = $line =~ /^(\S*)\b.*/; + my $h = shift @hosts; - $config{$h}{'status'} = $status; - if ($status eq 'NOERROR') { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - success("updating %s: %s: IP address set to %s", $h, $status, $ip); + $config{$h}{'status'} = $status; + if ($status eq 'NOERROR') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); - } elsif ($status =~ /TOOSOON/) { - ## make sure we wait at least a little - my ($wait, $units) = (5, 'm'); - my ($sec, $scale) = ($wait, 1); + } elsif ($status =~ /TOOSOON/) { + ## make sure we wait at least a little + my ($wait, $units) = (5, 'm'); + my ($sec, $scale) = ($wait, 1); - ($scale, $units) = (1, 'seconds') if $units eq 's'; - ($scale, $units) = (60, 'minutes') if $units eq 'm'; - ($scale, $units) = (60*60, 'hours') if $units eq 'h'; - $config{$h}{'wtime'} = $now + $sec; - warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); - } elsif (exists $errors{$status}) { - failed("updating %s: %s: %s", $h, $line, $errors{$status}); + } elsif (exists $errors{$status}) { + failed("updating %s: %s: %s", $h, $line, $errors{$status}); - } else { - failed("updating %s: %s: unexpected status (%s)", $h, $line); - } - last; - } - } - failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) - if $state ne 'results2'; + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + last; + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; } } ###################################################################### @@ -3546,18 +3542,18 @@ sub nic_namecheap_update { foreach my $h (@_) { my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); my $url; - $url = "https://$config{$h}{'server'}/update"; + $url = "https://$config{$h}{'server'}/update"; my $domain = $config{$h}{'login'}; - my $host = $h; - $host =~ s/(.*)\.$domain(.*)/$1$2/; - $url .= "?host=$host"; - $url .= "&domain=$domain"; - $url .= "&password=$config{$h}{'password'}"; - $url .= "&ip="; - $url .= $ip if $ip; + my $host = $h; + $host =~ s/(.*)\.$domain(.*)/$1$2/; + $url .= "?host=$host"; + $url .= "&domain=$domain"; + $url .= "&password=$config{$h}{'password'}"; + $url .= "&ip="; + $url .= $ip if $ip; my $reply = geturl(opt('proxy'), $url); if (!defined($reply) || !$reply) { @@ -3622,7 +3618,7 @@ EoEXAMPLE ## nic_nfsn_gen_auth_header ###################################################################### sub nic_nfsn_gen_auth_header { - my $h = shift; + my $h = shift; my $path = shift; my $body = shift || ''; @@ -3652,9 +3648,9 @@ sub nic_nfsn_gen_auth_header { ## hash is a SHA1 hash of a string in the following format: ## login;timestamp;salt;api-key;request-uri;body-hash - my $hash_string = $config{$h}{'login'}.';'. - $timestamp . ';' . - $salt . ';' . + my $hash_string = $config{$h}{'login'} . ';' . + $timestamp . ';' . + $salt . ';' . $config{$h}{'password'} . ';'; ## The request-uri value is the path portion of the requested URL @@ -3677,14 +3673,14 @@ sub nic_nfsn_gen_auth_header { ## nic_nfsn_make_request ###################################################################### sub nic_nfsn_make_request { - my $h = shift; - my $path = shift; + my $h = shift; + my $path = shift; my $method = shift || 'GET'; - my $body = shift || ''; + my $body = shift || ''; my $base_url = "https://$config{$h}{'server'}"; - my $url = $base_url . $path; - my $header = nic_nfsn_gen_auth_header($h, $path, $body); + my $url = $base_url . $path; + my $header = nic_nfsn_gen_auth_header($h, $path, $body); if ($method eq 'POST' && $body ne '') { $header .= "\nContent-Type: application/x-www-form-urlencoded"; } @@ -3697,10 +3693,10 @@ sub nic_nfsn_make_request { ###################################################################### sub nic_nfsn_handle_error { my $resp = shift; - my $h = shift; + my $h = shift; - $resp =~ s/^.*?\n\n//s; # Strip header - my $json = eval {decode_json($resp)}; + $resp =~ s/^.*?\n\n//s; # Strip header + my $json = eval { decode_json($resp) }; if ($@ || ref($json) ne 'HASH' || not defined $json->{'error'}) { failed("Invalid error response: %s", $resp); return; @@ -3750,17 +3746,17 @@ sub nic_nfsn_update { my $list_path = "/dns/$zone/listRRs"; my $list_body = encode_www_form_urlencoded({name => $name, - type => 'A'}); + type => 'A'}); my $list_resp = nic_nfsn_make_request($h, $list_path, 'POST', - $list_body); + $list_body); if (!header_ok($h, $list_resp)) { $config{$h}{'status'} = 'failed'; nic_nfsn_handle_error($list_resp, $h); next; } - $list_resp =~ s/^.*?\n\n//s; # Strip header - my $list = eval{decode_json($list_resp)}; + $list_resp =~ s/^.*?\n\n//s; # Strip header + my $list = eval { decode_json($list_resp) }; if ($@) { $config{$h}{'status'} = 'failed'; failed("updating %s: JSON decoding failure", $h); @@ -3773,11 +3769,11 @@ sub nic_nfsn_update { my $rr_data = $list->[0]->{'data'}; my $rm_path = "/dns/$zone/removeRR"; my $rm_data = {name => $name, - type => 'A', - data => $rr_data}; + type => 'A', + data => $rr_data}; my $rm_body = encode_www_form_urlencoded($rm_data); my $rm_resp = nic_nfsn_make_request($h, $rm_path, - 'POST', $rm_body); + 'POST', $rm_body); if (!header_ok($h, $rm_resp)) { $config{$h}{'status'} = 'failed'; nic_nfsn_handle_error($rm_resp); @@ -3787,12 +3783,12 @@ sub nic_nfsn_update { my $add_path = "/dns/$zone/addRR"; my $add_data = {name => $name, - type => 'A', - data => $ip, - ttl => $rr_ttl}; + type => 'A', + data => $ip, + ttl => $rr_ttl}; my $add_body = encode_www_form_urlencoded($add_data); my $add_resp = nic_nfsn_make_request($h, $add_path, 'POST', - $add_body); + $add_body); if (header_ok($h, $add_resp)) { $config{$h}{'ip'} = $ip; $config{$h}{'mtime'} = $now; @@ -3851,17 +3847,17 @@ sub nic_sitelutions_update { ## update each configured host foreach my $h (@_) { - my $ip = delete $config{$h}{'wantip'}; + my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); my $url; - $url = "http://$config{$h}{'server'}/dnsup"; - $url .= "?id=$h"; - $url .= "&user=$config{$h}{'login'}"; - $url .= "&pass=$config{$h}{'password'}"; - $url .= "&ip="; - $url .= $ip if $ip; + $url = "http://$config{$h}{'server'}/dnsup"; + $url .= "?id=$h"; + $url .= "&user=$config{$h}{'login'}"; + $url .= "&pass=$config{$h}{'password'}"; + $url .= "&ip="; + $url .= $ip if $ip; my $reply = geturl(opt('proxy'), $url); if (!defined($reply) || !$reply) { @@ -3891,7 +3887,7 @@ sub nic_sitelutions_update { ## nic_freedns_examples ###################################################################### sub nic_freedns_examples { -return < 0); + $freedns_hosts{$rec[0]} = \@rec if ($#rec > 0); } @lines; if (!keys %freedns_hosts) { - failed("Could not get freedns update URLs from %s", $config{$_[0]}{'server'}); - return; + failed("Could not get freedns update URLs from %s", $config{$_[0]}{'server'}); + return; } ## update each configured host foreach my $h (@_) { - if(!$h){ next }; + if (!$h) { next }; my $ip = delete $config{$h}{'wantip'}; - info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + info("setting IP address to %s for %s", $ip, $h); + verbose("UPDATE:", "updating %s", $h); - if($ip eq $freedns_hosts{$h}->[1]) { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("update not necessary %s: good: IP address already set to %s", $h, $ip); - } else { - my $reply = geturl(opt('proxy'), $freedns_hosts{$h}->[2]); - if (!defined($reply) || !$reply) { - failed("updating %s: Could not connect to %s.", $h, $freedns_hosts{$h}->[2]); - last; - } - if(!header_ok($h, $reply)) { - $config{$h}{'status'} = 'failed'; - last; - } + if ($ip eq $freedns_hosts{$h}->[1]) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("update not necessary %s: good: IP address already set to %s", $h, $ip); + } else { + my $reply = geturl(opt('proxy'), $freedns_hosts{$h}->[2]); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $h, $freedns_hosts{$h}->[2]); + last; + } + if (!header_ok($h, $reply)) { + $config{$h}{'status'} = 'failed'; + last; + } - if($reply =~ /Updated.*$h.*to.*$ip/) { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: good: IP address set to %s", $h, $ip); - } else { - $config{$h}{'status'} = 'failed'; - warning("SENT: %s", $freedns_hosts{$h}->[2]) unless opt('verbose'); - warning("REPLIED: %s", $reply); - failed("updating %s: Invalid reply.", $h); - } - } + if ($reply =~ /Updated.*$h.*to.*$ip/) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $freedns_hosts{$h}->[2]) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: Invalid reply.", $h); + } + } } } @@ -3991,7 +3987,7 @@ sub nic_freedns_update { ## nic_changeip_examples ###################################################################### sub nic_changeip_examples { -return < ###################################################################### sub nic_nsupdate_update { - debug("\nnic_nsupdate_update -------------------"); + debug("\nnic_nsupdate_update -------------------"); - ## group hosts with identical attributes together - my %groups = group_hosts_by([ @_ ], [ qw(login password server zone) ]); + ## group hosts with identical attributes together + my %groups = group_hosts_by([ @_ ], [ qw(login password server zone) ]); - ## update each set of hosts that had similar configurations - foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $h = $hosts[0]; - my $binary = $config{$h}{'login'}; - my $keyfile = $config{$h}{'password'}; - my $server = $config{$h}{'server'}; - ## nsupdate requires a port number to be separated by whitepace, not colon - $server =~ s/:/ /; - my $zone = $config{$h}{'zone'}; - my $ip = $config{$h}{'wantip'}; - my $recordtype = ''; - if (is_ipv6($ip)) { - $recordtype = 'AAAA'; - } else { - $recordtype = 'A'; - } - delete $config{$_}{'wantip'} foreach @hosts; + ## update each set of hosts that had similar configurations + foreach my $sig (keys %groups) { + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + my $binary = $config{$h}{'login'}; + my $keyfile = $config{$h}{'password'}; + my $server = $config{$h}{'server'}; + ## nsupdate requires a port number to be separated by whitepace, not colon + $server =~ s/:/ /; + my $zone = $config{$h}{'zone'}; + my $ip = $config{$h}{'wantip'}; + my $recordtype = ''; + if (is_ipv6($ip)) { + $recordtype = 'AAAA'; + } else { + $recordtype = 'A'; + } + delete $config{$_}{'wantip'} foreach @hosts; - info("setting IP address to %s for %s", $ip, $hosts); - verbose("UPDATE:","updating %s", $hosts); + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:", "updating %s", $hosts); - ## send separate requests for each zone with all hosts in that zone - my $instructions = <{result}) { + failed("invalid json or result."); + next; + } + + # Pull the ID out of the json, messy + my ($zone_id) = map { $_->{name} eq $config{$key}{'zone'} ? $_->{id} : () } @{$response->{result}}; + unless ($zone_id) { + failed("updating %s: No zone ID found.", $config{$key}{'zone'}); + next; + } + info("zone ID is $zone_id"); + + # Get DNS record ID + $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records?"; + if (is_ipv6($ip)) { + $url .= "type=AAAA&name=$domain"; + } else { + $url .= "type=A&name=$domain"; + } + + $reply = geturl(opt('proxy'), $url, undef, undef, $headers); + unless ($reply) { + failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); + last; + } + last if !header_ok($domain, $reply); + + # Strip header + $reply =~ s/^.*?\n\n//s; + $response = eval { decode_json($reply) }; + if (!defined $response || !defined $response->{result}) { + failed("invalid json or result."); + next; + } + + # Pull the ID out of the json, messy + my ($dns_rec_id) = map { $_->{name} eq $domain ? $_->{id} : () } @{$response->{result}}; + unless ($dns_rec_id) { + failed("updating %s: No DNS record ID found.", $domain); + next; + } + info("DNS record ID is $dns_rec_id"); + + # Set domain + $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records/$dns_rec_id"; + my $data = "{\"content\":\"$ip\"}"; + $reply = geturl(opt('proxy'), $url, undef, undef, $headers, "PATCH", $data); + unless ($reply) { + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); + last; + } + last if !header_ok($domain, $reply); + + # Strip header + $reply =~ s/^.*?\n\n//s; + $response = eval { decode_json($reply) }; + if (!defined $response || !defined $response->{result}) { + failed("invalid json or result."); + } else { + success("%s -- Updated Successfully to %s", $domain, $ip); + + } + + # Cache + $config{$domain}{'ip'} = $ip; + $config{$domain}{'mtime'} = $now; + $config{$domain}{'status'} = 'good'; + } } - - # FQDNs - for my $domain (@hosts) { - (my $hostname = $domain) =~ s/\.$config{$key}{zone}$//; - delete $config{$domain}{'wantip'}; - - info("setting IP address to %s for %s", $ip, $domain); - verbose("UPDATE:","updating %s", $domain); - - # Get zone ID - my $url = "https://$config{$key}{'server'}/zones?"; - $url .= "name=".$config{$key}{'zone'}; - - my $reply = geturl(opt('proxy'), $url, undef, undef, $headers); - unless ($reply) { - failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); - last; - } - last if !header_ok($domain, $reply); - - # Strip header - $reply =~ s/^.*?\n\n//s; - my $response = eval {decode_json($reply)}; - if (!defined $response || !defined $response->{result}) { - failed ("invalid json or result."); - next; - } - - # Pull the ID out of the json, messy - my ($zone_id) = map { $_->{name} eq $config{$key}{'zone'} ? $_->{id} : () } @{ $response->{result} }; - unless($zone_id) { - failed("updating %s: No zone ID found.", $config{$key}{'zone'}); - next; - } - info("zone ID is $zone_id"); - - # Get DNS record ID - $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records?"; - if (is_ipv6($ip)) { - $url .= "type=AAAA&name=$domain"; - } else { - $url .= "type=A&name=$domain"; - } - - $reply = geturl(opt('proxy'), $url, undef, undef, $headers); - unless ($reply) { - failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); - last; - } - last if !header_ok($domain, $reply); - - # Strip header - $reply =~ s/^.*?\n\n//s; - $response = eval {decode_json($reply)}; - if (!defined $response || !defined $response->{result}) { - failed ("invalid json or result."); - next; - } - - # Pull the ID out of the json, messy - my ($dns_rec_id) = map { $_->{name} eq $domain ? $_->{id} : () } @{ $response->{result} }; - unless($dns_rec_id) { - failed("updating %s: No DNS record ID found.", $domain); - next; - } - info("DNS record ID is $dns_rec_id"); - - # Set domain - $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records/$dns_rec_id"; - my $data = "{\"content\":\"$ip\"}"; - $reply = geturl(opt('proxy'), $url, undef, undef, $headers, "PATCH", $data); - unless ($reply) { - failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); - last; - } - last if !header_ok($domain, $reply); - - # Strip header - $reply =~ s/^.*?\n\n//s; - $response = eval {decode_json($reply)}; - if (!defined $response || !defined $response->{result}) { - failed ("invalid json or result."); - } else { - success ("%s -- Updated Successfully to %s", $domain, $ip); - - } - - # Cache - $config{$domain}{'ip'} = $ip; - $config{$domain}{'mtime'} = $now; - $config{$domain}{'status'} = 'good'; - } - } } ###################################################################### ## nic_yandex_examples @@ -4511,14 +4504,14 @@ Configuration variables applicable to the 'yandex' protocol are: Example ${program}.conf file entries: ## single host update - protocol=yandex, \\ - login=myhost.com, \\ + protocol=yandex, \\ + login=myhost.com, \\ password=123456789ABCDEF0000000000000000000000000000000000000 \\ record.myhost.com ## multiple host update - protocol=yandex, \\ - login=myhost.com, \\ + protocol=yandex, \\ + login=myhost.com, \\ password=123456789ABCDEF0000000000000000000000000000000000000 \\ record.myhost.com,other.myhost.com EoEXAMPLE @@ -4537,9 +4530,9 @@ sub nic_yandex_update { ## update each set of hosts that had similar configurations foreach my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $key = $hosts[0]; - my $ip = $config{$key}{'wantip'}; + my @hosts = @{$groups{$sig}}; + my $key = $hosts[0]; + my $ip = $config{$key}{'wantip'}; my $headers = 'PddToken: ' . $config{$key}{'password'}; # FQDNs @@ -4547,16 +4540,16 @@ sub nic_yandex_update { delete $config{$host}{'wantip'}; info("setting IP address to %s for %s", $ip, $host); - verbose("UPDATE:","updating %s", $host); + verbose("UPDATE:", "updating %s", $host); # Get record ID for host my $url = "https://$config{$host}{'server'}/api2/admin/dns/list?"; - $url .= "domain="; - $url .= $config{$key}{'login'}; + $url .= "domain="; + $url .= $config{$key}{'login'}; my $reply = geturl(opt('proxy'), $url, '', '', $headers); unless ($reply) { - failed("updating %s: Could not connect to %s.", $host, $config{$key}{'server'}); - last; + failed("updating %s: Could not connect to %s.", $host, $config{$key}{'server'}); + last; } last if !header_ok($host, $reply); @@ -4564,25 +4557,25 @@ sub nic_yandex_update { $reply =~ s/^.*?\n\n//s; my $response = eval { decode_json($reply) }; if ($response->{success} eq 'error') { - failed ("%s", $response->{error}); - next; + failed("%s", $response->{error}); + next; } # Pull the ID out of the json - my ($id) = map { $_->{fqdn} eq $host ? $_->{record_id} : () } @{ $response->{records} }; - unless($id) { - failed("updating %s: DNS record ID not found.", $host); - next; + my ($id) = map { $_->{fqdn} eq $host ? $_->{record_id} : () } @{$response->{records}}; + unless ($id) { + failed("updating %s: DNS record ID not found.", $host); + next; } # Update the DNS record $url = "https://$config{$host}{'server'}/api2/admin/dns/edit"; - my $data = "domain="; - $data .= $config{$key}{'login'}; - $data .= "&record_id="; - $data .= $id; - $data .= "&content="; - $data .= $ip if $ip; + my $data = "domain="; + $data .= $config{$key}{'login'}; + $data .= "&record_id="; + $data .= $id; + $data .= "&content="; + $data .= $ip if $ip; $reply = geturl(opt('proxy'), $url, '', '', $headers, 'POST', $data); unless ($reply) { @@ -4595,9 +4588,9 @@ sub nic_yandex_update { $reply =~ s/^.*?\n\n//s; $response = eval { decode_json($reply) }; if ($response->{success} eq 'error') { - failed ("%s", $response->{error}); + failed("%s", $response->{error}); } else { - success ("%s -- Updated Successfully to %s", $host, $ip); + success("%s -- Updated Successfully to %s", $host, $ip); } # Cache @@ -4627,8 +4620,8 @@ Configuration variables applicable to the 'duckdns' protocol are: Example ${program}.conf file entries: ## single host update - protocol=duckdns, \\ - password=your_password, \\ + protocol=duckdns, \\ + password=your_password, \\ myhost EoEXAMPLE @@ -4648,7 +4641,7 @@ sub nic_duckdns_update { foreach my $h (@_) { my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); # Set the URL that we're going to to update my $url; @@ -4673,18 +4666,15 @@ sub nic_duckdns_update { my @reply = split /\n/, $reply; my $returned = pop(@reply); - if ($returned =~ /OK/) - { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: good: IP address set to %s", $h, $ip); - } - else - { - $config{$h}{'status'} = 'failed'; - failed("updating %s: Server said: '$returned'", $h); - } + if ($returned =~ /OK/) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + failed("updating %s: Server said: '$returned'", $h); + } } } @@ -4725,7 +4715,7 @@ sub nic_freemyip_update { foreach my $h (@_) { my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); # Set the URL that we're going to to update my $url; @@ -4747,18 +4737,15 @@ sub nic_freemyip_update { my @reply = split /\n/, $reply; my $returned = pop(@reply); - if ($returned =~ /OK/) - { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; - success("updating %s: good: IP address set to %s", $h, $ip); - } - else - { - $config{$h}{'status'} = 'failed'; - failed("updating %s: Server said: '$returned'", $h); - } + if ($returned =~ /OK/) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + failed("updating %s: Server said: '$returned'", $h); + } } } @@ -4775,7 +4762,7 @@ It offers also nameservers for own domains for free. Dynamic DNS service for own domains is not free. Configuration variables applicable to the 'woima' protocol are: - protocol=woima ## + protocol=woima ## server=fqdn.of.service ## defaults to dyn.woima.fi script=/path/to/script ## defaults to /nic/update backupmx=no|yes ## indicates that this host is the primary MX for the domain. @@ -4789,20 +4776,20 @@ Configuration variables applicable to the 'woima' protocol are: Example ${program}.conf file entries: ## single host update - protocol=woima, \\ + protocol=woima, \\ login=my-dyndns.org-login, \\ password=my-dyndns.org-password \\ myhost.dyndns.org ## multiple host update with wildcard'ing mx, and backupmx - protocol=woima, \\ + protocol=woima, \\ login=my-dyndns.org-login, \\ password=my-dyndns.org-password, \\ mx=a.host.willing.to.mx.for.me,backupmx=yes,wildcard=yes \\ myhost.dyndns.org,my2ndhost.dyndns.org ## multiple host update to the custom DNS service - protocol=woima, \\ + protocol=woima, \\ login=my-dyndns.org-login, \\ password=my-dyndns.org-password \\ my-toplevel-domain.com,my-other-domain.com @@ -4815,57 +4802,57 @@ sub nic_woima_update { debug("\nnic_woima_update -------------------"); my %errors = ( - 'badauth' => 'Bad authorization (username or password)', - 'badsys' => 'The system parameter given was not valid', + 'badauth' => 'Bad authorization (username or password)', + 'badsys' => 'The system parameter given was not valid', - 'notfqdn' => 'A Fully-Qualified Domain Name was not provided', - 'nohost' => 'The hostname specified does not exist in the database', - '!yours' => 'The hostname specified exists, but not under the username currently being used', - '!donator' => 'The offline setting was set, when the user is not a donator', - '!active' => 'The hostname specified is in a Custom DNS domain which has not yet been activated.', - 'abuse', => 'The hostname specified is blocked for abuse; you should receive an email notification ' . - 'which provides an unblock request link. More info can be found on ' . - 'https://www.dyndns.com/support/abuse.html', + 'notfqdn' => 'A Fully-Qualified Domain Name was not provided', + 'nohost' => 'The hostname specified does not exist in the database', + '!yours' => 'The hostname specified exists, but not under the username currently being used', + '!donator' => 'The offline setting was set, when the user is not a donator', + '!active' => 'The hostname specified is in a Custom DNS domain which has not yet been activated.', + 'abuse', => 'The hostname specified is blocked for abuse; you should receive an email notification ' . + 'which provides an unblock request link. More info can be found on ' . + 'https://www.dyndns.com/support/abuse.html', - 'numhost' => 'System error: Too many or too few hosts found. Contact support@dyndns.org', - 'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org', + 'numhost' => 'System error: Too many or too few hosts found. Contact support@dyndns.org', + 'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org', - 'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive', + 'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive', ); my @hosts = @_; foreach my $key (keys @hosts) { - my $h = $hosts[$key]; + my $h = $hosts[$key]; my $ip = $config{$h}{'wantip'}; delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); ## Select the DynDNS system to update my $url = "http://$config{$h}{'server'}$config{$h}{'script'}?system="; if ($config{$h}{'custom'}) { warning("updating %s: 'custom' and 'static' may not be used together. ('static' ignored)", $h) - if $config{$h}{'static'}; - # warning("updating %s: 'custom' and 'offline' may not be used together. ('offline' ignored)", $h) - # if $config{$h}{'offline'}; + if $config{$h}{'static'}; + #warning("updating %s: 'custom' and 'offline' may not be used together. ('offline' ignored)", $h) + # if $config{$h}{'offline'}; $url .= 'custom'; - } elsif ($config{$h}{'static'}) { - # warning("updating %s: 'static' and 'offline' may not be used together. ('offline' ignored)", $h) - # if $config{$h}{'offline'}; + } elsif ($config{$h}{'static'}) { + #warning("updating %s: 'static' and 'offline' may not be used together. ('offline' ignored)", $h) + # if $config{$h}{'offline'}; $url .= 'statdns'; } else { $url .= 'dyndns'; } - $url .= "&hostname=$h"; - $url .= "&myip="; - $url .= $ip if $ip; + $url .= "&hostname=$h"; + $url .= "&myip="; + $url .= $ip if $ip; ## some args are not valid for a custom domain. - $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); + $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); if ($config{$h}{'mx'}) { $url .= "&mx=$config{$h}{'mx'}"; $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); @@ -4878,8 +4865,8 @@ sub nic_woima_update { } last if !header_ok($h, $reply); - my @reply = split /\n/, $reply; - my $state = 'header'; + my @reply = split /\n/, $reply; + my $state = 'header'; my $returnedip = $ip; foreach my $line (@reply) { @@ -4900,19 +4887,19 @@ sub nic_woima_update { $config{$h}{'status'} = $status; if ($status eq 'good') { - $config{$h}{'ip'} = $ip; - $config{$h}{'mtime'} = $now; + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; success("updating %s: %s: IP address set to %s", $h, $status, $ip); } elsif (exists $errors{$status}) { if ($status eq 'nochg') { - warning("updating %s: %s: %s", $h, $status, $errors{$status}); - $config{$h}{'ip'} = $ip; + warning("updating %s: %s: %s", $h, $status, $errors{$status}); + $config{$h}{'ip'} = $ip; $config{$h}{'mtime'} = $now; - $config{$h}{'status'} = 'good'; + $config{$h}{'status'} = 'good'; } else { - failed("updating %s: %s: %s", $h, $status, $errors{$status}); + failed("updating %s: %s: %s", $h, $status, $errors{$status}); } } elsif ($status =~ /w(\d+)(.)/) { @@ -4972,7 +4959,7 @@ sub nic_dondominio_update { foreach my $h (@_) { my $ip = delete $config{$h}{'wantip'}; info("setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","updating %s", $h); + verbose("UPDATE:", "updating %s", $h); # Set the URL that we're going to update my $url; @@ -5032,7 +5019,7 @@ Note: Dynamic record ID is generated when you create a new Dynamic DNS record in Example ${program}.conf file entries: ## single host update protocol=dnsmadeeasy, \\ - username=dme\@example.com, \\ + username=dme\@example.com, \\ password=myg3nerat3dp4ssword, \\ 1007,1008 @@ -5062,12 +5049,12 @@ sub nic_dnsmadeeasy_update { foreach my $h (@_) { my $ip = delete $config{$h}{'wantip'}; info("Setting IP address to %s for %s", $ip, $h); - verbose("UPDATE:","Updating %s", $h); + verbose("UPDATE:", "Updating %s", $h); # Set the URL that we're going to to update my $url; $url = $globals{'ssl'} ? "https://" : "http://"; - $url .= $config{$h}{'server'}.$config{$h}{'script'}; + $url .= $config{$h}{'server'} . $config{$h}{'script'}; $url .= "?username=$config{$h}{'login'}"; $url .= "&password=$config{$h}{'password'}"; $url .= "&ip=$ip"; @@ -5085,15 +5072,12 @@ sub nic_dnsmadeeasy_update { my @reply = split /\n/, $reply; my $returned = pop(@reply); - if ($returned =~ 'success') - { + if ($returned =~ 'success') { $config{$h}{'ip'} = $ip; $config{$h}{'mtime'} = $now; $config{$h}{'status'} = 'good'; success("Updating %s: good: IP address set to %s", $h, $ip); - } - else - { + } else { $config{$h}{'status'} = 'failed'; failed("Updating %s: Server said: '$returned': $messages{$returned}", $h); }