Project

General

Profile

Download (71.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * dyndns.class
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright notice,
13
 *    this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgment:
22
 *    "This product includes software developed by the pfSense Project
23
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
24
 *
25
 * 4. The names "pfSense" and "pfSense Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    coreteam@pfsense.org.
29
 *
30
 * 5. Products derived from this software may not be called "pfSense"
31
 *    nor may "pfSense" appear in their names without prior written
32
 *    permission of the Electric Sheep Fencing, LLC.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *
37
 * "This product includes software developed by the pfSense Project
38
 * for use in the pfSense software distribution (http://www.pfsense.org/).
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 */
53

    
54
	/*
55
	 * PHP.updateDNS (pfSense version)
56
	 *
57
	 * +====================================================+
58
	 *  Services Supported:
59
	 *    - DynDns (dyndns.org) [dynamic, static, custom]
60
	 *    - No-IP (no-ip.com)
61
	 *    - EasyDNS (easydns.com)
62
	 *    - DHS (www.dhs.org)
63
	 *    - HN (hn.org) -- incomplete checking!
64
	 *    - DynS (dyns.org)
65
	 *    - ZoneEdit (zoneedit.com)
66
	 *    - FreeDNS (freedns.afraid.org)
67
	 *    - FreeDNS IPv6 (freedns.afraid.org)
68
	 *    - Loopia (loopia.se)
69
	 *    - StaticCling (staticcling.org)
70
	 *    - DNSexit (dnsexit.com)
71
	 *    - OpenDNS (opendns.com)
72
	 *    - Namecheap (namecheap.com)
73
	 *    - HE.net (dns.he.net)
74
	 *    - HE.net IPv6 (dns.he.net)
75
	 *    - HE.net Tunnelbroker IP update (ipv4.tunnelbroker.net)
76
	 *    - SelfHost (selfhost.de)
77
	 *    - Amazon Route 53 (aws.amazon.com)
78
	 *    - DNS-O-Matic (dnsomatic.com)
79
	 *    - Custom DDNS (any URL)
80
	 *    - Custom DDNS IPv6 (any URL)
81
	 *    - CloudFlare (www.cloudflare.com)
82
	 *    - CloudFlare IPv6 (www.cloudflare.com)
83
	 *    - Eurodns (eurodns.com)
84
	 *    - GratisDNS (gratisdns.dk)
85
	 *    - City Network (citynetwork.se)
86
	 *    - GleSYS (glesys.com)
87
	 *    - DNSimple (dnsimple.com)
88
	 *    - Google Domains (domains.google.com)
89
	 *    - DNS Made Easy (www.dnsmadeeasy.com)
90
	 *    - SPDYN (spdyn.de)
91
	 *    - SPDYN IPv6 (spdyn.de)
92
	 *    - All-Inkl (all-inkl.com)
93
	 *    - DuiaDNS (www.duiadns.net)
94
	 *    - DuiaDNS IPv6 (www.duiadns.net)
95
	 * +----------------------------------------------------+
96
	 *  Requirements:
97
	 *    - PHP version 4.0.2 or higher with the CURL Library and the PCRE Library
98
	 * +----------------------------------------------------+
99
	 *  Public Functions
100
	 *    - updatedns()
101
	 *
102
	 *  Private Functions
103
	 *    - _update()
104
	 *    - _checkStatus()
105
	 *    - _error()
106
	 *    - _detectChange()
107
	 *    - _debug()
108
	 *    - _checkIP()
109
	 * +----------------------------------------------------+
110
	 *  DynDNS Dynamic  - Last Tested: 12 July 2005
111
	 *  DynDNS Static   - Last Tested: NEVER
112
	 *  DynDNS Custom   - Last Tested: NEVER
113
	 *  No-IP           - Last Tested: 20 July 2008
114
	 *  HN.org          - Last Tested: 12 July 2005
115
	 *  EasyDNS         - Last Tested: 20 July 2008
116
	 *  DHS             - Last Tested: 12 July 2005
117
	 *  ZoneEdit        - Last Tested: NEVER
118
	 *  Dyns            - Last Tested: NEVER
119
	 *  ODS             - Last Tested: 02 August 2005
120
	 *  FreeDNS         - Last Tested: 01 May 2016
121
	 *  FreeDNS IPv6    - Last Tested: 01 May 2016
122
	 *  Loopia          - Last Tested: NEVER
123
	 *  StaticCling     - Last Tested: 27 April 2006
124
	 *  DNSexit         - Last Tested: 20 July 2008
125
	 *  OpenDNS         - Last Tested: 4 August 2008
126
	 *  Namecheap       - Last Tested: 31 August 2010
127
	 *  HE.net          - Last Tested: 7 July 2013
128
	 *  HE.net IPv6     - Last Tested: 7 July 2013
129
	 *  HE.net Tunnel   - Last Tested: 28 June 2011
130
	 *  SelfHost        - Last Tested: 26 December 2011
131
	 *  Amazon Route 53 - Last Tested: 04 February 2017
132
	 *  DNS-O-Matic     - Last Tested: 9 September 2010
133
	 *  CloudFlare      - Last Tested: 05 September 2016
134
	 *  CloudFlare IPv6 - Last Tested: 17 July 2016
135
	 *  Eurodns         - Last Tested: 27 June 2013
136
	 *  GratisDNS       - Last Tested: 15 August 2012
137
	 *  OVH DynHOST     - Last Tested: NEVER
138
	 *  City Network    - Last Tested: 13 November 2013
139
	 *  GleSYS          - Last Tested: 3 February 2015
140
	 *  DNSimple        - Last Tested: 09 February 2015
141
	 *  Google Domains  - Last Tested: 27 April 2015
142
	 *  DNS Made Easy   - Last Tested: 27 April 2015
143
	 *  SPDYN           - Last Tested: 02 July 2016
144
	 *  SPDYN IPv6      - Last Tested: 02 July 2016
145
	 *  All-Inkl        - Last Tested: 12 November 2016
146
	 *  DuiaDNS         - Last Tested: 25 November 2016
147
	 *  DuiaDNS IPv6    - Last Tested: 25 November 2016
148
	 * +====================================================+
149
	 *
150
	 * @author 	E.Kristensen
151
	 * @link    	http://www.idylldesigns.com/projects/phpdns/
152
	 * @version 	0.8
153
	 * @updated	13 October 05 at 21:02:42 GMT
154
	 *
155
	 * DNSexit/OpenDNS support and multiwan extension for pfSense by Ermal Luçi
156
	 * Custom DNS support by Matt Corallo
157
	 *
158
	 */
159

    
160
	class updatedns {
161
		var $_cacheFile;
162
		var $_cacheFile_v6;
163
		var $_debugFile;
164
		var $_UserAgent = 'phpDynDNS/0.7';
165
		var $_errorVerbosity = 0;
166
		var $_dnsService;
167
		var $_dnsUser;
168
		var $_dnsPass;
169
		var $_dnsHost;
170
		var $_dnsDomain;
171
		var $_FQDN;
172
		var $_dnsIP;
173
		var $_dnsWildcard;
174
		var $_dnsProxied;
175
		var $_dnsMX;
176
		var $_dnsBackMX;
177
		var $_dnsServer;
178
		var $_dnsPort;
179
		var $_dnsUpdateURL;
180
		var $_dnsZoneID;
181
		var $_dnsTTL;
182
		var $status;
183
		var $_debugID;
184
		var $_if;
185
		var $_dnsResultMatch;
186
		var $_dnsRequestIf;
187
		var $_dnsRequestIfIP;
188
		var $_dnsVerboseLog;
189
		var $_curlIpresolveV4;
190
		var $_curlSslVerifypeer;
191
		var $_dnsMaxCacheAgeDays;
192
		var $_dnsDummyUpdateDone;
193
		var $_forceUpdateNeeded;
194
		var $_useIPv6;
195

    
196
		/*
197
		 * Public Constructor Function (added 12 July 05) [beta]
198
		 *   - Gets the dice rolling for the update.
199
		 *   - $dnsResultMatch should only be used with $dnsService = 'custom'
200
		 *   -  $dnsResultMatch is parsed for '%IP%', which is the IP the provider was updated to,
201
		 *   -  it is otherwise expected to be exactly identical to what is returned by the Provider.
202
		 *   - $dnsUser, and $dnsPass indicate HTTP Auth for custom DNS, if they are needed in the URL (GET Variables), include them in $dnsUpdateURL.
203
		 *   - $For custom requests, $dnsUpdateURL is parsed for '%IP%', which is replaced with the new IP.
204
		 */
205
		function updatedns ($dnsService = '', $dnsHost = '', $dnsDomain = '', $dnsUser = '', $dnsPass = '',
206
					$dnsWildcard = 'OFF', $dnsProxied = false, $dnsMX = '', $dnsIf = '', $dnsBackMX = '',
207
					$dnsServer = '', $dnsPort = '', $dnsUpdateURL = '', $forceUpdate = false,
208
					$dnsZoneID ='', $dnsTTL='', $dnsResultMatch = '', $dnsRequestIf = '',
209
					$dnsID = '', $dnsVerboseLog = false, $curlIpresolveV4 = false, $curlSslVerifypeer = true) {
210

    
211
			global $config, $g, $dyndns_split_domain_types;
212
			if (in_array($dnsService, $dyndns_split_domain_types)) {
213
				$this->_FQDN = $dnsHost . "." . $dnsDomain;
214
			} else {
215
				$this->_FQDN = $dnsHost;
216
			}
217

    
218
			$this->_cacheFile = "{$g['conf_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}.cache";
219
			$this->_cacheFile_v6 = "{$g['conf_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}_v6.cache";
220
			$this->_debugFile = "{$g['varetc_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}.debug";
221

    
222
			$this->_curlIpresolveV4 = $curlIpresolveV4;
223
			$this->_curlSslVerifypeer = $curlSslVerifypeer;
224
			$this->_dnsVerboseLog = $dnsVerboseLog;
225
			if ($this->_dnsVerboseLog) {
226
				log_error(gettext("Dynamic DNS: updatedns() starting"));
227
			}
228

    
229
			$dyndnslck = lock("DDNS".$dnsID, LOCK_EX);
230

    
231
			if (!$dnsService) $this->_error(2);
232
			switch ($dnsService) {
233
			case 'freedns':
234
			case 'freedns-v6':
235
				if (!$dnsHost) $this->_error(5);
236
				break;
237
			case "namecheap":
238
				if (!$dnsPass) $this->_error(4);
239
				if (!$dnsHost) $this->_error(5);
240
				if (!$dnsDomain) $this->_error(5);
241
				break;
242
			case "cloudflare-v6":
243
			case "cloudflare":
244
			case "gratisdns":
245
				if (!$dnsUser) $this->_error(3);
246
				if (!$dnsPass) $this->_error(4);
247
				if (!$dnsHost) $this->_error(5);
248
				if (!$dnsDomain) $this->_error(5);
249
				break;
250
			case 'route53':
251
				if (!$dnsZoneID) $this->_error(8);
252
				if (!$dnsTTL) $this->_error(9);
253
				break;
254
			case 'custom':
255
				if (!$dnsUpdateURL) $this->_error(7);
256
				break;
257
			default:
258
				if (!$dnsUser) $this->_error(3);
259
				if (!$dnsPass) $this->_error(4);
260
				if (!$dnsHost) $this->_error(5);
261
			}
262

    
263
			switch ($dnsService) {
264
				case 'he-net-v6':
265
				case 'custom-v6':
266
				case 'spdyn-v6':
267
				case 'duiadns-v6':
268
				case 'freedns-v6':
269
				case 'cloudflare-v6':
270
					$this->_useIPv6 = true;
271
					break;
272
				default:
273
					$this->_useIPv6 = false;
274
			}
275
			$this->_dnsService = strtolower($dnsService);
276
			$this->_dnsUser = $dnsUser;
277
			$this->_dnsPass = base64_decode($dnsPass);
278
			$this->_dnsHost = $dnsHost;
279
			$this->_dnsDomain = $dnsDomain;
280
			$this->_dnsServer = $dnsServer;
281
			$this->_dnsPort = $dnsPort;
282
			$this->_dnsWildcard = $dnsWildcard;
283
			$this->_dnsProxied = $dnsProxied;
284
			$this->_dnsMX = $dnsMX;
285
			$this->_dnsZoneID = $dnsZoneID;
286
			$this->_dnsTTL = $dnsTTL;
287
			$this->_if = get_failover_interface($dnsIf);
288
			$this->_checkIP();
289
			$this->_dnsUpdateURL = $dnsUpdateURL;
290
			$this->_dnsResultMatch = $dnsResultMatch;
291
			$this->_dnsRequestIf = get_failover_interface($dnsRequestIf);
292
			if ($this->_dnsVerboseLog) {
293
				log_error(sprintf(gettext('Dynamic DNS (%1$s): running get_failover_interface for %2$s. found %3$s'), $this->_FQDN, $dnsRequestIf, $this->_dnsRequestIf));
294
			}
295
			$this->_dnsRequestIfIP = get_interface_ip($dnsRequestIf);
296
			$this->_dnsMaxCacheAgeDays = 25;
297
			$this->_dnsDummyUpdateDone = false;
298
			$this->_forceUpdateNeeded = $forceUpdate;
299

    
300
			// Ensure that we were able to lookup the IP
301
			if (!is_ipaddr($this->_dnsIP)) {
302
				log_error(sprintf(gettext('Dynamic DNS (%1$s) There was an error trying to determine the public IP for interface - %2$s (%3$s %4$s).'), $this->_FQDN, $dnsIf, $this->_if, $this->_dnsIP));
303
				unlock($dyndnslck);
304
				return;
305
			}
306

    
307
			$this->_debugID = rand(1000000, 9999999);
308

    
309
			if ($forceUpdate == false && $this->_detectChange() == false) {
310
				$this->_error(10);
311
			} else {
312
				switch ($this->_dnsService) {
313
					case 'glesys':
314
					case 'dnsomatic':
315
					case 'dyndns':
316
					case 'dyndns-static':
317
					case 'dyndns-custom':
318
					case 'dhs':
319
					case 'noip':
320
					case 'noip-free':
321
					case 'easydns':
322
					case 'hn':
323
					case 'zoneedit':
324
					case 'dyns':
325
					case 'ods':
326
					case 'freedns':
327
					case 'freedns-v6':
328
					case 'loopia':
329
					case 'staticcling':
330
					case 'dnsexit':
331
					case 'custom':
332
					case 'custom-v6':
333
					case 'opendns':
334
					case 'namecheap':
335
					case 'he-net':
336
					case 'he-net-v6':
337
					case 'duiadns':
338
					case 'duiadns-v6':
339
					case 'selfhost':
340
					case 'he-net-tunnelbroker':
341
					case 'route53':
342
					case 'cloudflare':
343
					case 'cloudflare-v6':
344
					case 'eurodns':
345
					case 'gratisdns':
346
					case 'ovh-dynhost':
347
					case 'citynetwork':
348
					case 'dnsimple':
349
					case 'googledomains':
350
					case 'dnsmadeeasy':
351
					case 'spdyn':
352
					case 'spdyn-v6':
353
					case 'all-inkl':
354
						$this->_update();
355
						if ($this->_dnsDummyUpdateDone == true) {
356
							// If a dummy update was needed, then sleep a while and do the update again to put the proper address back.
357
							// Some providers (e.g. No-IP free accounts) need to have at least 1 address change every month.
358
							// If the address has not changed recently, or the user did "Force Update", then the code does
359
							// a dummy address change for providers like this.
360
							sleep(10);
361
							$this->_update();
362
						}
363
						break;
364
					default:
365
						$this->_error(6);
366
						break;
367
				}
368
			}
369

    
370
			unlock($dyndnslck);
371
		}
372

    
373
		/*
374
		 * Private Function (added 12 July 05) [beta]
375
		 *   Send Update To Selected Service.
376
		 */
377
		function _update() {
378

    
379
			if ($this->_dnsVerboseLog) {
380
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _update() starting.'), $this->_dnsService, $this->_FQDN));
381
			}
382

    
383
			if (strstr($this->_dnsRequestIf, "_vip")) {
384
				$parentif = get_configured_vip_interface($this->_dnsRequestIf);
385
				$realparentif = convert_friendly_interface_to_real_interface_name($parentif);
386
			} else {
387
				$realparentif = $this->_dnsRequestIf;
388
			}
389

    
390
			$ch = curl_init();
391

    
392
			if ($this->_useIPv6 == false) {
393
				curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
394
			}
395

    
396
			if ($this->_dnsService != 'ods') {
397
				curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
398
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
399
				curl_setopt($ch, CURLOPT_INTERFACE, 'if!' . $realparentif);
400
				curl_setopt($ch, CURLOPT_TIMEOUT, 120); // Completely empirical
401
			}
402

    
403
			switch ($this->_dnsService) {
404
				case 'glesys':
405
					$needsIP = TRUE;
406
					$server = 'https://api.glesys.com/domain/updaterecord/format/json';
407
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
408
					$post_data['recordid'] = $this->_FQDN;
409
					$post_data['data'] = $this->_dnsIP;
410
					curl_setopt($ch, CURLOPT_URL, $server);
411
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
412
					break;
413
				case 'dyndns':
414
				case 'dyndns-static':
415
				case 'dyndns-custom':
416
					$needsIP = FALSE;
417
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
418
						$this->_dnsWildcard = "ON";
419
					}
420
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
421
					$server = "https://members.dyndns.org/nic/update";
422
					$port = "";
423
					if ($this->_dnsServer) {
424
						$server = $this->_dnsServer;
425
					}
426
					if ($this->_dnsPort) {
427
						$port = ":" . $this->_dnsPort;
428
					}
429
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
430
					break;
431
				case 'dhs':
432
					// DHS is disabled in the GUI because the following doesn't work.
433
					$needsIP = TRUE;
434
					$post_data['hostscmd'] = 'edit';
435
					$post_data['hostscmdstage'] = '2';
436
					$post_data['type'] = '4';
437
					$post_data['updatetype'] = 'Online';
438
					$post_data['mx'] = $this->_dnsMX;
439
					$post_data['mx2'] = '';
440
					$post_data['txt'] = '';
441
					$post_data['offline_url'] = '';
442
					$post_data['cloak'] = 'Y';
443
					$post_data['cloak_title'] = '';
444
					$post_data['ip'] = $this->_dnsIP;
445
					$post_data['domain'] = 'dyn.dhs.org';
446
					$post_data['hostname'] = $this->_dnsHost;
447
					$post_data['submit'] = 'Update';
448
					$server = "https://members.dhs.org/nic/hosts";
449
					$port = "";
450
					if ($this->_dnsServer) {
451
						$server = $this->_dnsServer;
452
					}
453
					if ($this->_dnsPort) {
454
						$port = ":" . $this->_dnsPort;
455
					}
456
					curl_setopt($ch, CURLOPT_URL, $server . $port);
457
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
458
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
459
					break;
460
				case 'noip':
461
				case 'noip-free':
462
					$needsIP = TRUE;
463
					$server = "https://dynupdate.no-ip.com/ducupdate.php";
464
					$port = "";
465
					if ($this->_dnsServer) {
466
						$server = $this->_dnsServer;
467
					}
468
					if ($this->_dnsPort) {
469
						$port = ":" . $this->_dnsPort;
470
					}
471
					if (($this->_dnsService == "noip-free") &&
472
					    ($this->_forceUpdateNeeded == true) &&
473
					    ($this->_dnsDummyUpdateDone == false)) {
474
						// Update the IP to a dummy value to force No-IP free accounts to see a change.
475
						$iptoset = "192.168.1.1";
476
						$this->_dnsDummyUpdateDone = true;
477
						log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): Processing dummy update on No-IP free account. IP temporarily set to %3$s'), $this->_dnsService, $this->_dnsHost, $iptoset));
478
					} else {
479
						$iptoset = $this->_dnsIP;
480
					}
481
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&pass=' . urlencode($this->_dnsPass) . '&h[]=' . $this->_dnsHost.'&ip=' . $iptoset);
482
					break;
483
				case 'easydns':
484
					$needsIP = TRUE;
485
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
486
					$server = "https://members.easydns.com/dyn/dyndns.php";
487
					$port = "";
488
					if ($this->_dnsServer) {
489
						$server = $this->_dnsServer;
490
					}
491
					if ($this->_dnsPort) {
492
						$port = ":" . $this->_dnsPort;
493
					}
494
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard=' . $this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=' . $this->_dnsBackMX);
495
					break;
496
				case 'hn':
497
					$needsIP = TRUE;
498
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
499
					$server = "http://dup.hn.org/vanity/update";
500
					$port = "";
501
					if ($this->_dnsServer) {
502
						$server = $this->_dnsServer;
503
					}
504
					if ($this->_dnsPort) {
505
						$port = ":" . $this->_dnsPort;
506
					}
507
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?ver=1&IP=' . $this->_dnsIP);
508
					break;
509
				case 'zoneedit':
510
					$needsIP = FALSE;
511
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
512

    
513
					$server = "https://dynamic.zoneedit.com/auth/dynamic.html";
514
					$port = "";
515
					if ($this->_dnsServer) {
516
						$server = $this->_dnsServer;
517
					}
518
					if ($this->_dnsPort) {
519
						$port = ":" . $this->_dnsPort;
520
					}
521
					curl_setopt($ch, CURLOPT_URL, "{$server}{$port}?host=" . $this->_dnsHost . '&dnsto=' . $this->_dnsIP);
522
					break;
523
				case 'dyns':
524
					$needsIP = FALSE;
525
					$server = "http://www.dyns.net/postscript011.php";
526
					$port = "";
527
					if ($this->_dnsServer) {
528
						$server = $this->_dnsServer;
529
					}
530
					if ($this->_dnsPort) {
531
						$port = ":" . $this->_dnsPort;
532
					}
533
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&password=' . $this->_dnsPass . '&host=' . $this->_dnsHost);
534
					break;
535
				case 'ods':
536
					$needsIP = FALSE;
537
					$misc_errno = 0;
538
					$misc_error = "";
539
					$server = "ods.org";
540
					$port = "";
541
					if ($this->_dnsServer) {
542
						$server = $this->_dnsServer;
543
					}
544
					if ($this->_dnsPort) {
545
						$port = ":" . $this->_dnsPort;
546
					}
547
					$this->con['socket'] = fsockopen("{$server}{$port}", "7070", $misc_errno, $misc_error, 30);
548
					/* Check that we have connected */
549
					if (!$this->con['socket']) {
550
						print "error! could not connect.";
551
						break;
552
					}
553
					/* Here is the loop. Read the incoming data (from the socket connection) */
554
					while (!feof($this->con['socket'])) {
555
						$this->con['buffer']['all'] = trim(fgets($this->con['socket'], 4096));
556
						$code = substr($this->con['buffer']['all'], 0, 3);
557
						sleep(1);
558
						switch ($code) {
559
							case 100:
560
								fputs($this->con['socket'], "LOGIN ".$this->_dnsUser." ".$this->_dnsPass."\n");
561
								break;
562
							case 225:
563
								fputs($this->con['socket'], "DELRR ".$this->_dnsHost." A\n");
564
								break;
565
							case 901:
566
								fputs($this->con['socket'], "ADDRR ".$this->_dnsHost." A ".$this->_dnsIP."\n");
567
								break;
568
							case 795:
569
								fputs($this->con['socket'], "QUIT\n");
570
								break;
571
						}
572
					}
573
					$this->_checkStatus(0, $code);
574
					break;
575
				case 'freedns':
576
				case 'freedns-v6':
577
					$needIP = FALSE;
578
					curl_setopt($ch, CURLOPT_URL, 'https://freedns.afraid.org/dynamic/update.php?' . $this->_dnsPass);
579
					break;
580
				case 'dnsexit':
581
					$needsIP = TRUE;
582
					curl_setopt($ch, CURLOPT_URL, 'https://www.dnsexit.com/RemoteUpdate.sv?login='.$this->_dnsUser. '&password='.$this->_dnsPass.'&host='.$this->_dnsHost.'&myip='.$this->_dnsIP);
583
					break;
584
				case 'loopia':
585
					$needsIP = TRUE;
586
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
587
					curl_setopt($ch, CURLOPT_URL, 'https://dns.loopia.se/XDynDNSServer/XDynDNS.php?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP);
588
					break;
589
				case 'opendns':
590
					$needsIP = FALSE;
591
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
592
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
593
					$server = "https://updates.opendns.com/nic/update?hostname=". $this->_dnsHost;
594
					$port = "";
595
					if ($this->_dnsServer) {
596
						$server = $this->_dnsServer;
597
					}
598
					if ($this->_dnsPort) {
599
						$port = ":" . $this->_dnsPort;
600
					}
601
					curl_setopt($ch, CURLOPT_URL, $server .$port);
602
					break;
603

    
604
				case 'staticcling':
605
					$needsIP = FALSE;
606
					curl_setopt($ch, CURLOPT_URL, 'https://www.staticcling.org/update.html?login='.$this->_dnsUser.'&pass='.$this->_dnsPass);
607
					break;
608
				case 'dnsomatic':
609
					/* Example syntax
610
						https://username:password@updates.dnsomatic.com/nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
611
					*/
612
					$needsIP = FALSE;
613
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
614
						$this->_dnsWildcard = "ON";
615
					}
616
					/*
617
					Reference: https://www.dnsomatic.com/wiki/api
618
						DNS-O-Matic usernames are 3-25 characters.
619
						DNS-O-Matic passwords are 6-20 characters.
620
						All ASCII letters and numbers accepted.
621
						Dots, dashes, and underscores allowed, but not at the beginning or end of the string.
622
					Required: "rawurlencode" http://www.php.net/manual/en/function.rawurlencode.php
623
						Encodes the given string according to RFC 3986.
624
					*/
625
					$server = "https://" . rawurlencode($this->_dnsUser) . ":" . rawurlencode($this->_dnsPass) . "@updates.dnsomatic.com/nic/update?hostname=";
626
					if ($this->_dnsServer) {
627
						$server = $this->_dnsServer;
628
					}
629
					if ($this->_dnsPort) {
630
						$port = ":" . $this->_dnsPort;
631
					}
632
					curl_setopt($ch, CURLOPT_URL, $server . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NOCHG');
633
					break;
634
				case 'namecheap':
635
					/* Example:
636
						https://dynamicdns.park-your-domain.com/update?host=[host_name]&domain=[domain.com]&password=[domain_password]&ip=[your_ip]
637
					*/
638
					$needsIP = FALSE;
639
					$dnspass = trim($this->_dnsPass);
640
					$server = "https://dynamicdns.park-your-domain.com/update?host={$this->_dnsHost}&domain={$this->_dnsDomain}&password={$dnspass}&ip={$this->_dnsIP}";
641
					curl_setopt($ch, CURLOPT_URL, $server);
642
					break;
643
				case 'duiadns':
644
				case 'duiadns-v6':
645
					$needsIP = FALSE;
646
					$server = "https://ipv4.duiadns.net/dyndns.duia?";
647
					curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
648
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
649
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
650
					curl_setopt($ch, CURLOPT_URL, $server . 'hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
651
					break;
652
				case 'he-net':
653
				case 'he-net-v6':
654
					$needsIP = FALSE;
655
					$server = "https://dyn.dns.he.net/nic/update?";
656
					curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
657
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
658
					curl_setopt($ch, CURLOPT_URL, $server . 'hostname=' . $this->_dnsHost . '&password=' . $this->_dnsPass . '&myip=' . $this->_dnsIP);
659
					break;
660
				case 'he-net-tunnelbroker':
661
					$needsIP = FALSE;
662
					$server = "https://ipv4.tunnelbroker.net/ipv4_end.php?";
663
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
664
					curl_setopt($ch, CURLOPT_URL, $server . 'tid=' . $this->_dnsHost);
665
					break;
666
				case 'selfhost':
667
					$needsIP = FALSE;
668
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
669
						$this->_dnsWildcard = "ON";
670
					}
671
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
672
					$server = "https://carol.selfhost.de/nic/update";
673
					$port = "";
674
					if ($this->_dnsServer) {
675
						$server = $this->_dnsServer;
676
					}
677
					if ($this->_dnsPort) {
678
						$port = ":" . $this->_dnsPort;
679
					}
680
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
681
					break;
682
				case 'route53':		
683
					require_once("r53.class");
684
					$r53 = new Route53($this->_dnsUser, $this->_dnsPass);
685
					list($r53_regionId, $r53_zoneId) = split('/', $this->_dnsZoneID);
686
					$apiurl = $r53->getApiUrl($r53_zoneId);
687
					$xmlreq = $r53->getRequestBody($this->_dnsHost, $this->_dnsIP, $this->_dnsTTL);
688
					$httphead = $r53->getHttpPostHeaders($r53_zoneId, $r53_regionId, hash("sha256",$xmlreq));
689
					curl_setopt($ch, CURLOPT_HTTPHEADER, $httphead);
690
					if($this->_dnsVerboseLog){
691
						log_error(sprintf("Sending reuquest to: %s", $apiurl));
692
						foreach($httphead as $hv){
693
							log_error(sprintf("Header: %s", $hv));
694
						}
695
						log_error(sprintf("XMLPOST: %s", $xmlreq));
696
					}
697
					curl_setopt($ch, CURLOPT_URL, $apiurl);
698
					curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlreq);
699
					break;
700
				case 'custom':
701
				case 'custom-v6':
702
					if (strstr($this->dnsUpdateURL, "%IP%")) {$needsIP = TRUE;} else {$needsIP = FALSE;}
703
					if ($this->_dnsUser != '') {
704
						if ($this->_curlIpresolveV4) {
705
							curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
706
						}
707
						if ($this->_curlSslVerifypeer) {
708
							curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
709
						} else {
710
							curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
711
						}
712
						curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
713
						curl_setopt($ch, CURLOPT_USERPWD, "{$this->_dnsUser}:{$this->_dnsPass}");
714
					}
715
					$server = str_replace("%IP%", $this->_dnsIP, $this->_dnsUpdateURL);
716
					if ($this->_dnsVerboseLog) {
717
						log_error(sprintf(gettext("Sending request to: %s"), $server));
718
					}
719
					curl_setopt($ch, CURLOPT_URL, $server);
720
					break;
721
				case 'cloudflare-v6':
722
				case 'cloudflare':
723
					$this->_FQDN = ltrim($this->_FQDN, '@.');
724
					$isv6 = ($this->_dnsService === 'cloudflare-v6');
725
					$recordType = $isv6 ? "AAAA" : "A";
726
					$needsIP = TRUE;
727
					$dnsServer ='api.cloudflare.com';
728
					$dnsHost = str_replace(' ', '', $this->_dnsHost);
729

    
730
					curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
731
					curl_setopt($ch, CURLOPT_HTTPHEADER, array(
732
						'X-Auth-Email: '.$this->_dnsUser.'',
733
						'X-Auth-Key: '.$this->_dnsPass.'',
734
						'Content-Type: application/json'
735
					));
736

    
737
					// Get zone ID
738
					$getZoneId = "https://{$dnsServer}/client/v4/zones/?name={$this->_dnsDomain}";
739
					curl_setopt($ch, CURLOPT_URL, $getZoneId);
740
					$output = json_decode(curl_exec($ch));
741
					$zone = $output->result[0]->id;
742
					if ($zone) { // If zone ID was found get host ID
743
						$getHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records?name={$this->_FQDN}&type={$recordType}";
744
						curl_setopt($ch, CURLOPT_URL, $getHostId);
745
						$output = json_decode(curl_exec($ch));
746
						$host = $output->result[0]->id;
747
						if ($host) { // If host ID was found update host
748
							$hostData = array(
749
								"content" => "{$this->_dnsIP}",
750
								"type" => "{$recordType}",
751
								"proxied" => $this->_dnsProxied,
752
								"name" => "{$this->_dnsHost}"
753
							);
754
							$data_json = json_encode($hostData);
755
							$updateHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records/{$host}";
756
							curl_setopt($ch, CURLOPT_URL, $updateHostId);
757
							curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
758
							curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
759
						}
760
					}
761
					break;
762
				case 'eurodns':
763
					$needsIP = TRUE;
764
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
765
					$server = "https://update.eurodyndns.org/update/";
766
					$port = "";
767
					if ($this->_dnsPort) {
768
						$port = ":" . $this->_dnsPort;
769
					}
770
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
771
					break;
772
				case 'gratisdns':
773
					$needsIP = TRUE;
774
					$server = "https://ssl.gratisdns.dk/ddns.phtml";
775
					curl_setopt($ch, CURLOPT_URL, $server . '?u=' . $this->_dnsUser . '&p=' . $this->_dnsPass . '&h=' . $this->_dnsHost . '&d=' . $this->_dnsDomain . '&i=' . $this->_dnsIP);
776
					break;
777
				case 'ovh-dynhost':
778
					$needsIP = FALSE;
779
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
780
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
781
					$server = "https://www.ovh.com/nic/update";
782
					$port = "";
783
					if ($this->_dnsServer) {
784
						$server = $this->_dnsServer;
785
					}
786
					if ($this->_dnsPort) {
787
						$port = ":" . $this->_dnsPort;
788
					}
789
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
790
					break;
791
				case 'citynetwork':
792
					$needsIP = TRUE;
793
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
794
					$server = 'https://dyndns.citynetwork.se/nic/update';
795
					$port = "";
796
					if ($this->_dnsServer) {
797
						$server = $this->_dnsServer;
798
					}
799
					if ($this->_dnsPort) {
800
						$port = ":" . $this->_dnsPort;
801
					}
802
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
803
					break;
804
				case 'dnsimple':
805
					/* Uses DNSimple's REST API
806
					   Requires username and Account API token passed in header
807
					   Piggybacks on Route 53's ZoneID field for DNSimple record ID
808
					   Data sent as JSON */
809
					$needsIP = TRUE;
810
					$server = 'https://api.dnsimple.com/v1/domains/';
811
					$token = $this->_dnsUser . ':' . $this->_dnsPass;
812
					$jsondata = '{"record":{"content":"' . $this->_dnsIP . '","ttl":"' . $this->_dnsTTL . '"}}';
813
					curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
814
					curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json', 'X-DNSimple-Token: ' . $token));
815
					curl_setopt($ch, CURLOPT_URL, $server . $this->_dnsHost . '/records/' . $this->_dnsZoneID);
816
					curl_setopt($ch, CURLOPT_POSTFIELDS, $jsondata);
817
					break;
818
				case 'googledomains':
819
					$needsIP = FALSE;
820
					$post_data['username:password'] = $this->_dnsUser . ':' . $this->_dnsPass;
821
					$post_data['hostname'] = $this->_dnsHost;
822
					$post_data['myip'] = $this->_dnsIP;
823
					$post_data['offline'] = 'no';
824
					$server = "https://domains.google.com/nic/update";
825
					$port = "";
826
					curl_setopt($ch, CURLOPT_URL, 'https://domains.google.com/nic/update');
827
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
828
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
829
					break;
830
				case 'dnsmadeeasy':
831
					$needsIP = TRUE;
832
					$server = "https://cp.dnsmadeeasy.com/servlet/updateip";
833
					curl_setopt($ch, CURLOPT_URL, $server . '?username=' . $this->_dnsUser . '&password=' . $this->_dnsPass . '&id=' . $this->_dnsHost . '&ip=' . $this->_dnsIP);
834
					break;
835
				case 'spdyn':
836
				case 'spdyn-v6':
837
					$needsIP = FALSE;
838
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
839
					$server = "https://update.spdyn.de/nic/update";
840
					$port = "";
841
					if ($this->_dnsServer) {
842
						$server = $this->_dnsServer;
843
					}
844
					if ($this->_dnsPort) {
845
						$port = ":" . $this->_dnsPort;
846
					}
847
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
848
					break;
849
				case 'all-inkl':
850
					$needsIP = FALSE;
851
					$server = 'https://dyndns.kasserver.com/';
852
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
853
					curl_setopt($ch, CURLOPT_URL, $server . 'myip=' . $this->_dnsIP);
854
					break;
855
				default:
856
					break;
857
			}
858
			if ($this->_dnsService != 'ods') {
859
				curl_setopt($ch, CURLOPT_HEADER, 1);
860
				$response = curl_exec($ch);
861
				$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
862
				$header = substr($response, 0, $header_size);
863
				$data = substr($response, $header_size);
864
				$this->_checkStatus($ch, $data, $header);
865
				@curl_close($ch);
866
			}
867
		}
868

    
869
		/*
870
		 * Private Function (added 12 July 2005) [beta]
871
		 *   Retrieve Update Status
872
		 */
873
		function _checkStatus($ch, $data, $header) {
874
			if ($this->_dnsVerboseLog) {
875
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkStatus() starting.'), $this->_dnsService, $this->_FQDN));
876
			}
877
			$successful_update = false;
878
			$success_str = "(" . gettext("Success") . ") ";
879
			$error_str = "(" . gettext("Error") . ") ";
880
			$status_intro = "phpDynDNS ({$this->_dnsHost}): ";
881

    
882
			if ($this->_dnsService != 'ods' && @curl_error($ch)) {
883
				$status = gettext("Curl error occurred:") . " " . curl_error($ch);
884
				log_error($status);
885
				$this->status = $status;
886
				return;
887
			}
888
			switch ($this->_dnsService) {
889
				case 'glesys':
890
					$status_intro = "GleSYS ({$this->_dnsHost}): ";
891
					if (preg_match('/Record updated/i', $data)) {
892
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
893
						$successful_update = true;
894
					} else {
895
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
896
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
897
						$this->_debug($data);
898
					}
899
					break;
900
				case 'dnsomatic':
901
					$status_intro = "DNS-O-Matic ({$this->_dnsHost}): ";
902
					if (preg_match('/badauth/i', $data)) {
903
						$status = $status_intro . gettext("The DNS-O-Matic username or password specified are incorrect. No updates will be distributed to services until this is resolved.");
904
					} else if (preg_match('/notfqdn /i', $data)) {
905
						$status = $status_intro . gettext("The hostname specified is not a fully-qualified domain name. If no hostnames included, notfqdn will be returned once.");
906
					} else if (preg_match('/nohost/i', $data)) {
907
						$status = $status_intro . gettext("The hostname passed could not be matched to any services configured. The service field will be blank in the return code.");
908
					} else if (preg_match('/numhost/i', $data)) {
909
						$status = $status_intro . gettext("Up to 20 hosts my be updated. numhost is returned if attempting to update more than 20 or update a round-robin.");
910
					} else if (preg_match('/abuse/i', $data)) {
911
						$status = $status_intro . gettext("The hostname is blocked for update abuse.");
912
					} else if (preg_match('/good/i', $data)) {
913
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
914
						$successful_update = true;
915
					} else if (preg_match('/dnserr/i', $data)) {
916
						$status = $status_intro . gettext("DNS error encountered. Stop updating for 30 minutes.");
917
					} else {
918
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
919
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
920
						$this->_debug($data);
921
					}
922
					break;
923
				case 'citynetwork':
924
					if (preg_match('/notfqdn/i', $data)) {
925
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
926
					} else if (preg_match('/nohost/i', $data)) {
927
						$status = $status_intro . $error_str . gettext("No such host");
928
					} else if (preg_match('/nochg/i', $data)) {
929
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
930
						$successful_update = true;
931
					} else if (preg_match('/good/i', $data)) {
932
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
933
						$successful_update = true;
934
					} else if (preg_match('/badauth/i', $data)) {
935
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
936
					} else {
937
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
938
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
939
						$this->_debug($data);
940
					}
941
					break;
942
				case 'ovh-dynhost':
943
				case 'dyndns':
944
					if (preg_match('/notfqdn/i', $data)) {
945
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
946
					} else if (preg_match('/nochg/i', $data)) {
947
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
948
						$successful_update = true;
949
					} else if (preg_match('/good/i', $data)) {
950
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
951
						$successful_update = true;
952
					} else if (preg_match('/noauth/i', $data)) {
953
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
954
					} else {
955
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
956
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
957
						$this->_debug($data);
958
					}
959
					break;
960
				case 'dyndns-static':
961
					if (preg_match('/notfqdn/i', $data)) {
962
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
963
					} else if (preg_match('/nochg/i', $data)) {
964
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
965
						$successful_update = true;
966
					} else if (preg_match('/good/i', $data)) {
967
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
968
						$successful_update = true;
969
					} else if (preg_match('/noauth/i', $data)) {
970
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
971
					} else {
972
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
973
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
974
						$this->_debug($data);
975
					}
976
					break;
977
				case 'dyndns-custom':
978
					if (preg_match('/notfqdn/i', $data)) {
979
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
980
					} else if (preg_match('/nochg/i', $data)) {
981
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
982
						$successful_update = true;
983
					} else if (preg_match('/good/i', $data)) {
984
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
985
						$successful_update = true;
986
					} else if (preg_match('/noauth/i', $data)) {
987
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
988
					} else {
989
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
990
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
991
						$this->_debug($data);
992
					}
993
					break;
994
				case 'dhs':
995
					break;
996
				case 'noip':
997
				case 'noip-free':
998
					list($ip, $code) = explode(":", $data);
999
					switch ($code) {
1000
						case 0:
1001
							$status = $status_intro . $success_str . gettext("IP address is current, no update performed.");
1002
							$successful_update = true;
1003
							break;
1004
						case 1:
1005
							$status = $status_intro . $success_str . gettext("DNS hostname update successful.");
1006
							$successful_update = true;
1007
							break;
1008
						case 2:
1009
							$status = $status_intro . $error_str . gettext("Hostname supplied does not exist.");
1010
							break;
1011
						case 3:
1012
							$status = $status_intro . $error_str . gettext("Invalid Username.");
1013
							break;
1014
						case 4:
1015
							$status = $status_intro . $error_str . gettext("Invalid Password.");
1016
							break;
1017
						case 5:
1018
							$status = $status_intro . $error_str . gettext("Too many updates sent.");
1019
							break;
1020
						case 6:
1021
							$status = $status_intro . $error_str . gettext("Account disabled due to violation of No-IP terms of service.");
1022
							break;
1023
						case 7:
1024
							$status = $status_intro . $error_str . gettext("Invalid IP. IP Address submitted is improperly formatted or is a private IP address or is on a blacklist.");
1025
							break;
1026
						case 8:
1027
							$status = $status_intro . $error_str . gettext("Disabled / Locked Hostname.");
1028
							break;
1029
						case 9:
1030
							$status = $status_intro . $error_str . gettext("Host updated is configured as a web redirect and no update was performed.");
1031
							break;
1032
						case 10:
1033
							$status = $status_intro . $error_str . gettext("Group supplied does not exist.");
1034
							break;
1035
						case 11:
1036
							$status = $status_intro . $success_str . gettext("DNS group update is successful.");
1037
							$successful_update = true;
1038
							break;
1039
						case 12:
1040
							$status = $status_intro . $success_str . gettext("DNS group is current, no update performed.");
1041
							$successful_update = true;
1042
							break;
1043
						case 13:
1044
							$status = $status_intro . $error_str . gettext("Update client support not available for supplied hostname or group.");
1045
							break;
1046
						case 14:
1047
							$status = $status_intro . $error_str . gettext("Hostname supplied does not have offline settings configured.");
1048
							break;
1049
						case 99:
1050
							$status = $status_intro . $error_str . gettext("Client disabled. Client should exit and not perform any more updates without user intervention.");
1051
							break;
1052
						case 100:
1053
							$status = $status_intro . $error_str . gettext("Client disabled. Client should exit and not perform any more updates without user intervention.");
1054
							break;
1055
						default:
1056
							$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1057
							$this->_debug(gettext("Unknown Response:") . " " . $data);
1058
							break;
1059
					}
1060
					break;
1061
				case 'easydns':
1062
					if (preg_match('/NOACCESS/i', $data)) {
1063
						$status = $status_intro . $error_str . gettext("Authentication Failed: Username and/or Password was Incorrect.");
1064
					} else if (preg_match('/NOSERVICE/i', $data)) {
1065
						$status = $status_intro . $error_str . gettext("No Service: Dynamic DNS Service has been disabled for this domain.");
1066
					} else if (preg_match('/ILLEGAL INPUT/i', $data)) {
1067
						$status = $status_intro . $error_str . gettext("Illegal Input: Self-Explanatory");
1068
					} else if (preg_match('/TOOSOON/i', $data)) {
1069
						$status = $status_intro . $error_str . gettext("Too Soon: Not Enough Time Has Elapsed Since Last Update");
1070
					} else if (preg_match('/NOERROR/i', $data)) {
1071
						$status = $status_intro . $success_str . gettext("IP Updated Successfully!");
1072
						$successful_update = true;
1073
					} else {
1074
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1075
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1076
						$this->_debug($data);
1077
					}
1078
					break;
1079
				case 'hn':
1080
					/* FIXME: add checks */
1081
					break;
1082
				case 'zoneedit':
1083
					if (preg_match('/799/i', $data)) {
1084
						$status = $status_intro . "(" . gettext("Error 799") . ") " . gettext("Update Failed!");
1085
					} else if (preg_match('/700/i', $data)) {
1086
						$status = $status_intro . "(" . gettext("Error 700") . ") " . gettext("Update Failed!");
1087
					} else if (preg_match('/200/i', $data)) {
1088
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1089
						$successful_update = true;
1090
					} else if (preg_match('/201/i', $data)) {
1091
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1092
						$successful_update = true;
1093
					} else {
1094
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1095
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1096
						$this->_debug($data);
1097
					}
1098
					break;
1099
				case 'dyns':
1100
					if (preg_match("/400/i", $data)) {
1101
						$status = $status_intro . $error_str . gettext("Bad Request - The URL was malformed. Required parameters were not provided.");
1102
					} else if (preg_match('/402/i', $data)) {
1103
						$status = $status_intro . $error_str . gettext("Update Too Soon - Attempted to update too quickly since last change.");
1104
					} else if (preg_match('/403/i', $data)) {
1105
						$status = $status_intro . $error_str . gettext("Database Error - There was a server-sided database error.");
1106
					} else if (preg_match('/405/i', $data)) {
1107
						$status = $status_intro . $error_str . sprintf(gettext("Hostname Error - The hostname (%s) doesn't belong to user (%s)."), $this->_dnsHost, $this->_dnsUser);
1108
					} else if (preg_match('/200/i', $data)) {
1109
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1110
						$successful_update = true;
1111
					} else {
1112
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1113
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1114
						$this->_debug($data);
1115
					}
1116
					break;
1117
				case 'ods':
1118
					if (preg_match("/299/i", $data)) {
1119
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1120
						$successful_update = true;
1121
					} else {
1122
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1123
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1124
						$this->_debug($data);
1125
					}
1126
					break;
1127
				case 'freedns':
1128
				case 'freedns-v6':
1129
					if (preg_match("/has not changed./i", $data)) {
1130
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1131
						$successful_update = true;
1132
					} else if (preg_match("/Updated/i", $data)) {
1133
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1134
						$successful_update = true;
1135
					} else {
1136
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1137
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1138
						$this->_debug($data);
1139
					}
1140
					break;
1141
				case 'dnsexit':
1142
					if (preg_match("/is the same/i", $data)) {
1143
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1144
						$successful_update = true;
1145
					} else if (preg_match("/Success/i", $data)) {
1146
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1147
						$successful_update = true;
1148
					} else {
1149
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1150
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1151
						$this->_debug($data);
1152
					}
1153
					break;
1154
				case 'loopia':
1155
					if (preg_match("/nochg/i", $data)) {
1156
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1157
						$successful_update = true;
1158
					} else if (preg_match("/good/i", $data)) {
1159
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1160
						$successful_update = true;
1161
					} else if (preg_match('/badauth/i', $data)) {
1162
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1163
					} else {
1164
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1165
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1166
						$this->_debug($data);
1167
					}
1168
					break;
1169
				case 'opendns':
1170
					if (preg_match('/badauth/i', $data)) {
1171
						$status = $status_intro . $error_str . gettext("Not a valid username or password!");
1172
					} else if (preg_match('/nohost/i', $data)) {
1173
						$status = $status_intro . $error_str . gettext("Hostname specified does not exist.");
1174
						$successful_update = true;
1175
					} else if (preg_match('/good/i', $data)) {
1176
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1177
						$successful_update = true;
1178
					} else if (preg_match('/yours/i', $data)) {
1179
						$status = $status_intro . $error_str . gettext("Hostname specified exists, but not under the username specified.");
1180
					} else if (preg_match('/abuse/i', $data)) {
1181
						$status = $status_intro . $error_str . gettext("Updating too frequently, considered abuse.");
1182
					} else {
1183
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1184
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1185
						$this->_debug($data);
1186
					}
1187
					break;
1188
				case 'staticcling':
1189
					if (preg_match("/invalid ip/i", $data)) {
1190
						$status = $status_intro . $error_str . gettext("Bad Request - The IP provided was invalid.");
1191
					} else if (preg_match('/required info missing/i', $data)) {
1192
						$status = $status_intro . $error_str . gettext("Bad Request - Required parameters were not provided.");
1193
					} else if (preg_match('/invalid characters/i', $data)) {
1194
						$status = $status_intro . $error_str . gettext("Bad Request - Illegal characters in either the username or the password.");
1195
					} else if (preg_match('/bad password/i', $data)) {
1196
						$status = $status_intro . $error_str . gettext("Invalid password.");
1197
					} else if (preg_match('/account locked/i', $data)) {
1198
						$status = $status_intro . $error_str . gettext("This account has been administratively locked.");
1199
					} else if (preg_match('/update too frequent/i', $data)) {
1200
						$status = $status_intro . $error_str . gettext("Updating too frequently.");
1201
					} else if (preg_match('/DB error/i', $data)) {
1202
						$status = $status_intro . $error_str . gettext("Server side error.");
1203
					} else if (preg_match('/success/i', $data)) {
1204
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1205
						$successful_update = true;
1206
					} else {
1207
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1208
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1209
						$this->_debug($data);
1210
					}
1211
					break;
1212
				case 'namecheap':
1213
					$tmp = str_replace("^M", "", $data);
1214
					$ncresponse = @xml2array($tmp);
1215
					if (preg_match("/internal server error/i", $data)) {
1216
						$status = $status_intro . $error_str . gettext("Server side error.");
1217
					} else if (preg_match("/request is badly formed/i", $data)) {
1218
						$status = $status_intro . $error_str . gettext("Badly Formed Request (check the settings).");
1219
					} else if ($ncresponse['interface-response']['ErrCount'] === "0") {
1220
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1221
						$successful_update = true;
1222
					} else if (is_numeric($ncresponse['interface-response']['ErrCount']) && ($ncresponse['interface-response']['ErrCount'] > 0)) {
1223
						$status = $status_intro . $error_str . implode(", ", $ncresponse["interface-response"]["errors"]);
1224
						$successful_update = true;
1225
					} else {
1226
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1227
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1228
						$this->_debug($data);
1229
					}
1230
					break;
1231
				case 'duiadns':
1232
				case 'duiadns-v6':
1233
					if (preg_match("/error/i", $data)) {
1234
						$status = $status_intro . $error_str . gettext("Server side error.");
1235
					} else if (preg_match('/nohost/i', $data)) {
1236
						$status = $status_intro . $error_str . gettext("Bad Request - A hostname was not provided.");
1237
					} else if (preg_match('/badauth/i', $data)) {
1238
						$status = $status_intro . $error_str . gettext("Invalid username or password.");
1239
					} else if (preg_match('/good/i', $data)) {
1240
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1241
						$successful_update = true;
1242
					} else if (preg_match('/nochg/i', $data)) {
1243
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1244
						$successful_update = true;
1245
					} else {
1246
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1247
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1248
						$this->_debug($data);
1249
					}
1250
					break;
1251
				case 'he-net':
1252
				case 'he-net-v6':
1253
					if (preg_match("/badip/i", $data)) {
1254
						$status = $status_intro . $error_str . gettext("Bad Request - The IP provided was invalid.");
1255
					} else if (preg_match('/nohost/i', $data)) {
1256
						$status = $status_intro . $error_str . gettext("Bad Request - A hostname was not provided.");
1257
					} else if (preg_match('/badauth/i', $data)) {
1258
						$status = $status_intro . $error_str . gettext("Invalid username or password.");
1259
					} else if (preg_match('/good/i', $data)) {
1260
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1261
						$successful_update = true;
1262
					} else if (preg_match('/nochg/i', $data)) {
1263
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1264
						$successful_update = true;
1265
					} else {
1266
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1267
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1268
						$this->_debug($data);
1269
					}
1270
					break;
1271
				case 'he-net-tunnelbroker':
1272
					/*
1273
					-ERROR: Missing parameter(s).
1274
					-ERROR: Invalid API key or password
1275
					-ERROR: Tunnel not found
1276
					-ERROR: Another tunnel exists for this IP.
1277
					-ERROR: This tunnel is already associated with this IP address
1278
					+OK: Tunnel endpoint updated to: x.x.x.x
1279
					*/
1280
					if (preg_match("/Missing parameter/i", $data)) {
1281
						$status = $status_intro . $error_str . gettext("Bad Request - Missing/Invalid Parameters.");
1282
					} else if (preg_match('/Tunnel not found/i', $data)) {
1283
						$status = $status_intro . $error_str . gettext("Bad Request - Invalid Tunnel ID.");
1284
					} else if (preg_match('/Invalid API key or password/i', $data)) {
1285
						$status = $status_intro . $error_str . gettext("Invalid username or password.");
1286
					} else if (preg_match('/OK:/i', $data)) {
1287
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1288
						$successful_update = true;
1289
					} else if (preg_match('/This tunnel is already associated with this IP address/i', $data)) {
1290
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1291
						$successful_update = true;
1292
					} else {
1293
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1294
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1295
						$this->_debug($data);
1296
					}
1297
					break;
1298
				case 'selfhost':
1299
					if (preg_match('/notfqdn/i', $data)) {
1300
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
1301
					} else if (preg_match('/nochg/i', $data)) {
1302
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1303
						$successful_update = true;
1304
					} else if (preg_match('/good/i', $data)) {
1305
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1306
						$successful_update = true;
1307
					} else if (preg_match('/noauth/i', $data)) {
1308
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1309
					} else {
1310
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1311
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1312
						$this->_debug($data);
1313
					}
1314
					break;
1315
				case 'route53':
1316
					if(preg_match('/ErrorResponse/', $data)){
1317
						$status = $status_intro . $error_str . gettext("Route53 API call failed");
1318
						log_error(sprintf("error message: %s", $data));
1319
						$status_update = false;
1320
					} else {
1321
						$status = $status_intro . $success_str . gettext("IP address changed successfully");
1322
						$successful_update = true;
1323
					}
1324
					break;
1325
				case 'custom':
1326
				case 'custom-v6':
1327
					$successful_update = false;
1328
					if ($this->_dnsResultMatch == "") {
1329
						$successful_update = true;
1330
					} else {
1331
						$this->_dnsResultMatch = str_replace("%IP%", $this->_dnsIP, $this->_dnsResultMatch);
1332
						$matches = preg_split("/(?<!\\\\)\\|/", $this->_dnsResultMatch);
1333
						foreach ($matches as $match) {
1334
							$match= str_replace("\\|", "|", $match);
1335
							if (strcmp($match, trim($data, "\t\n\r")) == 0) {
1336
								$successful_update = true;
1337
							}
1338
						}
1339
						unset ($matches);
1340
					}
1341
					if ($successful_update == true) {
1342
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1343
					} else {
1344
						$status = $status_intro . $error_str . gettext("Result did not match.") . " [" . $data . "]";
1345
					}
1346
					break;
1347
				case 'cloudflare-v6':
1348
				case 'cloudflare':
1349
					$output = json_decode($data);
1350
					if ($output->result->content === $this->_dnsIP) {
1351
						$status = $status_intro . $success_str . sprintf(gettext('%1$s updated to %2$s'), $this->_dnsHost, $this->_dnsIP);
1352
						$successful_update = true;
1353
					} elseif ($output->errors[0]->code === 9103) {
1354
						$status = $status_intro . $error_str . gettext("Invalid Credentials! Don't forget to use API Key for password field with CloudFlare.");
1355
					} elseif (($output->success) && (!$output->result[0]->id)) {
1356
						$status = $status_intro . $error_str . gettext("Zone or Host ID was not found, check the hostname.");
1357
					} else {
1358
						$status = $status_intro . gettext("UNKNOWN ERROR") . " - " . $output->errors[0]->message;
1359
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1360
					}
1361
					break;
1362
				case 'eurodns':
1363
					if (preg_match('/notfqdn/i', $data)) {
1364
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
1365
					} else if (preg_match('/nochg/i', $data)) {
1366
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1367
						$successful_update = true;
1368
					} else if (preg_match('/good/i', $data)) {
1369
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1370
						$successful_update = true;
1371
					} else if (preg_match('/badauth/i', $data)) {
1372
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1373
					} else {
1374
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1375
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1376
						$this->_debug($data);
1377
					}
1378
					break;
1379
				case 'gratisdns':
1380
					if (preg_match('/Forkerte værdier/i', $data)) {
1381
						$status = $status_intro . $error_str . gettext("Wrong values - Update could not be completed.");
1382
					} else if (preg_match('/Bruger login: Bruger eksistere ikke/i', $data)) {
1383
						$status = $status_intro . $error_str . gettext("Unknown username - User does not exist.");
1384
					} else if (preg_match('/Bruger login: 1Fejl i kodeord/i', $data)) {
1385
						$status = $status_intro . $error_str . gettext("Wrong password - Remember password is case sensitive.");
1386
					} else if (preg_match('/Domæne kan IKKE administreres af bruger/i', $data)) {
1387
						$status = $status_intro . $error_str . gettext("User unable to administer the selected domain.");
1388
					} else if (preg_match('/OK/i', $data)) {
1389
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1390
						$successful_update = true;
1391
					} else {
1392
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1393
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1394
						$this->_debug($data);
1395
					}
1396
					break;
1397
				case 'dnsimple':
1398
					/* Responds with HTTP 200 on success.
1399
					   Responds with HTTP 4xx on error.
1400
					   Returns JSON data as body */
1401
;
1402
					if (preg_match("/\s200\sOK/i", $header)) {
1403
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1404
						$successful_update = true;
1405
					} else if (preg_match("/\s4\d\d\s/i", $header)) {
1406
						$arrbody = json_decode($data, true);
1407
						$message = $arrbody['message'] . ".";
1408
						if (isset($arrbody['errors']['content'])) {
1409
							foreach ($arrbody['errors']['content'] as $key => $content) {
1410
								$message .= " " . $content . ".";
1411
							}
1412
						}
1413
						$status = $status_intro . $error_str . $message;
1414
					} else {
1415
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1416
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1417
						$this->_debug($data);
1418
					}
1419
					break;
1420
				case 'googledomains':
1421
					if (preg_match('/notfqdn/i', $data)) {
1422
						$status = $status_intro . $error_str . gettext("Not A FQDN");
1423
					} else if (preg_match('/nochg/i', $data)) {
1424
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1425
						$successful_update = true;
1426
					} else if (preg_match('/good/i', $data)) {
1427
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1428
						$successful_update = true;
1429
					} else if (preg_match('/badauth/i', $data)) {
1430
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1431
					} else if (preg_match('/nohost/i', $data)) {
1432
						$status = $status_intro . $error_str . gettext("Hostname does not exist or DynDNS not enabled");
1433
					} else if (preg_match('/badagent/i', $data)) {
1434
						$status = $status_intro . $error_str . gettext("Bad request");
1435
					} else if (preg_match('/abuse/i', $data)) {
1436
						$status = $status_intro . $error_str . gettext("Dynamic DNS access has been blocked!");
1437
					} else if (preg_match('/911/i', $data)) {
1438
						$status = $status_intro . $error_str . gettext("Error on Google's end, retry in 5 minutes");
1439
					} else {
1440
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1441
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1442
						$this->_debug($data);
1443
					}
1444
					break;
1445
				case 'dnsmadeeasy':
1446
					switch ($data) {
1447
						case 'success':
1448
							$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1449
							$successful_update = true;
1450
							break;
1451
						case 'error-auth':
1452
							$status = $status_intro . $error_str . gettext("Invalid username or password");
1453
							break;
1454
						case 'error-auth-suspend':
1455
							$status = $status_intro . $error_str . gettext("Account suspended");
1456
							break;
1457
						case 'error-auth-voided':
1458
							$status = $status_intro . $error_str . gettext("Account revoked");
1459
							break;
1460
						case 'error-record-invalid':
1461
							$status = $status_intro . $error_str . gettext("Record does not exist in the system. Unable to update record");
1462
							break;
1463
						case 'error-record-auth':
1464
							$status = $status_intro . $error_str . gettext("User does not have access to this record");
1465
							break;
1466
						case 'error-record-ip-same':
1467
							$status = $status_intro . $success_str . gettext("No Change In IP Address");
1468
							$successful_update = true;
1469
							break;
1470
						case 'error-system':
1471
							$status = $status_intro . $error_str . gettext("General system error recognized by the system");
1472
							break;
1473
						case 'error':
1474
							$status = $status_intro . $error_str . gettext("General system error unrecognized by the system");
1475
							break;
1476
						default:
1477
							$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1478
							log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1479
							$this->_debug($data);
1480
							break;
1481
					}
1482
					break;
1483
				case 'spdyn':
1484
				case 'spdyn-v6':
1485
					if (preg_match('/notfqdn/i', $data)) {
1486
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
1487
					} else if (preg_match('/nohost/i', $data)) {
1488
						$status = $status_intro . $error_str . gettext("No such host");
1489
					} else if (preg_match('/nochg/i', $data)) {
1490
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1491
						$successful_update = true;
1492
					} else if (preg_match('/good/i', $data)) {
1493
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1494
						$successful_update = true;
1495
					} else if (preg_match('/badauth/i', $data)) {
1496
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1497
					} else {
1498
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1499
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1500
						$this->_debug($data);
1501
					}
1502
					break;
1503
				case 'all-inkl':
1504
 					if (preg_match('/good\s'.$this->_dnsIP.'/i', $data)) {
1505
							$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1506
 							$successful_update = true;
1507
 					} else if (preg_match('/good/i', $data)) {
1508
						$status = $status_intro . $error_str . gettext("Result did not match.");
1509
					} else if (preg_match("/\s401\sUnauthorized/i", $header)) {
1510
						$status = $status_intro . $error_str . gettext("Invalid username or password");
1511
					} 
1512
					else {
1513
							$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1514
							log_error($status_intro . gettext("PAYLOAD:") . " " . $header.$data);
1515
 							$this->_debug($data);
1516
 							$this->_debug($header);
1517
 					}
1518
 					break;
1519
			}
1520

    
1521
			if ($successful_update == true) {
1522
				/* Write WAN IP to cache file */
1523
				$wan_ip = $this->_checkIP();
1524
				conf_mount_rw();
1525
				if ($this->_useIPv6 == false && $wan_ip > 0) {
1526
					$currentTime = time();
1527
					notify_all_remote(sprintf(gettext('DynDNS updated IP Address on %1$s (%2$s) to %3$s'), convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
1528
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile, $wan_ip));
1529
					@file_put_contents($this->_cacheFile, "{$wan_ip}|{$currentTime}");
1530
				} else {
1531
					@unlink($this->_cacheFile);
1532
				}
1533
				if ($this->_useIPv6 == true && $wan_ip > 0) {
1534
					$currentTime = time();
1535
					notify_all_remote(sprintf(gettext("DynDNS updated IPv6 Address on %s (%s) to %s"), convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
1536
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile_v6, $wan_ip));
1537
					@file_put_contents($this->_cacheFile_v6, "{$wan_ip}|{$currentTime}");
1538
				} else {
1539
					@unlink($this->_cacheFile_v6);
1540
				}
1541
				conf_mount_ro();
1542
			}
1543
			$this->status = $status;
1544
			log_error($status);
1545
		}
1546

    
1547
		/*
1548
		 * Private Function (added 12 July 05) [beta]
1549
		 *   Return Error, Set Last Error, and Die.
1550
		 */
1551
		function _error($errorNumber = '1') {
1552
			$err_str = 'phpDynDNS: (' . gettext('ERROR!') . ') ';
1553
			$err_str_r53 = 'Route 53: (' . gettext('Error') . ') ';
1554
			switch ($errorNumber) {
1555
				case 0:
1556
					break;
1557
				case 2:
1558
					$error = $err_str . gettext('No Dynamic DNS Service provider was selected.');
1559
					break;
1560
				case 3:
1561
					$error = $err_str . gettext('No Username Provided.');
1562
					break;
1563
				case 4:
1564
					$error = $err_str . gettext('No Password Provided.');
1565
					break;
1566
				case 5:
1567
					$error = $err_str . gettext('No Hostname Provided.');
1568
					break;
1569
				case 6:
1570
					$error = $err_str . gettext('The Dynamic DNS Service provided is not yet supported.');
1571
					break;
1572
				case 7:
1573
					$error = $err_str . gettext('No Update URL Provided.');
1574
					break;
1575
				case 8:
1576
					$status = $err_str_r53 . gettext("Invalid ZoneID");
1577
					break;
1578
				case 9:
1579
					$status = $err_str_r53 . gettext("Invalid TTL");
1580
					break;
1581
				case 10:
1582
					$error = "phpDynDNS ({$this->_FQDN}): " . sprintf(gettext("No change in my IP address and/or %s days has not passed. Not updating dynamic DNS entry."), $this->_dnsMaxCacheAgeDays);
1583
					break;
1584
				default:
1585
					$error = $err_str . gettext('Unknown Response.');
1586
					/* FIXME: $data isn't in scope here */
1587
					/* $this->_debug($data); */
1588
					break;
1589
			}
1590
			$this->lastError = $error;
1591
			log_error($error);
1592
		}
1593

    
1594
		/*
1595
		 * Private Function (added 12 July 05) [beta]
1596
		 *   - Detect whether or not IP needs to be updated.
1597
		 *      | Written Specifically for pfSense (https://www.pfsense.org) may
1598
		 *      | work with other systems. pfSense base is FreeBSD.
1599
		 */
1600
		function _detectChange() {
1601
			global $debug;
1602

    
1603
			if ($debug) {
1604
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _detectChange() starting.'), $this->_dnsService, $this->_FQDN));
1605
			}
1606

    
1607
			$currentTime = time();
1608

    
1609
			$wan_ip = $this->_checkIP();
1610
			if ($wan_ip == 0) {
1611
				log_error(sprintf(gettext("Dynamic Dns (%s): Current WAN IP could not be determined, skipping update process."), $this->_FQDN));
1612
				return false;
1613
			}
1614
			$log_error = sprintf(gettext('Dynamic Dns (%1$s): Current WAN IP: %2$s'), $this->_FQDN, $wan_ip) . " ";
1615

    
1616
			if ($this->_useIPv6 == true) {
1617
				if (file_exists($this->_cacheFile_v6)) {
1618
					$contents = file_get_contents($this->_cacheFile_v6);
1619
					list($cacheIP, $cacheTime) = explode('|', $contents);
1620
					$this->_debug($cacheIP.'/'.$cacheTime);
1621
					$initial = false;
1622
					$log_error .= sprintf(gettext("Cached IPv6: %s"), $cacheIP);
1623
				} else {
1624
					conf_mount_rw();
1625
					$cacheIP = '::';
1626
					@file_put_contents($this->_cacheFile, "::|{$currentTime}");
1627
					conf_mount_ro();
1628
					$cacheTime = $currentTime;
1629
					$initial = true;
1630
					$log_error .= gettext("No Cached IPv6 found.");
1631
				}
1632
			} else {
1633
				if (file_exists($this->_cacheFile)) {
1634
					$contents = file_get_contents($this->_cacheFile);
1635
					list($cacheIP, $cacheTime) = explode('|', $contents);
1636
					$this->_debug($cacheIP.'/'.$cacheTime);
1637
					$initial = false;
1638
					$log_error .= sprintf(gettext("Cached IP: %s"), $cacheIP);
1639
				} else {
1640
					conf_mount_rw();
1641
					$cacheIP = '0.0.0.0';
1642
					@file_put_contents($this->_cacheFile, "0.0.0.0|{$currentTime}");
1643
					conf_mount_ro();
1644
					$cacheTime = $currentTime;
1645
					$initial = true;
1646
					$log_error .= gettext("No Cached IP found.");
1647
				}
1648
			}
1649
			if ($this->_dnsVerboseLog) {
1650
				log_error($log_error);
1651
			}
1652

    
1653
			// Convert seconds = days * hr/day * min/hr * sec/min
1654
			$maxCacheAgeSecs = $this->_dnsMaxCacheAgeDays * 24 * 60 * 60;
1655

    
1656
			$needs_updating = FALSE;
1657
			/* lets determine if the item needs updating */
1658
			if ($cacheIP != $wan_ip) {
1659
				$needs_updating = true;
1660
				$update_reason = gettext("Dynamic Dns: cacheIP != wan_ip. Updating.") . " ";
1661
				$update_reason .= sprintf(gettext('Cached IP: %1$s WAN IP: %2$s'), $cacheIP, $wan_ip) . " ";
1662
			}
1663
			if (($currentTime - $cacheTime) > $maxCacheAgeSecs) {
1664
				$needs_updating = true;
1665
				$this->_forceUpdateNeeded = true;
1666
				$update_reason = sprintf(gettext("Dynamic Dns: More than %s days. Updating."), $this->_dnsMaxCacheAgeDays);
1667
				$update_reason .= " {$currentTime} - {$cacheTime} > {$maxCacheAgeSecs} ";
1668
			}
1669
			if ($initial == true) {
1670
				$needs_updating = true;
1671
				$update_reason .= gettext("Initial update.");
1672
			}
1673

    
1674
			/*   finally if we need updating then store the
1675
			 *   new cache value and return true
1676
			 */
1677
			if ($needs_updating == true) {
1678
				if ($this->_dnsVerboseLog) {
1679
					log_error("DynDns ({$this->_FQDN}): {$update_reason}");
1680
				}
1681
				return true;
1682
			}
1683

    
1684
			return false;
1685
		}
1686

    
1687
		/*
1688
		 * Private Function (added 16 July 05) [beta]
1689
		 *   - Writes debug information to a file.
1690
		 *   - This function is only called when a unknown response
1691
		 *   - status is returned from a DynDNS service provider.
1692
		 */
1693
		function _debug($data) {
1694
			global $g;
1695

    
1696
			if (!$g['debug']) {
1697
				return;
1698
			}
1699
			$string = date('m-d-y h:i:s').' - ('.$this->_debugID.') - ['.$this->_dnsService.'] - '.$data."\n";
1700
			conf_mount_rw();
1701
			$file = fopen($this->_debugFile, 'a');
1702
			fwrite($file, $string);
1703
			fclose($file);
1704
			conf_mount_ro();
1705
		}
1706
		function _checkIP() {
1707
			global $debug;
1708

    
1709
			if ($debug) {
1710
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkIP() starting.'), $this->_dnsService, $this->_FQDN));
1711
			}
1712

    
1713
			if ($this->_useIPv6 == true) {
1714
				$ip_address = get_interface_ipv6($this->_if);
1715
				if (!is_ipaddrv6($ip_address)) {
1716
					return 0;
1717
				}
1718
			} else {
1719
				$ip_address = get_interface_ip($this->_if);
1720
				if (!is_ipaddr($ip_address)) {
1721
					return 0;
1722
				}
1723
			}
1724
			if ($this->_useIPv6 == false && is_private_ip($ip_address)) {
1725
				$hosttocheck = "checkip.dyndns.org";
1726
				$try = 0;
1727
				while ($try < 3) {
1728
					$checkip = gethostbyname($hosttocheck);
1729
					if (is_ipaddr($checkip)) {
1730
						break;
1731
					}
1732
					$try++;
1733
				}
1734
				if ($try >= 3) {
1735
					log_error(sprintf(gettext('Dynamic DNS %1$s debug information (%2$s): Could not resolve %3$s to IP using interface IP %4$s.'), $this->_dnsService, $this->_FQDN, $hosttocheck, $ip_address));
1736
					return 0;
1737
				}
1738
				$ip_ch = curl_init("http://{$checkip}");
1739
				curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1740
				curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1741
				curl_setopt($ip_ch, CURLOPT_INTERFACE, 'host!' . $ip_address);
1742
				curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1743
				curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1744
				if ($this->_useIPv6 == false) {
1745
					curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1746
				}
1747
				$ip_result_page = curl_exec($ip_ch);
1748
				curl_close($ip_ch);
1749
				$ip_result_decoded = urldecode($ip_result_page);
1750
				preg_match('/Current IP Address: (.*)<\/body>/', $ip_result_decoded, $matches);
1751
				$ip_address = trim($matches[1]);
1752
				if (is_ipaddr($ip_address)) {
1753
					if ($this->_dnsVerboseLog) {
1754
						log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from %4$s'), $this->_dnsService, $this->_FQDN, $ip_address, $hosttocheck));
1755
					}
1756
				} else {
1757
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): IP address could not be extracted from %3$s'), $this->_dnsService, $this->_FQDN, $hosttocheck));
1758
					return 0;
1759
				}
1760
			} else {
1761
				if ($this->_dnsVerboseLog) {
1762
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from local system.'), $this->_dnsService, $this->_FQDN, $ip_address));
1763
				}
1764
			}
1765
			$this->_dnsIP = $ip_address;
1766

    
1767
			return $ip_address;
1768
		}
1769

    
1770
	}
1771

    
1772
?>
(16-16/65)