Projet

Général

Profil

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

univnautes / etc / inc / services.inc @ ce30ee0e

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 .= " --$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
# univnautes
1945
%ucd
1946

    
1947
laConfig.1 = "6.0"
1948
laErrMessage.1 = "1min load average is high!"
1949
laConfig.2 = "5.0"
1950
laErrMessage.2 = "5min load average is high!"
1951
laConfig.3 = "4.0"
1952
laErrMessage.3 = "15min load average is high!"
1953

    
1954
prNames.0 = "python"
1955
prNames.1 = "php"
1956
prNames.2 = "lighttpd"
1957
prNames.3 = "sshd"
1958
prNames.4 = "minicron"
1959

    
1960
extNames.0 = "uname"
1961
extCommand.0 = "/usr/bin/uname -a"
1962
extNames.1 = "uptime"
1963
extCommand.1 = "/usr/bin/uptime"
1964
extNames.2 = "cp_sessions"
1965
extCommand.2 = "/usr/local/bin/univnautes-value.sh cp_sessions"
1966
extNames.3 = "ip_whitelist"
1967
extCommand.3 = "/usr/local/bin/univnautes-value.sh ip_whitelist"
1968
extNames.4 = "idp_federation"
1969
extCommand.4 = "/usr/local/bin/univnautes-value.sh idp_federation"
1970
extNames.5 = "idp_local"
1971
extCommand.5 = "/usr/local/bin/univnautes-value.sh idp_local"
1972
extNames.6 = "mdurl"
1973
extCommand.6 = "/usr/local/bin/univnautes-value.sh mdurl"
1974
extNames.7 = "wlurl"
1975
extCommand.7 = "/usr/local/bin/univnautes-value.sh wlurl"
1976
extNames.8 = "defaultidp"
1977
extCommand.8 = "/usr/local/bin/univnautes-value.sh defaultidp"
1978

    
1979
EOD;
1980
			}
1981
			if(isset($config['snmpd']['modules']['regex'])) {
1982
				$snmpdconf .= <<<EOD
1983
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1984

    
1985
EOD;
1986
			}
1987
		}
1988

    
1989
		fwrite($fd, $snmpdconf);
1990
		fclose($fd);
1991
		unset($snmpdconf);
1992

    
1993
		if (isset($config['snmpd']['bindlan'])) {
1994
			$bindlan = "";
1995
		}
1996

    
1997
		/* run bsnmpd */
1998
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1999
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
2000

    
2001
		if ($g['booting'])
2002
			echo gettext("done.") . "\n";
2003
	}
2004

    
2005
	return 0;
2006
}
2007

    
2008
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
2009
	global $config, $g;
2010
	if(isset($config['system']['developerspew'])) {
2011
		$mt = microtime();
2012
		echo "services_dnsupdate_process() being called $mt\n";
2013
	}
2014

    
2015
	/* Dynamic DNS updating active? */
2016
	if (is_array($config['dnsupdates']['dnsupdate'])) {
2017
		$notify_text = "";
2018
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
2019
			if (!isset($dnsupdate['enable']))
2020
				continue;
2021
			if (!empty($int) && $int != $dnsupdate['interface'])
2022
				continue;
2023
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
2024
				continue;
2025

    
2026
			/* determine interface name */
2027
			$if = get_real_interface($dnsupdate['interface']);
2028
			if (isset($dnsupdate['usepublicip']))
2029
                                $wanip = dyndnsCheckIP($dnsupdate['interface']);
2030
                        else
2031
                                $wanip = get_interface_ip($dnsupdate['interface']);
2032
			
2033
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2034
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2035
			$currentTime = time();
2036

    
2037
			if ($wanip || $wanipv6) {
2038
				$keyname = $dnsupdate['keyname'];
2039
				/* trailing dot */
2040
				if (substr($keyname, -1) != ".")
2041
					$keyname .= ".";
2042

    
2043
				$hostname = $dnsupdate['host'];
2044
				/* trailing dot */
2045
				if (substr($hostname, -1) != ".")
2046
					$hostname .= ".";
2047

    
2048
				/* write private key file
2049
				   this is dumb - public and private keys are the same for HMAC-MD5,
2050
				   but nsupdate insists on having both */
2051
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2052
				$privkey = <<<EOD
2053
Private-key-format: v1.2
2054
Algorithm: 157 (HMAC)
2055
Key: {$dnsupdate['keydata']}
2056

    
2057
EOD;
2058
				fwrite($fd, $privkey);
2059
				fclose($fd);
2060

    
2061
				/* write public key file */
2062
				if ($dnsupdate['keytype'] == "zone") {
2063
					$flags = 257;
2064
					$proto = 3;
2065
				} else if ($dnsupdate['keytype'] == "host") {
2066
					$flags = 513;
2067
					$proto = 3;
2068
				} else if ($dnsupdate['keytype'] == "user") {
2069
					$flags = 0;
2070
					$proto = 2;
2071
				}
2072

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

    
2077
				/* generate update instructions */
2078
				$upinst = "";
2079
				if (!empty($dnsupdate['server']))
2080
					$upinst .= "server {$dnsupdate['server']}\n";
2081

    
2082
				if (file_exists($cacheFile)) {
2083
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2084
				}
2085
				if (file_exists("{$cacheFile}.ipv6")) {
2086
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2087
				}
2088

    
2089
				// 25 Days
2090
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2091
				$need_update = false;
2092

    
2093
				conf_mount_rw();
2094
				/* Update IPv4 if we have it. */
2095
				if (is_ipaddrv4($wanip)) {
2096
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2097
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2098
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2099
						$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";
2100
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2101
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2102
						$need_update = true;
2103
					} else {
2104
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2105
					}
2106
				} else
2107
					@unlink($cacheFile);
2108

    
2109
				/* Update IPv6 if we have it. */
2110
				if (is_ipaddrv6($wanipv6)) {
2111
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2112
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2113
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2114
						$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";
2115
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2116
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2117
						$need_update = true;
2118
					} else {
2119
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2120
					}
2121
				} else
2122
					@unlink("{$cacheFile}.ipv6");
2123
				conf_mount_ro();
2124

    
2125
				$upinst .= "\n";	/* mind that trailing newline! */
2126

    
2127
				if ($need_update) {
2128
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2129
					unset($upinst);
2130
					/* invoke nsupdate */
2131
					$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2132
					if (isset($dnsupdate['usetcp']))
2133
						$cmd .= " -v";
2134
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2135
					mwexec_bg($cmd);
2136
					unset($cmd);
2137
				}
2138
			}
2139
		}
2140
		if (!empty($notify_text)) {
2141
			notify_all_remote($notify_text);
2142
		}
2143
	}
2144

    
2145
	return 0;
2146
}
2147

    
2148
/* configure cron service */
2149
function configure_cron() {
2150
	global $g, $config;
2151

    
2152
	conf_mount_rw();
2153
	/* preserve existing crontab entries */
2154
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2155

    
2156
	for ($i = 0; $i < count($crontab_contents); $i++) {
2157
		$cron_item =& $crontab_contents[$i];
2158
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2159
			array_splice($crontab_contents, $i - 1);
2160
			break;
2161
		}
2162
	}
2163
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2164

    
2165

    
2166
	if (is_array($config['cron']['item'])) {
2167
		$crontab_contents .= "#\n";
2168
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2169
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2170
		$crontab_contents .= "#\n";
2171

    
2172
		foreach ($config['cron']['item'] as $item) {
2173
			$crontab_contents .= "\n{$item['minute']}\t";
2174
			$crontab_contents .= "{$item['hour']}\t";
2175
			$crontab_contents .= "{$item['mday']}\t";
2176
			$crontab_contents .= "{$item['month']}\t";
2177
			$crontab_contents .= "{$item['wday']}\t";
2178
			$crontab_contents .= "{$item['who']}\t";
2179
			$crontab_contents .= "{$item['command']}";
2180
		}
2181

    
2182
		$crontab_contents .= "\n#\n";
2183
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2184
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2185
		$crontab_contents .= "#\n\n";
2186
	}
2187

    
2188
	/* please maintain the newline at the end of file */
2189
	file_put_contents("/etc/crontab", $crontab_contents);
2190
	unset($crontab_contents);
2191

    
2192
	/* do a HUP kill to force sync changes */
2193
	exec('/bin/pkill -HUP cron');
2194

    
2195
	conf_mount_ro();
2196
}
2197

    
2198
function upnp_action ($action) {
2199
	global $g, $config;
2200
	switch($action) {
2201
		case "start":
2202
			if (file_exists('/var/etc/miniupnpd.conf')) {
2203
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2204
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2205
			}
2206
			break;
2207
		case "stop":
2208
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2209
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2210
				mwexec('killall miniupnpd 2>/dev/null', true);
2211
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2212
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2213
			break;
2214
		case "restart":
2215
			upnp_action('stop');
2216
			upnp_action('start');
2217
			break;
2218
	}
2219
}
2220

    
2221
function upnp_start() {
2222
	global $config;
2223

    
2224
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2225
		return;
2226

    
2227
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2228
		echo gettext("Starting UPnP service... ");
2229
		require_once('/usr/local/pkg/miniupnpd.inc');
2230
		sync_package_miniupnpd();
2231
		echo "done.\n";
2232
	}
2233
}
2234

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

    
2238
	$is_installed = false;
2239

    
2240
	if (!is_array($config['cron']))
2241
		$config['cron'] = array();
2242
	if (!is_array($config['cron']['item']))
2243
		$config['cron']['item'] = array();
2244

    
2245
	$x=0;
2246
	foreach($config['cron']['item'] as $item) {
2247
		if(strstr($item['command'], $command)) {
2248
			$is_installed = true;
2249
			break;
2250
		}
2251
		$x++;
2252
	}
2253

    
2254
	if($active) {
2255
		$cron_item = array();
2256
		$cron_item['minute'] = $minute;
2257
		$cron_item['hour'] = $hour;
2258
		$cron_item['mday'] = $monthday;
2259
		$cron_item['month'] = $month;
2260
		$cron_item['wday'] = $weekday;
2261
		$cron_item['who'] = $who;
2262
		$cron_item['command'] = $command;
2263
		if(!$is_installed) {
2264
			$config['cron']['item'][] = $cron_item;
2265
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2266
		} else {
2267
			$config['cron']['item'][$x] = $cron_item;
2268
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2269
		}
2270
	} else {
2271
		if($is_installed == true) {
2272
			unset($config['cron']['item'][$x]);
2273
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2274
		}
2275
	}
2276
	configure_cron();
2277
}
2278

    
2279
?>
(50-50/67)