Project

General

Profile

Download (61.6 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
	$dhcpdv6cfg = $config['dhcpdv6'];
58
	$Iflist = get_configured_interface_list();
59
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
60
	$carplist = get_configured_carp_interface_list();
61

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

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

    
68
	/* handle manually configured DHCP6 server settings first */
69
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
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 ($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
		$subnetmaskv6 = gen_subnet_mask($ifcfgsnv6);
105

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

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

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

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

    
217
		$ifcfgipv6 = get_interface_ipv6($if);
218
		if(!is_ipaddrv6($ifcfgipv6))
219
			continue;
220

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

    
227
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
228
	
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
				$radvdconf .= "\tAdvLinkMTU 1280;\n";
239
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
240
					$radvdconf .= "\t\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
241
					$radvdconf .= "\t\tAdvOnLink on;\n";
242
					$radvdconf .= "\t\tAdvAutonomous on;\n";
243
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
244
				$radvdconf .= "\t};\n";
245

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

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

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

    
293
function services_dhcpd_configure() {
294
	global $config, $g;
295

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

    
312
	$status = `mount | grep "{$g['dhcpd_chroot_path']}/dev"`;
313
	if(!trim($status))
314
		fwrite($fd, "mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
315
	fclose($fd);
316
	mwexec("/bin/sh {$g['tmp_path']}/dhcpd.sh");
317

    
318
	services_dhcpdv4_configure();
319
	services_dhcpdv6_configure();
320
	services_radvd_configure();
321
	return;
322

    
323
}
324
function services_dhcpdv4_configure() {
325
	global $config, $g;
326

    
327
	if($g['services_dhcp_server_enable'] == false)
328
		return;
329

    
330
	if(isset($config['system']['developerspew'])) {
331
		$mt = microtime();
332
		echo "services_dhcpdv4_configure($if) being called $mt\n";
333
	}
334

    
335
	/* kill any running dhcpd */
336
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
337
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
338
	else
339
		mwexec("/usr/bin/killall dhcpd", true);
340

    
341
	/* DHCP enabled on any interfaces? */
342
	if (!is_dhcp_server_enabled())
343
		return 0;
344

    
345
	/* if OLSRD is enabled, allow WAN to house DHCP. */
346
	if($config['installedpackages']['olsrd'])
347
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
348
				if($olsrd['enable'])
349
					$is_olsr_enabled = true;
350

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

    
366
	$syscfg = $config['system'];
367
	if (!is_array($config['dhcpd']))
368
		$config['dhcpd'] = array();
369
	$dhcpdcfg = $config['dhcpd'];
370
	$Iflist = get_configured_interface_list();
371

    
372
	if ($g['booting'])
373
		echo gettext("Starting DHCP service...");
374
	else
375
		sleep(1);
376

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

    
390
	$dhcpdconf = <<<EOD
391

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

    
404
EOD;
405

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

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

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

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

    
430
		interfaces_staticarp_configure($dhcpif);
431

    
432
		if (!isset($dhcpifconf['enable']))
433
			continue;
434

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

    
481
EOPP;
482
		$dhcpnum++;
483
		}
484
	}
485

    
486
	$dhcpnum = 0;
487

    
488
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
489

    
490
		$ifcfg = $config['interfaces'][$dhcpif];
491

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

    
499
		if (!is_ipaddr($subnet))
500
			continue;
501

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

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

    
512
		$dnscfg = "";
513

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

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

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

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

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

    
558
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
559

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

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

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

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

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

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

    
599
			$pdnscfg = "";
600

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

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

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

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

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

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

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

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

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

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

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

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

    
672
		$dhcpdconf .= <<<EOD
673
$dnscfg
674

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

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

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

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

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

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

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

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

    
726
		$dhcpdconf .= <<<EOD
727
}
728

    
729
EOD;
730

    
731
		/* add static mappings */
732
		if (is_array($dhcpifconf['staticmap'])) {
733

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

    
740
EOD;
741
				if ($sm['ipaddr'])
742
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
743

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

    
752
				if ($sm['rootpath'])
753
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
754

    
755
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
756
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
757

    
758
				$smdnscfg = "";
759

    
760
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
761
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
762
				}
763

    
764
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
765
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
766
				}
767

    
768
				if (isset($sm['ddnsupdate'])) {
769
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
770
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
771
					$pdnscfg .= "		ddns-update-style interim;\n";
772
				}
773

    
774
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
775
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
776
				}
777
				$dhcpdconf .= "{$smdnscfg}";
778

    
779
				// default-lease-time
780
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
781
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
782

    
783
				// max-lease-time
784
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
785
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
786

    
787
				// netbios-name*
788
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
789
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
790
					$dhcpdconf .= "	option netbios-node-type 8;\n";
791
				}
792

    
793
				// ntp-servers
794
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
795
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
796

    
797
				// tftp-server-name
798
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
799
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
800

    
801
				$dhcpdconf .= "}\n";
802
				$i++;
803
			}
804
		}
805

    
806
		$dhcpdifs[] = get_real_interface($dhcpif);
807
	}
808

    
809
	/* write dhcpd.conf */
810
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
811
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
812
		unset($dhcpdconf);
813
		return 1;
814
	}
815
	unset($dhcpdconf);
816

    
817
	/* create an empty leases database */
818
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
819
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
820

    
821
	/* fire up dhcpd in a chroot */
822
	if (count($dhcpdifs) > 0) {
823
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
824
			join(" ", $dhcpdifs));
825
	}
826

    
827
	if ($g['booting'])
828
		print "done.\n";
829

    
830
	return 0;
831
}
832

    
833
function services_dhcpdv6_configure() {
834
	global $config, $g;
835

    
836
	if($g['services_dhcp_server_enable'] == false)
837
		return;
838

    
839
	if(isset($config['system']['developerspew'])) {
840
		$mt = microtime();
841
		echo "services_dhcpd_configure($if) being called $mt\n";
842
	}
843

    
844
	/* kill any running dhcpd */
845
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
846
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
847
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
848
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
849

    
850
	/* DHCP enabled on any interfaces? */
851
	if (!is_dhcpv6_server_enabled())
852
		return 0;
853

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

    
869
	$syscfg = $config['system'];
870
	if (!is_array($config['dhcpdv6']))
871
		$config['dhcpdv6'] = array();
872
	$dhcpdv6cfg = $config['dhcpdv6'];
873
	$Iflist = get_configured_interface_list();
874
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
875

    
876

    
877
	if ($g['booting'])
878
		echo "Starting DHCPv6 service...";
879
	else
880
		sleep(1);
881

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

    
908
				/* set the delegation start to half the current address block */
909
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
910
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
911

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

    
916
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
917
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
918
			}
919
		}
920
	}
921

    
922
	$custoptionsv6 = "";
923
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
924
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
925
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
926
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
927
			}
928
		}
929
	}
930

    
931
	$dhcpdv6conf = <<<EOD
932

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

    
945
EOD;
946

    
947
	if(!isset($dhcpv6ifconf['disableauthoritative']))
948
		$dhcpdv6conf .= "authoritative;\n";
949

    
950
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
951
		$dhcpdv6conf .= "always-broadcast on\n";
952

    
953
	$dhcpdv6ifs = array();
954

    
955
	$dhcpv6num = 0;
956
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
957

    
958
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
959

    
960
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
961
			continue;
962
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
963
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
964
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
965
		$subnetmaskv6 = gen_subnet_mask($ifcfgsnv6);
966

    
967
		if($is_olsr_enabled == true)
968
			if($dhcpv6ifconf['netmask'])
969
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
970

    
971
		$dnscfgv6 = "";
972

    
973
		if ($dhcpv6ifconf['domain']) {
974
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
975
		}
976

    
977
    		if($dhcpv6ifconf['domainsearchlist'] <> "") {
978
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
979
    		}
980

    
981
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
982
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
983
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
984
			}
985
			$dnscfgv6 .= "	ddns-update-style interim;\n";
986
		}
987

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

    
1003
		if(is_ipaddrv6(ifcfgipv6)) {
1004
			$subnet6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1005
			$dhcpdv6conf .= "subnet6 {$subnet6}/{$ifcfgsnv6} {\n";
1006
		} else {
1007
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1008
			$dhcpdv6conf .= "subnet6 {$subnet6}/64 {\n";
1009
		}
1010

    
1011
		if($dhcpv6ifconf['failover_peerip'] <> "")
1012
			$dhcpdv6conf .= "		deny dynamic bootp clients;\n";
1013

    
1014
		if (isset($dhcpv6ifconf['denyunknown']))
1015
		   $dhcpdv6conf .= "		deny unknown-clients;\n";
1016

    
1017
		$dhcpdv6conf .= <<<EOD
1018
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1019
$dnscfgv6
1020

    
1021
EOD;
1022

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

    
1026
		}
1027
    		// default-lease-time
1028
		if ($dhcpv6ifconf['defaultleasetime'])
1029
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1030

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

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

    
1051
		// Handle option, number rowhelper values
1052
		$dhcpdv6conf .= "\n";
1053
		if($dhcpv6ifconf['numberoptions']['item']) {
1054
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1055
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1056
			}
1057
		}
1058

    
1059
		// ldap-server
1060
		if ($dhcpv6ifconf['ldap'] <> "")
1061
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1062

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

    
1076
		$dhcpdv6conf .= <<<EOD
1077
}
1078

    
1079
EOD;
1080

    
1081
		/* add static mappings */
1082
		/* Needs to use DUID */
1083
		if (is_array($dhcpv6ifconf['staticmap'])) {
1084

    
1085
			$i = 0;
1086
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1087
				$dhcpdv6conf .= <<<EOD
1088
host s_{$dhcpv6if}_{$i} {
1089
	host-identifier option dhcp6.client-id {$sm['duid']};
1090

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

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

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

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

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

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

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

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

    
1152
	return 0;
1153
}
1154

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

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

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

    
1164
        $iflist = get_configured_interface_list();
1165

    
1166
        $igmpconf = <<<EOD
1167

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

    
1173
EOD;
1174

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

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

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

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

    
1209
        return 0;
1210
}
1211

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

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

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

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

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

    
1235
	$iflist = get_configured_interface_list();
1236

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

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

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

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

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

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

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

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

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

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

    
1324
	return 0;
1325
}
1326

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

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

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

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

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

    
1350
	$iflist = get_configured_interface_list();
1351

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

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

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

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

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

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

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

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

    
1444
	return 0;
1445
}
1446

    
1447
function services_dyndns_configure_client($conf) {
1448

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

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

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

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

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

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

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

    
1498
	return 0;
1499
}
1500

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

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

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

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

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

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

    
1525
		$args = "";
1526

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

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

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

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

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

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

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

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

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

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

    
1576
	return $return;
1577
}
1578

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

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

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

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

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

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

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

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

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

    
1622
	return $return;
1623
}
1624

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

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

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

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

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

    
1650

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

    
1656
EOD;
1657

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

    
1664
EOD;
1665
		}
1666
*/
1667

    
1668

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

    
1676

    
1677
EOD;
1678
		}
1679

    
1680

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

    
1688
EOD;
1689

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

    
1695
EOD;
1696
		}
1697
*/
1698

    
1699

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

    
1706
EOD;
1707
		}
1708

    
1709

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

    
1713
EOD;
1714

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

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

    
1734
EOD;
1735

    
1736
		}
1737

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

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

    
1747
snmpEnableAuthenTraps = 2
1748

    
1749
EOD;
1750

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

    
1756
EOD;
1757
		    }
1758

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

    
1765
EOD;
1766
		    }
1767

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

    
1772
EOD;
1773
		    }
1774

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

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

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

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

    
1798
EOD;
1799
			}
1800
		}
1801

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

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

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

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

    
1818
	return 0;
1819
}
1820

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1903
	return 0;
1904
}
1905

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

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

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

    
1923

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

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

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

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

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

    
1953
	conf_mount_ro();
1954
}
1955

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

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

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

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

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

    
1996
	$is_installed = false;
1997

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

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

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

    
2037
?>
(49-49/67)