Project

General

Profile

Download (74.6 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
	 *    - Hover (www.hover.com)
96
	 * +----------------------------------------------------+
97
	 *  Requirements:
98
	 *    - PHP version 4.0.2 or higher with the CURL Library and the PCRE Library
99
	 * +----------------------------------------------------+
100
	 *  Public Functions
101
	 *    - updatedns()
102
	 *
103
	 *  Private Functions
104
	 *    - _update()
105
	 *    - _checkStatus()
106
	 *    - _error()
107
	 *    - _detectChange()
108
	 *    - _debug()
109
	 *    - _checkIP()
110
	 * +----------------------------------------------------+
111
	 *  DynDNS Dynamic  - Last Tested: 12 July 2005
112
	 *  DynDNS Static   - Last Tested: NEVER
113
	 *  DynDNS Custom   - Last Tested: NEVER
114
	 *  No-IP           - Last Tested: 20 July 2008
115
	 *  HN.org          - Last Tested: 12 July 2005
116
	 *  EasyDNS         - Last Tested: 20 July 2008
117
	 *  DHS             - Last Tested: 12 July 2005
118
	 *  ZoneEdit        - Last Tested: NEVER
119
	 *  Dyns            - Last Tested: NEVER
120
	 *  ODS             - Last Tested: 02 August 2005
121
	 *  FreeDNS         - Last Tested: 01 May 2016
122
	 *  FreeDNS IPv6    - Last Tested: 01 May 2016
123
	 *  Loopia          - Last Tested: NEVER
124
	 *  StaticCling     - Last Tested: 27 April 2006
125
	 *  DNSexit         - Last Tested: 20 July 2008
126
	 *  OpenDNS         - Last Tested: 4 August 2008
127
	 *  Namecheap       - Last Tested: 31 August 2010
128
	 *  HE.net          - Last Tested: 7 July 2013
129
	 *  HE.net IPv6     - Last Tested: 7 July 2013
130
	 *  HE.net Tunnel   - Last Tested: 28 June 2011
131
	 *  SelfHost        - Last Tested: 26 December 2011
132
	 *  Amazon Route 53 - Last Tested: 04 February 2017
133
	 *  DNS-O-Matic     - Last Tested: 9 September 2010
134
	 *  CloudFlare      - Last Tested: 05 September 2016
135
	 *  CloudFlare IPv6 - Last Tested: 17 July 2016
136
	 *  Eurodns         - Last Tested: 27 June 2013
137
	 *  GratisDNS       - Last Tested: 15 August 2012
138
	 *  OVH DynHOST     - Last Tested: NEVER
139
	 *  City Network    - Last Tested: 13 November 2013
140
	 *  GleSYS          - Last Tested: 3 February 2015
141
	 *  DNSimple        - Last Tested: 09 February 2015
142
	 *  Google Domains  - Last Tested: 27 April 2015
143
	 *  DNS Made Easy   - Last Tested: 27 April 2015
144
	 *  SPDYN           - Last Tested: 02 July 2016
145
	 *  SPDYN IPv6      - Last Tested: 02 July 2016
146
	 *  All-Inkl        - Last Tested: 12 November 2016
147
	 *  DuiaDNS         - Last Tested: 25 November 2016
148
	 *  DuiaDNS IPv6    - Last Tested: 25 November 2016
149
	 *  Hover           - Last Tested: 15 February 2017
150
	 * +====================================================+
151
	 *
152
	 * @author 	E.Kristensen
153
	 * @link    	http://www.idylldesigns.com/projects/phpdns/
154
	 * @version 	0.8
155
	 * @updated	13 October 05 at 21:02:42 GMT
156
	 *
157
	 * DNSexit/OpenDNS support and multiwan extension for pfSense by Ermal Luçi
158
	 * Custom DNS support by Matt Corallo
159
	 *
160
	 */
161

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

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

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

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

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

    
231
			$dyndnslck = lock("DDNS".$dnsID, LOCK_EX);
232

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

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

    
303
			// Ensure that we were able to lookup the IP
304
			if (!is_ipaddr($this->_dnsIP)) {
305
				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));
306
				unlock($dyndnslck);
307
				return;
308
			}
309

    
310
			$this->_debugID = rand(1000000, 9999999);
311

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

    
374
			unlock($dyndnslck);
375
		}
376

    
377
		/*
378
		 * Private Function (added 12 July 05) [beta]
379
		 *   Send Update To Selected Service.
380
		 */
381
		function _update() {
382

    
383
			if ($this->_dnsVerboseLog) {
384
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _update() starting.'), $this->_dnsService, $this->_FQDN));
385
			}
386

    
387
			if (strstr($this->_dnsRequestIf, "_vip")) {
388
				$parentif = get_configured_vip_interface($this->_dnsRequestIf);
389
				$realparentif = convert_friendly_interface_to_real_interface_name($parentif);
390
			} else {
391
				$realparentif = $this->_dnsRequestIf;
392
			}
393

    
394
			$ch = curl_init();
395

    
396
			if ($this->_useIPv6 == false) {
397
				curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
398
			}
399

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

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

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

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

    
735
					curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
736
					curl_setopt($ch, CURLOPT_HTTPHEADER, array(
737
						'X-Auth-Email: '.$this->_dnsUser.'',
738
						'X-Auth-Key: '.$this->_dnsPass.'',
739
						'Content-Type: application/json'
740
					));
741

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

    
866
					//step 1: login to API
867
					$post_data['username'] = $this->_dnsUser;
868
					$post_data['password'] = $this->_dnsPass;
869
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
870
					curl_setopt($ch, CURLOPT_URL, "https://www.hover.com/api/login");
871
					curl_setopt($ch, CURLOPT_HEADER, 1); //return the full headers to extract the cookies
872
					$output = curl_exec($ch);
873

    
874
					//extract the cookies
875
					preg_match_all("/^Set-cookie: (.*?);/ism", $output, $cookies);
876
					if( count($cookies[1]) > 0 ){
877
						$cookie_data = implode("; ",$cookies[1]);
878
					}
879

    
880
					//step 2: find the id of the A record
881
					$post_data = null;
882
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
883
					curl_setopt($ch, CURLOPT_COOKIE, $cookie_data);
884
					curl_setopt($ch, CURLOPT_HEADER, 0);
885
					curl_setopt($ch, CURLOPT_URL, "https://www.hover.com/api/dns");
886
					curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
887

    
888
					$output = curl_exec($ch);
889
					preg_match("/^{\"succeeded\":true.*?domain_name\":\"{$this->_dnsDomain}.*?entries.*?{\"id\":\"([^\"]*?)\",\"name\":\"{$this->_dnsHost}\".*?\$/", $output, $hostID);
890
					$hostID = $hostID[1];
891
					preg_match("/^{\"succeeded\":true.*?domain_name\":\"{$this->_dnsDomain}.*?entries.*?{[^\}]*?\"name\":\"{$this->_dnsHost}\".*?content\":\"([^\"]*?)\".*?\$/", $output, $hostIP);
892
					$hostIP = $hostIP[1];
893

    
894
					//step 3: update the IP
895
					if ($hostID) {
896
						curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
897
						curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
898
						curl_setopt($ch, CURLOPT_COOKIE, $cookie_data);
899
						$post_data['content'] = $this->_dnsIP;
900
						curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
901
						curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
902
						curl_setopt($ch, CURLOPT_URL, "https://www.hover.com/api/dns/{$hostID}");
903
						log_error("HostID:{$hostID}, OldIP:{$hostIP}");
904
					}
905
					break;
906
				default:
907
					break;
908
			}
909
			if ($this->_dnsService != 'ods') {
910
				curl_setopt($ch, CURLOPT_HEADER, 1);
911
				$response = curl_exec($ch);
912
				$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
913
				$header = substr($response, 0, $header_size);
914
				$data = substr($response, $header_size);
915
				$this->_checkStatus($ch, $data, $header);
916
				@curl_close($ch);
917
			}
918
		}
919

    
920
		/*
921
		 * Private Function (added 12 July 2005) [beta]
922
		 *   Retrieve Update Status
923
		 */
924
		function _checkStatus($ch, $data, $header) {
925
			if ($this->_dnsVerboseLog) {
926
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkStatus() starting.'), $this->_dnsService, $this->_FQDN));
927
			}
928
			$successful_update = false;
929
			$success_str = "(" . gettext("Success") . ") ";
930
			$error_str = "(" . gettext("Error") . ") ";
931
			$status_intro = "phpDynDNS ({$this->_dnsHost}): ";
932

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

    
1582
			if ($successful_update == true) {
1583
				/* Write WAN IP to cache file */
1584
				$wan_ip = $this->_checkIP();
1585
				conf_mount_rw();
1586
				if ($this->_useIPv6 == false && $wan_ip > 0) {
1587
					$currentTime = time();
1588
					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));
1589
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile, $wan_ip));
1590
					@file_put_contents($this->_cacheFile, "{$wan_ip}|{$currentTime}");
1591
				} else {
1592
					@unlink($this->_cacheFile);
1593
				}
1594
				if ($this->_useIPv6 == true && $wan_ip > 0) {
1595
					$currentTime = time();
1596
					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));
1597
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile_v6, $wan_ip));
1598
					@file_put_contents($this->_cacheFile_v6, "{$wan_ip}|{$currentTime}");
1599
				} else {
1600
					@unlink($this->_cacheFile_v6);
1601
				}
1602
				conf_mount_ro();
1603
			}
1604
			$this->status = $status;
1605
			log_error($status);
1606
		}
1607

    
1608
		/*
1609
		 * Private Function (added 12 July 05) [beta]
1610
		 *   Return Error, Set Last Error, and Die.
1611
		 */
1612
		function _error($errorNumber = '1') {
1613
			$err_str = 'phpDynDNS: (' . gettext('ERROR!') . ') ';
1614
			$err_str_r53 = 'Route 53: (' . gettext('Error') . ') ';
1615
			switch ($errorNumber) {
1616
				case 0:
1617
					break;
1618
				case 2:
1619
					$error = $err_str . gettext('No Dynamic DNS Service provider was selected.');
1620
					break;
1621
				case 3:
1622
					$error = $err_str . gettext('No Username Provided.');
1623
					break;
1624
				case 4:
1625
					$error = $err_str . gettext('No Password Provided.');
1626
					break;
1627
				case 5:
1628
					$error = $err_str . gettext('No Hostname Provided.');
1629
					break;
1630
				case 6:
1631
					$error = $err_str . gettext('The Dynamic DNS Service provided is not yet supported.');
1632
					break;
1633
				case 7:
1634
					$error = $err_str . gettext('No Update URL Provided.');
1635
					break;
1636
				case 8:
1637
					$status = $err_str_r53 . gettext("Invalid ZoneID");
1638
					break;
1639
				case 9:
1640
					$status = $err_str_r53 . gettext("Invalid TTL");
1641
					break;
1642
				case 10:
1643
					$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);
1644
					break;
1645
				default:
1646
					$error = $err_str . gettext('Unknown Response.');
1647
					/* FIXME: $data isn't in scope here */
1648
					/* $this->_debug($data); */
1649
					break;
1650
			}
1651
			$this->lastError = $error;
1652
			log_error($error);
1653
		}
1654

    
1655
		/*
1656
		 * Private Function (added 12 July 05) [beta]
1657
		 *   - Detect whether or not IP needs to be updated.
1658
		 *      | Written Specifically for pfSense (https://www.pfsense.org) may
1659
		 *      | work with other systems. pfSense base is FreeBSD.
1660
		 */
1661
		function _detectChange() {
1662
			global $debug;
1663

    
1664
			if ($debug) {
1665
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _detectChange() starting.'), $this->_dnsService, $this->_FQDN));
1666
			}
1667

    
1668
			$currentTime = time();
1669

    
1670
			$wan_ip = $this->_checkIP();
1671
			if ($wan_ip == 0) {
1672
				log_error(sprintf(gettext("Dynamic Dns (%s): Current WAN IP could not be determined, skipping update process."), $this->_FQDN));
1673
				return false;
1674
			}
1675
			$log_error = sprintf(gettext('Dynamic Dns (%1$s): Current WAN IP: %2$s'), $this->_FQDN, $wan_ip) . " ";
1676

    
1677
			if ($this->_useIPv6 == true) {
1678
				if (file_exists($this->_cacheFile_v6)) {
1679
					$contents = file_get_contents($this->_cacheFile_v6);
1680
					list($cacheIP, $cacheTime) = explode('|', $contents);
1681
					$this->_debug($cacheIP.'/'.$cacheTime);
1682
					$initial = false;
1683
					$log_error .= sprintf(gettext("Cached IPv6: %s"), $cacheIP);
1684
				} else {
1685
					conf_mount_rw();
1686
					$cacheIP = '::';
1687
					@file_put_contents($this->_cacheFile, "::|{$currentTime}");
1688
					conf_mount_ro();
1689
					$cacheTime = $currentTime;
1690
					$initial = true;
1691
					$log_error .= gettext("No Cached IPv6 found.");
1692
				}
1693
			} else {
1694
				if (file_exists($this->_cacheFile)) {
1695
					$contents = file_get_contents($this->_cacheFile);
1696
					list($cacheIP, $cacheTime) = explode('|', $contents);
1697
					$this->_debug($cacheIP.'/'.$cacheTime);
1698
					$initial = false;
1699
					$log_error .= sprintf(gettext("Cached IP: %s"), $cacheIP);
1700
				} else {
1701
					conf_mount_rw();
1702
					$cacheIP = '0.0.0.0';
1703
					@file_put_contents($this->_cacheFile, "0.0.0.0|{$currentTime}");
1704
					conf_mount_ro();
1705
					$cacheTime = $currentTime;
1706
					$initial = true;
1707
					$log_error .= gettext("No Cached IP found.");
1708
				}
1709
			}
1710
			if ($this->_dnsVerboseLog) {
1711
				log_error($log_error);
1712
			}
1713

    
1714
			// Convert seconds = days * hr/day * min/hr * sec/min
1715
			$maxCacheAgeSecs = $this->_dnsMaxCacheAgeDays * 24 * 60 * 60;
1716

    
1717
			$needs_updating = FALSE;
1718
			/* lets determine if the item needs updating */
1719
			if ($cacheIP != $wan_ip) {
1720
				$needs_updating = true;
1721
				$update_reason = gettext("Dynamic Dns: cacheIP != wan_ip. Updating.") . " ";
1722
				$update_reason .= sprintf(gettext('Cached IP: %1$s WAN IP: %2$s'), $cacheIP, $wan_ip) . " ";
1723
			}
1724
			if (($currentTime - $cacheTime) > $maxCacheAgeSecs) {
1725
				$needs_updating = true;
1726
				$this->_forceUpdateNeeded = true;
1727
				$update_reason = sprintf(gettext("Dynamic Dns: More than %s days. Updating."), $this->_dnsMaxCacheAgeDays);
1728
				$update_reason .= " {$currentTime} - {$cacheTime} > {$maxCacheAgeSecs} ";
1729
			}
1730
			if ($initial == true) {
1731
				$needs_updating = true;
1732
				$update_reason .= gettext("Initial update.");
1733
			}
1734

    
1735
			/*   finally if we need updating then store the
1736
			 *   new cache value and return true
1737
			 */
1738
			if ($needs_updating == true) {
1739
				if ($this->_dnsVerboseLog) {
1740
					log_error("DynDns ({$this->_FQDN}): {$update_reason}");
1741
				}
1742
				return true;
1743
			}
1744

    
1745
			return false;
1746
		}
1747

    
1748
		/*
1749
		 * Private Function (added 16 July 05) [beta]
1750
		 *   - Writes debug information to a file.
1751
		 *   - This function is only called when a unknown response
1752
		 *   - status is returned from a DynDNS service provider.
1753
		 */
1754
		function _debug($data) {
1755
			global $g;
1756

    
1757
			if (!$g['debug']) {
1758
				return;
1759
			}
1760
			$string = date('m-d-y h:i:s').' - ('.$this->_debugID.') - ['.$this->_dnsService.'] - '.$data."\n";
1761
			conf_mount_rw();
1762
			$file = fopen($this->_debugFile, 'a');
1763
			fwrite($file, $string);
1764
			fclose($file);
1765
			conf_mount_ro();
1766
		}
1767
		function _checkIP() {
1768
			global $debug;
1769

    
1770
			if ($debug) {
1771
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkIP() starting.'), $this->_dnsService, $this->_FQDN));
1772
			}
1773

    
1774
			if ($this->_useIPv6 == true) {
1775
				$ip_address = get_interface_ipv6($this->_if);
1776
				if (!is_ipaddrv6($ip_address)) {
1777
					return 0;
1778
				}
1779
			} else {
1780
				$ip_address = get_interface_ip($this->_if);
1781
				if (!is_ipaddr($ip_address)) {
1782
					return 0;
1783
				}
1784
			}
1785
			if ($this->_useIPv6 == false && is_private_ip($ip_address)) {
1786
				$hosttocheck = "checkip.dyndns.org";
1787
				$try = 0;
1788
				while ($try < 3) {
1789
					$checkip = gethostbyname($hosttocheck);
1790
					if (is_ipaddr($checkip)) {
1791
						break;
1792
					}
1793
					$try++;
1794
				}
1795
				if ($try >= 3) {
1796
					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));
1797
					return 0;
1798
				}
1799
				$ip_ch = curl_init("http://{$checkip}");
1800
				curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1801
				curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1802
				curl_setopt($ip_ch, CURLOPT_INTERFACE, 'host!' . $ip_address);
1803
				curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1804
				curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1805
				if ($this->_useIPv6 == false) {
1806
					curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1807
				}
1808
				$ip_result_page = curl_exec($ip_ch);
1809
				curl_close($ip_ch);
1810
				$ip_result_decoded = urldecode($ip_result_page);
1811
				preg_match('/Current IP Address: (.*)<\/body>/', $ip_result_decoded, $matches);
1812
				$ip_address = trim($matches[1]);
1813
				if (is_ipaddr($ip_address)) {
1814
					if ($this->_dnsVerboseLog) {
1815
						log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from %4$s'), $this->_dnsService, $this->_FQDN, $ip_address, $hosttocheck));
1816
					}
1817
				} else {
1818
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): IP address could not be extracted from %3$s'), $this->_dnsService, $this->_FQDN, $hosttocheck));
1819
					return 0;
1820
				}
1821
			} else {
1822
				if ($this->_dnsVerboseLog) {
1823
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from local system.'), $this->_dnsService, $this->_FQDN, $ip_address));
1824
				}
1825
			}
1826
			$this->_dnsIP = $ip_address;
1827

    
1828
			return $ip_address;
1829
		}
1830

    
1831
	}
1832

    
1833
?>
(18-18/67)