Projet

Général

Profil

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

univnautes / etc / inc / services.inc @ 8b8085ce

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 IPs defined!"));
480
			}
481
			if($skew > 10) {
482
				$type = "secondary";
483
				$my_port = "520";
484
				$peer_port = "519";
485
			} else {
486
				$my_port = "519";
487
				$peer_port = "520";
488
				$type = "primary";
489
				$dhcpdconf_pri  = "split 128;\n";
490
				$dhcpdconf_pri .= "  mclt 600;\n";
491
			}
492
			$dhcpdconf .= <<<EOPP
493
failover peer "dhcp_{$dhcpif}" {
494
  {$type};
495
  address {$intip};
496
  port {$my_port};
497
  peer address {$dhcpifconf['failover_peerip']};
498
  peer port {$peer_port};
499
  max-response-delay 10;
500
  max-unacked-updates 10;
501
  {$dhcpdconf_pri}
502
  load balance max seconds 3;
503
}
504
\n
505
EOPP;
506
		}
507
	}
508

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

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

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

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

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

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

    
534
		$dnscfg = "";
535

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

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

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

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

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

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

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

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

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

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

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

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

    
638
			$pdnscfg = "";
639

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
768
EOD;
769

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

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

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

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

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

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

    
797
				$smdnscfg = "";
798

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
910
	return 0;
911
}
912

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

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

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

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

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

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

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

    
956

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

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

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

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

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

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

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

    
1020
	$dhcpdv6conf = <<<EOD
1021

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

    
1034
EOD;
1035

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

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

    
1042
	$dhcpdv6ifs = array();
1043

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

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

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

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

    
1060
		$dnscfgv6 = "";
1061

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

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

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

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

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

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

    
1104
EOD;
1105

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1218
	/* fire up dhcpd in a chroot */
1219
	if (count($dhcpdv6ifs) > 0) {
1220
		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 " .
1221
			join(" ", $dhcpdv6ifs));
1222
		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");
1223
	}
1224
	if ($g['booting'])
1225
		print gettext("done.") . "\n";
1226

    
1227
	return 0;
1228
}
1229

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

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

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

    
1239
        $iflist = get_configured_interface_list();
1240

    
1241
        $igmpconf = <<<EOD
1242

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

    
1248
EOD;
1249

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

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

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

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

    
1285
        return 0;
1286
}
1287

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

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

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

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

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

    
1311
	$iflist = get_configured_interface_list();
1312

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

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

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

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

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

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

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

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

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

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

    
1407
	return 0;
1408
}
1409

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

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

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

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

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

    
1433
	$iflist = get_configured_interface_list();
1434

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

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

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

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

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

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

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

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

    
1526
	return 0;
1527
}
1528

    
1529
function services_dyndns_configure_client($conf) {
1530

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

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

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

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

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

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

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

    
1582
	return 0;
1583
}
1584

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

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

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

    
1622

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

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

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

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

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

    
1643
		$args = "";
1644

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1765
	return $return;
1766
}
1767

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

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

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

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

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

    
1793

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

    
1799
EOD;
1800

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

    
1807
EOD;
1808
		}
1809
*/
1810

    
1811

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

    
1819

    
1820
EOD;
1821
		}
1822

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

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

    
1839
EOD;
1840

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

    
1846
EOD;
1847
		}
1848
*/
1849

    
1850

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

    
1857
EOD;
1858
		}
1859

    
1860

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

    
1864
EOD;
1865

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

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

    
1885
EOD;
1886

    
1887
		}
1888

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

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

    
1898
snmpEnableAuthenTraps = 2
1899

    
1900
EOD;
1901

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

    
1907
EOD;
1908
		    }
1909

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

    
1916
EOD;
1917
		    }
1918

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

    
1923
EOD;
1924
		    }
1925

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

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

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

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

    
1949
EOD;
1950
			}
1951
		}
1952

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

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

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

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

    
1969
	return 0;
1970
}
1971

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2109
	return 0;
2110
}
2111

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

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

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

    
2129

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

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

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

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

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

    
2159
	conf_mount_ro();
2160
}
2161

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

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

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

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

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

    
2202
	$is_installed = false;
2203

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

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

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

    
2243
?>
(49-49/66)