Project

General

Profile

Download (68.5 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 Electric Sheep Fencing, LLC
7
 * All rights reserved.
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

    
22
	/*
23
	 * PHP.updateDNS (pfSense version)
24
	 *
25
	 * +====================================================+
26
	 *  Services Supported:
27
	 *    - DynDns (dyndns.org) [dynamic, static, custom]
28
	 *    - No-IP (no-ip.com)
29
	 *    - EasyDNS (easydns.com)
30
	 *    - DHS (www.dhs.org)
31
	 *    - HN (hn.org) -- incomplete checking!
32
	 *    - DynS (dyns.org)
33
	 *    - ZoneEdit (zoneedit.com)
34
	 *    - FreeDNS (freedns.afraid.org)
35
	 *    - FreeDNS IPv6 (freedns.afraid.org)
36
	 *    - Loopia (loopia.se)
37
	 *    - StaticCling (staticcling.org)
38
	 *    - DNSexit (dnsexit.com)
39
	 *    - OpenDNS (opendns.com)
40
	 *    - Namecheap (namecheap.com)
41
	 *    - HE.net (dns.he.net)
42
	 *    - HE.net IPv6 (dns.he.net)
43
	 *    - HE.net Tunnelbroker IP update (ipv4.tunnelbroker.net)
44
	 *    - SelfHost (selfhost.de)
45
	 *    - Amazon Route 53 (aws.amazon.com)
46
	 *    - DNS-O-Matic (dnsomatic.com)
47
	 *    - Custom DDNS (any URL)
48
	 *    - Custom DDNS IPv6 (any URL)
49
	 *    - CloudFlare (www.cloudflare.com)
50
	 *    - CloudFlare IPv6 (www.cloudflare.com)
51
	 *    - Eurodns (eurodns.com)
52
	 *    - GratisDNS (gratisdns.dk)
53
	 *    - City Network (citynetwork.se)
54
	 *    - GleSYS (glesys.com)
55
	 *    - DNSimple (dnsimple.com)
56
	 *    - Google Domains (domains.google.com)
57
	 *    - DNS Made Easy (www.dnsmadeeasy.com)
58
	 *    - SPDYN (spdyn.de)
59
	 *    - SPDYN IPv6 (spdyn.de)
60
	 * +----------------------------------------------------+
61
	 *  Requirements:
62
	 *    - PHP version 4.0.2 or higher with the CURL Library and the PCRE Library
63
	 * +----------------------------------------------------+
64
	 *  Public Functions
65
	 *    - updatedns()
66
	 *
67
	 *  Private Functions
68
	 *    - _update()
69
	 *    - _checkStatus()
70
	 *    - _error()
71
	 *    - _detectChange()
72
	 *    - _debug()
73
	 *    - _checkIP()
74
	 * +----------------------------------------------------+
75
	 *  DynDNS Dynamic  - Last Tested: 12 July 2005
76
	 *  DynDNS Static   - Last Tested: NEVER
77
	 *  DynDNS Custom   - Last Tested: NEVER
78
	 *  No-IP           - Last Tested: 20 July 2008
79
	 *  HN.org          - Last Tested: 12 July 2005
80
	 *  EasyDNS         - Last Tested: 20 July 2008
81
	 *  DHS             - Last Tested: 12 July 2005
82
	 *  ZoneEdit        - Last Tested: NEVER
83
	 *  Dyns            - Last Tested: NEVER
84
	 *  ODS             - Last Tested: 02 August 2005
85
	 *  FreeDNS         - Last Tested: 01 May 2016
86
	 *  FreeDNS IPv6    - Last Tested: 01 May 2016
87
	 *  Loopia          - Last Tested: NEVER
88
	 *  StaticCling     - Last Tested: 27 April 2006
89
	 *  DNSexit         - Last Tested: 20 July 2008
90
	 *  OpenDNS         - Last Tested: 4 August 2008
91
	 *  Namecheap       - Last Tested: 31 August 2010
92
	 *  HE.net          - Last Tested: 7 July 2013
93
	 *  HE.net IPv6     - Last Tested: 7 July 2013
94
	 *  HE.net Tunnel   - Last Tested: 28 June 2011
95
	 *  SelfHost        - Last Tested: 26 December 2011
96
	 *  Amazon Route 53 - Last tested: 01 April 2012
97
	 *  DNS-O-Matic     - Last Tested: 9 September 2010
98
	 *  CloudFlare      - Last Tested: 05 September 2016
99
	 *  CloudFlare IPv6 - Last Tested: 17 July 2016
100
	 *  Eurodns         - Last Tested: 27 June 2013
101
	 *  GratisDNS       - Last Tested: 15 August 2012
102
	 *  OVH DynHOST     - Last Tested: NEVER
103
	 *  City Network    - Last Tested: 13 November 2013
104
	 *  GleSYS          - Last Tested: 3 February 2015
105
	 *  DNSimple        - Last Tested: 09 February 2015
106
	 *  Google Domains  - Last Tested: 27 April 2015
107
	 *  DNS Made Easy   - Last Tested: 27 April 2015
108
	 *  SPDYN           - Last Tested: 02 July 2016
109
	 *  SPDYN IPv6      - Last Tested: 02 July 2016
110
	 * +====================================================+
111
	 *
112
	 * @author 	E.Kristensen
113
	 * @link    	http://www.idylldesigns.com/projects/phpdns/
114
	 * @version 	0.8
115
	 * @updated	13 October 05 at 21:02:42 GMT
116
	 *
117
	 * DNSexit/OpenDNS support and multiwan extension for pfSense by Ermal Luçi
118
	 * Custom DNS support by Matt Corallo
119
	 *
120
	 */
121

    
122
	class updatedns {
123
		var $_cacheFile;
124
		var $_cacheFile_v6;
125
		var $_debugFile;
126
		var $_UserAgent = 'phpDynDNS/0.7';
127
		var $_errorVerbosity = 0;
128
		var $_dnsService;
129
		var $_dnsUser;
130
		var $_dnsPass;
131
		var $_dnsHost;
132
		var $_dnsDomain;
133
		var $_FQDN;
134
		var $_dnsIP;
135
		var $_dnsWildcard;
136
		var $_dnsProxied;
137
		var $_dnsMX;
138
		var $_dnsBackMX;
139
		var $_dnsServer;
140
		var $_dnsPort;
141
		var $_dnsUpdateURL;
142
		var $_dnsZoneID;
143
		var $_dnsTTL;
144
		var $status;
145
		var $_debugID;
146
		var $_if;
147
		var $_dnsResultMatch;
148
		var $_dnsRequestIf;
149
		var $_dnsRequestIfIP;
150
		var $_dnsVerboseLog;
151
		var $_curlIpresolveV4;
152
		var $_curlSslVerifypeer;
153
		var $_dnsMaxCacheAgeDays;
154
		var $_dnsDummyUpdateDone;
155
		var $_forceUpdateNeeded;
156
		var $_useIPv6;
157

    
158
		/*
159
		 * Public Constructor Function (added 12 July 05) [beta]
160
		 *   - Gets the dice rolling for the update.
161
		 *   - $dnsResultMatch should only be used with $dnsService = 'custom'
162
		 *   -  $dnsResultMatch is parsed for '%IP%', which is the IP the provider was updated to,
163
		 *   -  it is otherwise expected to be exactly identical to what is returned by the Provider.
164
		 *   - $dnsUser, and $dnsPass indicate HTTP Auth for custom DNS, if they are needed in the URL (GET Variables), include them in $dnsUpdateURL.
165
		 *   - $For custom requests, $dnsUpdateURL is parsed for '%IP%', which is replaced with the new IP.
166
		 */
167
		function updatedns ($dnsService = '', $dnsHost = '', $dnsDomain = '', $dnsUser = '', $dnsPass = '',
168
					$dnsWildcard = 'OFF', $dnsProxied = false, $dnsMX = '', $dnsIf = '', $dnsBackMX = '',
169
					$dnsServer = '', $dnsPort = '', $dnsUpdateURL = '', $forceUpdate = false,
170
					$dnsZoneID ='', $dnsTTL='', $dnsResultMatch = '', $dnsRequestIf = '',
171
					$dnsID = '', $dnsVerboseLog = false, $curlIpresolveV4 = false, $curlSslVerifypeer = true) {
172

    
173
			global $config, $g;
174

    
175
			if ($dnsService == "namecheap") {
176
				$this->_FQDN = $dnsHost . "." . $dnsDomain;
177
			} else {
178
				$this->_FQDN = $dnsHost;
179
			}
180

    
181
			$this->_cacheFile = "{$g['conf_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}.cache";
182
			$this->_cacheFile_v6 = "{$g['conf_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}_v6.cache";
183
			$this->_debugFile = "{$g['varetc_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($this->_FQDN) . "{$dnsID}.debug";
184

    
185
			$this->_curlIpresolveV4 = $curlIpresolveV4;
186
			$this->_curlSslVerifypeer = $curlSslVerifypeer;
187
			$this->_dnsVerboseLog = $dnsVerboseLog;
188
			if ($this->_dnsVerboseLog) {
189
				log_error(gettext("Dynamic DNS: updatedns() starting"));
190
			}
191

    
192
			$dyndnslck = lock("DDNS".$dnsID, LOCK_EX);
193

    
194
			if (!$dnsService) $this->_error(2);
195
			switch ($dnsService) {
196
			case 'freedns':
197
			case 'freedns-v6':
198
				if (!$dnsHost) $this->_error(5);
199
				break;
200
			case 'namecheap':
201
				if (!$dnsPass) $this->_error(4);
202
				if (!$dnsHost) $this->_error(5);
203
				if (!$dnsDomain) $this->_error(5);
204
				break;
205
			case 'route53':
206
				if (!$dnsZoneID) $this->_error(8);
207
				if (!$dnsTTL) $this->_error(9);
208
				break;
209
			case 'custom':
210
				if (!$dnsUpdateURL) $this->_error(7);
211
				break;
212
			default:
213
				if (!$dnsUser) $this->_error(3);
214
				if (!$dnsPass) $this->_error(4);
215
				if (!$dnsHost) $this->_error(5);
216
			}
217

    
218
			switch ($dnsService) {
219
				case 'he-net-v6':
220
				case 'custom-v6':
221
				case 'spdyn-v6':
222
				case 'freedns-v6':
223
				case 'cloudflare-v6':
224
					$this->_useIPv6 = true;
225
					break;
226
				default:
227
					$this->_useIPv6 = false;
228
			}
229
			$this->_dnsService = strtolower($dnsService);
230
			$this->_dnsUser = $dnsUser;
231
			$this->_dnsPass = $dnsPass;
232
			$this->_dnsHost = $dnsHost;
233
			$this->_dnsDomain = $dnsDomain;
234
			$this->_dnsServer = $dnsServer;
235
			$this->_dnsPort = $dnsPort;
236
			$this->_dnsWildcard = $dnsWildcard;
237
			$this->_dnsProxied = $dnsProxied;
238
			$this->_dnsMX = $dnsMX;
239
			$this->_dnsZoneID = $dnsZoneID;
240
			$this->_dnsTTL = $dnsTTL;
241
			$this->_if = get_failover_interface($dnsIf);
242
			$this->_checkIP();
243
			$this->_dnsUpdateURL = $dnsUpdateURL;
244
			$this->_dnsResultMatch = $dnsResultMatch;
245
			$this->_dnsRequestIf = get_failover_interface($dnsRequestIf);
246
			if ($this->_dnsVerboseLog) {
247
				log_error(sprintf(gettext('Dynamic DNS (%1$s): running get_failover_interface for %2$s. found %3$s'), $this->_FQDN, $dnsRequestIf, $this->_dnsRequestIf));
248
			}
249
			$this->_dnsRequestIfIP = get_interface_ip($dnsRequestIf);
250
			$this->_dnsMaxCacheAgeDays = 25;
251
			$this->_dnsDummyUpdateDone = false;
252
			$this->_forceUpdateNeeded = $forceUpdate;
253

    
254
			// Ensure that we were able to lookup the IP
255
			if (!is_ipaddr($this->_dnsIP)) {
256
				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));
257
				unlock($dyndnslck);
258
				return;
259
			}
260

    
261
			$this->_debugID = rand(1000000, 9999999);
262

    
263
			if ($forceUpdate == false && $this->_detectChange() == false) {
264
				$this->_error(10);
265
			} else {
266
				switch ($this->_dnsService) {
267
					case 'glesys':
268
					case 'dnsomatic':
269
					case 'dyndns':
270
					case 'dyndns-static':
271
					case 'dyndns-custom':
272
					case 'dhs':
273
					case 'noip':
274
					case 'noip-free':
275
					case 'easydns':
276
					case 'hn':
277
					case 'zoneedit':
278
					case 'dyns':
279
					case 'ods':
280
					case 'freedns':
281
					case 'freedns-v6':
282
					case 'loopia':
283
					case 'staticcling':
284
					case 'dnsexit':
285
					case 'custom':
286
					case 'custom-v6':
287
					case 'opendns':
288
					case 'namecheap':
289
					case 'he-net':
290
					case 'he-net-v6':
291
					case 'selfhost':
292
					case 'he-net-tunnelbroker':
293
					case 'route53':
294
					case 'cloudflare':
295
					case 'cloudflare-v6':
296
					case 'eurodns':
297
					case 'gratisdns':
298
					case 'ovh-dynhost':
299
					case 'citynetwork':
300
					case 'dnsimple':
301
					case 'googledomains':
302
					case 'dnsmadeeasy':
303
					case 'spdyn':
304
					case 'spdyn-v6':
305
						$this->_update();
306
						if ($this->_dnsDummyUpdateDone == true) {
307
							// If a dummy update was needed, then sleep a while and do the update again to put the proper address back.
308
							// Some providers (e.g. No-IP free accounts) need to have at least 1 address change every month.
309
							// If the address has not changed recently, or the user did "Force Update", then the code does
310
							// a dummy address change for providers like this.
311
							sleep(10);
312
							$this->_update();
313
						}
314
						break;
315
					default:
316
						$this->_error(6);
317
						break;
318
				}
319
			}
320

    
321
			unlock($dyndnslck);
322
		}
323

    
324
		/*
325
		 * Private Function (added 12 July 05) [beta]
326
		 *   Send Update To Selected Service.
327
		 */
328
		function _update() {
329

    
330
			if ($this->_dnsVerboseLog) {
331
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _update() starting.'), $this->_dnsService, $this->_FQDN));
332
			}
333

    
334
			if (strstr($this->_dnsRequestIf, "_vip")) {
335
				$parentif = get_configured_vip_interface($this->_dnsRequestIf);
336
				$realparentif = convert_friendly_interface_to_real_interface_name($parentif);
337
			} else {
338
				$realparentif = $this->_dnsRequestIf;
339
			}
340

    
341
			$ch = curl_init();
342

    
343
			if ($this->_useIPv6 == false) {
344
				curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
345
			}
346

    
347
			if ($this->_dnsService != 'ods' and $this->_dnsService != 'route53 ') {
348
				curl_setopt($ch, CURLOPT_HEADER, 0);
349
				curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
350
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
351
				curl_setopt($ch, CURLOPT_INTERFACE, 'if!' . $realparentif);
352
				curl_setopt($ch, CURLOPT_TIMEOUT, 120); // Completely empirical
353
			}
354

    
355
			switch ($this->_dnsService) {
356
				case 'glesys':
357
					$needsIP = TRUE;
358
					$server = 'https://api.glesys.com/domain/updaterecord/format/json';
359
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
360
					$post_data['recordid'] = $this->_FQDN;
361
					$post_data['data'] = $this->_dnsIP;
362
					curl_setopt($ch, CURLOPT_URL, $server);
363
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
364
					break;
365
				case 'dyndns':
366
				case 'dyndns-static':
367
				case 'dyndns-custom':
368
					$needsIP = FALSE;
369
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
370
						$this->_dnsWildcard = "ON";
371
					}
372
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
373
					$server = "https://members.dyndns.org/nic/update";
374
					$port = "";
375
					if ($this->_dnsServer) {
376
						$server = $this->_dnsServer;
377
					}
378
					if ($this->_dnsPort) {
379
						$port = ":" . $this->_dnsPort;
380
					}
381
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
382
					break;
383
				case 'dhs':
384
					// DHS is disabled in the GUI because the following doesn't work.
385
					$needsIP = TRUE;
386
					$post_data['hostscmd'] = 'edit';
387
					$post_data['hostscmdstage'] = '2';
388
					$post_data['type'] = '4';
389
					$post_data['updatetype'] = 'Online';
390
					$post_data['mx'] = $this->_dnsMX;
391
					$post_data['mx2'] = '';
392
					$post_data['txt'] = '';
393
					$post_data['offline_url'] = '';
394
					$post_data['cloak'] = 'Y';
395
					$post_data['cloak_title'] = '';
396
					$post_data['ip'] = $this->_dnsIP;
397
					$post_data['domain'] = 'dyn.dhs.org';
398
					$post_data['hostname'] = $this->_dnsHost;
399
					$post_data['submit'] = 'Update';
400
					$server = "https://members.dhs.org/nic/hosts";
401
					$port = "";
402
					if ($this->_dnsServer) {
403
						$server = $this->_dnsServer;
404
					}
405
					if ($this->_dnsPort) {
406
						$port = ":" . $this->_dnsPort;
407
					}
408
					curl_setopt($ch, CURLOPT_URL, $server . $port);
409
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
410
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
411
					break;
412
				case 'noip':
413
				case 'noip-free':
414
					$needsIP = TRUE;
415
					$server = "https://dynupdate.no-ip.com/ducupdate.php";
416
					$port = "";
417
					if ($this->_dnsServer) {
418
						$server = $this->_dnsServer;
419
					}
420
					if ($this->_dnsPort) {
421
						$port = ":" . $this->_dnsPort;
422
					}
423
					if (($this->_dnsService == "noip-free") &&
424
					    ($this->_forceUpdateNeeded == true) &&
425
					    ($this->_dnsDummyUpdateDone == false)) {
426
						// Update the IP to a dummy value to force No-IP free accounts to see a change.
427
						$iptoset = "192.168.1.1";
428
						$this->_dnsDummyUpdateDone = true;
429
						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));
430
					} else {
431
						$iptoset = $this->_dnsIP;
432
					}
433
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&pass=' . urlencode($this->_dnsPass) . '&h[]=' . $this->_dnsHost.'&ip=' . $iptoset);
434
					break;
435
				case 'easydns':
436
					$needsIP = TRUE;
437
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
438
					$server = "https://members.easydns.com/dyn/dyndns.php";
439
					$port = "";
440
					if ($this->_dnsServer) {
441
						$server = $this->_dnsServer;
442
					}
443
					if ($this->_dnsPort) {
444
						$port = ":" . $this->_dnsPort;
445
					}
446
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard=' . $this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=' . $this->_dnsBackMX);
447
					break;
448
				case 'hn':
449
					$needsIP = TRUE;
450
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
451
					$server = "http://dup.hn.org/vanity/update";
452
					$port = "";
453
					if ($this->_dnsServer) {
454
						$server = $this->_dnsServer;
455
					}
456
					if ($this->_dnsPort) {
457
						$port = ":" . $this->_dnsPort;
458
					}
459
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?ver=1&IP=' . $this->_dnsIP);
460
					break;
461
				case 'zoneedit':
462
					$needsIP = FALSE;
463
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
464

    
465
					$server = "https://dynamic.zoneedit.com/auth/dynamic.html";
466
					$port = "";
467
					if ($this->_dnsServer) {
468
						$server = $this->_dnsServer;
469
					}
470
					if ($this->_dnsPort) {
471
						$port = ":" . $this->_dnsPort;
472
					}
473
					curl_setopt($ch, CURLOPT_URL, "{$server}{$port}?host=" .$this->_dnsHost);
474
					break;
475
				case 'dyns':
476
					$needsIP = FALSE;
477
					$server = "http://www.dyns.net/postscript011.php";
478
					$port = "";
479
					if ($this->_dnsServer) {
480
						$server = $this->_dnsServer;
481
					}
482
					if ($this->_dnsPort) {
483
						$port = ":" . $this->_dnsPort;
484
					}
485
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&password=' . $this->_dnsPass . '&host=' . $this->_dnsHost);
486
					break;
487
				case 'ods':
488
					$needsIP = FALSE;
489
					$misc_errno = 0;
490
					$misc_error = "";
491
					$server = "ods.org";
492
					$port = "";
493
					if ($this->_dnsServer) {
494
						$server = $this->_dnsServer;
495
					}
496
					if ($this->_dnsPort) {
497
						$port = ":" . $this->_dnsPort;
498
					}
499
					$this->con['socket'] = fsockopen("{$server}{$port}", "7070", $misc_errno, $misc_error, 30);
500
					/* Check that we have connected */
501
					if (!$this->con['socket']) {
502
						print "error! could not connect.";
503
						break;
504
					}
505
					/* Here is the loop. Read the incoming data (from the socket connection) */
506
					while (!feof($this->con['socket'])) {
507
						$this->con['buffer']['all'] = trim(fgets($this->con['socket'], 4096));
508
						$code = substr($this->con['buffer']['all'], 0, 3);
509
						sleep(1);
510
						switch ($code) {
511
							case 100:
512
								fputs($this->con['socket'], "LOGIN ".$this->_dnsUser." ".$this->_dnsPass."\n");
513
								break;
514
							case 225:
515
								fputs($this->con['socket'], "DELRR ".$this->_dnsHost." A\n");
516
								break;
517
							case 901:
518
								fputs($this->con['socket'], "ADDRR ".$this->_dnsHost." A ".$this->_dnsIP."\n");
519
								break;
520
							case 795:
521
								fputs($this->con['socket'], "QUIT\n");
522
								break;
523
						}
524
					}
525
					$this->_checkStatus(0, $code);
526
					break;
527
				case 'freedns':
528
				case 'freedns-v6':
529
					$needIP = FALSE;
530
					curl_setopt($ch, CURLOPT_URL, 'https://freedns.afraid.org/dynamic/update.php?' . $this->_dnsPass);
531
					break;
532
				case 'dnsexit':
533
					$needsIP = TRUE;
534
					curl_setopt($ch, CURLOPT_URL, 'https://www.dnsexit.com/RemoteUpdate.sv?login='.$this->_dnsUser. '&password='.$this->_dnsPass.'&host='.$this->_dnsHost.'&myip='.$this->_dnsIP);
535
					break;
536
				case 'loopia':
537
					$needsIP = TRUE;
538
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
539
					curl_setopt($ch, CURLOPT_URL, 'https://dns.loopia.se/XDynDNSServer/XDynDNS.php?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP);
540
					break;
541
				case 'opendns':
542
					$needsIP = FALSE;
543
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
544
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
545
					$server = "https://updates.opendns.com/nic/update?hostname=". $this->_dnsHost;
546
					$port = "";
547
					if ($this->_dnsServer) {
548
						$server = $this->_dnsServer;
549
					}
550
					if ($this->_dnsPort) {
551
						$port = ":" . $this->_dnsPort;
552
					}
553
					curl_setopt($ch, CURLOPT_URL, $server .$port);
554
					break;
555

    
556
				case 'staticcling':
557
					$needsIP = FALSE;
558
					curl_setopt($ch, CURLOPT_URL, 'https://www.staticcling.org/update.html?login='.$this->_dnsUser.'&pass='.$this->_dnsPass);
559
					break;
560
				case 'dnsomatic':
561
					/* Example syntax
562
						https://username:password@updates.dnsomatic.com/nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
563
					*/
564
					$needsIP = FALSE;
565
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
566
						$this->_dnsWildcard = "ON";
567
					}
568
					/*
569
					Reference: https://www.dnsomatic.com/wiki/api
570
						DNS-O-Matic usernames are 3-25 characters.
571
						DNS-O-Matic passwords are 6-20 characters.
572
						All ASCII letters and numbers accepted.
573
						Dots, dashes, and underscores allowed, but not at the beginning or end of the string.
574
					Required: "rawurlencode" http://www.php.net/manual/en/function.rawurlencode.php
575
						Encodes the given string according to RFC 3986.
576
					*/
577
					$server = "https://" . rawurlencode($this->_dnsUser) . ":" . rawurlencode($this->_dnsPass) . "@updates.dnsomatic.com/nic/update?hostname=";
578
					if ($this->_dnsServer) {
579
						$server = $this->_dnsServer;
580
					}
581
					if ($this->_dnsPort) {
582
						$port = ":" . $this->_dnsPort;
583
					}
584
					curl_setopt($ch, CURLOPT_URL, $server . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NOCHG');
585
					break;
586
				case 'namecheap':
587
					/* Example:
588
						https://dynamicdns.park-your-domain.com/update?host=[host_name]&domain=[domain.com]&password=[domain_password]&ip=[your_ip]
589
					*/
590
					$needsIP = FALSE;
591
					$dnspass = trim($this->_dnsPass);
592
					$server = "https://dynamicdns.park-your-domain.com/update?host={$this->_dnsHost}&domain={$this->_dnsDomain}&password={$dnspass}&ip={$this->_dnsIP}";
593
					curl_setopt($ch, CURLOPT_URL, $server);
594
					break;
595
				case 'he-net':
596
				case 'he-net-v6':
597
					$needsIP = FALSE;
598
					$server = "https://dyn.dns.he.net/nic/update?";
599
					curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
600
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
601
					curl_setopt($ch, CURLOPT_URL, $server . 'hostname=' . $this->_dnsHost . '&password=' . $this->_dnsPass . '&myip=' . $this->_dnsIP);
602
					break;
603
				case 'he-net-tunnelbroker':
604
					$needsIP = FALSE;
605
					$server = "https://ipv4.tunnelbroker.net/ipv4_end.php?";
606
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
607
					curl_setopt($ch, CURLOPT_URL, $server . 'tid=' . $this->_dnsHost);
608
					break;
609
				case 'selfhost':
610
					$needsIP = FALSE;
611
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") {
612
						$this->_dnsWildcard = "ON";
613
					}
614
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
615
					$server = "https://carol.selfhost.de/nic/update";
616
					$port = "";
617
					if ($this->_dnsServer) {
618
						$server = $this->_dnsServer;
619
					}
620
					if ($this->_dnsPort) {
621
						$port = ":" . $this->_dnsPort;
622
					}
623
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
624
					break;
625
				case 'route53':
626

    
627
					/* Setting Variables */
628
					$hostname = "{$this->_dnsHost}.";
629
					$ZoneID = trim($this->_dnsZoneID);
630
					$AccessKeyId = $this->_dnsUser;
631
					$SecretAccessKey = $this->_dnsPass;
632
					$NewIP = $this->_dnsIP;
633
					$NewTTL = $this->_dnsTTL;
634

    
635
					/* Include Route 53 Library Class */
636
					require_once('/etc/inc/r53.class');
637

    
638
					/* Set Amazon AWS Credentials for this record */
639
					$r53 = new Route53($AccessKeyId, $SecretAccessKey);
640

    
641
					/* Function to find old values of records in Route 53 */
642
					if (!function_exists('Searchrecords')) {
643
						function SearchRecords($records, $name) {
644
							$result = array();
645
							foreach ($records as $record) {
646
								if (strtolower($record['Name']) == strtolower($name)) {
647
									$result [] = $record;
648
								}
649
							}
650
							return ($result) ? $result : false;
651
						}
652
					}
653

    
654
					$records = $r53->listResourceRecordSets("/hostedzone/$ZoneID");
655

    
656
					/* Get IP for your hostname in Route 53 */
657
					if (false !== ($a_result = SearchRecords($records['ResourceRecordSets'], "$hostname"))) {
658
						$OldTTL = $a_result[0][TTL];
659
						$OldIP = $a_result[0][ResourceRecords][0];
660
					} else {
661
						$OldIP = "";
662
					}
663

    
664
					/* Check if we need to update DNS Record */
665
					if ($OldIP !== $NewIP || $OldTTL !== $NewTTL) {
666
						if (!empty($OldIP)) {
667
							/* Your Hostname already exists, deleting and creating it again */
668
							$changes = array();
669
							$changes[] = $r53->prepareChange(DELETE, $hostname, A, $OldTTL, $OldIP);
670
							$changes[] = $r53->prepareChange(CREATE, $hostname, A, $NewTTL, $NewIP);
671
							$result = $r53->changeResourceRecordSets("/hostedzone/$ZoneID", $changes);
672
						} else {
673
							/* Your Hostname does not exist yet, creating it */
674
							$changes = $r53->prepareChange(CREATE, $hostname, A, $NewTTL, $NewIP);
675
							$result = $r53->changeResourceRecordSets("/hostedzone/$ZoneID", $changes);
676
						}
677
					}
678
					$this->_checkStatus(0, $result);
679
					break;
680
				case 'custom':
681
				case 'custom-v6':
682
					if (strstr($this->dnsUpdateURL, "%IP%")) {$needsIP = TRUE;} else {$needsIP = FALSE;}
683
					if ($this->_dnsUser != '') {
684
						if ($this->_curlIpresolveV4) {
685
							curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
686
						}
687
						if ($this->_curlSslVerifypeer) {
688
							curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
689
						} else {
690
							curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
691
						}
692
						curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
693
						curl_setopt($ch, CURLOPT_USERPWD, "{$this->_dnsUser}:{$this->_dnsPass}");
694
					}
695
					$server = str_replace("%IP%", $this->_dnsIP, $this->_dnsUpdateURL);
696
					if ($this->_dnsVerboseLog) {
697
						log_error(sprintf(gettext("Sending request to: %s"), $server));
698
					}
699
					curl_setopt($ch, CURLOPT_URL, $server);
700
					break;
701
				case 'cloudflare-v6':
702
				case 'cloudflare':
703
					$isv6 = ($this->_dnsService === 'cloudflare-v6');
704
					$recordType = $isv6 ? "AAAA" : "A";
705
					$needsIP = TRUE;
706
					$dnsServer ='api.cloudflare.com';
707
					$dnsHost = str_replace(' ', '', $this->_dnsHost);
708
					$host_names = explode(".", $dnsHost);
709
					$bottom_host_name = $host_names[count($host_names)-2] . "." . $host_names[count($host_names)-1];
710

    
711
					curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
712
					curl_setopt($ch, CURLOPT_HTTPHEADER, array(
713
						'X-Auth-Email: '.$this->_dnsUser.'',
714
						'X-Auth-Key: '.$this->_dnsPass.'',
715
						'Content-Type: application/json'
716
					));
717

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

    
849
		/*
850
		 * Private Function (added 12 July 2005) [beta]
851
		 *   Retrieve Update Status
852
		 */
853
		function _checkStatus($ch, $data) {
854
			if ($this->_dnsVerboseLog) {
855
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkStatus() starting.'), $this->_dnsService, $this->_FQDN));
856
			}
857
			$successful_update = false;
858
			$success_str = "(" . gettext("Success") . ") ";
859
			$error_str = "(" . gettext("Error") . ") ";
860
			$status_intro = "phpDynDNS ({$this->_dnsHost}): ";
861

    
862
			if ($this->_dnsService != 'ods' and $this->_dnsService != 'route53' && @curl_error($ch)) {
863
				$status = gettext("Curl error occurred:") . " " . curl_error($ch);
864
				log_error($status);
865
				$this->status = $status;
866
				return;
867
			}
868
			switch ($this->_dnsService) {
869
				case 'glesys':
870
					$status_intro = "GleSYS ({$this->_dnsHost}): ";
871
					if (preg_match('/Record updated/i', $data)) {
872
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
873
						$successful_update = true;
874
					} else {
875
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
876
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
877
						$this->_debug($data);
878
					}
879
					break;
880
				case 'dnsomatic':
881
					$status_intro = "DNS-O-Matic ({$this->_dnsHost}): ";
882
					if (preg_match('/badauth/i', $data)) {
883
						$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.");
884
					} else if (preg_match('/notfqdn /i', $data)) {
885
						$status = $status_intro . gettext("The hostname specified is not a fully-qualified domain name. If no hostnames included, notfqdn will be returned once.");
886
					} else if (preg_match('/nohost/i', $data)) {
887
						$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.");
888
					} else if (preg_match('/numhost/i', $data)) {
889
						$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.");
890
					} else if (preg_match('/abuse/i', $data)) {
891
						$status = $status_intro . gettext("The hostname is blocked for update abuse.");
892
					} else if (preg_match('/good/i', $data)) {
893
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
894
						$successful_update = true;
895
					} else if (preg_match('/dnserr/i', $data)) {
896
						$status = $status_intro . gettext("DNS error encountered. Stop updating for 30 minutes.");
897
					} else {
898
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
899
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
900
						$this->_debug($data);
901
					}
902
					break;
903
				case 'citynetwork':
904
					if (preg_match('/notfqdn/i', $data)) {
905
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
906
					} else if (preg_match('/nohost/i', $data)) {
907
						$status = $status_intro . $error_str . gettext("No such host");
908
					} else if (preg_match('/nochg/i', $data)) {
909
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
910
						$successful_update = true;
911
					} else if (preg_match('/good/i', $data)) {
912
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
913
						$successful_update = true;
914
					} else if (preg_match('/badauth/i', $data)) {
915
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
916
					} else {
917
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
918
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
919
						$this->_debug($data);
920
					}
921
					break;
922
				case 'ovh-dynhost':
923
				case 'dyndns':
924
					if (preg_match('/notfqdn/i', $data)) {
925
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
926
					} else if (preg_match('/nochg/i', $data)) {
927
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
928
						$successful_update = true;
929
					} else if (preg_match('/good/i', $data)) {
930
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
931
						$successful_update = true;
932
					} else if (preg_match('/noauth/i', $data)) {
933
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
934
					} else {
935
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
936
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
937
						$this->_debug($data);
938
					}
939
					break;
940
				case 'dyndns-static':
941
					if (preg_match('/notfqdn/i', $data)) {
942
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
943
					} else if (preg_match('/nochg/i', $data)) {
944
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
945
						$successful_update = true;
946
					} else if (preg_match('/good/i', $data)) {
947
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
948
						$successful_update = true;
949
					} else if (preg_match('/noauth/i', $data)) {
950
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
951
					} else {
952
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
953
						log_error($status_intro . gettext("PAYLOAD:") . " {$data}");
954
						$this->_debug($data);
955
					}
956
					break;
957
				case 'dyndns-custom':
958
					if (preg_match('/notfqdn/i', $data)) {
959
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
960
					} else if (preg_match('/nochg/i', $data)) {
961
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
962
						$successful_update = true;
963
					} else if (preg_match('/good/i', $data)) {
964
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
965
						$successful_update = true;
966
					} else if (preg_match('/noauth/i', $data)) {
967
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
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 'dhs':
975
					break;
976
				case 'noip':
977
				case 'noip-free':
978
					list($ip, $code) = explode(":", $data);
979
					switch ($code) {
980
						case 0:
981
							$status = $status_intro . $success_str . gettext("IP address is current, no update performed.");
982
							$successful_update = true;
983
							break;
984
						case 1:
985
							$status = $status_intro . $success_str . gettext("DNS hostname update successful.");
986
							$successful_update = true;
987
							break;
988
						case 2:
989
							$status = $status_intro . $error_str . gettext("Hostname supplied does not exist.");
990
							break;
991
						case 3:
992
							$status = $status_intro . $error_str . gettext("Invalid Username.");
993
							break;
994
						case 4:
995
							$status = $status_intro . $error_str . gettext("Invalid Password.");
996
							break;
997
						case 5:
998
							$status = $status_intro . $error_str . gettext("Too many updates sent.");
999
							break;
1000
						case 6:
1001
							$status = $status_intro . $error_str . gettext("Account disabled due to violation of No-IP terms of service.");
1002
							break;
1003
						case 7:
1004
							$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.");
1005
							break;
1006
						case 8:
1007
							$status = $status_intro . $error_str . gettext("Disabled / Locked Hostname.");
1008
							break;
1009
						case 9:
1010
							$status = $status_intro . $error_str . gettext("Host updated is configured as a web redirect and no update was performed.");
1011
							break;
1012
						case 10:
1013
							$status = $status_intro . $error_str . gettext("Group supplied does not exist.");
1014
							break;
1015
						case 11:
1016
							$status = $status_intro . $success_str . gettext("DNS group update is successful.");
1017
							$successful_update = true;
1018
							break;
1019
						case 12:
1020
							$status = $status_intro . $success_str . gettext("DNS group is current, no update performed.");
1021
							$successful_update = true;
1022
							break;
1023
						case 13:
1024
							$status = $status_intro . $error_str . gettext("Update client support not available for supplied hostname or group.");
1025
							break;
1026
						case 14:
1027
							$status = $status_intro . $error_str . gettext("Hostname supplied does not have offline settings configured.");
1028
							break;
1029
						case 99:
1030
							$status = $status_intro . $error_str . gettext("Client disabled. Client should exit and not perform any more updates without user intervention.");
1031
							break;
1032
						case 100:
1033
							$status = $status_intro . $error_str . gettext("Client disabled. Client should exit and not perform any more updates without user intervention.");
1034
							break;
1035
						default:
1036
							$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1037
							$this->_debug(gettext("Unknown Response:") . " " . $data);
1038
							break;
1039
					}
1040
					break;
1041
				case 'easydns':
1042
					if (preg_match('/NOACCESS/i', $data)) {
1043
						$status = $status_intro . $error_str . gettext("Authentication Failed: Username and/or Password was Incorrect.");
1044
					} else if (preg_match('/NOSERVICE/i', $data)) {
1045
						$status = $status_intro . $error_str . gettext("No Service: Dynamic DNS Service has been disabled for this domain.");
1046
					} else if (preg_match('/ILLEGAL INPUT/i', $data)) {
1047
						$status = $status_intro . $error_str . gettext("Illegal Input: Self-Explanatory");
1048
					} else if (preg_match('/TOOSOON/i', $data)) {
1049
						$status = $status_intro . $error_str . gettext("Too Soon: Not Enough Time Has Elapsed Since Last Update");
1050
					} else if (preg_match('/NOERROR/i', $data)) {
1051
						$status = $status_intro . $success_str . gettext("IP Updated Successfully!");
1052
						$successful_update = true;
1053
					} else {
1054
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1055
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1056
						$this->_debug($data);
1057
					}
1058
					break;
1059
				case 'hn':
1060
					/* FIXME: add checks */
1061
					break;
1062
				case 'zoneedit':
1063
					if (preg_match('/799/i', $data)) {
1064
						$status = $status_intro . "(" . gettext("Error 799") . ") " . gettext("Update Failed!");
1065
					} else if (preg_match('/700/i', $data)) {
1066
						$status = $status_intro . "(" . gettext("Error 700") . ") " . gettext("Update Failed!");
1067
					} else if (preg_match('/200/i', $data)) {
1068
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1069
						$successful_update = true;
1070
					} else if (preg_match('/201/i', $data)) {
1071
						$status = $status_intro . $success_str . gettext("IP Address 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 'dyns':
1080
					if (preg_match("/400/i", $data)) {
1081
						$status = $status_intro . $error_str . gettext("Bad Request - The URL was malformed. Required parameters were not provided.");
1082
					} else if (preg_match('/402/i', $data)) {
1083
						$status = $status_intro . $error_str . gettext("Update Too Soon - Attempted to update too quickly since last change.");
1084
					} else if (preg_match('/403/i', $data)) {
1085
						$status = $status_intro . $error_str . gettext("Database Error - There was a server-sided database error.");
1086
					} else if (preg_match('/405/i', $data)) {
1087
						$status = $status_intro . $error_str . sprintf(gettext("Hostname Error - The hostname (%s) doesn't belong to user (%s)."), $this->_dnsHost, $this->_dnsUser);
1088
					} else if (preg_match('/200/i', $data)) {
1089
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1090
						$successful_update = true;
1091
					} else {
1092
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1093
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1094
						$this->_debug($data);
1095
					}
1096
					break;
1097
				case 'ods':
1098
					if (preg_match("/299/i", $data)) {
1099
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1100
						$successful_update = true;
1101
					} else {
1102
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1103
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1104
						$this->_debug($data);
1105
					}
1106
					break;
1107
				case 'freedns':
1108
				case 'freedns-v6':
1109
					if (preg_match("/has not changed./i", $data)) {
1110
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1111
						$successful_update = true;
1112
					} else if (preg_match("/Updated/i", $data)) {
1113
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1114
						$successful_update = true;
1115
					} else {
1116
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1117
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1118
						$this->_debug($data);
1119
					}
1120
					break;
1121
				case 'dnsexit':
1122
					if (preg_match("/is the same/i", $data)) {
1123
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1124
						$successful_update = true;
1125
					} else if (preg_match("/Success/i", $data)) {
1126
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1127
						$successful_update = true;
1128
					} else {
1129
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1130
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1131
						$this->_debug($data);
1132
					}
1133
					break;
1134
				case 'loopia':
1135
					if (preg_match("/nochg/i", $data)) {
1136
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1137
						$successful_update = true;
1138
					} else if (preg_match("/good/i", $data)) {
1139
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!");
1140
						$successful_update = true;
1141
					} else if (preg_match('/badauth/i', $data)) {
1142
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1143
					} else {
1144
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1145
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1146
						$this->_debug($data);
1147
					}
1148
					break;
1149
				case 'opendns':
1150
					if (preg_match('/badauth/i', $data)) {
1151
						$status = $status_intro . $error_str . gettext("Not a valid username or password!");
1152
					} else if (preg_match('/nohost/i', $data)) {
1153
						$status = $status_intro . $error_str . gettext("Hostname specified does not exist.");
1154
						$successful_update = true;
1155
					} else if (preg_match('/good/i', $data)) {
1156
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1157
						$successful_update = true;
1158
					} else if (preg_match('/yours/i', $data)) {
1159
						$status = $status_intro . $error_str . gettext("Hostname specified exists, but not under the username specified.");
1160
					} else if (preg_match('/abuse/i', $data)) {
1161
						$status = $status_intro . $error_str . gettext("Updating too frequently, considered abuse.");
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 'staticcling':
1169
					if (preg_match("/invalid ip/i", $data)) {
1170
						$status = $status_intro . $error_str . gettext("Bad Request - The IP provided was invalid.");
1171
					} else if (preg_match('/required info missing/i', $data)) {
1172
						$status = $status_intro . $error_str . gettext("Bad Request - Required parameters were not provided.");
1173
					} else if (preg_match('/invalid characters/i', $data)) {
1174
						$status = $status_intro . $error_str . gettext("Bad Request - Illegal characters in either the username or the password.");
1175
					} else if (preg_match('/bad password/i', $data)) {
1176
						$status = $status_intro . $error_str . gettext("Invalid password.");
1177
					} else if (preg_match('/account locked/i', $data)) {
1178
						$status = $status_intro . $error_str . gettext("This account has been administratively locked.");
1179
					} else if (preg_match('/update too frequent/i', $data)) {
1180
						$status = $status_intro . $error_str . gettext("Updating too frequently.");
1181
					} else if (preg_match('/DB error/i', $data)) {
1182
						$status = $status_intro . $error_str . gettext("Server side error.");
1183
					} else if (preg_match('/success/i', $data)) {
1184
						$status = $status_intro . $success_str . gettext("IP Address Updated 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 'namecheap':
1193
					$tmp = str_replace("^M", "", $data);
1194
					$ncresponse = @xml2array($tmp);
1195
					if (preg_match("/internal server error/i", $data)) {
1196
						$status = $status_intro . $error_str . gettext("Server side error.");
1197
					} else if (preg_match("/request is badly formed/i", $data)) {
1198
						$status = $status_intro . $error_str . gettext("Badly Formed Request (check the settings).");
1199
					} else if ($ncresponse['interface-response']['ErrCount'] === "0") {
1200
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1201
						$successful_update = true;
1202
					} else if (is_numeric($ncresponse['interface-response']['ErrCount']) && ($ncresponse['interface-response']['ErrCount'] > 0)) {
1203
						$status = $status_intro . $error_str . implode(", ", $ncresponse["interface-response"]["errors"]);
1204
						$successful_update = true;
1205
					} else {
1206
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1207
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1208
						$this->_debug($data);
1209
					}
1210
					break;
1211

    
1212
				case 'he-net':
1213
				case 'he-net-v6':
1214
					if (preg_match("/badip/i", $data)) {
1215
						$status = $status_intro . $error_str . gettext("Bad Request - The IP provided was invalid.");
1216
					} else if (preg_match('/nohost/i', $data)) {
1217
						$status = $status_intro . $error_str . gettext("Bad Request - A hostname was not provided.");
1218
					} else if (preg_match('/badauth/i', $data)) {
1219
						$status = $status_intro . $error_str . gettext("Invalid username or password.");
1220
					} else if (preg_match('/good/i', $data)) {
1221
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1222
						$successful_update = true;
1223
					} else if (preg_match('/nochg/i', $data)) {
1224
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1225
						$successful_update = true;
1226
					} else {
1227
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1228
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1229
						$this->_debug($data);
1230
					}
1231
					break;
1232
				case 'he-net-tunnelbroker':
1233
					/*
1234
					-ERROR: Missing parameter(s).
1235
					-ERROR: Invalid API key or password
1236
					-ERROR: Tunnel not found
1237
					-ERROR: Another tunnel exists for this IP.
1238
					-ERROR: This tunnel is already associated with this IP address
1239
					+OK: Tunnel endpoint updated to: x.x.x.x
1240
					*/
1241
					if (preg_match("/Missing parameter/i", $data)) {
1242
						$status = $status_intro . $error_str . gettext("Bad Request - Missing/Invalid Parameters.");
1243
					} else if (preg_match('/Tunnel not found/i', $data)) {
1244
						$status = $status_intro . $error_str . gettext("Bad Request - Invalid Tunnel ID.");
1245
					} else if (preg_match('/Invalid API key or password/i', $data)) {
1246
						$status = $status_intro . $error_str . gettext("Invalid username or password.");
1247
					} else if (preg_match('/OK:/i', $data)) {
1248
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1249
						$successful_update = true;
1250
					} else if (preg_match('/This tunnel is already associated with this IP address/i', $data)) {
1251
						$status = $status_intro . $success_str . gettext("No Change In IP Address.");
1252
						$successful_update = true;
1253
					} else {
1254
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1255
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1256
						$this->_debug($data);
1257
					}
1258
					break;
1259
				case 'selfhost':
1260
					if (preg_match('/notfqdn/i', $data)) {
1261
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
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 if (preg_match('/good/i', $data)) {
1266
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1267
						$successful_update = true;
1268
					} else if (preg_match('/noauth/i', $data)) {
1269
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1270
					} else {
1271
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1272
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1273
						$this->_debug($data);
1274
					}
1275
					break;
1276
				case 'route53':
1277
					$successful_update = true;
1278
					break;
1279
				case 'custom':
1280
				case 'custom-v6':
1281
					$successful_update = false;
1282
					if ($this->_dnsResultMatch == "") {
1283
						$successful_update = true;
1284
					} else {
1285
						$this->_dnsResultMatch = str_replace("%IP%", $this->_dnsIP, $this->_dnsResultMatch);
1286
						$matches = preg_split("/(?<!\\\\)\\|/", $this->_dnsResultMatch);
1287
						foreach ($matches as $match) {
1288
							$match= str_replace("\\|", "|", $match);
1289
							if (strcmp($match, trim($data, "\t\n\r")) == 0) {
1290
								$successful_update = true;
1291
							}
1292
						}
1293
						unset ($matches);
1294
					}
1295
					if ($successful_update == true) {
1296
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1297
					} else {
1298
						$status = $status_intro . $error_str . gettext("Result did not match.") . " [" . $data . "]";
1299
					}
1300
					break;
1301
				case 'cloudflare-v6':
1302
				case 'cloudflare':
1303
					$output = json_decode($data);
1304
					if ($output->result->content === $this->_dnsIP) {
1305
						$status = $status_intro . $success_str . sprintf(gettext('%1$s updated to %2$s'), $this->_dnsHost, $this->_dnsIP);
1306
						$successful_update = true;
1307
					} elseif ($output->errors[0]->code === 9103) {
1308
						$status = $status_intro . $error_str . gettext("Invalid Credentials! Don't forget to use API Key for password field with CloudFlare.");
1309
					} elseif (($output->success) && (!$output->result[0]->id)) {
1310
						$status = $status_intro . $error_str . gettext("Zone or Host ID was not found, check the hostname.");
1311
					} else {
1312
						$status = $status_intro . gettext("UNKNOWN ERROR") . " - " . $output->errors[0]->message;
1313
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1314
					}
1315
					break;
1316
				case 'eurodns':
1317
					if (preg_match('/notfqdn/i', $data)) {
1318
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
1319
					} else if (preg_match('/nochg/i', $data)) {
1320
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1321
						$successful_update = true;
1322
					} else if (preg_match('/good/i', $data)) {
1323
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1324
						$successful_update = true;
1325
					} else if (preg_match('/badauth/i', $data)) {
1326
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1327
					} else {
1328
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1329
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1330
						$this->_debug($data);
1331
					}
1332
					break;
1333
				case 'gratisdns':
1334
					if (preg_match('/Forkerte værdier/i', $data)) {
1335
						$status = $status_intro . $error_str . gettext("Wrong values - Update could not be completed.");
1336
					} else if (preg_match('/Bruger login: Bruger eksistere ikke/i', $data)) {
1337
						$status = $status_intro . $error_str . gettext("Unknown username - User does not exist.");
1338
					} else if (preg_match('/Bruger login: 1Fejl i kodeord/i', $data)) {
1339
						$status = $status_intro . $error_str . gettext("Wrong password - Remember password is case sensitive.");
1340
					} else if (preg_match('/Domæne kan IKKE administreres af bruger/i', $data)) {
1341
						$status = $status_intro . $error_str . gettext("User unable to administer the selected domain.");
1342
					} else if (preg_match('/OK/i', $data)) {
1343
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1344
						$successful_update = true;
1345
					} else {
1346
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1347
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1348
						$this->_debug($data);
1349
					}
1350
					break;
1351
				case 'dnsimple':
1352
					/* Responds with HTTP 200 on success.
1353
					   Responds with HTTP 4xx on error.
1354
					   Returns JSON data as body */
1355
					$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
1356
					$header = substr($data, 0, $header_size);
1357
					$body = substr($data, $header_size);
1358
					if (preg_match("/Status: 200\s/i", $header)) {
1359
						$status = $status_intro . $success_str . gettext("IP Address Updated Successfully!");
1360
						$successful_update = true;
1361
					} else if (preg_match("/Status: 4\d\d\s/i", $header)) {
1362
						$arrbody = json_decode($body, true);
1363
						$message = $arrbody['message'] . ".";
1364
						if (isset($arrbody['errors']['content'])) {
1365
							foreach ($arrbody['errors']['content'] as $key => $content) {
1366
								$message .= " " . $content . ".";
1367
							}
1368
						}
1369
						$status = $status_intro . $error_str . $message;
1370
					} else {
1371
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1372
						log_error($status_intro . gettext("PAYLOAD:") . " " . $body);
1373
						$this->_debug($body);
1374
					}
1375
					break;
1376
				case 'googledomains':
1377
					if (preg_match('/notfqdn/i', $data)) {
1378
						$status = $status_intro . $error_str . gettext("Not A FQDN");
1379
					} else if (preg_match('/nochg/i', $data)) {
1380
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1381
						$successful_update = true;
1382
					} else if (preg_match('/good/i', $data)) {
1383
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1384
						$successful_update = true;
1385
					} else if (preg_match('/badauth/i', $data)) {
1386
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1387
					} else if (preg_match('/nohost/i', $data)) {
1388
						$status = $status_intro . $error_str . gettext("Hostname does not exist or DynDNS not enabled");
1389
					} else if (preg_match('/badagent/i', $data)) {
1390
						$status = $status_intro . $error_str . gettext("Bad request");
1391
					} else if (preg_match('/abuse/i', $data)) {
1392
						$status = $status_intro . $error_str . gettext("Dynamic DNS access has been blocked!");
1393
					} else if (preg_match('/911/i', $data)) {
1394
						$status = $status_intro . $error_str . gettext("Error on Google's end, retry in 5 minutes");
1395
					} else {
1396
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1397
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1398
						$this->_debug($data);
1399
					}
1400
					break;
1401
				case 'dnsmadeeasy':
1402
					switch ($data) {
1403
						case 'success':
1404
							$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1405
							$successful_update = true;
1406
							break;
1407
						case 'error-auth':
1408
							$status = $status_intro . $error_str . gettext("Invalid username or password");
1409
							break;
1410
						case 'error-auth-suspend':
1411
							$status = $status_intro . $error_str . gettext("Account suspended");
1412
							break;
1413
						case 'error-auth-voided':
1414
							$status = $status_intro . $error_str . gettext("Account revoked");
1415
							break;
1416
						case 'error-record-invalid':
1417
							$status = $status_intro . $error_str . gettext("Record does not exist in the system. Unable to update record");
1418
							break;
1419
						case 'error-record-auth':
1420
							$status = $status_intro . $error_str . gettext("User does not have access to this record");
1421
							break;
1422
						case 'error-record-ip-same':
1423
							$status = $status_intro . $success_str . gettext("No Change In IP Address");
1424
							$successful_update = true;
1425
							break;
1426
						case 'error-system':
1427
							$status = $status_intro . $error_str . gettext("General system error recognized by the system");
1428
							break;
1429
						case 'error':
1430
							$status = $status_intro . $error_str . gettext("General system error unrecognized by the system");
1431
							break;
1432
						default:
1433
							$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1434
							log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1435
							$this->_debug($data);
1436
							break;
1437
					}
1438
					break;
1439
				case 'spdyn':
1440
				case 'spdyn-v6':
1441
					if (preg_match('/notfqdn/i', $data)) {
1442
						$status = $status_intro . $error_str . gettext("Not A FQDN!");
1443
					} else if (preg_match('/nohost/i', $data)) {
1444
						$status = $status_intro . $error_str . gettext("No such host");
1445
					} else if (preg_match('/nochg/i', $data)) {
1446
						$status = $status_intro . $success_str . gettext("No Change In IP Address");
1447
						$successful_update = true;
1448
					} else if (preg_match('/good/i', $data)) {
1449
						$status = $status_intro . $success_str . gettext("IP Address Changed Successfully!") . " (" . $this->_dnsIP . ")";
1450
						$successful_update = true;
1451
					} else if (preg_match('/badauth/i', $data)) {
1452
						$status = $status_intro . $error_str . gettext("User Authorization Failed");
1453
					} else {
1454
						$status = $status_intro . "(" . gettext("Unknown Response") . ")";
1455
						log_error($status_intro . gettext("PAYLOAD:") . " " . $data);
1456
						$this->_debug($data);
1457
					}
1458
					break;
1459
			}
1460

    
1461
			if ($successful_update == true) {
1462
				/* Write WAN IP to cache file */
1463
				$wan_ip = $this->_checkIP();
1464
				conf_mount_rw();
1465
				if ($this->_useIPv6 == false && $wan_ip > 0) {
1466
					$currentTime = time();
1467
					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));
1468
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile, $wan_ip));
1469
					@file_put_contents($this->_cacheFile, "{$wan_ip}:{$currentTime}");
1470
				} else {
1471
					@unlink($this->_cacheFile);
1472
				}
1473
				if ($this->_useIPv6 == true && $wan_ip > 0) {
1474
					$currentTime = time();
1475
					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));
1476
					log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile_v6, $wan_ip));
1477
					@file_put_contents($this->_cacheFile_v6, "{$wan_ip}|{$currentTime}");
1478
				} else {
1479
					@unlink($this->_cacheFile_v6);
1480
				}
1481
				conf_mount_ro();
1482
			}
1483
			$this->status = $status;
1484
			log_error($status);
1485
		}
1486

    
1487
		/*
1488
		 * Private Function (added 12 July 05) [beta]
1489
		 *   Return Error, Set Last Error, and Die.
1490
		 */
1491
		function _error($errorNumber = '1') {
1492
			$err_str = 'phpDynDNS: (' . gettext('ERROR!') . ') ';
1493
			$err_str_r53 = 'Route 53: (' . gettext('Error') . ') ';
1494
			switch ($errorNumber) {
1495
				case 0:
1496
					break;
1497
				case 2:
1498
					$error = $err_str . gettext('No Dynamic DNS Service provider was selected.');
1499
					break;
1500
				case 3:
1501
					$error = $err_str . gettext('No Username Provided.');
1502
					break;
1503
				case 4:
1504
					$error = $err_str . gettext('No Password Provided.');
1505
					break;
1506
				case 5:
1507
					$error = $err_str . gettext('No Hostname Provided.');
1508
					break;
1509
				case 6:
1510
					$error = $err_str . gettext('The Dynamic DNS Service provided is not yet supported.');
1511
					break;
1512
				case 7:
1513
					$error = $err_str . gettext('No Update URL Provided.');
1514
					break;
1515
				case 8:
1516
					$status = $err_str_r53 . gettext("Invalid ZoneID");
1517
					break;
1518
				case 9:
1519
					$status = $err_str_r53 . gettext("Invalid TTL");
1520
					break;
1521
				case 10:
1522
					$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);
1523
					break;
1524
				default:
1525
					$error = $err_str . gettext('Unknown Response.');
1526
					/* FIXME: $data isn't in scope here */
1527
					/* $this->_debug($data); */
1528
					break;
1529
			}
1530
			$this->lastError = $error;
1531
			log_error($error);
1532
		}
1533

    
1534
		/*
1535
		 * Private Function (added 12 July 05) [beta]
1536
		 *   - Detect whether or not IP needs to be updated.
1537
		 *      | Written Specifically for pfSense (https://www.pfsense.org) may
1538
		 *      | work with other systems. pfSense base is FreeBSD.
1539
		 */
1540
		function _detectChange() {
1541
			global $debug;
1542

    
1543
			if ($debug) {
1544
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _detectChange() starting.'), $this->_dnsService, $this->_FQDN));
1545
			}
1546

    
1547
			$currentTime = time();
1548

    
1549
			$wan_ip = $this->_checkIP();
1550
			if ($wan_ip == 0) {
1551
				log_error(sprintf(gettext("Dynamic Dns (%s): Current WAN IP could not be determined, skipping update process."), $this->_FQDN));
1552
				return false;
1553
			}
1554
			$log_error = sprintf(gettext('Dynamic Dns (%1$s): Current WAN IP: %2$s'), $this->_FQDN, $wan_ip) . " ";
1555

    
1556
			if ($this->_useIPv6 == true) {
1557
				if (file_exists($this->_cacheFile_v6)) {
1558
					$contents = file_get_contents($this->_cacheFile_v6);
1559
					list($cacheIP, $cacheTime) = explode('|', $contents);
1560
					$this->_debug($cacheIP.'/'.$cacheTime);
1561
					$initial = false;
1562
					$log_error .= sprintf(gettext("Cached IPv6: %s"), $cacheIP);
1563
				} else {
1564
					conf_mount_rw();
1565
					$cacheIP = '::';
1566
					@file_put_contents($this->_cacheFile, "::|{$currentTime}");
1567
					conf_mount_ro();
1568
					$cacheTime = $currentTime;
1569
					$initial = true;
1570
					$log_error .= gettext("No Cached IPv6 found.");
1571
				}
1572
			} else {
1573
				if (file_exists($this->_cacheFile)) {
1574
					$contents = file_get_contents($this->_cacheFile);
1575
					list($cacheIP, $cacheTime) = explode(':', $contents);
1576
					$this->_debug($cacheIP.'/'.$cacheTime);
1577
					$initial = false;
1578
					$log_error .= sprintf(gettext("Cached IP: %s"), $cacheIP);
1579
				} else {
1580
					conf_mount_rw();
1581
					$cacheIP = '0.0.0.0';
1582
					@file_put_contents($this->_cacheFile, "0.0.0.0:{$currentTime}");
1583
					conf_mount_ro();
1584
					$cacheTime = $currentTime;
1585
					$initial = true;
1586
					$log_error .= gettext("No Cached IP found.");
1587
				}
1588
			}
1589
			if ($this->_dnsVerboseLog) {
1590
				log_error($log_error);
1591
			}
1592

    
1593
			// Convert seconds = days * hr/day * min/hr * sec/min
1594
			$maxCacheAgeSecs = $this->_dnsMaxCacheAgeDays * 24 * 60 * 60;
1595

    
1596
			$needs_updating = FALSE;
1597
			/* lets determine if the item needs updating */
1598
			if ($cacheIP != $wan_ip) {
1599
				$needs_updating = true;
1600
				$update_reason = gettext("Dynamic Dns: cacheIP != wan_ip. Updating.") . " ";
1601
				$update_reason .= sprintf(gettext('Cached IP: %1$s WAN IP: %2$s'), $cacheIP, $wan_ip) . " ";
1602
			}
1603
			if (($currentTime - $cacheTime) > $maxCacheAgeSecs) {
1604
				$needs_updating = true;
1605
				$this->_forceUpdateNeeded = true;
1606
				$update_reason = sprintf(gettext("Dynamic Dns: More than %s days. Updating."), $this->_dnsMaxCacheAgeDays);
1607
				$update_reason .= " {$currentTime} - {$cacheTime} > {$maxCacheAgeSecs} ";
1608
			}
1609
			if ($initial == true) {
1610
				$needs_updating = true;
1611
				$update_reason .= gettext("Initial update.");
1612
			}
1613

    
1614
			/*   finally if we need updating then store the
1615
			 *   new cache value and return true
1616
			 */
1617
			if ($needs_updating == true) {
1618
				if ($this->_dnsVerboseLog) {
1619
					log_error("DynDns ({$this->_FQDN}): {$update_reason}");
1620
				}
1621
				return true;
1622
			}
1623

    
1624
			return false;
1625
		}
1626

    
1627
		/*
1628
		 * Private Function (added 16 July 05) [beta]
1629
		 *   - Writes debug information to a file.
1630
		 *   - This function is only called when a unknown response
1631
		 *   - status is returned from a DynDNS service provider.
1632
		 */
1633
		function _debug($data) {
1634
			global $g;
1635

    
1636
			if (!$g['debug']) {
1637
				return;
1638
			}
1639
			$string = date('m-d-y h:i:s').' - ('.$this->_debugID.') - ['.$this->_dnsService.'] - '.$data."\n";
1640
			conf_mount_rw();
1641
			$file = fopen($this->_debugFile, 'a');
1642
			fwrite($file, $string);
1643
			fclose($file);
1644
			conf_mount_ro();
1645
		}
1646
		function _checkIP() {
1647
			global $debug;
1648

    
1649
			if ($debug) {
1650
				log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): _checkIP() starting.'), $this->_dnsService, $this->_FQDN));
1651
			}
1652

    
1653
			if ($this->_useIPv6 == true) {
1654
				$ip_address = get_interface_ipv6($this->_if);
1655
				if (!is_ipaddrv6($ip_address)) {
1656
					return 0;
1657
				}
1658
			} else {
1659
				$ip_address = get_interface_ip($this->_if);
1660
				if (!is_ipaddr($ip_address)) {
1661
					return 0;
1662
				}
1663
			}
1664
			if ($this->_useIPv6 == false && is_private_ip($ip_address)) {
1665
				$hosttocheck = "checkip.dyndns.org";
1666
				$try = 0;
1667
				while ($try < 3) {
1668
					$checkip = gethostbyname($hosttocheck);
1669
					if (is_ipaddr($checkip)) {
1670
						break;
1671
					}
1672
					$try++;
1673
				}
1674
				if ($try >= 3) {
1675
					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));
1676
					return 0;
1677
				}
1678
				$ip_ch = curl_init("http://{$checkip}");
1679
				curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1680
				curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1681
				curl_setopt($ip_ch, CURLOPT_INTERFACE, 'host!' . $ip_address);
1682
				curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1683
				curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1684
				if ($this->_useIPv6 == false) {
1685
					curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1686
				}
1687
				$ip_result_page = curl_exec($ip_ch);
1688
				curl_close($ip_ch);
1689
				$ip_result_decoded = urldecode($ip_result_page);
1690
				preg_match('/Current IP Address: (.*)<\/body>/', $ip_result_decoded, $matches);
1691
				$ip_address = trim($matches[1]);
1692
				if (is_ipaddr($ip_address)) {
1693
					if ($this->_dnsVerboseLog) {
1694
						log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from %4$s'), $this->_dnsService, $this->_FQDN, $ip_address, $hosttocheck));
1695
					}
1696
				} else {
1697
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): IP address could not be extracted from %3$s'), $this->_dnsService, $this->_FQDN, $hosttocheck));
1698
					return 0;
1699
				}
1700
			} else {
1701
				if ($this->_dnsVerboseLog) {
1702
					log_error(sprintf(gettext('Dynamic DNS %1$s (%2$s): %3$s extracted from local system.'), $this->_dnsService, $this->_FQDN, $ip_address));
1703
				}
1704
			}
1705
			$this->_dnsIP = $ip_address;
1706

    
1707
			return $ip_address;
1708
		}
1709

    
1710
	}
1711

    
1712
?>
(10-10/50)