Projet

Général

Profil

Télécharger (71,6 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / services.inc @ 52c67bc2

1
<?php
2
/*
3
	services.inc
4
	part of the pfSense project (https://www.pfsense.org)
5

    
6
	originally part of m0n0wall (http://m0n0.ch/wall)
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	Copyright (C) 2010	Ermal Luci
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
/*
34
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/bin/pgrep	/bin/sh	/usr/local/sbin/dhcpd	/usr/local/sbin/igmpproxy
35
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig		/usr/local/sbin/dnsmasq
36
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/miniupnpd	/usr/sbin/radvd
37
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcleases6	/usr/sbin/bsnmpd
38
	pfSense_MODULE:	utils
39
*/
40

    
41
define('DYNDNS_PROVIDER_VALUES', 'dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip noip-free ods zoneedit loopia freedns dnsexit opendns namecheap he-net he-net-v6 he-net-tunnelbroker selfhost route53 custom custom-v6');
42
define('DYNDNS_PROVIDER_DESCRIPTIONS', 'DNS-O-Matic,DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,No-IP (free),ODS.org,ZoneEdit,Loopia,freeDNS,DNSexit,OpenDNS,Namecheap,HE.net,HE.net (v6),HE.net Tunnelbroker,SelfHost,Route 53,Custom,Custom (v6)');
43

    
44
/* implement ipv6 route advertising deamon */
45
function services_radvd_configure($blacklist = array()) {
46
	global $config, $g;
47
	
48
	if ($g['platform'] == 'jail') 
49
		return;
50

    
51
	if(isset($config['system']['developerspew'])) {
52
		$mt = microtime();
53
		echo "services_radvd_configure() being called $mt\n";
54
	}
55

    
56
	if (!is_array($config['dhcpdv6']))
57
		$config['dhcpdv6'] = array();
58

    
59
	$Iflist = get_configured_interface_list();
60
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
61
	$carplist = get_configured_carp_interface_list();
62

    
63
	$radvdconf = "# Automatically Generated, do not edit\n";
64

    
65
	/* Process all links which need the router advertise daemon */
66
	$radvdifs = array();
67

    
68
	/* handle manually configured DHCP6 server settings first */
69
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
70
		if (!is_array($config['interfaces'][$dhcpv6if]))
71
			continue;
72
		if (!isset($config['interfaces'][$dhcpv6if]['enable']))
73
			continue;
74

    
75
		/* Do not put in the config an interface which is down */
76
		if (isset($blacklist[$dhcpv6if]))
77
			continue;
78
		if (!isset($dhcpv6ifconf['ramode']))
79
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
80

    
81
		/* are router advertisements enabled? */
82
		if ($dhcpv6ifconf['ramode'] == "disabled")
83
			continue;
84

    
85
		if (!isset($dhcpv6ifconf['rapriority']))
86
			$dhcpv6ifconf['rapriority'] = "medium";
87

    
88
		/* always start with the real parent, we override with the carp if later */
89
		$carpif = false;
90
		/* check if we need to listen on a CARP interface */
91
		if (!empty($dhcpv6ifconf['rainterface'])) {
92
			if (!empty($carplist[$dhcpv6ifconf['rainterface']])) {
93
				$dhcpv6if = $dhcpv6ifconf['rainterface'];
94
				$carpif = true;
95
			}
96
		}
97

    
98
		$realif = get_real_interface($dhcpv6if, "inet6");
99
		if (isset($radvdifs[$realif]))
100
			continue;
101

    
102
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
103
		if (!is_ipaddrv6($ifcfgipv6))
104
			continue;
105

    
106
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
107
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
108
		$radvdifs[$realif] = $realif;
109

    
110
		$radvdconf .= "# Generated for DHCPv6 Server $dhcpv6if\n";
111
		$radvdconf .= "interface {$realif} {\n";
112
		$radvdconf .= "\tAdvSendAdvert on;\n";
113
		$radvdconf .= "\tMinRtrAdvInterval 5;\n";
114
		$radvdconf .= "\tMaxRtrAdvInterval 20;\n";
115
		$mtu = get_interface_mtu($realif);
116
		if (is_numeric($mtu))
117
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
118
		else
119
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
120
		// $radvdconf .= "\tDeprecatePrefix on;\n";
121
		switch($dhcpv6ifconf['rapriority']) {
122
			case "low":
123
				$radvdconf .= "\tAdvDefaultPreference low;\n";
124
				break;
125
			case "high":
126
				$radvdconf .= "\tAdvDefaultPreference high;\n";
127
				break;
128
			default:
129
				$radvdconf .= "\tAdvDefaultPreference medium;\n";
130
				break;
131
		}
132
		switch($dhcpv6ifconf['ramode']) {
133
			case "managed":
134
			case "assist":
135
				$radvdconf .= "\tAdvManagedFlag on;\n";
136
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
137
				break;
138
		}
139
		$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
140
		if($carpif == true) {
141
			$radvdconf .= "\t\tDeprecatePrefix off;\n";
142
		} else {
143
			$radvdconf .= "\t\tDeprecatePrefix on;\n";
144
		}
145
		switch($dhcpv6ifconf['ramode']) {
146
			case "managed":
147
				$radvdconf .= "\t\tAdvOnLink on;\n";
148
				$radvdconf .= "\t\tAdvAutonomous off;\n";
149
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
150
				break;
151
			case "router":
152
				$radvdconf .= "\t\tAdvOnLink off;\n";
153
				$radvdconf .= "\t\tAdvAutonomous off;\n";
154
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
155
				break;
156
			case "assist":
157
				$radvdconf .= "\t\tAdvOnLink on;\n";
158
				$radvdconf .= "\t\tAdvAutonomous on;\n";
159
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
160
				break;
161
			case "unmanaged":
162
				$radvdconf .= "\t\tAdvOnLink on;\n";
163
				$radvdconf .= "\t\tAdvAutonomous on;\n";
164
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
165
				break;				
166
		}
167
		$radvdconf .= "\t};\n";
168

    
169
		if($carpif === true) {
170
			$radvdconf .= "\troute ::/0 {\n";
171
			$radvdconf .= "\t\tRemoveRoute off;\n";
172
			$radvdconf .= "\t};\n";
173
		} else {
174
			$radvdconf .= "\troute ::/0 {\n";
175
			$radvdconf .= "\t\tRemoveRoute on;\n";
176
			$radvdconf .= "\t};\n";
177
		}
178

    
179
		/* add DNS servers */
180
		$dnslist = array();
181
		if (isset($dhcpv6ifconf['rasamednsasdhcp6']) && is_array($dhcpv6ifconf['dnsserver']) && !empty($dhcpv6ifconf['dnsserver'])) {
182
			foreach($dhcpv6ifconf['dnsserver'] as $server)
183
				if (is_ipaddrv6($server))
184
					$dnslist[] = $server;
185
		} elseif (!isset($dhcpv6ifconf['rasamednsasdhcp6']) && isset($dhcpv6ifconf['radnsserver']) && is_array($dhcpv6ifconf['radnsserver'])) {
186
			foreach($dhcpv6ifconf['radnsserver'] as $server)
187
				if (is_ipaddrv6($server))
188
					$dnslist[] = $server;
189
		} elseif (isset($config['dnsmasq']['enable'])) {
190
			$dnslist[] = get_interface_ipv6($realif);
191
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
192
			foreach($config['system']['dnsserver'] as $server) {
193
				if (is_ipaddrv6($server))
194
					$dnslist[] = $server;
195
			}
196
		}
197
		if (count($dnslist) > 0) {
198
			$dnsstring = implode(" ", $dnslist);
199
			if ($dnsstring <> "")
200
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
201
		}
202
		if (!empty($dhcpv6ifconf['domain'])) {
203
			$radvdconf .= "\tDNSSL {$dhcpv6ifconf['domain']} { };\n";
204
		} elseif (!empty($config['system']['domain'])) {
205
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
206
		}
207
		$radvdconf .= "};\n";
208
	}
209

    
210
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
211
	foreach ($Iflist as $if => $ifdescr) {
212
		if(!isset($config['interfaces'][$if]['track6-interface']))
213
			continue;
214
		if(!isset($config['interfaces'][$if]['enable']))
215
			continue;
216
		/* Do not put in the config an interface which is down */
217
		if (isset($blacklist[$if]))
218
			continue;
219
		$trackif = $config['interfaces'][$if]['track6-interface'];
220
		if (empty($config['interfaces'][$trackif]))
221
			continue;
222

    
223
		$realif = get_real_interface($if, "inet6");
224
		/* prevent duplicate entries, manual overrides */
225
		if (isset($radvdifs[$realif]))
226
			continue;
227

    
228
		$ifcfgipv6 = get_interface_ipv6($if);
229
		if(!is_ipaddrv6($ifcfgipv6)) {
230
			$subnetv6 = "::";
231
			$ifcfgsnv6 = "64";
232
		} else {
233
			$ifcfgsnv6 = get_interface_subnetv6($if);
234
			$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
235
		}
236
		$radvdifs[$realif] = $realif;
237

    
238
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
239
	
240
		if ($g['debug'])
241
			log_error("configuring RA on {$if} for type {$autotype} radvd subnet {$subnetv6}/{$ifcfgsnv6}");
242

    
243
		$radvdconf .= "# Generated config for {$autotype} delegation from {$trackif} on {$if}\n";
244
		$radvdconf .= "interface {$realif} {\n";
245
		$radvdconf .= "\tAdvSendAdvert on;\n";
246
		$radvdconf .= "\tMinRtrAdvInterval 3;\n";
247
		$radvdconf .= "\tMaxRtrAdvInterval 10;\n";
248
		$mtu = get_interface_mtu($realif);
249
		if (is_numeric($mtu))
250
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
251
		else
252
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
253
		$radvdconf .= "\tAdvOtherConfigFlag on;\n";
254
		$radvdconf .= "\t\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
255
		$radvdconf .= "\t\tAdvOnLink on;\n";
256
		$radvdconf .= "\t\tAdvAutonomous on;\n";
257
		$radvdconf .= "\t\tAdvRouterAddr on;\n";
258
		$radvdconf .= "\t};\n";
259

    
260
		/* add DNS servers */
261
		$dnslist = array();
262
		if (isset($config['dnsmasq']['enable'])) {
263
			$dnslist[] = $ifcfgipv6;
264
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
265
			foreach($config['system']['dnsserver'] as $server) {
266
				if(is_ipaddrv6($server))
267
					$dnslist[] = $server;
268
			}
269
		}
270
		if (count($dnslist) > 0) {
271
			$dnsstring = implode(" ", $dnslist);
272
			if (!empty($dnsstring))
273
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
274
		}
275
		if (!empty($config['system']['domain'])) {
276
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
277
		}
278
		$radvdconf .= "};\n";
279
	}
280

    
281
	/* write radvd.conf */
282
	if (!@file_put_contents("{$g['varetc_path']}/radvd.conf", $radvdconf)) {
283
		log_error("Error: cannot open radvd.conf in services_radvd_configure().\n");
284
		if ($g['booting'])
285
			printf("Error: cannot open radvd.conf in services_radvd_configure().\n");
286
	}
287
	unset($radvdconf);
288

    
289
	if (count($radvdifs) > 0) {
290
		if (isvalidpid("{$g['varrun_path']}/radvd.pid"))
291
			sigkillbypid("{$g['varrun_path']}/radvd.pid", "HUP");
292
		else
293
			mwexec("/usr/local/sbin/radvd -p {$g['varrun_path']}/radvd.pid -C {$g['varetc_path']}/radvd.conf -m syslog");
294
	} else {
295
		/* we need to shut down the radvd cleanly, it will send out the prefix
296
		 * information with a lifetime of 0 to notify clients of a (possible) new prefix */
297
		if (isvalidpid("{$g['varrun_path']}/radvd.pid")) {
298
			log_error("Shutting down Router Advertisment daemon cleanly");
299
			killbypid("{$g['varrun_path']}/radvd.pid");
300
			@unlink("{$g['varrun_path']}/radvd.pid");
301
		}
302
	}
303
	return 0;
304
}
305

    
306
function services_dhcpd_configure($family = "all", $blacklist = array()) {
307
	global $config, $g;
308

    
309
	/* configure DHCPD chroot once */
310
	$fd = fopen("{$g['tmp_path']}/dhcpd.sh","w");
311
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}\n");
312
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/dev\n");
313
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/etc\n");
314
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr/local/sbin\n");
315
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db\n");
316
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/run\n");
317
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr\n");
318
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/lib\n");
319
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/run\n");
320
	fwrite($fd, "/usr/sbin/chown -R dhcpd:_dhcp {$g['dhcpd_chroot_path']}/*\n");
321
	fwrite($fd, "/bin/cp -n /lib/libc.so.* {$g['dhcpd_chroot_path']}/lib/\n");
322
	fwrite($fd, "/bin/cp -n /usr/local/sbin/dhcpd {$g['dhcpd_chroot_path']}/usr/local/sbin/\n");
323
	fwrite($fd, "/bin/chmod a+rx {$g['dhcpd_chroot_path']}/usr/local/sbin/dhcpd\n");
324

    
325
	$status = `/sbin/mount | /usr/bin/grep -v grep  | /usr/bin/grep  "{$g['dhcpd_chroot_path']}/dev"`;
326
	if (!trim($status))
327
		fwrite($fd, "/sbin/mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
328
	fclose($fd);
329
	mwexec("/bin/sh {$g['tmp_path']}/dhcpd.sh");
330

    
331
	if ($family == "all" || $family == "inet")
332
		services_dhcpdv4_configure();
333
	if ($family == "all" || $family == "inet6") {
334
		services_dhcpdv6_configure($blacklist);
335
		services_radvd_configure($blacklist);
336
	}
337
}
338

    
339
function services_dhcpdv4_configure() {
340
	global $config, $g;
341
	$need_ddns_updates = false;
342
	$ddns_zones = array();
343

    
344
	if($g['services_dhcp_server_enable'] == false)
345
		return;
346

    
347
	if(isset($config['system']['developerspew'])) {
348
		$mt = microtime();
349
		echo "services_dhcpdv4_configure($if) being called $mt\n";
350
	}
351

    
352
	/* kill any running dhcpd */
353
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
354
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
355

    
356
	/* DHCP enabled on any interfaces? */
357
	if (!is_dhcp_server_enabled())
358
		return 0;
359

    
360
	/* if OLSRD is enabled, allow WAN to house DHCP. */
361
	if($config['installedpackages']['olsrd'])
362
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
363
				if($olsrd['enable'])
364
					$is_olsr_enabled = true;
365

    
366
	if ($g['booting']) {
367
		/* restore the leases, if we have them */
368
		if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
369
			$dhcprestore = "";
370
			$dhcpreturn = "";
371
			exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
372
			$dhcprestore = implode(" ", $dhcprestore);
373
			if($dhcpreturn <> 0) {
374
				log_error(sprintf(gettext('DHCP leases restore failed exited with %1$s, the error is: %2$s%3$s'), $dhcpreturn, $dhcprestore, "\n"));
375
			}
376
		}
377
		/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
378
		if (($g['platform'] == "pfSense") && !isset($config['system']['use_mfs_tmpvar'])) {
379
			unlink_if_exists("{$g['cf_conf_path']}/dhcpleases.tgz");
380
		}
381
	}
382

    
383
	$syscfg = $config['system'];
384
	if (!is_array($config['dhcpd']))
385
		$config['dhcpd'] = array();
386
	$dhcpdcfg = $config['dhcpd'];
387
	$Iflist = get_configured_interface_list();
388

    
389
	/* Only consider DNS servers with IPv4 addresses for the IPv4 DHCP server. */
390
	$dns_arrv4 = array();
391
	if (is_array($syscfg['dnsserver'])) {
392
		foreach($syscfg['dnsserver'] as $dnsserver) {
393
			if (is_ipaddrv4($dnsserver)) {
394
				$dns_arrv4[] = $dnsserver;
395
			}
396
		}
397
	}
398

    
399
	if ($g['booting'])
400
		echo gettext("Starting DHCP service...");
401
	else
402
		sleep(1);
403

    
404
	$custoptions = "";
405
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
406
		if(is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) {
407
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
408
				if(!empty($item['type']))
409
					$itemtype = $item['type'];
410
				else
411
					$itemtype = "text";
412
				$custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n";
413
			}
414
		}
415
	}
416

    
417
	$dhcpdconf = <<<EOD
418

    
419
option domain-name "{$syscfg['domain']}";
420
option ldap-server code 95 = text;
421
option domain-search-list code 119 = text;
422
{$custoptions}
423
default-lease-time 7200;
424
max-lease-time 86400;
425
log-facility local7;
426
one-lease-per-client true;
427
deny duplicates;
428
ping-check true;
429

    
430
EOD;
431

    
432
	if(!isset($dhcpifconf['disableauthoritative']))
433
		$dhcpdconf .= "authoritative;\n";
434

    
435
	if(isset($dhcpifconf['alwaysbroadcast']))
436
		$dhcpdconf .= "always-broadcast on\n";
437

    
438
	$dhcpdifs = array();
439
	$add_routers = false;
440
	$gateways_arr = return_gateways_array();
441
	/* only add a routers line if the system has any IPv4 gateway at all */
442
	/* a static route has a gateway, manually overriding this field always works */
443
	foreach($gateways_arr as $gwitem) {
444
		if($gwitem['ipprotocol'] == "inet") {
445
			$add_routers = true;
446
			break;
447
		}
448
	}
449

    
450
	/*    loop through and determine if we need to setup
451
	 *    failover peer "bleh" entries
452
	 */
453
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
454

    
455
		interfaces_staticarp_configure($dhcpif);
456

    
457
		if (!isset($dhcpifconf['enable']))
458
			continue;
459

    
460
		if($dhcpifconf['failover_peerip'] <> "") {
461
			$int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
462
			$intip = find_interface_ip($int);
463
			$real_dhcpif = convert_friendly_interface_to_real_interface_name($dhcpif);
464
			/*
465
			 *    yep, failover peer is defined.
466
			 *    does it match up to a defined vip?
467
			 */
468
			$skew = 110;
469
			$a_vip = &$config['virtualip']['vip'];
470
			if(is_array($a_vip)) {
471
				foreach ($a_vip as $vipent) {
472
					if($int == $real_dhcpif) {
473
						/* this is the interface! */
474
						if(is_numeric($vipent['advskew']) && ($vipent['advskew'] < "20"))
475
							$skew = 0;
476
					}
477
				}
478
			} else {
479
				log_error(gettext("Warning!  DHCP Failover setup and no CARP virtual IP's defined!"));
480
			}
481
			if($skew > 10) {
482
				$type = "secondary";
483
				$dhcpdconf_pri  = "mclt 600;\n";
484
				$my_port = "520";
485
				$peer_port = "519";
486
			} else {
487
				$my_port = "519";
488
				$peer_port = "520";
489
				$type = "primary";
490
				$dhcpdconf_pri  = "split 128;\n";
491
				$dhcpdconf_pri .= "  mclt 600;\n";
492
			}
493
			$dhcpdconf .= <<<EOPP
494
failover peer "dhcp_{$dhcpif}" {
495
  {$type};
496
  address {$intip};
497
  port {$my_port};
498
  peer address {$dhcpifconf['failover_peerip']};
499
  peer port {$peer_port};
500
  max-response-delay 10;
501
  max-unacked-updates 10;
502
  {$dhcpdconf_pri}
503
  load balance max seconds 3;
504
}
505

    
506
EOPP;
507
		}
508
	}
509

    
510
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
511

    
512
		$newzone = array();
513
		$ifcfg = $config['interfaces'][$dhcpif];
514

    
515
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
516
			continue;
517
		$ifcfgip = get_interface_ip($dhcpif);
518
		$ifcfgsn = get_interface_subnet($dhcpif);
519
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
520
		$subnetmask = gen_subnet_mask($ifcfgsn);
521

    
522
		if (!is_ipaddr($subnet))
523
			continue;
524

    
525
		if($is_olsr_enabled == true)
526
			if($dhcpifconf['netmask'])
527
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
528

    
529
		$all_pools = array();
530
		$all_pools[] = $dhcpifconf;
531
		if (is_array($dhcpifconf['pool'])) {
532
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
533
		}
534

    
535
		$dnscfg = "";
536

    
537
		if ($dhcpifconf['domain']) {
538
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
539
		}
540

    
541
		if($dhcpifconf['domainsearchlist'] <> "") {
542
			$dnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpifconf['domainsearchlist'])) . "\";\n";
543
		}
544

    
545
		if (isset($dhcpifconf['ddnsupdate'])) {
546
			$need_ddns_updates = true;
547
			$newzone = array();
548
			if($dhcpifconf['ddnsdomain'] <> "") {
549
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
550
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
551
			} else {
552
				$newzone['domain-name'] = $config['system']['domain'];
553
			}
554
			$revsubnet = explode(".", $subnet);
555
			$revsubnet = array_reverse($revsubnet);
556
			foreach ($revsubnet as $octet) {
557
				if ($octet != "0")
558
					break;
559
				array_shift($revsubnet);
560
			}
561
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
562
		}
563

    
564
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
565
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
566
			if ($newzone['domain-name'])
567
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
568
		} else if (isset($config['dnsmasq']['enable'])) {
569
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
570
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0]))
571
				$newzone['dns-servers'] = $syscfg['dnsserver'];
572
		} else if (!empty($dns_arrv4)) {
573
			$dnscfg .= "	option domain-name-servers " . join(",", $dns_arrv4) . ";";
574
			if ($newzone['domain-name'])
575
				$newzone['dns-servers'] = $dns_arrv4;
576
		}
577

    
578
		/* Create classes - These all contain comma separated lists. Join them into one 
579
		   big comma separated string then split them all up. */
580
		$all_mac_strings = array();
581
		if (is_array($dhcpifconf['pool'])) {
582
			foreach($all_pools as $poolconf) {
583
				$all_mac_strings[] = $poolconf['mac_allow'];
584
				$all_mac_strings[] = $poolconf['mac_deny'];
585
			}
586
		}
587
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
588
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
589
		$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
590
		foreach ($all_mac_list as $mac) {
591
			if (empty($mac))
592
				continue;
593
			$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
594
			// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
595
			$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
596
			$dhcpdconf .= '}' . "\n";
597
		}
598

    
599
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
600

    
601
// Setup pool options
602
		foreach($all_pools as $poolconf) {
603
			$dhcpdconf .= "	pool {\n";
604
			/* is failover dns setup? */
605
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
606
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
607
				if($poolconf['dnsserver'][1] <> "")
608
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
609
				$dhcpdconf .= ";\n";
610
			}
611

    
612
			/* allow/deny MACs */
613
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
614
			foreach ($mac_allow_list as $mac) {
615
				if (empty($mac))
616
					continue;
617
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
618
			}
619
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
620
			foreach ($mac_deny_list as $mac) {
621
				if (empty($mac))
622
					continue;
623
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
624
			}
625

    
626
			if($poolconf['failover_peerip'] <> "")
627
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
628

    
629
			if (isset($poolconf['denyunknown']))
630
			   $dhcpdconf .= "		deny unknown-clients;\n";
631

    
632
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
633
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
634

    
635
			if($dhcpifconf['failover_peerip'] <> "") {
636
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
637
			}
638

    
639
			$pdnscfg = "";
640

    
641
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
642
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
643
			}
644

    
645
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
646
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
647
			}
648

    
649
			if (isset($poolconf['ddnsupdate'])) {
650
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
651
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
652
				$pdnscfg .= "		ddns-update-style interim;\n";
653
			}
654

    
655
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
656
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
657
			}
658
			$dhcpdconf .= "{$pdnscfg}";
659

    
660
			// default-lease-time
661
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
662
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
663

    
664
			// max-lease-time
665
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
666
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
667

    
668
			// netbios-name*
669
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
670
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
671
				$dhcpdconf .= "		option netbios-node-type 8;\n";
672
			}
673

    
674
			// ntp-servers
675
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
676
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
677

    
678
			// tftp-server-name
679
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
680
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
681

    
682
			// ldap-server
683
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
684
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
685

    
686
			// net boot information
687
			if(isset($poolconf['netboot'])) {
688
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
689
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
690
				}
691
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
692
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
693
				}
694
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
695
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
696
				}
697
			}
698
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
699
			$dhcpdconf .= "	}\n\n";
700
		}
701
// End of settings inside pools
702

    
703
		if ($dhcpifconf['gateway']) {
704
			$routers = $dhcpifconf['gateway'];
705
			$add_routers = true;
706
		} else {
707
			$routers = $ifcfgip;
708
		}
709
		if($add_routers)
710
			$dhcpdconf .= "	option routers {$routers};\n";
711

    
712
		$dhcpdconf .= <<<EOD
713
$dnscfg
714

    
715
EOD;
716
    		// default-lease-time
717
		if ($dhcpifconf['defaultleasetime'])
718
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
719

    
720
		// max-lease-time
721
		if ($dhcpifconf['maxleasetime'])
722
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
723

    
724
		// netbios-name*
725
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
726
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
727
			$dhcpdconf .= "	option netbios-node-type 8;\n";
728
		}
729

    
730
		// ntp-servers
731
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
732
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
733

    
734
		// tftp-server-name
735
		if ($dhcpifconf['tftp'] <> "")
736
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
737

    
738
		// Handle option, number rowhelper values
739
		$dhcpdconf .= "\n";
740
		if($dhcpifconf['numberoptions']['item']) {
741
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
742
				if(empty($item['type']) || $item['type'] == "text")
743
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
744
				else
745
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
746
			}
747
		}
748

    
749
		// ldap-server
750
		if ($dhcpifconf['ldap'] <> "")
751
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
752

    
753
		// net boot information
754
		if(isset($dhcpifconf['netboot'])) {
755
			if ($dhcpifconf['nextserver'] <> "") {
756
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
757
			}
758
			if ($dhcpifconf['filename'] <> "") {
759
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
760
			}
761
			if ($dhcpifconf['rootpath'] <> "") {
762
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
763
			}
764
		}
765

    
766
		$dhcpdconf .= <<<EOD
767
}
768

    
769
EOD;
770

    
771
		/* add static mappings */
772
		if (is_array($dhcpifconf['staticmap'])) {
773

    
774
			$i = 0;
775
			foreach ($dhcpifconf['staticmap'] as $sm) {
776
				$dhcpdconf .= <<<EOD
777
host s_{$dhcpif}_{$i} {
778
	hardware ethernet {$sm['mac']};
779

    
780
EOD;
781
				if ($sm['ipaddr'])
782
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
783

    
784
				if ($sm['hostname']) {
785
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
786
					$dhhostname = str_replace(".", "_", $dhhostname);
787
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
788
				}
789
				if ($sm['filename'])
790
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
791

    
792
				if ($sm['rootpath'])
793
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
794

    
795
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
796
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
797

    
798
				$smdnscfg = "";
799

    
800
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
801
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
802
				}
803

    
804
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
805
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
806
				}
807

    
808
				if (isset($sm['ddnsupdate'])) {
809
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
810
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
811
					$pdnscfg .= "		ddns-update-style interim;\n";
812
				}
813

    
814
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
815
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
816
				}
817
				$dhcpdconf .= "{$smdnscfg}";
818

    
819
				// default-lease-time
820
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
821
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
822

    
823
				// max-lease-time
824
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
825
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
826

    
827
				// netbios-name*
828
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
829
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
830
					$dhcpdconf .= "	option netbios-node-type 8;\n";
831
				}
832

    
833
				// ntp-servers
834
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
835
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
836

    
837
				// tftp-server-name
838
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
839
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
840

    
841
				$dhcpdconf .= "}\n";
842
				$i++;
843
			}
844
		}
845

    
846
		$dhcpdifs[] = get_real_interface($dhcpif);
847
		if ($newzone['domain-name'])
848
			$ddns_zones[] = $newzone;
849
	}
850

    
851
	if ($need_ddns_updates) {
852
		$dhcpdconf .= "ddns-update-style interim;\n";
853
		if (is_array($ddns_zones)) {
854
			$added_zones = array();
855
			foreach ($ddns_zones as $zone) {
856
				if (!is_array($zone) || empty($zone) || !is_array($zone['dns-servers']))
857
					continue;
858
				$primary = $zone['dns-servers'][0];
859
				$secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1];
860
				// Make sure we aren't using any invalid or IPv6 DNS servers.
861
				if (!is_ipaddrv4($primary)) {
862
					if (is_ipaddrv4($secondary)) {
863
						$primary = $secondary;
864
						$secondary = "";
865
					} else {
866
						continue;
867
					}
868
				}
869
				// We don't need to add zones multiple times.
870
				if (!in_array($zone['domain-name'], $added_zones)) {
871
					$dhcpdconf .= "zone {$zone['domain-name']} {\n";
872
					$dhcpdconf .= "	primary {$primary};\n";
873
					if (is_ipaddrv4($secondary))
874
						$dhcpdconf .= "	secondary {$secondary};\n";
875
					$dhcpdconf .= "}\n";
876
					$added_zones[] = $zone['domain-name'];
877
				}
878
				if (!in_array($zone['ptr-domain'], $added_zones)) {
879
					$dhcpdconf .= "zone {$zone['ptr-domain']} {\n";
880
					$dhcpdconf .= "	primary {$primary};\n";
881
					if (is_ipaddrv4($secondary))
882
						$dhcpdconf .= "	secondary {$secondary};\n";
883
					$dhcpdconf .= "}\n";
884
					$added_zones[] = $zone['ptr-domain'];
885
				}
886
			}
887
		}
888
	}
889

    
890
	/* write dhcpd.conf */
891
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
892
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
893
		unset($dhcpdconf);
894
		return 1;
895
	}
896
	unset($dhcpdconf);
897

    
898
	/* create an empty leases database */
899
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
900
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
901

    
902
	/* fire up dhcpd in a chroot */
903
	if (count($dhcpdifs) > 0) {
904
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
905
			join(" ", $dhcpdifs));
906
	}
907

    
908
	if ($g['booting'])
909
		print "done.\n";
910

    
911
	return 0;
912
}
913

    
914
function services_dhcpdv6_configure($blacklist = array()) {
915
	global $config, $g;
916

    
917
	if($g['services_dhcp_server_enable'] == false)
918
		return;
919

    
920
	if(isset($config['system']['developerspew'])) {
921
		$mt = microtime();
922
		echo "services_dhcpd_configure($if) being called $mt\n";
923
	}
924

    
925
	/* kill any running dhcpd */
926
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
927
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
928
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
929
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
930

    
931
	/* DHCP enabled on any interfaces? */
932
	if (!is_dhcpv6_server_enabled())
933
		return 0;
934

    
935
	if ($g['booting']) {
936
		if ($g['platform'] != "pfSense") {
937
			/* restore the leases, if we have them */
938
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
939
				$dhcprestore = "";
940
				$dhcpreturn = "";
941
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
942
				$dhcprestore = implode(" ", $dhcprestore);
943
				if($dhcpreturn <> 0) {
944
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
945
				}
946
			}
947
		}
948
	}
949

    
950
	$syscfg = $config['system'];
951
	if (!is_array($config['dhcpdv6']))
952
		$config['dhcpdv6'] = array();
953
	$dhcpdv6cfg = $config['dhcpdv6'];
954
	$Iflist = get_configured_interface_list();
955
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
956

    
957

    
958
	if ($g['booting'])
959
		echo "Starting DHCPv6 service...";
960
	else
961
		sleep(1);
962

    
963
	/* we add a fake entry for interfaces that are set to track6 another WAN */
964
	foreach ($Iflist as $ifname) {
965
		/* Do not put in the config an interface which is down */
966
		if (isset($blacklist[$ifname]))
967
			continue;
968
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
969
			$realif = get_real_interface($ifname, "inet6");
970
			$ifcfgipv6 = get_interface_ipv6($ifname);
971
			if(!is_ipaddrv6($ifcfgipv6))
972
				continue;
973
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
974
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
975
			$trackcfg = $config['interfaces'][$trackifname];
976
			$pdlen = calculate_ipv6_delegation_length($trackifname);
977
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
978
			$dhcpdv6cfg[$ifname] = array();
979
			$dhcpdv6cfg[$ifname]['enable'] = true;
980
			/* range */
981
			$ifcfgipv6arr[7] = "1000";
982
			$dhcpdv6cfg[$ifname]['range'] = array();
983
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
984
			$ifcfgipv6arr[7] = "2000";
985
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
986
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
987
			if($pdlen > 2) {
988
				$pdlenmax = $pdlen;
989
				$pdlenhalf = $pdlenmax -1;
990
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
991
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
992
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
993

    
994
				/* set the delegation start to half the current address block */
995
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
996
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
997

    
998
				/* set the end range to a multiple of the prefix delegation size, required by dhcpd */
999
				$range = Net_IPv6::parseAddress($range['end'], (64 - $pdlenhalf));
1000
				$range['end'] = Net_IPv6::getNetmask($range['end'], (64 - round($pdlen / 2)));
1001

    
1002
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
1003
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
1004
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
1005
			}
1006
		}
1007
	}
1008

    
1009
	$custoptionsv6 = "";
1010
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1011
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
1012
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1013
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
1014
			}
1015
		}
1016
	}
1017

    
1018
	if(isset($dhcpv6ifconf['netboot']) && !empty($dhcpv6ifconf['bootfile_url']))
1019
		$custoptionsv6 .= "option dhcp6.bootfile-url code 59 = string;\n";
1020

    
1021
	$dhcpdv6conf = <<<EOD
1022

    
1023
option domain-name "{$syscfg['domain']}";
1024
option ldap-server code 95 = text;
1025
option domain-search-list code 119 = text;
1026
{$custoptionsv6}
1027
default-lease-time 7200;
1028
max-lease-time 86400;
1029
log-facility local7;
1030
ddns-update-style none;
1031
one-lease-per-client true;
1032
deny duplicates;
1033
ping-check true;
1034

    
1035
EOD;
1036

    
1037
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1038
		$dhcpdv6conf .= "authoritative;\n";
1039

    
1040
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1041
		$dhcpdv6conf .= "always-broadcast on\n";
1042

    
1043
	$dhcpdv6ifs = array();
1044

    
1045
	$dhcpv6num = 0;
1046
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1047

    
1048
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1049

    
1050
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1051
			continue;
1052
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1053
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1054
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1055

    
1056
		if ($is_olsr_enabled == true) {
1057
			if($dhcpv6ifconf['netmask'])
1058
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1059
		}
1060

    
1061
		$dnscfgv6 = "";
1062

    
1063
		if ($dhcpv6ifconf['domain']) {
1064
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1065
		}
1066

    
1067
    		if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1068
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1069
    		}
1070

    
1071
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1072
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1073
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1074
			}
1075
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1076
		}
1077

    
1078
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1079
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1080
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1081
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1082
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1083
			$dns_arrv6 = array();
1084
			foreach($syscfg['dnsserver'] as $dnsserver) {
1085
				if (is_ipaddrv6($dnsserver)) {
1086
					$dns_arrv6[] = $dnsserver;
1087
				}
1088
			}
1089
			if(!empty($dns_arrv6))
1090
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1091
		}
1092

    
1093
		if (is_ipaddrv6($ifcfgipv6)) {
1094
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1095
		} else {
1096
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1097
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1098
		}
1099
		$dhcpdv6conf .= " {\n";
1100

    
1101
		$dhcpdv6conf .= <<<EOD
1102
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1103
$dnscfgv6
1104

    
1105
EOD;
1106

    
1107
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1108
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1109
		}
1110
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1111
			$dhcpdv6conf .= "       option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1112
		}
1113
    		// default-lease-time
1114
		if ($dhcpv6ifconf['defaultleasetime'])
1115
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1116

    
1117
		// max-lease-time
1118
		if ($dhcpv6ifconf['maxleasetime'])
1119
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1120

    
1121
		// ntp-servers
1122
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1123
			$ntpservers = array();
1124
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1125
				if(is_ipaddrv6($ntpserver))
1126
					$ntpservers[] = $ntpserver;
1127
			}
1128
			if(count($ntpservers) > 0 )
1129
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1130
		}
1131
		// tftp-server-name
1132
		/* Needs ISC DHCPD support
1133
		 if ($dhcpv6ifconf['tftp'] <> "")
1134
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1135
		*/
1136

    
1137
		// Handle option, number rowhelper values
1138
		$dhcpdv6conf .= "\n";
1139
		if ($dhcpv6ifconf['numberoptions']['item']) {
1140
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1141
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1142
			}
1143
		}
1144

    
1145
		// ldap-server
1146
		if ($dhcpv6ifconf['ldap'] <> "")
1147
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1148

    
1149
		// net boot information
1150
		if(isset($dhcpv6ifconf['netboot'])) {
1151
			if (!empty($dhcpv6ifconf['bootfile_url'])) {
1152
				$dhcpdv6conf .= "	option dhcp6.bootfile-url \"{$dhcpv6ifconf['bootfile_url']}\";\n";
1153
			}
1154
		}
1155

    
1156
		$dhcpdv6conf .= "}\n";
1157

    
1158
		/* add static mappings */
1159
		/* Needs to use DUID */
1160
		if (is_array($dhcpv6ifconf['staticmap'])) {
1161
			$i = 0;
1162
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1163
				$dhcpdv6conf .= <<<EOD
1164
host s_{$dhcpv6if}_{$i} {
1165
	host-identifier option dhcp6.client-id {$sm['duid']};
1166

    
1167
EOD;
1168
				if ($sm['ipaddrv6'])
1169
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1170

    
1171
				if ($sm['hostname']) {
1172
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1173
					$dhhostname = str_replace(".", "_", $dhhostname);
1174
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1175
				}
1176
				if ($sm['filename'])
1177
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1178

    
1179
				if ($sm['rootpath'])
1180
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1181

    
1182
				$dhcpdv6conf .= "}\n";
1183
				$i++;
1184
			}
1185
		}
1186

    
1187
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1188
			if(preg_match("/poes/si", $dhcpv6if)) {
1189
				/* magic here */
1190
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1191
			} else {
1192
				$realif = get_real_interface($dhcpv6if, "inet6");
1193
				if (stristr("$realif", "bridge")) {
1194
					$mac = get_interface_mac($realif);
1195
					$v6address = generate_ipv6_from_mac($mac);
1196
					/* Create link local address for bridges */
1197
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1198
				}
1199
				$realif = escapeshellcmd($realif);
1200
				$dhcpdv6ifs[] = $realif;
1201
			}
1202
		}
1203
	}
1204

    
1205
	/* write dhcpdv6.conf */
1206
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1207
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1208
		if ($g['booting'])
1209
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1210
		unset($dhcpdv6conf);
1211
		return 1;
1212
	}
1213
	unset($dhcpdv6conf);
1214

    
1215
	/* create an empty leases v6 database */
1216
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1217
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1218

    
1219
	/* fire up dhcpd in a chroot */
1220
	if (count($dhcpdv6ifs) > 0) {
1221
		mwexec("/usr/local/sbin/dhcpd -6 -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpdv6.conf -pf {$g['varrun_path']}/dhcpdv6.pid " .
1222
			join(" ", $dhcpdv6ifs));
1223
		mwexec("/usr/local/sbin/dhcpleases6 -c \"/usr/local/bin/php -f /usr/local/sbin/prefixes.php|/bin/sh\" -l {$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1224
	}
1225
	if ($g['booting'])
1226
		print gettext("done.") . "\n";
1227

    
1228
	return 0;
1229
}
1230

    
1231
function services_igmpproxy_configure() {
1232
        global $config, $g;
1233

    
1234
        /* kill any running igmpproxy */
1235
        killbyname("igmpproxy");
1236

    
1237
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1238
		return 1;
1239

    
1240
        $iflist = get_configured_interface_list();
1241

    
1242
        $igmpconf = <<<EOD
1243

    
1244
##------------------------------------------------------
1245
## Enable Quickleave mode (Sends Leave instantly)
1246
##------------------------------------------------------
1247
quickleave
1248

    
1249
EOD;
1250

    
1251
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1252
                unset($iflist[$igmpcf['ifname']]);
1253
                $realif = get_real_interface($igmpcf['ifname']);
1254
                if (empty($igmpcf['threshold']))
1255
                        $threshld = 1;
1256
                else
1257
                        $threshld = $igmpcf['threshold'];
1258
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1259

    
1260
                if ($igmpcf['address'] <> "") {
1261
                        $item = explode(" ", $igmpcf['address']);
1262
                        foreach($item as $iww)
1263
                                $igmpconf .= "altnet {$iww}\n";
1264
                }
1265
                $igmpconf .= "\n";
1266
        }
1267
        foreach ($iflist as $ifn) {
1268
                $realif = get_real_interface($ifn);
1269
                $igmpconf .= "phyint {$realif} disabled\n";
1270
        }
1271
	$igmpconf .= "\n";
1272

    
1273
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1274
        if (!$igmpfl) {
1275
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1276
                return;
1277
        }
1278
        fwrite($igmpfl, $igmpconf);
1279
        fclose($igmpfl);
1280
	unset($igmpconf);
1281

    
1282
	/* NOTE: -d 4 means everything LOG_WARNING and smaller */
1283
        mwexec("/usr/local/sbin/igmpproxy -d 4 -c {$g['tmp_path']}/igmpproxy.conf");
1284
        log_error(gettext("Started IGMP proxy service."));
1285

    
1286
        return 0;
1287
}
1288

    
1289
function services_dhcrelay_configure() {
1290
	global $config, $g;
1291
	if ($g['platform'] == 'jail')
1292
		return;
1293
	if(isset($config['system']['developerspew'])) {
1294
		$mt = microtime();
1295
		echo "services_dhcrelay_configure() being called $mt\n";
1296
	}
1297

    
1298
	/* kill any running dhcrelay */
1299
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1300

    
1301
	$dhcrelaycfg =& $config['dhcrelay'];
1302

    
1303
	/* DHCPRelay enabled on any interfaces? */
1304
	if (!isset($dhcrelaycfg['enable']))
1305
		return 0;
1306

    
1307
	if ($g['booting'])
1308
		echo gettext("Starting DHCP relay service...");
1309
	else
1310
		sleep(1);
1311

    
1312
	$iflist = get_configured_interface_list();
1313

    
1314
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1315
	foreach ($dhcifaces as $dhcrelayif) {
1316
		if (!isset($iflist[$dhcrelayif]) ||
1317
			link_interface_to_bridge($dhcrelayif))
1318
			continue;
1319

    
1320
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1321
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1322
	}
1323

    
1324
	/*
1325
	 * In order for the relay to work, it needs to be active
1326
	 * on the interface in which the destination server sits.
1327
	 */
1328
	$srvips = explode(",", $dhcrelaycfg['server']);
1329
	foreach ($srvips as $srcidx => $srvip) {
1330
		unset($destif);
1331
		foreach ($iflist as $ifname) {
1332
			$subnet = get_interface_ip($ifname);
1333
			if (!is_ipaddr($subnet))
1334
				continue;
1335
			$subnet .=  "/" . get_interface_subnet($ifname);
1336
			if (ip_in_subnet($srvip, $subnet)) {
1337
				$destif = get_real_interface($ifname);
1338
				break;
1339
			}
1340
		}
1341
		if (!isset($destif)) {
1342
			foreach (get_staticroutes() as $rtent) {
1343
				if (ip_in_subnet($srvip, $rtent['network'])) {
1344
					$a_gateways = return_gateways_array(true);
1345
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1346
					break;
1347
				}
1348
			}
1349
		}
1350

    
1351
		if (!isset($destif)) {
1352
			/* Create a array from the existing route table */
1353
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1354
        		array_shift($route_str);
1355
        		array_shift($route_str);
1356
        		array_shift($route_str);
1357
        		array_shift($route_str);
1358
        		$route_arr = array();
1359
        		foreach($route_str as $routeline) {
1360
				$items = preg_split("/[ ]+/i", $routeline);
1361
				if (is_subnetv4($items[0])) {
1362
					$subnet = $items[0];
1363
				} elseif (is_ipaddrv4($items[0])) {
1364
					$subnet = "{$items[0]}/32";
1365
				} else {
1366
					// Not a subnet or IP address, skip to the next line.
1367
					continue;
1368
				}
1369
				if (ip_in_subnet($srvip, $subnet)) {
1370
					$destif = trim($items[6]);
1371
					break;
1372
				}
1373
			}
1374
		}
1375

    
1376
		if (!isset($destif)) {
1377
			if (is_array($config['gateways']['gateway_item'])) {
1378
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1379
					if (isset($gateway['defaultgw'])) {
1380
						$destif = get_real_interface($gateway['interface']);
1381
						break;
1382
					}
1383
				}
1384
			} else
1385
				$destif = get_real_interface("wan");
1386
		}
1387

    
1388
		if (!empty($destif))
1389
			$dhcrelayifs[] = $destif;
1390
	}
1391
	$dhcrelayifs = array_unique($dhcrelayifs);
1392

    
1393
	/* fire up dhcrelay */
1394
	if (empty($dhcrelayifs)) {
1395
		log_error("No suitable interface found for running dhcrelay!");
1396
		return; /* XXX */
1397
	}
1398

    
1399
	$cmd = "/usr/local/sbin/dhcrelay -i " .  implode(" -i ", $dhcrelayifs);
1400

    
1401
	if (isset($dhcrelaycfg['agentoption']))
1402
		$cmd .=  " -a -m replace";
1403

    
1404
	$cmd .= " " . implode(" ", $srvips);
1405
	mwexec($cmd);
1406
	unset($cmd);
1407

    
1408
	return 0;
1409
}
1410

    
1411
function services_dhcrelay6_configure() {
1412
	global $config, $g;
1413
	if ($g['platform'] == 'jail')
1414
		return;
1415
	if(isset($config['system']['developerspew'])) {
1416
		$mt = microtime();
1417
		echo "services_dhcrelay6_configure() being called $mt\n";
1418
	}
1419

    
1420
	/* kill any running dhcrelay */
1421
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1422

    
1423
	$dhcrelaycfg =& $config['dhcrelay6'];
1424

    
1425
	/* DHCPv6 Relay enabled on any interfaces? */
1426
	if (!isset($dhcrelaycfg['enable']))
1427
		return 0;
1428

    
1429
	if ($g['booting'])
1430
		echo gettext("Starting DHCPv6 relay service...");
1431
	else
1432
		sleep(1);
1433

    
1434
	$iflist = get_configured_interface_list();
1435

    
1436
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1437
	foreach ($dhcifaces as $dhcrelayif) {
1438
		if (!isset($iflist[$dhcrelayif]) ||
1439
			link_interface_to_bridge($dhcrelayif))
1440
			continue;
1441

    
1442
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1443
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1444
	}
1445
	$dhcrelayifs = array_unique($dhcrelayifs);
1446

    
1447
	/*
1448
	 * In order for the relay to work, it needs to be active
1449
	 * on the interface in which the destination server sits.
1450
	 */
1451
	$srvips = explode(",", $dhcrelaycfg['server']);
1452
        $srvifaces = array();
1453
	foreach ($srvips as $srcidx => $srvip) {
1454
		unset($destif);
1455
		foreach ($iflist as $ifname) {
1456
			$subnet = get_interface_ipv6($ifname);
1457
			if (!is_ipaddrv6($subnet))
1458
				continue;
1459
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1460
			if (ip_in_subnet($srvip, $subnet)) {
1461
				$destif = get_real_interface($ifname);
1462
				break;
1463
			}
1464
		}
1465
		if (!isset($destif)) {
1466
			if (is_array($config['staticroutes']['route'])) {
1467
				foreach ($config['staticroutes']['route'] as $rtent) {
1468
					if (ip_in_subnet($srvip, $rtent['network'])) {
1469
						$a_gateways = return_gateways_array(true);
1470
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1471
						break;
1472
					}
1473
				}
1474
			}
1475
		}
1476

    
1477
		if (!isset($destif)) {
1478
			/* Create a array from the existing route table */
1479
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1480
        		array_shift($route_str);
1481
        		array_shift($route_str);
1482
        		array_shift($route_str);
1483
        		array_shift($route_str);
1484
        		$route_arr = array();
1485
        		foreach($route_str as $routeline) {
1486
                		$items = preg_split("/[ ]+/i", $routeline);
1487
				if (ip_in_subnet($srvip, $items[0])) {
1488
					$destif = trim($items[6]);
1489
					break;
1490
				}
1491
        		}
1492
		}
1493

    
1494
		if (!isset($destif)) {
1495
			if (is_array($config['gateways']['gateway_item'])) {
1496
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1497
					if (isset($gateway['defaultgw'])) {
1498
						$destif = $gateway['interface'];
1499
						break;
1500
					}
1501
				}
1502
			} else
1503
				$destif = get_real_interface("wan");
1504
		}
1505

    
1506
		if (!empty($destif)) {
1507
			$srvifaces[] = "{$srvip}%{$destif}";
1508
		}
1509
	}
1510

    
1511
	/* fire up dhcrelay */
1512
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1513
		log_error("No suitable interface found for running dhcrelay -6!");
1514
		return; /* XXX */
1515
	}
1516

    
1517
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1518
	foreach ($dhcrelayifs as $dhcrelayif) {
1519
		$cmd .= " -l {$dhcrelayif}";
1520
	}
1521
	foreach ($srvifaces as $srviface) {
1522
		$cmd .= " -u \"{$srviface}\"";
1523
	}
1524
	mwexec($cmd);
1525
	unset($cmd);
1526

    
1527
	return 0;
1528
}
1529

    
1530
function services_dyndns_configure_client($conf) {
1531

    
1532
	if (!isset($conf['enable']))
1533
		return;
1534

    
1535
	/* load up the dyndns.class */
1536
	require_once("dyndns.class");
1537

    
1538
	$dns = new updatedns($dnsService = $conf['type'],
1539
		$dnsHost = $conf['host'],
1540
		$dnsUser = $conf['username'],
1541
		$dnsPass = $conf['password'],
1542
		$dnsWilcard = $conf['wildcard'],
1543
		$dnsMX = $conf['mx'],
1544
		$dnsIf = "{$conf['interface']}",
1545
		$dnsBackMX = NULL,
1546
		$dnsServer = NULL,
1547
		$dnsPort = NULL,
1548
		$dnsUpdateURL = "{$conf['updateurl']}",
1549
		$forceUpdate = $conf['force'],
1550
		$dnsZoneID=$conf['zoneid'],
1551
		$dnsTTL=$conf['ttl'],
1552
		$dnsResultMatch = "{$conf['resultmatch']}",
1553
		$dnsRequestIf = "{$conf['requestif']}",
1554
		$dnsID = "{$conf['id']}",
1555
		$dnsVerboseLog = $conf['verboselog']);
1556
}
1557

    
1558
function services_dyndns_configure($int = "") {
1559
	global $config, $g;
1560
	if(isset($config['system']['developerspew'])) {
1561
		$mt = microtime();
1562
		echo "services_dyndns_configure() being called $mt\n";
1563
	}
1564

    
1565
	$dyndnscfg = $config['dyndnses']['dyndns'];
1566
	$gwgroups = return_gateway_groups_array();
1567
	if (is_array($dyndnscfg)) {
1568
		if ($g['booting'])
1569
			echo gettext("Starting DynDNS clients...");
1570

    
1571
		foreach ($dyndnscfg as $dyndns) {
1572
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1573
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1574
				services_dyndns_configure_client($dyndns);
1575
				sleep(1);
1576
			}
1577
		}
1578

    
1579
		if ($g['booting'])
1580
			echo gettext("done.") . "\n";
1581
	}
1582

    
1583
	return 0;
1584
}
1585

    
1586
function dyndnsCheckIP($int) {
1587
	global $config;
1588
	$ip_address = get_interface_ip($int);
1589
	if (is_private_ip($ip_address)) {
1590
		$gateways_status = return_gateways_status(true);
1591
		// If the gateway for this interface is down, then the external check cannot work.
1592
		// Avoid the long wait for the external check to timeout.
1593
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1594
			return "down";
1595
		$hosttocheck = "http://checkip.dyndns.org";
1596
		$ip_ch = curl_init($hosttocheck);
1597
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1598
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1599
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1600
		curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1601
		curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1602
		curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1603
		$ip_result_page = curl_exec($ip_ch);
1604
		curl_close($ip_ch);
1605
		$ip_result_decoded = urldecode($ip_result_page);
1606
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1607
		$ip_address = trim($matches[1]);
1608
	}
1609
	return $ip_address;
1610
}
1611

    
1612
function services_dnsmasq_configure() {
1613
	global $config, $g;
1614
	$return = 0;
1615

    
1616
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1617
	$standard_args = array(
1618
		"dns-forward-max" => "--dns-forward-max=5000",
1619
		"cache-size" => "--cache-size=10000",
1620
		"local-ttl" => "--local-ttl=1"
1621
	);
1622

    
1623

    
1624
	if(isset($config['system']['developerspew'])) {
1625
		$mt = microtime();
1626
		echo "services_dnsmasq_configure() being called $mt\n";
1627
	}
1628

    
1629
	/* kill any running dnsmasq */
1630
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1631
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1632

    
1633
	if (isset($config['dnsmasq']['enable'])) {
1634

    
1635
		if ($g['booting'])
1636
			echo gettext("Starting DNS forwarder...");
1637
		else
1638
			sleep(1);
1639

    
1640
		/* generate hosts file */
1641
		if(system_hosts_generate()!=0)
1642
			$return = 1;
1643

    
1644
		$args = "";
1645

    
1646
		if (isset($config['dnsmasq']['regdhcp'])) {
1647
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1648
		}
1649

    
1650
		/* Setup listen port, if non-default */
1651
		if (is_port($config['dnsmasq']['port']))
1652
			$args .= " --port={$config['dnsmasq']['port']} ";
1653

    
1654
		$listen_addresses = "";
1655
		if(isset($config['dnsmasq']['interface'])) {
1656
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1657
			foreach ($interfaces as $interface) {
1658
				if (is_ipaddrv4($interface)) {
1659
					$listen_addresses .= " --listen-address={$interface} ";
1660
				} else if (is_ipaddrv6($interface)) {
1661
					/*
1662
					* XXX: Since dnsmasq does not support link-local address
1663
					* with scope specified. These checks are being done.
1664
					*/
1665
					if (is_linklocal($interface) && strstr($interface, "%")) {
1666
						$tmpaddrll6 = explode("%", $interface);
1667
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1668
					} else 
1669
						$listen_addresses .= " --listen-address={$interface} ";
1670
				} else {
1671
					$if = get_real_interface($interface);
1672
					if (does_interface_exist($if)) {
1673
						$laddr = find_interface_ip($if);
1674
						if (is_ipaddrv4($laddr))
1675
							$listen_addresses .= " --listen-address={$laddr} ";
1676
						$laddr6 = find_interface_ipv6($if);
1677
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
1678
							/*
1679
							 * XXX: Since dnsmasq does not support link-local address
1680
							 * with scope specified. These checks are being done.
1681
							 */
1682
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
1683
								$tmpaddrll6 = explode("%", $laddr6);
1684
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1685
							} else 
1686
								$listen_addresses .= " --listen-address={$laddr6} ";
1687
						}
1688
					}
1689
				}
1690
			}
1691
			if (!empty($listen_addresses)) {
1692
				$args .= " {$listen_addresses} ";
1693
				if (isset($config['dnsmasq']['strictbind']))
1694
					$args .= " --bind-interfaces ";
1695
			}
1696
		}
1697

    
1698
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
1699
		/* If any of these are duplicated by a user-specified domain override (e.g. 10.in-addr.arpa) then */
1700
		/* the user-specified entry made later on the command line below will be the one that is effective. */
1701
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1702
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1703
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1704
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1705
			$args .= " --server=/10.in-addr.arpa/ ";
1706
			$args .= " --server=/168.192.in-addr.arpa/ ";
1707
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1708
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1709
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1710
			}
1711
		}
1712

    
1713
		/* Setup forwarded domains */
1714
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1715
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1716
				if ($override['ip'] == "!")
1717
					$override[ip] = "";
1718
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1719
			}
1720
		}
1721

    
1722
		/* Allow DNS Rebind for forwarded domains */
1723
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1724
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1725
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1726
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1727
				}
1728
			}
1729
		}
1730

    
1731
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1732
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1733

    
1734
		if (isset($config['dnsmasq']['strict_order'])) {
1735
			$args .= " --strict-order ";
1736
		}
1737

    
1738
		if (isset($config['dnsmasq']['domain_needed'])) {
1739
			$args .= " --domain-needed ";
1740
		}
1741

    
1742
		if ($config['dnsmasq']['custom_options'])
1743
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1744
				$args .= " " . escapeshellarg("--{$c}");
1745
				$p = explode('=', $c);
1746
				if (array_key_exists($p[0], $standard_args))
1747
					unset($standard_args[$p[0]]);
1748
			}
1749
		$args .= ' ' . implode(' ', array_values($standard_args));
1750

    
1751
		/* run dnsmasq */
1752
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1753
		//log_error("dnsmasq command: {$cmd}");
1754
		mwexec_bg($cmd);
1755
		unset($args);
1756

    
1757
		if ($g['booting'])
1758
			echo gettext("done.") . "\n";
1759
	}
1760

    
1761
	if (!$g['booting']) {
1762
		if(services_dhcpd_configure()!=0)
1763
			$return = 1;
1764
	}
1765

    
1766
	return $return;
1767
}
1768

    
1769
function services_snmpd_configure() {
1770
	global $config, $g;
1771
	if(isset($config['system']['developerspew'])) {
1772
		$mt = microtime();
1773
		echo "services_snmpd_configure() being called $mt\n";
1774
	}
1775

    
1776
	/* kill any running snmpd */
1777
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1778
	sleep(2);
1779
	if(is_process_running("bsnmpd"))
1780
		mwexec("/usr/bin/killall bsnmpd", true);
1781

    
1782
	if (isset($config['snmpd']['enable'])) {
1783

    
1784
		if ($g['booting'])
1785
			echo gettext("Starting SNMP daemon... ");
1786

    
1787
		/* generate snmpd.conf */
1788
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1789
		if (!$fd) {
1790
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1791
			return 1;
1792
		}
1793

    
1794

    
1795
		$snmpdconf = <<<EOD
1796
location := "{$config['snmpd']['syslocation']}"
1797
contact := "{$config['snmpd']['syscontact']}"
1798
read := "{$config['snmpd']['rocommunity']}"
1799

    
1800
EOD;
1801

    
1802
/* No docs on what write strings do there for disable for now.
1803
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1804
		    $snmpdconf .= <<<EOD
1805
# write string
1806
write := "{$config['snmpd']['rwcommunity']}"
1807

    
1808
EOD;
1809
		}
1810
*/
1811

    
1812

    
1813
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1814
		    $snmpdconf .= <<<EOD
1815
# SNMP Trap support.
1816
traphost := {$config['snmpd']['trapserver']}
1817
trapport := {$config['snmpd']['trapserverport']}
1818
trap := "{$config['snmpd']['trapstring']}"
1819

    
1820

    
1821
EOD;
1822
		}
1823

    
1824
		$version = trim(file_get_contents('/etc/version'));
1825
		$platform = trim(file_get_contents('/etc/platform'));
1826
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1827
			$platform = $g['product_name'];
1828
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1829
			" {$version} {$platform} " . php_uname("s") .
1830
			" " . php_uname("r") . " " . php_uname("m");
1831

    
1832
		$snmpdconf .= <<<EOD
1833
system := 1     # pfSense
1834
%snmpd
1835
sysDescr			= "{$sysDescr}"
1836
begemotSnmpdDebugDumpPdus       = 2
1837
begemotSnmpdDebugSyslogPri      = 7
1838
begemotSnmpdCommunityString.0.1 = $(read)
1839

    
1840
EOD;
1841

    
1842
/* No docs on what write strings do there for disable for now.
1843
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1844
		    $snmpdconf .= <<<EOD
1845
begemotSnmpdCommunityString.0.2 = $(write)
1846

    
1847
EOD;
1848
		}
1849
*/
1850

    
1851

    
1852
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1853
		    $snmpdconf .= <<<EOD
1854
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1855
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1856
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1857

    
1858
EOD;
1859
		}
1860

    
1861

    
1862
		$snmpdconf .= <<<EOD
1863
begemotSnmpdCommunityDisable    = 1
1864

    
1865
EOD;
1866

    
1867
		if (isset($config['snmpd']['bindlan'])) {
1868
			$config['snmpd']['bindip'] = 'lan';
1869
			unset($config['snmpd']['bindlan']);
1870
		}
1871
		$bind_to_ip = "0.0.0.0";
1872
		if(isset($config['snmpd']['bindip'])) {
1873
			if (is_ipaddr($config['snmpd']['bindip'])) {
1874
				$bind_to_ip = $config['snmpd']['bindip'];
1875
			} else {
1876
				$if = get_real_interface($config['snmpd']['bindip']);
1877
				if (does_interface_exist($if))
1878
					$bind_to_ip = find_interface_ip($if);
1879
			}
1880
		}
1881

    
1882
		if(is_port( $config['snmpd']['pollport'] )) {
1883
		    $snmpdconf .= <<<EOD
1884
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1885

    
1886
EOD;
1887

    
1888
		}
1889

    
1890
		$snmpdconf .= <<<EOD
1891
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1892
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1893

    
1894
# These are bsnmp macros not php vars.
1895
sysContact      = $(contact)
1896
sysLocation     = $(location)
1897
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1898

    
1899
snmpEnableAuthenTraps = 2
1900

    
1901
EOD;
1902

    
1903
		if (is_array( $config['snmpd']['modules'] )) {
1904
		    if(isset($config['snmpd']['modules']['mibii'])) {
1905
			$snmpdconf .= <<<EOD
1906
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1907

    
1908
EOD;
1909
		    }
1910

    
1911
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1912
			$snmpdconf .= <<<EOD
1913
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1914
%netgraph
1915
begemotNgControlNodeName = "snmpd"
1916

    
1917
EOD;
1918
		    }
1919

    
1920
		    if(isset($config['snmpd']['modules']['pf'])) {
1921
			$snmpdconf .= <<<EOD
1922
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1923

    
1924
EOD;
1925
		    }
1926

    
1927
		    if(isset($config['snmpd']['modules']['hostres'])) {
1928
			$snmpdconf .= <<<EOD
1929
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1930

    
1931
EOD;
1932
		    }
1933
		    if(isset($config['snmpd']['modules']['bridge'])) {
1934
			$snmpdconf .= <<<EOD
1935
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1936
# config must end with blank line
1937

    
1938
EOD;
1939
		    }
1940
			if(isset($config['snmpd']['modules']['ucd'])) {
1941
				$snmpdconf .= <<<EOD
1942
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1943

    
1944
EOD;
1945
			}
1946
			if(isset($config['snmpd']['modules']['regex'])) {
1947
				$snmpdconf .= <<<EOD
1948
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1949

    
1950
EOD;
1951
			}
1952
		}
1953

    
1954
		fwrite($fd, $snmpdconf);
1955
		fclose($fd);
1956
		unset($snmpdconf);
1957

    
1958
		if (isset($config['snmpd']['bindlan'])) {
1959
			$bindlan = "";
1960
		}
1961

    
1962
		/* run bsnmpd */
1963
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1964
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1965

    
1966
		if ($g['booting'])
1967
			echo gettext("done.") . "\n";
1968
	}
1969

    
1970
	return 0;
1971
}
1972

    
1973
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
1974
	global $config, $g;
1975
	if(isset($config['system']['developerspew'])) {
1976
		$mt = microtime();
1977
		echo "services_dnsupdate_process() being called $mt\n";
1978
	}
1979

    
1980
	/* Dynamic DNS updating active? */
1981
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1982
		$notify_text = "";
1983
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1984
			if (!isset($dnsupdate['enable']))
1985
				continue;
1986
			if (!empty($int) && $int != $dnsupdate['interface'])
1987
				continue;
1988
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
1989
				continue;
1990

    
1991
			/* determine interface name */
1992
			$if = get_real_interface($dnsupdate['interface']);
1993
			if (isset($dnsupdate['usepublicip']))
1994
                                $wanip = dyndnsCheckIP($dnsupdate['interface']);
1995
                        else
1996
                                $wanip = get_interface_ip($dnsupdate['interface']);
1997
			
1998
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
1999
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2000
			$currentTime = time();
2001

    
2002
			if ($wanip || $wanipv6) {
2003
				$keyname = $dnsupdate['keyname'];
2004
				/* trailing dot */
2005
				if (substr($keyname, -1) != ".")
2006
					$keyname .= ".";
2007

    
2008
				$hostname = $dnsupdate['host'];
2009
				/* trailing dot */
2010
				if (substr($hostname, -1) != ".")
2011
					$hostname .= ".";
2012

    
2013
				/* write private key file
2014
				   this is dumb - public and private keys are the same for HMAC-MD5,
2015
				   but nsupdate insists on having both */
2016
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2017
				$privkey = <<<EOD
2018
Private-key-format: v1.2
2019
Algorithm: 157 (HMAC)
2020
Key: {$dnsupdate['keydata']}
2021

    
2022
EOD;
2023
				fwrite($fd, $privkey);
2024
				fclose($fd);
2025

    
2026
				/* write public key file */
2027
				if ($dnsupdate['keytype'] == "zone") {
2028
					$flags = 257;
2029
					$proto = 3;
2030
				} else if ($dnsupdate['keytype'] == "host") {
2031
					$flags = 513;
2032
					$proto = 3;
2033
				} else if ($dnsupdate['keytype'] == "user") {
2034
					$flags = 0;
2035
					$proto = 2;
2036
				}
2037

    
2038
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.key", "w");
2039
				fwrite($fd, "{$keyname} IN KEY {$flags} {$proto} 157 {$dnsupdate['keydata']}\n");
2040
				fclose($fd);
2041

    
2042
				/* generate update instructions */
2043
				$upinst = "";
2044
				if (!empty($dnsupdate['server']))
2045
					$upinst .= "server {$dnsupdate['server']}\n";
2046

    
2047
				if (file_exists($cacheFile)) {
2048
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2049
				}
2050
				if (file_exists("{$cacheFile}.ipv6")) {
2051
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2052
				}
2053

    
2054
				// 25 Days
2055
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2056
				$need_update = false;
2057

    
2058
				conf_mount_rw();
2059
				/* Update IPv4 if we have it. */
2060
				if (is_ipaddrv4($wanip)) {
2061
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2062
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2063
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2064
						$notify_text .= sprintf(gettext("DynDNS updated IP Address (A) for {$dnsupdate['host']} on %s (%s) to %s"), convert_real_interface_to_friendly_descr($if), $if, $wanip) . "\n";
2065
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2066
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2067
						$need_update = true;
2068
					} else {
2069
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2070
					}
2071
				} else
2072
					@unlink($cacheFile);
2073

    
2074
				/* Update IPv6 if we have it. */
2075
				if (is_ipaddrv6($wanipv6)) {
2076
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2077
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2078
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2079
						$notify_text .= sprintf(gettext("DynDNS updated IPv6 Address (AAAA) for {$dnsupdate['host']} on %s (%s) to %s"), convert_real_interface_to_friendly_descr($if), $if, $wanipv6) . "\n";
2080
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2081
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2082
						$need_update = true;
2083
					} else {
2084
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2085
					}
2086
				} else
2087
					@unlink("{$cacheFile}.ipv6");
2088
				conf_mount_ro();
2089

    
2090
				$upinst .= "\n";	/* mind that trailing newline! */
2091

    
2092
				if ($need_update) {
2093
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2094
					unset($upinst);
2095
					/* invoke nsupdate */
2096
					$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2097
					if (isset($dnsupdate['usetcp']))
2098
						$cmd .= " -v";
2099
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2100
					mwexec_bg($cmd);
2101
					unset($cmd);
2102
				}
2103
			}
2104
		}
2105
		if (!empty($notify_text)) {
2106
			notify_all_remote($notify_text);
2107
		}
2108
	}
2109

    
2110
	return 0;
2111
}
2112

    
2113
/* configure cron service */
2114
function configure_cron() {
2115
	global $g, $config;
2116

    
2117
	conf_mount_rw();
2118
	/* preserve existing crontab entries */
2119
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2120

    
2121
	for ($i = 0; $i < count($crontab_contents); $i++) {
2122
		$cron_item =& $crontab_contents[$i];
2123
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2124
			array_splice($crontab_contents, $i - 1);
2125
			break;
2126
		}
2127
	}
2128
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2129

    
2130

    
2131
	if (is_array($config['cron']['item'])) {
2132
		$crontab_contents .= "#\n";
2133
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2134
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2135
		$crontab_contents .= "#\n";
2136

    
2137
		foreach ($config['cron']['item'] as $item) {
2138
			$crontab_contents .= "\n{$item['minute']}\t";
2139
			$crontab_contents .= "{$item['hour']}\t";
2140
			$crontab_contents .= "{$item['mday']}\t";
2141
			$crontab_contents .= "{$item['month']}\t";
2142
			$crontab_contents .= "{$item['wday']}\t";
2143
			$crontab_contents .= "{$item['who']}\t";
2144
			$crontab_contents .= "{$item['command']}";
2145
		}
2146

    
2147
		$crontab_contents .= "\n#\n";
2148
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2149
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2150
		$crontab_contents .= "#\n\n";
2151
	}
2152

    
2153
	/* please maintain the newline at the end of file */
2154
	file_put_contents("/etc/crontab", $crontab_contents);
2155
	unset($crontab_contents);
2156

    
2157
	/* do a HUP kill to force sync changes */
2158
	exec('/bin/pkill -HUP cron');
2159

    
2160
	conf_mount_ro();
2161
}
2162

    
2163
function upnp_action ($action) {
2164
	global $g, $config;
2165
	switch($action) {
2166
		case "start":
2167
			if (file_exists('/var/etc/miniupnpd.conf')) {
2168
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2169
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2170
			}
2171
			break;
2172
		case "stop":
2173
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2174
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2175
				mwexec('killall miniupnpd 2>/dev/null', true);
2176
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2177
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2178
			break;
2179
		case "restart":
2180
			upnp_action('stop');
2181
			upnp_action('start');
2182
			break;
2183
	}
2184
}
2185

    
2186
function upnp_start() {
2187
	global $config;
2188

    
2189
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2190
		return;
2191

    
2192
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2193
		echo gettext("Starting UPnP service... ");
2194
		require_once('/usr/local/pkg/miniupnpd.inc');
2195
		sync_package_miniupnpd();
2196
		echo "done.\n";
2197
	}
2198
}
2199

    
2200
function install_cron_job($command, $active=false, $minute="0", $hour="*", $monthday="*", $month="*", $weekday="*", $who="root") {
2201
	global $config, $g;
2202

    
2203
	$is_installed = false;
2204

    
2205
	if (!is_array($config['cron']))
2206
		$config['cron'] = array();
2207
	if (!is_array($config['cron']['item']))
2208
		$config['cron']['item'] = array();
2209

    
2210
	$x=0;
2211
	foreach($config['cron']['item'] as $item) {
2212
		if(strstr($item['command'], $command)) {
2213
			$is_installed = true;
2214
			break;
2215
		}
2216
		$x++;
2217
	}
2218

    
2219
	if($active) {
2220
		$cron_item = array();
2221
		$cron_item['minute'] = $minute;
2222
		$cron_item['hour'] = $hour;
2223
		$cron_item['mday'] = $monthday;
2224
		$cron_item['month'] = $month;
2225
		$cron_item['wday'] = $weekday;
2226
		$cron_item['who'] = $who;
2227
		$cron_item['command'] = $command;
2228
		if(!$is_installed) {
2229
			$config['cron']['item'][] = $cron_item;
2230
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2231
		} else {
2232
			$config['cron']['item'][$x] = $cron_item;
2233
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2234
		}
2235
	} else {
2236
		if($is_installed == true) {
2237
			unset($config['cron']['item'][$x]);
2238
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2239
		}
2240
	}
2241
	configure_cron();
2242
}
2243

    
2244
?>
(49-49/66)