Project

General

Profile

Download (36.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
	/*
3
	 * PHP.updateDNS (pfSense version)
4
	 *
5
	 * +====================================================+
6
	 *  Services Supported:
7
	 *    - DynDns (dyndns.org) [dynamic, static, custom]
8
	 *    - DHSDns (dhs.org)
9
	 *    - No-IP (no-ip.com)
10
	 *    - EasyDNS (easydns.com)
11
	 *    - DHS (www.dhs.org)
12
	 *    - HN (hn.org) -- incomplete checking!
13
	 *    - DynS (dyns.org)
14
	 *    - ZoneEdit (zoneedit.com)
15
	 *    - FreeDNS (freedns.afraid.org)
16
	 *    - Loopia (loopia.se)
17
	 *    - StaticCling (staticcling.org)
18
	 *    - DNSexit (dnsexit.com)
19
	 *    - OpenDNS (opendns.com)
20
	 *    - Namecheap (namecheap.com)
21
	 *    - HE.net (dns.he.net)
22
	 *    - HE.net Tunnelbroker IP update (ipv4.tunnelbroker.net)
23
	 * +----------------------------------------------------+
24
	 *  Requirements:
25
	 *    - PHP version 4.0.2 or higher with CURL Library
26
	 * +----------------------------------------------------+
27
	 *  Public Functions
28
	 *    - updatedns()
29
	 *
30
	 *  Private Functions
31
	 *    - _update()
32
	 *    - _checkStatus()
33
	 *    - _error()
34
	 *    - _detectChange()
35
	 *    - _debug()
36
	 *    - _checkIP()
37
	 * +----------------------------------------------------+
38
	 *  DynDNS Dynamic - Last Tested: 12 July 2005
39
	 *  DynDNS Static  - Last Tested: NEVER
40
	 *  DynDNS Custom  - Last Tested: NEVER
41
	 *  No-IP          - Last Tested: 20 July 2008
42
	 *  HN.org         - Last Tested: 12 July 2005
43
	 *  EasyDNS        - Last Tested: 20 July 2008
44
	 *  DHS            - Last Tested: 12 July 2005
45
	 *  ZoneEdit       - Last Tested: NEVER
46
	 *  Dyns           - Last Tested: NEVER
47
	 *  ODS            - Last Tested: 02 August 2005
48
	 *  FreeDNS        - Last Tested: 23 Feb 2011
49
	 *  Loopia         - Last Tested: NEVER
50
	 *  StaticCling    - Last Tested: 27 April 2006
51
	 *  DNSexit	   - Last Tested: 20 July 2008
52
	 *  OpenDNS	   - Last Tested: 4 August 2008
53
	 *  Namecheap	   - Last Tested: 31 August 2010
54
	 *  HE.net         - Last Tested: NEVER
55
	 *  HE.net Tunnel  - Last Tested: 28 June 2011
56
	 * +====================================================+
57
	 *
58
	 * @author 	E.Kristensen
59
	 * @link    	http://www.idylldesigns.com/projects/phpdns/
60
	 * @version 	0.8
61
	 * @updated	13 October 05 at 21:02:42 GMT
62
	 *
63
	 * DNSexit/OpenDNS support and multiwan extension for pfSense by Ermal Lu?i
64
	 *
65
	 */
66

    
67
	class updatedns {
68
		var $_cacheFile;
69
		var $_debugFile;
70
		var $_UserAgent = 'User-Agent: phpDynDNS/0.7';
71
		var $_errorVerbosity = 0;
72
		var $_dnsService;
73
		var $_dnsUser;
74
		var $_dnsPass;
75
		var $_dnsHost;
76
		var $_dnsIP;
77
		/* This is needed for support on addresses behind NAT. */
78
		var $_ifIP;
79
		var $_dnsWildcard;
80
		var $_dnsMX;
81
		var $_dnsBackMX;
82
		var $_dnsServer;
83
		var $_dnsPort;
84
		var $_dnsUpdateURL;
85
		var $status;
86
		var $_debugID;
87
		var $_if;
88
		
89
		/* 
90
		 * Public Constructor Function (added 12 July 05) [beta]
91
		 *   - Gets the dice rolling for the update. 
92
		 */
93
		function updatedns ($dnsService = '', $dnsHost = '', $dnsUser = '', $dnsPass = '',
94
				    $dnsWildcard = 'OFF', $dnsMX = '', $dnsIf = '', $dnsBackMX = '',
95
				    $dnsServer = '', $dnsPort = '', $dnsUpdateURL = '') {
96
			
97
			global $config, $g;
98
			
99
			$this->_cacheFile = "{$g['conf_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($dnsHost) . ".cache";
100
			$this->_debugFile = "{$g['varetc_path']}/dyndns_{$dnsIf}{$dnsService}" . escapeshellarg($dnsHost) . ".debug";
101

    
102
			log_error("DynDns: updatedns() starting");
103

    
104
			$dyndnslck = lock($dnsHost, LOCK_EX);
105

    
106
			if (!$dnsService) $this->_error(2);
107
			switch ($dnsService) {
108
			case 'freedns':
109
				if (!$dnsHost) $this->_error(5);
110
				break;
111
			case 'namecheap':
112
				if (!$dnsPass) $this->_error(4);
113
				if (!$dnsHost) $this->_error(5);
114
				break;
115
			default:
116
				if (!$dnsUser) $this->_error(3);
117
				if (!$dnsPass) $this->_error(4);
118
				if (!$dnsHost) $this->_error(5);
119
			}
120
			
121
			$this->_dnsService = strtolower($dnsService);
122
			$this->_dnsUser = $dnsUser;
123
			$this->_dnsPass = $dnsPass;
124
			$this->_dnsHost = $dnsHost;
125
			$this->_dnsServer = $dnsServer;
126
			$this->_dnsPort = $dnsPort;
127
			$this->_dnsWildcard = $dnsWildcard;
128
			$this->_dnsMX = $dnsMX;
129
			$this->_if = get_real_interface($dnsIf);
130
			$this->_ifIP = get_interface_ip($dnsIf);
131

    
132
			// Ensure that we where able to lookup the IP
133
			if(!is_ipaddr($this->_ifIP)) {
134
				log_error("There was an error trying to determine the IP for interface - {$dnsIf}({$this->_if}). Probably interface has no ip or is down. Dyndns update not possible for {$dnsService}.");
135
				unlock($dyndnslck);
136
				return;
137
			}
138

    
139
			$this->_debugID = rand(1000000, 9999999);
140
			
141
			if ($this->_detectChange() == false) {
142
				$this->_error(10);
143
			} else {
144
				switch ($this->_dnsService) {
145
				case 'dnsomatic':
146
				case 'dyndns':
147
				case 'dyndns-static':
148
				case 'dyndns-custom':
149
				case 'dhs':
150
				case 'noip':
151
				case 'easydns':
152
				case 'hn':
153
				case 'zoneedit':
154
				case 'dyns':
155
				case 'ods':
156
				case 'freedns':
157
				case 'loopia':
158
				case 'staticcling':
159
				case 'dnsexit':
160
				case 'opendns':
161
				case 'namecheap':
162
				case 'he-net':
163
					$this->_update();	
164
					break;
165
				case 'he-net-tunnelbroker':
166
					$this->_update();
167
					break;
168
				default:
169
					$this->_error(6);
170
					break;
171
				}
172
			}
173

    
174
			unlock($dyndnslck);
175
		}
176
			
177
		/*
178
		 * Private Function (added 12 July 05) [beta]
179
		 *   Send Update To Selected Service.
180
		 */
181
		function _update() {
182
		
183
			log_error("DynDns: DynDns _update() starting.");
184
		
185
			if ($this->_dnsService != 'ods') {
186
				$ch = curl_init();
187
				curl_setopt($ch, CURLOPT_HEADER, 0);
188
				curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
189
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
190
				curl_setopt($ch, CURLOPT_INTERFACE, $this->_ifIP);
191
				curl_setopt($ch, CURLOPT_TIMEOUT, 120); // Completely empirical
192
			}
193

    
194
			switch ($this->_dnsService) {
195
				case 'dyndns':
196
				case 'dyndns-static':
197
				case 'dyndns-custom':
198
					$needsIP = FALSE;
199
					//log_error("DynDns: DynDns _update() starting. Dynamic");
200
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
201
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
202
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
203
					$server = "https://members.dyndns.org/nic/update";
204
					$port = "";
205
					if($this->_dnsServer)
206
						$server = $this->_dnsServer;
207
					if($this->_dnsPort)
208
						$port = ":" . $this->_dnsPort;
209
					curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
210
					break;
211
				case 'dhs':
212
					$needsIP = TRUE;
213
					$post_data['hostscmd'] = 'edit';
214
					$post_data['hostscmdstage'] = '2';
215
					$post_data['type'] = '4';
216
					$post_data['updatetype'] = 'Online';
217
					$post_data['mx'] = $this->_dnsMX;
218
					$post_data['mx2'] = '';
219
					$post_data['txt'] = '';
220
					$post_data['offline_url'] = '';
221
					$post_data['cloak'] = 'Y';
222
					$post_data['cloak_title'] = '';
223
					$post_data['ip'] = $this->_dnsIP;
224
					$post_data['domain'] = 'dyn.dhs.org';
225
					$post_data['hostname'] = $this->_dnsHost;
226
					$post_data['submit'] = 'Update';
227
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
228
					$server = "https://members.dhs.org/nic/hosts";
229
					$port = "";
230
					if($this->_dnsServer)
231
						$server = $this->_dnsServer;
232
					if($this->_dnsPort)
233
						$port = ":" . $this->_dnsPort;					
234
					curl_setopt($ch, CURLOPT_URL, '{$server}{$port}');
235
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
236
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
237
					break;
238
				case 'noip':
239
					$needsIP = TRUE;
240
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
241
					$server = "http://dynupdate.no-ip.com/ducupdate.php";
242
					$port = "";
243
					if($this->_dnsServer)
244
						$server = $this->_dnsServer;
245
					if($this->_dnsPort)
246
						$port = ":" . $this->_dnsPort;
247
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&pass=' . urlencode($this->_dnsPass) . '&hostname=' . $this->_dnsHost.'&ip=' . $this->_dnsIP);
248
					break;
249
				case 'easydns':
250
					$needsIP = TRUE;
251
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
252
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
253
					$server = "http://members.easydns.com/dyn/dyndns.php";
254
					$port = "";
255
					if($this->_dnsServer)
256
						$server = $this->_dnsServer;
257
					if($this->_dnsPort)
258
						$port = ":" . $this->_dnsPort;
259
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard=' . $this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=' . $this->_dnsBackMX);
260
					break;
261
				case 'hn':
262
					$needsIP = TRUE;
263
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
264
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
265
					$server = "http://dup.hn.org/vanity/update";
266
					$port = "";
267
					if($this->_dnsServer)
268
						$server = $this->_dnsServer;
269
					if($this->_dnsPort)
270
						$port = ":" . $this->_dnsPort;
271
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?ver=1&IP=' . $this->_dnsIP);
272
					break;
273
				case 'zoneedit':
274
					$needsIP = FALSE;
275
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
276
					curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
277
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
278

    
279
					$server = "https://dynamic.zoneedit.com/auth/dynamic.html";
280
					$port = "";
281
					if($this->_dnsServer)
282
						$server = $this->_dnsServer;
283
					if($this->_dnsPort)
284
						$port = ":" . $this->_dnsPort;
285
					curl_setopt($ch, CURLOPT_URL, "{$server}{$port}?host=" .$this->_dnsHost);
286
					break;
287
				case 'dyns':
288
					$needsIP = FALSE;
289
					$server = "http://www.dyns.cx/postscript011.php";
290
					$port = "";
291
					if($this->_dnsServer)
292
						$server = $this->_dnsServer;
293
					if($this->_dnsPort)
294
						$port = ":" . $this->_dnsPort;					
295
					curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&password=' . $this->_dnsPass . '&host=' . $this->_dnsHost);
296
					break;
297
				case 'ods':
298
					$needsIP = FALSE;
299
					$misc_errno = 0;
300
					$misc_error = "";
301
					$server = "ods.org";
302
					$port = "";
303
					if($this->_dnsServer)
304
						$server = $this->_dnsServer;
305
					if($this->_dnsPort)
306
						$port = ":" . $this->_dnsPort;						
307
					$this->con['socket'] = fsockopen("{$server}{$port}", "7070", $misc_errno, $misc_error, 30);
308
					/* Check that we have connected */
309
					if (!$this->con['socket']) {
310
						print "error! could not connect.";
311
						break;
312
					}
313
					/* Here is the loop. Read the incoming data (from the socket connection) */
314
					while (!feof($this->con['socket'])) {
315
						$this->con['buffer']['all'] = trim(fgets($this->con['socket'], 4096));
316
						$code = substr($this->con['buffer']['all'], 0, 3);
317
						sleep(1);
318
						switch($code) {
319
							case 100:
320
								fputs($this->con['socket'], "LOGIN ".$this->_dnsUser." ".$this->_dnsPass."\n");
321
								break;
322
							case 225:
323
								fputs($this->con['socket'], "DELRR ".$this->_dnsHost." A\n");
324
								break;
325
							case 901:
326
								fputs($this->con['socket'], "ADDRR ".$this->_dnsHost." A ".$this->_dnsIP."\n");
327
								break;
328
							case 795:
329
								fputs($this->con['socket'], "QUIT\n");
330
								break;
331
						}
332
					}
333
					$this->_checkStatus(0, $code);
334
					break;
335
				case 'freedns':
336
					$needIP = FALSE;
337
					curl_setopt($ch, CURLOPT_URL, 'http://freedns.afraid.org/dynamic/update.php?' . $this->_dnsPass);
338
					break;
339
				case 'dnsexit':
340
					$needsIP = TRUE;
341
					curl_setopt($ch, CURLOPT_URL, 'http://www.dnsexit.com/RemoteUpdate.sv?login='.$this->_dnsUser. '&password='.$this->_dnsPass.'&host='.$this->_dnsHost.'&myip='.$this->_dnsIP);
342
					break;
343
				case 'loopia':
344
					$needsIP = TRUE;
345
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
346
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
347
					curl_setopt($ch, CURLOPT_URL, 'https://dns.loopia.se/XDynDNSServer/XDynDNS.php?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP);
348
					break;
349
				case 'opendns':
350
					$needsIP = FALSE;
351
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
352
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
353
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
354
					$server = "https://updates.opendns.com/nic/update?hostname=". $this->_dnsHost;
355
					$port = "";
356
					if($this->_dnsServer)
357
						$server = $this->_dnsServer;
358
					if($this->_dnsPort)
359
						$port = ":" . $this->_dnsPort;
360
					curl_setopt($ch, CURLOPT_URL, $server .$port);
361
					break;
362

    
363
				case 'staticcling':
364
					$needsIP = FALSE;
365
					curl_setopt($ch, CURLOPT_URL, 'http://www.staticcling.org/update.html?login='.$this->_dnsUser.'&pass='.$this->_dnsPass);
366
					break;	                    
367
				case 'dnsomatic':
368
					/* Example syntax 
369
						https://username:password@updates.dnsomatic.com/nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
370
					*/
371
					$needsIP = FALSE;
372
					log_error("DNS-O-Matic: DNS update() starting.");
373
					if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
374
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
375
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
376
					$server = "https://" . $this->_dnsUser . ":" . $this->_dnsPass . "@updates.dnsomatic.com/nic/update?hostname=";
377
					if($this->_dnsServer)
378
						$server = $this->_dnsServer;
379
					if($this->_dnsPort)
380
						$port = ":" . $this->_dnsPort;
381
					curl_setopt($ch, CURLOPT_URL, $server . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NOCHG');
382
					break;
383
				case 'namecheap':
384
					/* Example:
385
						https://dynamicdns.park-your-domain.com/update?host=[host_name]&domain=[domain.com]&password=[domain_password]&ip=[your_ip]
386
					*/
387
					$needsIP = FALSE;
388
					log_error("Namecheap: DNS update() starting.");
389
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
390
					list($hostname, $domain) = explode(".", $this->_dnsHost, 2);
391
					$server = "https://dynamicdns.park-your-domain.com/update?host={$hostname}&domain={$domain}&password={$this->_dnsPass}&ip={$this->_dnsIP}";
392
					curl_setopt($ch, CURLOPT_URL, $server);
393
					break;
394
				case 'he-net':
395
					$needsIP = FALSE;
396
					log_error("HE.net: DNS update() starting.");
397
					$server = "https://dyn.dns.he.net/nic/update?";
398
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
399
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsHost . ':' . $this->_dnsPass);
400
					curl_setopt($ch, CURLOPT_URL, $server . 'hostname=' . $this->_dnsHost);
401
					break;
402
				case 'he-net-tunnelbroker':
403
					$needsIP = FALSE;
404
					log_error("HE.net Tunnelbroker: DNS update() starting.");
405
					$server = "https://ipv4.tunnelbroker.net/ipv4_end.php?";
406
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
407
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
408
					curl_setopt($ch, CURLOPT_URL, $server . 'tid=' . $this->_dnsHost);
409
					break;
410
				default:
411
					break;
412
			}
413
			if ($this->_dnsService != 'ods') {
414
				$data = curl_exec($ch);
415
				$this->_checkStatus($ch, $data);
416
				@curl_close($ch);
417
			}
418
		}
419

    
420
		/*
421
		 * Private Function (added 12 July 2005) [beta]
422
		 *   Retrieve Update Status
423
		 */
424
		function _checkStatus($ch, $data) {
425
			log_error("DynDns: DynDns _checkStatus() starting.");
426
			log_error("DynDns: Current Service: {$this->_dnsService}");
427
			$successful_update = false;
428
			if ($this->_dnsService != 'ods' && @curl_error($ch)) {
429
				$status = "Curl error occurred: " . curl_error($ch);
430
				log_error($status);
431
				$this->status = $status;
432
				return;
433
			}
434
			switch ($this->_dnsService) {
435
				case 'dnsomatic':
436
					if (preg_match('/badauth/i', $data)) {
437
						$status = "DNS-O-Matic: The DNS-O-Matic username or password specified are incorrect. No updates will be distributed to services until this is resolved.";
438
					} else if (preg_match('/notfqdn /i', $data)) {
439
						$status = "DNS-O-Matic: The hostname specified is not a fully-qualified domain name. If no hostnames included, notfqdn will be returned once.";
440
					} else if (preg_match('/nohost/i', $data)) {
441
						$status = "DNS-O-Matic: The hostname passed could not be matched to any services configured. The service field will be blank in the return code.";
442
					} else if (preg_match('/numhost/i', $data)) {
443
						$status = "DNS-O-Matic: You may update up to 20 hosts. numhost is returned if you try to update more than 20 or update a round-robin.";	
444
					} else if (preg_match('/abuse/i', $data)) {
445
						$status = "DNS-O-Matic: The hostname is blocked for update abuse.";
446
					} else if (preg_match('/good/i', $data)) {
447
						$status = "DNS-O-Matic: (Success) IP Address Changed Successfully! (".$this->_dnsIP.")";
448
						$successful_update = true;
449
					} else if (preg_match('/dnserr/i', $data)) {
450
						$status = "DNS-O-Matic: DNS error encountered. Stop updating for 30 minutes.";
451
					} else {
452
						$status = "DNS-O-Matic: (Unknown Response)";
453
						log_error("DNS-O-Matic: PAYLOAD: {$data}");
454
						$this->_debug($data);
455
					}
456
					break;
457
				case 'dyndns':
458
					if (preg_match('/notfqdn/i', $data)) {
459
						$status = "phpDynDNS: (Error) Not A FQDN!";
460
					} else if (preg_match('/nochg/i', $data)) {
461
						$status = "phpDynDNS: (Success) No Change In IP Address";
462
						$successful_update = true;
463
					} else if (preg_match('/good/i', $data)) {
464
						$status = "phpDynDNS: (Success) IP Address Changed Successfully! (".$this->_dnsIP.")";
465
						$successful_update = true;
466
					} else if (preg_match('/noauth/i', $data)) {
467
						$status = "phpDynDNS: (Error) User Authorization Failed";
468
					} else {
469
						$status = "phpDynDNS: (Unknown Response)";
470
						log_error("phpDynDNS: PAYLOAD: {$data}");
471
						$this->_debug($data);
472
					}
473
					break;
474
				case 'dyndns-static':
475
					if (preg_match('/notfqdn/i', $data)) {
476
						$status = "phpDynDNS: (Error) Not A FQDN!";
477
					} else if (preg_match('/nochg/i', $data)) {
478
						$status = "phpDynDNS: (Success) No Change In IP Address";
479
						$successful_update = true;
480
					} else if (preg_match('/good/i', $data)) {
481
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
482
						$successful_update = true;
483
					} else if (preg_match('/noauth/i', $data)) {
484
						$status = "phpDynDNS: (Error) User Authorization Failed";
485
					} else {
486
						$status = "phpDynDNS: (Unknown Response)";
487
						log_error("phpDynDNS: PAYLOAD: {$data}");
488
						$this->_debug($data);
489
					}
490
					break;
491
				case 'dyndns-custom':
492
					if (preg_match('/notfqdn/i', $data)) {
493
						$status = "phpDynDNS: (Error) Not A FQDN!";
494
					} else if (preg_match('/nochg/i', $data)) {
495
						$status = "phpDynDNS: (Success) No Change In IP Address";
496
						$successful_update = true;
497
					} else if (preg_match('/good/i', $data)) {
498
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
499
						$successful_update = true;
500
					} else if (preg_match('/noauth/i', $data)) {
501
						$status = "phpDynDNS: (Error) User Authorization Failed";
502
					} else {
503
						$status = "phpDynDNS: (Unknown Response)";
504
						log_error("phpDynDNS: PAYLOAD: {$data}");
505
						$this->_debug($data);
506
					}
507
					break;
508
				case 'dhs':
509
					break;
510
				case 'noip':
511
					list($ip,$code) = split(":",$data);
512
					switch ($code) {
513
						case 0:
514
							$status = "phpDynDNS: (Success) IP address is current, no update performed.";
515
							$successful_update = true;
516
							break;
517
						case 1:
518
							$status = "phpDynDNS: (Success) DNS hostname update successful.";
519
							$successful_update = true;
520
							break;
521
						case 2:
522
							$status = "phpDynDNS: (Error) Hostname supplied does not exist.";
523
							break;
524
						case 3:
525
							$status = "phpDynDNS: (Error) Invalid Username.";
526
							break;
527
						case 4:
528
							$status = "phpDynDNS: (Error) Invalid Password.";
529
							break;
530
						case 5:
531
							$status = "phpDynDNS: (Error) To many updates sent.";
532
							break;
533
						case 6:
534
							$status = "phpDynDNS: (Error) Account disabled due to violation of No-IP terms of service.";
535
							break;
536
						case 7:
537
							$status = "phpDynDNS: (Error) Invalid IP. IP Address submitted is improperly formatted or is a private IP address or is on a blacklist.";
538
							break;
539
						case 8:
540
							$status = "phpDynDNS: (Error) Disabled / Locked Hostname.";
541
							break;
542
						case 9:
543
							$status = "phpDynDNS: (Error) Host updated is configured as a web redirect and no update was performed.";
544
							break;
545
						case 10:
546
							$status = "phpDynDNS: (Error) Group supplied does not exist.";
547
							break;
548
						case 11:
549
							$status = "phpDynDNS: (Success) DNS group update is successful.";
550
							$successful_update = true;
551
							break;
552
						case 12:
553
							$status = "phpDynDNS: (Success) DNS group is current, no update performed.";
554
							$successful_update = true;
555
							break;
556
						case 13:
557
							$status = "phpDynDNS: (Error) Update client support not available for supplied hostname or group.";
558
							break;
559
						case 14:
560
							$status = "phpDynDNS: (Error) Hostname supplied does not have offline settings configured.";
561
							break;
562
						case 99:
563
							$status = "phpDynDNS: (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
564
							break;
565
						case 100:
566
							$status = "phpDynDNS: (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
567
							break;
568
						default:
569
							$status = "phpDynDNS: (Unknown Response)";
570
							$this->_debug("Unknown Response: ".$data);
571
							break;
572
					}
573
					break;
574
				case 'easydns':
575
					if (preg_match('/NOACCESS/i', $data)) {
576
						$status = "phpDynDNS: (Error) Authentication Failed: Username and/or Password was Incorrect.";
577
					} else if (preg_match('/NOSERVICE/i', $data)) {
578
						$status = "phpDynDNS: (Error) No Service: Dynamic DNS Service has been disabled for this domain.";
579
					} else if (preg_match('/ILLEGAL INPUT/i', $data)) {
580
						$status = "phpDynDNS: (Error) Illegal Input: Self-Explantory";
581
					} else if (preg_match('/TOOSOON/i', $data)) {
582
						$status = "phpDynDNS: (Error) Too Soon: Not Enough Time Has Elapsed Since Last Update";
583
					} else if (preg_match('/NOERROR/i', $data)) {
584
						$status = "phpDynDNS: (Success) IP Updated Successfully!";
585
						$successful_update = true;
586
					} else {
587
						$status = "phpDynDNS: (Unknown Response)";
588
						log_error("phpDynDNS: PAYLOAD: {$data}");
589
						$this->_debug($data);
590
					}
591
					break;
592
				case 'hn':
593
					/* FIXME: add checks */
594
					break;
595
				case 'zoneedit':
596
					if (preg_match('/799/i', $data)) {
597
						$status = "phpDynDNS: (Error 799) Update Failed!";				
598
					} else if (preg_match('/700/i', $data)) {
599
						$status = "phpDynDNS: (Error 700) Update Failed!";
600
					} else if (preg_match('/200/i', $data)) {
601
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
602
						$successful_update = true;
603
					} else if (preg_match('/201/i', $data)) {
604
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
605
						$successful_update = true;						
606
					} else {
607
						$status = "phpDynDNS: (Unknown Response)";
608
						log_error("phpDynDNS: PAYLOAD: {$data}");
609
						$this->_debug($data);
610
					}
611
					break;
612
				case 'dyns':
613
					if (preg_match("/400/i", $data)) {
614
						$status = "phpDynDNS: (Error) Bad Request - The URL was malformed. Required parameters were not provided.";
615
					} else if (preg_match('/402/i', $data)) {
616
						$status = "phpDynDNS: (Error) Update Too Soon - You have tried updating to quickly since last change.";
617
					} else if (preg_match('/403/i', $data)) {
618
						$status = "phpDynDNS: (Error) Database Error - There was a server-sided database error.";
619
					} else if (preg_match('/405/i', $data)) {
620
						$status = "phpDynDNS: (Error) Hostname Error - The hostname (".$this->_dnsHost.") doesn't belong to you.";
621
					} else if (preg_match('/200/i', $data)) {
622
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
623
						$successful_update = true;
624
					} else {
625
						$status = "phpDynDNS: (Unknown Response)";
626
						log_error("phpDynDNS: PAYLOAD: {$data}");
627
						$this->_debug($data);
628
					}
629
					break;
630
				case 'ods':
631
					if (preg_match("/299/i", $data)) {
632
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
633
						$successful_update = true;
634
					} else {
635
						$status = "phpDynDNS: (Unknown Response)";
636
						log_error("phpDynDNS: PAYLOAD: {$data}");
637
						$this->_debug($data);
638
					}
639
					break;
640
				case 'freedns':
641
					if (preg_match("/has not changed./i", $data)) {
642
						$status = "phpDynDNS: (Success) No Change In IP Address";
643
						$successful_update = true;
644
					} else if (preg_match("/Updated/i", $data)) {
645
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
646
						$successful_update = true;
647
					} else {
648
						$status = "phpDynDNS: (Unknown Response)";
649
						log_error("phpDynDNS: PAYLOAD: {$data}");
650
						$this->_debug($data);
651
					} 
652
					break;
653
				case 'dnsexit':
654
					if (preg_match("/is the same/i", $data)) {
655
						$status = "phpDynDns: (Success) No Change In IP Address";
656
						$successful_update = true;
657
					} else if (preg_match("/Success/i", $data)) {
658
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
659
						$successful_update = true;
660
					} else {
661
						$status = "phpDynDNS: (Unknown Response)";
662
                                                log_error("phpDynDNS: PAYLOAD: {$data}");
663
                                                $this->_debug($data);
664
					}
665
					break;
666
				case 'loopia':
667
					if (preg_match("/nochg/i", $data)) {
668
						$status = "phpDynDNS: (Success) No Change In IP Address";
669
						$successful_update = true;
670
					} else if (preg_match("/good/i", $data)) {
671
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
672
						$successful_update = true;
673
					} else if (preg_match('/badauth/i', $data)) {
674
						$status = "phpDynDNS: (Error) User Authorization Failed";
675
					} else {
676
						$status = "phpDynDNS: (Unknown Response)";
677
						log_error("phpDynDNS: PAYLOAD: {$data}");
678
						$this->_debug($data);
679
					}
680
					break;
681
				case 'opendns':
682
					if (preg_match('/badauth/i', $data)) {
683
						$status = "phpDynDNS: (Error) Not a valid username or password!";
684
					} else if (preg_match('/nohost/i', $data)) {
685
						$status = "phpDynDNS: (Error) Hostname you are trying to update does not exist.";
686
						$successful_update = true;
687
					} else if (preg_match('/good/i', $data)) {
688
						$status = "phpDynDNS: (Success) IP Address Changed Successfully! (".$this->_dnsIP.")";
689
						$successful_update = true;
690
					} else if (preg_match('/yours/i', $data)) {
691
						$status = "phpDynDNS: (Error) hostname specified exists, but not under the username specified.";
692
					} else if (preg_match('/abuse/i', $data)) {
693
						$status = "phpDynDns: (Error) Updating to frequently, considered abuse.";
694
					} else {
695
						$status = "phpDynDNS: (Unknown Response)";
696
						log_error("phpDynDNS: PAYLOAD: {$data}");
697
						$this->_debug($data);
698
					}
699
					break;
700
                 case 'staticcling':
701
					if (preg_match("/invalid ip/i", $data)) {
702
					        $status = "phpDynDNS: (Error) Bad Request - The IP provided was invalid.";
703
					} else if (preg_match('/required info missing/i', $data)) {
704
					        $status = "phpDynDNS: (Error) Bad Request - Required parameters were not provided.";
705
					} else if (preg_match('/invalid characters/i', $data)) {
706
					        $status = "phpDynDNS: (Error) Bad Request - Illegal characters in either the username or the password.";
707
					} else if (preg_match('/bad password/i', $data)) {
708
					        $status = "phpDynDNS: (Error) Invalid password.";
709
					} else if (preg_match('/account locked/i', $data)) {
710
					        $status = "phpDynDNS: (Error) This account has been administratively locked.";
711
					} else if (preg_match('/update too frequent/i', $data)) {
712
					        $status = "phpDynDNS: (Error) Updating too frequently.";
713
					} else if (preg_match('/DB error/i', $data)) {
714
					        $status = "phpDynDNS: (Error) Server side error.";
715
					} else if (preg_match('/success/i', $data)) {
716
					        $status = "phpDynDNS: (Success) IP Address Updated Successfully!";
717
					        $successful_update = true;
718
					} else {
719
					        $status = "phpDynDNS: (Unknown Response)";
720
					        log_error("phpDynDNS: PAYLOAD: {$data}");
721
					        $this->_debug($data);
722
					}
723
					break;
724
				case 'namecheap':
725
					$tmp = str_replace("^M", "", $data);
726
					$ncresponse = @xml2array($tmp);
727
					if (preg_match("/internal server error/i", $data)) {
728
						$status = "phpDynDNS: (Error) Server side error.";
729
					} else if ($ncresponse['interface-response']['ErrCount'] === "0") {
730
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
731
						$successful_update = true;
732
					} else if (is_numeric($ncresponse['interface-response']['ErrCount']) && ($ncresponse['interface-response']['ErrCount'] > 0)) {
733
						$status = "phpDynDNS: (Error) " . implode(", ", $ncresponse["interface-response"]["errors"]);
734
						$successful_update = true;
735
					} else {
736
						$status = "phpDynDNS: (Unknown Response)";
737
						log_error("phpDynDNS: PAYLOAD: {$data}");
738
						$this->_debug($data);
739
					}
740
					break;
741
					
742
				case 'he-net':
743
					if (preg_match("/badip/i", $data)) {
744
					        $status = "phpDynDNS: (Error) Bad Request - The IP provided was invalid.";
745
					} else if (preg_match('/nohost/i', $data)) {
746
					        $status = "phpDynDNS: (Error) Bad Request - A hostname was not provided.";
747
					} else if (preg_match('/badauth/i', $data)) {
748
					        $status = "phpDynDNS: (Error) Invalid username or password.";
749
					} else if (preg_match('/good/i', $data)) {
750
					        $status = "phpDynDNS: (Success) IP Address Updated Successfully!";
751
					        $successful_update = true;
752
					} else if (preg_match('/nochg/i', $data)) {
753
							$status = "phpDynDNS: (Success) No Change In IP Address.";
754
							$successful_update = true;
755
					} else {
756
					        $status = "phpDynDNS: (Unknown Response)";
757
					        log_error("phpDynDNS: PAYLOAD: {$data}");
758
					        $this->_debug($data);
759
					}
760
					break;
761
				case 'he-net-tunnelbroker':
762
					/*
763
					-ERROR: Missing parameter(s).
764
					-ERROR: Invalid API key or password
765
					-ERROR: Tunnel not found
766
					-ERROR: Another tunnel exists for this IP.
767
					-ERROR: This tunnel is already associated with this IP address
768
					+OK: Tunnel endpoint updated to: x.x.x.x
769
					*/
770
					if (preg_match("/Missing parameter/i", $data)) {
771
					        $status = "phpDynDNS: (Error) Bad Request - Missing/Invalid Parameters.";
772
					} else if (preg_match('/Tunnel not found/i', $data)) {
773
					        $status = "phpDynDNS: (Error) Bad Request - Invalid Tunnel ID.";
774
					} else if (preg_match('/Invalid API key or password/i', $data)) {
775
					        $status = "phpDynDNS: (Error) Invalid username or password.";
776
					} else if (preg_match('/OK:/i', $data)) {
777
					        $status = "phpDynDNS: (Success) IP Address Updated Successfully!";
778
					        $successful_update = true;
779
					} else if (preg_match('/This tunnel is already associated with this IP address/i', $data)) {
780
							$status = "phpDynDNS: (Success) No Change In IP Address.";
781
							$successful_update = true;
782
					} else {
783
					        $status = "phpDynDNS: (Unknown Response)";
784
					        log_error("phpDynDNS: PAYLOAD: {$data}");
785
					        $this->_debug($data);
786
					}
787
					break;
788
			}
789
			
790
			if($successful_update == true) {
791
				/* Write WAN IP to cache file */
792
				$wan_ip = $this->_checkIP();
793
				conf_mount_rw();
794
				if ($wan_ip > 0) {
795
					$currentTime = time();				  
796
					log_error("phpDynDNS: updating cache file {$this->_cacheFile}: {$wan_ip}");
797
					@file_put_contents($this->_cacheFile, "{$wan_ip}:{$currentTime}");
798
				} else
799
					@unlink($this->_cacheFile);
800
				conf_mount_ro();
801
			}
802
			$this->status = $status;
803
			log_error($status);
804
		}
805

    
806
		/*
807
		 * Private Function (added 12 July 05) [beta]
808
		 *   Return Error, Set Last Error, and Die.
809
		 */
810
		function _error($errorNumber = '1') {
811
			switch ($errorNumber) {
812
				case 0:
813
					break;
814
				case 2:
815
					$error = 'phpDynDNS: (ERROR!) No Dynamic DNS Service provider was selected.';
816
					break;
817
				case 3:
818
					$error = 'phpDynDNS: (ERROR!) No Username Provided.';
819
					break;
820
				case 4:
821
					$error = 'phpDynDNS: (ERROR!) No Password Provided.';
822
					break;
823
				case 5:
824
					$error = 'phpDynDNS: (ERROR!) No Hostname Provided.';
825
					break;
826
				case 6:
827
					$error = 'phpDynDNS: (ERROR!) The Dynamic DNS Service provided is not yet supported.';
828
					break;
829
				case 7:
830
					$error = 'phpDynDNS: (ERROR!) No Update URL Provided.';
831
					break;
832
				case 10:
833
					$error = 'phpDynDNS: No change in my IP address and/or 25 days has not passed. Not updating dynamic DNS entry.';
834
					break;
835
				default:
836
					$error = "phpDynDNS: (ERROR!) Unknown Response.";
837
					/* FIXME: $data isn't in scope here */
838
					/* $this->_debug($data); */
839
					break;
840
			}
841
			$this->lastError = $error;
842
			log_error($error);
843
		}
844

    
845
		/*
846
		 * Private Function (added 12 July 05) [beta]
847
		 *   - Detect whether or not IP needs to be updated.
848
		 *      | Written Specifically for pfSense (pfsense.com) may
849
		 *      | work with other systems. pfSense base is FreeBSD.
850
		 */
851
		function _detectChange() {
852
			global $debug;
853

    
854
			if ($debug)
855
				log_error("DynDns: _detectChange() starting.");
856
		
857
			$currentTime = time();
858

    
859
			$wan_ip = $this->_checkIP();
860
			if ($wan_ip == 0) {
861
				log_error("DynDns: Current WAN IP could not be determined, skipping update process.");
862
				return false;
863
			}
864
			$this->_dnsIP = $wan_ip;
865
			$log_error = "DynDns: Current WAN IP: {$wan_ip} ";
866

    
867
			if (file_exists($this->_cacheFile)) {
868
				$contents = file_get_contents($this->_cacheFile);
869
				list($cacheIP,$cacheTime) = split(':', $contents);
870
				$this->_debug($cacheIP.'/'.$cacheTime);
871
				$initial = false;
872
				$log_error .= "Cached IP: {$cacheIP} ";
873
			} else {
874
				conf_mount_rw();
875
				$cacheIP = '0.0.0.0';
876
				@file_put_contents($this->_cacheFile, "0.0.0.0:{$currentTime}");
877
				conf_mount_ro();
878
				$cacheTime = $currentTime;
879
				$initial = true;
880
				$log_error .= "No Cached IP found.";
881
			}
882
			log_error($log_error);
883

    
884
			/*   use 2419200 for dyndns, dhs, easydns, noip, hn
885
			 *   zoneedit, dyns, ods
886
			 */
887
			$time = '2160000';
888

    
889
			$needs_updating = FALSE;
890
			/* lets determine if the item needs updating */
891
			if ($cacheIP != $wan_ip) {
892
				$needs_updating = true;
893
				$update_reason = "DynDns: cacheIP != wan_ip.  Updating. ";
894
				$update_reason .= "Cached IP: {$cacheIP} WAN IP: {$wan_ip} ";
895
			}
896
			if (($currentTime - $cacheTime) > $time ) {
897
				$needs_updating = true;
898
				$update_reason = "DynDns: More than 25 days.  Updating. ";
899
				$update_reason .= "{$currentTime} - {$cacheTime} > {$time} ";
900
			}
901
			if ($initial == true) {
902
				$needs_updating = true;
903
				$update_reason .= "Inital update. ";
904
			}
905

    
906
			/*   finally if we need updating then store the
907
			 *   new cache value and return true
908
                         */
909
			if ($needs_updating == true) {
910
				log_error("DynDns debug information: {$update_reason}");
911
				return true;
912
			}
913

    
914
			return false;			
915
		}
916

    
917
		/*
918
		 * Private Funcation (added 16 July 05) [beta]
919
		 *   - Writes debug information to a file.
920
		 *   - This function is only called when a unknown response
921
		 *   - status is returned from a DynDNS service provider.
922
		 */
923
		function _debug ($data) {
924
			$string = '\n'.date('m-d-y h:i:s').' - ('.$this->_debugID.') - ['.$this->_dnsService.'] - '.$data.'\n';
925
			conf_mount_rw();
926
			$file = fopen($this->_debugFile, 'a');
927
			fwrite($file, $string);
928
			fclose($file);
929
			conf_mount_ro();
930
		}
931
		function _checkIP() {
932
			global $debug;
933

    
934
			if ($debug)
935
				log_error("DynDns: _checkIP() starting.");
936

    
937
			$ip_address = find_interface_ip($this->_if);
938
			if (!is_ipaddr($ip_address))
939
				return 0;
940
			$this->_ifIP = $ip_address;
941
			if (is_private_ip($ip_address)) {
942
				$hosttocheck = "checkip.dyndns.org";
943
				$try = 0;
944
				while ($try < 3) {
945
					$checkip = gethostbyname($hosttocheck);
946
					if (is_ipaddr($checkip))
947
						break;
948
					$try++;
949
				}
950
				if ($try >= 3) {
951
					log_error("Dyndns debug information: Could not resolve {$hosttocheck} to ip using interface ip {$ip_address}.");
952
					return 0;
953
				}
954
				$ip_ch = curl_init("http://{$checkip}");
955
				curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
956
				curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
957
				curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
958
				curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
959
				curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
960
				$ip_result_page = curl_exec($ip_ch);
961
				curl_close($ip_ch);
962
				$ip_result_decoded = urldecode($ip_result_page);
963
				preg_match('/Current IP Address: (.*)<\/body>/', $ip_result_decoded, $matches);
964
				$ip_address = trim($matches[1]);
965
				if (is_ipaddr($ip_address))
966
					log_error("DynDns debug information: {$ip_address} extracted from {$hosttocheck}");
967
				else {
968
					log_error("DynDns debug information: IP address could not be extracted from {$hosttocheck}");
969
					return 0;
970
				}
971
			} else
972
				log_error("DynDns debug information: {$ip_address} extracted from local system.");
973

    
974
			return $ip_address;
975
		}
976

    
977
	}
978

    
979
?>
(17-17/61)