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 gratisdns ovh-dynhost');
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,GratisDNS,OVH DynHOST');
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
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
994
			}
995
		}
996
	}
997

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

    
1007
	$dhcpdv6conf = <<<EOD
1008

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

    
1021
EOD;
1022

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

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

    
1029
	$dhcpdv6ifs = array();
1030

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

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

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

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

    
1047
		$dnscfgv6 = "";
1048

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

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

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

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

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

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

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

    
1094
EOD;
1095

    
1096
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1097
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1098
		}
1099
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1100
			$dhcpdv6conf .= "       option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1101
		}
1102
    		// default-lease-time
1103
		if ($dhcpv6ifconf['defaultleasetime'])
1104
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1105

    
1106
		// max-lease-time
1107
		if ($dhcpv6ifconf['maxleasetime'])
1108
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1109

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

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

    
1134
		// ldap-server
1135
		if ($dhcpv6ifconf['ldap'] <> "")
1136
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1137

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

    
1151
		$dhcpdv6conf .= "}\n";
1152

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

    
1162
EOD;
1163
				if ($sm['ipaddrv6'])
1164
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1165

    
1166
				if ($sm['hostname']) {
1167
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1168
					$dhhostname = str_replace(".", "_", $dhhostname);
1169
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1170
				}
1171
				if ($sm['filename'])
1172
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1173

    
1174
				if ($sm['rootpath'])
1175
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1176

    
1177
				$dhcpdv6conf .= "}\n";
1178
				$i++;
1179
			}
1180
		}
1181

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

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

    
1210
	/* create an empty leases v6 database */
1211
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1212
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1213

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

    
1223
	return 0;
1224
}
1225

    
1226
function services_igmpproxy_configure() {
1227
        global $config, $g;
1228

    
1229
        /* kill any running igmpproxy */
1230
        killbyname("igmpproxy");
1231

    
1232
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1233
		return 1;
1234

    
1235
        $iflist = get_configured_interface_list();
1236

    
1237
        $igmpconf = <<<EOD
1238

    
1239
##------------------------------------------------------
1240
## Enable Quickleave mode (Sends Leave instantly)
1241
##------------------------------------------------------
1242
quickleave
1243

    
1244
EOD;
1245

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

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

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

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

    
1281
        return 0;
1282
}
1283

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

    
1293
	/* kill any running dhcrelay */
1294
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1295

    
1296
	$dhcrelaycfg =& $config['dhcrelay'];
1297

    
1298
	/* DHCPRelay enabled on any interfaces? */
1299
	if (!isset($dhcrelaycfg['enable']))
1300
		return 0;
1301

    
1302
	if ($g['booting'])
1303
		echo gettext("Starting DHCP relay service...");
1304
	else
1305
		sleep(1);
1306

    
1307
	$iflist = get_configured_interface_list();
1308

    
1309
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1310
	foreach ($dhcifaces as $dhcrelayif) {
1311
		if (!isset($iflist[$dhcrelayif]) ||
1312
			link_interface_to_bridge($dhcrelayif))
1313
			continue;
1314

    
1315
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1316
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1317
	}
1318

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

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

    
1371
		if (!isset($destif)) {
1372
			if (is_array($config['gateways']['gateway_item'])) {
1373
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1374
					if (isset($gateway['defaultgw'])) {
1375
						$destif = $gateway['interface'];
1376
						break;
1377
					}
1378
				}
1379
			} else
1380
				$destif = get_real_interface("wan");
1381
		}
1382

    
1383
		if (!empty($destif))
1384
			$dhcrelayifs[] = $destif;
1385
	}
1386
	$dhcrelayifs = array_unique($dhcrelayifs);
1387

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

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

    
1396
	if (isset($dhcrelaycfg['agentoption']))
1397
		$cmd .=  " -a -m replace";
1398

    
1399
	$cmd .= " " . implode(" ", $srvips);
1400
	mwexec($cmd);
1401
	unset($cmd);
1402

    
1403
	return 0;
1404
}
1405

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

    
1415
	/* kill any running dhcrelay */
1416
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1417

    
1418
	$dhcrelaycfg =& $config['dhcrelay6'];
1419

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

    
1424
	if ($g['booting'])
1425
		echo gettext("Starting DHCPv6 relay service...");
1426
	else
1427
		sleep(1);
1428

    
1429
	$iflist = get_configured_interface_list();
1430

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

    
1437
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1438
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1439
	}
1440
	$dhcrelayifs = array_unique($dhcrelayifs);
1441

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

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

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

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

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

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

    
1522
	return 0;
1523
}
1524

    
1525
function services_dyndns_configure_client($conf) {
1526

    
1527
	if (!isset($conf['enable']))
1528
		return;
1529

    
1530
	/* load up the dyndns.class */
1531
	require_once("dyndns.class");
1532

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

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

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

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

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

    
1582
	return 0;
1583
}
1584

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

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

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

    
1620

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

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

    
1630
	if (isset($config['dnsmasq']['enable'])) {
1631

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

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

    
1641
		$args = "";
1642

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1763
	return $return;
1764
}
1765

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

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

    
1779
	if (isset($config['snmpd']['enable'])) {
1780

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

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

    
1791

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

    
1797
EOD;
1798

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

    
1805
EOD;
1806
		}
1807
*/
1808

    
1809

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

    
1817

    
1818
EOD;
1819
		}
1820

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

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

    
1837
EOD;
1838

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

    
1844
EOD;
1845
		}
1846
*/
1847

    
1848

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

    
1855
EOD;
1856
		}
1857

    
1858

    
1859
		$snmpdconf .= <<<EOD
1860
begemotSnmpdCommunityDisable    = 1
1861

    
1862
EOD;
1863

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

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

    
1883
EOD;
1884

    
1885
		}
1886

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

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

    
1896
snmpEnableAuthenTraps = 2
1897

    
1898
EOD;
1899

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

    
1905
EOD;
1906
		    }
1907

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

    
1914
EOD;
1915
		    }
1916

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

    
1921
EOD;
1922
		    }
1923

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

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

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

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

    
1947
EOD;
1948
			}
1949
		}
1950

    
1951
		fwrite($fd, $snmpdconf);
1952
		fclose($fd);
1953
		unset($snmpdconf);
1954

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

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

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

    
1967
	return 0;
1968
}
1969

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

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

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

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

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

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

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

    
2016
EOD;
2017
				fwrite($fd, $privkey);
2018
				fclose($fd);
2019

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

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

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

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

    
2048
				// 25 Days
2049
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2050
				$need_update = false;
2051

    
2052
				conf_mount_rw();
2053
				/* Update IPv4 if we have it. */
2054
				if (is_ipaddrv4($wanip)) {
2055
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2056
						if (isset($dnsupdate['usepublicip'])) {
2057
							$wanip = dyndnsCheckIP($dnsupdate['interface']);
2058
						}
2059
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2060
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2061
						$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";
2062
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2063
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2064
						$need_update = true;
2065
					} else {
2066
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2067
					}
2068
				} else
2069
					@unlink($cacheFile);
2070

    
2071
				/* Update IPv6 if we have it. */
2072
				if (is_ipaddrv6($wanipv6)) {
2073
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2074
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2075
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2076
						$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";
2077
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2078
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2079
						$need_update = true;
2080
					} else {
2081
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2082
					}
2083
				} else
2084
					@unlink("{$cacheFile}.ipv6");
2085
				conf_mount_ro();
2086

    
2087
				$upinst .= "\n";	/* mind that trailing newline! */
2088

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

    
2107
	return 0;
2108
}
2109

    
2110
/* configure cron service */
2111
function configure_cron() {
2112
	global $g, $config;
2113

    
2114
	conf_mount_rw();
2115
	/* preserve existing crontab entries */
2116
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2117

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

    
2127

    
2128
	if (is_array($config['cron']['item'])) {
2129
		$crontab_contents .= "#\n";
2130
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2131
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2132
		$crontab_contents .= "#\n";
2133

    
2134
		foreach ($config['cron']['item'] as $item) {
2135
			$crontab_contents .= "\n{$item['minute']}\t";
2136
			$crontab_contents .= "{$item['hour']}\t";
2137
			$crontab_contents .= "{$item['mday']}\t";
2138
			$crontab_contents .= "{$item['month']}\t";
2139
			$crontab_contents .= "{$item['wday']}\t";
2140
			$crontab_contents .= "{$item['who']}\t";
2141
			$crontab_contents .= "{$item['command']}";
2142
		}
2143

    
2144
		$crontab_contents .= "\n#\n";
2145
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2146
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2147
		$crontab_contents .= "#\n\n";
2148
	}
2149

    
2150
	/* please maintain the newline at the end of file */
2151
	file_put_contents("/etc/crontab", $crontab_contents);
2152
	unset($crontab_contents);
2153

    
2154
	/* do a HUP kill to force sync changes */
2155
	exec('/bin/pkill -HUP cron');
2156

    
2157
	conf_mount_ro();
2158
}
2159

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

    
2183
function upnp_start() {
2184
	global $config;
2185

    
2186
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2187
		return;
2188

    
2189
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2190
		echo gettext("Starting UPnP service... ");
2191
		require_once('/usr/local/pkg/miniupnpd.inc');
2192
		sync_package_miniupnpd();
2193
		echo "done.\n";
2194
	}
2195
}
2196

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

    
2200
	$is_installed = false;
2201

    
2202
	if (!is_array($config['cron']))
2203
		$config['cron'] = array();
2204
	if (!is_array($config['cron']['item']))
2205
		$config['cron']['item'] = array();
2206

    
2207
	$x=0;
2208
	foreach($config['cron']['item'] as $item) {
2209
		if(strstr($item['command'], $command)) {
2210
			$is_installed = true;
2211
			break;
2212
		}
2213
		$x++;
2214
	}
2215

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

    
2241
?>
(49-49/66)