Project

General

Profile

Download (62 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/sbin/arp	/sbin/ifconfig	/usr/local/sbin/dnsmasq
36
	pfSense_BUILDER_BINARIES:	/usr/sbin/bsnmpd	/sbin/route
37
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/miniupnpd	/usr/sbin/radvd		/usr/local/sbin/unbound
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcleases6
39
	pfSense_MODULE:	utils
40
*/
41

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

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

    
54
	if (!is_array($config['dhcpdv6']))
55
		$config['dhcpdv6'] = array();
56

    
57
	$Iflist = get_configured_interface_list();
58
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
59
	$carplist = get_configured_carp_interface_list();
60

    
61
	$radvdconf = "# Automatically Generated, do not edit\n";
62

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

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

    
73
		if (!isset($dhcpv6ifconf['ramode']))
74
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
75

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

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

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

    
93
		$realif = get_real_interface($dhcpv6if);
94
		if (in_array($realif, $radvdifs))
95
			continue;
96
		$radvdifs[] = $realif;
97

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

    
102
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
103
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
104

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

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

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

    
203
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
204
	foreach ($Iflist as $if => $ifdescr) {
205
		if(!isset($config['interfaces'][$if]['track6-interface']))
206
			continue;
207
		if(!isset($config['interfaces'][$if]['enable']))
208
			continue;
209
			
210
		$realif = get_real_interface($if);
211
		/* prevent duplicate entries, manual overrides */
212
		if(in_array($realif, $radvdifs))
213
			continue;
214

    
215
		$ifcfgipv6 = get_interface_ipv6($if);
216
		if(!is_ipaddrv6($ifcfgipv6))
217
			continue;
218

    
219
		$ifcfgsnv6 = get_interface_subnetv6($if);
220
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
221
		$trackif = $config['interfaces'][$if]['track6-interface'];
222
		if (empty($config['interfaces'][$trackif]))
223
			continue;
224
		$radvdifs[] = $realif;
225

    
226
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
227
	
228
		if ($g['debug'])
229
			log_error("configuring RA on {$if} for type {$autotype} radvd subnet {$subnetv6}/{$ifcfgsnv6}");
230

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

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

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

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

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

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

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

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

    
330
function services_dhcpdv4_configure() {
331
	global $config, $g;
332

    
333
	if($g['services_dhcp_server_enable'] == false)
334
		return;
335

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

    
341
	/* kill any running dhcpd */
342
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
343
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
344
	else
345
		mwexec("/usr/bin/killall dhcpd", true);
346

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

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

    
357
	if ($g['booting']) {
358
		if ($g['platform'] != "pfSense") {
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
		}
370
	}
371

    
372
	$syscfg = $config['system'];
373
	if (!is_array($config['dhcpd']))
374
		$config['dhcpd'] = array();
375
	$dhcpdcfg = $config['dhcpd'];
376
	$Iflist = get_configured_interface_list();
377

    
378
	if ($g['booting'])
379
		echo gettext("Starting DHCP service...");
380
	else
381
		sleep(1);
382

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

    
396
	$dhcpdconf = <<<EOD
397

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

    
410
EOD;
411

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

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

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

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

    
436
		interfaces_staticarp_configure($dhcpif);
437

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

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

    
487
EOPP;
488
		$dhcpnum++;
489
		}
490
	}
491

    
492
	$dhcpnum = 0;
493

    
494
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
495

    
496
		$ifcfg = $config['interfaces'][$dhcpif];
497

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

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

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

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

    
518
		$dnscfg = "";
519

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

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

    
528
		if (isset($dhcpifconf['ddnsupdate'])) {
529
			if($dhcpifconf['ddnsdomain'] <> "") {
530
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
531
			}
532
			$dnscfg .= "	ddns-update-style interim;\n";
533
		}
534

    
535
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
536
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
537
		} else if (isset($config['dnsmasq']['enable'])) {
538
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
539
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
540
			$dnscfg .= "	option domain-name-servers " . join(",", $syscfg['dnsserver']) . ";";
541
		}
542

    
543
		/* Create classes - These all contain comma separated lists. Join them into one 
544
		   big comma separated string then split them all up. */
545
		$all_mac_strings = array();
546
		if (is_array($dhcpifconf['pool'])) {
547
			foreach($all_pools as $poolconf) {
548
				$all_mac_strings[] = $poolconf['mac_allow'];
549
				$all_mac_strings[] = $poolconf['mac_deny'];
550
			}
551
		}
552
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
553
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
554
		$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
555
		foreach ($all_mac_list as $mac) {
556
			if (empty($mac))
557
				continue;
558
			$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
559
			// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
560
			$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
561
			$dhcpdconf .= '}' . "\n";
562
		}
563

    
564
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
565

    
566
// Setup pool options
567
		foreach($all_pools as $poolconf) {
568
			$dhcpdconf .= "	pool {\n";
569
			/* is failover dns setup? */
570
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
571
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
572
				if($poolconf['dnsserver'][1] <> "")
573
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
574
				$dhcpdconf .= ";\n";
575
			}
576

    
577
			/* allow/deny MACs */
578
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
579
			foreach ($mac_allow_list as $mac) {
580
				if (empty($mac))
581
					continue;
582
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
583
			}
584
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
585
			foreach ($mac_deny_list as $mac) {
586
				if (empty($mac))
587
					continue;
588
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
589
			}
590

    
591
			if($poolconf['failover_peerip'] <> "")
592
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
593

    
594
			if (isset($poolconf['denyunknown']))
595
			   $dhcpdconf .= "		deny unknown-clients;\n";
596

    
597
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
598
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
599

    
600
			if($dhcpifconf['failover_peerip'] <> "") {
601
				$dhcpdconf .= "		failover peer \"dhcp{$dhcpnum}\";\n";
602
				$dhcpnum++;
603
			}
604

    
605
			$pdnscfg = "";
606

    
607
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
608
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
609
			}
610

    
611
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
612
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
613
			}
614

    
615
			if (isset($poolconf['ddnsupdate'])) {
616
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
617
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
618
				$pdnscfg .= "		ddns-update-style interim;\n";
619
			}
620

    
621
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
622
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
623
			}
624
			$dhcpdconf .= "{$pdnscfg}";
625

    
626
			// default-lease-time
627
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
628
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
629

    
630
			// max-lease-time
631
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
632
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
633

    
634
			// netbios-name*
635
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
636
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
637
				$dhcpdconf .= "		option netbios-node-type 8;\n";
638
			}
639

    
640
			// ntp-servers
641
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
642
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
643

    
644
			// tftp-server-name
645
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
646
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
647

    
648
			// ldap-server
649
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
650
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
651

    
652
			// net boot information
653
			if(isset($poolconf['netboot'])) {
654
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
655
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
656
				}
657
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
658
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
659
				}
660
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
661
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
662
				}
663
			}
664
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
665
			$dhcpdconf .= "	}\n\n";
666
		}
667
// End of settings inside pools
668

    
669
		if ($dhcpifconf['gateway']) {
670
			$routers = $dhcpifconf['gateway'];
671
			$add_routers = true;
672
		} else {
673
			$routers = $ifcfgip;
674
		}
675
		if($add_routers)
676
			$dhcpdconf .= "	option routers {$routers};\n";
677

    
678
		$dhcpdconf .= <<<EOD
679
$dnscfg
680

    
681
EOD;
682
    		// default-lease-time
683
		if ($dhcpifconf['defaultleasetime'])
684
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
685

    
686
		// max-lease-time
687
		if ($dhcpifconf['maxleasetime'])
688
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
689

    
690
		// netbios-name*
691
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
692
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
693
			$dhcpdconf .= "	option netbios-node-type 8;\n";
694
		}
695

    
696
		// ntp-servers
697
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
698
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
699

    
700
		// tftp-server-name
701
		if ($dhcpifconf['tftp'] <> "")
702
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
703

    
704
		// Handle option, number rowhelper values
705
		$dhcpdconf .= "\n";
706
		if($dhcpifconf['numberoptions']['item']) {
707
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
708
				if(empty($item['type']) || $item['type'] == "text")
709
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
710
				else
711
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
712
			}
713
		}
714

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

    
719
		// net boot information
720
		if(isset($dhcpifconf['netboot'])) {
721
			if ($dhcpifconf['nextserver'] <> "") {
722
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
723
			}
724
			if ($dhcpifconf['filename'] <> "") {
725
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
726
			}
727
			if ($dhcpifconf['rootpath'] <> "") {
728
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
729
			}
730
		}
731

    
732
		$dhcpdconf .= <<<EOD
733
}
734

    
735
EOD;
736

    
737
		/* add static mappings */
738
		if (is_array($dhcpifconf['staticmap'])) {
739

    
740
			$i = 0;
741
			foreach ($dhcpifconf['staticmap'] as $sm) {
742
				$dhcpdconf .= <<<EOD
743
host s_{$dhcpif}_{$i} {
744
	hardware ethernet {$sm['mac']};
745

    
746
EOD;
747
				if ($sm['ipaddr'])
748
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
749

    
750
				if ($sm['hostname']) {
751
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
752
					$dhhostname = str_replace(".", "_", $dhhostname);
753
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
754
				}
755
				if ($sm['filename'])
756
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
757

    
758
				if ($sm['rootpath'])
759
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
760

    
761
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
762
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
763

    
764
				$smdnscfg = "";
765

    
766
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
767
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
768
				}
769

    
770
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
771
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
772
				}
773

    
774
				if (isset($sm['ddnsupdate'])) {
775
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
776
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
777
					$pdnscfg .= "		ddns-update-style interim;\n";
778
				}
779

    
780
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
781
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
782
				}
783
				$dhcpdconf .= "{$smdnscfg}";
784

    
785
				// default-lease-time
786
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
787
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
788

    
789
				// max-lease-time
790
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
791
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
792

    
793
				// netbios-name*
794
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
795
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
796
					$dhcpdconf .= "	option netbios-node-type 8;\n";
797
				}
798

    
799
				// ntp-servers
800
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
801
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
802

    
803
				// tftp-server-name
804
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
805
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
806

    
807
				$dhcpdconf .= "}\n";
808
				$i++;
809
			}
810
		}
811

    
812
		$dhcpdifs[] = get_real_interface($dhcpif);
813
	}
814

    
815
	/* write dhcpd.conf */
816
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
817
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
818
		unset($dhcpdconf);
819
		return 1;
820
	}
821
	unset($dhcpdconf);
822

    
823
	/* create an empty leases database */
824
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
825
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
826

    
827
	/* fire up dhcpd in a chroot */
828
	if (count($dhcpdifs) > 0) {
829
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
830
			join(" ", $dhcpdifs));
831
	}
832

    
833
	if ($g['booting'])
834
		print "done.\n";
835

    
836
	return 0;
837
}
838

    
839
function services_dhcpdv6_configure() {
840
	global $config, $g;
841

    
842
	if($g['services_dhcp_server_enable'] == false)
843
		return;
844

    
845
	if(isset($config['system']['developerspew'])) {
846
		$mt = microtime();
847
		echo "services_dhcpd_configure($if) being called $mt\n";
848
	}
849

    
850
	/* kill any running dhcpd */
851
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
852
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
853
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
854
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
855

    
856
	/* DHCP enabled on any interfaces? */
857
	if (!is_dhcpv6_server_enabled())
858
		return 0;
859

    
860
	if ($g['booting']) {
861
		if ($g['platform'] != "pfSense") {
862
			/* restore the leases, if we have them */
863
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
864
				$dhcprestore = "";
865
				$dhcpreturn = "";
866
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
867
				$dhcprestore = implode(" ", $dhcprestore);
868
				if($dhcpreturn <> 0) {
869
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
870
				}
871
			}
872
		}
873
	}
874

    
875
	$syscfg = $config['system'];
876
	if (!is_array($config['dhcpdv6']))
877
		$config['dhcpdv6'] = array();
878
	$dhcpdv6cfg = $config['dhcpdv6'];
879
	$Iflist = get_configured_interface_list();
880
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
881

    
882

    
883
	if ($g['booting'])
884
		echo "Starting DHCPv6 service...";
885
	else
886
		sleep(1);
887

    
888
	/* we add a fake entry for interfaces that are set to track6 another WAN */
889
	foreach ($Iflist as $ifname) {
890
		$realif = get_real_interface($ifname);
891
		$ifcfgipv6 = find_interface_ipv6($realif);
892
		if(!is_ipaddrv6($ifcfgipv6))
893
			continue;
894
		$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
895
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
896
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
897
			$trackcfg = $config['interfaces'][$trackifname];
898
			$pdlen = calculate_ipv6_delegation_length($trackifname);
899
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
900
			$dhcpdv6cfg[$ifname] = array();
901
			$dhcpdv6cfg[$ifname]['enable'] = true;
902
			/* range */
903
			$ifcfgipv6arr[7] = "1000";
904
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
905
			$ifcfgipv6arr[7] = "2000";
906
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
907
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
908
			if($pdlen > 2) {
909
				$pdlenmax = $pdlen;
910
				$pdlenhalf = $pdlenmax -1;
911
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
912
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
913

    
914
				/* set the delegation start to half the current address block */
915
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
916
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
917

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

    
922
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
923
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
924
			}
925
		}
926
	}
927

    
928
	$custoptionsv6 = "";
929
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
930
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
931
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
932
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
933
			}
934
		}
935
	}
936

    
937
	$dhcpdv6conf = <<<EOD
938

    
939
option domain-name "{$syscfg['domain']}";
940
option ldap-server code 95 = text;
941
option domain-search-list code 119 = text;
942
{$custoptions}
943
default-lease-time 7200;
944
max-lease-time 86400;
945
log-facility local7;
946
ddns-update-style none;
947
one-lease-per-client true;
948
deny duplicates;
949
ping-check true;
950

    
951
EOD;
952

    
953
	if(!isset($dhcpv6ifconf['disableauthoritative']))
954
		$dhcpdv6conf .= "authoritative;\n";
955

    
956
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
957
		$dhcpdv6conf .= "always-broadcast on\n";
958

    
959
	$dhcpdv6ifs = array();
960

    
961
	$dhcpv6num = 0;
962
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
963

    
964
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
965

    
966
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
967
			continue;
968
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
969
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
970
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
971

    
972
		if($is_olsr_enabled == true)
973
			if($dhcpv6ifconf['netmask'])
974
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
975

    
976
		$dnscfgv6 = "";
977

    
978
		if ($dhcpv6ifconf['domain']) {
979
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
980
		}
981

    
982
    		if($dhcpv6ifconf['domainsearchlist'] <> "") {
983
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
984
    		}
985

    
986
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
987
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
988
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
989
			}
990
			$dnscfgv6 .= "	ddns-update-style interim;\n";
991
		}
992

    
993
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
994
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
995
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
996
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
997
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
998
			$dns_arrv6 = array();
999
			foreach($syscfg['dnsserver'] as $dnsserver) {
1000
				if(is_ipaddrv6($dnsserver)) {
1001
					$dns_arrv6[] = $dnsserver;
1002
				}
1003
			}
1004
			if(!empty($dns_arrv6))
1005
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1006
		}
1007

    
1008
		if(is_ipaddrv6(ifcfgipv6)) {
1009
			$subnet6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1010
			$dhcpdv6conf .= "subnet6 {$subnet6}/{$ifcfgsnv6} {\n";
1011
		} else {
1012
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1013
			$dhcpdv6conf .= "subnet6 {$subnet6}/64 {\n";
1014
		}
1015

    
1016
		if($dhcpv6ifconf['failover_peerip'] <> "")
1017
			$dhcpdv6conf .= "		deny dynamic bootp clients;\n";
1018

    
1019
		if (isset($dhcpv6ifconf['denyunknown']))
1020
		   $dhcpdv6conf .= "		deny unknown-clients;\n";
1021

    
1022
		$dhcpdv6conf .= <<<EOD
1023
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1024
$dnscfgv6
1025

    
1026
EOD;
1027

    
1028
		if(is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1029
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1030

    
1031
		}
1032
    		// default-lease-time
1033
		if ($dhcpv6ifconf['defaultleasetime'])
1034
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1035

    
1036
		// max-lease-time
1037
		if ($dhcpv6ifconf['maxleasetime'])
1038
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1039

    
1040
		// ntp-servers
1041
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1042
			$ntpservers = array();
1043
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1044
				if(is_ipaddrv6($ntpserver))
1045
					$ntpservers[] = $ntpserver;
1046
			}
1047
			if(count($ntpservers) > 0 )
1048
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1049
		}
1050
		// tftp-server-name
1051
		/* Needs ISC DHCPD support
1052
		 if ($dhcpv6ifconf['tftp'] <> "")
1053
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1054
		*/
1055

    
1056
		// Handle option, number rowhelper values
1057
		$dhcpdv6conf .= "\n";
1058
		if($dhcpv6ifconf['numberoptions']['item']) {
1059
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1060
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1061
			}
1062
		}
1063

    
1064
		// ldap-server
1065
		if ($dhcpv6ifconf['ldap'] <> "")
1066
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1067

    
1068
		// net boot information
1069
		if(isset($dhcpv6ifconf['netboot'])) {
1070
			if ($dhcpv6ifconf['nextserver'] <> "") {
1071
				$dhcpdv6conf .= "	next-server {$dhcpv6ifconf['nextserver']};\n";
1072
			}
1073
			if ($dhcpv6ifconf['filename'] <> "") {
1074
				$dhcpdv6conf .= "	filename \"{$dhcpv6ifconf['filename']}\";\n";
1075
			}
1076
			if ($dhcpv6ifconf['rootpath'] <> "") {
1077
				$dhcpdv6conf .= "	option root-path \"{$dhcpv6ifconf['rootpath']}\";\n";
1078
			}
1079
		}
1080

    
1081
		$dhcpdv6conf .= "}\n";
1082

    
1083
		/* add static mappings */
1084
		/* Needs to use DUID */
1085
		if (is_array($dhcpv6ifconf['staticmap'])) {
1086
			$i = 0;
1087
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1088
				$dhcpdv6conf .= <<<EOD
1089
host s_{$dhcpv6if}_{$i} {
1090
	host-identifier option dhcp6.client-id {$sm['duid']};
1091

    
1092
EOD;
1093
				if ($sm['ipaddrv6'])
1094
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1095

    
1096
				if ($sm['hostname']) {
1097
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1098
					$dhhostname = str_replace(".", "_", $dhhostname);
1099
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1100
				}
1101
				if ($sm['filename'])
1102
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1103

    
1104
				if ($sm['rootpath'])
1105
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1106

    
1107
				$dhcpdv6conf .= "}\n";
1108
				$i++;
1109
			}
1110
		}
1111

    
1112
		if($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1113
			if(preg_match("/poes/si", $dhcpv6if)) {
1114
				/* magic here */
1115
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1116
			} else {
1117
				$realif = get_real_interface($dhcpv6if);
1118
				if (stristr("$realif", "bridge")) {
1119
					$mac = get_interface_mac($realif);
1120
					$v6address = generate_ipv6_from_mac($mac);
1121
					/* Create link local address for bridges */
1122
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1123
				}
1124
				$realif = escapeshellcmd($realif);
1125
				$dhcpdv6ifs[] = $realif;
1126
			}
1127
		}
1128
	}
1129

    
1130
	/* write dhcpdv6.conf */
1131
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1132
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1133
		if ($g['booting'])
1134
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1135
		unset($dhcpdv6conf);
1136
		return 1;
1137
	}
1138
	unset($dhcpdv6conf);
1139

    
1140
	/* create an empty leases v6 database */
1141
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1142
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1143

    
1144
	/* fire up dhcpd in a chroot */
1145
	if (count($dhcpdv6ifs) > 0) {
1146
		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 " .
1147
			join(" ", $dhcpdv6ifs));
1148
		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");
1149
	}
1150
	if ($g['booting'])
1151
		print gettext("done.") . "\n";
1152

    
1153
	return 0;
1154
}
1155

    
1156
function services_igmpproxy_configure() {
1157
        global $config, $g;
1158

    
1159
        /* kill any running igmpproxy */
1160
        killbyname("igmpproxy");
1161

    
1162
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1163
		return 1;
1164

    
1165
        $iflist = get_configured_interface_list();
1166

    
1167
        $igmpconf = <<<EOD
1168

    
1169
##------------------------------------------------------
1170
## Enable Quickleave mode (Sends Leave instantly)
1171
##------------------------------------------------------
1172
quickleave
1173

    
1174
EOD;
1175

    
1176
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1177
                unset($iflist[$igmpcf['ifname']]);
1178
                $realif = get_real_interface($igmpcf['ifname']);
1179
                if (empty($igmpcf['threshold']))
1180
                        $threshld = 1;
1181
                else
1182
                        $threshld = $igmpcf['threshold'];
1183
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1184

    
1185
                if ($igmpcf['address'] <> "") {
1186
                        $item = explode(" ", $igmpcf['address']);
1187
                        foreach($item as $iww)
1188
                                $igmpconf .= "altnet {$iww}\n";
1189
                }
1190
                $igmpconf .= "\n";
1191
        }
1192
        foreach ($iflist as $ifn) {
1193
                $realif = get_real_interface($ifn);
1194
                $igmpconf .= "phyint {$realif} disabled\n";
1195
        }
1196
	$igmpconf .= "\n";
1197

    
1198
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1199
        if (!$igmpfl) {
1200
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1201
                return;
1202
        }
1203
        fwrite($igmpfl, $igmpconf);
1204
        fclose($igmpfl);
1205
	unset($igmpconf);
1206

    
1207
        mwexec("/usr/local/sbin/igmpproxy -c {$g['tmp_path']}/igmpproxy.conf");
1208
        log_error(gettext("Started IGMP proxy service."));
1209

    
1210
        return 0;
1211
}
1212

    
1213
function services_dhcrelay_configure() {
1214
	global $config, $g;
1215
	if ($g['platform'] == 'jail')
1216
		return;
1217
	if(isset($config['system']['developerspew'])) {
1218
		$mt = microtime();
1219
		echo "services_dhcrelay_configure() being called $mt\n";
1220
	}
1221

    
1222
	/* kill any running dhcrelay */
1223
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1224

    
1225
	$dhcrelaycfg =& $config['dhcrelay'];
1226

    
1227
	/* DHCPRelay enabled on any interfaces? */
1228
	if (!isset($dhcrelaycfg['enable']))
1229
		return 0;
1230

    
1231
	if ($g['booting'])
1232
		echo gettext("Starting DHCP relay service...");
1233
	else
1234
		sleep(1);
1235

    
1236
	$iflist = get_configured_interface_list();
1237

    
1238
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1239
	foreach ($dhcifaces as $dhcrelayif) {
1240
		if (!isset($iflist[$dhcrelayif]) ||
1241
			link_interface_to_bridge($dhcrelayif))
1242
			continue;
1243

    
1244
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1245
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1246
	}
1247

    
1248
	/*
1249
	 * In order for the relay to work, it needs to be active
1250
	 * on the interface in which the destination server sits.
1251
	 */
1252
	$srvips = explode(",", $dhcrelaycfg['server']);
1253
	foreach ($srvips as $srcidx => $srvip) {
1254
		unset($destif);
1255
		foreach ($iflist as $ifname) {
1256
			$subnet = get_interface_ip($ifname);
1257
			if (!is_ipaddr($subnet))
1258
				continue;
1259
			$subnet .=  "/" . get_interface_subnet($ifname);
1260
			if (ip_in_subnet($srvip, $subnet)) {
1261
				$destif = get_real_interface($ifname);
1262
				break;
1263
			}
1264
		}
1265
		if (!isset($destif)) {
1266
			foreach (get_staticroutes() as $rtent) {
1267
				if (ip_in_subnet($srvip, $rtent['network'])) {
1268
					$a_gateways = return_gateways_array(true);
1269
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1270
					break;
1271
				}
1272
			}
1273
		}
1274

    
1275
		if (!isset($destif)) {
1276
			/* Create a array from the existing route table */
1277
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1278
        		array_shift($route_str);
1279
        		array_shift($route_str);
1280
        		array_shift($route_str);
1281
        		array_shift($route_str);
1282
        		$route_arr = array();
1283
        		foreach($route_str as $routeline) {
1284
                		$items = preg_split("/[ ]+/i", $routeline);
1285
				if (ip_in_subnet($srvip, $items[0])) {
1286
					$destif = trim($items[6]);
1287
					break;
1288
				}
1289
        		}
1290
		}
1291

    
1292
		if (!isset($destif)) {
1293
			if (is_array($config['gateways']['gateway_item'])) {
1294
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1295
					if (isset($gateway['defaultgw'])) {
1296
						$a_gateways = return_gateways_array(true);
1297
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1298
						break;
1299
					}
1300
				}
1301
			} else
1302
				$destif = get_real_interface("wan");
1303
		}
1304

    
1305
		if (!empty($destif))
1306
			$dhcrelayifs[] = $destif;
1307
	}
1308
	$dhcrelayifs = array_unique($dhcrelayifs);
1309

    
1310
	/* fire up dhcrelay */
1311
	if (empty($dhcrelayifs)) {
1312
		log_error("No suitable interface found for running dhcrelay!");
1313
		return; /* XXX */
1314
	}
1315

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

    
1318
	if (isset($dhcrelaycfg['agentoption']))
1319
		$cmd .=  " -a -m replace";
1320

    
1321
	$cmd .= " " . implode(" ", $srvips);
1322
	mwexec($cmd);
1323
	unset($cmd);
1324

    
1325
	return 0;
1326
}
1327

    
1328
function services_dhcrelay6_configure() {
1329
	global $config, $g;
1330
	if ($g['platform'] == 'jail')
1331
		return;
1332
	if(isset($config['system']['developerspew'])) {
1333
		$mt = microtime();
1334
		echo "services_dhcrelay_configure() being called $mt\n";
1335
	}
1336

    
1337
	/* kill any running dhcrelay */
1338
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1339

    
1340
	$dhcrelaycfg =& $config['dhcrelay6'];
1341

    
1342
	/* DHCPv6 Relay enabled on any interfaces? */
1343
	if (!isset($dhcrelaycfg['enable']))
1344
		return 0;
1345

    
1346
	if ($g['booting'])
1347
		echo gettext("Starting DHCPv6 relay service...");
1348
	else
1349
		sleep(1);
1350

    
1351
	$iflist = get_configured_interface_list();
1352

    
1353
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1354
	foreach ($dhcifaces as $dhcrelayif) {
1355
		if (!isset($iflist[$dhcrelayif]) ||
1356
			link_interface_to_bridge($dhcrelayif))
1357
			continue;
1358

    
1359
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1360
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1361
	}
1362
	$dhcrelayifs = array_unique($dhcrelayifs);
1363

    
1364
	/*
1365
	 * In order for the relay to work, it needs to be active
1366
	 * on the interface in which the destination server sits.
1367
	 */
1368
	$srvips = explode(",", $dhcrelaycfg['server']);
1369
        $srvifaces = array();
1370
	foreach ($srvips as $srcidx => $srvip) {
1371
		unset($destif);
1372
		foreach ($iflist as $ifname) {
1373
			$subnet = get_interface_ipv6($ifname);
1374
			if (!is_ipaddrv6($subnet))
1375
				continue;
1376
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1377
			if (ip_in_subnet($srvip, $subnet)) {
1378
				$destif = get_real_interface($ifname);
1379
				break;
1380
			}
1381
		}
1382
		if (!isset($destif)) {
1383
			if (is_array($config['staticroutes']['route'])) {
1384
				foreach ($config['staticroutes']['route'] as $rtent) {
1385
					if (ip_in_subnet($srvip, $rtent['network'])) {
1386
						$a_gateways = return_gateways_array(true);
1387
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1388
						break;
1389
					}
1390
				}
1391
			}
1392
		}
1393

    
1394
		if (!isset($destif)) {
1395
			/* Create a array from the existing route table */
1396
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1397
        		array_shift($route_str);
1398
        		array_shift($route_str);
1399
        		array_shift($route_str);
1400
        		array_shift($route_str);
1401
        		$route_arr = array();
1402
        		foreach($route_str as $routeline) {
1403
                		$items = preg_split("/[ ]+/i", $routeline);
1404
				if (ip_in_subnet($srvip, $items[0])) {
1405
					$destif = trim($items[6]);
1406
					break;
1407
				}
1408
        		}
1409
		}
1410

    
1411
		if (!isset($destif)) {
1412
			if (is_array($config['gateways']['gateway_item'])) {
1413
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1414
					if (isset($gateway['defaultgw'])) {
1415
						$a_gateways = return_gateways_array(true);
1416
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1417
						break;
1418
					}
1419
				}
1420
			} else
1421
				$destif = get_real_interface("wan");
1422
		}
1423

    
1424
		if (!empty($destif)) {
1425
			$srvifaces[] = "{$srvip}%{$destif}";
1426
		}
1427
	}
1428

    
1429
	/* fire up dhcrelay */
1430
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1431
		log_error("No suitable interface found for running dhcrelay -6!");
1432
		return; /* XXX */
1433
	}
1434

    
1435
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varetc_path']}/dhcrelay6.pid\"";
1436
	foreach ($dhcrelayifs as $dhcrelayif) {
1437
		$cmd .= " -l {$dhcrelayif}";
1438
	}
1439
	foreach ($srvifaces as $srviface) {
1440
		$cmd .= " -u \"{$srviface}\"";
1441
	}
1442
	mwexec($cmd);
1443
	unset($cmd);
1444

    
1445
	return 0;
1446
}
1447

    
1448
function services_dyndns_configure_client($conf) {
1449

    
1450
	if (!isset($conf['enable']))
1451
		return;
1452

    
1453
	/* load up the dyndns.class */
1454
	require_once("dyndns.class");
1455

    
1456
	$dns = new updatedns($dnsService = $conf['type'],
1457
		$dnsHost = $conf['host'],
1458
		$dnsUser = $conf['username'],
1459
		$dnsPass = $conf['password'],
1460
		$dnsWilcard = $conf['wildcard'],
1461
		$dnsMX = $conf['mx'],
1462
		$dnsIf = "{$conf['interface']}",
1463
		$dnsBackMX = NULL,
1464
		$dnsServer = NULL,
1465
		$dnsPort = NULL,
1466
		$dnsUpdateURL = "{$conf['updateurl']}",
1467
		$forceUpdate = $conf['force'],
1468
                $dnsZoneID=$conf['zoneid'],
1469
                $dnsTTL=$conf['ttl'],
1470
		$dnsResultMatch = "{$conf['resultmatch']}",
1471
		$dnsRequestIf = "{$conf['requestif']}",
1472
		$dnsID = "{$conf['id']}");
1473
}
1474

    
1475
function services_dyndns_configure($int = "") {
1476
	global $config, $g;
1477
	if(isset($config['system']['developerspew'])) {
1478
		$mt = microtime();
1479
		echo "services_dyndns_configure() being called $mt\n";
1480
	}
1481

    
1482
	$dyndnscfg = $config['dyndnses']['dyndns'];
1483
	$gwgroups = return_gateway_groups_array();
1484
	if (is_array($dyndnscfg)) {
1485
		if ($g['booting'])
1486
			echo gettext("Starting DynDNS clients...");
1487

    
1488
		foreach ($dyndnscfg as $dyndns) {
1489
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1490
				services_dyndns_configure_client($dyndns);
1491
				sleep(1);
1492
			}
1493
		}
1494

    
1495
		if ($g['booting'])
1496
			echo gettext("done.") . "\n";
1497
	}
1498

    
1499
	return 0;
1500
}
1501

    
1502
function services_dnsmasq_configure() {
1503
	global $config, $g;
1504
	$return = 0;
1505

    
1506
	if(isset($config['system']['developerspew'])) {
1507
		$mt = microtime();
1508
		echo "services_dnsmasq_configure() being called $mt\n";
1509
	}
1510

    
1511
	/* kill any running dnsmasq */
1512
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1513
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1514

    
1515
	if (isset($config['dnsmasq']['enable'])) {
1516

    
1517
		if ($g['booting'])
1518
			echo gettext("Starting DNS forwarder...");
1519
		else
1520
			sleep(1);
1521

    
1522
		/* generate hosts file */
1523
		if(system_hosts_generate()!=0)
1524
			$return = 1;
1525

    
1526
		$args = "";
1527

    
1528
		if (isset($config['dnsmasq']['regdhcp'])) {
1529
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1530
		}
1531

    
1532
		/* Setup forwarded domains */
1533
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1534
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1535
			        $args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1536
			}
1537
		}
1538

    
1539
		/* Allow DNS Rebind for forwarded domains */
1540
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1541
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1542
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1543
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1544
				}
1545
			}
1546
		}
1547

    
1548
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1549
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1550

    
1551
		if (isset($config['dnsmasq']['strict_order'])) {
1552
			$args .= " --strict-order ";
1553
		}
1554

    
1555
		if (isset($config['dnsmasq']['domain_needed'])) {
1556
			$args .= " --domain-needed ";
1557
		}
1558

    
1559
		if ($config['dnsmasq']['custom_options']) {
1560
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1561
				$args .= " --$c";
1562
		}
1563

    
1564
		/* run dnsmasq */
1565
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1566
		unset($args);
1567

    
1568
		if ($g['booting'])
1569
			echo gettext("done.") . "\n";
1570
	}
1571

    
1572
	if (!$g['booting']) {
1573
		if(services_dhcpd_configure()!=0)
1574
			$return = 1;
1575
	}
1576

    
1577
	return $return;
1578
}
1579

    
1580
function services_unbound_configure() {
1581
	global $config, $g;
1582
	$return = 0;
1583

    
1584
	if(isset($config['system']['developerspew'])) {
1585
		$mt = microtime();
1586
		echo "services_unbound_configure() being called $mt\n";
1587
	}
1588

    
1589
	/* kill any running unbound */
1590
	sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
1591

    
1592
	if (isset($config['unbound']['enable'])) {
1593

    
1594
		if ($g['booting'])
1595
			echo "Starting Unbound DNS...";
1596
		else
1597
			sleep(1);
1598

    
1599
		/* Setup Unbound DHCP Chroot environment */
1600
		$fd = fopen("{$g['tmp_path']}/unbound.sh","w");
1601
		$status = `/sbin/mount | /usr/bin/grep "{$g['unbound_chroot_path']}/dev"`;
1602
		fwrite($fd, "mkdir -p {$g['unbound_chroot_path']}\n");
1603
		fwrite($fd, "mkdir -p {$g['unbound_chroot_path']}/dev\n");
1604
		fwrite($fd, "mkdir -p {$g['unbound_chroot_path']}/etc\n");
1605
		if(!trim($status))
1606
			fwrite($fd, "mount -t devfs devfs {$g['unbound_chroot_path']}/dev\n");
1607
		fclose($fd);
1608
		mwexec("/bin/sh {$g['tmp_path']}/unbound.sh");
1609

    
1610
		/* generate Unbound config file */
1611
		if(unbound_generate_config()!=0) {
1612
			log_error("Problem generating Unbound configuration.");
1613
			$return = 1;
1614
		}
1615

    
1616
		/* run Unbound */
1617
		mwexec("/usr/local/sbin/unbound -c {$g['unbound_chroot_path']}/etc/unbound.conf");
1618

    
1619
		if ($g['booting'])
1620
			echo "done.\n";
1621
	}
1622

    
1623
	return $return;
1624
}
1625

    
1626
function services_snmpd_configure() {
1627
	global $config, $g;
1628
	if(isset($config['system']['developerspew'])) {
1629
		$mt = microtime();
1630
		echo "services_snmpd_configure() being called $mt\n";
1631
	}
1632

    
1633
	/* kill any running snmpd */
1634
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1635
	sleep(2);
1636
	if(is_process_running("bsnmpd"))
1637
		mwexec("/usr/bin/killall bsnmpd", true);
1638

    
1639
	if (isset($config['snmpd']['enable'])) {
1640

    
1641
		if ($g['booting'])
1642
			echo gettext("Starting SNMP daemon... ");
1643

    
1644
		/* generate snmpd.conf */
1645
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1646
		if (!$fd) {
1647
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1648
			return 1;
1649
		}
1650

    
1651

    
1652
		$snmpdconf = <<<EOD
1653
location := "{$config['snmpd']['syslocation']}"
1654
contact := "{$config['snmpd']['syscontact']}"
1655
read := "{$config['snmpd']['rocommunity']}"
1656

    
1657
EOD;
1658

    
1659
/* No docs on what write strings do there for disable for now.
1660
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1661
		    $snmpdconf .= <<<EOD
1662
# write string
1663
write := "{$config['snmpd']['rwcommunity']}"
1664

    
1665
EOD;
1666
		}
1667
*/
1668

    
1669

    
1670
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1671
		    $snmpdconf .= <<<EOD
1672
# SNMP Trap support.
1673
traphost := {$config['snmpd']['trapserver']}
1674
trapport := {$config['snmpd']['trapserverport']}
1675
trap := "{$config['snmpd']['trapstring']}"
1676

    
1677

    
1678
EOD;
1679
		}
1680

    
1681

    
1682
		$snmpdconf .= <<<EOD
1683
system := 1     # pfSense
1684
%snmpd
1685
begemotSnmpdDebugDumpPdus       = 2
1686
begemotSnmpdDebugSyslogPri      = 7
1687
begemotSnmpdCommunityString.0.1 = $(read)
1688

    
1689
EOD;
1690

    
1691
/* No docs on what write strings do there for disable for now.
1692
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1693
		    $snmpdconf .= <<<EOD
1694
begemotSnmpdCommunityString.0.2 = $(write)
1695

    
1696
EOD;
1697
		}
1698
*/
1699

    
1700

    
1701
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1702
		    $snmpdconf .= <<<EOD
1703
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1704
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1705
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1706

    
1707
EOD;
1708
		}
1709

    
1710

    
1711
		$snmpdconf .= <<<EOD
1712
begemotSnmpdCommunityDisable    = 1
1713

    
1714
EOD;
1715

    
1716
		if (isset($config['snmpd']['bindlan'])) {
1717
			$config['snmpd']['bindip'] = 'lan';
1718
			unset($config['snmpd']['bindlan']);
1719
		}
1720
		$bind_to_ip = "0.0.0.0";
1721
		if(isset($config['snmpd']['bindip'])) {
1722
			if (is_ipaddr($config['snmpd']['bindip'])) {
1723
				$bind_to_ip = $config['snmpd']['bindip'];
1724
			} else {
1725
				$if = get_real_interface($config['snmpd']['bindip']);
1726
				if (does_interface_exist($if))
1727
					$bind_to_ip = find_interface_ip($if);
1728
			}
1729
		}
1730

    
1731
		if(is_port( $config['snmpd']['pollport'] )) {
1732
		    $snmpdconf .= <<<EOD
1733
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1734

    
1735
EOD;
1736

    
1737
		}
1738

    
1739
		$snmpdconf .= <<<EOD
1740
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1741
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1742

    
1743
# These are bsnmp macros not php vars.
1744
sysContact      = $(contact)
1745
sysLocation     = $(location)
1746
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1747

    
1748
snmpEnableAuthenTraps = 2
1749

    
1750
EOD;
1751

    
1752
		if (is_array( $config['snmpd']['modules'] )) {
1753
		    if(isset($config['snmpd']['modules']['mibii'])) {
1754
			$snmpdconf .= <<<EOD
1755
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1756

    
1757
EOD;
1758
		    }
1759

    
1760
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1761
			$snmpdconf .= <<<EOD
1762
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1763
%netgraph
1764
begemotNgControlNodeName = "snmpd"
1765

    
1766
EOD;
1767
		    }
1768

    
1769
		    if(isset($config['snmpd']['modules']['pf'])) {
1770
			$snmpdconf .= <<<EOD
1771
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1772

    
1773
EOD;
1774
		    }
1775

    
1776
		    if(isset($config['snmpd']['modules']['hostres'])) {
1777
			$snmpdconf .= <<<EOD
1778
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1779

    
1780
EOD;
1781
		    }
1782
		    if(isset($config['snmpd']['modules']['bridge'])) {
1783
			$snmpdconf .= <<<EOD
1784
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1785
# config must end with blank line
1786

    
1787
EOD;
1788
		    }
1789
			if(isset($config['snmpd']['modules']['ucd'])) {
1790
				$snmpdconf .= <<<EOD
1791
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1792

    
1793
EOD;
1794
			}
1795
			if(isset($config['snmpd']['modules']['regex'])) {
1796
				$snmpdconf .= <<<EOD
1797
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1798

    
1799
EOD;
1800
			}
1801
		}
1802

    
1803
		fwrite($fd, $snmpdconf);
1804
		fclose($fd);
1805
		unset($snmpdconf);
1806

    
1807
		if (isset($config['snmpd']['bindlan'])) {
1808
			$bindlan = "";
1809
		}
1810

    
1811
		/* run bsnmpd */
1812
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1813
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1814

    
1815
		if ($g['booting'])
1816
			echo gettext("done.") . "\n";
1817
	}
1818

    
1819
	return 0;
1820
}
1821

    
1822
function services_dnsupdate_process($int = "") {
1823
	global $config, $g;
1824
	if(isset($config['system']['developerspew'])) {
1825
		$mt = microtime();
1826
		echo "services_dnsupdate_process() being called $mt\n";
1827
	}
1828

    
1829
	/* Dynamic DNS updating active? */
1830
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1831
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1832
			if (!isset($dnsupdate['enable']))
1833
				continue;
1834
			if (!empty($int) && $int != $dnsupdate['interface'])
1835
				continue;
1836

    
1837
			/* determine interface name */
1838
			$if = get_real_interface($dnsupdate['interface']);
1839
			$wanip = get_interface_ip($dnsupdate['interface']);
1840
			if ($wanip) {
1841

    
1842
				$keyname = $dnsupdate['keyname'];
1843
				/* trailing dot */
1844
				if (substr($keyname, -1) != ".")
1845
					$keyname .= ".";
1846

    
1847
				$hostname = $dnsupdate['host'];
1848
				/* trailing dot */
1849
				if (substr($hostname, -1) != ".")
1850
					$hostname .= ".";
1851

    
1852
				/* write private key file
1853
				   this is dumb - public and private keys are the same for HMAC-MD5,
1854
				   but nsupdate insists on having both */
1855
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
1856
				$privkey = <<<EOD
1857
Private-key-format: v1.2
1858
Algorithm: 157 (HMAC)
1859
Key: {$dnsupdate['keydata']}
1860

    
1861
EOD;
1862
				fwrite($fd, $privkey);
1863
				fclose($fd);
1864

    
1865
				/* write public key file */
1866
				if ($dnsupdate['keytype'] == "zone") {
1867
					$flags = 257;
1868
					$proto = 3;
1869
				} else if ($dnsupdate['keytype'] == "host") {
1870
					$flags = 513;
1871
					$proto = 3;
1872
				} else if ($dnsupdate['keytype'] == "user") {
1873
					$flags = 0;
1874
					$proto = 2;
1875
				}
1876

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

    
1881
				/* generate update instructions */
1882
				$upinst = "";
1883
				if (!empty($dnsupdate['server']))
1884
					$upinst .= "server {$dnsupdate['server']}\n";
1885
				$upinst .= "update delete {$dnsupdate['host']} A\n";
1886
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
1887
				$upinst .= "\n";	/* mind that trailing newline! */
1888

    
1889
				@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
1890
				unset($upinst);
1891

    
1892
				/* invoke nsupdate */
1893
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
1894
				if (isset($dnsupdate['usetcp']))
1895
					$cmd .= " -v";
1896
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
1897

    
1898
				mwexec_bg($cmd);
1899
				unset($cmd);
1900
			}
1901
		}
1902
	}
1903

    
1904
	return 0;
1905
}
1906

    
1907
/* configure cron service */
1908
function configure_cron() {
1909
	global $g, $config;
1910

    
1911
	conf_mount_rw();
1912
	/* preserve existing crontab entries */
1913
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1914

    
1915
	for ($i = 0; $i < count($crontab_contents); $i++) {
1916
		$cron_item =& $crontab_contents[$i];
1917
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
1918
			array_splice($crontab_contents, $i - 1);
1919
			break;
1920
		}
1921
	}
1922
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
1923

    
1924

    
1925
	if (is_array($config['cron']['item'])) {
1926
		$crontab_contents .= "#\n";
1927
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
1928
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
1929
		$crontab_contents .= "#\n";
1930

    
1931
		foreach ($config['cron']['item'] as $item) {
1932
			$crontab_contents .= "\n{$item['minute']}\t";
1933
			$crontab_contents .= "{$item['hour']}\t";
1934
			$crontab_contents .= "{$item['mday']}\t";
1935
			$crontab_contents .= "{$item['month']}\t";
1936
			$crontab_contents .= "{$item['wday']}\t";
1937
			$crontab_contents .= "{$item['who']}\t";
1938
			$crontab_contents .= "{$item['command']}";
1939
		}
1940

    
1941
		$crontab_contents .= "\n#\n";
1942
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
1943
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
1944
		$crontab_contents .= "#\n\n";
1945
	}
1946

    
1947
	/* please maintain the newline at the end of file */
1948
	file_put_contents("/etc/crontab", $crontab_contents);
1949
	unset($crontab_contents);
1950

    
1951
	/* do a HUP kill to force sync changes */
1952
	exec('/bin/pkill -HUP cron');
1953

    
1954
	conf_mount_ro();
1955
}
1956

    
1957
function upnp_action ($action) {
1958
	global $g, $config;
1959
	switch($action) {
1960
		case "start":
1961
			if (file_exists('/var/etc/miniupnpd.conf')) {
1962
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
1963
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
1964
			}
1965
			break;
1966
		case "stop":
1967
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
1968
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
1969
				mwexec('killall miniupnpd 2>/dev/null', true);
1970
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
1971
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
1972
			break;
1973
		case "restart":
1974
			upnp_action('stop');
1975
			upnp_action('start');
1976
			break;
1977
	}
1978
}
1979

    
1980
function upnp_start() {
1981
	global $config;
1982

    
1983
	if(!isset($config['installedpackages']['miniupnpd']['config']))
1984
		return;
1985

    
1986
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1987
		echo gettext("Starting UPnP service... ");
1988
		require_once('/usr/local/pkg/miniupnpd.inc');
1989
		sync_package_miniupnpd();
1990
		echo "done.\n";
1991
	}
1992
}
1993

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

    
1997
	$is_installed = false;
1998

    
1999
	if (!is_array($config['cron']))
2000
		$config['cron'] = array();
2001
	if (!is_array($config['cron']['item']))
2002
		$config['cron']['item'] = array();
2003

    
2004
	$x=0;
2005
	foreach($config['cron']['item'] as $item) {
2006
		if(strstr($item['command'], $command)) {
2007
			$is_installed = true;
2008
			break;
2009
		}
2010
		$x++;
2011
	}
2012

    
2013
	if($active) {
2014
		$cron_item = array();
2015
		$cron_item['minute'] = $minute;
2016
		$cron_item['hour'] = $hour;
2017
		$cron_item['mday'] = $monthday;
2018
		$cron_item['month'] = $month;
2019
		$cron_item['wday'] = $weekday;
2020
		$cron_item['who'] = $who;
2021
		$cron_item['command'] = $command;
2022
		if(!$is_installed) {
2023
			$config['cron']['item'][] = $cron_item;
2024
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2025
		} else {
2026
			$config['cron']['item'][$x] = $cron_item;
2027
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2028
		}
2029
	} else {
2030
		if(($is_installed == true) && ($x > 0)) {
2031
			unset($config['cron']['item'][$x]);
2032
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2033
		}
2034
	}
2035
	configure_cron();
2036
}
2037

    
2038
?>
(49-49/67)