Project

General

Profile

Download (71.5 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/local/sbin/dnsmasq
36
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/miniupnpd	/usr/sbin/radvd
37
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcleases6	/usr/sbin/bsnmpd
38
	pfSense_MODULE:	utils
39
*/
40

    
41
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-v6 he-net-tunnelbroker selfhost route53 cloudflare custom custom-v6 eurodns');
42
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 (v6),HE.net Tunnelbroker,SelfHost,Route 53,CloudFlare,Custom,Custom (v6),Euro Dns');
43

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

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

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

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

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

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

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

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

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

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

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

    
95
		$realif = get_real_interface($dhcpv6if, "inet6");
96
		if (isset($radvdifs[$realif]))
97
			continue;
98

    
99
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
100
		if (!is_ipaddrv6($ifcfgipv6))
101
			continue;
102

    
103
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
104
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
105
		$radvdifs[$realif] = $realif;
106

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

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

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

    
207
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
208
	foreach ($Iflist as $if => $ifdescr) {
209
		if(!isset($config['interfaces'][$if]['track6-interface']))
210
			continue;
211
		if(!isset($config['interfaces'][$if]['enable']))
212
			continue;
213
		$trackif = $config['interfaces'][$if]['track6-interface'];
214
		if (empty($config['interfaces'][$trackif]))
215
			continue;
216

    
217
		$realif = get_real_interface($if, "inet6");
218
		/* prevent duplicate entries, manual overrides */
219
		if (isset($radvdifs[$realif]))
220
			continue;
221

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

    
226
		$ifcfgsnv6 = get_interface_subnetv6($if);
227
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
228
		$radvdifs[$realif] = $realif;
229

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

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

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

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

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

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

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

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

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

    
331
function services_dhcpdv4_configure() {
332
	global $config, $g;
333
	$need_ddns_updates = false;
334
	$ddns_zones = array();
335

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

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

    
344
	/* kill any running dhcpd */
345
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
346
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
347

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

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

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

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

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

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

    
399
	$dhcpdconf = <<<EOD
400

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

    
412
EOD;
413

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

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

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

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

    
437
		interfaces_staticarp_configure($dhcpif);
438

    
439
		if (!isset($dhcpifconf['enable']))
440
			continue;
441

    
442
		if($dhcpifconf['failover_peerip'] <> "") {
443
			$intip = get_interface_ip($dhcpif);
444
			/*
445
			 *    yep, failover peer is defined.
446
			 *    does it match up to a defined vip?
447
			 */
448
			$skew = 110;
449
			if(is_array($config['virtualip']['vip'])) {
450
				foreach ($config['virtualip']['vip'] as $vipent) {
451
					if($vipent['interface'] == $dhcpif) {
452
						$carp_nw = gen_subnet($vipent['subnet'], $vipent['subnet_bits']);
453
						if (ip_in_subnet($dhcpifconf['failover_peerip'], "{$carp_nw}/{$vipent['subnet_bits']}")) {
454
							/* this is the interface! */
455
							if(is_numeric($vipent['advskew']) && (intval($vipent['advskew']) < 20)) {
456
								$skew = 0;
457
								break;
458
							}
459
						}
460
					}
461
				}
462
			} else {
463
				log_error(gettext("Warning!  DHCP Failover setup and no CARP virtual IP's defined!"));
464
			}
465
			if($skew > 10) {
466
				$type = "secondary";
467
				$dhcpdconf_pri  = "mclt 600;\n";
468
				$my_port = "520";
469
				$peer_port = "519";
470
			} else {
471
				$my_port = "519";
472
				$peer_port = "520";
473
				$type = "primary";
474
				$dhcpdconf_pri  = "split 128;\n";
475
				$dhcpdconf_pri .= "  mclt 600;\n";
476
			}
477

    
478
			if (is_ipaddrv4($intip)) {
479
			$dhcpdconf .= <<<EOPP
480
failover peer "dhcp_{$dhcpif}" {
481
  {$type};
482
  address {$intip};
483
  port {$my_port};
484
  peer address {$dhcpifconf['failover_peerip']};
485
  peer port {$peer_port};
486
  max-response-delay 10;
487
  max-unacked-updates 10;
488
  {$dhcpdconf_pri}
489
  load balance max seconds 3;
490
}
491

    
492
EOPP;
493
			}
494
		}
495
	}
496

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

    
499
		$newzone = array();
500
		$ifcfg = $config['interfaces'][$dhcpif];
501

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

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

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

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

    
522
		$dnscfg = "";
523

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

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

    
532
		if (isset($dhcpifconf['ddnsupdate'])) {
533
			$need_ddns_updates = true;
534
			$newzone = array();
535
			if($dhcpifconf['ddnsdomain'] <> "") {
536
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
537
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
538
			} else {
539
				$newzone['domain-name'] = $config['system']['domain'];
540
			}
541
			$revsubnet = explode(".", $subnet);
542
			$revsubnet = array_reverse($revsubnet);
543
			foreach ($revsubnet as $octet) {
544
				if ($octet != "0")
545
					break;
546
				array_shift($revsubnet);
547
			}
548
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
549
		}
550

    
551
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
552
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
553
			if ($newzone['domain-name'])
554
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
555
		} else if (isset($config['dnsmasq']['enable'])) {
556
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
557
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0]))
558
				$newzone['dns-servers'] = $syscfg['dnsserver'];
559
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
560
			$dnscfg .= "	option domain-name-servers " . join(",", $syscfg['dnsserver']) . ";";
561
			if ($newzone['domain-name'])
562
				$newzone['dns-servers'] = $syscfg['dnsserver'];
563
		}
564

    
565
		/* Create classes - These all contain comma separated lists. Join them into one 
566
		   big comma separated string then split them all up. */
567
		$all_mac_strings = array();
568
		if (is_array($dhcpifconf['pool'])) {
569
			foreach($all_pools as $poolconf) {
570
				$all_mac_strings[] = $poolconf['mac_allow'];
571
				$all_mac_strings[] = $poolconf['mac_deny'];
572
			}
573
		}
574
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
575
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
576
		$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
577
		foreach ($all_mac_list as $mac) {
578
			if (empty($mac))
579
				continue;
580
			$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
581
			// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
582
			$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
583
			$dhcpdconf .= '}' . "\n";
584
		}
585

    
586
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
587

    
588
// Setup pool options
589
		foreach($all_pools as $poolconf) {
590
			$dhcpdconf .= "	pool {\n";
591
			/* is failover dns setup? */
592
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
593
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
594
				if($poolconf['dnsserver'][1] <> "")
595
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
596
				$dhcpdconf .= ";\n";
597
			}
598

    
599
			/* allow/deny MACs */
600
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
601
			foreach ($mac_allow_list as $mac) {
602
				if (empty($mac))
603
					continue;
604
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
605
			}
606
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
607
			foreach ($mac_deny_list as $mac) {
608
				if (empty($mac))
609
					continue;
610
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
611
			}
612

    
613
			if($poolconf['failover_peerip'] <> "")
614
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
615

    
616
			if (isset($poolconf['denyunknown']))
617
			   $dhcpdconf .= "		deny unknown-clients;\n";
618

    
619
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
620
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
621

    
622
			if($dhcpifconf['failover_peerip'] <> "") {
623
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
624
			}
625

    
626
			$pdnscfg = "";
627

    
628
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
629
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
630
			}
631

    
632
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
633
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
634
			}
635

    
636
			if (isset($poolconf['ddnsupdate'])) {
637
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
638
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
639
				$pdnscfg .= "		ddns-update-style interim;\n";
640
			}
641

    
642
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
643
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
644
			}
645
			$dhcpdconf .= "{$pdnscfg}";
646

    
647
			// default-lease-time
648
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
649
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
650

    
651
			// max-lease-time
652
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
653
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
654

    
655
			// netbios-name*
656
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
657
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
658
				$dhcpdconf .= "		option netbios-node-type 8;\n";
659
			}
660

    
661
			// ntp-servers
662
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
663
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
664

    
665
			// tftp-server-name
666
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
667
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
668

    
669
			// ldap-server
670
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
671
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
672

    
673
			// net boot information
674
			if(isset($poolconf['netboot'])) {
675
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
676
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
677
				}
678
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
679
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
680
				}
681
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
682
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
683
				}
684
			}
685
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
686
			$dhcpdconf .= "	}\n\n";
687
		}
688
// End of settings inside pools
689

    
690
		if ($dhcpifconf['gateway']) {
691
			$routers = $dhcpifconf['gateway'];
692
			$add_routers = true;
693
		} else {
694
			$routers = $ifcfgip;
695
		}
696
		if($add_routers)
697
			$dhcpdconf .= "	option routers {$routers};\n";
698

    
699
		$dhcpdconf .= <<<EOD
700
$dnscfg
701

    
702
EOD;
703
    		// default-lease-time
704
		if ($dhcpifconf['defaultleasetime'])
705
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
706

    
707
		// max-lease-time
708
		if ($dhcpifconf['maxleasetime'])
709
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
710

    
711
		// netbios-name*
712
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
713
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
714
			$dhcpdconf .= "	option netbios-node-type 8;\n";
715
		}
716

    
717
		// ntp-servers
718
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
719
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
720

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

    
725
		// Handle option, number rowhelper values
726
		$dhcpdconf .= "\n";
727
		if($dhcpifconf['numberoptions']['item']) {
728
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
729
				if(empty($item['type']) || $item['type'] == "text")
730
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
731
				else
732
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
733
			}
734
		}
735

    
736
		// ldap-server
737
		if ($dhcpifconf['ldap'] <> "")
738
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
739

    
740
		// net boot information
741
		if(isset($dhcpifconf['netboot'])) {
742
			if ($dhcpifconf['nextserver'] <> "") {
743
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
744
			}
745
			if ($dhcpifconf['filename'] <> "") {
746
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
747
			}
748
			if ($dhcpifconf['rootpath'] <> "") {
749
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
750
			}
751
		}
752

    
753
		$dhcpdconf .= <<<EOD
754
}
755

    
756
EOD;
757

    
758
		/* add static mappings */
759
		if (is_array($dhcpifconf['staticmap'])) {
760

    
761
			$i = 0;
762
			foreach ($dhcpifconf['staticmap'] as $sm) {
763
				$dhcpdconf .= "host s_{$dhcpif}_{$i} {\n";
764

    
765
                if ($sm['mac'])
766
                    $dhcpdconf .= "        hardware ethernet {$sm['mac']};\n";
767

    
768
                if ($sm['cid'])
769
                    $dhcpdconf .= "        option dhcp-client-identifier \"{$sm['cid']}\";\n";
770

    
771
				if ($sm['ipaddr'])
772
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
773

    
774
				if ($sm['hostname']) {
775
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
776
					$dhhostname = str_replace(".", "_", $dhhostname);
777
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
778
				}
779
				if ($sm['filename'])
780
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
781

    
782
				if ($sm['rootpath'])
783
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
784

    
785
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
786
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
787

    
788
				$smdnscfg = "";
789

    
790
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
791
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
792
				}
793

    
794
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
795
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
796
				}
797

    
798
				if (isset($sm['ddnsupdate'])) {
799
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
800
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
801
					$pdnscfg .= "		ddns-update-style interim;\n";
802
				}
803

    
804
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
805
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
806
				}
807
				$dhcpdconf .= "{$smdnscfg}";
808

    
809
				// default-lease-time
810
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
811
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
812

    
813
				// max-lease-time
814
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
815
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
816

    
817
				// netbios-name*
818
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
819
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
820
					$dhcpdconf .= "	option netbios-node-type 8;\n";
821
				}
822

    
823
				// ntp-servers
824
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
825
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
826

    
827
				// tftp-server-name
828
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
829
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
830

    
831
				$dhcpdconf .= "}\n";
832
				$i++;
833
			}
834
		}
835

    
836
		$dhcpdifs[] = get_real_interface($dhcpif);
837
		if ($newzone['domain-name'])
838
			$ddns_zones[] = $newzone;
839
	}
840

    
841
	if ($need_ddns_updates) {
842
		$dhcpdconf .= "ddns-update-style interim;\n";
843
		$dhcpdconf .= "update-static-leases on;\n";
844
		
845
		if (is_array($ddns_zones)) {
846
			$added_zones = array();
847
			foreach ($ddns_zones as $zone) {
848
				if (!is_array($zone) || empty($zone) || !is_array($zone['dns-servers']))
849
					continue;
850
				$primary = $zone['dns-servers'][0];
851
				$secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1];
852
				// Make sure we aren't using any invalid or IPv6 DNS servers.
853
				if (!is_ipaddrv4($primary)) {
854
					if (is_ipaddrv4($secondary)) {
855
						$primary = $secondary;
856
						$secondary = "";
857
					} else {
858
						continue;
859
					}
860
				}
861
				// We don't need to add zones multiple times.
862
				if (!in_array($zone['domain-name'], $added_zones)) {
863
					$dhcpdconf .= "zone {$zone['domain-name']} {\n";
864
					$dhcpdconf .= "	primary {$primary};\n";
865
					if (is_ipaddrv4($secondary))
866
						$dhcpdconf .= "	secondary {$secondary};\n";
867
					$dhcpdconf .= "}\n";
868
					$added_zones[] = $zone['domain-name'];
869
				}
870
				if (!in_array($zone['ptr-domain'], $added_zones)) {
871
					$dhcpdconf .= "zone {$zone['ptr-domain']} {\n";
872
					$dhcpdconf .= "	primary {$primary};\n";
873
					if (is_ipaddrv4($secondary))
874
						$dhcpdconf .= "	secondary {$secondary};\n";
875
					$dhcpdconf .= "}\n";
876
					$added_zones[] = $zone['ptr-domain'];
877
				}
878
			}
879
		}
880
	}
881

    
882
	/* write dhcpd.conf */
883
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
884
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
885
		unset($dhcpdconf);
886
		return 1;
887
	}
888
	unset($dhcpdconf);
889

    
890
	/* create an empty leases database */
891
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
892
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
893

    
894
	/* fire up dhcpd in a chroot */
895
	if (count($dhcpdifs) > 0) {
896
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
897
			join(" ", $dhcpdifs));
898
	}
899

    
900
	if ($g['booting'])
901
		print "done.\n";
902

    
903
	return 0;
904
}
905

    
906
function services_dhcpdv6_configure() {
907
	global $config, $g;
908

    
909
	if($g['services_dhcp_server_enable'] == false)
910
		return;
911

    
912
	if(isset($config['system']['developerspew'])) {
913
		$mt = microtime();
914
		echo "services_dhcpd_configure($if) being called $mt\n";
915
	}
916

    
917
	/* kill any running dhcpd */
918
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
919
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
920
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
921
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
922

    
923
	/* DHCP enabled on any interfaces? */
924
	if (!is_dhcpv6_server_enabled())
925
		return 0;
926

    
927
	if ($g['booting']) {
928
		if ($g['platform'] != "pfSense") {
929
			/* restore the leases, if we have them */
930
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
931
				$dhcprestore = "";
932
				$dhcpreturn = "";
933
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
934
				$dhcprestore = implode(" ", $dhcprestore);
935
				if($dhcpreturn <> 0) {
936
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
937
				}
938
			}
939
		}
940
	}
941

    
942
	$syscfg = $config['system'];
943
	if (!is_array($config['dhcpdv6']))
944
		$config['dhcpdv6'] = array();
945
	$dhcpdv6cfg = $config['dhcpdv6'];
946
	$Iflist = get_configured_interface_list();
947
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
948

    
949

    
950
	if ($g['booting'])
951
		echo "Starting DHCPv6 service...";
952
	else
953
		sleep(1);
954

    
955
	/* we add a fake entry for interfaces that are set to track6 another WAN */
956
	foreach ($Iflist as $ifname) {
957
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
958
			$realif = get_real_interface($ifname, "inet6");
959
			$ifcfgipv6 = get_interface_ipv6($ifname);
960
			if(!is_ipaddrv6($ifcfgipv6))
961
				continue;
962
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
963
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
964
			$trackcfg = $config['interfaces'][$trackifname];
965
			$pdlen = calculate_ipv6_delegation_length($trackifname);
966
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
967
			$dhcpdv6cfg[$ifname] = array();
968
			$dhcpdv6cfg[$ifname]['enable'] = true;
969
			/* range */
970
			$ifcfgipv6arr[7] = "1000";
971
			$dhcpdv6cfg[$ifname]['range'] = array();
972
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
973
			$ifcfgipv6arr[7] = "2000";
974
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
975
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
976
			if($pdlen > 2) {
977
				$pdlenmax = $pdlen;
978
				$pdlenhalf = $pdlenmax -1;
979
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
980
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
981
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
982

    
983
				/* set the delegation start to half the current address block */
984
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
985
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
986

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

    
991
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
992
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
993
			}
994
		}
995
	}
996

    
997
	$custoptionsv6 = "";
998
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
999
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
1000
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1001
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
1002
			}
1003
		}
1004
	}
1005

    
1006
	$dhcpdv6conf = <<<EOD
1007

    
1008
option domain-name "{$syscfg['domain']}";
1009
option ldap-server code 95 = text;
1010
option domain-search-list code 119 = text;
1011
{$custoptions}
1012
default-lease-time 7200;
1013
max-lease-time 86400;
1014
log-facility local7;
1015
ddns-update-style none;
1016
one-lease-per-client true;
1017
deny duplicates;
1018
ping-check true;
1019

    
1020
EOD;
1021

    
1022
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1023
		$dhcpdv6conf .= "authoritative;\n";
1024

    
1025
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1026
		$dhcpdv6conf .= "always-broadcast on\n";
1027

    
1028
	$dhcpdv6ifs = array();
1029

    
1030
	$dhcpv6num = 0;
1031
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1032

    
1033
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1034

    
1035
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1036
			continue;
1037
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1038
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1039
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1040

    
1041
		if ($is_olsr_enabled == true) {
1042
			if($dhcpv6ifconf['netmask'])
1043
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1044
		}
1045

    
1046
		$dnscfgv6 = "";
1047

    
1048
		if ($dhcpv6ifconf['domain']) {
1049
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1050
		}
1051

    
1052
    		if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1053
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1054
    		}
1055

    
1056
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1057
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1058
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1059
			}
1060
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1061
		}
1062

    
1063
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1064
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1065
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1066
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1067
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1068
			$dns_arrv6 = array();
1069
			foreach($syscfg['dnsserver'] as $dnsserver) {
1070
				if (is_ipaddrv6($dnsserver)) {
1071
					$dns_arrv6[] = $dnsserver;
1072
				}
1073
			}
1074
			if(!empty($dns_arrv6))
1075
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1076
		}
1077

    
1078
		if (is_ipaddrv6($ifcfgipv6)) {
1079
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1080
		} else {
1081
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1082
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1083
		}
1084
		$dhcpdv6conf .= " {\n";
1085

    
1086
		if (isset($dhcpv6ifconf['denyunknown']))
1087
		   $dhcpdv6conf .= "		deny unknown-clients;\n";
1088

    
1089
		$dhcpdv6conf .= <<<EOD
1090
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1091
$dnscfgv6
1092

    
1093
EOD;
1094

    
1095
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1096
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1097
		}
1098
    		// default-lease-time
1099
		if ($dhcpv6ifconf['defaultleasetime'])
1100
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1101

    
1102
		// max-lease-time
1103
		if ($dhcpv6ifconf['maxleasetime'])
1104
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1105

    
1106
		// ntp-servers
1107
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1108
			$ntpservers = array();
1109
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1110
				if(is_ipaddrv6($ntpserver))
1111
					$ntpservers[] = $ntpserver;
1112
			}
1113
			if(count($ntpservers) > 0 )
1114
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1115
		}
1116
		// tftp-server-name
1117
		/* Needs ISC DHCPD support
1118
		 if ($dhcpv6ifconf['tftp'] <> "")
1119
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1120
		*/
1121

    
1122
		// Handle option, number rowhelper values
1123
		$dhcpdv6conf .= "\n";
1124
		if ($dhcpv6ifconf['numberoptions']['item']) {
1125
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1126
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1127
			}
1128
		}
1129

    
1130
		// ldap-server
1131
		if ($dhcpv6ifconf['ldap'] <> "")
1132
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1133

    
1134
		// net boot information
1135
		if(isset($dhcpv6ifconf['netboot'])) {
1136
			if ($dhcpv6ifconf['nextserver'] <> "") {
1137
				$dhcpdv6conf .= "	next-server {$dhcpv6ifconf['nextserver']};\n";
1138
			}
1139
			if ($dhcpv6ifconf['filename'] <> "") {
1140
				$dhcpdv6conf .= "	filename \"{$dhcpv6ifconf['filename']}\";\n";
1141
			}
1142
			if ($dhcpv6ifconf['rootpath'] <> "") {
1143
				$dhcpdv6conf .= "	option root-path \"{$dhcpv6ifconf['rootpath']}\";\n";
1144
			}
1145
		}
1146

    
1147
		$dhcpdv6conf .= "}\n";
1148

    
1149
		/* add static mappings */
1150
		/* Needs to use DUID */
1151
		if (is_array($dhcpv6ifconf['staticmap'])) {
1152
			$i = 0;
1153
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1154
				$dhcpdv6conf .= <<<EOD
1155
host s_{$dhcpv6if}_{$i} {
1156
	host-identifier option dhcp6.client-id {$sm['duid']};
1157

    
1158
EOD;
1159
				if ($sm['ipaddrv6'])
1160
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1161

    
1162
				if ($sm['hostname']) {
1163
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1164
					$dhhostname = str_replace(".", "_", $dhhostname);
1165
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1166
				}
1167
				if ($sm['filename'])
1168
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1169

    
1170
				if ($sm['rootpath'])
1171
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1172

    
1173
				$dhcpdv6conf .= "}\n";
1174
				$i++;
1175
			}
1176
		}
1177

    
1178
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1179
			if(preg_match("/poes/si", $dhcpv6if)) {
1180
				/* magic here */
1181
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1182
			} else {
1183
				$realif = get_real_interface($dhcpv6if, "inet6");
1184
				if (stristr("$realif", "bridge")) {
1185
					$mac = get_interface_mac($realif);
1186
					$v6address = generate_ipv6_from_mac($mac);
1187
					/* Create link local address for bridges */
1188
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1189
				}
1190
				$realif = escapeshellcmd($realif);
1191
				$dhcpdv6ifs[] = $realif;
1192
			}
1193
		}
1194
	}
1195

    
1196
	/* write dhcpdv6.conf */
1197
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1198
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1199
		if ($g['booting'])
1200
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1201
		unset($dhcpdv6conf);
1202
		return 1;
1203
	}
1204
	unset($dhcpdv6conf);
1205

    
1206
	/* create an empty leases v6 database */
1207
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1208
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1209

    
1210
	/* fire up dhcpd in a chroot */
1211
	if (count($dhcpdv6ifs) > 0) {
1212
		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 " .
1213
			join(" ", $dhcpdv6ifs));
1214
		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");
1215
	}
1216
	if ($g['booting'])
1217
		print gettext("done.") . "\n";
1218

    
1219
	return 0;
1220
}
1221

    
1222
function services_igmpproxy_configure() {
1223
        global $config, $g;
1224

    
1225
        /* kill any running igmpproxy */
1226
        killbyname("igmpproxy");
1227

    
1228
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1229
		return 1;
1230

    
1231
        $iflist = get_configured_interface_list();
1232

    
1233
        $igmpconf = <<<EOD
1234

    
1235
##------------------------------------------------------
1236
## Enable Quickleave mode (Sends Leave instantly)
1237
##------------------------------------------------------
1238
quickleave
1239

    
1240
EOD;
1241

    
1242
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1243
                unset($iflist[$igmpcf['ifname']]);
1244
                $realif = get_real_interface($igmpcf['ifname']);
1245
                if (empty($igmpcf['threshold']))
1246
                        $threshld = 1;
1247
                else
1248
                        $threshld = $igmpcf['threshold'];
1249
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1250

    
1251
                if ($igmpcf['address'] <> "") {
1252
                        $item = explode(" ", $igmpcf['address']);
1253
                        foreach($item as $iww)
1254
                                $igmpconf .= "altnet {$iww}\n";
1255
                }
1256
                $igmpconf .= "\n";
1257
        }
1258
        foreach ($iflist as $ifn) {
1259
                $realif = get_real_interface($ifn);
1260
                $igmpconf .= "phyint {$realif} disabled\n";
1261
        }
1262
	$igmpconf .= "\n";
1263

    
1264
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1265
        if (!$igmpfl) {
1266
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1267
                return;
1268
        }
1269
        fwrite($igmpfl, $igmpconf);
1270
        fclose($igmpfl);
1271
	unset($igmpconf);
1272

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

    
1277
        return 0;
1278
}
1279

    
1280
function services_dhcrelay_configure() {
1281
	global $config, $g;
1282
	if ($g['platform'] == 'jail')
1283
		return;
1284
	if(isset($config['system']['developerspew'])) {
1285
		$mt = microtime();
1286
		echo "services_dhcrelay_configure() being called $mt\n";
1287
	}
1288

    
1289
	/* kill any running dhcrelay */
1290
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1291

    
1292
	$dhcrelaycfg =& $config['dhcrelay'];
1293

    
1294
	/* DHCPRelay enabled on any interfaces? */
1295
	if (!isset($dhcrelaycfg['enable']))
1296
		return 0;
1297

    
1298
	if ($g['booting'])
1299
		echo gettext("Starting DHCP relay service...");
1300
	else
1301
		sleep(1);
1302

    
1303
	$iflist = get_configured_interface_list();
1304

    
1305
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1306
	foreach ($dhcifaces as $dhcrelayif) {
1307
		if (!isset($iflist[$dhcrelayif]) ||
1308
			link_interface_to_bridge($dhcrelayif))
1309
			continue;
1310

    
1311
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1312
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1313
	}
1314

    
1315
	/*
1316
	 * In order for the relay to work, it needs to be active
1317
	 * on the interface in which the destination server sits.
1318
	 */
1319
	$srvips = explode(",", $dhcrelaycfg['server']);
1320
	foreach ($srvips as $srcidx => $srvip) {
1321
		unset($destif);
1322
		foreach ($iflist as $ifname) {
1323
			$subnet = get_interface_ip($ifname);
1324
			if (!is_ipaddr($subnet))
1325
				continue;
1326
			$subnet .=  "/" . get_interface_subnet($ifname);
1327
			if (ip_in_subnet($srvip, $subnet)) {
1328
				$destif = get_real_interface($ifname);
1329
				break;
1330
			}
1331
		}
1332
		if (!isset($destif)) {
1333
			foreach (get_staticroutes() as $rtent) {
1334
				if (ip_in_subnet($srvip, $rtent['network'])) {
1335
					$a_gateways = return_gateways_array(true);
1336
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1337
					break;
1338
				}
1339
			}
1340
		}
1341

    
1342
		if (!isset($destif)) {
1343
			/* Create a array from the existing route table */
1344
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1345
        		array_shift($route_str);
1346
        		array_shift($route_str);
1347
        		array_shift($route_str);
1348
        		array_shift($route_str);
1349
        		$route_arr = array();
1350
        		foreach($route_str as $routeline) {
1351
				$items = preg_split("/[ ]+/i", $routeline);
1352
				if (is_subnetv4($items[0])) {
1353
					$subnet = $items[0];
1354
				} elseif (is_ipaddrv4($items[0])) {
1355
					$subnet = "{$items[0]}/32";
1356
				} else {
1357
					// Not a subnet or IP address, skip to the next line.
1358
					continue;
1359
				}
1360
				if (ip_in_subnet($srvip, $subnet)) {
1361
					$destif = trim($items[6]);
1362
					break;
1363
				}
1364
			}
1365
		}
1366

    
1367
		if (!isset($destif)) {
1368
			if (is_array($config['gateways']['gateway_item'])) {
1369
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1370
					if (isset($gateway['defaultgw'])) {
1371
						$a_gateways = return_gateways_array(true);
1372
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1373
						break;
1374
					}
1375
				}
1376
			} else
1377
				$destif = get_real_interface("wan");
1378
		}
1379

    
1380
		if (!empty($destif))
1381
			$dhcrelayifs[] = $destif;
1382
	}
1383
	$dhcrelayifs = array_unique($dhcrelayifs);
1384

    
1385
	/* fire up dhcrelay */
1386
	if (empty($dhcrelayifs)) {
1387
		log_error("No suitable interface found for running dhcrelay!");
1388
		return; /* XXX */
1389
	}
1390

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

    
1393
	if (isset($dhcrelaycfg['agentoption']))
1394
		$cmd .=  " -a -m replace";
1395

    
1396
	$cmd .= " " . implode(" ", $srvips);
1397
	mwexec($cmd);
1398
	unset($cmd);
1399

    
1400
	return 0;
1401
}
1402

    
1403
function services_dhcrelay6_configure() {
1404
	global $config, $g;
1405
	if ($g['platform'] == 'jail')
1406
		return;
1407
	if(isset($config['system']['developerspew'])) {
1408
		$mt = microtime();
1409
		echo "services_dhcrelay6_configure() being called $mt\n";
1410
	}
1411

    
1412
	/* kill any running dhcrelay */
1413
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1414

    
1415
	$dhcrelaycfg =& $config['dhcrelay6'];
1416

    
1417
	/* DHCPv6 Relay enabled on any interfaces? */
1418
	if (!isset($dhcrelaycfg['enable']))
1419
		return 0;
1420

    
1421
	if ($g['booting'])
1422
		echo gettext("Starting DHCPv6 relay service...");
1423
	else
1424
		sleep(1);
1425

    
1426
	$iflist = get_configured_interface_list();
1427

    
1428
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1429
	foreach ($dhcifaces as $dhcrelayif) {
1430
		if (!isset($iflist[$dhcrelayif]) ||
1431
			link_interface_to_bridge($dhcrelayif))
1432
			continue;
1433

    
1434
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1435
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1436
	}
1437
	$dhcrelayifs = array_unique($dhcrelayifs);
1438

    
1439
	/*
1440
	 * In order for the relay to work, it needs to be active
1441
	 * on the interface in which the destination server sits.
1442
	 */
1443
	$srvips = explode(",", $dhcrelaycfg['server']);
1444
        $srvifaces = array();
1445
	foreach ($srvips as $srcidx => $srvip) {
1446
		unset($destif);
1447
		foreach ($iflist as $ifname) {
1448
			$subnet = get_interface_ipv6($ifname);
1449
			if (!is_ipaddrv6($subnet))
1450
				continue;
1451
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1452
			if (ip_in_subnet($srvip, $subnet)) {
1453
				$destif = get_real_interface($ifname);
1454
				break;
1455
			}
1456
		}
1457
		if (!isset($destif)) {
1458
			if (is_array($config['staticroutes']['route'])) {
1459
				foreach ($config['staticroutes']['route'] as $rtent) {
1460
					if (ip_in_subnet($srvip, $rtent['network'])) {
1461
						$a_gateways = return_gateways_array(true);
1462
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1463
						break;
1464
					}
1465
				}
1466
			}
1467
		}
1468

    
1469
		if (!isset($destif)) {
1470
			/* Create a array from the existing route table */
1471
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1472
        		array_shift($route_str);
1473
        		array_shift($route_str);
1474
        		array_shift($route_str);
1475
        		array_shift($route_str);
1476
        		$route_arr = array();
1477
        		foreach($route_str as $routeline) {
1478
                		$items = preg_split("/[ ]+/i", $routeline);
1479
				if (ip_in_subnet($srvip, $items[0])) {
1480
					$destif = trim($items[6]);
1481
					break;
1482
				}
1483
        		}
1484
		}
1485

    
1486
		if (!isset($destif)) {
1487
			if (is_array($config['gateways']['gateway_item'])) {
1488
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1489
					if (isset($gateway['defaultgw'])) {
1490
						$a_gateways = return_gateways_array(true);
1491
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
1492
						break;
1493
					}
1494
				}
1495
			} else
1496
				$destif = get_real_interface("wan");
1497
		}
1498

    
1499
		if (!empty($destif)) {
1500
			$srvifaces[] = "{$srvip}%{$destif}";
1501
		}
1502
	}
1503

    
1504
	/* fire up dhcrelay */
1505
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1506
		log_error("No suitable interface found for running dhcrelay -6!");
1507
		return; /* XXX */
1508
	}
1509

    
1510
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1511
	foreach ($dhcrelayifs as $dhcrelayif) {
1512
		$cmd .= " -l {$dhcrelayif}";
1513
	}
1514
	foreach ($srvifaces as $srviface) {
1515
		$cmd .= " -u \"{$srviface}\"";
1516
	}
1517
	mwexec($cmd);
1518
	unset($cmd);
1519

    
1520
	return 0;
1521
}
1522

    
1523
function services_dyndns_configure_client($conf) {
1524

    
1525
	if (!isset($conf['enable']))
1526
		return;
1527

    
1528
	/* load up the dyndns.class */
1529
	require_once("dyndns.class");
1530

    
1531
	$dns = new updatedns($dnsService = $conf['type'],
1532
		$dnsHost = $conf['host'],
1533
		$dnsUser = $conf['username'],
1534
		$dnsPass = $conf['password'],
1535
		$dnsWilcard = $conf['wildcard'],
1536
		$dnsMX = $conf['mx'],
1537
		$dnsIf = "{$conf['interface']}",
1538
		$dnsBackMX = NULL,
1539
		$dnsServer = NULL,
1540
		$dnsPort = NULL,
1541
		$dnsUpdateURL = "{$conf['updateurl']}",
1542
		$forceUpdate = $conf['force'],
1543
		$dnsZoneID=$conf['zoneid'],
1544
		$dnsTTL=$conf['ttl'],
1545
		$dnsResultMatch = "{$conf['resultmatch']}",
1546
		$dnsRequestIf = "{$conf['requestif']}",
1547
		$dnsID = "{$conf['id']}",
1548
		$dnsVerboseLog = $conf['verboselog'],
1549
		$curlIpresolveV4 = $conf['curl_ipresolve_v4'],
1550
		$curlSslVerifypeer = $conf['curl_ssl_verifypeer']);
1551
}
1552

    
1553
function services_dyndns_configure($int = "") {
1554
	global $config, $g;
1555
	if(isset($config['system']['developerspew'])) {
1556
		$mt = microtime();
1557
		echo "services_dyndns_configure() being called $mt\n";
1558
	}
1559

    
1560
	$dyndnscfg = $config['dyndnses']['dyndns'];
1561
	$gwgroups = return_gateway_groups_array();
1562
	if (is_array($dyndnscfg)) {
1563
		if ($g['booting'])
1564
			echo gettext("Starting DynDNS clients...");
1565

    
1566
		foreach ($dyndnscfg as $dyndns) {
1567
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1568
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1569
				$dyndns['curl_ipresolve_v4'] = isset($dyndns['curl_ipresolve_v4']);
1570
				$dyndns['curl_ssl_verifypeer'] = isset($dyndns['curl_ssl_verifypeer']);
1571
				services_dyndns_configure_client($dyndns);
1572
				sleep(1);
1573
			}
1574
		}
1575

    
1576
		if ($g['booting'])
1577
			echo gettext("done.") . "\n";
1578
	}
1579

    
1580
	return 0;
1581
}
1582

    
1583
function dyndnsCheckIP($int) {
1584
	global $config;
1585
	$ip_address = get_interface_ip($int);
1586
	if (is_private_ip($ip_address)) {
1587
		$gateways_status = return_gateways_status(true);
1588
		// If the gateway for this interface is down, then the external check cannot work.
1589
		// Avoid the long wait for the external check to timeout.
1590
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1591
			return "down";
1592
		$hosttocheck = "checkip.dyndns.org";
1593
		$checkip = gethostbyname($hosttocheck);
1594
		$ip_ch = curl_init("http://{$checkip}");
1595
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1596
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1597
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1598
		$ip_result_page = curl_exec($ip_ch);
1599
		curl_close($ip_ch);
1600
		$ip_result_decoded = urldecode($ip_result_page);
1601
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1602
		$ip_address = trim($matches[1]);
1603
	}
1604
	return $ip_address;
1605
}
1606

    
1607
function services_dnsmasq_configure() {
1608
	global $config, $g;
1609
	$return = 0;
1610

    
1611
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1612
	$standard_args = array(
1613
		"dns-forward-max" => "--dns-forward-max=5000",
1614
		"cache-size" => "--cache-size=10000",
1615
		"local-ttl" => "--local-ttl=1"
1616
	);
1617

    
1618

    
1619
	if(isset($config['system']['developerspew'])) {
1620
		$mt = microtime();
1621
		echo "services_dnsmasq_configure() being called $mt\n";
1622
	}
1623

    
1624
	/* kill any running dnsmasq */
1625
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1626
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1627

    
1628
	if (isset($config['dnsmasq']['enable'])) {
1629

    
1630
		if ($g['booting'])
1631
			echo gettext("Starting DNS forwarder...");
1632
		else
1633
			sleep(1);
1634

    
1635
		/* generate hosts file */
1636
		if(system_hosts_generate()!=0)
1637
			$return = 1;
1638

    
1639
		$args = "";
1640

    
1641
		if (isset($config['dnsmasq']['regdhcp'])) {
1642
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1643
		}
1644

    
1645
		/* Setup listen port, if non-default */
1646
		if (is_port($config['dnsmasq']['port']))
1647
			$args .= " --port={$config['dnsmasq']['port']} ";
1648

    
1649
		$listen_addresses = "";
1650
		if(isset($config['dnsmasq']['interface'])) {
1651
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1652
			foreach ($interfaces as $interface) {
1653
				if (is_ipaddrv4($interface)) {
1654
					$listen_addresses .= " --listen-address={$interface} ";
1655
				} else if (is_ipaddrv6($interface)) {
1656
					/*
1657
					 * XXX: Since dnsmasq does not support link-local address
1658
					 * with scope specified. These checks are being done.
1659
					 */
1660
					if (is_linklocal($interface) && strstr($interface, "%")) {
1661
						$tmpaddrll6 = explode("%", $interface);
1662
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1663
					} else 
1664
						$listen_addresses .= " --listen-address={$interface} ";
1665
				} else {
1666
					$if = get_real_interface($interface);
1667
					if (does_interface_exist($if)) {
1668
						$laddr = find_interface_ip($if);
1669
						if (is_ipaddrv4($laddr))
1670
							$listen_addresses .= " --listen-address={$laddr} ";
1671
						$laddr6 = find_interface_ipv6($if);
1672
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
1673
							/*
1674
							 * XXX: Since dnsmasq does not support link-local address
1675
							 * with scope specified. These checks are being done.
1676
							 */
1677
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
1678
								$tmpaddrll6 = explode("%", $laddr6);
1679
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1680
							} else
1681
								$listen_addresses .= " --listen-address={$laddr6} ";
1682
						}
1683
					}
1684
				}
1685
			}
1686
			if (!empty($listen_addresses)) {
1687
				$args .= " {$listen_addresses} ";
1688
				if (isset($config['dnsmasq']['strictbind']))
1689
					$args .= " --bind-interfaces ";
1690
			}
1691
		}
1692

    
1693
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
1694
		/* If any of these are duplicated by a user-specified domain override (e.g. 10.in-addr.arpa) then */
1695
		/* the user-specified entry made later on the command line below will be the one that is effective. */
1696
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1697
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1698
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1699
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1700
			$args .= " --server=/10.in-addr.arpa/ ";
1701
			$args .= " --server=/168.192.in-addr.arpa/ ";
1702
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1703
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1704
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1705
			}
1706
		}
1707

    
1708
		/* Setup forwarded domains */
1709
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1710
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1711
				if ($override['ip'] == "!")
1712
					$override[ip] = "";
1713
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1714
			}
1715
		}
1716

    
1717
		/* Allow DNS Rebind for forwarded domains */
1718
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1719
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1720
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1721
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1722
				}
1723
			}
1724
		}
1725

    
1726
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1727
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1728

    
1729
		if (isset($config['dnsmasq']['strict_order'])) {
1730
			$args .= " --strict-order ";
1731
		}
1732

    
1733
		if (isset($config['dnsmasq']['domain_needed'])) {
1734
			$args .= " --domain-needed ";
1735
		}
1736

    
1737
		if ($config['dnsmasq']['custom_options'])
1738
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1739
				$args .= " --$c";
1740
				$p = explode('=', $c);
1741
				if (array_key_exists($p[0], $standard_args))
1742
					unset($standard_args[$p[0]]);
1743
			}
1744
		$args .= ' ' . implode(' ', array_values($standard_args));
1745

    
1746
		/* run dnsmasq */
1747
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1748
		//log_error("dnsmasq command: {$cmd}");
1749
		mwexec_bg($cmd);
1750
		unset($args);
1751

    
1752
		if ($g['booting'])
1753
			echo gettext("done.") . "\n";
1754
	}
1755

    
1756
	if (!$g['booting']) {
1757
		if(services_dhcpd_configure()!=0)
1758
			$return = 1;
1759
	}
1760

    
1761
	return $return;
1762
}
1763

    
1764
function services_snmpd_configure() {
1765
	global $config, $g;
1766
	if(isset($config['system']['developerspew'])) {
1767
		$mt = microtime();
1768
		echo "services_snmpd_configure() being called $mt\n";
1769
	}
1770

    
1771
	/* kill any running snmpd */
1772
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1773
	sleep(2);
1774
	if(is_process_running("bsnmpd"))
1775
		mwexec("/usr/bin/killall bsnmpd", true);
1776

    
1777
	if (isset($config['snmpd']['enable'])) {
1778

    
1779
		if ($g['booting'])
1780
			echo gettext("Starting SNMP daemon... ");
1781

    
1782
		/* generate snmpd.conf */
1783
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1784
		if (!$fd) {
1785
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1786
			return 1;
1787
		}
1788

    
1789

    
1790
		$snmpdconf = <<<EOD
1791
location := "{$config['snmpd']['syslocation']}"
1792
contact := "{$config['snmpd']['syscontact']}"
1793
read := "{$config['snmpd']['rocommunity']}"
1794

    
1795
EOD;
1796

    
1797
/* No docs on what write strings do there for disable for now.
1798
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1799
		    $snmpdconf .= <<<EOD
1800
# write string
1801
write := "{$config['snmpd']['rwcommunity']}"
1802

    
1803
EOD;
1804
		}
1805
*/
1806

    
1807

    
1808
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1809
		    $snmpdconf .= <<<EOD
1810
# SNMP Trap support.
1811
traphost := {$config['snmpd']['trapserver']}
1812
trapport := {$config['snmpd']['trapserverport']}
1813
trap := "{$config['snmpd']['trapstring']}"
1814

    
1815

    
1816
EOD;
1817
		}
1818

    
1819
		$version = trim(file_get_contents('/etc/version'));
1820
		$platform = trim(file_get_contents('/etc/platform'));
1821
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1822
			$platform = $g['product_name'];
1823
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1824
			" {$version} {$platform} " . php_uname("s") .
1825
			" " . php_uname("r") . " " . php_uname("m");
1826

    
1827
		$snmpdconf .= <<<EOD
1828
system := 1     # pfSense
1829
%snmpd
1830
sysDescr			= "{$sysDescr}"
1831
begemotSnmpdDebugDumpPdus       = 2
1832
begemotSnmpdDebugSyslogPri      = 7
1833
begemotSnmpdCommunityString.0.1 = $(read)
1834

    
1835
EOD;
1836

    
1837
/* No docs on what write strings do there for disable for now.
1838
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1839
		    $snmpdconf .= <<<EOD
1840
begemotSnmpdCommunityString.0.2 = $(write)
1841

    
1842
EOD;
1843
		}
1844
*/
1845

    
1846

    
1847
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1848
		    $snmpdconf .= <<<EOD
1849
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1850
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1851
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1852

    
1853
EOD;
1854
		}
1855

    
1856

    
1857
		$snmpdconf .= <<<EOD
1858
begemotSnmpdCommunityDisable    = 1
1859

    
1860
EOD;
1861

    
1862
		if (isset($config['snmpd']['bindlan'])) {
1863
			$config['snmpd']['bindip'] = 'lan';
1864
			unset($config['snmpd']['bindlan']);
1865
		}
1866
		$bind_to_ip = "0.0.0.0";
1867
		if(isset($config['snmpd']['bindip'])) {
1868
			if (is_ipaddr($config['snmpd']['bindip'])) {
1869
				$bind_to_ip = $config['snmpd']['bindip'];
1870
			} else {
1871
				$if = get_real_interface($config['snmpd']['bindip']);
1872
				if (does_interface_exist($if))
1873
					$bind_to_ip = find_interface_ip($if);
1874
			}
1875
		}
1876

    
1877
		if(is_port( $config['snmpd']['pollport'] )) {
1878
		    $snmpdconf .= <<<EOD
1879
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1880

    
1881
EOD;
1882

    
1883
		}
1884

    
1885
		$snmpdconf .= <<<EOD
1886
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1887
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1888

    
1889
# These are bsnmp macros not php vars.
1890
sysContact      = $(contact)
1891
sysLocation     = $(location)
1892
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1893

    
1894
snmpEnableAuthenTraps = 2
1895

    
1896
EOD;
1897

    
1898
		if (is_array( $config['snmpd']['modules'] )) {
1899
		    if(isset($config['snmpd']['modules']['mibii'])) {
1900
			$snmpdconf .= <<<EOD
1901
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1902

    
1903
EOD;
1904
		    }
1905

    
1906
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1907
			$snmpdconf .= <<<EOD
1908
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1909
%netgraph
1910
begemotNgControlNodeName = "snmpd"
1911

    
1912
EOD;
1913
		    }
1914

    
1915
		    if(isset($config['snmpd']['modules']['pf'])) {
1916
			$snmpdconf .= <<<EOD
1917
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1918

    
1919
EOD;
1920
		    }
1921

    
1922
		    if(isset($config['snmpd']['modules']['hostres'])) {
1923
			$snmpdconf .= <<<EOD
1924
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1925

    
1926
EOD;
1927
		    }
1928
		    if(isset($config['snmpd']['modules']['bridge'])) {
1929
			$snmpdconf .= <<<EOD
1930
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1931
# config must end with blank line
1932

    
1933
EOD;
1934
		    }
1935
			if(isset($config['snmpd']['modules']['ucd'])) {
1936
				$snmpdconf .= <<<EOD
1937
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1938

    
1939
EOD;
1940
			}
1941
			if(isset($config['snmpd']['modules']['regex'])) {
1942
				$snmpdconf .= <<<EOD
1943
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1944

    
1945
EOD;
1946
			}
1947
		}
1948

    
1949
		fwrite($fd, $snmpdconf);
1950
		fclose($fd);
1951
		unset($snmpdconf);
1952

    
1953
		if (isset($config['snmpd']['bindlan'])) {
1954
			$bindlan = "";
1955
		}
1956

    
1957
		/* run bsnmpd */
1958
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1959
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1960

    
1961
		if ($g['booting'])
1962
			echo gettext("done.") . "\n";
1963
	}
1964

    
1965
	return 0;
1966
}
1967

    
1968
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
1969
	global $config, $g;
1970
	if(isset($config['system']['developerspew'])) {
1971
		$mt = microtime();
1972
		echo "services_dnsupdate_process() being called $mt\n";
1973
	}
1974

    
1975
	/* Dynamic DNS updating active? */
1976
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1977
		$notify_text = "";
1978
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1979
			if (!isset($dnsupdate['enable']))
1980
				continue;
1981
			if (!empty($int) && $int != $dnsupdate['interface'])
1982
				continue;
1983
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
1984
				continue;
1985

    
1986
			/* determine interface name */
1987
			$if = get_real_interface($dnsupdate['interface']);
1988
			$wanip = get_interface_ip($dnsupdate['interface']);
1989
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
1990

    
1991
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
1992
			$currentTime = time();
1993

    
1994
			if ($wanip || $wanipv6) {
1995
				$keyname = $dnsupdate['keyname'];
1996
				/* trailing dot */
1997
				if (substr($keyname, -1) != ".")
1998
					$keyname .= ".";
1999

    
2000
				$hostname = $dnsupdate['host'];
2001
				/* trailing dot */
2002
				if (substr($hostname, -1) != ".")
2003
					$hostname .= ".";
2004

    
2005
				/* write private key file
2006
				   this is dumb - public and private keys are the same for HMAC-MD5,
2007
				   but nsupdate insists on having both */
2008
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2009
				$privkey = <<<EOD
2010
Private-key-format: v1.2
2011
Algorithm: 157 (HMAC)
2012
Key: {$dnsupdate['keydata']}
2013

    
2014
EOD;
2015
				fwrite($fd, $privkey);
2016
				fclose($fd);
2017

    
2018
				/* write public key file */
2019
				if ($dnsupdate['keytype'] == "zone") {
2020
					$flags = 257;
2021
					$proto = 3;
2022
				} else if ($dnsupdate['keytype'] == "host") {
2023
					$flags = 513;
2024
					$proto = 3;
2025
				} else if ($dnsupdate['keytype'] == "user") {
2026
					$flags = 0;
2027
					$proto = 2;
2028
				}
2029

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

    
2034
				/* generate update instructions */
2035
				$upinst = "";
2036
				if (!empty($dnsupdate['server']))
2037
					$upinst .= "server {$dnsupdate['server']}\n";
2038

    
2039
				if (file_exists($cacheFile)) {
2040
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2041
				}
2042
				if (file_exists("{$cacheFile}.ipv6")) {
2043
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2044
				}
2045

    
2046
				// 25 Days
2047
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2048
				$need_update = false;
2049
				/* Update IPv4 if we have it. */
2050
				if (is_ipaddrv4($wanip)) {
2051
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2052
						if (isset($dnsupdate['usepublicip'])) {
2053
							$wanip = dyndnsCheckIP($dnsupdate['interface']);
2054
						}
2055
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2056
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2057
						$notify_text .= sprintf(gettext("DynDNS updated IP Address (A) for {$dnsupdate['host']} on %s (%s) to %s"), convert_real_interface_to_friendly_descr($if), $if, $wanip) . "\n";
2058
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2059
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2060
						$need_update = true;
2061
					} else {
2062
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2063
					}
2064
				} else
2065
					@unlink($cacheFile);
2066

    
2067
				/* Update IPv6 if we have it. */
2068
				if (is_ipaddrv6($wanipv6)) {
2069
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2070
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2071
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2072
						$notify_text .= sprintf(gettext("DynDNS updated IPv6 Address (AAAA) for {$dnsupdate['host']} on %s (%s) to %s"), convert_real_interface_to_friendly_descr($if), $if, $wanipv6) . "\n";
2073
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2074
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2075
						$need_update = true;
2076
					} else {
2077
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2078
					}
2079
				} else
2080
					@unlink("{$cacheFile}.ipv6");
2081

    
2082
				$upinst .= "\n";	/* mind that trailing newline! */
2083

    
2084
				if ($need_update) {
2085
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2086
					unset($upinst);
2087
					/* invoke nsupdate */
2088
					$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2089
					if (isset($dnsupdate['usetcp']))
2090
						$cmd .= " -v";
2091
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2092
					mwexec_bg($cmd);
2093
					unset($cmd);
2094
				}
2095
			}
2096
		}
2097
		if (!empty($notify_text)) {
2098
			notify_all_remote($notify_text);
2099
		}
2100
	}
2101

    
2102
	return 0;
2103
}
2104

    
2105
/* configure cron service */
2106
function configure_cron() {
2107
	global $g, $config;
2108

    
2109
	conf_mount_rw();
2110
	/* preserve existing crontab entries */
2111
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2112

    
2113
	for ($i = 0; $i < count($crontab_contents); $i++) {
2114
		$cron_item =& $crontab_contents[$i];
2115
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2116
			array_splice($crontab_contents, $i - 1);
2117
			break;
2118
		}
2119
	}
2120
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2121

    
2122

    
2123
	if (is_array($config['cron']['item'])) {
2124
		$crontab_contents .= "#\n";
2125
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2126
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2127
		$crontab_contents .= "#\n";
2128

    
2129
		foreach ($config['cron']['item'] as $item) {
2130
			$crontab_contents .= "\n{$item['minute']}\t";
2131
			$crontab_contents .= "{$item['hour']}\t";
2132
			$crontab_contents .= "{$item['mday']}\t";
2133
			$crontab_contents .= "{$item['month']}\t";
2134
			$crontab_contents .= "{$item['wday']}\t";
2135
			$crontab_contents .= "{$item['who']}\t";
2136
			$crontab_contents .= "{$item['command']}";
2137
		}
2138

    
2139
		$crontab_contents .= "\n#\n";
2140
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2141
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2142
		$crontab_contents .= "#\n\n";
2143
	}
2144

    
2145
	/* please maintain the newline at the end of file */
2146
	file_put_contents("/etc/crontab", $crontab_contents);
2147
	unset($crontab_contents);
2148

    
2149
	/* do a HUP kill to force sync changes */
2150
	exec('/bin/pkill -HUP cron');
2151

    
2152
	conf_mount_ro();
2153
}
2154

    
2155
function upnp_action ($action) {
2156
	global $g, $config;
2157
	switch($action) {
2158
		case "start":
2159
			if (file_exists('/var/etc/miniupnpd.conf')) {
2160
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2161
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2162
			}
2163
			break;
2164
		case "stop":
2165
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2166
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2167
				mwexec('killall miniupnpd 2>/dev/null', true);
2168
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2169
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2170
			break;
2171
		case "restart":
2172
			upnp_action('stop');
2173
			upnp_action('start');
2174
			break;
2175
	}
2176
}
2177

    
2178
function upnp_start() {
2179
	global $config;
2180

    
2181
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2182
		return;
2183

    
2184
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2185
		echo gettext("Starting UPnP service... ");
2186
		require_once('/usr/local/pkg/miniupnpd.inc');
2187
		sync_package_miniupnpd();
2188
		echo "done.\n";
2189
	}
2190
}
2191

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

    
2195
	$is_installed = false;
2196

    
2197
	if (!is_array($config['cron']))
2198
		$config['cron'] = array();
2199
	if (!is_array($config['cron']['item']))
2200
		$config['cron']['item'] = array();
2201

    
2202
	$x=0;
2203
	foreach($config['cron']['item'] as $item) {
2204
		if(strstr($item['command'], $command)) {
2205
			$is_installed = true;
2206
			break;
2207
		}
2208
		$x++;
2209
	}
2210

    
2211
	if($active) {
2212
		$cron_item = array();
2213
		$cron_item['minute'] = $minute;
2214
		$cron_item['hour'] = $hour;
2215
		$cron_item['mday'] = $monthday;
2216
		$cron_item['month'] = $month;
2217
		$cron_item['wday'] = $weekday;
2218
		$cron_item['who'] = $who;
2219
		$cron_item['command'] = $command;
2220
		if(!$is_installed) {
2221
			$config['cron']['item'][] = $cron_item;
2222
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2223
		} else {
2224
			$config['cron']['item'][$x] = $cron_item;
2225
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2226
		}
2227
	} else {
2228
		if(($is_installed == true) && ($x > 0)) {
2229
			unset($config['cron']['item'][$x]);
2230
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2231
		}
2232
	}
2233
	configure_cron();
2234
}
2235

    
2236
?>
(49-49/66)