Project

General

Profile

Download (61.8 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
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcleases6
39
	pfSense_MODULE:	utils
40
*/
41

    
42
define('DYNDNS_PROVIDER_VALUES', 'dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net he-net-tunnelbroker selfhost route53 custom');
43
define('DYNDNS_PROVIDER_DESCRIPTIONS', 'DNS-O-Matic,DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS,DNSexit,OpenDNS,Namecheap,HE.net,HE.net Tunnelbroker,SelfHost,Route 53,Custom');
44

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

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

    
57
	if (!is_array($config['dhcpdv6']))
58
		$config['dhcpdv6'] = array();
59

    
60
	$Iflist = get_configured_interface_list();
61
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
62
	$carplist = get_configured_carp_interface_list();
63

    
64
	$radvdconf = "# Automatically Generated, do not edit\n";
65

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

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

    
76
		if (!isset($dhcpv6ifconf['ramode']))
77
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
78

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

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

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

    
96
		$realif = get_real_interface($dhcpv6if);
97
		if (in_array($realif, $radvdifs))
98
			continue;
99
		$radvdifs[] = $realif;
100

    
101
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
102
		if (!is_ipaddrv6($ifcfgipv6))
103
			continue;
104

    
105
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
106
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
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
		$mtu = get_interface_mtu($realif);
114
		if (is_numeric($mtu))
115
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
116
		else
117
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
118
		// $radvdconf .= "\tDeprecatePrefix on;\n";
119
		switch($dhcpv6ifconf['rapriority']) {
120
			case "low":
121
				$radvdconf .= "\tAdvDefaultPreference low;\n";
122
				break;
123
			case "high":
124
				$radvdconf .= "\tAdvDefaultPreference high;\n";
125
				break;
126
			default:
127
				$radvdconf .= "\tAdvDefaultPreference medium;\n";
128
				break;
129
		}
130
		switch($dhcpv6ifconf['ramode']) {
131
			case "managed":
132
				$radvdconf .= "\tAdvManagedFlag on;\n";
133
				break;
134
			case "assist":
135
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
136
				break;
137
		}
138
		$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
139
		if($carpif == true) {
140
			$radvdconf .= "\t\tDeprecatePrefix off;\n";
141
		} else {
142
			$radvdconf .= "\t\tDeprecatePrefix on;\n";
143
		}
144
		switch($dhcpv6ifconf['ramode']) {
145
			case "managed":
146
				$radvdconf .= "\t\tAdvOnLink on;\n";
147
				$radvdconf .= "\t\tAdvAutonomous off;\n";
148
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
149
				break;
150
			case "router":
151
				$radvdconf .= "\t\tAdvOnLink off;\n";
152
				$radvdconf .= "\t\tAdvAutonomous off;\n";
153
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
154
				break;
155
			case "assist":
156
				$radvdconf .= "\t\tAdvOnLink on;\n";
157
				$radvdconf .= "\t\tAdvAutonomous on;\n";
158
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
159
				break;
160
			case "unmanaged":
161
				$radvdconf .= "\t\tAdvOnLink on;\n";
162
				$radvdconf .= "\t\tAdvAutonomous on;\n";
163
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
164
				break;				
165
		}
166
		$radvdconf .= "\t};\n";
167

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
333
function services_dhcpdv4_configure() {
334
	global $config, $g;
335

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

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

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

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

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

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

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

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

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

    
399
	$dhcpdconf = <<<EOD
400

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

    
413
EOD;
414

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

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

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

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

    
439
		interfaces_staticarp_configure($dhcpif);
440

    
441
		if (!isset($dhcpifconf['enable']))
442
			continue;
443

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

    
490
EOPP;
491
		$dhcpnum++;
492
		}
493
	}
494

    
495
	$dhcpnum = 0;
496

    
497
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
498

    
499
		$ifcfg = $config['interfaces'][$dhcpif];
500

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

    
508
		if (!is_ipaddr($subnet))
509
			continue;
510

    
511
		if($is_olsr_enabled == true)
512
			if($dhcpifconf['netmask'])
513
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
514

    
515
		$all_pools = array();
516
		$all_pools[] = $dhcpifconf;
517
		if (is_array($dhcpifconf['pool'])) {
518
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
519
		}
520

    
521
		$dnscfg = "";
522

    
523
		if ($dhcpifconf['domain']) {
524
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
525
		}
526

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

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

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

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

    
567
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
568

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

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

    
594
			if($poolconf['failover_peerip'] <> "")
595
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
596

    
597
			if (isset($poolconf['denyunknown']))
598
			   $dhcpdconf .= "		deny unknown-clients;\n";
599

    
600
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
601
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
602

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

    
608
			$pdnscfg = "";
609

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

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

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

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

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

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

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

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

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

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

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

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

    
681
		$dhcpdconf .= <<<EOD
682
$dnscfg
683

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

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

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

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

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

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

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

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

    
735
		$dhcpdconf .= <<<EOD
736
}
737

    
738
EOD;
739

    
740
		/* add static mappings */
741
		if (is_array($dhcpifconf['staticmap'])) {
742

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

    
749
EOD;
750
				if ($sm['ipaddr'])
751
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
752

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

    
761
				if ($sm['rootpath'])
762
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
763

    
764
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
765
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
766

    
767
				$smdnscfg = "";
768

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

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

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

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

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

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

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

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

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

    
810
				$dhcpdconf .= "}\n";
811
				$i++;
812
			}
813
		}
814

    
815
		$dhcpdifs[] = get_real_interface($dhcpif);
816
	}
817

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

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

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

    
836
	if ($g['booting'])
837
		print "done.\n";
838

    
839
	return 0;
840
}
841

    
842
function services_dhcpdv6_configure() {
843
	global $config, $g;
844

    
845
	if($g['services_dhcp_server_enable'] == false)
846
		return;
847

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

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

    
859
	/* DHCP enabled on any interfaces? */
860
	if (!is_dhcpv6_server_enabled())
861
		return 0;
862

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

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

    
885

    
886
	if ($g['booting'])
887
		echo "Starting DHCPv6 service...";
888
	else
889
		sleep(1);
890

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

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

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

    
925
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
926
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
927
			}
928
		}
929
	}
930

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

    
940
	$dhcpdv6conf = <<<EOD
941

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

    
954
EOD;
955

    
956
	if(!isset($dhcpv6ifconf['disableauthoritative']))
957
		$dhcpdv6conf .= "authoritative;\n";
958

    
959
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
960
		$dhcpdv6conf .= "always-broadcast on\n";
961

    
962
	$dhcpdv6ifs = array();
963

    
964
	$dhcpv6num = 0;
965
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
966

    
967
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
968

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

    
975
		if($is_olsr_enabled == true)
976
			if($dhcpv6ifconf['netmask'])
977
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
978

    
979
		$dnscfgv6 = "";
980

    
981
		if ($dhcpv6ifconf['domain']) {
982
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
983
		}
984

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

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

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

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

    
1019
		if($dhcpv6ifconf['failover_peerip'] <> "")
1020
			$dhcpdv6conf .= "		deny dynamic bootp clients;\n";
1021

    
1022
		if (isset($dhcpv6ifconf['denyunknown']))
1023
		   $dhcpdv6conf .= "		deny unknown-clients;\n";
1024

    
1025
		$dhcpdv6conf .= <<<EOD
1026
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1027
$dnscfgv6
1028

    
1029
EOD;
1030

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

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

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

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

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

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

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

    
1084
		$dhcpdv6conf .= "}\n";
1085

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

    
1095
EOD;
1096
				if ($sm['ipaddrv6'])
1097
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1098

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

    
1107
				if ($sm['rootpath'])
1108
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1109

    
1110
				$dhcpdv6conf .= "}\n";
1111
				$i++;
1112
			}
1113
		}
1114

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

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

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

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

    
1156
	return 0;
1157
}
1158

    
1159
function services_igmpproxy_configure() {
1160
        global $config, $g;
1161

    
1162
        /* kill any running igmpproxy */
1163
        killbyname("igmpproxy");
1164

    
1165
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1166
		return 1;
1167

    
1168
        $iflist = get_configured_interface_list();
1169

    
1170
        $igmpconf = <<<EOD
1171

    
1172
##------------------------------------------------------
1173
## Enable Quickleave mode (Sends Leave instantly)
1174
##------------------------------------------------------
1175
quickleave
1176

    
1177
EOD;
1178

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

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

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

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

    
1213
        return 0;
1214
}
1215

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

    
1225
	/* kill any running dhcrelay */
1226
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1227

    
1228
	$dhcrelaycfg =& $config['dhcrelay'];
1229

    
1230
	/* DHCPRelay enabled on any interfaces? */
1231
	if (!isset($dhcrelaycfg['enable']))
1232
		return 0;
1233

    
1234
	if ($g['booting'])
1235
		echo gettext("Starting DHCP relay service...");
1236
	else
1237
		sleep(1);
1238

    
1239
	$iflist = get_configured_interface_list();
1240

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

    
1247
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1248
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1249
	}
1250

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

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

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

    
1308
		if (!empty($destif))
1309
			$dhcrelayifs[] = $destif;
1310
	}
1311
	$dhcrelayifs = array_unique($dhcrelayifs);
1312

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

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

    
1321
	if (isset($dhcrelaycfg['agentoption']))
1322
		$cmd .=  " -a -m replace";
1323

    
1324
	$cmd .= " " . implode(" ", $srvips);
1325
	mwexec($cmd);
1326
	unset($cmd);
1327

    
1328
	return 0;
1329
}
1330

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

    
1340
	/* kill any running dhcrelay */
1341
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1342

    
1343
	$dhcrelaycfg =& $config['dhcrelay6'];
1344

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

    
1349
	if ($g['booting'])
1350
		echo gettext("Starting DHCPv6 relay service...");
1351
	else
1352
		sleep(1);
1353

    
1354
	$iflist = get_configured_interface_list();
1355

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

    
1362
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1363
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1364
	}
1365
	$dhcrelayifs = array_unique($dhcrelayifs);
1366

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

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

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

    
1427
		if (!empty($destif)) {
1428
			$srvifaces[] = "{$srvip}%{$destif}";
1429
		}
1430
	}
1431

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

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

    
1448
	return 0;
1449
}
1450

    
1451
function services_dyndns_configure_client($conf) {
1452

    
1453
	if (!isset($conf['enable']))
1454
		return;
1455

    
1456
	/* load up the dyndns.class */
1457
	require_once("dyndns.class");
1458

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

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

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

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

    
1498
		if ($g['booting'])
1499
			echo gettext("done.") . "\n";
1500
	}
1501

    
1502
	return 0;
1503
}
1504

    
1505
function dyndnsCheckIP($int) {
1506
	$ip_address = get_interface_ip($int);
1507
	if (is_private_ip($ip_address)) {
1508
		$hosttocheck = "checkip.dyndns.org";
1509
		$checkip = gethostbyname($hosttocheck);
1510
		$ip_ch = curl_init("http://{$checkip}");
1511
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1512
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1513
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1514
		$ip_result_page = curl_exec($ip_ch);
1515
		curl_close($ip_ch);
1516
		$ip_result_decoded = urldecode($ip_result_page);
1517
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1518
		$ip_address = trim($matches[1]);
1519
	}
1520
	return $ip_address;
1521
}
1522

    
1523
function services_dnsmasq_configure() {
1524
	global $config, $g;
1525
	$return = 0;
1526

    
1527
	if(isset($config['system']['developerspew'])) {
1528
		$mt = microtime();
1529
		echo "services_dnsmasq_configure() being called $mt\n";
1530
	}
1531

    
1532
	/* kill any running dnsmasq */
1533
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1534
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1535

    
1536
	if (isset($config['dnsmasq']['enable'])) {
1537

    
1538
		if ($g['booting'])
1539
			echo gettext("Starting DNS forwarder...");
1540
		else
1541
			sleep(1);
1542

    
1543
		/* generate hosts file */
1544
		if(system_hosts_generate()!=0)
1545
			$return = 1;
1546

    
1547
		$args = "";
1548

    
1549
		if (isset($config['dnsmasq']['regdhcp'])) {
1550
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1551
		}
1552

    
1553
		/* Setup forwarded domains */
1554
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1555
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1556
			        $args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1557
			}
1558
		}
1559

    
1560
		/* Allow DNS Rebind for forwarded domains */
1561
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1562
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1563
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1564
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1565
				}
1566
			}
1567
		}
1568

    
1569
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1570
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1571

    
1572
		if (isset($config['dnsmasq']['strict_order'])) {
1573
			$args .= " --strict-order ";
1574
		}
1575

    
1576
		if (isset($config['dnsmasq']['domain_needed'])) {
1577
			$args .= " --domain-needed ";
1578
		}
1579

    
1580
		if ($config['dnsmasq']['custom_options']) {
1581
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1582
				$args .= " --$c";
1583
		}
1584

    
1585
		/* run dnsmasq */
1586
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1587
		unset($args);
1588

    
1589
		if ($g['booting'])
1590
			echo gettext("done.") . "\n";
1591
	}
1592

    
1593
	if (!$g['booting']) {
1594
		if(services_dhcpd_configure()!=0)
1595
			$return = 1;
1596
	}
1597

    
1598
	return $return;
1599
}
1600

    
1601
function services_snmpd_configure() {
1602
	global $config, $g;
1603
	if(isset($config['system']['developerspew'])) {
1604
		$mt = microtime();
1605
		echo "services_snmpd_configure() being called $mt\n";
1606
	}
1607

    
1608
	/* kill any running snmpd */
1609
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1610
	sleep(2);
1611
	if(is_process_running("bsnmpd"))
1612
		mwexec("/usr/bin/killall bsnmpd", true);
1613

    
1614
	if (isset($config['snmpd']['enable'])) {
1615

    
1616
		if ($g['booting'])
1617
			echo gettext("Starting SNMP daemon... ");
1618

    
1619
		/* generate snmpd.conf */
1620
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1621
		if (!$fd) {
1622
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1623
			return 1;
1624
		}
1625

    
1626

    
1627
		$snmpdconf = <<<EOD
1628
location := "{$config['snmpd']['syslocation']}"
1629
contact := "{$config['snmpd']['syscontact']}"
1630
read := "{$config['snmpd']['rocommunity']}"
1631

    
1632
EOD;
1633

    
1634
/* No docs on what write strings do there for disable for now.
1635
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1636
		    $snmpdconf .= <<<EOD
1637
# write string
1638
write := "{$config['snmpd']['rwcommunity']}"
1639

    
1640
EOD;
1641
		}
1642
*/
1643

    
1644

    
1645
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1646
		    $snmpdconf .= <<<EOD
1647
# SNMP Trap support.
1648
traphost := {$config['snmpd']['trapserver']}
1649
trapport := {$config['snmpd']['trapserverport']}
1650
trap := "{$config['snmpd']['trapstring']}"
1651

    
1652

    
1653
EOD;
1654
		}
1655

    
1656

    
1657
		$snmpdconf .= <<<EOD
1658
system := 1     # pfSense
1659
%snmpd
1660
begemotSnmpdDebugDumpPdus       = 2
1661
begemotSnmpdDebugSyslogPri      = 7
1662
begemotSnmpdCommunityString.0.1 = $(read)
1663

    
1664
EOD;
1665

    
1666
/* No docs on what write strings do there for disable for now.
1667
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1668
		    $snmpdconf .= <<<EOD
1669
begemotSnmpdCommunityString.0.2 = $(write)
1670

    
1671
EOD;
1672
		}
1673
*/
1674

    
1675

    
1676
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1677
		    $snmpdconf .= <<<EOD
1678
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1679
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1680
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1681

    
1682
EOD;
1683
		}
1684

    
1685

    
1686
		$snmpdconf .= <<<EOD
1687
begemotSnmpdCommunityDisable    = 1
1688

    
1689
EOD;
1690

    
1691
		if (isset($config['snmpd']['bindlan'])) {
1692
			$config['snmpd']['bindip'] = 'lan';
1693
			unset($config['snmpd']['bindlan']);
1694
		}
1695
		$bind_to_ip = "0.0.0.0";
1696
		if(isset($config['snmpd']['bindip'])) {
1697
			if (is_ipaddr($config['snmpd']['bindip'])) {
1698
				$bind_to_ip = $config['snmpd']['bindip'];
1699
			} else {
1700
				$if = get_real_interface($config['snmpd']['bindip']);
1701
				if (does_interface_exist($if))
1702
					$bind_to_ip = find_interface_ip($if);
1703
			}
1704
		}
1705

    
1706
		if(is_port( $config['snmpd']['pollport'] )) {
1707
		    $snmpdconf .= <<<EOD
1708
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1709

    
1710
EOD;
1711

    
1712
		}
1713

    
1714
		$snmpdconf .= <<<EOD
1715
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1716
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1717

    
1718
# These are bsnmp macros not php vars.
1719
sysContact      = $(contact)
1720
sysLocation     = $(location)
1721
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1722

    
1723
snmpEnableAuthenTraps = 2
1724

    
1725
EOD;
1726

    
1727
		if (is_array( $config['snmpd']['modules'] )) {
1728
		    if(isset($config['snmpd']['modules']['mibii'])) {
1729
			$snmpdconf .= <<<EOD
1730
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1731

    
1732
EOD;
1733
		    }
1734

    
1735
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1736
			$snmpdconf .= <<<EOD
1737
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1738
%netgraph
1739
begemotNgControlNodeName = "snmpd"
1740

    
1741
EOD;
1742
		    }
1743

    
1744
		    if(isset($config['snmpd']['modules']['pf'])) {
1745
			$snmpdconf .= <<<EOD
1746
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1747

    
1748
EOD;
1749
		    }
1750

    
1751
		    if(isset($config['snmpd']['modules']['hostres'])) {
1752
			$snmpdconf .= <<<EOD
1753
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1754

    
1755
EOD;
1756
		    }
1757
		    if(isset($config['snmpd']['modules']['bridge'])) {
1758
			$snmpdconf .= <<<EOD
1759
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1760
# config must end with blank line
1761

    
1762
EOD;
1763
		    }
1764
			if(isset($config['snmpd']['modules']['ucd'])) {
1765
				$snmpdconf .= <<<EOD
1766
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1767

    
1768
EOD;
1769
			}
1770
			if(isset($config['snmpd']['modules']['regex'])) {
1771
				$snmpdconf .= <<<EOD
1772
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1773

    
1774
EOD;
1775
			}
1776
		}
1777

    
1778
		fwrite($fd, $snmpdconf);
1779
		fclose($fd);
1780
		unset($snmpdconf);
1781

    
1782
		if (isset($config['snmpd']['bindlan'])) {
1783
			$bindlan = "";
1784
		}
1785

    
1786
		/* run bsnmpd */
1787
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1788
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1789

    
1790
		if ($g['booting'])
1791
			echo gettext("done.") . "\n";
1792
	}
1793

    
1794
	return 0;
1795
}
1796

    
1797
function services_dnsupdate_process($int = "") {
1798
	global $config, $g;
1799
	if(isset($config['system']['developerspew'])) {
1800
		$mt = microtime();
1801
		echo "services_dnsupdate_process() being called $mt\n";
1802
	}
1803

    
1804
	/* Dynamic DNS updating active? */
1805
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1806
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1807
			if (!isset($dnsupdate['enable']))
1808
				continue;
1809
			if (!empty($int) && $int != $dnsupdate['interface'])
1810
				continue;
1811

    
1812
			/* determine interface name */
1813
			$if = get_real_interface($dnsupdate['interface']);
1814
			$wanip = get_interface_ip($dnsupdate['interface']);
1815
			if ($wanip) {
1816

    
1817
				$keyname = $dnsupdate['keyname'];
1818
				/* trailing dot */
1819
				if (substr($keyname, -1) != ".")
1820
					$keyname .= ".";
1821

    
1822
				$hostname = $dnsupdate['host'];
1823
				/* trailing dot */
1824
				if (substr($hostname, -1) != ".")
1825
					$hostname .= ".";
1826

    
1827
				/* write private key file
1828
				   this is dumb - public and private keys are the same for HMAC-MD5,
1829
				   but nsupdate insists on having both */
1830
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
1831
				$privkey = <<<EOD
1832
Private-key-format: v1.2
1833
Algorithm: 157 (HMAC)
1834
Key: {$dnsupdate['keydata']}
1835

    
1836
EOD;
1837
				fwrite($fd, $privkey);
1838
				fclose($fd);
1839

    
1840
				/* write public key file */
1841
				if ($dnsupdate['keytype'] == "zone") {
1842
					$flags = 257;
1843
					$proto = 3;
1844
				} else if ($dnsupdate['keytype'] == "host") {
1845
					$flags = 513;
1846
					$proto = 3;
1847
				} else if ($dnsupdate['keytype'] == "user") {
1848
					$flags = 0;
1849
					$proto = 2;
1850
				}
1851

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

    
1856
				/* generate update instructions */
1857
				$upinst = "";
1858
				if (!empty($dnsupdate['server']))
1859
					$upinst .= "server {$dnsupdate['server']}\n";
1860
				$upinst .= "update delete {$dnsupdate['host']} A\n";
1861
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
1862
				$upinst .= "\n";	/* mind that trailing newline! */
1863

    
1864
				@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
1865
				unset($upinst);
1866

    
1867
				/* invoke nsupdate */
1868
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
1869
				if (isset($dnsupdate['usetcp']))
1870
					$cmd .= " -v";
1871
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
1872

    
1873
				mwexec_bg($cmd);
1874
				unset($cmd);
1875
			}
1876
		}
1877
	}
1878

    
1879
	return 0;
1880
}
1881

    
1882
/* configure cron service */
1883
function configure_cron() {
1884
	global $g, $config;
1885

    
1886
	conf_mount_rw();
1887
	/* preserve existing crontab entries */
1888
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1889

    
1890
	for ($i = 0; $i < count($crontab_contents); $i++) {
1891
		$cron_item =& $crontab_contents[$i];
1892
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
1893
			array_splice($crontab_contents, $i - 1);
1894
			break;
1895
		}
1896
	}
1897
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
1898

    
1899

    
1900
	if (is_array($config['cron']['item'])) {
1901
		$crontab_contents .= "#\n";
1902
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
1903
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
1904
		$crontab_contents .= "#\n";
1905

    
1906
		foreach ($config['cron']['item'] as $item) {
1907
			$crontab_contents .= "\n{$item['minute']}\t";
1908
			$crontab_contents .= "{$item['hour']}\t";
1909
			$crontab_contents .= "{$item['mday']}\t";
1910
			$crontab_contents .= "{$item['month']}\t";
1911
			$crontab_contents .= "{$item['wday']}\t";
1912
			$crontab_contents .= "{$item['who']}\t";
1913
			$crontab_contents .= "{$item['command']}";
1914
		}
1915

    
1916
		$crontab_contents .= "\n#\n";
1917
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
1918
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
1919
		$crontab_contents .= "#\n\n";
1920
	}
1921

    
1922
	/* please maintain the newline at the end of file */
1923
	file_put_contents("/etc/crontab", $crontab_contents);
1924
	unset($crontab_contents);
1925

    
1926
	/* do a HUP kill to force sync changes */
1927
	exec('/bin/pkill -HUP cron');
1928

    
1929
	conf_mount_ro();
1930
}
1931

    
1932
function upnp_action ($action) {
1933
	global $g, $config;
1934
	switch($action) {
1935
		case "start":
1936
			if (file_exists('/var/etc/miniupnpd.conf')) {
1937
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
1938
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
1939
			}
1940
			break;
1941
		case "stop":
1942
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
1943
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
1944
				mwexec('killall miniupnpd 2>/dev/null', true);
1945
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
1946
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
1947
			break;
1948
		case "restart":
1949
			upnp_action('stop');
1950
			upnp_action('start');
1951
			break;
1952
	}
1953
}
1954

    
1955
function upnp_start() {
1956
	global $config;
1957

    
1958
	if(!isset($config['installedpackages']['miniupnpd']['config']))
1959
		return;
1960

    
1961
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1962
		echo gettext("Starting UPnP service... ");
1963
		require_once('/usr/local/pkg/miniupnpd.inc');
1964
		sync_package_miniupnpd();
1965
		echo "done.\n";
1966
	}
1967
}
1968

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

    
1972
	$is_installed = false;
1973

    
1974
	if (!is_array($config['cron']))
1975
		$config['cron'] = array();
1976
	if (!is_array($config['cron']['item']))
1977
		$config['cron']['item'] = array();
1978

    
1979
	$x=0;
1980
	foreach($config['cron']['item'] as $item) {
1981
		if(strstr($item['command'], $command)) {
1982
			$is_installed = true;
1983
			break;
1984
		}
1985
		$x++;
1986
	}
1987

    
1988
	if($active) {
1989
		$cron_item = array();
1990
		$cron_item['minute'] = $minute;
1991
		$cron_item['hour'] = $hour;
1992
		$cron_item['mday'] = $monthday;
1993
		$cron_item['month'] = $month;
1994
		$cron_item['wday'] = $weekday;
1995
		$cron_item['who'] = $who;
1996
		$cron_item['command'] = $command;
1997
		if(!$is_installed) {
1998
			$config['cron']['item'][] = $cron_item;
1999
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2000
		} else {
2001
			$config['cron']['item'][$x] = $cron_item;
2002
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2003
		}
2004
	} else {
2005
		if(($is_installed == true) && ($x > 0)) {
2006
			unset($config['cron']['item'][$x]);
2007
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2008
		}
2009
	}
2010
	configure_cron();
2011
}
2012

    
2013
?>
(49-49/66)