Project

General

Profile

Download (63.9 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
        mwexec("/usr/local/sbin/igmpproxy -c {$g['tmp_path']}/igmpproxy.conf");
1217
        log_error(gettext("Started IGMP proxy service."));
1218

    
1219
        return 0;
1220
}
1221

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

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

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

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

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

    
1245
	$iflist = get_configured_interface_list();
1246

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

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

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

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

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

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

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

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

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

    
1330
	$cmd .= " " . implode(" ", $srvips);
1331
	mwexec($cmd);
1332
	unset($cmd);
1333

    
1334
	return 0;
1335
}
1336

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

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

    
1349
	$dhcrelaycfg =& $config['dhcrelay6'];
1350

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

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

    
1360
	$iflist = get_configured_interface_list();
1361

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

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

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

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

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

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

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

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

    
1454
	return 0;
1455
}
1456

    
1457
function services_dyndns_configure_client($conf) {
1458

    
1459
	if (!isset($conf['enable']))
1460
		return;
1461

    
1462
	/* load up the dyndns.class */
1463
	require_once("dyndns.class");
1464

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

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

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

    
1498
		foreach ($dyndnscfg as $dyndns) {
1499
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1500
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1501
				services_dyndns_configure_client($dyndns);
1502
				sleep(1);
1503
			}
1504
		}
1505

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

    
1510
	return 0;
1511
}
1512

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

    
1537
function services_dnsmasq_configure() {
1538
	global $config, $g;
1539
	$return = 0;
1540

    
1541
	if(isset($config['system']['developerspew'])) {
1542
		$mt = microtime();
1543
		echo "services_dnsmasq_configure() being called $mt\n";
1544
	}
1545

    
1546
	/* kill any running dnsmasq */
1547
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1548
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1549

    
1550
	if (isset($config['dnsmasq']['enable'])) {
1551

    
1552
		if ($g['booting'])
1553
			echo gettext("Starting DNS forwarder...");
1554
		else
1555
			sleep(1);
1556

    
1557
		/* generate hosts file */
1558
		if(system_hosts_generate()!=0)
1559
			$return = 1;
1560

    
1561
		$args = "";
1562

    
1563
		if (isset($config['dnsmasq']['regdhcp'])) {
1564
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1565
		}
1566

    
1567
		/* Setup forwarded domains */
1568
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1569
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1570
				if ($override['ip'] == "!")
1571
					$override[ip] = "";
1572
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1573
			}
1574
		}
1575

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

    
1589
		/* Allow DNS Rebind for forwarded domains */
1590
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1591
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1592
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1593
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1594
				}
1595
			}
1596
		}
1597

    
1598
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1599
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1600

    
1601
		if (isset($config['dnsmasq']['strict_order'])) {
1602
			$args .= " --strict-order ";
1603
		}
1604

    
1605
		if (isset($config['dnsmasq']['domain_needed'])) {
1606
			$args .= " --domain-needed ";
1607
		}
1608

    
1609
		if ($config['dnsmasq']['custom_options']) {
1610
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
1611
				$args .= " --$c";
1612
		}
1613

    
1614
		/* run dnsmasq */
1615
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
1616
		unset($args);
1617

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

    
1622
	if (!$g['booting']) {
1623
		if(services_dhcpd_configure()!=0)
1624
			$return = 1;
1625
	}
1626

    
1627
	return $return;
1628
}
1629

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

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

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

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

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

    
1655

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

    
1661
EOD;
1662

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

    
1669
EOD;
1670
		}
1671
*/
1672

    
1673

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

    
1681

    
1682
EOD;
1683
		}
1684

    
1685
		$version = trim(file_get_contents('/etc/version'));
1686
		$platform = trim(file_get_contents('/etc/platform'));
1687
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1688
			$platform = $g['product_name'];
1689
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1690
			" {$version} {$platform} " . php_uname("s") .
1691
			" " . php_uname("r") . " " . php_uname("m");
1692

    
1693
		$snmpdconf .= <<<EOD
1694
system := 1     # pfSense
1695
%snmpd
1696
sysDescr			= "{$sysDescr}"
1697
begemotSnmpdDebugDumpPdus       = 2
1698
begemotSnmpdDebugSyslogPri      = 7
1699
begemotSnmpdCommunityString.0.1 = $(read)
1700

    
1701
EOD;
1702

    
1703
/* No docs on what write strings do there for disable for now.
1704
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1705
		    $snmpdconf .= <<<EOD
1706
begemotSnmpdCommunityString.0.2 = $(write)
1707

    
1708
EOD;
1709
		}
1710
*/
1711

    
1712

    
1713
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1714
		    $snmpdconf .= <<<EOD
1715
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1716
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1717
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1718

    
1719
EOD;
1720
		}
1721

    
1722

    
1723
		$snmpdconf .= <<<EOD
1724
begemotSnmpdCommunityDisable    = 1
1725

    
1726
EOD;
1727

    
1728
		if (isset($config['snmpd']['bindlan'])) {
1729
			$config['snmpd']['bindip'] = 'lan';
1730
			unset($config['snmpd']['bindlan']);
1731
		}
1732
		$bind_to_ip = "0.0.0.0";
1733
		if(isset($config['snmpd']['bindip'])) {
1734
			if (is_ipaddr($config['snmpd']['bindip'])) {
1735
				$bind_to_ip = $config['snmpd']['bindip'];
1736
			} else {
1737
				$if = get_real_interface($config['snmpd']['bindip']);
1738
				if (does_interface_exist($if))
1739
					$bind_to_ip = find_interface_ip($if);
1740
			}
1741
		}
1742

    
1743
		if(is_port( $config['snmpd']['pollport'] )) {
1744
		    $snmpdconf .= <<<EOD
1745
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1746

    
1747
EOD;
1748

    
1749
		}
1750

    
1751
		$snmpdconf .= <<<EOD
1752
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1753
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1754

    
1755
# These are bsnmp macros not php vars.
1756
sysContact      = $(contact)
1757
sysLocation     = $(location)
1758
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1759

    
1760
snmpEnableAuthenTraps = 2
1761

    
1762
EOD;
1763

    
1764
		if (is_array( $config['snmpd']['modules'] )) {
1765
		    if(isset($config['snmpd']['modules']['mibii'])) {
1766
			$snmpdconf .= <<<EOD
1767
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1768

    
1769
EOD;
1770
		    }
1771

    
1772
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1773
			$snmpdconf .= <<<EOD
1774
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1775
%netgraph
1776
begemotNgControlNodeName = "snmpd"
1777

    
1778
EOD;
1779
		    }
1780

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

    
1785
EOD;
1786
		    }
1787

    
1788
		    if(isset($config['snmpd']['modules']['hostres'])) {
1789
			$snmpdconf .= <<<EOD
1790
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1791

    
1792
EOD;
1793
		    }
1794
		    if(isset($config['snmpd']['modules']['bridge'])) {
1795
			$snmpdconf .= <<<EOD
1796
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1797
# config must end with blank line
1798

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

    
1805
EOD;
1806
			}
1807
			if(isset($config['snmpd']['modules']['regex'])) {
1808
				$snmpdconf .= <<<EOD
1809
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1810

    
1811
EOD;
1812
			}
1813
		}
1814

    
1815
		fwrite($fd, $snmpdconf);
1816
		fclose($fd);
1817
		unset($snmpdconf);
1818

    
1819
		if (isset($config['snmpd']['bindlan'])) {
1820
			$bindlan = "";
1821
		}
1822

    
1823
		/* run bsnmpd */
1824
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1825
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1826

    
1827
		if ($g['booting'])
1828
			echo gettext("done.") . "\n";
1829
	}
1830

    
1831
	return 0;
1832
}
1833

    
1834
function services_dnsupdate_process($int = "") {
1835
	global $config, $g;
1836
	if(isset($config['system']['developerspew'])) {
1837
		$mt = microtime();
1838
		echo "services_dnsupdate_process() being called $mt\n";
1839
	}
1840

    
1841
	/* Dynamic DNS updating active? */
1842
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1843
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1844
			if (!isset($dnsupdate['enable']))
1845
				continue;
1846
			if (!empty($int) && $int != $dnsupdate['interface'])
1847
				continue;
1848

    
1849
			/* determine interface name */
1850
			$if = get_real_interface($dnsupdate['interface']);
1851
			$wanip = get_interface_ip($dnsupdate['interface']);
1852
			if ($wanip) {
1853

    
1854
				$keyname = $dnsupdate['keyname'];
1855
				/* trailing dot */
1856
				if (substr($keyname, -1) != ".")
1857
					$keyname .= ".";
1858

    
1859
				$hostname = $dnsupdate['host'];
1860
				/* trailing dot */
1861
				if (substr($hostname, -1) != ".")
1862
					$hostname .= ".";
1863

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

    
1873
EOD;
1874
				fwrite($fd, $privkey);
1875
				fclose($fd);
1876

    
1877
				/* write public key file */
1878
				if ($dnsupdate['keytype'] == "zone") {
1879
					$flags = 257;
1880
					$proto = 3;
1881
				} else if ($dnsupdate['keytype'] == "host") {
1882
					$flags = 513;
1883
					$proto = 3;
1884
				} else if ($dnsupdate['keytype'] == "user") {
1885
					$flags = 0;
1886
					$proto = 2;
1887
				}
1888

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

    
1893
				/* generate update instructions */
1894
				$upinst = "";
1895
				if (!empty($dnsupdate['server']))
1896
					$upinst .= "server {$dnsupdate['server']}\n";
1897
				$upinst .= "update delete {$dnsupdate['host']} A\n";
1898
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
1899
				$upinst .= "\n";	/* mind that trailing newline! */
1900

    
1901
				@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
1902
				unset($upinst);
1903

    
1904
				/* invoke nsupdate */
1905
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
1906
				if (isset($dnsupdate['usetcp']))
1907
					$cmd .= " -v";
1908
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
1909

    
1910
				mwexec_bg($cmd);
1911
				unset($cmd);
1912
			}
1913
		}
1914
	}
1915

    
1916
	return 0;
1917
}
1918

    
1919
/* configure cron service */
1920
function configure_cron() {
1921
	global $g, $config;
1922

    
1923
	conf_mount_rw();
1924
	/* preserve existing crontab entries */
1925
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1926

    
1927
	for ($i = 0; $i < count($crontab_contents); $i++) {
1928
		$cron_item =& $crontab_contents[$i];
1929
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
1930
			array_splice($crontab_contents, $i - 1);
1931
			break;
1932
		}
1933
	}
1934
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
1935

    
1936

    
1937
	if (is_array($config['cron']['item'])) {
1938
		$crontab_contents .= "#\n";
1939
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
1940
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
1941
		$crontab_contents .= "#\n";
1942

    
1943
		foreach ($config['cron']['item'] as $item) {
1944
			$crontab_contents .= "\n{$item['minute']}\t";
1945
			$crontab_contents .= "{$item['hour']}\t";
1946
			$crontab_contents .= "{$item['mday']}\t";
1947
			$crontab_contents .= "{$item['month']}\t";
1948
			$crontab_contents .= "{$item['wday']}\t";
1949
			$crontab_contents .= "{$item['who']}\t";
1950
			$crontab_contents .= "{$item['command']}";
1951
		}
1952

    
1953
		$crontab_contents .= "\n#\n";
1954
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
1955
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
1956
		$crontab_contents .= "#\n\n";
1957
	}
1958

    
1959
	/* please maintain the newline at the end of file */
1960
	file_put_contents("/etc/crontab", $crontab_contents);
1961
	unset($crontab_contents);
1962

    
1963
	/* do a HUP kill to force sync changes */
1964
	exec('/bin/pkill -HUP cron');
1965

    
1966
	conf_mount_ro();
1967
}
1968

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

    
1992
function upnp_start() {
1993
	global $config;
1994

    
1995
	if(!isset($config['installedpackages']['miniupnpd']['config']))
1996
		return;
1997

    
1998
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1999
		echo gettext("Starting UPnP service... ");
2000
		require_once('/usr/local/pkg/miniupnpd.inc');
2001
		sync_package_miniupnpd();
2002
		echo "done.\n";
2003
	}
2004
}
2005

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

    
2009
	$is_installed = false;
2010

    
2011
	if (!is_array($config['cron']))
2012
		$config['cron'] = array();
2013
	if (!is_array($config['cron']['item']))
2014
		$config['cron']['item'] = array();
2015

    
2016
	$x=0;
2017
	foreach($config['cron']['item'] as $item) {
2018
		if(strstr($item['command'], $command)) {
2019
			$is_installed = true;
2020
			break;
2021
		}
2022
		$x++;
2023
	}
2024

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

    
2050
?>
(49-49/66)