Project

General

Profile

Download (63.2 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 noip-free 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,No-IP (free),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
		/* restore the leases, if we have them */
362
		if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
363
			$dhcprestore = "";
364
			$dhcpreturn = "";
365
			exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
366
			$dhcprestore = implode(" ", $dhcprestore);
367
			if($dhcpreturn <> 0) {
368
				log_error(sprintf(gettext('DHCP leases restore failed exited with %1$s, the error is: %2$s%3$s'), $dhcpreturn, $dhcprestore, "\n"));
369
			}
370
		}
371
		/* If this backup is still there on a full install, but we aren't going to use ram disks, remove the archive since this is a transition. */
372
		if (($g['platform'] == "pfSense") && !isset($config['system']['use_mfs_tmpvar'])) {
373
			unlink_if_exists("{$g['cf_conf_path']}/dhcpleases.tgz");
374
		}
375
	}
376

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

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

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

    
401
	$dhcpdconf = <<<EOD
402

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

    
415
EOD;
416

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

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

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

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

    
441
		interfaces_staticarp_configure($dhcpif);
442

    
443
		if (!isset($dhcpifconf['enable']))
444
			continue;
445

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

    
492
EOPP;
493
		$dhcpnum++;
494
		}
495
	}
496

    
497
	$dhcpnum = 0;
498

    
499
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
500

    
501
		$ifcfg = $config['interfaces'][$dhcpif];
502

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

    
510
		if (!is_ipaddr($subnet))
511
			continue;
512

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

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

    
523
		$dnscfg = "";
524

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

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

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

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

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

    
569
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
570

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

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

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

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

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

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

    
610
			$pdnscfg = "";
611

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

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

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

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

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

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

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

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

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

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

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

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

    
683
		$dhcpdconf .= <<<EOD
684
$dnscfg
685

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

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

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

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

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

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

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

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

    
737
		$dhcpdconf .= <<<EOD
738
}
739

    
740
EOD;
741

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

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

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

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

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

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

    
769
				$smdnscfg = "";
770

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

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

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

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

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

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

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

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

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

    
812
				$dhcpdconf .= "}\n";
813
				$i++;
814
			}
815
		}
816

    
817
		$dhcpdifs[] = get_real_interface($dhcpif);
818
	}
819

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

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

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

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

    
841
	return 0;
842
}
843

    
844
function services_dhcpdv6_configure() {
845
	global $config, $g;
846

    
847
	if($g['services_dhcp_server_enable'] == false)
848
		return;
849

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

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

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

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

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

    
887

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

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

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

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

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

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

    
942
	$dhcpdv6conf = <<<EOD
943

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

    
956
EOD;
957

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

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

    
964
	$dhcpdv6ifs = array();
965

    
966
	$dhcpv6num = 0;
967
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
968

    
969
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
970

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

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

    
981
		$dnscfgv6 = "";
982

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

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

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

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

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

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

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

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

    
1031
EOD;
1032

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

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

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

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

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

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

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

    
1086
		$dhcpdv6conf .= "}\n";
1087

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

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

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

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

    
1112
				$dhcpdv6conf .= "}\n";
1113
				$i++;
1114
			}
1115
		}
1116

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

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

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

    
1149
	/* fire up dhcpd in a chroot */
1150
	if (count($dhcpdv6ifs) > 0) {
1151
		mwexec("/usr/local/sbin/dhcpd -6 -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpdv6.conf -pf {$g['varrun_path']}/dhcpdv6.pid " .
1152
			join(" ", $dhcpdv6ifs));
1153
		mwexec("/usr/local/sbin/dhcpleases6 -c \"/usr/local/bin/php -f /usr/local/sbin/prefixes.php|/bin/sh\" -l {$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1154
	}
1155
	if ($g['booting'])
1156
		print gettext("done.") . "\n";
1157

    
1158
	return 0;
1159
}
1160

    
1161
function services_igmpproxy_configure() {
1162
        global $config, $g;
1163

    
1164
        /* kill any running igmpproxy */
1165
        killbyname("igmpproxy");
1166

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

    
1170
        $iflist = get_configured_interface_list();
1171

    
1172
        $igmpconf = <<<EOD
1173

    
1174
##------------------------------------------------------
1175
## Enable Quickleave mode (Sends Leave instantly)
1176
##------------------------------------------------------
1177
quickleave
1178

    
1179
EOD;
1180

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

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

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

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

    
1215
        return 0;
1216
}
1217

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

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

    
1230
	$dhcrelaycfg =& $config['dhcrelay'];
1231

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

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

    
1241
	$iflist = get_configured_interface_list();
1242

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

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

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

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

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

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

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

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

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

    
1326
	$cmd .= " " . implode(" ", $srvips);
1327
	mwexec($cmd);
1328
	unset($cmd);
1329

    
1330
	return 0;
1331
}
1332

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

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

    
1345
	$dhcrelaycfg =& $config['dhcrelay6'];
1346

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

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

    
1356
	$iflist = get_configured_interface_list();
1357

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

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

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

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

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

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

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

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

    
1450
	return 0;
1451
}
1452

    
1453
function services_dyndns_configure_client($conf) {
1454

    
1455
	if (!isset($conf['enable']))
1456
		return;
1457

    
1458
	/* load up the dyndns.class */
1459
	require_once("dyndns.class");
1460

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

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

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

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

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

    
1504
	return 0;
1505
}
1506

    
1507
function dyndnsCheckIP($int) {
1508
	global $config;
1509
	$ip_address = get_interface_ip($int);
1510
	if (is_private_ip($ip_address)) {
1511
		$gateways_status = return_gateways_status(true);
1512
		// If the gateway for this interface is down, then the external check cannot work.
1513
		// Avoid the long wait for the external check to timeout.
1514
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1515
			return "down";
1516
		$hosttocheck = "checkip.dyndns.org";
1517
		$checkip = gethostbyname($hosttocheck);
1518
		$ip_ch = curl_init("http://{$checkip}");
1519
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1520
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1521
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1522
		$ip_result_page = curl_exec($ip_ch);
1523
		curl_close($ip_ch);
1524
		$ip_result_decoded = urldecode($ip_result_page);
1525
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1526
		$ip_address = trim($matches[1]);
1527
	}
1528
	return $ip_address;
1529
}
1530

    
1531
function services_dnsmasq_configure() {
1532
	global $config, $g;
1533
	$return = 0;
1534

    
1535
	if(isset($config['system']['developerspew'])) {
1536
		$mt = microtime();
1537
		echo "services_dnsmasq_configure() being called $mt\n";
1538
	}
1539

    
1540
	/* kill any running dnsmasq */
1541
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1542
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1543

    
1544
	if (isset($config['dnsmasq']['enable'])) {
1545

    
1546
		if ($g['booting'])
1547
			echo gettext("Starting DNS forwarder...");
1548
		else
1549
			sleep(1);
1550

    
1551
		/* generate hosts file */
1552
		if(system_hosts_generate()!=0)
1553
			$return = 1;
1554

    
1555
		$args = "";
1556

    
1557
		if (isset($config['dnsmasq']['regdhcp'])) {
1558
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1559
		}
1560

    
1561
		/* Setup forwarded domains */
1562
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1563
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1564
				if ($override['ip'] == "!")
1565
					$override[ip] = "";
1566
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1567
			}
1568
		}
1569

    
1570
		/* If selected, then forward reverse lookups for private IPv4 addresses to nowhere. */
1571
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1572
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1573
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1574
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1575
			$args .= " --server=/10.in-addr.arpa/ ";
1576
			$args .= " --server=/168.192.in-addr.arpa/ ";
1577
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1578
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1579
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1580
			}
1581
		}
1582

    
1583
		/* Allow DNS Rebind for forwarded domains */
1584
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1585
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1586
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1587
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1588
				}
1589
			}
1590
		}
1591

    
1592
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1593
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1594

    
1595
		if (isset($config['dnsmasq']['strict_order'])) {
1596
			$args .= " --strict-order ";
1597
		}
1598

    
1599
		if (isset($config['dnsmasq']['domain_needed'])) {
1600
			$args .= " --domain-needed ";
1601
		}
1602

    
1603
		if ($config['dnsmasq']['custom_options']) {
1604
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1605
				$args .= " --$c";
1606
		}
1607

    
1608
		/* run dnsmasq */
1609
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1610
		unset($args);
1611

    
1612
		if ($g['booting'])
1613
			echo gettext("done.") . "\n";
1614
	}
1615

    
1616
	if (!$g['booting']) {
1617
		if(services_dhcpd_configure()!=0)
1618
			$return = 1;
1619
	}
1620

    
1621
	return $return;
1622
}
1623

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

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

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

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

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

    
1649

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

    
1655
EOD;
1656

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

    
1663
EOD;
1664
		}
1665
*/
1666

    
1667

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

    
1675

    
1676
EOD;
1677
		}
1678

    
1679

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

    
1687
EOD;
1688

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

    
1694
EOD;
1695
		}
1696
*/
1697

    
1698

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

    
1705
EOD;
1706
		}
1707

    
1708

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

    
1712
EOD;
1713

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

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

    
1733
EOD;
1734

    
1735
		}
1736

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

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

    
1746
snmpEnableAuthenTraps = 2
1747

    
1748
EOD;
1749

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

    
1755
EOD;
1756
		    }
1757

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

    
1764
EOD;
1765
		    }
1766

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

    
1771
EOD;
1772
		    }
1773

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

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

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

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

    
1797
EOD;
1798
			}
1799
		}
1800

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

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

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

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

    
1817
	return 0;
1818
}
1819

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1902
	return 0;
1903
}
1904

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

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

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

    
1922

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

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

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

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

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

    
1952
	conf_mount_ro();
1953
}
1954

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

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

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

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

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

    
1995
	$is_installed = false;
1996

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

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

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

    
2036
?>
(49-49/66)