Projet

Général

Profil

Télécharger (72,1 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / services.inc @ a762649b

1
<?php
2
/*
3
	services.inc
4
	part of the pfSense project (https://www.pfsense.org)
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 custom custom-v6');
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,Custom,Custom (v6)');
43

    
44
/* implement ipv6 route advertising deamon */
45
function services_radvd_configure($blacklist = array()) {
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
		/* Do not put in the config an interface which is down */
76
		if (isset($blacklist[$dhcpv6if]))
77
			continue;
78
		if (!isset($dhcpv6ifconf['ramode']))
79
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
80

    
81
		/* are router advertisements enabled? */
82
		if ($dhcpv6ifconf['ramode'] == "disabled")
83
			continue;
84

    
85
		if (!isset($dhcpv6ifconf['rapriority']))
86
			$dhcpv6ifconf['rapriority'] = "medium";
87

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

    
98
		$realif = get_real_interface($dhcpv6if, "inet6");
99
		if (isset($radvdifs[$realif]))
100
			continue;
101

    
102
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
103
		if (!is_ipaddrv6($ifcfgipv6))
104
			continue;
105

    
106
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
107
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
108
		$radvdifs[$realif] = $realif;
109

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

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

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

    
210
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
211
	foreach ($Iflist as $if => $ifdescr) {
212
		if(!isset($config['interfaces'][$if]['track6-interface']))
213
			continue;
214
		if(!isset($config['interfaces'][$if]['enable']))
215
			continue;
216
		/* Do not put in the config an interface which is down */
217
		if (isset($blacklist[$if]))
218
			continue;
219
		$trackif = $config['interfaces'][$if]['track6-interface'];
220
		if (empty($config['interfaces'][$trackif]))
221
			continue;
222

    
223
		$realif = get_real_interface($if, "inet6");
224
		/* prevent duplicate entries, manual overrides */
225
		if (isset($radvdifs[$realif]))
226
			continue;
227

    
228
		$ifcfgipv6 = get_interface_ipv6($if);
229
		if(!is_ipaddrv6($ifcfgipv6)) {
230
			$subnetv6 = "::";
231
			$ifcfgsnv6 = "64";
232
		} else {
233
			$ifcfgsnv6 = get_interface_subnetv6($if);
234
			$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
235
		}
236
		$radvdifs[$realif] = $realif;
237

    
238
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
239
	
240
		if ($g['debug'])
241
			log_error("configuring RA on {$if} for type {$autotype} radvd subnet {$subnetv6}/{$ifcfgsnv6}");
242

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

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

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

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

    
306
function services_dhcpd_configure($family = "all", $blacklist = array()) {
307
	global $config, $g;
308

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

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

    
331
	if ($family == "all" || $family == "inet")
332
		services_dhcpdv4_configure();
333
	if ($family == "all" || $family == "inet6") {
334
		services_dhcpdv6_configure($blacklist);
335
		services_radvd_configure($blacklist);
336
	}
337
}
338

    
339
function services_dhcpdv4_configure() {
340
	global $config, $g;
341
	$need_ddns_updates = false;
342
	$ddns_zones = array();
343

    
344
	if($g['services_dhcp_server_enable'] == false)
345
		return;
346

    
347
	if(isset($config['system']['developerspew'])) {
348
		$mt = microtime();
349
		echo "services_dhcpdv4_configure($if) being called $mt\n";
350
	}
351

    
352
	/* kill any running dhcpd */
353
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid"))
354
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
355

    
356
	/* DHCP enabled on any interfaces? */
357
	if (!is_dhcp_server_enabled())
358
		return 0;
359

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

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

    
383
	$syscfg = $config['system'];
384
	if (!is_array($config['dhcpd']))
385
		$config['dhcpd'] = array();
386
	$dhcpdcfg = $config['dhcpd'];
387
	$Iflist = get_configured_interface_list();
388

    
389
	/* Only consider DNS servers with IPv4 addresses for the IPv4 DHCP server. */
390
	$dns_arrv4 = array();
391
	if (is_array($syscfg['dnsserver'])) {
392
		foreach($syscfg['dnsserver'] as $dnsserver) {
393
			if (is_ipaddrv4($dnsserver)) {
394
				$dns_arrv4[] = $dnsserver;
395
			}
396
		}
397
	}
398

    
399
	if ($g['booting'])
400
		echo gettext("Starting DHCP service...");
401
	else
402
		sleep(1);
403

    
404
	$custoptions = "";
405
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
406
		if(is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) {
407
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
408
				if(!empty($item['type']))
409
					$itemtype = $item['type'];
410
				else
411
					$itemtype = "text";
412
				$custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n";
413
			}
414
		}
415
	}
416

    
417
	$dhcpdconf = <<<EOD
418

    
419
option domain-name "{$syscfg['domain']}";
420
option ldap-server code 95 = text;
421
option domain-search-list code 119 = text;
422
{$custoptions}
423
default-lease-time 7200;
424
max-lease-time 86400;
425
log-facility local7;
426
one-lease-per-client true;
427
deny duplicates;
428
ping-check true;
429

    
430
EOD;
431

    
432
	if(!isset($dhcpifconf['disableauthoritative']))
433
		$dhcpdconf .= "authoritative;\n";
434

    
435
	if(isset($dhcpifconf['alwaysbroadcast']))
436
		$dhcpdconf .= "always-broadcast on\n";
437

    
438
	$dhcpdifs = array();
439
	$add_routers = false;
440
	$gateways_arr = return_gateways_array();
441
	/* only add a routers line if the system has any IPv4 gateway at all */
442
	/* a static route has a gateway, manually overriding this field always works */
443
	foreach($gateways_arr as $gwitem) {
444
		if($gwitem['ipprotocol'] == "inet") {
445
			$add_routers = true;
446
			break;
447
		}
448
	}
449

    
450
	/*    loop through and determine if we need to setup
451
	 *    failover peer "bleh" entries
452
	 */
453
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
454

    
455
		interfaces_staticarp_configure($dhcpif);
456

    
457
		if (!isset($dhcpifconf['enable']))
458
			continue;
459

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

    
509
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
510

    
511
		$newzone = array();
512
		$ifcfg = $config['interfaces'][$dhcpif];
513

    
514
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
515
			continue;
516
		$ifcfgip = get_interface_ip($dhcpif);
517
		$ifcfgsn = get_interface_subnet($dhcpif);
518
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
519
		$subnetmask = gen_subnet_mask($ifcfgsn);
520

    
521
		if (!is_ipaddr($subnet))
522
			continue;
523

    
524
		if($is_olsr_enabled == true)
525
			if($dhcpifconf['netmask'])
526
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
527

    
528
		$all_pools = array();
529
		$all_pools[] = $dhcpifconf;
530
		if (is_array($dhcpifconf['pool'])) {
531
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
532
		}
533

    
534
		$dnscfg = "";
535

    
536
		if ($dhcpifconf['domain']) {
537
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
538
		}
539

    
540
		if($dhcpifconf['domainsearchlist'] <> "") {
541
			$dnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpifconf['domainsearchlist'])) . "\";\n";
542
		}
543

    
544
		if (isset($dhcpifconf['ddnsupdate'])) {
545
			$need_ddns_updates = true;
546
			$newzone = array();
547
			if($dhcpifconf['ddnsdomain'] <> "") {
548
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
549
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
550
			} else {
551
				$newzone['domain-name'] = $config['system']['domain'];
552
			}
553
			$revsubnet = explode(".", $subnet);
554
			$revsubnet = array_reverse($revsubnet);
555
			foreach ($revsubnet as $octet) {
556
				if ($octet != "0")
557
					break;
558
				array_shift($revsubnet);
559
			}
560
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
561
		}
562

    
563
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
564
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
565
			if ($newzone['domain-name'])
566
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
567
		} else if (isset($config['dnsmasq']['enable'])) {
568
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
569
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0]))
570
				$newzone['dns-servers'] = $syscfg['dnsserver'];
571
		} else if (!empty($dns_arrv4)) {
572
			$dnscfg .= "	option domain-name-servers " . join(",", $dns_arrv4) . ";";
573
			if ($newzone['domain-name'])
574
				$newzone['dns-servers'] = $dns_arrv4;
575
		}
576

    
577
		/* Create classes - These all contain comma separated lists. Join them into one 
578
		   big comma separated string then split them all up. */
579
		$all_mac_strings = array();
580
		if (is_array($dhcpifconf['pool'])) {
581
			foreach($all_pools as $poolconf) {
582
				$all_mac_strings[] = $poolconf['mac_allow'];
583
				$all_mac_strings[] = $poolconf['mac_deny'];
584
			}
585
		}
586
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
587
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
588
		$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
589
		foreach ($all_mac_list as $mac) {
590
			if (empty($mac))
591
				continue;
592
			$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
593
			// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
594
			$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
595
			$dhcpdconf .= '}' . "\n";
596
		}
597

    
598
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
599

    
600
// Setup pool options
601
		foreach($all_pools as $poolconf) {
602
			$dhcpdconf .= "	pool {\n";
603
			/* is failover dns setup? */
604
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
605
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
606
				if($poolconf['dnsserver'][1] <> "")
607
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
608
				$dhcpdconf .= ";\n";
609
			}
610

    
611
			/* allow/deny MACs */
612
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
613
			foreach ($mac_allow_list as $mac) {
614
				if (empty($mac))
615
					continue;
616
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
617
			}
618
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
619
			foreach ($mac_deny_list as $mac) {
620
				if (empty($mac))
621
					continue;
622
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
623
			}
624

    
625
			if($poolconf['failover_peerip'] <> "")
626
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
627

    
628
			if (isset($poolconf['denyunknown']))
629
			   $dhcpdconf .= "		deny unknown-clients;\n";
630

    
631
			if ($poolconf['gateway'] && ($poolconf['gateway'] != $dhcpifconf['gateway']))
632
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
633

    
634
			if($dhcpifconf['failover_peerip'] <> "") {
635
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
636
			}
637

    
638
			$pdnscfg = "";
639

    
640
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
641
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
642
			}
643

    
644
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
645
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
646
			}
647

    
648
			if (isset($poolconf['ddnsupdate'])) {
649
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
650
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
651
				$pdnscfg .= "		ddns-update-style interim;\n";
652
			}
653

    
654
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
655
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
656
			}
657
			$dhcpdconf .= "{$pdnscfg}";
658

    
659
			// default-lease-time
660
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
661
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
662

    
663
			// max-lease-time
664
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
665
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
666

    
667
			// netbios-name*
668
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
669
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
670
				$dhcpdconf .= "		option netbios-node-type 8;\n";
671
			}
672

    
673
			// ntp-servers
674
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
675
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
676

    
677
			// tftp-server-name
678
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
679
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
680

    
681
			// ldap-server
682
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
683
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
684

    
685
			// net boot information
686
			if(isset($poolconf['netboot'])) {
687
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
688
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
689
				}
690
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
691
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
692
				}
693
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
694
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
695
				}
696
			}
697
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
698
			$dhcpdconf .= "	}\n\n";
699
		}
700
// End of settings inside pools
701

    
702
		if ($dhcpifconf['gateway']) {
703
			$routers = $dhcpifconf['gateway'];
704
			$add_routers = true;
705
		} else {
706
			$routers = $ifcfgip;
707
		}
708
		if($add_routers)
709
			$dhcpdconf .= "	option routers {$routers};\n";
710

    
711
		$dhcpdconf .= <<<EOD
712
$dnscfg
713

    
714
EOD;
715
    		// default-lease-time
716
		if ($dhcpifconf['defaultleasetime'])
717
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
718

    
719
		// max-lease-time
720
		if ($dhcpifconf['maxleasetime'])
721
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
722

    
723
		// netbios-name*
724
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
725
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
726
			$dhcpdconf .= "	option netbios-node-type 8;\n";
727
		}
728

    
729
		// ntp-servers
730
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
731
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
732

    
733
		// tftp-server-name
734
		if ($dhcpifconf['tftp'] <> "")
735
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
736

    
737
		// Handle option, number rowhelper values
738
		$dhcpdconf .= "\n";
739
		if($dhcpifconf['numberoptions']['item']) {
740
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
741
				if(empty($item['type']) || $item['type'] == "text")
742
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
743
				else
744
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
745
			}
746
		}
747

    
748
		// ldap-server
749
		if ($dhcpifconf['ldap'] <> "")
750
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
751

    
752
		// net boot information
753
		if(isset($dhcpifconf['netboot'])) {
754
			if ($dhcpifconf['nextserver'] <> "") {
755
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
756
			}
757
			if ($dhcpifconf['filename'] <> "") {
758
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
759
			}
760
			if ($dhcpifconf['rootpath'] <> "") {
761
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
762
			}
763
		}
764

    
765
		$dhcpdconf .= <<<EOD
766
}
767

    
768
EOD;
769

    
770
		/* add static mappings */
771
		if (is_array($dhcpifconf['staticmap'])) {
772

    
773
			$i = 0;
774
			foreach ($dhcpifconf['staticmap'] as $sm) {
775
				$dhcpdconf .= <<<EOD
776
host s_{$dhcpif}_{$i} {
777
	hardware ethernet {$sm['mac']};
778

    
779
EOD;
780
				if ($sm['ipaddr'])
781
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
782

    
783
				if ($sm['hostname']) {
784
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
785
					$dhhostname = str_replace(".", "_", $dhhostname);
786
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
787
				}
788
				if ($sm['filename'])
789
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
790

    
791
				if ($sm['rootpath'])
792
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
793

    
794
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
795
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
796

    
797
				$smdnscfg = "";
798

    
799
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
800
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
801
				}
802

    
803
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
804
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
805
				}
806

    
807
				if (isset($sm['ddnsupdate'])) {
808
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
809
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
810
					$pdnscfg .= "		ddns-update-style interim;\n";
811
				}
812

    
813
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
814
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
815
				}
816
				$dhcpdconf .= "{$smdnscfg}";
817

    
818
				// default-lease-time
819
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
820
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
821

    
822
				// max-lease-time
823
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
824
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
825

    
826
				// netbios-name*
827
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
828
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
829
					$dhcpdconf .= "	option netbios-node-type 8;\n";
830
				}
831

    
832
				// ntp-servers
833
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
834
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
835

    
836
				// tftp-server-name
837
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
838
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
839

    
840
				$dhcpdconf .= "}\n";
841
				$i++;
842
			}
843
		}
844

    
845
		$dhcpdifs[] = get_real_interface($dhcpif);
846
		if ($newzone['domain-name'])
847
			$ddns_zones[] = $newzone;
848
	}
849

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

    
889
	/* write dhcpd.conf */
890
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
891
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
892
		unset($dhcpdconf);
893
		return 1;
894
	}
895
	unset($dhcpdconf);
896

    
897
	/* create an empty leases database */
898
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
899
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
900

    
901
	/* make sure there isn't a stale dhcpd.pid file, which can make dhcpd fail to start.   */
902
	/* if we get here, dhcpd has been killed and is not started yet                        */ 
903
	unlink_if_exists("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
904

    
905
	/* fire up dhcpd in a chroot */
906
	if (count($dhcpdifs) > 0) {
907
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
908
			join(" ", $dhcpdifs));
909
	}
910

    
911
	if ($g['booting'])
912
		print "done.\n";
913

    
914
	return 0;
915
}
916

    
917
function services_dhcpdv6_configure($blacklist = array()) {
918
	global $config, $g;
919

    
920
	if($g['services_dhcp_server_enable'] == false)
921
		return;
922

    
923
	if(isset($config['system']['developerspew'])) {
924
		$mt = microtime();
925
		echo "services_dhcpd_configure($if) being called $mt\n";
926
	}
927

    
928
	/* kill any running dhcpd */
929
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
930
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
931
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
932
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
933

    
934
	/* DHCP enabled on any interfaces? */
935
	if (!is_dhcpv6_server_enabled())
936
		return 0;
937

    
938
	if ($g['booting']) {
939
		if ($g['platform'] != "pfSense") {
940
			/* restore the leases, if we have them */
941
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
942
				$dhcprestore = "";
943
				$dhcpreturn = "";
944
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
945
				$dhcprestore = implode(" ", $dhcprestore);
946
				if($dhcpreturn <> 0) {
947
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
948
				}
949
			}
950
		}
951
	}
952

    
953
	$syscfg = $config['system'];
954
	if (!is_array($config['dhcpdv6']))
955
		$config['dhcpdv6'] = array();
956
	$dhcpdv6cfg = $config['dhcpdv6'];
957
	$Iflist = get_configured_interface_list();
958
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
959

    
960

    
961
	if ($g['booting'])
962
		echo "Starting DHCPv6 service...";
963
	else
964
		sleep(1);
965

    
966
	/* we add a fake entry for interfaces that are set to track6 another WAN */
967
	foreach ($Iflist as $ifname) {
968
		/* Do not put in the config an interface which is down */
969
		if (isset($blacklist[$ifname]))
970
			continue;
971
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
972
			$realif = get_real_interface($ifname, "inet6");
973
			$ifcfgipv6 = get_interface_ipv6($ifname);
974
			if(!is_ipaddrv6($ifcfgipv6))
975
				continue;
976
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
977
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
978
			$trackcfg = $config['interfaces'][$trackifname];
979
			$pdlen = calculate_ipv6_delegation_length($trackifname);
980
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
981
			$dhcpdv6cfg[$ifname] = array();
982
			$dhcpdv6cfg[$ifname]['enable'] = true;
983
			/* range */
984
			$ifcfgipv6arr[7] = "1000";
985
			$dhcpdv6cfg[$ifname]['range'] = array();
986
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
987
			$ifcfgipv6arr[7] = "2000";
988
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));;
989
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
990
			if($pdlen > 2) {
991
				$pdlenmax = $pdlen;
992
				$pdlenhalf = $pdlenmax -1;
993
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
994
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
995
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
996

    
997
				/* set the delegation start to half the current address block */
998
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
999
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
1000

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

    
1005
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
1006
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
1007
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
1008
			}
1009
		}
1010
	}
1011

    
1012
	$custoptionsv6 = "";
1013
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1014
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
1015
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1016
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
1017
			}
1018
		}
1019
	}
1020

    
1021
	if(isset($dhcpv6ifconf['netboot']) && !empty($dhcpv6ifconf['bootfile_url']))
1022
		$custoptionsv6 .= "option dhcp6.bootfile-url code 59 = string;\n";
1023

    
1024
	$dhcpdv6conf = <<<EOD
1025

    
1026
option domain-name "{$syscfg['domain']}";
1027
option ldap-server code 95 = text;
1028
option domain-search-list code 119 = text;
1029
{$custoptionsv6}
1030
default-lease-time 7200;
1031
max-lease-time 86400;
1032
log-facility local7;
1033
ddns-update-style none;
1034
one-lease-per-client true;
1035
deny duplicates;
1036
ping-check true;
1037

    
1038
EOD;
1039

    
1040
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1041
		$dhcpdv6conf .= "authoritative;\n";
1042

    
1043
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1044
		$dhcpdv6conf .= "always-broadcast on\n";
1045

    
1046
	$dhcpdv6ifs = array();
1047

    
1048
	$dhcpv6num = 0;
1049
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1050

    
1051
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1052

    
1053
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1054
			continue;
1055
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1056
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1057
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1058

    
1059
		if ($is_olsr_enabled == true) {
1060
			if($dhcpv6ifconf['netmask'])
1061
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1062
		}
1063

    
1064
		$dnscfgv6 = "";
1065

    
1066
		if ($dhcpv6ifconf['domain']) {
1067
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1068
		}
1069

    
1070
    		if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1071
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1072
    		}
1073

    
1074
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1075
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1076
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1077
			}
1078
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1079
		}
1080

    
1081
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1082
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1083
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1084
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1085
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1086
			$dns_arrv6 = array();
1087
			foreach($syscfg['dnsserver'] as $dnsserver) {
1088
				if (is_ipaddrv6($dnsserver)) {
1089
					$dns_arrv6[] = $dnsserver;
1090
				}
1091
			}
1092
			if(!empty($dns_arrv6))
1093
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1094
		}
1095

    
1096
		if (is_ipaddrv6($ifcfgipv6)) {
1097
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1098
		} else {
1099
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1100
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1101
		}
1102
		$dhcpdv6conf .= " {\n";
1103

    
1104
		$dhcpdv6conf .= <<<EOD
1105
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1106
$dnscfgv6
1107

    
1108
EOD;
1109

    
1110
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1111
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1112
		}
1113
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1114
			$dhcpdv6conf .= "       option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1115
		}
1116
    		// default-lease-time
1117
		if ($dhcpv6ifconf['defaultleasetime'])
1118
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1119

    
1120
		// max-lease-time
1121
		if ($dhcpv6ifconf['maxleasetime'])
1122
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1123

    
1124
		// ntp-servers
1125
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1126
			$ntpservers = array();
1127
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1128
				if(is_ipaddrv6($ntpserver))
1129
					$ntpservers[] = $ntpserver;
1130
			}
1131
			if(count($ntpservers) > 0 )
1132
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1133
		}
1134
		// tftp-server-name
1135
		/* Needs ISC DHCPD support
1136
		 if ($dhcpv6ifconf['tftp'] <> "")
1137
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1138
		*/
1139

    
1140
		// Handle option, number rowhelper values
1141
		$dhcpdv6conf .= "\n";
1142
		if ($dhcpv6ifconf['numberoptions']['item']) {
1143
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1144
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1145
			}
1146
		}
1147

    
1148
		// ldap-server
1149
		if ($dhcpv6ifconf['ldap'] <> "")
1150
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1151

    
1152
		// net boot information
1153
		if(isset($dhcpv6ifconf['netboot'])) {
1154
			if (!empty($dhcpv6ifconf['bootfile_url'])) {
1155
				$dhcpdv6conf .= "	option dhcp6.bootfile-url \"{$dhcpv6ifconf['bootfile_url']}\";\n";
1156
			}
1157
		}
1158

    
1159
		$dhcpdv6conf .= "}\n";
1160

    
1161
		/* add static mappings */
1162
		/* Needs to use DUID */
1163
		if (is_array($dhcpv6ifconf['staticmap'])) {
1164
			$i = 0;
1165
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1166
				$dhcpdv6conf .= <<<EOD
1167
host s_{$dhcpv6if}_{$i} {
1168
	host-identifier option dhcp6.client-id {$sm['duid']};
1169

    
1170
EOD;
1171
				if ($sm['ipaddrv6'])
1172
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1173

    
1174
				if ($sm['hostname']) {
1175
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1176
					$dhhostname = str_replace(".", "_", $dhhostname);
1177
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1178
				}
1179
				if ($sm['filename'])
1180
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1181

    
1182
				if ($sm['rootpath'])
1183
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1184

    
1185
				$dhcpdv6conf .= "}\n";
1186
				$i++;
1187
			}
1188
		}
1189

    
1190
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1191
			if(preg_match("/poes/si", $dhcpv6if)) {
1192
				/* magic here */
1193
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1194
			} else {
1195
				$realif = get_real_interface($dhcpv6if, "inet6");
1196
				if (stristr("$realif", "bridge")) {
1197
					$mac = get_interface_mac($realif);
1198
					$v6address = generate_ipv6_from_mac($mac);
1199
					/* Create link local address for bridges */
1200
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1201
				}
1202
				$realif = escapeshellcmd($realif);
1203
				$dhcpdv6ifs[] = $realif;
1204
			}
1205
		}
1206
	}
1207

    
1208
	/* write dhcpdv6.conf */
1209
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1210
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1211
		if ($g['booting'])
1212
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1213
		unset($dhcpdv6conf);
1214
		return 1;
1215
	}
1216
	unset($dhcpdv6conf);
1217

    
1218
	/* create an empty leases v6 database */
1219
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1220
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1221

    
1222
        /* make sure there isn't a stale dhcpdv6.pid file, which may make dhcpdv6 fail to start.  */
1223
        /* if we get here, dhcpdv6 has been killed and is not started yet                         */
1224
        unlink_if_exists("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
1225

    
1226
	/* fire up dhcpd in a chroot */
1227
	if (count($dhcpdv6ifs) > 0) {
1228
		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 " .
1229
			join(" ", $dhcpdv6ifs));
1230
		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");
1231
	}
1232
	if ($g['booting'])
1233
		print gettext("done.") . "\n";
1234

    
1235
	return 0;
1236
}
1237

    
1238
function services_igmpproxy_configure() {
1239
        global $config, $g;
1240

    
1241
        /* kill any running igmpproxy */
1242
        killbyname("igmpproxy");
1243

    
1244
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1245
		return 1;
1246

    
1247
        $iflist = get_configured_interface_list();
1248

    
1249
        $igmpconf = <<<EOD
1250

    
1251
##------------------------------------------------------
1252
## Enable Quickleave mode (Sends Leave instantly)
1253
##------------------------------------------------------
1254
quickleave
1255

    
1256
EOD;
1257

    
1258
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1259
                unset($iflist[$igmpcf['ifname']]);
1260
                $realif = get_real_interface($igmpcf['ifname']);
1261
                if (empty($igmpcf['threshold']))
1262
                        $threshld = 1;
1263
                else
1264
                        $threshld = $igmpcf['threshold'];
1265
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1266

    
1267
                if ($igmpcf['address'] <> "") {
1268
                        $item = explode(" ", $igmpcf['address']);
1269
                        foreach($item as $iww)
1270
                                $igmpconf .= "altnet {$iww}\n";
1271
                }
1272
                $igmpconf .= "\n";
1273
        }
1274
        foreach ($iflist as $ifn) {
1275
                $realif = get_real_interface($ifn);
1276
                $igmpconf .= "phyint {$realif} disabled\n";
1277
        }
1278
	$igmpconf .= "\n";
1279

    
1280
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1281
        if (!$igmpfl) {
1282
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1283
                return;
1284
        }
1285
        fwrite($igmpfl, $igmpconf);
1286
        fclose($igmpfl);
1287
	unset($igmpconf);
1288

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

    
1293
        return 0;
1294
}
1295

    
1296
function services_dhcrelay_configure() {
1297
	global $config, $g;
1298
	if ($g['platform'] == 'jail')
1299
		return;
1300
	if(isset($config['system']['developerspew'])) {
1301
		$mt = microtime();
1302
		echo "services_dhcrelay_configure() being called $mt\n";
1303
	}
1304

    
1305
	/* kill any running dhcrelay */
1306
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1307

    
1308
	$dhcrelaycfg =& $config['dhcrelay'];
1309

    
1310
	/* DHCPRelay enabled on any interfaces? */
1311
	if (!isset($dhcrelaycfg['enable']))
1312
		return 0;
1313

    
1314
	if ($g['booting'])
1315
		echo gettext("Starting DHCP relay service...");
1316
	else
1317
		sleep(1);
1318

    
1319
	$iflist = get_configured_interface_list();
1320

    
1321
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1322
	foreach ($dhcifaces as $dhcrelayif) {
1323
		if (!isset($iflist[$dhcrelayif]) ||
1324
			link_interface_to_bridge($dhcrelayif))
1325
			continue;
1326

    
1327
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1328
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1329
	}
1330

    
1331
	/*
1332
	 * In order for the relay to work, it needs to be active
1333
	 * on the interface in which the destination server sits.
1334
	 */
1335
	$srvips = explode(",", $dhcrelaycfg['server']);
1336
	foreach ($srvips as $srcidx => $srvip) {
1337
		unset($destif);
1338
		foreach ($iflist as $ifname) {
1339
			$subnet = get_interface_ip($ifname);
1340
			if (!is_ipaddr($subnet))
1341
				continue;
1342
			$subnet .=  "/" . get_interface_subnet($ifname);
1343
			if (ip_in_subnet($srvip, $subnet)) {
1344
				$destif = get_real_interface($ifname);
1345
				break;
1346
			}
1347
		}
1348
		if (!isset($destif)) {
1349
			foreach (get_staticroutes() as $rtent) {
1350
				if (ip_in_subnet($srvip, $rtent['network'])) {
1351
					$a_gateways = return_gateways_array(true);
1352
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1353
					break;
1354
				}
1355
			}
1356
		}
1357

    
1358
		if (!isset($destif)) {
1359
			/* Create a array from the existing route table */
1360
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1361
        		array_shift($route_str);
1362
        		array_shift($route_str);
1363
        		array_shift($route_str);
1364
        		array_shift($route_str);
1365
        		$route_arr = array();
1366
        		foreach($route_str as $routeline) {
1367
				$items = preg_split("/[ ]+/i", $routeline);
1368
				if (is_subnetv4($items[0])) {
1369
					$subnet = $items[0];
1370
				} elseif (is_ipaddrv4($items[0])) {
1371
					$subnet = "{$items[0]}/32";
1372
				} else {
1373
					// Not a subnet or IP address, skip to the next line.
1374
					continue;
1375
				}
1376
				if (ip_in_subnet($srvip, $subnet)) {
1377
					$destif = trim($items[6]);
1378
					break;
1379
				}
1380
			}
1381
		}
1382

    
1383
		if (!isset($destif)) {
1384
			if (is_array($config['gateways']['gateway_item'])) {
1385
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1386
					if (isset($gateway['defaultgw'])) {
1387
						$destif = get_real_interface($gateway['interface']);
1388
						break;
1389
					}
1390
				}
1391
			} else
1392
				$destif = get_real_interface("wan");
1393
		}
1394

    
1395
		if (!empty($destif))
1396
			$dhcrelayifs[] = $destif;
1397
	}
1398
	$dhcrelayifs = array_unique($dhcrelayifs);
1399

    
1400
	/* fire up dhcrelay */
1401
	if (empty($dhcrelayifs)) {
1402
		log_error("No suitable interface found for running dhcrelay!");
1403
		return; /* XXX */
1404
	}
1405

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

    
1408
	if (isset($dhcrelaycfg['agentoption']))
1409
		$cmd .=  " -a -m replace";
1410

    
1411
	$cmd .= " " . implode(" ", $srvips);
1412
	mwexec($cmd);
1413
	unset($cmd);
1414

    
1415
	return 0;
1416
}
1417

    
1418
function services_dhcrelay6_configure() {
1419
	global $config, $g;
1420
	if ($g['platform'] == 'jail')
1421
		return;
1422
	if(isset($config['system']['developerspew'])) {
1423
		$mt = microtime();
1424
		echo "services_dhcrelay6_configure() being called $mt\n";
1425
	}
1426

    
1427
	/* kill any running dhcrelay */
1428
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1429

    
1430
	$dhcrelaycfg =& $config['dhcrelay6'];
1431

    
1432
	/* DHCPv6 Relay enabled on any interfaces? */
1433
	if (!isset($dhcrelaycfg['enable']))
1434
		return 0;
1435

    
1436
	if ($g['booting'])
1437
		echo gettext("Starting DHCPv6 relay service...");
1438
	else
1439
		sleep(1);
1440

    
1441
	$iflist = get_configured_interface_list();
1442

    
1443
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1444
	foreach ($dhcifaces as $dhcrelayif) {
1445
		if (!isset($iflist[$dhcrelayif]) ||
1446
			link_interface_to_bridge($dhcrelayif))
1447
			continue;
1448

    
1449
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1450
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1451
	}
1452
	$dhcrelayifs = array_unique($dhcrelayifs);
1453

    
1454
	/*
1455
	 * In order for the relay to work, it needs to be active
1456
	 * on the interface in which the destination server sits.
1457
	 */
1458
	$srvips = explode(",", $dhcrelaycfg['server']);
1459
        $srvifaces = array();
1460
	foreach ($srvips as $srcidx => $srvip) {
1461
		unset($destif);
1462
		foreach ($iflist as $ifname) {
1463
			$subnet = get_interface_ipv6($ifname);
1464
			if (!is_ipaddrv6($subnet))
1465
				continue;
1466
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1467
			if (ip_in_subnet($srvip, $subnet)) {
1468
				$destif = get_real_interface($ifname);
1469
				break;
1470
			}
1471
		}
1472
		if (!isset($destif)) {
1473
			if (is_array($config['staticroutes']['route'])) {
1474
				foreach ($config['staticroutes']['route'] as $rtent) {
1475
					if (ip_in_subnet($srvip, $rtent['network'])) {
1476
						$a_gateways = return_gateways_array(true);
1477
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1478
						break;
1479
					}
1480
				}
1481
			}
1482
		}
1483

    
1484
		if (!isset($destif)) {
1485
			/* Create a array from the existing route table */
1486
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1487
        		array_shift($route_str);
1488
        		array_shift($route_str);
1489
        		array_shift($route_str);
1490
        		array_shift($route_str);
1491
        		$route_arr = array();
1492
        		foreach($route_str as $routeline) {
1493
                		$items = preg_split("/[ ]+/i", $routeline);
1494
				if (ip_in_subnet($srvip, $items[0])) {
1495
					$destif = trim($items[6]);
1496
					break;
1497
				}
1498
        		}
1499
		}
1500

    
1501
		if (!isset($destif)) {
1502
			if (is_array($config['gateways']['gateway_item'])) {
1503
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1504
					if (isset($gateway['defaultgw'])) {
1505
						$destif = $gateway['interface'];
1506
						break;
1507
					}
1508
				}
1509
			} else
1510
				$destif = get_real_interface("wan");
1511
		}
1512

    
1513
		if (!empty($destif)) {
1514
			$srvifaces[] = "{$srvip}%{$destif}";
1515
		}
1516
	}
1517

    
1518
	/* fire up dhcrelay */
1519
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1520
		log_error("No suitable interface found for running dhcrelay -6!");
1521
		return; /* XXX */
1522
	}
1523

    
1524
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1525
	foreach ($dhcrelayifs as $dhcrelayif) {
1526
		$cmd .= " -l {$dhcrelayif}";
1527
	}
1528
	foreach ($srvifaces as $srviface) {
1529
		$cmd .= " -u \"{$srviface}\"";
1530
	}
1531
	mwexec($cmd);
1532
	unset($cmd);
1533

    
1534
	return 0;
1535
}
1536

    
1537
function services_dyndns_configure_client($conf) {
1538

    
1539
	if (!isset($conf['enable']))
1540
		return;
1541

    
1542
	/* load up the dyndns.class */
1543
	require_once("dyndns.class");
1544

    
1545
	$dns = new updatedns($dnsService = $conf['type'],
1546
		$dnsHost = $conf['host'],
1547
		$dnsUser = $conf['username'],
1548
		$dnsPass = $conf['password'],
1549
		$dnsWilcard = $conf['wildcard'],
1550
		$dnsMX = $conf['mx'],
1551
		$dnsIf = "{$conf['interface']}",
1552
		$dnsBackMX = NULL,
1553
		$dnsServer = NULL,
1554
		$dnsPort = NULL,
1555
		$dnsUpdateURL = "{$conf['updateurl']}",
1556
		$forceUpdate = $conf['force'],
1557
		$dnsZoneID=$conf['zoneid'],
1558
		$dnsTTL=$conf['ttl'],
1559
		$dnsResultMatch = "{$conf['resultmatch']}",
1560
		$dnsRequestIf = "{$conf['requestif']}",
1561
		$dnsID = "{$conf['id']}",
1562
		$dnsVerboseLog = $conf['verboselog']);
1563
}
1564

    
1565
function services_dyndns_configure($int = "") {
1566
	global $config, $g;
1567
	if(isset($config['system']['developerspew'])) {
1568
		$mt = microtime();
1569
		echo "services_dyndns_configure() being called $mt\n";
1570
	}
1571

    
1572
	$dyndnscfg = $config['dyndnses']['dyndns'];
1573
	$gwgroups = return_gateway_groups_array();
1574
	if (is_array($dyndnscfg)) {
1575
		if ($g['booting'])
1576
			echo gettext("Starting DynDNS clients...");
1577

    
1578
		foreach ($dyndnscfg as $dyndns) {
1579
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1580
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1581
				services_dyndns_configure_client($dyndns);
1582
				sleep(1);
1583
			}
1584
		}
1585

    
1586
		if ($g['booting'])
1587
			echo gettext("done.") . "\n";
1588
	}
1589

    
1590
	return 0;
1591
}
1592

    
1593
function dyndnsCheckIP($int) {
1594
	global $config;
1595
	$ip_address = get_interface_ip($int);
1596
	if (is_private_ip($ip_address)) {
1597
		$gateways_status = return_gateways_status(true);
1598
		// If the gateway for this interface is down, then the external check cannot work.
1599
		// Avoid the long wait for the external check to timeout.
1600
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1601
			return "down";
1602
		$hosttocheck = "http://checkip.dyndns.org";
1603
		$ip_ch = curl_init($hosttocheck);
1604
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1605
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1606
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1607
		curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1608
		curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1609
		curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1610
		$ip_result_page = curl_exec($ip_ch);
1611
		curl_close($ip_ch);
1612
		$ip_result_decoded = urldecode($ip_result_page);
1613
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1614
		$ip_address = trim($matches[1]);
1615
	}
1616
	return $ip_address;
1617
}
1618

    
1619
function services_dnsmasq_configure() {
1620
	global $config, $g;
1621
	$return = 0;
1622

    
1623
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1624
	$standard_args = array(
1625
		"dns-forward-max" => "--dns-forward-max=5000",
1626
		"cache-size" => "--cache-size=10000",
1627
		"local-ttl" => "--local-ttl=1"
1628
	);
1629

    
1630

    
1631
	if(isset($config['system']['developerspew'])) {
1632
		$mt = microtime();
1633
		echo "services_dnsmasq_configure() being called $mt\n";
1634
	}
1635

    
1636
	/* kill any running dnsmasq */
1637
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1638
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1639

    
1640
	if (isset($config['dnsmasq']['enable'])) {
1641

    
1642
		if ($g['booting'])
1643
			echo gettext("Starting DNS forwarder...");
1644
		else
1645
			sleep(1);
1646

    
1647
		/* generate hosts file */
1648
		if(system_hosts_generate()!=0)
1649
			$return = 1;
1650

    
1651
		$args = "";
1652

    
1653
		if (isset($config['dnsmasq']['regdhcp'])) {
1654
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1655
		}
1656

    
1657
		/* Setup listen port, if non-default */
1658
		if (is_port($config['dnsmasq']['port']))
1659
			$args .= " --port={$config['dnsmasq']['port']} ";
1660

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

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

    
1720
		/* Setup forwarded domains */
1721
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1722
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1723
				if ($override['ip'] == "!")
1724
					$override[ip] = "";
1725
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1726
			}
1727
		}
1728

    
1729
		/* Allow DNS Rebind for forwarded domains */
1730
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1731
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1732
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1733
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1734
				}
1735
			}
1736
		}
1737

    
1738
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1739
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1740

    
1741
		if (isset($config['dnsmasq']['strict_order'])) {
1742
			$args .= " --strict-order ";
1743
		}
1744

    
1745
		if (isset($config['dnsmasq']['domain_needed'])) {
1746
			$args .= " --domain-needed ";
1747
		}
1748

    
1749
		if ($config['dnsmasq']['custom_options'])
1750
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1751
				$args .= " " . escapeshellarg("--{$c}");
1752
				$p = explode('=', $c);
1753
				if (array_key_exists($p[0], $standard_args))
1754
					unset($standard_args[$p[0]]);
1755
			}
1756
		$args .= ' ' . implode(' ', array_values($standard_args));
1757

    
1758
		/* run dnsmasq */
1759
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1760
		//log_error("dnsmasq command: {$cmd}");
1761
		mwexec_bg($cmd);
1762
		unset($args);
1763

    
1764
		if ($g['booting'])
1765
			echo gettext("done.") . "\n";
1766
	}
1767

    
1768
	if (!$g['booting']) {
1769
		if(services_dhcpd_configure()!=0)
1770
			$return = 1;
1771
	}
1772

    
1773
	return $return;
1774
}
1775

    
1776
function services_snmpd_configure() {
1777
	global $config, $g;
1778
	if(isset($config['system']['developerspew'])) {
1779
		$mt = microtime();
1780
		echo "services_snmpd_configure() being called $mt\n";
1781
	}
1782

    
1783
	/* kill any running snmpd */
1784
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1785
	sleep(2);
1786
	if(is_process_running("bsnmpd"))
1787
		mwexec("/usr/bin/killall bsnmpd", true);
1788

    
1789
	if (isset($config['snmpd']['enable'])) {
1790

    
1791
		if ($g['booting'])
1792
			echo gettext("Starting SNMP daemon... ");
1793

    
1794
		/* generate snmpd.conf */
1795
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1796
		if (!$fd) {
1797
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1798
			return 1;
1799
		}
1800

    
1801

    
1802
		$snmpdconf = <<<EOD
1803
location := "{$config['snmpd']['syslocation']}"
1804
contact := "{$config['snmpd']['syscontact']}"
1805
read := "{$config['snmpd']['rocommunity']}"
1806

    
1807
EOD;
1808

    
1809
/* No docs on what write strings do there for disable for now.
1810
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1811
		    $snmpdconf .= <<<EOD
1812
# write string
1813
write := "{$config['snmpd']['rwcommunity']}"
1814

    
1815
EOD;
1816
		}
1817
*/
1818

    
1819

    
1820
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1821
		    $snmpdconf .= <<<EOD
1822
# SNMP Trap support.
1823
traphost := {$config['snmpd']['trapserver']}
1824
trapport := {$config['snmpd']['trapserverport']}
1825
trap := "{$config['snmpd']['trapstring']}"
1826

    
1827

    
1828
EOD;
1829
		}
1830

    
1831
		$version = trim(file_get_contents('/etc/version'));
1832
		$platform = trim(file_get_contents('/etc/platform'));
1833
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1834
			$platform = $g['product_name'];
1835
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1836
			" {$version} {$platform} " . php_uname("s") .
1837
			" " . php_uname("r") . " " . php_uname("m");
1838

    
1839
		$snmpdconf .= <<<EOD
1840
system := 1     # pfSense
1841
%snmpd
1842
sysDescr			= "{$sysDescr}"
1843
begemotSnmpdDebugDumpPdus       = 2
1844
begemotSnmpdDebugSyslogPri      = 7
1845
begemotSnmpdCommunityString.0.1 = $(read)
1846

    
1847
EOD;
1848

    
1849
/* No docs on what write strings do there for disable for now.
1850
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1851
		    $snmpdconf .= <<<EOD
1852
begemotSnmpdCommunityString.0.2 = $(write)
1853

    
1854
EOD;
1855
		}
1856
*/
1857

    
1858

    
1859
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1860
		    $snmpdconf .= <<<EOD
1861
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1862
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1863
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1864

    
1865
EOD;
1866
		}
1867

    
1868

    
1869
		$snmpdconf .= <<<EOD
1870
begemotSnmpdCommunityDisable    = 1
1871

    
1872
EOD;
1873

    
1874
		if (isset($config['snmpd']['bindlan'])) {
1875
			$config['snmpd']['bindip'] = 'lan';
1876
			unset($config['snmpd']['bindlan']);
1877
		}
1878
		$bind_to_ip = "0.0.0.0";
1879
		if(isset($config['snmpd']['bindip'])) {
1880
			if (is_ipaddr($config['snmpd']['bindip'])) {
1881
				$bind_to_ip = $config['snmpd']['bindip'];
1882
			} else {
1883
				$if = get_real_interface($config['snmpd']['bindip']);
1884
				if (does_interface_exist($if))
1885
					$bind_to_ip = find_interface_ip($if);
1886
			}
1887
		}
1888

    
1889
		if(is_port( $config['snmpd']['pollport'] )) {
1890
		    $snmpdconf .= <<<EOD
1891
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
1892

    
1893
EOD;
1894

    
1895
		}
1896

    
1897
		$snmpdconf .= <<<EOD
1898
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
1899
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
1900

    
1901
# These are bsnmp macros not php vars.
1902
sysContact      = $(contact)
1903
sysLocation     = $(location)
1904
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
1905

    
1906
snmpEnableAuthenTraps = 2
1907

    
1908
EOD;
1909

    
1910
		if (is_array( $config['snmpd']['modules'] )) {
1911
		    if(isset($config['snmpd']['modules']['mibii'])) {
1912
			$snmpdconf .= <<<EOD
1913
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
1914

    
1915
EOD;
1916
		    }
1917

    
1918
		    if(isset($config['snmpd']['modules']['netgraph'])) {
1919
			$snmpdconf .= <<<EOD
1920
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
1921
%netgraph
1922
begemotNgControlNodeName = "snmpd"
1923

    
1924
EOD;
1925
		    }
1926

    
1927
		    if(isset($config['snmpd']['modules']['pf'])) {
1928
			$snmpdconf .= <<<EOD
1929
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
1930

    
1931
EOD;
1932
		    }
1933

    
1934
		    if(isset($config['snmpd']['modules']['hostres'])) {
1935
			$snmpdconf .= <<<EOD
1936
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
1937

    
1938
EOD;
1939
		    }
1940
		    if(isset($config['snmpd']['modules']['bridge'])) {
1941
			$snmpdconf .= <<<EOD
1942
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
1943
# config must end with blank line
1944

    
1945
EOD;
1946
		    }
1947
			if(isset($config['snmpd']['modules']['ucd'])) {
1948
				$snmpdconf .= <<<EOD
1949
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
1950

    
1951
EOD;
1952
			}
1953
			if(isset($config['snmpd']['modules']['regex'])) {
1954
				$snmpdconf .= <<<EOD
1955
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
1956

    
1957
EOD;
1958
			}
1959
		}
1960

    
1961
		fwrite($fd, $snmpdconf);
1962
		fclose($fd);
1963
		unset($snmpdconf);
1964

    
1965
		if (isset($config['snmpd']['bindlan'])) {
1966
			$bindlan = "";
1967
		}
1968

    
1969
		/* run bsnmpd */
1970
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
1971
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
1972

    
1973
		if ($g['booting'])
1974
			echo gettext("done.") . "\n";
1975
	}
1976

    
1977
	return 0;
1978
}
1979

    
1980
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
1981
	global $config, $g;
1982
	if(isset($config['system']['developerspew'])) {
1983
		$mt = microtime();
1984
		echo "services_dnsupdate_process() being called $mt\n";
1985
	}
1986

    
1987
	/* Dynamic DNS updating active? */
1988
	if (is_array($config['dnsupdates']['dnsupdate'])) {
1989
		$notify_text = "";
1990
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
1991
			if (!isset($dnsupdate['enable']))
1992
				continue;
1993
			if (!empty($int) && $int != $dnsupdate['interface'])
1994
				continue;
1995
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
1996
				continue;
1997

    
1998
			/* determine interface name */
1999
			$if = get_real_interface($dnsupdate['interface']);
2000
			if (isset($dnsupdate['usepublicip']))
2001
                                $wanip = dyndnsCheckIP($dnsupdate['interface']);
2002
                        else
2003
                                $wanip = get_interface_ip($dnsupdate['interface']);
2004
			
2005
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2006
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2007
			$currentTime = time();
2008

    
2009
			if ($wanip || $wanipv6) {
2010
				$keyname = $dnsupdate['keyname'];
2011
				/* trailing dot */
2012
				if (substr($keyname, -1) != ".")
2013
					$keyname .= ".";
2014

    
2015
				$hostname = $dnsupdate['host'];
2016
				/* trailing dot */
2017
				if (substr($hostname, -1) != ".")
2018
					$hostname .= ".";
2019

    
2020
				/* write private key file
2021
				   this is dumb - public and private keys are the same for HMAC-MD5,
2022
				   but nsupdate insists on having both */
2023
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2024
				$privkey = <<<EOD
2025
Private-key-format: v1.2
2026
Algorithm: 157 (HMAC)
2027
Key: {$dnsupdate['keydata']}
2028

    
2029
EOD;
2030
				fwrite($fd, $privkey);
2031
				fclose($fd);
2032

    
2033
				/* write public key file */
2034
				if ($dnsupdate['keytype'] == "zone") {
2035
					$flags = 257;
2036
					$proto = 3;
2037
				} else if ($dnsupdate['keytype'] == "host") {
2038
					$flags = 513;
2039
					$proto = 3;
2040
				} else if ($dnsupdate['keytype'] == "user") {
2041
					$flags = 0;
2042
					$proto = 2;
2043
				}
2044

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

    
2049
				/* generate update instructions */
2050
				$upinst = "";
2051
				if (!empty($dnsupdate['server']))
2052
					$upinst .= "server {$dnsupdate['server']}\n";
2053

    
2054
				if (file_exists($cacheFile)) {
2055
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2056
				}
2057
				if (file_exists("{$cacheFile}.ipv6")) {
2058
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2059
				}
2060

    
2061
				// 25 Days
2062
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2063
				$need_update = false;
2064

    
2065
				conf_mount_rw();
2066
				/* Update IPv4 if we have it. */
2067
				if (is_ipaddrv4($wanip)) {
2068
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2069
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2070
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2071
						$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";
2072
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2073
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2074
						$need_update = true;
2075
					} else {
2076
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2077
					}
2078
				} else
2079
					@unlink($cacheFile);
2080

    
2081
				/* Update IPv6 if we have it. */
2082
				if (is_ipaddrv6($wanipv6)) {
2083
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2084
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2085
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2086
						$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";
2087
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2088
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2089
						$need_update = true;
2090
					} else {
2091
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2092
					}
2093
				} else
2094
					@unlink("{$cacheFile}.ipv6");
2095
				conf_mount_ro();
2096

    
2097
				$upinst .= "\n";	/* mind that trailing newline! */
2098

    
2099
				if ($need_update) {
2100
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2101
					unset($upinst);
2102
					/* invoke nsupdate */
2103
					$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2104
					if (isset($dnsupdate['usetcp']))
2105
						$cmd .= " -v";
2106
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2107
					mwexec_bg($cmd);
2108
					unset($cmd);
2109
				}
2110
			}
2111
		}
2112
		if (!empty($notify_text)) {
2113
			notify_all_remote($notify_text);
2114
		}
2115
	}
2116

    
2117
	return 0;
2118
}
2119

    
2120
/* configure cron service */
2121
function configure_cron() {
2122
	global $g, $config;
2123

    
2124
	conf_mount_rw();
2125
	/* preserve existing crontab entries */
2126
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2127

    
2128
	for ($i = 0; $i < count($crontab_contents); $i++) {
2129
		$cron_item =& $crontab_contents[$i];
2130
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2131
			array_splice($crontab_contents, $i - 1);
2132
			break;
2133
		}
2134
	}
2135
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2136

    
2137

    
2138
	if (is_array($config['cron']['item'])) {
2139
		$crontab_contents .= "#\n";
2140
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2141
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2142
		$crontab_contents .= "#\n";
2143

    
2144
		foreach ($config['cron']['item'] as $item) {
2145
			$crontab_contents .= "\n{$item['minute']}\t";
2146
			$crontab_contents .= "{$item['hour']}\t";
2147
			$crontab_contents .= "{$item['mday']}\t";
2148
			$crontab_contents .= "{$item['month']}\t";
2149
			$crontab_contents .= "{$item['wday']}\t";
2150
			$crontab_contents .= "{$item['who']}\t";
2151
			$crontab_contents .= "{$item['command']}";
2152
		}
2153

    
2154
		$crontab_contents .= "\n#\n";
2155
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2156
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2157
		$crontab_contents .= "#\n\n";
2158
	}
2159

    
2160
	/* please maintain the newline at the end of file */
2161
	file_put_contents("/etc/crontab", $crontab_contents);
2162
	unset($crontab_contents);
2163

    
2164
	/* do a HUP kill to force sync changes */
2165
	exec('/bin/pkill -HUP cron');
2166

    
2167
	conf_mount_ro();
2168
}
2169

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

    
2193
function upnp_start() {
2194
	global $config;
2195

    
2196
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2197
		return;
2198

    
2199
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2200
		echo gettext("Starting UPnP service... ");
2201
		require_once('/usr/local/pkg/miniupnpd.inc');
2202
		sync_package_miniupnpd();
2203
		echo "done.\n";
2204
	}
2205
}
2206

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

    
2210
	$is_installed = false;
2211

    
2212
	if (!is_array($config['cron']))
2213
		$config['cron'] = array();
2214
	if (!is_array($config['cron']['item']))
2215
		$config['cron']['item'] = array();
2216

    
2217
	$x=0;
2218
	foreach($config['cron']['item'] as $item) {
2219
		if(strstr($item['command'], $command)) {
2220
			$is_installed = true;
2221
			break;
2222
		}
2223
		$x++;
2224
	}
2225

    
2226
	if($active) {
2227
		$cron_item = array();
2228
		$cron_item['minute'] = $minute;
2229
		$cron_item['hour'] = $hour;
2230
		$cron_item['mday'] = $monthday;
2231
		$cron_item['month'] = $month;
2232
		$cron_item['wday'] = $weekday;
2233
		$cron_item['who'] = $who;
2234
		$cron_item['command'] = $command;
2235
		if(!$is_installed) {
2236
			$config['cron']['item'][] = $cron_item;
2237
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2238
		} else {
2239
			$config['cron']['item'][$x] = $cron_item;
2240
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2241
		}
2242
	} else {
2243
		if($is_installed == true) {
2244
			unset($config['cron']['item'][$x]);
2245
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2246
		}
2247
	}
2248
	configure_cron();
2249
}
2250

    
2251
?>
(49-49/66)