Project

General

Profile

Download (60.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	services.inc
5
	part of the pfSense project (http://www.pfsense.com)
6

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

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

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

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

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

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

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

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

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

    
58
	$dhcpdv6cfg = $config['dhcpdv6'];
59
	$Iflist = get_configured_interface_list();
60

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

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

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

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

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

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

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

    
94
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
95
		if(!is_ipaddrv6($ifcfgipv6))
96
			continue;
97

    
98
		if(in_array($realif, $radvdifs))
99
			continue;
100

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

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

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

    
174
		/* add DNS servers */
175
		$dnslist = array();
176
		if(!empty($dhcpv6ifconf['dnsserver'][0])) {
177
			foreach($dhcpv6ifconf['dnsserver'] as $server) {
178
				if(is_ipaddrv6($server))
179
					$dnslist[] = $server;
180
			}
181
		} elseif (isset($config['dnsmasq']['enable'])) {
182
			$dnslist[] = get_interface_ipv6($realif);
183
		} elseif (!empty($config['system']['dnsserver'][0])) {
184
			foreach($config['system']['dnsserver'] as $server) {
185
				if(is_ipaddrv6($server))
186
					$dnslist[] = $server;
187
			}
188
		}
189
		if(count($dnslist) > 0) {
190
			$dnsstring = implode(" ", $dnslist);
191
			if($dnsstring <> "")
192
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
193
		}
194
		if($dhcpv6ifconf['domain'] <> "") {
195
			$radvdconf .= "\tDNSSL {$dhcpv6ifconf['domain']} { };\n";
196
		} elseif ($config['system']['domain'] <> "") {
197
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
198
		}
199
		$radvdconf .= "};\n";
200
		$radvdnum++;
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
		$subnetmaskv6 = gen_subnet_mask($ifcfgsnv6);
222
		$trackif = $config['interfaces'][$if]['track6-interface'];
223
		$radvdifs[] = $realif;
224

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

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

    
244
				/* add DNS servers */
245
				$dnslist = array();
246
				if (isset($config['dnsmasq']['enable'])) {
247
						$dnslist[] = $ifcfgipv6;
248
				} elseif (!empty($config['system']['dnsserver'][0])) {
249
					foreach($config['system']['dnsserver'] as $server) {
250
						if(is_ipaddrv6($server))
251
							$dnslist[] = $server;
252
					}
253
				}
254
				if(count($dnslist) > 0) {
255
					$dnsstring = implode(" ", $dnslist);
256
					if($dnsstring <> "")
257
						$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
258
				}
259
				if ($config['system']['domain'] <> "") {
260
					$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
261
				}
262
			$radvdconf .= "};\n";
263
			$radvdnum++;
264
		}
265
	}
266

    
267
	/* write radvd.conf */
268
	if (!@file_put_contents("{$g['varetc_path']}/radvd.conf", $radvdconf))
269
		printf("Error: cannot open radvd.conf in services_radvd_configure().\n");
270
	unset($radvdconf);
271

    
272
	if(count($radvdifs) > 0) {
273
		if(is_process_running("radvd")) {
274
			mwexec("killall -1 radvd");
275
		} else {
276
			mwexec("/usr/local/sbin/radvd -C {$g['varetc_path']}/radvd.conf -m syslog");
277
		}
278
	} else {
279
		/* we need to shut down the radvd cleanly, it will send out the prefix
280
		 * information with a lifetime of 0 to notify clients of a (possible) new prefix */
281
		if(is_process_running("radvd")) {
282
			log_error("Shutting down Router Advertisment daemon cleanly");
283
			mwexec("killall radvd");
284
		}
285
	}
286
	return 0;
287
}
288

    
289
function services_dhcpd_configure() {
290
	global $config, $g;
291

    
292
	/* configure DHCPD chroot once */
293
	$fd = fopen("{$g['tmp_path']}/dhcpd.sh","w");
294
	$status = `mount | grep "{$g['dhcpd_chroot_path']}/dev"`;
295
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}\n");
296
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/dev\n");
297
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/etc\n");
298
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/usr/local/sbin\n");
299
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/var/db\n");
300
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/var/run\n");
301
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/usr\n");
302
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/lib\n");
303
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/run\n");
304
	fwrite($fd, "chown -R dhcpd:_dhcp {$g['dhcpd_chroot_path']}/*\n");
305
	fwrite($fd, "cp /lib/libc.so.* {$g['dhcpd_chroot_path']}/lib/\n");
306
	fwrite($fd, "cp /usr/local/sbin/dhcpd {$g['dhcpd_chroot_path']}/usr/local/sbin/\n");
307
	fwrite($fd, "chmod a+rx {$g['dhcpd_chroot_path']}/usr/local/sbin/dhcpd\n");
308

    
309
	if(!trim($status))
310
		fwrite($fd, "mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
311
	fclose($fd);
312
	mwexec("/bin/sh {$g['tmp_path']}/dhcpd.sh");
313

    
314
	services_dhcpdv4_configure();
315
	services_dhcpdv6_configure();
316
	services_radvd_configure();
317
	return;
318

    
319
}
320
function services_dhcpdv4_configure() {
321
	global $config, $g;
322

    
323
	if($g['services_dhcp_server_enable'] == false)
324
		return;
325

    
326
	if(isset($config['system']['developerspew'])) {
327
		$mt = microtime();
328
		echo "services_dhcpdv4_configure($if) being called $mt\n";
329
	}
330

    
331
	/* kill any running dhcpd */
332
	if(is_process_running("dhcpd")) {
333
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
334
	}
335

    
336
	/* DHCP enabled on any interfaces? */
337
	if (!is_dhcp_server_enabled())
338
		return 0;
339

    
340
	/* if OLSRD is enabled, allow WAN to house DHCP. */
341
	if($config['installedpackages']['olsrd'])
342
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
343
				if($olsrd['enable'])
344
					$is_olsr_enabled = true;
345

    
346
	if ($g['booting']) {
347
		if ($g['platform'] != "pfSense") {
348
			/* restore the leases, if we have them */
349
			if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
350
				$dhcprestore = "";
351
				$dhcpreturn = "";
352
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
353
				$dhcprestore = implode(" ", $dhcprestore);
354
				if($dhcpreturn <> 0) {
355
					log_error(sprintf(gettext('DHCP leases restore failed exited with %1$s, the error is: %2$s%3$s'), $dhcpreturn, $dhcprestore, "\n"));
356
				}
357
			}
358
		}
359
	}
360

    
361
	$syscfg = $config['system'];
362
	if (!is_array($config['dhcpd']))
363
		$config['dhcpd'] = array();
364
	$dhcpdcfg = $config['dhcpd'];
365
	$Iflist = get_configured_interface_list();
366

    
367
	if ($g['booting'])
368
		echo gettext("Starting DHCP service...");
369
	else
370
		sleep(1);
371

    
372
	/* write dhcpd.conf */
373
	$fd = fopen("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", "w");
374
	if (!$fd) {
375
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
376
		return 1;
377
	}
378

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

    
392
	$dhcpdconf = <<<EOD
393

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

    
406
EOD;
407

    
408
	if(!isset($dhcpifconf['disableauthoritative']))
409
		$dhcpdconf .= "authoritative;\n";
410

    
411
	if(isset($dhcpifconf['alwaysbroadcast']))
412
		$dhcpdconf .= "always-broadcast on\n";
413

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

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

    
432
		interfaces_staticarp_configure($dhcpif);
433

    
434
		if (!isset($dhcpifconf['enable']))
435
			continue;
436

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

    
483
EOPP;
484
		$dhcpnum++;
485
		}
486
	}
487

    
488
	$dhcpnum = 0;
489

    
490
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
491

    
492
		$ifcfg = $config['interfaces'][$dhcpif];
493

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

    
501
		if (!is_ipaddr($subnet))
502
			continue;
503

    
504
		if($is_olsr_enabled == true)
505
			if($dhcpifconf['netmask'])
506
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
507

    
508
		$all_pools = array();
509
		$all_pools[] = $dhcpifconf;
510
		if (is_array($dhcpifconf['pool'])) {
511
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
512
		}
513

    
514
		$dnscfg = "";
515

    
516
		if ($dhcpifconf['domain']) {
517
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
518
		}
519

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

    
524
		if (isset($dhcpifconf['ddnsupdate'])) {
525
			if($dhcpifconf['ddnsdomain'] <> "") {
526
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
527
			}
528
			$dnscfg .= "	ddns-update-style interim;\n";
529
		}
530

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

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

    
560
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
561

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

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

    
587
			if($poolconf['failover_peerip'] <> "")
588
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
589

    
590
			if (isset($poolconf['denyunknown']))
591
			   $dhcpdconf .= "		deny unknown-clients;\n";
592

    
593
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
594
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
595

    
596
			if($dhcpifconf['failover_peerip'] <> "") {
597
				$dhcpdconf .= "		failover peer \"dhcp{$dhcpnum}\";\n";
598
				$dhcpnum++;
599
			}
600

    
601
			$pdnscfg = "";
602

    
603
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
604
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
605
			}
606

    
607
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
608
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
609
			}
610

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

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

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

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

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

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

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

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

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

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

    
675
		$dhcpdconf .= <<<EOD
676
$dnscfg
677

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

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

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

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

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

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

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

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

    
729
		$dhcpdconf .= <<<EOD
730
}
731

    
732
EOD;
733

    
734
		/* add static mappings */
735
		if (is_array($dhcpifconf['staticmap'])) {
736

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

    
743
EOD;
744
				if ($sm['ipaddr'])
745
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
746

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

    
755
				if ($sm['rootpath'])
756
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
757

    
758
				$dhcpdconf .= "}\n";
759
				$i++;
760
			}
761
		}
762

    
763
		$dhcpdifs[] = get_real_interface($dhcpif);
764
	}
765

    
766
	fwrite($fd, $dhcpdconf);
767
	fclose($fd);
768
	unset($dhcpdconf);
769

    
770
	/* create an empty leases database */
771
	touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
772

    
773

    
774
	/* fire up dhcpd in a chroot */
775
	if(count($dhcpdifs) > 0) {
776
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
777
			join(" ", $dhcpdifs));
778
	}
779

    
780
	if ($g['booting']) {
781
		print "done.\n";
782
	}
783

    
784
	return 0;
785
}
786

    
787
function services_dhcpdv6_configure() {
788
	global $config, $g;
789

    
790
	if($g['services_dhcp_server_enable'] == false)
791
		return;
792

    
793
	if(isset($config['system']['developerspew'])) {
794
		$mt = microtime();
795
		echo "services_dhcpd_configure($if) being called $mt\n";
796
	}
797

    
798
	/* kill any running dhcpd */
799
	if(is_process_running("dhcpd")) {
800
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
801
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
802
	}
803

    
804
	/* DHCP enabled on any interfaces? */
805
	if (!is_dhcpv6_server_enabled())
806
		return 0;
807

    
808
	if ($g['booting']) {
809
		if ($g['platform'] != "pfSense") {
810
			/* restore the leases, if we have them */
811
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
812
				$dhcprestore = "";
813
				$dhcpreturn = "";
814
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
815
				$dhcprestore = implode(" ", $dhcprestore);
816
				if($dhcpreturn <> 0) {
817
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
818
				}
819
			}
820
		}
821
	}
822

    
823
	$syscfg = $config['system'];
824
	if (!is_array($config['dhcpdv6']))
825
		$config['dhcpdv6'] = array();
826
	$dhcpdv6cfg = $config['dhcpdv6'];
827
	$Iflist = get_configured_interface_list();
828

    
829
	if ($g['booting'])
830
		echo "Starting DHCPv6 service...";
831
	else
832
		sleep(1);
833

    
834
	/* we add a fake entry for interfaces that are set to track6 another WAN */
835
	foreach($Iflist as $ifname) {
836
		$realif = get_real_interface($ifname);
837
		$ifcfgipv6 = find_interface_ipv6($realif);
838
		if(!is_ipaddrv6($ifcfgipv6))
839
			continue;
840
		$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
841
		if($config['interfaces'][$ifname]['track6-interface'] <> "") {
842
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
843
			$trackcfg = $config['interfaces'][$trackifname];
844
			$pdlen = calculate_ipv6_delegation_length($trackifname);
845
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
846
			$dhcpdv6cfg[$ifname] = array();
847
			$dhcpdv6cfg[$ifname]['enable'] = true;
848
			/* range */
849
			$ifcfgipv6arr[7] = "1000";
850
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
851
			$ifcfgipv6arr[7] = "2000";
852
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
853
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
854
			if($pdlen > 2) {
855
				$pdlenmax = $pdlen;
856
				$pdlenhalf = $pdlenmax -1;
857
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
858
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
859

    
860
				/* set the delegation start to half the current address block */
861
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
862
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
863

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

    
868
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
869
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
870
			}
871
		}
872
	}
873

    
874
	/* write dhcpdv6.conf */
875
	$fdv6 = fopen("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", "w");
876
	if (! $fdv6) {
877
		printf("Error: cannot open dhcpdv6.conf in services_dhcpdv6_configure().\n");
878
		return 1;
879
	}
880

    
881
	$custoptionsv6 = "";
882
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
883
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
884
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
885
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
886
			}
887
		}
888
	}
889

    
890
	$dhcpdv6conf = <<<EOD
891

    
892
option domain-name "{$syscfg['domain']}";
893
option ldap-server code 95 = text;
894
option domain-search-list code 119 = text;
895
{$custoptions}
896
default-lease-time 7200;
897
max-lease-time 86400;
898
log-facility local7;
899
ddns-update-style none;
900
one-lease-per-client true;
901
deny duplicates;
902
ping-check true;
903

    
904
EOD;
905

    
906
	if(!isset($dhcpv6ifconf['disableauthoritative']))
907
		$dhcpdv6conf .= "authoritative;\n";
908

    
909
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
910
		$dhcpdv6conf .= "always-broadcast on\n";
911

    
912
	$dhcpdv6ifs = array();
913

    
914
	/*    loop through and determine if we need to setup
915
	 *    failover peer "bleh" entries
916
	 */
917
	$dhcpv6num = 0;
918
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
919

    
920
		if (!isset($dhcpv6ifconf['enable']))
921
			continue;
922

    
923
		if($dhcpv6ifconf['failover_peerip'] <> "") {
924
			$intv6 = guess_interface_from_ip($dhcpv6ifconf['failover_peerip']);
925
			$intipv6 = find_interface_ipv6($intv6);
926
			$real_dhcpv6if = convert_friendly_interface_to_real_interface_name($dhcpv6if);
927
			/*
928
			 *    yep, failover peer is defined.
929
			 *    does it match up to a defined vip?
930
			 */
931
			$skew = 110;
932
			$a_vip = &$config['virtualip']['vip'];
933
			if(is_array($a_vip)) {
934
				foreach ($a_vip as $vipent) {
935
					if($intv6 == $real_dhcpv6if) {
936
						/* this is the interface! */
937
						if(is_numeric($vipent['advskew']) && ($vipent['advskew'] < "20"))
938
							$skew = 0;
939
					}
940
				}
941
			} else {
942
				log_error("Warning!  DHCPv6 Failover setup and no CARP virtual IPv6's defined!");
943
			}
944
			if($skew > 10) {
945
				$typev6 = "secondary";
946
				$dhcpdv6conf_pri  = "mclt 600;\n";
947
				$my_portv6 = "520";
948
				$peer_portv6 = "519";
949
			} else {
950
				$my_portv6 = "519";
951
				$peer_portv6 = "520";
952
				$typev6 = "primary";
953
				$dhcpdv6conf_pri  = "split 128;\n";
954
				$dhcpdv6conf_pri .= "  mclt 600;\n";
955
			}
956
			$dhcpdv6conf .= <<<EOPP
957
failover peer "dhcpv6{$dhcpv6num}" {
958
  {$typev6};
959
  address {$intipv6};
960
  port {$my_portv6};
961
  peer address {$dhcpv6ifconf['failover_peerip']};
962
  peer port {$peer_portv6};
963
  max-response-delay 10;
964
  max-unacked-updates 10;
965
  {$dhcpdv6conf_pri}
966
  load balance max seconds 3;
967
}
968

    
969
EOPP;
970
		$dhcpv6num++;
971
		}
972
	}
973

    
974
	$dhcpv6num = 0;
975
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
976

    
977
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
978

    
979
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
980
			continue;
981
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
982
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
983
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
984
		$subnetmaskv6 = gen_subnet_mask($ifcfgsnv6);
985

    
986
		if($is_olsr_enabled == true)
987
			if($dhcpv6ifconf['netmask'])
988
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
989

    
990
		$dnscfgv6 = "";
991

    
992
		if ($dhcpv6ifconf['domain']) {
993
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
994
		}
995

    
996
    		if($dhcpv6ifconf['domainsearchlist'] <> "") {
997
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
998
    		}
999

    
1000
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1001
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1002
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1003
			}
1004
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1005
		}
1006

    
1007
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1008
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1009
		} else if (isset($config['dnsmasq']['enable'])) {
1010
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1011
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1012
			$dns_arrv6 = array();
1013
			foreach($syscfg['dnsserver'] as $dnsserver) {
1014
				if(is_ipaddrv6($dnsserver)) {
1015
					$dns_arrv6[] = $dnsserver;
1016
				}
1017
			}
1018
			if(!empty($dns_arrv6))
1019
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1020
		}
1021

    
1022
		$subnet6 = Net_IPv6::compress(gen_subnetv6($ifcfgipv6, $ifcfgsnv6));
1023
		$dhcpdv6conf .= "subnet6 {$subnet6}/{$ifcfgsnv6} {\n";
1024

    
1025
		if($dhcpv6ifconf['failover_peerip'] <> "")
1026
			$dhcpdv6conf .= "		deny dynamic bootp clients;\n";
1027

    
1028
		if (isset($dhcpv6ifconf['denyunknown']))
1029
		   $dhcpdv6conf .= "		deny unknown-clients;\n";
1030

    
1031
		if($dhcpv6ifconf['failover_peerip'] <> "") {
1032
			$dhcpdv6conf .= "		failover peer \"dhcpv6{$dhcpv6num}\";\n";
1033
			$dhcpv6num++;
1034
		}
1035

    
1036
		$dhcpdv6conf .= <<<EOD
1037
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1038
$dnscfgv6
1039

    
1040
EOD;
1041

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

    
1045
		}
1046
    		// default-lease-time
1047
		if ($dhcpv6ifconf['defaultleasetime'])
1048
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1049

    
1050
		// max-lease-time
1051
		if ($dhcpv6ifconf['maxleasetime'])
1052
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1053

    
1054
		// ntp-servers
1055
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1056
			$ntpservers = array();
1057
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1058
				if(is_ipaddrv6($ntpserver))
1059
					$ntpservers[] = $ntpserver;
1060
			}
1061
			if(count($ntpservers) > 0 )
1062
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1063
		}
1064
		// tftp-server-name
1065
		/* Needs ISC DHCPD support
1066
		 if ($dhcpv6ifconf['tftp'] <> "")
1067
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1068
		*/
1069

    
1070
		// Handle option, number rowhelper values
1071
		$dhcpdv6conf .= "\n";
1072
		if($dhcpv6ifconf['numberoptions']['item']) {
1073
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1074
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1075
			}
1076
		}
1077

    
1078
		// ldap-server
1079
		if ($dhcpv6ifconf['ldap'] <> "")
1080
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1081

    
1082
		// net boot information
1083
		if(isset($dhcpv6ifconf['netboot'])) {
1084
			if ($dhcpv6ifconf['nextserver'] <> "") {
1085
				$dhcpdv6conf .= "	next-server {$dhcpv6ifconf['nextserver']};\n";
1086
			}
1087
			if ($dhcpv6ifconf['filename'] <> "") {
1088
				$dhcpdv6conf .= "	filename \"{$dhcpv6ifconf['filename']}\";\n";
1089
			}
1090
			if ($dhcpv6ifconf['rootpath'] <> "") {
1091
				$dhcpdv6conf .= "	option root-path \"{$dhcpv6ifconf['rootpath']}\";\n";
1092
      		}
1093
	}
1094

    
1095
		$dhcpdv6conf .= <<<EOD
1096
}
1097

    
1098
EOD;
1099

    
1100
		/* add static mappings */
1101
		/* Needs to use DUID */
1102
		if (is_array($dhcpv6ifconf['staticmap'])) {
1103

    
1104
			$i = 0;
1105
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1106
				$dhcpdv6conf .= <<<EOD
1107
host s_{$dhcpv6if}_{$i} {
1108
	host-identifier option dhcp6.client-id {$sm['duid']};
1109

    
1110
EOD;
1111
				if ($sm['ipaddrv6'])
1112
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1113

    
1114
				if ($sm['hostname']) {
1115
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1116
					$dhhostname = str_replace(".", "_", $dhhostname);
1117
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1118
				}
1119
				if ($sm['filename'])
1120
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1121

    
1122
				if ($sm['rootpath'])
1123
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1124

    
1125
				$dhcpdv6conf .= "}\n";
1126
				$i++;
1127
			}
1128
		}
1129

    
1130
		if($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1131
			$realif = escapeshellcmd(get_real_interface($dhcpv6if));
1132
			$dhcpdv6ifs[] = $realif;
1133
			exec("/sbin/ifconfig {$realif} |awk  '/ether/ {print $2}'", $mac);
1134
			$v6address = generate_ipv6_from_mac($mac[0]);
1135
			/* Create link local address for bridges */
1136
			if(stristr("$realif", "bridge")) {
1137
				mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1138
			}
1139
		}
1140
	}
1141

    
1142
	fwrite($fdv6, $dhcpdv6conf);
1143
	fclose($fdv6);
1144
	unset($dhcpdv6conf);
1145

    
1146
	/* create an empty leases v6 database */
1147
	touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1148

    
1149
	/* fire up dhcpd in a chroot */
1150
	if(count($dhcpdv6ifs) > 0) {
1151
		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 " .
1152
			join(" ", $dhcpdv6ifs));
1153
		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");
1154
	}
1155

    
1156
	if ($g['booting']) {
1157
		print gettext("done.") . "\n";
1158
	}
1159

    
1160
	return 0;
1161
}
1162

    
1163
function services_igmpproxy_configure() {
1164
        global $config, $g;
1165

    
1166
        /* kill any running igmpproxy */
1167
        killbyname("igmpproxy");
1168

    
1169
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1170
		return 1;
1171

    
1172
        $iflist = get_configured_interface_list();
1173

    
1174
        $igmpconf = <<<EOD
1175

    
1176
##------------------------------------------------------
1177
## Enable Quickleave mode (Sends Leave instantly)
1178
##------------------------------------------------------
1179
quickleave
1180

    
1181
EOD;
1182

    
1183
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1184
                unset($iflist[$igmpcf['ifname']]);
1185
                $realif = get_real_interface($igmpcf['ifname']);
1186
                if (empty($igmpcf['threshold']))
1187
                        $threshld = 1;
1188
                else
1189
                        $threshld = $igmpcf['threshold'];
1190
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1191

    
1192
                if ($igmpcf['address'] <> "") {
1193
                        $item = explode(" ", $igmpcf['address']);
1194
                        foreach($item as $iww)
1195
                                $igmpconf .= "altnet {$iww}\n";
1196
                }
1197
                $igmpconf .= "\n";
1198
        }
1199
        foreach ($iflist as $ifn) {
1200
                $realif = get_real_interface($ifn);
1201
                $igmpconf .= "phyint {$realif} disabled\n";
1202
        }
1203
	$igmpconf .= "\n";
1204

    
1205
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1206
        if (!$igmpfl) {
1207
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1208
                return;
1209
        }
1210
        fwrite($igmpfl, $igmpconf);
1211
        fclose($igmpfl);
1212
	unset($igmpconf);
1213

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

    
1217
        return 0;
1218
}
1219

    
1220
function services_dhcrelay_configure() {
1221
	global $config, $g;
1222
	if ($g['platform'] == 'jail')
1223
		return;
1224
	if(isset($config['system']['developerspew'])) {
1225
		$mt = microtime();
1226
		echo "services_dhcrelay_configure() being called $mt\n";
1227
	}
1228

    
1229
	/* kill any running dhcrelay */
1230
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1231

    
1232
	$dhcrelaycfg =& $config['dhcrelay'];
1233

    
1234
	/* DHCPRelay enabled on any interfaces? */
1235
	if (!isset($dhcrelaycfg['enable']))
1236
		return 0;
1237

    
1238
	if ($g['booting'])
1239
		echo gettext("Starting DHCP relay service...");
1240
	else
1241
		sleep(1);
1242

    
1243
	$iflist = get_configured_interface_list();
1244

    
1245
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1246
	foreach ($dhcifaces as $dhcrelayif) {
1247
		if (!isset($iflist[$dhcrelayif]) ||
1248
			link_interface_to_bridge($dhcrelayif))
1249
			continue;
1250

    
1251
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1252
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1253
	}
1254

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

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

    
1299
		if (!isset($destif)) {
1300
			if (is_array($config['gateways']['gateway_item'])) {
1301
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1302
					if (isset($gateway['defaultgw'])) {
1303
						$a_gateways = return_gateways_array(true);
1304
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1305
						break;
1306
					}
1307
				}
1308
			} else
1309
				$destif = get_real_interface("wan");
1310
		}
1311

    
1312
		if (!empty($destif))
1313
			$dhcrelayifs[] = $destif;
1314
	}
1315
	$dhcrelayifs = array_unique($dhcrelayifs);
1316

    
1317
	/* fire up dhcrelay */
1318
	if (empty($dhcrelayifs)) {
1319
		log_error("No suitable interface found for running dhcrelay!");
1320
		return; /* XXX */
1321
	}
1322

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

    
1325
	if (isset($dhcrelaycfg['agentoption']))
1326
		$cmd .=  " -a -m replace";
1327

    
1328
	$cmd .= " " . implode(" ", $srvips);
1329
	mwexec($cmd);
1330
	unset($cmd);
1331

    
1332
	return 0;
1333
}
1334

    
1335
function services_dhcrelay6_configure() {
1336
	global $config, $g;
1337
	if ($g['platform'] == 'jail')
1338
		return;
1339
	if(isset($config['system']['developerspew'])) {
1340
		$mt = microtime();
1341
		echo "services_dhcrelay_configure() being called $mt\n";
1342
	}
1343

    
1344
	/* kill any running dhcrelay */
1345
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1346

    
1347
	$dhcrelaycfg =& $config['dhcrelay6'];
1348

    
1349
	/* DHCPv6 Relay enabled on any interfaces? */
1350
	if (!isset($dhcrelaycfg['enable']))
1351
		return 0;
1352

    
1353
	if ($g['booting'])
1354
		echo gettext("Starting DHCPv6 relay service...");
1355
	else
1356
		sleep(1);
1357

    
1358
	$iflist = get_configured_interface_list();
1359

    
1360
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1361
	foreach ($dhcifaces as $dhcrelayif) {
1362
		if (!isset($iflist[$dhcrelayif]) ||
1363
			link_interface_to_bridge($dhcrelayif))
1364
			continue;
1365

    
1366
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1367
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1368
	}
1369
	$dhcrelayifs = array_unique($dhcrelayifs);
1370

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

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

    
1418
		if (!isset($destif)) {
1419
			if (is_array($config['gateways']['gateway_item'])) {
1420
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1421
					if (isset($gateway['defaultgw'])) {
1422
						$a_gateways = return_gateways_array(true);
1423
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1424
						break;
1425
					}
1426
				}
1427
			} else
1428
				$destif = get_real_interface("wan");
1429
		}
1430

    
1431
		if (!empty($destif)) {
1432
			$srvifaces[] = "{$srvip}%{$destif}";
1433
		}
1434
	}
1435

    
1436
	/* fire up dhcrelay */
1437
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1438
		log_error("No suitable interface found for running dhcrelay -6!");
1439
		return; /* XXX */
1440
	}
1441

    
1442
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varetc_path']}/dhcrelay6.pid\"";
1443
	foreach ($dhcrelayifs as $dhcrelayif) {
1444
		$cmd .= " -l {$dhcrelayif}";
1445
	}
1446
	foreach ($srvifaces as $srviface) {
1447
		$cmd .= " -u \"{$srviface}\"";
1448
	}
1449
	mwexec($cmd);
1450
	unset($cmd);
1451

    
1452
	return 0;
1453
}
1454

    
1455
function services_dyndns_configure_client($conf) {
1456

    
1457
	if (!isset($conf['enable']))
1458
		return;
1459

    
1460
	/* load up the dyndns.class */
1461
	require_once("dyndns.class");
1462

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

    
1482
function services_dyndns_configure($int = "") {
1483
	global $config, $g;
1484
	if(isset($config['system']['developerspew'])) {
1485
		$mt = microtime();
1486
		echo "services_dyndns_configure() being called $mt\n";
1487
	}
1488

    
1489
	$dyndnscfg = $config['dyndnses']['dyndns'];
1490
	$gwgroups = return_gateway_groups_array();
1491
	if (is_array($dyndnscfg)) {
1492
		if ($g['booting'])
1493
			echo gettext("Starting DynDNS clients...");
1494

    
1495
		foreach ($dyndnscfg as $dyndns) {
1496
			$failovergroup = interface_gateway_group_member($int);
1497
			if (!empty($int) && $int == $dyndns['interface']) {
1498
				services_dyndns_configure_client($dyndns);
1499
				sleep(1);
1500
			} elseif (is_array($gwgroups[$dyndns['interface']])){
1501
				services_dyndns_configure_client($dyndns);
1502
				sleep(1);				
1503
			} else {
1504
				continue;
1505
			}
1506
		}
1507

    
1508
		if ($g['booting'])
1509
			echo gettext("done.") . "\n";
1510
	}
1511

    
1512
	return 0;
1513
}
1514

    
1515
function services_dnsmasq_configure() {
1516
	global $config, $g;
1517
	$return = 0;
1518

    
1519
	if(isset($config['system']['developerspew'])) {
1520
		$mt = microtime();
1521
		echo "services_dnsmasq_configure() being called $mt\n";
1522
	}
1523

    
1524
	/* kill any running dnsmasq */
1525
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1526
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1527

    
1528
	if (isset($config['dnsmasq']['enable'])) {
1529

    
1530
		if ($g['booting'])
1531
			echo gettext("Starting DNS forwarder...");
1532
		else
1533
			sleep(1);
1534

    
1535
		/* generate hosts file */
1536
		if(system_hosts_generate()!=0)
1537
			$return = 1;
1538

    
1539
		$args = "";
1540

    
1541
		if (isset($config['dnsmasq']['regdhcp'])) {
1542
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1543
		}
1544

    
1545
		/* Setup forwarded domains */
1546
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1547
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1548
			        $args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1549
			}
1550
		}
1551

    
1552
		/* Allow DNS Rebind for forwarded domains */
1553
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1554
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1555
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1556
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1557
				}
1558
			}
1559
		}
1560

    
1561
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1562
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1563

    
1564
		if ($config['dnsmasq']['custom_options']) {
1565
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1566
				$args .= " --$c";
1567
		}
1568

    
1569
		/* run dnsmasq */
1570
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1571
		unset($args);
1572

    
1573
		if ($g['booting'])
1574
			echo gettext("done.") . "\n";
1575
	}
1576

    
1577
	if (!$g['booting']) {
1578
		if(services_dhcpd_configure()!=0)
1579
			$return = 1;
1580
	}
1581

    
1582
	return $return;
1583
}
1584

    
1585
function services_unbound_configure() {
1586
	global $config, $g;
1587
	$return = 0;
1588

    
1589
	if(isset($config['system']['developerspew'])) {
1590
		$mt = microtime();
1591
		echo "services_unbound_configure() being called $mt\n";
1592
	}
1593

    
1594
	/* kill any running unbound */
1595
	sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
1596

    
1597
	if (isset($config['unbound']['enable'])) {
1598

    
1599
		if ($g['booting'])
1600
			echo "Starting Unbound DNS...";
1601
		else
1602
			sleep(1);
1603

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

    
1615
		/* generate Unbound config file */
1616
		if(unbound_generate_config()!=0) {
1617
			log_error("Problem generating Unbound configuration.");
1618
			$return = 1;
1619
		}
1620

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

    
1624
		if ($g['booting'])
1625
			echo "done.\n";
1626
	}
1627

    
1628
	return $return;
1629
}
1630

    
1631
function services_snmpd_configure() {
1632
	global $config, $g;
1633
	if(isset($config['system']['developerspew'])) {
1634
		$mt = microtime();
1635
		echo "services_snmpd_configure() being called $mt\n";
1636
	}
1637

    
1638
	/* kill any running snmpd */
1639
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1640
	sleep(2);
1641
	if(is_process_running("bsnmpd"))
1642
		mwexec("/usr/bin/killall bsnmpd", true);
1643

    
1644
	if (isset($config['snmpd']['enable'])) {
1645

    
1646
		if ($g['booting'])
1647
			echo gettext("Starting SNMP daemon... ");
1648

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

    
1656

    
1657
		$snmpdconf = <<<EOD
1658
location := "{$config['snmpd']['syslocation']}"
1659
contact := "{$config['snmpd']['syscontact']}"
1660
read := "{$config['snmpd']['rocommunity']}"
1661

    
1662
EOD;
1663

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

    
1670
EOD;
1671
		}
1672
*/
1673

    
1674

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

    
1682

    
1683
EOD;
1684
		}
1685

    
1686

    
1687
		$snmpdconf .= <<<EOD
1688
system := 1     # pfSense
1689
%snmpd
1690
begemotSnmpdDebugDumpPdus       = 2
1691
begemotSnmpdDebugSyslogPri      = 7
1692
begemotSnmpdCommunityString.0.1 = $(read)
1693

    
1694
EOD;
1695

    
1696
/* No docs on what write strings do there for disable for now.
1697
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1698
		    $snmpdconf .= <<<EOD
1699
begemotSnmpdCommunityString.0.2 = $(write)
1700

    
1701
EOD;
1702
		}
1703
*/
1704

    
1705

    
1706
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1707
		    $snmpdconf .= <<<EOD
1708
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1709
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1710
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1711

    
1712
EOD;
1713
		}
1714

    
1715

    
1716
		$snmpdconf .= <<<EOD
1717
begemotSnmpdCommunityDisable    = 1
1718

    
1719
EOD;
1720

    
1721
		if (isset($config['snmpd']['bindlan'])) {
1722
			$config['snmpd']['bindip'] = 'lan';
1723
			unset($config['snmpd']['bindlan']);
1724
		}
1725
		$bind_to_ip = "0.0.0.0";
1726
		if(isset($config['snmpd']['bindip'])) {
1727
			if (is_ipaddr($config['snmpd']['bindip'])) {
1728
				$bind_to_ip = $config['snmpd']['bindip'];
1729
			} else {
1730
				$if = get_real_interface($config['snmpd']['bindip']);
1731
				if (does_interface_exist($if))
1732
					$bind_to_ip = find_interface_ip($if);
1733
			}
1734
		}
1735

    
1736
		if(is_port( $config['snmpd']['pollport'] )) {
1737
		    $snmpdconf .= <<<EOD
1738
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1739

    
1740
EOD;
1741

    
1742
		}
1743

    
1744
		$snmpdconf .= <<<EOD
1745
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1746
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1747

    
1748
# These are bsnmp macros not php vars.
1749
sysContact      = $(contact)
1750
sysLocation     = $(location)
1751
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1752

    
1753
snmpEnableAuthenTraps = 2
1754

    
1755
EOD;
1756

    
1757
		if (is_array( $config['snmpd']['modules'] )) {
1758
		    if(isset($config['snmpd']['modules']['mibii'])) {
1759
			$snmpdconf .= <<<EOD
1760
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1761

    
1762
EOD;
1763
		    }
1764

    
1765
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1766
			$snmpdconf .= <<<EOD
1767
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1768
%netgraph
1769
begemotNgControlNodeName = "snmpd"
1770

    
1771
EOD;
1772
		    }
1773

    
1774
		    if(isset($config['snmpd']['modules']['pf'])) {
1775
			$snmpdconf .= <<<EOD
1776
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1777

    
1778
EOD;
1779
		    }
1780

    
1781
		    if(isset($config['snmpd']['modules']['hostres'])) {
1782
			$snmpdconf .= <<<EOD
1783
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1784

    
1785
EOD;
1786
		    }
1787
		    if(isset($config['snmpd']['modules']['bridge'])) {
1788
			$snmpdconf .= <<<EOD
1789
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1790
# config must end with blank line
1791

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

    
1798
EOD;
1799
			}
1800
			if(isset($config['snmpd']['modules']['regex'])) {
1801
				$snmpdconf .= <<<EOD
1802
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1803

    
1804
EOD;
1805
			}
1806
		}
1807

    
1808
		fwrite($fd, $snmpdconf);
1809
		fclose($fd);
1810
		unset($snmpdconf);
1811

    
1812
		if (isset($config['snmpd']['bindlan'])) {
1813
			$bindlan = "";
1814
		}
1815

    
1816
		/* run bsnmpd */
1817
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1818
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1819

    
1820
		if ($g['booting'])
1821
			echo gettext("done.") . "\n";
1822
	}
1823

    
1824
	return 0;
1825
}
1826

    
1827
function services_dnsupdate_process($int = "") {
1828
	global $config, $g;
1829
	if(isset($config['system']['developerspew'])) {
1830
		$mt = microtime();
1831
		echo "services_dnsupdate_process() being called $mt\n";
1832
	}
1833

    
1834
	/* Dynamic DNS updating active? */
1835
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1836
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1837
			if (!isset($dnsupdate['enable']))
1838
				continue;
1839
			if (!empty($int) && $int != $dnsupdate['interface'])
1840
				continue;
1841

    
1842
			/* determine interface name */
1843
			$if = get_real_interface($dnsupdate['interface']);
1844
			$wanip = get_interface_ip($dnsupdate['interface']);
1845
			if ($wanip) {
1846

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

    
1852
				$hostname = $dnsupdate['host'];
1853
				/* trailing dot */
1854
				if (substr($hostname, -1) != ".")
1855
					$hostname .= ".";
1856

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

    
1866
EOD;
1867
				fwrite($fd, $privkey);
1868
				fclose($fd);
1869

    
1870
				/* write public key file */
1871
				if ($dnsupdate['keytype'] == "zone") {
1872
					$flags = 257;
1873
					$proto = 3;
1874
				} else if ($dnsupdate['keytype'] == "host") {
1875
					$flags = 513;
1876
					$proto = 3;
1877
				} else if ($dnsupdate['keytype'] == "user") {
1878
					$flags = 0;
1879
					$proto = 2;
1880
				}
1881

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

    
1886
				/* generate update instructions */
1887
				$upinst = "";
1888
				if (!empty($dnsupdate['server']))
1889
					$upinst .= "server {$dnsupdate['server']}\n";
1890
				$upinst .= "update delete {$dnsupdate['host']} A\n";
1891
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
1892
				$upinst .= "\n";	/* mind that trailing newline! */
1893

    
1894
				@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
1895
				unset($upinst);
1896

    
1897
				/* invoke nsupdate */
1898
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
1899
				if (isset($dnsupdate['usetcp']))
1900
					$cmd .= " -v";
1901
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
1902

    
1903
				mwexec_bg($cmd);
1904
				unset($cmd);
1905
			}
1906
		}
1907
	}
1908

    
1909
	return 0;
1910
}
1911

    
1912
/* configure cron service */
1913
function configure_cron() {
1914
	global $g, $config;
1915

    
1916
	conf_mount_rw();
1917
	/* preserve existing crontab entries */
1918
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1919

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

    
1929

    
1930
	if (is_array($config['cron']['item'])) {
1931
		$crontab_contents .= "#\n";
1932
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
1933
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
1934
		$crontab_contents .= "#\n";
1935

    
1936
		foreach ($config['cron']['item'] as $item) {
1937
			$crontab_contents .= "\n{$item['minute']}\t";
1938
			$crontab_contents .= "{$item['hour']}\t";
1939
			$crontab_contents .= "{$item['mday']}\t";
1940
			$crontab_contents .= "{$item['month']}\t";
1941
			$crontab_contents .= "{$item['wday']}\t";
1942
			$crontab_contents .= "{$item['who']}\t";
1943
			$crontab_contents .= "{$item['command']}";
1944
		}
1945

    
1946
		$crontab_contents .= "\n#\n";
1947
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
1948
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
1949
		$crontab_contents .= "#\n\n";
1950
	}
1951

    
1952
	/* please maintain the newline at the end of file */
1953
	file_put_contents("/etc/crontab", $crontab_contents);
1954
	unset($crontab_contents);
1955

    
1956
	/* do a HUP kill to force sync changes */
1957
	exec('/bin/pkill -HUP cron');
1958

    
1959
	conf_mount_ro();
1960
}
1961

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

    
1985
function upnp_start() {
1986
	global $config;
1987

    
1988
	if(!isset($config['installedpackages']['miniupnpd']['config']))
1989
		return;
1990

    
1991
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1992
		echo gettext("Starting UPnP service... ");
1993
		require_once('/usr/local/pkg/miniupnpd.inc');
1994
		sync_package_miniupnpd();
1995
		echo "done.\n";
1996
	}
1997
}
1998

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

    
2002
	$is_installed = false;
2003

    
2004
	if (!is_array($config['cron']))
2005
		$config['cron'] = array();
2006
	if (!is_array($config['cron']['item']))
2007
		$config['cron']['item'] = array();
2008

    
2009
	$x=0;
2010
	foreach($config['cron']['item'] as $item) {
2011
		if(strstr($item['command'], $command)) {
2012
			$is_installed = true;
2013
			break;
2014
		}
2015
		$x++;
2016
	}
2017

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

    
2043
?>
(50-50/68)