Project

General

Profile

Download (64.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 (isset($dhcpv6ifconf['rasamednsasdhcp6']) && is_array($dhcpv6ifconf['dnsserver']) && !empty($dhcpv6ifconf['dnsserver'])) {
181
			foreach($dhcpv6ifconf['dnsserver'] as $server)
182
				if (is_ipaddrv6($server))
183
					$dnslist[] = $server;
184
		} elseif (!isset($dhcpv6ifconf['rasamednsasdhcp6']) && isset($dhcpv6ifconf['radnsserver']) && is_array($dhcpv6ifconf['radnsserver'])) {
185
			foreach($dhcpv6ifconf['radnsserver'] as $server)
186
				if (is_ipaddrv6($server))
187
					$dnslist[] = $server;
188
		} elseif (isset($config['dnsmasq']['enable'])) {
189
			$dnslist[] = get_interface_ipv6($realif);
190
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
191
			foreach($config['system']['dnsserver'] as $server) {
192
				if (is_ipaddrv6($server))
193
					$dnslist[] = $server;
194
			}
195
		}
196
		if (count($dnslist) > 0) {
197
			$dnsstring = implode(" ", $dnslist);
198
			if ($dnsstring <> "")
199
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
200
		}
201
		if (!empty($dhcpv6ifconf['domain'])) {
202
			$radvdconf .= "\tDNSSL {$dhcpv6ifconf['domain']} { };\n";
203
		} elseif (!empty($config['system']['domain'])) {
204
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
205
		}
206
		$radvdconf .= "};\n";
207
	}
208

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

    
221
		$ifcfgipv6 = get_interface_ipv6($if);
222
		if(!is_ipaddrv6($ifcfgipv6))
223
			continue;
224

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

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

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

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

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

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

    
303
function services_dhcpd_configure($family = "all") {
304
	global $config, $g;
305

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

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

    
328
	if ($family == "all" || $family == "inet")
329
		services_dhcpdv4_configure();
330
	if ($family == "all" || $family == "inet6") {
331
		services_dhcpdv6_configure();
332
		services_radvd_configure();
333
	}
334
}
335

    
336
function services_dhcpdv4_configure() {
337
	global $config, $g;
338

    
339
	if($g['services_dhcp_server_enable'] == false)
340
		return;
341

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

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

    
353
	/* DHCP enabled on any interfaces? */
354
	if (!is_dhcp_server_enabled())
355
		return 0;
356

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

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

    
380
	$syscfg = $config['system'];
381
	if (!is_array($config['dhcpd']))
382
		$config['dhcpd'] = array();
383
	$dhcpdcfg = $config['dhcpd'];
384
	$Iflist = get_configured_interface_list();
385

    
386
	if ($g['booting'])
387
		echo gettext("Starting DHCP service...");
388
	else
389
		sleep(1);
390

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

    
404
	$dhcpdconf = <<<EOD
405

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

    
418
EOD;
419

    
420
	if(!isset($dhcpifconf['disableauthoritative']))
421
		$dhcpdconf .= "authoritative;\n";
422

    
423
	if(isset($dhcpifconf['alwaysbroadcast']))
424
		$dhcpdconf .= "always-broadcast on\n";
425

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

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

    
444
		interfaces_staticarp_configure($dhcpif);
445

    
446
		if (!isset($dhcpifconf['enable']))
447
			continue;
448

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

    
495
EOPP;
496
		$dhcpnum++;
497
		}
498
	}
499

    
500
	$dhcpnum = 0;
501

    
502
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
503

    
504
		$ifcfg = $config['interfaces'][$dhcpif];
505

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

    
513
		if (!is_ipaddr($subnet))
514
			continue;
515

    
516
		if($is_olsr_enabled == true)
517
			if($dhcpifconf['netmask'])
518
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
519

    
520
		$all_pools = array();
521
		$all_pools[] = $dhcpifconf;
522
		if (is_array($dhcpifconf['pool'])) {
523
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
524
		}
525

    
526
		$dnscfg = "";
527

    
528
		if ($dhcpifconf['domain']) {
529
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
530
		}
531

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

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

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

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

    
572
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
573

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

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

    
599
			if($poolconf['failover_peerip'] <> "")
600
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
601

    
602
			if (isset($poolconf['denyunknown']))
603
			   $dhcpdconf .= "		deny unknown-clients;\n";
604

    
605
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
606
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
607

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

    
613
			$pdnscfg = "";
614

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

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

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

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

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

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

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

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

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

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

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

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

    
686
		$dhcpdconf .= <<<EOD
687
$dnscfg
688

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

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

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

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

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

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

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

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

    
740
		$dhcpdconf .= <<<EOD
741
}
742

    
743
EOD;
744

    
745
		/* add static mappings */
746
		if (is_array($dhcpifconf['staticmap'])) {
747

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

    
754
EOD;
755
				if ($sm['ipaddr'])
756
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
757

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

    
766
				if ($sm['rootpath'])
767
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
768

    
769
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
770
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
771

    
772
				$smdnscfg = "";
773

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

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

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

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

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

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

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

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

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

    
815
				$dhcpdconf .= "}\n";
816
				$i++;
817
			}
818
		}
819

    
820
		$dhcpdifs[] = get_real_interface($dhcpif);
821
	}
822

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

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

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

    
841
	if ($g['booting'])
842
		print "done.\n";
843

    
844
	return 0;
845
}
846

    
847
function services_dhcpdv6_configure() {
848
	global $config, $g;
849

    
850
	if($g['services_dhcp_server_enable'] == false)
851
		return;
852

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

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

    
864
	/* DHCP enabled on any interfaces? */
865
	if (!is_dhcpv6_server_enabled())
866
		return 0;
867

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

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

    
890

    
891
	if ($g['booting'])
892
		echo "Starting DHCPv6 service...";
893
	else
894
		sleep(1);
895

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

    
924
				/* set the delegation start to half the current address block */
925
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
926
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
927

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

    
932
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
933
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
934
			}
935
		}
936
	}
937

    
938
	$custoptionsv6 = "";
939
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
940
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
941
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
942
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
943
			}
944
		}
945
	}
946

    
947
	$dhcpdv6conf = <<<EOD
948

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

    
961
EOD;
962

    
963
	if(!isset($dhcpv6ifconf['disableauthoritative']))
964
		$dhcpdv6conf .= "authoritative;\n";
965

    
966
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
967
		$dhcpdv6conf .= "always-broadcast on\n";
968

    
969
	$dhcpdv6ifs = array();
970

    
971
	$dhcpv6num = 0;
972
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
973

    
974
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
975

    
976
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
977
			continue;
978
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
979
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
980
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
981

    
982
		if($is_olsr_enabled == true)
983
			if($dhcpv6ifconf['netmask'])
984
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
985

    
986
		$dnscfgv6 = "";
987

    
988
		if ($dhcpv6ifconf['domain']) {
989
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
990
		}
991

    
992
    		if($dhcpv6ifconf['domainsearchlist'] <> "") {
993
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
994
    		}
995

    
996
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
997
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
998
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
999
			}
1000
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1001
		}
1002

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

    
1018
		if(is_ipaddrv6($ifcfgipv6)) {
1019
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6} {\n";
1020
		} else {
1021
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1022
			$dhcpdv6conf .= "subnet6 {$subnet6}/64 {\n";
1023
		}
1024

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

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

    
1031
		$dhcpdv6conf .= <<<EOD
1032
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1033
$dnscfgv6
1034

    
1035
EOD;
1036

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

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

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

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

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

    
1073
		// ldap-server
1074
		if ($dhcpv6ifconf['ldap'] <> "")
1075
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1076

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

    
1090
		$dhcpdv6conf .= "}\n";
1091

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

    
1101
EOD;
1102
				if ($sm['ipaddrv6'])
1103
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1104

    
1105
				if ($sm['hostname']) {
1106
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1107
					$dhhostname = str_replace(".", "_", $dhhostname);
1108
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1109
				}
1110
				if ($sm['filename'])
1111
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1112

    
1113
				if ($sm['rootpath'])
1114
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1115

    
1116
				$dhcpdv6conf .= "}\n";
1117
				$i++;
1118
			}
1119
		}
1120

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

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

    
1149
	/* create an empty leases v6 database */
1150
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1151
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1152

    
1153
	/* fire up dhcpd in a chroot */
1154
	if (count($dhcpdv6ifs) > 0) {
1155
		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 " .
1156
			join(" ", $dhcpdv6ifs));
1157
		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");
1158
	}
1159
	if ($g['booting'])
1160
		print gettext("done.") . "\n";
1161

    
1162
	return 0;
1163
}
1164

    
1165
function services_igmpproxy_configure() {
1166
        global $config, $g;
1167

    
1168
        /* kill any running igmpproxy */
1169
        killbyname("igmpproxy");
1170

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

    
1174
        $iflist = get_configured_interface_list();
1175

    
1176
        $igmpconf = <<<EOD
1177

    
1178
##------------------------------------------------------
1179
## Enable Quickleave mode (Sends Leave instantly)
1180
##------------------------------------------------------
1181
quickleave
1182

    
1183
EOD;
1184

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

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

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

    
1216
	/* NOTE: -d 4 means everything LOG_WARNING and smaller */
1217
        mwexec("/usr/local/sbin/igmpproxy -d 4 -c {$g['tmp_path']}/igmpproxy.conf");
1218
        log_error(gettext("Started IGMP proxy service."));
1219

    
1220
        return 0;
1221
}
1222

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

    
1232
	/* kill any running dhcrelay */
1233
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1234

    
1235
	$dhcrelaycfg =& $config['dhcrelay'];
1236

    
1237
	/* DHCPRelay enabled on any interfaces? */
1238
	if (!isset($dhcrelaycfg['enable']))
1239
		return 0;
1240

    
1241
	if ($g['booting'])
1242
		echo gettext("Starting DHCP relay service...");
1243
	else
1244
		sleep(1);
1245

    
1246
	$iflist = get_configured_interface_list();
1247

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

    
1254
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1255
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1256
	}
1257

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

    
1285
		if (!isset($destif)) {
1286
			/* Create a array from the existing route table */
1287
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1288
        		array_shift($route_str);
1289
        		array_shift($route_str);
1290
        		array_shift($route_str);
1291
        		array_shift($route_str);
1292
        		$route_arr = array();
1293
        		foreach($route_str as $routeline) {
1294
				$items = preg_split("/[ ]+/i", $routeline);
1295
				if (is_subnetv4($items[0])) {
1296
					$subnet = $items[0];
1297
				} elseif (is_ipaddrv4($items[0])) {
1298
					$subnet = "{$items[0]}/32";
1299
				} else {
1300
					// Not a subnet or IP address, skip to the next line.
1301
					continue;
1302
				}
1303
				if (ip_in_subnet($srvip, $subnet)) {
1304
					$destif = trim($items[6]);
1305
					break;
1306
				}
1307
			}
1308
		}
1309

    
1310
		if (!isset($destif)) {
1311
			if (is_array($config['gateways']['gateway_item'])) {
1312
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1313
					if (isset($gateway['defaultgw'])) {
1314
						$a_gateways = return_gateways_array(true);
1315
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1316
						break;
1317
					}
1318
				}
1319
			} else
1320
				$destif = get_real_interface("wan");
1321
		}
1322

    
1323
		if (!empty($destif))
1324
			$dhcrelayifs[] = $destif;
1325
	}
1326
	$dhcrelayifs = array_unique($dhcrelayifs);
1327

    
1328
	/* fire up dhcrelay */
1329
	if (empty($dhcrelayifs)) {
1330
		log_error("No suitable interface found for running dhcrelay!");
1331
		return; /* XXX */
1332
	}
1333

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

    
1336
	if (isset($dhcrelaycfg['agentoption']))
1337
		$cmd .=  " -a -m replace";
1338

    
1339
	$cmd .= " " . implode(" ", $srvips);
1340
	mwexec($cmd);
1341
	unset($cmd);
1342

    
1343
	return 0;
1344
}
1345

    
1346
function services_dhcrelay6_configure() {
1347
	global $config, $g;
1348
	if ($g['platform'] == 'jail')
1349
		return;
1350
	if(isset($config['system']['developerspew'])) {
1351
		$mt = microtime();
1352
		echo "services_dhcrelay_configure() being called $mt\n";
1353
	}
1354

    
1355
	/* kill any running dhcrelay */
1356
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1357

    
1358
	$dhcrelaycfg =& $config['dhcrelay6'];
1359

    
1360
	/* DHCPv6 Relay enabled on any interfaces? */
1361
	if (!isset($dhcrelaycfg['enable']))
1362
		return 0;
1363

    
1364
	if ($g['booting'])
1365
		echo gettext("Starting DHCPv6 relay service...");
1366
	else
1367
		sleep(1);
1368

    
1369
	$iflist = get_configured_interface_list();
1370

    
1371
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1372
	foreach ($dhcifaces as $dhcrelayif) {
1373
		if (!isset($iflist[$dhcrelayif]) ||
1374
			link_interface_to_bridge($dhcrelayif))
1375
			continue;
1376

    
1377
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1378
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1379
	}
1380
	$dhcrelayifs = array_unique($dhcrelayifs);
1381

    
1382
	/*
1383
	 * In order for the relay to work, it needs to be active
1384
	 * on the interface in which the destination server sits.
1385
	 */
1386
	$srvips = explode(",", $dhcrelaycfg['server']);
1387
        $srvifaces = array();
1388
	foreach ($srvips as $srcidx => $srvip) {
1389
		unset($destif);
1390
		foreach ($iflist as $ifname) {
1391
			$subnet = get_interface_ipv6($ifname);
1392
			if (!is_ipaddrv6($subnet))
1393
				continue;
1394
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1395
			if (ip_in_subnet($srvip, $subnet)) {
1396
				$destif = get_real_interface($ifname);
1397
				break;
1398
			}
1399
		}
1400
		if (!isset($destif)) {
1401
			if (is_array($config['staticroutes']['route'])) {
1402
				foreach ($config['staticroutes']['route'] as $rtent) {
1403
					if (ip_in_subnet($srvip, $rtent['network'])) {
1404
						$a_gateways = return_gateways_array(true);
1405
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1406
						break;
1407
					}
1408
				}
1409
			}
1410
		}
1411

    
1412
		if (!isset($destif)) {
1413
			/* Create a array from the existing route table */
1414
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1415
        		array_shift($route_str);
1416
        		array_shift($route_str);
1417
        		array_shift($route_str);
1418
        		array_shift($route_str);
1419
        		$route_arr = array();
1420
        		foreach($route_str as $routeline) {
1421
                		$items = preg_split("/[ ]+/i", $routeline);
1422
				if (ip_in_subnet($srvip, $items[0])) {
1423
					$destif = trim($items[6]);
1424
					break;
1425
				}
1426
        		}
1427
		}
1428

    
1429
		if (!isset($destif)) {
1430
			if (is_array($config['gateways']['gateway_item'])) {
1431
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1432
					if (isset($gateway['defaultgw'])) {
1433
						$a_gateways = return_gateways_array(true);
1434
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1435
						break;
1436
					}
1437
				}
1438
			} else
1439
				$destif = get_real_interface("wan");
1440
		}
1441

    
1442
		if (!empty($destif)) {
1443
			$srvifaces[] = "{$srvip}%{$destif}";
1444
		}
1445
	}
1446

    
1447
	/* fire up dhcrelay */
1448
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1449
		log_error("No suitable interface found for running dhcrelay -6!");
1450
		return; /* XXX */
1451
	}
1452

    
1453
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varetc_path']}/dhcrelay6.pid\"";
1454
	foreach ($dhcrelayifs as $dhcrelayif) {
1455
		$cmd .= " -l {$dhcrelayif}";
1456
	}
1457
	foreach ($srvifaces as $srviface) {
1458
		$cmd .= " -u \"{$srviface}\"";
1459
	}
1460
	mwexec($cmd);
1461
	unset($cmd);
1462

    
1463
	return 0;
1464
}
1465

    
1466
function services_dyndns_configure_client($conf) {
1467

    
1468
	if (!isset($conf['enable']))
1469
		return;
1470

    
1471
	/* load up the dyndns.class */
1472
	require_once("dyndns.class");
1473

    
1474
	$dns = new updatedns($dnsService = $conf['type'],
1475
		$dnsHost = $conf['host'],
1476
		$dnsUser = $conf['username'],
1477
		$dnsPass = $conf['password'],
1478
		$dnsWilcard = $conf['wildcard'],
1479
		$dnsMX = $conf['mx'],
1480
		$dnsIf = "{$conf['interface']}",
1481
		$dnsBackMX = NULL,
1482
		$dnsServer = NULL,
1483
		$dnsPort = NULL,
1484
		$dnsUpdateURL = "{$conf['updateurl']}",
1485
		$forceUpdate = $conf['force'],
1486
		$dnsZoneID=$conf['zoneid'],
1487
		$dnsTTL=$conf['ttl'],
1488
		$dnsResultMatch = "{$conf['resultmatch']}",
1489
		$dnsRequestIf = "{$conf['requestif']}",
1490
		$dnsID = "{$conf['id']}",
1491
		$dnsVerboseLog = $conf['verboselog']);
1492
}
1493

    
1494
function services_dyndns_configure($int = "") {
1495
	global $config, $g;
1496
	if(isset($config['system']['developerspew'])) {
1497
		$mt = microtime();
1498
		echo "services_dyndns_configure() being called $mt\n";
1499
	}
1500

    
1501
	$dyndnscfg = $config['dyndnses']['dyndns'];
1502
	$gwgroups = return_gateway_groups_array();
1503
	if (is_array($dyndnscfg)) {
1504
		if ($g['booting'])
1505
			echo gettext("Starting DynDNS clients...");
1506

    
1507
		foreach ($dyndnscfg as $dyndns) {
1508
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1509
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1510
				services_dyndns_configure_client($dyndns);
1511
				sleep(1);
1512
			}
1513
		}
1514

    
1515
		if ($g['booting'])
1516
			echo gettext("done.") . "\n";
1517
	}
1518

    
1519
	return 0;
1520
}
1521

    
1522
function dyndnsCheckIP($int) {
1523
	global $config;
1524
	$ip_address = get_interface_ip($int);
1525
	if (is_private_ip($ip_address)) {
1526
		$gateways_status = return_gateways_status(true);
1527
		// If the gateway for this interface is down, then the external check cannot work.
1528
		// Avoid the long wait for the external check to timeout.
1529
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1530
			return "down";
1531
		$hosttocheck = "checkip.dyndns.org";
1532
		$checkip = gethostbyname($hosttocheck);
1533
		$ip_ch = curl_init("http://{$checkip}");
1534
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1535
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1536
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1537
		$ip_result_page = curl_exec($ip_ch);
1538
		curl_close($ip_ch);
1539
		$ip_result_decoded = urldecode($ip_result_page);
1540
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1541
		$ip_address = trim($matches[1]);
1542
	}
1543
	return $ip_address;
1544
}
1545

    
1546
function services_dnsmasq_configure() {
1547
	global $config, $g;
1548
	$return = 0;
1549

    
1550
	if(isset($config['system']['developerspew'])) {
1551
		$mt = microtime();
1552
		echo "services_dnsmasq_configure() being called $mt\n";
1553
	}
1554

    
1555
	/* kill any running dnsmasq */
1556
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1557
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1558

    
1559
	if (isset($config['dnsmasq']['enable'])) {
1560

    
1561
		if ($g['booting'])
1562
			echo gettext("Starting DNS forwarder...");
1563
		else
1564
			sleep(1);
1565

    
1566
		/* generate hosts file */
1567
		if(system_hosts_generate()!=0)
1568
			$return = 1;
1569

    
1570
		$args = "";
1571

    
1572
		if (isset($config['dnsmasq']['regdhcp'])) {
1573
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1574
		}
1575

    
1576
		/* Setup forwarded domains */
1577
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1578
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1579
				if ($override['ip'] == "!")
1580
					$override[ip] = "";
1581
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1582
			}
1583
		}
1584

    
1585
		/* If selected, then forward reverse lookups for private IPv4 addresses to nowhere. */
1586
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1587
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1588
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1589
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1590
			$args .= " --server=/10.in-addr.arpa/ ";
1591
			$args .= " --server=/168.192.in-addr.arpa/ ";
1592
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1593
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1594
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1595
			}
1596
		}
1597

    
1598
		/* Allow DNS Rebind for forwarded domains */
1599
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1600
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1601
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1602
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1603
				}
1604
			}
1605
		}
1606

    
1607
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1608
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1609

    
1610
		if (isset($config['dnsmasq']['strict_order'])) {
1611
			$args .= " --strict-order ";
1612
		}
1613

    
1614
		if (isset($config['dnsmasq']['domain_needed'])) {
1615
			$args .= " --domain-needed ";
1616
		}
1617

    
1618
		if ($config['dnsmasq']['custom_options']) {
1619
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1620
				$args .= " --$c";
1621
		}
1622

    
1623
		/* run dnsmasq */
1624
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1625
		unset($args);
1626

    
1627
		if ($g['booting'])
1628
			echo gettext("done.") . "\n";
1629
	}
1630

    
1631
	if (!$g['booting']) {
1632
		if(services_dhcpd_configure()!=0)
1633
			$return = 1;
1634
	}
1635

    
1636
	return $return;
1637
}
1638

    
1639
function services_snmpd_configure() {
1640
	global $config, $g;
1641
	if(isset($config['system']['developerspew'])) {
1642
		$mt = microtime();
1643
		echo "services_snmpd_configure() being called $mt\n";
1644
	}
1645

    
1646
	/* kill any running snmpd */
1647
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1648
	sleep(2);
1649
	if(is_process_running("bsnmpd"))
1650
		mwexec("/usr/bin/killall bsnmpd", true);
1651

    
1652
	if (isset($config['snmpd']['enable'])) {
1653

    
1654
		if ($g['booting'])
1655
			echo gettext("Starting SNMP daemon... ");
1656

    
1657
		/* generate snmpd.conf */
1658
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1659
		if (!$fd) {
1660
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1661
			return 1;
1662
		}
1663

    
1664

    
1665
		$snmpdconf = <<<EOD
1666
location := "{$config['snmpd']['syslocation']}"
1667
contact := "{$config['snmpd']['syscontact']}"
1668
read := "{$config['snmpd']['rocommunity']}"
1669

    
1670
EOD;
1671

    
1672
/* No docs on what write strings do there for disable for now.
1673
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1674
		    $snmpdconf .= <<<EOD
1675
# write string
1676
write := "{$config['snmpd']['rwcommunity']}"
1677

    
1678
EOD;
1679
		}
1680
*/
1681

    
1682

    
1683
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1684
		    $snmpdconf .= <<<EOD
1685
# SNMP Trap support.
1686
traphost := {$config['snmpd']['trapserver']}
1687
trapport := {$config['snmpd']['trapserverport']}
1688
trap := "{$config['snmpd']['trapstring']}"
1689

    
1690

    
1691
EOD;
1692
		}
1693

    
1694
		$version = trim(file_get_contents('/etc/version'));
1695
		$platform = trim(file_get_contents('/etc/platform'));
1696
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1697
			$platform = $g['product_name'];
1698
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1699
			" {$version} {$platform} " . php_uname("s") .
1700
			" " . php_uname("r") . " " . php_uname("m");
1701

    
1702
		$snmpdconf .= <<<EOD
1703
system := 1     # pfSense
1704
%snmpd
1705
sysDescr			= "{$sysDescr}"
1706
begemotSnmpdDebugDumpPdus       = 2
1707
begemotSnmpdDebugSyslogPri      = 7
1708
begemotSnmpdCommunityString.0.1 = $(read)
1709

    
1710
EOD;
1711

    
1712
/* No docs on what write strings do there for disable for now.
1713
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1714
		    $snmpdconf .= <<<EOD
1715
begemotSnmpdCommunityString.0.2 = $(write)
1716

    
1717
EOD;
1718
		}
1719
*/
1720

    
1721

    
1722
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1723
		    $snmpdconf .= <<<EOD
1724
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1725
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1726
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1727

    
1728
EOD;
1729
		}
1730

    
1731

    
1732
		$snmpdconf .= <<<EOD
1733
begemotSnmpdCommunityDisable    = 1
1734

    
1735
EOD;
1736

    
1737
		if (isset($config['snmpd']['bindlan'])) {
1738
			$config['snmpd']['bindip'] = 'lan';
1739
			unset($config['snmpd']['bindlan']);
1740
		}
1741
		$bind_to_ip = "0.0.0.0";
1742
		if(isset($config['snmpd']['bindip'])) {
1743
			if (is_ipaddr($config['snmpd']['bindip'])) {
1744
				$bind_to_ip = $config['snmpd']['bindip'];
1745
			} else {
1746
				$if = get_real_interface($config['snmpd']['bindip']);
1747
				if (does_interface_exist($if))
1748
					$bind_to_ip = find_interface_ip($if);
1749
			}
1750
		}
1751

    
1752
		if(is_port( $config['snmpd']['pollport'] )) {
1753
		    $snmpdconf .= <<<EOD
1754
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1755

    
1756
EOD;
1757

    
1758
		}
1759

    
1760
		$snmpdconf .= <<<EOD
1761
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1762
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1763

    
1764
# These are bsnmp macros not php vars.
1765
sysContact      = $(contact)
1766
sysLocation     = $(location)
1767
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1768

    
1769
snmpEnableAuthenTraps = 2
1770

    
1771
EOD;
1772

    
1773
		if (is_array( $config['snmpd']['modules'] )) {
1774
		    if(isset($config['snmpd']['modules']['mibii'])) {
1775
			$snmpdconf .= <<<EOD
1776
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1777

    
1778
EOD;
1779
		    }
1780

    
1781
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1782
			$snmpdconf .= <<<EOD
1783
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1784
%netgraph
1785
begemotNgControlNodeName = "snmpd"
1786

    
1787
EOD;
1788
		    }
1789

    
1790
		    if(isset($config['snmpd']['modules']['pf'])) {
1791
			$snmpdconf .= <<<EOD
1792
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1793

    
1794
EOD;
1795
		    }
1796

    
1797
		    if(isset($config['snmpd']['modules']['hostres'])) {
1798
			$snmpdconf .= <<<EOD
1799
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1800

    
1801
EOD;
1802
		    }
1803
		    if(isset($config['snmpd']['modules']['bridge'])) {
1804
			$snmpdconf .= <<<EOD
1805
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1806
# config must end with blank line
1807

    
1808
EOD;
1809
		    }
1810
			if(isset($config['snmpd']['modules']['ucd'])) {
1811
				$snmpdconf .= <<<EOD
1812
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1813

    
1814
EOD;
1815
			}
1816
			if(isset($config['snmpd']['modules']['regex'])) {
1817
				$snmpdconf .= <<<EOD
1818
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1819

    
1820
EOD;
1821
			}
1822
		}
1823

    
1824
		fwrite($fd, $snmpdconf);
1825
		fclose($fd);
1826
		unset($snmpdconf);
1827

    
1828
		if (isset($config['snmpd']['bindlan'])) {
1829
			$bindlan = "";
1830
		}
1831

    
1832
		/* run bsnmpd */
1833
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1834
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1835

    
1836
		if ($g['booting'])
1837
			echo gettext("done.") . "\n";
1838
	}
1839

    
1840
	return 0;
1841
}
1842

    
1843
function services_dnsupdate_process($int = "") {
1844
	global $config, $g;
1845
	if(isset($config['system']['developerspew'])) {
1846
		$mt = microtime();
1847
		echo "services_dnsupdate_process() being called $mt\n";
1848
	}
1849

    
1850
	/* Dynamic DNS updating active? */
1851
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1852
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1853
			if (!isset($dnsupdate['enable']))
1854
				continue;
1855
			if (!empty($int) && $int != $dnsupdate['interface'])
1856
				continue;
1857

    
1858
			/* determine interface name */
1859
			$if = get_real_interface($dnsupdate['interface']);
1860
			$wanip = get_interface_ip($dnsupdate['interface']);
1861
			if ($wanip) {
1862

    
1863
				$keyname = $dnsupdate['keyname'];
1864
				/* trailing dot */
1865
				if (substr($keyname, -1) != ".")
1866
					$keyname .= ".";
1867

    
1868
				$hostname = $dnsupdate['host'];
1869
				/* trailing dot */
1870
				if (substr($hostname, -1) != ".")
1871
					$hostname .= ".";
1872

    
1873
				/* write private key file
1874
				   this is dumb - public and private keys are the same for HMAC-MD5,
1875
				   but nsupdate insists on having both */
1876
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
1877
				$privkey = <<<EOD
1878
Private-key-format: v1.2
1879
Algorithm: 157 (HMAC)
1880
Key: {$dnsupdate['keydata']}
1881

    
1882
EOD;
1883
				fwrite($fd, $privkey);
1884
				fclose($fd);
1885

    
1886
				/* write public key file */
1887
				if ($dnsupdate['keytype'] == "zone") {
1888
					$flags = 257;
1889
					$proto = 3;
1890
				} else if ($dnsupdate['keytype'] == "host") {
1891
					$flags = 513;
1892
					$proto = 3;
1893
				} else if ($dnsupdate['keytype'] == "user") {
1894
					$flags = 0;
1895
					$proto = 2;
1896
				}
1897

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

    
1902
				/* generate update instructions */
1903
				$upinst = "";
1904
				if (!empty($dnsupdate['server']))
1905
					$upinst .= "server {$dnsupdate['server']}\n";
1906
				$upinst .= "update delete {$dnsupdate['host']} A\n";
1907
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
1908
				$upinst .= "\n";	/* mind that trailing newline! */
1909

    
1910
				@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
1911
				unset($upinst);
1912

    
1913
				/* invoke nsupdate */
1914
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
1915
				if (isset($dnsupdate['usetcp']))
1916
					$cmd .= " -v";
1917
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
1918

    
1919
				mwexec_bg($cmd);
1920
				unset($cmd);
1921
			}
1922
		}
1923
	}
1924

    
1925
	return 0;
1926
}
1927

    
1928
/* configure cron service */
1929
function configure_cron() {
1930
	global $g, $config;
1931

    
1932
	conf_mount_rw();
1933
	/* preserve existing crontab entries */
1934
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1935

    
1936
	for ($i = 0; $i < count($crontab_contents); $i++) {
1937
		$cron_item =& $crontab_contents[$i];
1938
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
1939
			array_splice($crontab_contents, $i - 1);
1940
			break;
1941
		}
1942
	}
1943
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
1944

    
1945

    
1946
	if (is_array($config['cron']['item'])) {
1947
		$crontab_contents .= "#\n";
1948
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
1949
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
1950
		$crontab_contents .= "#\n";
1951

    
1952
		foreach ($config['cron']['item'] as $item) {
1953
			$crontab_contents .= "\n{$item['minute']}\t";
1954
			$crontab_contents .= "{$item['hour']}\t";
1955
			$crontab_contents .= "{$item['mday']}\t";
1956
			$crontab_contents .= "{$item['month']}\t";
1957
			$crontab_contents .= "{$item['wday']}\t";
1958
			$crontab_contents .= "{$item['who']}\t";
1959
			$crontab_contents .= "{$item['command']}";
1960
		}
1961

    
1962
		$crontab_contents .= "\n#\n";
1963
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
1964
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
1965
		$crontab_contents .= "#\n\n";
1966
	}
1967

    
1968
	/* please maintain the newline at the end of file */
1969
	file_put_contents("/etc/crontab", $crontab_contents);
1970
	unset($crontab_contents);
1971

    
1972
	/* do a HUP kill to force sync changes */
1973
	exec('/bin/pkill -HUP cron');
1974

    
1975
	conf_mount_ro();
1976
}
1977

    
1978
function upnp_action ($action) {
1979
	global $g, $config;
1980
	switch($action) {
1981
		case "start":
1982
			if (file_exists('/var/etc/miniupnpd.conf')) {
1983
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
1984
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
1985
			}
1986
			break;
1987
		case "stop":
1988
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
1989
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
1990
				mwexec('killall miniupnpd 2>/dev/null', true);
1991
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
1992
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
1993
			break;
1994
		case "restart":
1995
			upnp_action('stop');
1996
			upnp_action('start');
1997
			break;
1998
	}
1999
}
2000

    
2001
function upnp_start() {
2002
	global $config;
2003

    
2004
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2005
		return;
2006

    
2007
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2008
		echo gettext("Starting UPnP service... ");
2009
		require_once('/usr/local/pkg/miniupnpd.inc');
2010
		sync_package_miniupnpd();
2011
		echo "done.\n";
2012
	}
2013
}
2014

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

    
2018
	$is_installed = false;
2019

    
2020
	if (!is_array($config['cron']))
2021
		$config['cron'] = array();
2022
	if (!is_array($config['cron']['item']))
2023
		$config['cron']['item'] = array();
2024

    
2025
	$x=0;
2026
	foreach($config['cron']['item'] as $item) {
2027
		if(strstr($item['command'], $command)) {
2028
			$is_installed = true;
2029
			break;
2030
		}
2031
		$x++;
2032
	}
2033

    
2034
	if($active) {
2035
		$cron_item = array();
2036
		$cron_item['minute'] = $minute;
2037
		$cron_item['hour'] = $hour;
2038
		$cron_item['mday'] = $monthday;
2039
		$cron_item['month'] = $month;
2040
		$cron_item['wday'] = $weekday;
2041
		$cron_item['who'] = $who;
2042
		$cron_item['command'] = $command;
2043
		if(!$is_installed) {
2044
			$config['cron']['item'][] = $cron_item;
2045
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2046
		} else {
2047
			$config['cron']['item'][$x] = $cron_item;
2048
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2049
		}
2050
	} else {
2051
		if(($is_installed == true) && ($x > 0)) {
2052
			unset($config['cron']['item'][$x]);
2053
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2054
		}
2055
	}
2056
	configure_cron();
2057
}
2058

    
2059
?>
(49-49/66)