Project

General

Profile

Download (18.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?
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)
13
	 *    - DynS (dyns.org)
14
	 *    - ZoneEdit (zoneedit.com)
15
	 * +----------------------------------------------------+
16
	 *  Requirements:
17
	 *    - PHP version 4.0.2 or higher with CURL Library
18
	 * +----------------------------------------------------+
19
	 *  Public Functions
20
	 *    - updatedns()
21
	 *
22
	 *  Private Functions
23
	 *    - _update()
24
	 *    - _checkStatus()
25
	 *    - _error()
26
	 *    - _detectChange()
27
	 *    - _debug()
28
	 * +----------------------------------------------------+
29
	 *  DynDNS Dynamic - Last Tested: 12 July 2005
30
	 *  DynDNS Static  - Last Tested: NEVER
31
	 *  DynDNS Custom  - Last Tested: NEVER
32
	 *  No-IP          - Last Tested: 12 July 2005
33
	 *  HN.org         - Last Tested: 12 July 2005
34
	 *  EasyDNS        - Last Tested: NEVER
35
	 *  DHS            - Last Tested: 12 July 2005
36
	 *  ZoneEdit       - Last Tested: NEVER
37
	 *  Dyns           - Last Tested: NEVER
38
	 * +====================================================+
39
	 *
40
	 * @author 		E.Kristensen
41
	 * @link    	http://www.idylldesigns.com/projects/phpdns/
42
	 * @version 	0.7
43
	 * @updated		1 August 05 at 21:02:42 GMT
44
	 *
45
	 */
46

    
47
	class updatedns {
48
		var $_cacheFile = '/var/etc/dyndns.cache';
49
		var $_debugFile = '/var/etc/dyndns.debug';
50
		var $_UserAgent = 'User-Agent: phpDynDNS/0.7';
51
		var $_errorVerbosity = 0;
52
		var $_dnsService;
53
		var $_dnsUser;
54
		var $_dnsPass;
55
		var $_dnsHost;
56
		var $_dnsIP;
57
		var $_dnsWildcard;
58
		var $_dnsMX;
59
		var $_dnsBackMX;
60
		var $status;
61

    
62
		/* 
63
		 * Public Constructor Function (added 12 July 05) [beta]
64
		 *   - Gets the dice rolling for the update. 
65
		 */
66
		function updatedns ($dnsService = '', $dnsHost = '', $dnsUser = '', $dnsPass = '', $dnsWildcard = 'OFF', $dnsMX = '', $dnsBackMX = '') {
67
			if (!$dnsService) $this->_error(2);
68
			if (!$dnsUser) $this->_error(3);
69
			if (!$dnsPass) $this->_error(4);
70
			if (!$dnsHost) $this->_error(5);
71

    
72
			$this->_dnsService = strtolower($dnsService);
73
			$this->_dnsUser = $dnsUser;
74
			$this->_dnsPass = $dnsPass;
75
			$this->_dnsHost = $dnsHost;
76
			$this->_dnsIP = $dnsIP;
77

    
78
			if ($this->_detectChange() == FALSE) {
79
				$this->_error(10);
80
			} else {
81
				if ($this->_dnsService == 'dyndns' ||
82
					$this->_dnsService == 'dyndns-static' ||
83
					$this->_dnsService == 'dyndns-custom' ||
84
					$this->_dnsService == 'dhs' ||
85
					$this->_dnsService == 'noip' ||
86
					$this->_dnsService == 'easydns' ||
87
					$this->_dnsService == 'hn' ||
88
					$this->_dnsService == 'zoneedit' ||
89
					$this->_dnsService == 'dyns' ||
90
					$this->_dnsService == 'ods')
91
				{
92
					$this->_update();
93
				} else {
94
					$this->_error(6);
95
				}
96
			}
97

    
98
		}
99

    
100

    
101
		/*
102
		 * Private Function (added 12 July 05) [beta]
103
		 *   Send Update To Selected Service.
104
		 */
105
		function _update() {
106
			if ($this->_dnsService != 'ods') {
107
				$ch = curl_init();
108
				curl_setopt($ch, CURLOPT_HEADER, 0);
109
				curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
110
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
111
			}
112

    
113
			switch ($this->_dnsService) {
114
				case 'dyndns':
115
					$needsIP = FALSE;
116
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
117
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
118
					curl_setopt($ch, CURLOPT_URL, 'https://members.dyndns.org/nic/update?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP.'&wildcard='.$this->_dnsWildcard.'&mx='.$this->_dnsMX.'&backmx=NO');
119
					$data = curl_exec($ch);
120
					curl_close($ch);
121
					$this->_checkStatus($data);
122
					break;
123
				case 'dyndns-static':
124
					$needsIP = FALSE;
125
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
126
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
127
					curl_setopt($ch, CURLOPT_URL, 'https://members.dyndns.org/nic/update?system=statdns&hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP.'&wildcard='.$this->_dnsWildcard.'&mx='.$this->_dnsMX.'&backmx=NO');
128
					$data = curl_exec($ch);
129
					curl_close($ch);
130
					$this->_checkStatus($data);
131
					break;
132
				case 'dyndns-custom':
133
					$needsIP = FALSE;
134
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
135
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
136
					curl_setopt($ch, CURLOPT_URL, 'https://members.dyndns.org/nic/update?system=custom&hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP.'&wildcard='.$this->_dnsWildcard.'&mx='.$this->_dnsMX.'&backmx=NO');
137
					$data = curl_exec($ch);
138
					curl_close($ch);
139
					$this->_checkStatus($data);
140
					break;
141
				case 'dhs':
142
					$needsIP = TRUE;
143
						$post_data['hostscmd'] = 'edit';
144
						$post_data['hostscmdstage'] = '2';
145
						$post_data['type'] = '4';
146
						$post_data['updatetype'] = 'Online';
147
						$post_data['mx'] = $this->_dnsMX;
148
						$post_data['mx2'] = '';
149
						$post_data['txt'] = '';
150
						$post_data['offline_url'] = '';
151
						$post_data['cloak'] = 'Y';
152
						$post_data['cloak_title'] = '';
153
						$post_data['ip'] = $this->_dnsIP;
154
						$post_data['domain'] = 'dyn.dhs.org';
155
						$post_data['hostname'] = $this->_dnsHost;
156
						$post_data['submit'] = 'Update';
157
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
158
					curl_setopt($ch, CURLOPT_URL, 'https://members.dhs.org/nic/hosts');
159
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
160
					curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
161
					$data = curl_exec($ch);
162
					curl_close($ch);
163
					$this->_checkStatus($data);
164
					break;
165
				case 'noip':
166
					$needsIP = TRUE;
167
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
168
					curl_setopt($ch, CURLOPT_URL, 'http://dynupdate.no-ip.com/dns?username='.$this->_dnsUser.'&password='.$this->_dnsPass.'&hostname='.$this->_dnsHost.'&ip='.$this->_dnsIP);
169
					$data = curl_exec($ch);
170
					curl_close($ch);
171
					$this->_checkStatus($data);
172
					break;
173
				case 'easydns':
174
					$needsIP = TRUE;
175
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
176
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
177
					curl_setopt($ch, CURLOPT_URL, 'http://members.easydns.com/dyn/dyndns.php?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP.'&wildcard='.$this->_dnsWildcard.'&mx='.$this->_dnsMX.'&backmx='.$this->_dnsBackMX);
178
					$data = curl_exec($ch);
179
					curl_close($ch);
180
					$this->_checkStatus($data);
181
					break;
182
				case 'hn':
183
					$needsIP = TRUE;
184
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
185
					curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
186
					curl_setopt($ch, CURLOPT_URL, 'http://dup.hn.org/vanity/update?ver=1&IP='.$this->_dnsIP);
187
					$data = curl_exec($ch);
188
					curl_close($ch);
189
					$this->_checkStatus($data);
190
					break;
191
				case 'zoneedit':
192
					$needsIP = FALSE;
193
					curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
194
					curl_setopt($ch, CURLOPT_URL, 'https://dynamic.zoneedit.com/auth/dynamic.html?host='.$this->_dnsHost.'&dnsto='.$this->_dnsIP);
195
					$data = curl_exec($ch);
196
					curl_close($ch);
197
					$this->_checkStatus($data);
198
					break;
199
				case 'dyns':
200
					$needsIP = FALSE;
201
					curl_setopt($ch, CURLOPT_URL, 'http://www.dyns.cx/postscript011.php?username='.$this->_dnsUser.'&password='.$this->_dnsPass.'&host='.$this->_dnsHost);
202
					$data = curl_exec($ch);
203
					curl_close($ch);
204
					$this->_checkStatus($data);
205
					break;
206
				case 'ods':
207
					$needsIP = FALSE;
208
					$this->con['socket'] = fsockopen("ods.org", "7070");
209
					/* Check that we have connected */
210
					if (!$this->con['socket']) {
211
						print "error! could not connect.";
212
						break;
213
					}
214
					/* Here is the loop. Read the incoming data (from the socket connection) */
215
					while (!feof($this->con['socket'])) {
216
						$this->con['buffer']['all'] = trim(fgets($this->con['socket'], 4096));
217
						$code = substr($this->con['buffer']['all'], 0, 3);
218
						sleep(1);
219
						switch($code) {
220
							case 100:
221
								fputs($this->con['socket'], "LOGIN ".$this->_dnsUser." ".$this->_dnsPass."\n");
222
								break;
223
							case 225:
224
								fputs($this->con['socket'], "DELRR ".$this->_dnsHost." A\n");
225
								break;
226
							case 901:
227
								fputs($this->con['socket'], "ADDRR ".$this->_dnsHost." A ".$this->_dnsIP."\n");
228
								break;
229
							case 795:
230
								fputs($this->con['socket'], "QUIT\n");
231
								break;
232
						}
233
					}
234
					$this->_checkStatus($code);
235
					break;
236
				default:
237
					break;
238
			}
239
		}
240

    
241

    
242
		/*
243
		 * Private Function (added 12 July 2005) [beta]
244
		 *   Retrieve Update Status
245
		 */
246
		function _checkStatus($data) {
247
			switch ($this->_dnsService) {
248
				case 'dyndns':
249
					if (preg_match('/notfqdn/i', $data)) {
250
						$status = "phpDynDNS: (Error) Not A FQDN!";
251
					} else if (preg_match('/nochg/i', $data)) {
252
						$status = "phpDynDNS: (Success) No Change In IP Address";
253
					} else if (preg_match('/good/i', $data)) {
254
						$status = "phpDynDNS: (Success) IP Address Changed Successfully! (".$this->_dnsIP.")";
255
					} else if (preg_match('/noauth/i', $data)) {
256
						$status = "phpDynDNS: (Error) User Authorization Failed";
257
					} else {
258
						$status = "phpDynDNS: (Unknown Response)";
259
						$this->_debug($data);
260
					}
261
					break;
262
				case 'dyndns-static':
263
					if (preg_match('/notfqdn/i', $data)) {
264
						$status = "phpDynDNS: (Error) Not A FQDN!";
265
					} else if (preg_match('/nochg/i', $data)) {
266
						$status = "phpDynDNS: (Success) No Change In IP Address";
267
					} else if (preg_match('/good/i', $data)) {
268
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
269
					} else if (preg_match('/noauth/i', $data)) {
270
						$status = "phpDynDNS: (Error) User Authorization Failed";
271
					} else {
272
						$status = "phpDynDNS: (Unknown Response)";
273
						$this->_debug($data);
274
					}
275
					break;
276
				case 'dyndns-custom':
277
					if (preg_match('/notfqdn/i', $data)) {
278
						$status = "phpDynDNS: (Error) Not A FQDN!";
279
					} else if (preg_match('/nochg/i', $data)) {
280
						$status = "phpDynDNS: (Success) No Change In IP Address";
281
					} else if (preg_match('/good/i', $data)) {
282
						$status = "phpDynDNS: (Success) IP Address Changed Successfully!";
283
					} else if (preg_match('/noauth/i', $data)) {
284
						$status = "phpDynDNS: (Error) User Authorization Failed";
285
					} else {
286
						$status = "phpDynDNS: (Unknown Response)";
287
						$this->_debug($data);
288
					}
289
					break;
290
				case 'dhs':
291
					break;
292
				case 'noip':
293
					list($ip,$code) = split(":",$data);
294
					switch ($code) {
295
						case 0:
296
							$status = "phpDynDNS: (Success) IP address is current, no update performed.";
297
							break;
298
						case 1:
299
							$status = "phpDynDNS: (Success) DNS hostname update successful.";
300
							break;
301
						case 2:
302
							$status = "phpDynDNS: (Error) Hostname supplied does not exist.";
303
							break;
304
						case 3:
305
							$status = "phpDynDNS: (Error) Invalid Username.";
306
							break;
307
						case 4:
308
							$status = "phpDynDNS: (Error) Invalid Password.";
309
							break;
310
						case 5:
311
							$status = "phpDynDNS: (Error) To many updates sent.";
312
							break;
313
						case 6:
314
							$status = "phpDynDNS: (Error) Account disabled due to violation of No-IP terms of service.";
315
							break;
316
						case 7:
317
							$status = "phpDynDNS: (Error) Invalid IP. IP Address submitted is improperly formatted or is a private IP address or is on a blacklist.";
318
							break;
319
						case 8:
320
							$status = "phpDynDNS: (Error) Disabled / Locked Hostname.";
321
							break;
322
						case 9:
323
							$status = "phpDynDNS: (Error) Host updated is configured as a web redirect and no update was performed.";
324
							break;
325
						case 10:
326
							$status = "phpDynDNS: (Error) Group supplied does not exist.";
327
							break;
328
						case 11:
329
							$status = "phpDynDNS: (Success) DNS group update is successful.";
330
							break;
331
						case 12:
332
							$status = "phpDynDNS: (Success) DNS group is current, no update performed.";
333
							break;
334
						case 13:
335
							$status = "phpDynDNS: (Error) Update client support not available for supplied hostname or group.";
336
							break;
337
						case 14:
338
							$status = "phpDynDNS: (Error) Hostname supplied does not have offline settings configured.";
339
							break;
340
						case 99:
341
							$status = "phpDynDNS: (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
342
							break;
343
						case 100:
344
							$status = "phpDynDNS: (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
345
							break;
346
						default:
347
							$status = "phpDynDNS: (Unknown Response)";
348
							$this->_debug($data);
349
							break;
350
					}
351
					break;
352
				case 'easydns':
353
					if (preg_match('/NOACCESS/i', $data)) {
354
						$status = "phpDynDNS: (Error) Authentication Failed: Username and/or Password was Incorrect.";
355
					} else if (preg_match('/NOSERVICE/i', $data)) {
356
						$status = "phpDynDNS: (Error) No Service: Dynamic DNS Service has been disabled for this domain.";
357
					} else if (preg_match('/ILLEGAL INPUT/i', $data)) {
358
						$status = "phpDynDNS: (Error) Illegal Input: Self-Explantory";
359
					} else if (preg_match('/TOOSOON/i', $data)) {
360
						$status = "phpDynDNS: (Error) Too Soon: Not Enough Time Has Elapsed Since Last Update";
361
					} else if (preg_match('/NOERROR/i', $data)) {
362
						$status = "phpDynDNS: (Success) IP Updated Successfully!";					
363
					} else {
364
						$status = "phpDynDNS: (Unknown Response)";
365
						$this->_debug($data);
366
					}
367
					break;
368
				case 'hn':
369
					break;
370
				case 'zoneedit':
371
					if (preg_match('/{700,799}/i', $data)) {
372
						$status = "phpDynDNS: (Error) Update Failed!";
373
					} else if (preg_match('/{200,201}/i', $data)) {
374
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
375
					} else {
376
						$status = "phpDynDNS: (Unknown Response)";
377
						$this->_debug($data);
378
					}
379
					break;
380
				case 'dyns':
381
					if (preg_match("/400/i", $data)) {
382
						$status = "phpDynDNS: (Error) Bad Request - The URL was malformed. Required parameters were not provided.";
383
					} else if (preg_match('/402/i', $data)) {
384
						$status = "phpDynDNS: (Error) Update Too Soon - You have tried updating to quickly since last change.";
385
					} else if (preg_match('/403/i', $data)) {
386
						$status = "phpDynDNS: (Error) Database Error - There was a server-sided database error.";
387
					} else if (preg_match('/405/i', $data)) {
388
						$status = "phpDynDNS: (Error) Hostname Error - The hostname (".$this->_dnsHost.") doesn't belong to you.";
389
					} else if (preg_match('/200/i', $data)) {
390
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
391
					} else {
392
						$status = "phpDynDNS: (Unknown Response)";
393
						$this->_debug($data);
394
					}
395
					break;
396
				case 'ods':
397
					if (preg_match("/299/i", $data)) {
398
						$status = "phpDynDNS: (Success) IP Address Updated Successfully!";
399
					} else {
400
						$status = "phpDynDNS: (Unknown Response)";
401
						$this->_debug($data);
402
					}
403
					break;
404
			}
405
			$this->status = $status;
406
			log_error($status);
407
		}
408

    
409

    
410
		/*
411
		 * Private Function (added 12 July 05) [beta]
412
		 *   Return Error, Set Last Error, and Die.
413
		 */
414
		function _error($errorNumber = '1') {
415
			switch ($errorNumber) {
416
				case 0:
417
					break;
418
				case 2:
419
					$error = 'phpDynDNS: (ERROR!) No Dynamic DNS Service provider was selected.';
420
					break;
421
				case 3:
422
					$error = 'phpDynDNS: (ERROR!) No Username Provided.';
423
					break;
424
				case 4:
425
					$error = 'phpDynDNS: (ERROR!) No Password Provided.';
426
					break;
427
				case 5:
428
					$error = 'phpDynDNS: (ERROR!) No Hostname Provided.';
429
					break;
430
				case 6:
431
					$error = 'phpDynDNS: (ERROR!) The Dynamic DNS Service provided is not yet supported.';
432
					break;
433
				case 10:
434
					$error = 'phpDynDNS: No Change In My IP Address and/or 28 Days Has Not Past. Not Updating Dynamic DNS Entry.';
435
					break;
436
				default:
437
					$error = "phpDynDNS: (ERROR!) Unknown Response.";
438
					$this->_debug($data);
439
					break;
440
			}
441
			$this->lastError = $error;
442
			log_error($error);
443
		}
444

    
445

    
446
		/*
447
		 * Private Function (added 12 July 05) [beta]
448
		 *   - Detect whether or not IP needs to be updated.
449
		 *      | Written Specifically for pfSense (pfsense.com) may
450
		 *      | work with other systems. pfSense base is FreeBSD.
451
		 */
452
		function _detectChange() {
453
			$currentTime = time();
454

    
455
			#$wan_if = get_real_wan_interface();
456
			#$wan_ip = find_interface_ip($wan_if);
457
			$wan_ip = get_current_wan_address();
458
			$this->_dnsIP = $wan_ip;
459

    
460
			if (file_exists($this->_cacheFile)) {
461
				$file = fopen($this->_cacheFile, 'r');
462
				$contents = fread($file, filesize($this->_cacheFile));
463
				fclose($file);
464
				list($cacheIP,$cacheTime) = split(':', $contents);
465
			} else {
466
				$file = fopen($this->_cacheFile, 'w');
467
				fwrite($file, '0.0.0.0:'.$currentTime);
468
				fclose($file);
469
				$cacheIP = '0.0.0.0';
470
				$cacheTime = $currentTime;
471
			}
472

    
473
			switch ($this->_dnsService) {
474
				case 'dyndns':
475
					$time = '2419200';
476
					break;
477
				case 'dyndns-static':
478
					$time = '2419200';
479
					break;
480
				case 'dyndns-custom':
481
					$time = '2419200';
482
					break;
483
				case 'dhs':
484
					$time = '2419200';
485
					break;
486
				case 'easydns':
487
					$time = '2419200';
488
					break;
489
				case 'noip':
490
					$time = '2419200';
491
					break;
492
				case 'hn':
493
					$time = '2419200';
494
					break;
495
				case 'zoneedit':
496
					$time = '2419200';
497
					break;
498
				case 'dyns':
499
					$time = '2419200';
500
					break;
501
				case 'ods':
502
					$time = '2419200';
503
					break;
504
			}
505

    
506
			/* If IP addresses are different or 28 days have passed update record */
507
			if ( ($cacheIP != $wan_ip) || ( ($currentTime - $cacheTime) > $time ) ) {
508
				/* Write WAN IP to cache file */
509
				$file = fopen($this->_cacheFile, 'w');
510
				fwrite($file, $wan_ip.':'.$currentTime);
511
				fclose($file);
512

    
513
				return TRUE;
514
			} else {
515

    
516
				return FALSE;
517
			}
518
		}
519

    
520

    
521
		/*
522
		 * Private Funcation (added 16 July 05) [beta]
523
		 *   - Writes debug information to a file.
524
		 *   - This function is only called when a unknown response
525
		 *   - status is returned from a DynDNS service provider.
526
		 */
527
		function _debug ($data) {
528
			$string = date('m-d-y h:i:s').' - ['.$this->_dnsService.'] - '.$data;
529
			$file = fopen($this->_debugFile, 'a');
530
			fwrite($file, $string);
531
			fclose($file);
532
		}
533

    
534
	}
535

    
536
?>
(4-4/23)