Project

General

Profile

Download (70.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	services.inc
4
	part of the pfSense project (http://www.pfsense.com)
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() {
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
		if (!isset($dhcpv6ifconf['ramode']))
76
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
77

    
78
		/* are router advertisements enabled? */
79
		if ($dhcpv6ifconf['ramode'] == "disabled")
80
			continue;
81

    
82
		if (!isset($dhcpv6ifconf['rapriority']))
83
			$dhcpv6ifconf['rapriority'] = "medium";
84

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

    
95
		$realif = get_real_interface($dhcpv6if, "inet6");
96
		if (isset($radvdifs[$realif]))
97
			continue;
98

    
99
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
100
		if (!is_ipaddrv6($ifcfgipv6))
101
			continue;
102

    
103
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
104
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
105
		$radvdifs[$realif] = $realif;
106

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

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

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

    
207
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
208
	foreach ($Iflist as $if => $ifdescr) {
209
		if(!isset($config['interfaces'][$if]['track6-interface']))
210
			continue;
211
		if(!isset($config['interfaces'][$if]['enable']))
212
			continue;
213
		$trackif = $config['interfaces'][$if]['track6-interface'];
214
		if (empty($config['interfaces'][$trackif]))
215
			continue;
216

    
217
		$realif = get_real_interface($if, "inet6");
218
		/* prevent duplicate entries, manual overrides */
219
		if (isset($radvdifs[$realif]))
220
			continue;
221

    
222
		$ifcfgipv6 = get_interface_ipv6($if);
223
		if(!is_ipaddrv6($ifcfgipv6))
224
			continue;
225

    
226
		$ifcfgsnv6 = get_interface_subnetv6($if);
227
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
228
		$radvdifs[$realif] = $realif;
229

    
230
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
231
	
232
		if ($g['debug'])
233
			log_error("configuring RA on {$if} for type {$autotype} radvd subnet {$subnetv6}/{$ifcfgsnv6}");
234

    
235
		$radvdconf .= "# Generated config for {$autotype} delegation from {$trackif} on {$if}\n";
236
		$radvdconf .= "interface {$realif} {\n";
237
		$radvdconf .= "\tAdvSendAdvert on;\n";
238
		$radvdconf .= "\tMinRtrAdvInterval 3;\n";
239
		$radvdconf .= "\tMaxRtrAdvInterval 10;\n";
240
		$mtu = get_interface_mtu($realif);
241
		if (is_numeric($mtu))
242
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
243
		else
244
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
245
		$radvdconf .= "\tAdvOtherConfigFlag on;\n";
246
		$radvdconf .= "\t\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
247
		$radvdconf .= "\t\tAdvOnLink on;\n";
248
		$radvdconf .= "\t\tAdvAutonomous on;\n";
249
		$radvdconf .= "\t\tAdvRouterAddr on;\n";
250
		$radvdconf .= "\t};\n";
251

    
252
		/* add DNS servers */
253
		$dnslist = array();
254
		if (isset($config['dnsmasq']['enable'])) {
255
			$dnslist[] = $ifcfgipv6;
256
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
257
			foreach($config['system']['dnsserver'] as $server) {
258
				if(is_ipaddrv6($server))
259
					$dnslist[] = $server;
260
			}
261
		}
262
		if (count($dnslist) > 0) {
263
			$dnsstring = implode(" ", $dnslist);
264
			if (!empty($dnsstring))
265
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
266
		}
267
		if (!empty($config['system']['domain'])) {
268
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
269
		}
270
		$radvdconf .= "};\n";
271
	}
272

    
273
	/* write radvd.conf */
274
	if (!@file_put_contents("{$g['varetc_path']}/radvd.conf", $radvdconf)) {
275
		log_error("Error: cannot open radvd.conf in services_radvd_configure().\n");
276
		if ($g['booting'])
277
			printf("Error: cannot open radvd.conf in services_radvd_configure().\n");
278
	}
279
	unset($radvdconf);
280

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

    
298
function services_dhcpd_configure($family = "all") {
299
	global $config, $g;
300

    
301
	/* configure DHCPD chroot once */
302
	$fd = fopen("{$g['tmp_path']}/dhcpd.sh","w");
303
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}\n");
304
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/dev\n");
305
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/etc\n");
306
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr/local/sbin\n");
307
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db\n");
308
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/run\n");
309
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr\n");
310
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/lib\n");
311
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/run\n");
312
	fwrite($fd, "/usr/sbin/chown -R dhcpd:_dhcp {$g['dhcpd_chroot_path']}/*\n");
313
	fwrite($fd, "/bin/cp -n /lib/libc.so.* {$g['dhcpd_chroot_path']}/lib/\n");
314
	fwrite($fd, "/bin/cp -n /usr/local/sbin/dhcpd {$g['dhcpd_chroot_path']}/usr/local/sbin/\n");
315
	fwrite($fd, "/bin/chmod a+rx {$g['dhcpd_chroot_path']}/usr/local/sbin/dhcpd\n");
316

    
317
	$status = `/sbin/mount | /usr/bin/grep -v grep  | /usr/bin/grep  "{$g['dhcpd_chroot_path']}/dev"`;
318
	if (!trim($status))
319
		fwrite($fd, "/sbin/mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
320
	fclose($fd);
321
	mwexec("/bin/sh {$g['tmp_path']}/dhcpd.sh");
322

    
323
	if ($family == "all" || $family == "inet")
324
		services_dhcpdv4_configure();
325
	if ($family == "all" || $family == "inet6") {
326
		services_dhcpdv6_configure();
327
		services_radvd_configure();
328
	}
329
}
330

    
331
function services_dhcpdv4_configure() {
332
	global $config, $g;
333
	$need_ddns_updates = false;
334
	$ddns_zones = array();
335

    
336
	if($g['services_dhcp_server_enable'] == false)
337
		return;
338

    
339
	if(isset($config['system']['developerspew'])) {
340
		$mt = microtime();
341
		echo "services_dhcpdv4_configure($if) being called $mt\n";
342
	}
343

    
344
	/* kill any running dhcpd */
345
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
346
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
347

    
348
	/* DHCP enabled on any interfaces? */
349
	if (!is_dhcp_server_enabled())
350
		return 0;
351

    
352
	/* if OLSRD is enabled, allow WAN to house DHCP. */
353
	if($config['installedpackages']['olsrd'])
354
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
355
				if($olsrd['enable'])
356
					$is_olsr_enabled = true;
357

    
358
	if ($g['booting']) {
359
		/* restore the leases, if we have them */
360
		if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
361
			$dhcprestore = "";
362
			$dhcpreturn = "";
363
			exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
364
			$dhcprestore = implode(" ", $dhcprestore);
365
			if($dhcpreturn <> 0) {
366
				log_error(sprintf(gettext('DHCP leases restore failed exited with %1$s, the error is: %2$s%3$s'), $dhcpreturn, $dhcprestore, "\n"));
367
			}
368
		}
369
		/* 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. */
370
		if (($g['platform'] == "pfSense") && !isset($config['system']['use_mfs_tmpvar'])) {
371
			unlink_if_exists("{$g['cf_conf_path']}/dhcpleases.tgz");
372
		}
373
	}
374

    
375
	$syscfg = $config['system'];
376
	if (!is_array($config['dhcpd']))
377
		$config['dhcpd'] = array();
378
	$dhcpdcfg = $config['dhcpd'];
379
	$Iflist = get_configured_interface_list();
380

    
381
	if ($g['booting'])
382
		echo gettext("Starting DHCP service...");
383
	else
384
		sleep(1);
385

    
386
	$custoptions = "";
387
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
388
		if(is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) {
389
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
390
				if(!empty($item['type']))
391
					$itemtype = $item['type'];
392
				else
393
					$itemtype = "text";
394
				$custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n";
395
			}
396
		}
397
	}
398

    
399
	$dhcpdconf = <<<EOD
400

    
401
option domain-name "{$syscfg['domain']}";
402
option ldap-server code 95 = text;
403
option domain-search-list code 119 = text;
404
{$custoptions}
405
default-lease-time 7200;
406
max-lease-time 86400;
407
log-facility local7;
408
one-lease-per-client true;
409
deny duplicates;
410
ping-check true;
411

    
412
EOD;
413

    
414
	if(!isset($dhcpifconf['disableauthoritative']))
415
		$dhcpdconf .= "authoritative;\n";
416

    
417
	if(isset($dhcpifconf['alwaysbroadcast']))
418
		$dhcpdconf .= "always-broadcast on\n";
419

    
420
	$dhcpdifs = array();
421
	$add_routers = false;
422
	$gateways_arr = return_gateways_array();
423
	/* only add a routers line if the system has any IPv4 gateway at all */
424
	/* a static route has a gateway, manually overriding this field always works */
425
	foreach($gateways_arr as $gwitem) {
426
		if($gwitem['ipprotocol'] == "inet") {
427
			$add_routers = true;
428
			break;
429
		}
430
	}
431

    
432
	/*    loop through and determine if we need to setup
433
	 *    failover peer "bleh" entries
434
	 */
435
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
436

    
437
		interfaces_staticarp_configure($dhcpif);
438

    
439
		if (!isset($dhcpifconf['enable']))
440
			continue;
441

    
442
		if($dhcpifconf['failover_peerip'] <> "") {
443
			$int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
444
			$intip = find_interface_ip($int);
445
			$real_dhcpif = convert_friendly_interface_to_real_interface_name($dhcpif);
446
			/*
447
			 *    yep, failover peer is defined.
448
			 *    does it match up to a defined vip?
449
			 */
450
			$skew = 110;
451
			$a_vip = &$config['virtualip']['vip'];
452
			if(is_array($a_vip)) {
453
				foreach ($a_vip as $vipent) {
454
					if($int == $real_dhcpif) {
455
						/* this is the interface! */
456
						if(is_numeric($vipent['advskew']) && ($vipent['advskew'] < "20"))
457
							$skew = 0;
458
					}
459
				}
460
			} else {
461
				log_error(gettext("Warning!  DHCP Failover setup and no CARP virtual IP's defined!"));
462
			}
463
			if($skew > 10) {
464
				$type = "secondary";
465
				$dhcpdconf_pri  = "mclt 600;\n";
466
				$my_port = "520";
467
				$peer_port = "519";
468
			} else {
469
				$my_port = "519";
470
				$peer_port = "520";
471
				$type = "primary";
472
				$dhcpdconf_pri  = "split 128;\n";
473
				$dhcpdconf_pri .= "  mclt 600;\n";
474
			}
475
			$dhcpdconf .= <<<EOPP
476
failover peer "dhcp_{$dhcpif}" {
477
  {$type};
478
  address {$intip};
479
  port {$my_port};
480
  peer address {$dhcpifconf['failover_peerip']};
481
  peer port {$peer_port};
482
  max-response-delay 10;
483
  max-unacked-updates 10;
484
  {$dhcpdconf_pri}
485
  load balance max seconds 3;
486
}
487

    
488
EOPP;
489
		}
490
	}
491

    
492
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
493

    
494
		$newzone = array();
495
		$ifcfg = $config['interfaces'][$dhcpif];
496

    
497
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
498
			continue;
499
		$ifcfgip = get_interface_ip($dhcpif);
500
		$ifcfgsn = get_interface_subnet($dhcpif);
501
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
502
		$subnetmask = gen_subnet_mask($ifcfgsn);
503

    
504
		if (!is_ipaddr($subnet))
505
			continue;
506

    
507
		if($is_olsr_enabled == true)
508
			if($dhcpifconf['netmask'])
509
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
510

    
511
		$all_pools = array();
512
		$all_pools[] = $dhcpifconf;
513
		if (is_array($dhcpifconf['pool'])) {
514
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
515
		}
516

    
517
		$dnscfg = "";
518

    
519
		if ($dhcpifconf['domain']) {
520
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
521
		}
522

    
523
		if($dhcpifconf['domainsearchlist'] <> "") {
524
			$dnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpifconf['domainsearchlist'])) . "\";\n";
525
		}
526

    
527
		if (isset($dhcpifconf['ddnsupdate'])) {
528
			$need_ddns_updates = true;
529
			$newzone = array();
530
			if($dhcpifconf['ddnsdomain'] <> "") {
531
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
532
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
533
			} else {
534
				$newzone['domain-name'] = $config['system']['domain'];
535
			}
536
			$revsubnet = explode(".", $subnet);
537
			$revsubnet = array_reverse($revsubnet);
538
			foreach ($revsubnet as $octet) {
539
				if ($octet != "0")
540
					break;
541
				array_shift($revsubnet);
542
			}
543
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
544
		}
545

    
546
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
547
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
548
			if ($newzone['domain-name'])
549
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
550
		} else if (isset($config['dnsmasq']['enable'])) {
551
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
552
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0]))
553
				$newzone['dns-servers'] = $syscfg['dnsserver'];
554
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
555
			$dnscfg .= "	option domain-name-servers " . join(",", $syscfg['dnsserver']) . ";";
556
			if ($newzone['domain-name'])
557
				$newzone['dns-servers'] = $syscfg['dnsserver'];
558
		}
559

    
560
		/* Create classes - These all contain comma separated lists. Join them into one 
561
		   big comma separated string then split them all up. */
562
		$all_mac_strings = array();
563
		if (is_array($dhcpifconf['pool'])) {
564
			foreach($all_pools as $poolconf) {
565
				$all_mac_strings[] = $poolconf['mac_allow'];
566
				$all_mac_strings[] = $poolconf['mac_deny'];
567
			}
568
		}
569
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
570
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
571
		$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
572
		foreach ($all_mac_list as $mac) {
573
			if (empty($mac))
574
				continue;
575
			$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
576
			// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
577
			$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
578
			$dhcpdconf .= '}' . "\n";
579
		}
580

    
581
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
582

    
583
// Setup pool options
584
		foreach($all_pools as $poolconf) {
585
			$dhcpdconf .= "	pool {\n";
586
			/* is failover dns setup? */
587
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
588
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
589
				if($poolconf['dnsserver'][1] <> "")
590
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
591
				$dhcpdconf .= ";\n";
592
			}
593

    
594
			/* allow/deny MACs */
595
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
596
			foreach ($mac_allow_list as $mac) {
597
				if (empty($mac))
598
					continue;
599
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
600
			}
601
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
602
			foreach ($mac_deny_list as $mac) {
603
				if (empty($mac))
604
					continue;
605
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
606
			}
607

    
608
			if($poolconf['failover_peerip'] <> "")
609
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
610

    
611
			if (isset($poolconf['denyunknown']))
612
			   $dhcpdconf .= "		deny unknown-clients;\n";
613

    
614
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
615
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
616

    
617
			if($dhcpifconf['failover_peerip'] <> "") {
618
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
619
			}
620

    
621
			$pdnscfg = "";
622

    
623
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
624
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
625
			}
626

    
627
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
628
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
629
			}
630

    
631
			if (isset($poolconf['ddnsupdate'])) {
632
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
633
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
634
				$pdnscfg .= "		ddns-update-style interim;\n";
635
			}
636

    
637
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
638
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
639
			}
640
			$dhcpdconf .= "{$pdnscfg}";
641

    
642
			// default-lease-time
643
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
644
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
645

    
646
			// max-lease-time
647
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
648
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
649

    
650
			// netbios-name*
651
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
652
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
653
				$dhcpdconf .= "		option netbios-node-type 8;\n";
654
			}
655

    
656
			// ntp-servers
657
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
658
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
659

    
660
			// tftp-server-name
661
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
662
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
663

    
664
			// ldap-server
665
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
666
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
667

    
668
			// net boot information
669
			if(isset($poolconf['netboot'])) {
670
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
671
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
672
				}
673
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
674
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
675
				}
676
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
677
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
678
				}
679
			}
680
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
681
			$dhcpdconf .= "	}\n\n";
682
		}
683
// End of settings inside pools
684

    
685
		if ($dhcpifconf['gateway']) {
686
			$routers = $dhcpifconf['gateway'];
687
			$add_routers = true;
688
		} else {
689
			$routers = $ifcfgip;
690
		}
691
		if($add_routers)
692
			$dhcpdconf .= "	option routers {$routers};\n";
693

    
694
		$dhcpdconf .= <<<EOD
695
$dnscfg
696

    
697
EOD;
698
    		// default-lease-time
699
		if ($dhcpifconf['defaultleasetime'])
700
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
701

    
702
		// max-lease-time
703
		if ($dhcpifconf['maxleasetime'])
704
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
705

    
706
		// netbios-name*
707
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
708
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
709
			$dhcpdconf .= "	option netbios-node-type 8;\n";
710
		}
711

    
712
		// ntp-servers
713
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
714
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
715

    
716
		// tftp-server-name
717
		if ($dhcpifconf['tftp'] <> "")
718
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
719

    
720
		// Handle option, number rowhelper values
721
		$dhcpdconf .= "\n";
722
		if($dhcpifconf['numberoptions']['item']) {
723
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
724
				if(empty($item['type']) || $item['type'] == "text")
725
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
726
				else
727
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
728
			}
729
		}
730

    
731
		// ldap-server
732
		if ($dhcpifconf['ldap'] <> "")
733
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
734

    
735
		// net boot information
736
		if(isset($dhcpifconf['netboot'])) {
737
			if ($dhcpifconf['nextserver'] <> "") {
738
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
739
			}
740
			if ($dhcpifconf['filename'] <> "") {
741
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
742
			}
743
			if ($dhcpifconf['rootpath'] <> "") {
744
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
745
			}
746
		}
747

    
748
		$dhcpdconf .= <<<EOD
749
}
750

    
751
EOD;
752

    
753
		/* add static mappings */
754
		if (is_array($dhcpifconf['staticmap'])) {
755

    
756
			$i = 0;
757
			foreach ($dhcpifconf['staticmap'] as $sm) {
758
				$dhcpdconf .= <<<EOD
759
host s_{$dhcpif}_{$i} {
760
	hardware ethernet {$sm['mac']};
761

    
762
EOD;
763
				if ($sm['ipaddr'])
764
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
765

    
766
				if ($sm['hostname']) {
767
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
768
					$dhhostname = str_replace(".", "_", $dhhostname);
769
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
770
				}
771
				if ($sm['filename'])
772
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
773

    
774
				if ($sm['rootpath'])
775
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
776

    
777
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
778
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
779

    
780
				$smdnscfg = "";
781

    
782
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
783
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
784
				}
785

    
786
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
787
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
788
				}
789

    
790
				if (isset($sm['ddnsupdate'])) {
791
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
792
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
793
					$pdnscfg .= "		ddns-update-style interim;\n";
794
				}
795

    
796
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
797
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
798
				}
799
				$dhcpdconf .= "{$smdnscfg}";
800

    
801
				// default-lease-time
802
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
803
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
804

    
805
				// max-lease-time
806
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
807
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
808

    
809
				// netbios-name*
810
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
811
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
812
					$dhcpdconf .= "	option netbios-node-type 8;\n";
813
				}
814

    
815
				// ntp-servers
816
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
817
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
818

    
819
				// tftp-server-name
820
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
821
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
822

    
823
				$dhcpdconf .= "}\n";
824
				$i++;
825
			}
826
		}
827

    
828
		$dhcpdifs[] = get_real_interface($dhcpif);
829
		if ($newzone['domain-name'])
830
			$ddns_zones[] = $newzone;
831
	}
832

    
833
	if ($need_ddns_updates) {
834
		$dhcpdconf .= "ddns-update-style interim;\n";
835
		if (is_array($ddns_zones)) {
836
			$added_zones = array();
837
			foreach ($ddns_zones as $zone) {
838
				if (!is_array($zone) || empty($zone) || !is_array($zone['dns-servers']))
839
					continue;
840
				$primary = $zone['dns-servers'][0];
841
				$secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1];
842
				// Make sure we aren't using any invalid or IPv6 DNS servers.
843
				if (!is_ipaddrv4($primary)) {
844
					if (is_ipaddrv4($secondary)) {
845
						$primary = $secondary;
846
						$secondary = "";
847
					} else {
848
						continue;
849
					}
850
				}
851
				// We don't need to add zones multiple times.
852
				if (!in_array($zone['domain-name'], $added_zones)) {
853
					$dhcpdconf .= "zone {$zone['domain-name']} {\n";
854
					$dhcpdconf .= "	primary {$primary};\n";
855
					if (is_ipaddrv4($secondary))
856
						$dhcpdconf .= "	secondary {$secondary};\n";
857
					$dhcpdconf .= "}\n";
858
					$added_zones[] = $zone['domain-name'];
859
				}
860
				if (!in_array($zone['ptr-domain'], $added_zones)) {
861
					$dhcpdconf .= "zone {$zone['ptr-domain']} {\n";
862
					$dhcpdconf .= "	primary {$primary};\n";
863
					if (is_ipaddrv4($secondary))
864
						$dhcpdconf .= "	secondary {$secondary};\n";
865
					$dhcpdconf .= "}\n";
866
					$added_zones[] = $zone['ptr-domain'];
867
				}
868
			}
869
		}
870
	}
871

    
872
	/* write dhcpd.conf */
873
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
874
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
875
		unset($dhcpdconf);
876
		return 1;
877
	}
878
	unset($dhcpdconf);
879

    
880
	/* create an empty leases database */
881
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
882
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
883

    
884
	/* fire up dhcpd in a chroot */
885
	if (count($dhcpdifs) > 0) {
886
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
887
			join(" ", $dhcpdifs));
888
	}
889

    
890
	if ($g['booting'])
891
		print "done.\n";
892

    
893
	return 0;
894
}
895

    
896
function services_dhcpdv6_configure() {
897
	global $config, $g;
898

    
899
	if($g['services_dhcp_server_enable'] == false)
900
		return;
901

    
902
	if(isset($config['system']['developerspew'])) {
903
		$mt = microtime();
904
		echo "services_dhcpd_configure($if) being called $mt\n";
905
	}
906

    
907
	/* kill any running dhcpd */
908
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
909
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
910
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
911
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
912

    
913
	/* DHCP enabled on any interfaces? */
914
	if (!is_dhcpv6_server_enabled())
915
		return 0;
916

    
917
	if ($g['booting']) {
918
		if ($g['platform'] != "pfSense") {
919
			/* restore the leases, if we have them */
920
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
921
				$dhcprestore = "";
922
				$dhcpreturn = "";
923
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
924
				$dhcprestore = implode(" ", $dhcprestore);
925
				if($dhcpreturn <> 0) {
926
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
927
				}
928
			}
929
		}
930
	}
931

    
932
	$syscfg = $config['system'];
933
	if (!is_array($config['dhcpdv6']))
934
		$config['dhcpdv6'] = array();
935
	$dhcpdv6cfg = $config['dhcpdv6'];
936
	$Iflist = get_configured_interface_list();
937
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
938

    
939

    
940
	if ($g['booting'])
941
		echo "Starting DHCPv6 service...";
942
	else
943
		sleep(1);
944

    
945
	/* we add a fake entry for interfaces that are set to track6 another WAN */
946
	foreach ($Iflist as $ifname) {
947
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
948
			$realif = get_real_interface($ifname, "inet6");
949
			$ifcfgipv6 = get_interface_ipv6($ifname);
950
			if(!is_ipaddrv6($ifcfgipv6))
951
				continue;
952
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
953
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
954
			$trackcfg = $config['interfaces'][$trackifname];
955
			$pdlen = calculate_ipv6_delegation_length($trackifname);
956
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
957
			$dhcpdv6cfg[$ifname] = array();
958
			$dhcpdv6cfg[$ifname]['enable'] = true;
959
			/* range */
960
			$ifcfgipv6arr[7] = "1000";
961
			$dhcpdv6cfg[$ifname]['range'] = array();
962
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
963
			$ifcfgipv6arr[7] = "2000";
964
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
965
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
966
			if($pdlen > 2) {
967
				$pdlenmax = $pdlen;
968
				$pdlenhalf = $pdlenmax -1;
969
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
970
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
971
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
972

    
973
				/* set the delegation start to half the current address block */
974
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
975
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
976

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

    
981
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
982
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
983
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
984
			}
985
		}
986
	}
987

    
988
	$custoptionsv6 = "";
989
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
990
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
991
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
992
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
993
			}
994
		}
995
	}
996

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

    
1000
	$dhcpdv6conf = <<<EOD
1001

    
1002
option domain-name "{$syscfg['domain']}";
1003
option ldap-server code 95 = text;
1004
option domain-search-list code 119 = text;
1005
{$custoptionsv6}
1006
default-lease-time 7200;
1007
max-lease-time 86400;
1008
log-facility local7;
1009
ddns-update-style none;
1010
one-lease-per-client true;
1011
deny duplicates;
1012
ping-check true;
1013

    
1014
EOD;
1015

    
1016
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1017
		$dhcpdv6conf .= "authoritative;\n";
1018

    
1019
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1020
		$dhcpdv6conf .= "always-broadcast on\n";
1021

    
1022
	$dhcpdv6ifs = array();
1023

    
1024
	$dhcpv6num = 0;
1025
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1026

    
1027
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1028

    
1029
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1030
			continue;
1031
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1032
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1033
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1034

    
1035
		if ($is_olsr_enabled == true) {
1036
			if($dhcpv6ifconf['netmask'])
1037
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1038
		}
1039

    
1040
		$dnscfgv6 = "";
1041

    
1042
		if ($dhcpv6ifconf['domain']) {
1043
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1044
		}
1045

    
1046
    		if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1047
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1048
    		}
1049

    
1050
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1051
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1052
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1053
			}
1054
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1055
		}
1056

    
1057
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1058
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1059
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1060
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1061
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1062
			$dns_arrv6 = array();
1063
			foreach($syscfg['dnsserver'] as $dnsserver) {
1064
				if (is_ipaddrv6($dnsserver)) {
1065
					$dns_arrv6[] = $dnsserver;
1066
				}
1067
			}
1068
			if(!empty($dns_arrv6))
1069
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1070
		}
1071

    
1072
		if (is_ipaddrv6($ifcfgipv6)) {
1073
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1074
		} else {
1075
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1076
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1077
		}
1078
		$dhcpdv6conf .= " {\n";
1079

    
1080
		$dhcpdv6conf .= <<<EOD
1081
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1082
$dnscfgv6
1083

    
1084
EOD;
1085

    
1086
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1087
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1088
		}
1089
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1090
			$dhcpdv6conf .= "       option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1091
		}
1092
    		// default-lease-time
1093
		if ($dhcpv6ifconf['defaultleasetime'])
1094
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1095

    
1096
		// max-lease-time
1097
		if ($dhcpv6ifconf['maxleasetime'])
1098
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1099

    
1100
		// ntp-servers
1101
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1102
			$ntpservers = array();
1103
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1104
				if(is_ipaddrv6($ntpserver))
1105
					$ntpservers[] = $ntpserver;
1106
			}
1107
			if(count($ntpservers) > 0 )
1108
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1109
		}
1110
		// tftp-server-name
1111
		/* Needs ISC DHCPD support
1112
		 if ($dhcpv6ifconf['tftp'] <> "")
1113
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1114
		*/
1115

    
1116
		// Handle option, number rowhelper values
1117
		$dhcpdv6conf .= "\n";
1118
		if ($dhcpv6ifconf['numberoptions']['item']) {
1119
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1120
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1121
			}
1122
		}
1123

    
1124
		// ldap-server
1125
		if ($dhcpv6ifconf['ldap'] <> "")
1126
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1127

    
1128
		// net boot information
1129
		if(isset($dhcpv6ifconf['netboot'])) {
1130
			if (!empty($dhcpv6ifconf['bootfile_url'])) {
1131
				$dhcpdv6conf .= "	option dhcp6.bootfile-url \"{$dhcpv6ifconf['bootfile_url']}\";\n";
1132
			}
1133
		}
1134

    
1135
		$dhcpdv6conf .= "}\n";
1136

    
1137
		/* add static mappings */
1138
		/* Needs to use DUID */
1139
		if (is_array($dhcpv6ifconf['staticmap'])) {
1140
			$i = 0;
1141
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1142
				$dhcpdv6conf .= <<<EOD
1143
host s_{$dhcpv6if}_{$i} {
1144
	host-identifier option dhcp6.client-id {$sm['duid']};
1145

    
1146
EOD;
1147
				if ($sm['ipaddrv6'])
1148
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1149

    
1150
				if ($sm['hostname']) {
1151
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1152
					$dhhostname = str_replace(".", "_", $dhhostname);
1153
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1154
				}
1155
				if ($sm['filename'])
1156
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1157

    
1158
				if ($sm['rootpath'])
1159
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1160

    
1161
				$dhcpdv6conf .= "}\n";
1162
				$i++;
1163
			}
1164
		}
1165

    
1166
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1167
			if(preg_match("/poes/si", $dhcpv6if)) {
1168
				/* magic here */
1169
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1170
			} else {
1171
				$realif = get_real_interface($dhcpv6if, "inet6");
1172
				if (stristr("$realif", "bridge")) {
1173
					$mac = get_interface_mac($realif);
1174
					$v6address = generate_ipv6_from_mac($mac);
1175
					/* Create link local address for bridges */
1176
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1177
				}
1178
				$realif = escapeshellcmd($realif);
1179
				$dhcpdv6ifs[] = $realif;
1180
			}
1181
		}
1182
	}
1183

    
1184
	/* write dhcpdv6.conf */
1185
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1186
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1187
		if ($g['booting'])
1188
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1189
		unset($dhcpdv6conf);
1190
		return 1;
1191
	}
1192
	unset($dhcpdv6conf);
1193

    
1194
	/* create an empty leases v6 database */
1195
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1196
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1197

    
1198
	/* fire up dhcpd in a chroot */
1199
	if (count($dhcpdv6ifs) > 0) {
1200
		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 " .
1201
			join(" ", $dhcpdv6ifs));
1202
		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");
1203
	}
1204
	if ($g['booting'])
1205
		print gettext("done.") . "\n";
1206

    
1207
	return 0;
1208
}
1209

    
1210
function services_igmpproxy_configure() {
1211
        global $config, $g;
1212

    
1213
        /* kill any running igmpproxy */
1214
        killbyname("igmpproxy");
1215

    
1216
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1217
		return 1;
1218

    
1219
        $iflist = get_configured_interface_list();
1220

    
1221
        $igmpconf = <<<EOD
1222

    
1223
##------------------------------------------------------
1224
## Enable Quickleave mode (Sends Leave instantly)
1225
##------------------------------------------------------
1226
quickleave
1227

    
1228
EOD;
1229

    
1230
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1231
                unset($iflist[$igmpcf['ifname']]);
1232
                $realif = get_real_interface($igmpcf['ifname']);
1233
                if (empty($igmpcf['threshold']))
1234
                        $threshld = 1;
1235
                else
1236
                        $threshld = $igmpcf['threshold'];
1237
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1238

    
1239
                if ($igmpcf['address'] <> "") {
1240
                        $item = explode(" ", $igmpcf['address']);
1241
                        foreach($item as $iww)
1242
                                $igmpconf .= "altnet {$iww}\n";
1243
                }
1244
                $igmpconf .= "\n";
1245
        }
1246
        foreach ($iflist as $ifn) {
1247
                $realif = get_real_interface($ifn);
1248
                $igmpconf .= "phyint {$realif} disabled\n";
1249
        }
1250
	$igmpconf .= "\n";
1251

    
1252
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1253
        if (!$igmpfl) {
1254
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1255
                return;
1256
        }
1257
        fwrite($igmpfl, $igmpconf);
1258
        fclose($igmpfl);
1259
	unset($igmpconf);
1260

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

    
1265
        return 0;
1266
}
1267

    
1268
function services_dhcrelay_configure() {
1269
	global $config, $g;
1270
	if ($g['platform'] == 'jail')
1271
		return;
1272
	if(isset($config['system']['developerspew'])) {
1273
		$mt = microtime();
1274
		echo "services_dhcrelay_configure() being called $mt\n";
1275
	}
1276

    
1277
	/* kill any running dhcrelay */
1278
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1279

    
1280
	$dhcrelaycfg =& $config['dhcrelay'];
1281

    
1282
	/* DHCPRelay enabled on any interfaces? */
1283
	if (!isset($dhcrelaycfg['enable']))
1284
		return 0;
1285

    
1286
	if ($g['booting'])
1287
		echo gettext("Starting DHCP relay service...");
1288
	else
1289
		sleep(1);
1290

    
1291
	$iflist = get_configured_interface_list();
1292

    
1293
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1294
	foreach ($dhcifaces as $dhcrelayif) {
1295
		if (!isset($iflist[$dhcrelayif]) ||
1296
			link_interface_to_bridge($dhcrelayif))
1297
			continue;
1298

    
1299
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1300
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1301
	}
1302

    
1303
	/*
1304
	 * In order for the relay to work, it needs to be active
1305
	 * on the interface in which the destination server sits.
1306
	 */
1307
	$srvips = explode(",", $dhcrelaycfg['server']);
1308
	foreach ($srvips as $srcidx => $srvip) {
1309
		unset($destif);
1310
		foreach ($iflist as $ifname) {
1311
			$subnet = get_interface_ip($ifname);
1312
			if (!is_ipaddr($subnet))
1313
				continue;
1314
			$subnet .=  "/" . get_interface_subnet($ifname);
1315
			if (ip_in_subnet($srvip, $subnet)) {
1316
				$destif = get_real_interface($ifname);
1317
				break;
1318
			}
1319
		}
1320
		if (!isset($destif)) {
1321
			foreach (get_staticroutes() as $rtent) {
1322
				if (ip_in_subnet($srvip, $rtent['network'])) {
1323
					$a_gateways = return_gateways_array(true);
1324
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1325
					break;
1326
				}
1327
			}
1328
		}
1329

    
1330
		if (!isset($destif)) {
1331
			/* Create a array from the existing route table */
1332
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1333
        		array_shift($route_str);
1334
        		array_shift($route_str);
1335
        		array_shift($route_str);
1336
        		array_shift($route_str);
1337
        		$route_arr = array();
1338
        		foreach($route_str as $routeline) {
1339
				$items = preg_split("/[ ]+/i", $routeline);
1340
				if (is_subnetv4($items[0])) {
1341
					$subnet = $items[0];
1342
				} elseif (is_ipaddrv4($items[0])) {
1343
					$subnet = "{$items[0]}/32";
1344
				} else {
1345
					// Not a subnet or IP address, skip to the next line.
1346
					continue;
1347
				}
1348
				if (ip_in_subnet($srvip, $subnet)) {
1349
					$destif = trim($items[6]);
1350
					break;
1351
				}
1352
			}
1353
		}
1354

    
1355
		if (!isset($destif)) {
1356
			if (is_array($config['gateways']['gateway_item'])) {
1357
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1358
					if (isset($gateway['defaultgw'])) {
1359
						$destif = $gateway['interface'];
1360
						break;
1361
					}
1362
				}
1363
			} else
1364
				$destif = get_real_interface("wan");
1365
		}
1366

    
1367
		if (!empty($destif))
1368
			$dhcrelayifs[] = $destif;
1369
	}
1370
	$dhcrelayifs = array_unique($dhcrelayifs);
1371

    
1372
	/* fire up dhcrelay */
1373
	if (empty($dhcrelayifs)) {
1374
		log_error("No suitable interface found for running dhcrelay!");
1375
		return; /* XXX */
1376
	}
1377

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

    
1380
	if (isset($dhcrelaycfg['agentoption']))
1381
		$cmd .=  " -a -m replace";
1382

    
1383
	$cmd .= " " . implode(" ", $srvips);
1384
	mwexec($cmd);
1385
	unset($cmd);
1386

    
1387
	return 0;
1388
}
1389

    
1390
function services_dhcrelay6_configure() {
1391
	global $config, $g;
1392
	if ($g['platform'] == 'jail')
1393
		return;
1394
	if(isset($config['system']['developerspew'])) {
1395
		$mt = microtime();
1396
		echo "services_dhcrelay6_configure() being called $mt\n";
1397
	}
1398

    
1399
	/* kill any running dhcrelay */
1400
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1401

    
1402
	$dhcrelaycfg =& $config['dhcrelay6'];
1403

    
1404
	/* DHCPv6 Relay enabled on any interfaces? */
1405
	if (!isset($dhcrelaycfg['enable']))
1406
		return 0;
1407

    
1408
	if ($g['booting'])
1409
		echo gettext("Starting DHCPv6 relay service...");
1410
	else
1411
		sleep(1);
1412

    
1413
	$iflist = get_configured_interface_list();
1414

    
1415
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1416
	foreach ($dhcifaces as $dhcrelayif) {
1417
		if (!isset($iflist[$dhcrelayif]) ||
1418
			link_interface_to_bridge($dhcrelayif))
1419
			continue;
1420

    
1421
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1422
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1423
	}
1424
	$dhcrelayifs = array_unique($dhcrelayifs);
1425

    
1426
	/*
1427
	 * In order for the relay to work, it needs to be active
1428
	 * on the interface in which the destination server sits.
1429
	 */
1430
	$srvips = explode(",", $dhcrelaycfg['server']);
1431
        $srvifaces = array();
1432
	foreach ($srvips as $srcidx => $srvip) {
1433
		unset($destif);
1434
		foreach ($iflist as $ifname) {
1435
			$subnet = get_interface_ipv6($ifname);
1436
			if (!is_ipaddrv6($subnet))
1437
				continue;
1438
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1439
			if (ip_in_subnet($srvip, $subnet)) {
1440
				$destif = get_real_interface($ifname);
1441
				break;
1442
			}
1443
		}
1444
		if (!isset($destif)) {
1445
			if (is_array($config['staticroutes']['route'])) {
1446
				foreach ($config['staticroutes']['route'] as $rtent) {
1447
					if (ip_in_subnet($srvip, $rtent['network'])) {
1448
						$a_gateways = return_gateways_array(true);
1449
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1450
						break;
1451
					}
1452
				}
1453
			}
1454
		}
1455

    
1456
		if (!isset($destif)) {
1457
			/* Create a array from the existing route table */
1458
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1459
        		array_shift($route_str);
1460
        		array_shift($route_str);
1461
        		array_shift($route_str);
1462
        		array_shift($route_str);
1463
        		$route_arr = array();
1464
        		foreach($route_str as $routeline) {
1465
                		$items = preg_split("/[ ]+/i", $routeline);
1466
				if (ip_in_subnet($srvip, $items[0])) {
1467
					$destif = trim($items[6]);
1468
					break;
1469
				}
1470
        		}
1471
		}
1472

    
1473
		if (!isset($destif)) {
1474
			if (is_array($config['gateways']['gateway_item'])) {
1475
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1476
					if (isset($gateway['defaultgw'])) {
1477
						$destif = $gateway['interface'];
1478
						break;
1479
					}
1480
				}
1481
			} else
1482
				$destif = get_real_interface("wan");
1483
		}
1484

    
1485
		if (!empty($destif)) {
1486
			$srvifaces[] = "{$srvip}%{$destif}";
1487
		}
1488
	}
1489

    
1490
	/* fire up dhcrelay */
1491
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1492
		log_error("No suitable interface found for running dhcrelay -6!");
1493
		return; /* XXX */
1494
	}
1495

    
1496
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1497
	foreach ($dhcrelayifs as $dhcrelayif) {
1498
		$cmd .= " -l {$dhcrelayif}";
1499
	}
1500
	foreach ($srvifaces as $srviface) {
1501
		$cmd .= " -u \"{$srviface}\"";
1502
	}
1503
	mwexec($cmd);
1504
	unset($cmd);
1505

    
1506
	return 0;
1507
}
1508

    
1509
function services_dyndns_configure_client($conf) {
1510

    
1511
	if (!isset($conf['enable']))
1512
		return;
1513

    
1514
	/* load up the dyndns.class */
1515
	require_once("dyndns.class");
1516

    
1517
	$dns = new updatedns($dnsService = $conf['type'],
1518
		$dnsHost = $conf['host'],
1519
		$dnsUser = $conf['username'],
1520
		$dnsPass = $conf['password'],
1521
		$dnsWilcard = $conf['wildcard'],
1522
		$dnsMX = $conf['mx'],
1523
		$dnsIf = "{$conf['interface']}",
1524
		$dnsBackMX = NULL,
1525
		$dnsServer = NULL,
1526
		$dnsPort = NULL,
1527
		$dnsUpdateURL = "{$conf['updateurl']}",
1528
		$forceUpdate = $conf['force'],
1529
		$dnsZoneID=$conf['zoneid'],
1530
		$dnsTTL=$conf['ttl'],
1531
		$dnsResultMatch = "{$conf['resultmatch']}",
1532
		$dnsRequestIf = "{$conf['requestif']}",
1533
		$dnsID = "{$conf['id']}",
1534
		$dnsVerboseLog = $conf['verboselog']);
1535
}
1536

    
1537
function services_dyndns_configure($int = "") {
1538
	global $config, $g;
1539
	if(isset($config['system']['developerspew'])) {
1540
		$mt = microtime();
1541
		echo "services_dyndns_configure() being called $mt\n";
1542
	}
1543

    
1544
	$dyndnscfg = $config['dyndnses']['dyndns'];
1545
	$gwgroups = return_gateway_groups_array();
1546
	if (is_array($dyndnscfg)) {
1547
		if ($g['booting'])
1548
			echo gettext("Starting DynDNS clients...");
1549

    
1550
		foreach ($dyndnscfg as $dyndns) {
1551
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1552
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1553
				services_dyndns_configure_client($dyndns);
1554
				sleep(1);
1555
			}
1556
		}
1557

    
1558
		if ($g['booting'])
1559
			echo gettext("done.") . "\n";
1560
	}
1561

    
1562
	return 0;
1563
}
1564

    
1565
function dyndnsCheckIP($int) {
1566
	global $config;
1567
	$ip_address = get_interface_ip($int);
1568
	if (is_private_ip($ip_address)) {
1569
		$gateways_status = return_gateways_status(true);
1570
		// If the gateway for this interface is down, then the external check cannot work.
1571
		// Avoid the long wait for the external check to timeout.
1572
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1573
			return "down";
1574
		$hosttocheck = "checkip.dyndns.org";
1575
		$checkip = gethostbyname($hosttocheck);
1576
		$ip_ch = curl_init("http://{$checkip}");
1577
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1578
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1579
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1580
		$ip_result_page = curl_exec($ip_ch);
1581
		curl_close($ip_ch);
1582
		$ip_result_decoded = urldecode($ip_result_page);
1583
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1584
		$ip_address = trim($matches[1]);
1585
	}
1586
	return $ip_address;
1587
}
1588

    
1589
function services_dnsmasq_configure() {
1590
	global $config, $g;
1591
	$return = 0;
1592

    
1593
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1594
	$standard_args = array(
1595
		"dns-forward-max" => "--dns-forward-max=5000",
1596
		"cache-size" => "--cache-size=10000",
1597
		"local-ttl" => "--local-ttl=1"
1598
	);
1599

    
1600

    
1601
	if(isset($config['system']['developerspew'])) {
1602
		$mt = microtime();
1603
		echo "services_dnsmasq_configure() being called $mt\n";
1604
	}
1605

    
1606
	/* kill any running dnsmasq */
1607
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1608
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1609

    
1610
	if (isset($config['dnsmasq']['enable'])) {
1611

    
1612
		if ($g['booting'])
1613
			echo gettext("Starting DNS forwarder...");
1614
		else
1615
			sleep(1);
1616

    
1617
		/* generate hosts file */
1618
		if(system_hosts_generate()!=0)
1619
			$return = 1;
1620

    
1621
		$args = "";
1622

    
1623
		if (isset($config['dnsmasq']['regdhcp'])) {
1624
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1625
		}
1626

    
1627
		/* Setup listen port, if non-default */
1628
		if (is_port($config['dnsmasq']['port']))
1629
			$args .= " --port={$config['dnsmasq']['port']} ";
1630

    
1631
		$listen_addresses = "";
1632
		if(isset($config['dnsmasq']['interface'])) {
1633
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1634
			foreach ($interfaces as $interface) {
1635
				if (is_ipaddrv4($interface)) {
1636
					$listen_addresses .= " --listen-address={$interface} ";
1637
				} else if (is_ipaddrv6($interface)) {
1638
					/*
1639
					* XXX: Since dnsmasq does not support link-local address
1640
					* with scope specified. These checks are being done.
1641
					*/
1642
					if (is_linklocal($interface) && strstr($interface, "%")) {
1643
						$tmpaddrll6 = explode("%", $interface);
1644
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1645
					} else 
1646
						$listen_addresses .= " --listen-address={$interface} ";
1647
				} else {
1648
					$if = get_real_interface($interface);
1649
					if (does_interface_exist($if)) {
1650
						$laddr = find_interface_ip($if);
1651
						if (is_ipaddrv4($laddr))
1652
							$listen_addresses .= " --listen-address={$laddr} ";
1653
						$laddr6 = find_interface_ipv6($if);
1654
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
1655
							/*
1656
							 * XXX: Since dnsmasq does not support link-local address
1657
							 * with scope specified. These checks are being done.
1658
							 */
1659
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
1660
								$tmpaddrll6 = explode("%", $laddr6);
1661
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1662
							} else 
1663
								$listen_addresses .= " --listen-address={$laddr6} ";
1664
						}
1665
					}
1666
				}
1667
			}
1668
			if (!empty($listen_addresses)) {
1669
				$args .= " {$listen_addresses} ";
1670
				if (isset($config['dnsmasq']['strictbind']))
1671
					$args .= " --bind-interfaces ";
1672
			}
1673
		}
1674

    
1675
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
1676
		/* If any of these are duplicated by a user-specified domain override (e.g. 10.in-addr.arpa) then */
1677
		/* the user-specified entry made later on the command line below will be the one that is effective. */
1678
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1679
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1680
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1681
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1682
			$args .= " --server=/10.in-addr.arpa/ ";
1683
			$args .= " --server=/168.192.in-addr.arpa/ ";
1684
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1685
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1686
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1687
			}
1688
		}
1689

    
1690
		/* Setup forwarded domains */
1691
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1692
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1693
				if ($override['ip'] == "!")
1694
					$override[ip] = "";
1695
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1696
			}
1697
		}
1698

    
1699
		/* Allow DNS Rebind for forwarded domains */
1700
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1701
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1702
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1703
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1704
				}
1705
			}
1706
		}
1707

    
1708
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1709
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1710

    
1711
		if (isset($config['dnsmasq']['strict_order'])) {
1712
			$args .= " --strict-order ";
1713
		}
1714

    
1715
		if (isset($config['dnsmasq']['domain_needed'])) {
1716
			$args .= " --domain-needed ";
1717
		}
1718

    
1719
		if ($config['dnsmasq']['custom_options'])
1720
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1721
				$args .= " --$c";
1722
				$p = explode('=', $c);
1723
				if (array_key_exists($p[0], $standard_args))
1724
					unset($standard_args[$p[0]]);
1725
			}
1726
		$args .= ' ' . implode(' ', array_values($standard_args));
1727

    
1728
		/* run dnsmasq */
1729
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1730
		//log_error("dnsmasq command: {$cmd}");
1731
		mwexec_bg($cmd);
1732
		unset($args);
1733

    
1734
		if ($g['booting'])
1735
			echo gettext("done.") . "\n";
1736
	}
1737

    
1738
	if (!$g['booting']) {
1739
		if(services_dhcpd_configure()!=0)
1740
			$return = 1;
1741
	}
1742

    
1743
	return $return;
1744
}
1745

    
1746
function services_snmpd_configure() {
1747
	global $config, $g;
1748
	if(isset($config['system']['developerspew'])) {
1749
		$mt = microtime();
1750
		echo "services_snmpd_configure() being called $mt\n";
1751
	}
1752

    
1753
	/* kill any running snmpd */
1754
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1755
	sleep(2);
1756
	if(is_process_running("bsnmpd"))
1757
		mwexec("/usr/bin/killall bsnmpd", true);
1758

    
1759
	if (isset($config['snmpd']['enable'])) {
1760

    
1761
		if ($g['booting'])
1762
			echo gettext("Starting SNMP daemon... ");
1763

    
1764
		/* generate snmpd.conf */
1765
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1766
		if (!$fd) {
1767
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1768
			return 1;
1769
		}
1770

    
1771

    
1772
		$snmpdconf = <<<EOD
1773
location := "{$config['snmpd']['syslocation']}"
1774
contact := "{$config['snmpd']['syscontact']}"
1775
read := "{$config['snmpd']['rocommunity']}"
1776

    
1777
EOD;
1778

    
1779
/* No docs on what write strings do there for disable for now.
1780
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1781
		    $snmpdconf .= <<<EOD
1782
# write string
1783
write := "{$config['snmpd']['rwcommunity']}"
1784

    
1785
EOD;
1786
		}
1787
*/
1788

    
1789

    
1790
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1791
		    $snmpdconf .= <<<EOD
1792
# SNMP Trap support.
1793
traphost := {$config['snmpd']['trapserver']}
1794
trapport := {$config['snmpd']['trapserverport']}
1795
trap := "{$config['snmpd']['trapstring']}"
1796

    
1797

    
1798
EOD;
1799
		}
1800

    
1801
		$version = trim(file_get_contents('/etc/version'));
1802
		$platform = trim(file_get_contents('/etc/platform'));
1803
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1804
			$platform = $g['product_name'];
1805
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1806
			" {$version} {$platform} " . php_uname("s") .
1807
			" " . php_uname("r") . " " . php_uname("m");
1808

    
1809
		$snmpdconf .= <<<EOD
1810
system := 1     # pfSense
1811
%snmpd
1812
sysDescr			= "{$sysDescr}"
1813
begemotSnmpdDebugDumpPdus       = 2
1814
begemotSnmpdDebugSyslogPri      = 7
1815
begemotSnmpdCommunityString.0.1 = $(read)
1816

    
1817
EOD;
1818

    
1819
/* No docs on what write strings do there for disable for now.
1820
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1821
		    $snmpdconf .= <<<EOD
1822
begemotSnmpdCommunityString.0.2 = $(write)
1823

    
1824
EOD;
1825
		}
1826
*/
1827

    
1828

    
1829
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1830
		    $snmpdconf .= <<<EOD
1831
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1832
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1833
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1834

    
1835
EOD;
1836
		}
1837

    
1838

    
1839
		$snmpdconf .= <<<EOD
1840
begemotSnmpdCommunityDisable    = 1
1841

    
1842
EOD;
1843

    
1844
		if (isset($config['snmpd']['bindlan'])) {
1845
			$config['snmpd']['bindip'] = 'lan';
1846
			unset($config['snmpd']['bindlan']);
1847
		}
1848
		$bind_to_ip = "0.0.0.0";
1849
		if(isset($config['snmpd']['bindip'])) {
1850
			if (is_ipaddr($config['snmpd']['bindip'])) {
1851
				$bind_to_ip = $config['snmpd']['bindip'];
1852
			} else {
1853
				$if = get_real_interface($config['snmpd']['bindip']);
1854
				if (does_interface_exist($if))
1855
					$bind_to_ip = find_interface_ip($if);
1856
			}
1857
		}
1858

    
1859
		if(is_port( $config['snmpd']['pollport'] )) {
1860
		    $snmpdconf .= <<<EOD
1861
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1862

    
1863
EOD;
1864

    
1865
		}
1866

    
1867
		$snmpdconf .= <<<EOD
1868
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1869
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1870

    
1871
# These are bsnmp macros not php vars.
1872
sysContact      = $(contact)
1873
sysLocation     = $(location)
1874
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1875

    
1876
snmpEnableAuthenTraps = 2
1877

    
1878
EOD;
1879

    
1880
		if (is_array( $config['snmpd']['modules'] )) {
1881
		    if(isset($config['snmpd']['modules']['mibii'])) {
1882
			$snmpdconf .= <<<EOD
1883
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1884

    
1885
EOD;
1886
		    }
1887

    
1888
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1889
			$snmpdconf .= <<<EOD
1890
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1891
%netgraph
1892
begemotNgControlNodeName = "snmpd"
1893

    
1894
EOD;
1895
		    }
1896

    
1897
		    if(isset($config['snmpd']['modules']['pf'])) {
1898
			$snmpdconf .= <<<EOD
1899
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1900

    
1901
EOD;
1902
		    }
1903

    
1904
		    if(isset($config['snmpd']['modules']['hostres'])) {
1905
			$snmpdconf .= <<<EOD
1906
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1907

    
1908
EOD;
1909
		    }
1910
		    if(isset($config['snmpd']['modules']['bridge'])) {
1911
			$snmpdconf .= <<<EOD
1912
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1913
# config must end with blank line
1914

    
1915
EOD;
1916
		    }
1917
			if(isset($config['snmpd']['modules']['ucd'])) {
1918
				$snmpdconf .= <<<EOD
1919
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1920

    
1921
EOD;
1922
			}
1923
			if(isset($config['snmpd']['modules']['regex'])) {
1924
				$snmpdconf .= <<<EOD
1925
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1926

    
1927
EOD;
1928
			}
1929
		}
1930

    
1931
		fwrite($fd, $snmpdconf);
1932
		fclose($fd);
1933
		unset($snmpdconf);
1934

    
1935
		if (isset($config['snmpd']['bindlan'])) {
1936
			$bindlan = "";
1937
		}
1938

    
1939
		/* run bsnmpd */
1940
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1941
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1942

    
1943
		if ($g['booting'])
1944
			echo gettext("done.") . "\n";
1945
	}
1946

    
1947
	return 0;
1948
}
1949

    
1950
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
1951
	global $config, $g;
1952
	if(isset($config['system']['developerspew'])) {
1953
		$mt = microtime();
1954
		echo "services_dnsupdate_process() being called $mt\n";
1955
	}
1956

    
1957
	/* Dynamic DNS updating active? */
1958
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1959
		$notify_text = "";
1960
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1961
			if (!isset($dnsupdate['enable']))
1962
				continue;
1963
			if (!empty($int) && $int != $dnsupdate['interface'])
1964
				continue;
1965
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
1966
				continue;
1967

    
1968
			/* determine interface name */
1969
			$if = get_real_interface($dnsupdate['interface']);
1970
			$wanip = get_interface_ip($dnsupdate['interface']);
1971
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
1972

    
1973
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
1974
			$currentTime = time();
1975

    
1976
			if ($wanip || $wanipv6) {
1977
				$keyname = $dnsupdate['keyname'];
1978
				/* trailing dot */
1979
				if (substr($keyname, -1) != ".")
1980
					$keyname .= ".";
1981

    
1982
				$hostname = $dnsupdate['host'];
1983
				/* trailing dot */
1984
				if (substr($hostname, -1) != ".")
1985
					$hostname .= ".";
1986

    
1987
				/* write private key file
1988
				   this is dumb - public and private keys are the same for HMAC-MD5,
1989
				   but nsupdate insists on having both */
1990
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
1991
				$privkey = <<<EOD
1992
Private-key-format: v1.2
1993
Algorithm: 157 (HMAC)
1994
Key: {$dnsupdate['keydata']}
1995

    
1996
EOD;
1997
				fwrite($fd, $privkey);
1998
				fclose($fd);
1999

    
2000
				/* write public key file */
2001
				if ($dnsupdate['keytype'] == "zone") {
2002
					$flags = 257;
2003
					$proto = 3;
2004
				} else if ($dnsupdate['keytype'] == "host") {
2005
					$flags = 513;
2006
					$proto = 3;
2007
				} else if ($dnsupdate['keytype'] == "user") {
2008
					$flags = 0;
2009
					$proto = 2;
2010
				}
2011

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

    
2016
				/* generate update instructions */
2017
				$upinst = "";
2018
				if (!empty($dnsupdate['server']))
2019
					$upinst .= "server {$dnsupdate['server']}\n";
2020

    
2021
				if (file_exists($cacheFile)) {
2022
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2023
				}
2024
				if (file_exists("{$cacheFile}.ipv6")) {
2025
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2026
				}
2027

    
2028
				// 25 Days
2029
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2030
				$need_update = false;
2031

    
2032
				conf_mount_rw();
2033
				/* Update IPv4 if we have it. */
2034
				if (is_ipaddrv4($wanip)) {
2035
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2036
						if (isset($dnsupdate['usepublicip'])) {
2037
							$wanip = dyndnsCheckIP($dnsupdate['interface']);
2038
						}
2039
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2040
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2041
						$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";
2042
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2043
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2044
						$need_update = true;
2045
					} else {
2046
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2047
					}
2048
				} else
2049
					@unlink($cacheFile);
2050

    
2051
				/* Update IPv6 if we have it. */
2052
				if (is_ipaddrv6($wanipv6)) {
2053
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2054
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2055
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2056
						$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";
2057
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2058
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2059
						$need_update = true;
2060
					} else {
2061
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2062
					}
2063
				} else
2064
					@unlink("{$cacheFile}.ipv6");
2065
				conf_mount_ro();
2066

    
2067
				$upinst .= "\n";	/* mind that trailing newline! */
2068

    
2069
				if ($need_update) {
2070
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2071
					unset($upinst);
2072
					/* invoke nsupdate */
2073
					$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2074
					if (isset($dnsupdate['usetcp']))
2075
						$cmd .= " -v";
2076
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2077
					mwexec_bg($cmd);
2078
					unset($cmd);
2079
				}
2080
			}
2081
		}
2082
		if (!empty($notify_text)) {
2083
			notify_all_remote($notify_text);
2084
		}
2085
	}
2086

    
2087
	return 0;
2088
}
2089

    
2090
/* configure cron service */
2091
function configure_cron() {
2092
	global $g, $config;
2093

    
2094
	conf_mount_rw();
2095
	/* preserve existing crontab entries */
2096
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2097

    
2098
	for ($i = 0; $i < count($crontab_contents); $i++) {
2099
		$cron_item =& $crontab_contents[$i];
2100
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2101
			array_splice($crontab_contents, $i - 1);
2102
			break;
2103
		}
2104
	}
2105
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2106

    
2107

    
2108
	if (is_array($config['cron']['item'])) {
2109
		$crontab_contents .= "#\n";
2110
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2111
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2112
		$crontab_contents .= "#\n";
2113

    
2114
		foreach ($config['cron']['item'] as $item) {
2115
			$crontab_contents .= "\n{$item['minute']}\t";
2116
			$crontab_contents .= "{$item['hour']}\t";
2117
			$crontab_contents .= "{$item['mday']}\t";
2118
			$crontab_contents .= "{$item['month']}\t";
2119
			$crontab_contents .= "{$item['wday']}\t";
2120
			$crontab_contents .= "{$item['who']}\t";
2121
			$crontab_contents .= "{$item['command']}";
2122
		}
2123

    
2124
		$crontab_contents .= "\n#\n";
2125
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2126
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2127
		$crontab_contents .= "#\n\n";
2128
	}
2129

    
2130
	/* please maintain the newline at the end of file */
2131
	file_put_contents("/etc/crontab", $crontab_contents);
2132
	unset($crontab_contents);
2133

    
2134
	/* do a HUP kill to force sync changes */
2135
	exec('/bin/pkill -HUP cron');
2136

    
2137
	conf_mount_ro();
2138
}
2139

    
2140
function upnp_action ($action) {
2141
	global $g, $config;
2142
	switch($action) {
2143
		case "start":
2144
			if (file_exists('/var/etc/miniupnpd.conf')) {
2145
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2146
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2147
			}
2148
			break;
2149
		case "stop":
2150
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2151
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2152
				mwexec('killall miniupnpd 2>/dev/null', true);
2153
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2154
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2155
			break;
2156
		case "restart":
2157
			upnp_action('stop');
2158
			upnp_action('start');
2159
			break;
2160
	}
2161
}
2162

    
2163
function upnp_start() {
2164
	global $config;
2165

    
2166
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2167
		return;
2168

    
2169
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2170
		echo gettext("Starting UPnP service... ");
2171
		require_once('/usr/local/pkg/miniupnpd.inc');
2172
		sync_package_miniupnpd();
2173
		echo "done.\n";
2174
	}
2175
}
2176

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

    
2180
	$is_installed = false;
2181

    
2182
	if (!is_array($config['cron']))
2183
		$config['cron'] = array();
2184
	if (!is_array($config['cron']['item']))
2185
		$config['cron']['item'] = array();
2186

    
2187
	$x=0;
2188
	foreach($config['cron']['item'] as $item) {
2189
		if(strstr($item['command'], $command)) {
2190
			$is_installed = true;
2191
			break;
2192
		}
2193
		$x++;
2194
	}
2195

    
2196
	if($active) {
2197
		$cron_item = array();
2198
		$cron_item['minute'] = $minute;
2199
		$cron_item['hour'] = $hour;
2200
		$cron_item['mday'] = $monthday;
2201
		$cron_item['month'] = $month;
2202
		$cron_item['wday'] = $weekday;
2203
		$cron_item['who'] = $who;
2204
		$cron_item['command'] = $command;
2205
		if(!$is_installed) {
2206
			$config['cron']['item'][] = $cron_item;
2207
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2208
		} else {
2209
			$config['cron']['item'][$x] = $cron_item;
2210
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2211
		}
2212
	} else {
2213
		if($is_installed == true) {
2214
			unset($config['cron']['item'][$x]);
2215
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2216
		}
2217
	}
2218
	configure_cron();
2219
}
2220

    
2221
?>
(49-49/66)