Projet

Général

Profil

Télécharger (75,8 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / services.inc @ 86ce2df7

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 cloudflare custom custom-v6 eurodns gratisdns ovh-dynhost citynetwork');
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,City Network');
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 (!function_exists('is_package_installed'))
362
		require_once('pkg-utils.inc');
363
	if (is_package_installed('olsrd') && isset($config['installedpackages']['olsrd']))
364
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
365
			if (isset($olsrd['enable']) && $olsrd['enable'] == "on") {
366
				$is_olsr_enabled = true;
367
				break;
368
			}
369

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

    
387
	$syscfg = $config['system'];
388
	if (!is_array($config['dhcpd']))
389
		$config['dhcpd'] = array();
390
	$dhcpdcfg = $config['dhcpd'];
391
	$Iflist = get_configured_interface_list();
392

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

    
403
	if ($g['booting'])
404
		echo gettext("Starting DHCP service...");
405
	else
406
		sleep(1);
407

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

    
421
	$dhcpdconf = <<<EOD
422

    
423
option domain-name "{$syscfg['domain']}";
424
option ldap-server code 95 = text;
425
option domain-search-list code 119 = text;
426
option arch code 93 = unsigned integer 16; # RFC4578
427
{$custoptions}
428
default-lease-time 7200;
429
max-lease-time 86400;
430
log-facility local7;
431
one-lease-per-client true;
432
deny duplicates;
433
ping-check true;
434
update-conflict-detection false;
435

    
436
EOD;
437

    
438
	if(!isset($dhcpifconf['disableauthoritative']))
439
		$dhcpdconf .= "authoritative;\n";
440

    
441
	if(isset($dhcpifconf['alwaysbroadcast']))
442
		$dhcpdconf .= "always-broadcast on\n";
443

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

    
456
	/*    loop through and determine if we need to setup
457
	 *    failover peer "bleh" entries
458
	 */
459
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
460

    
461
		interfaces_staticarp_configure($dhcpif);
462

    
463
		if (!isset($dhcpifconf['enable']))
464
			continue;
465

    
466
		if($dhcpifconf['failover_peerip'] <> "") {
467
			$intip = get_interface_ip($dhcpif);
468
			/*
469
			 *    yep, failover peer is defined.
470
			 *    does it match up to a defined vip?
471
			 */
472
			$skew = 110;
473
			if(is_array($config['virtualip']['vip'])) {
474
				foreach ($config['virtualip']['vip'] as $vipent) {
475
					if($vipent['interface'] == $dhcpif) {
476
						$carp_nw = gen_subnet($vipent['subnet'], $vipent['subnet_bits']);
477
						if (ip_in_subnet($dhcpifconf['failover_peerip'], "{$carp_nw}/{$vipent['subnet_bits']}")) {
478
							/* this is the interface! */
479
							if(is_numeric($vipent['advskew']) && (intval($vipent['advskew']) < 20)) {
480
								$skew = 0;
481
								break;
482
							}
483
						}
484
					}
485
				}
486
			} else {
487
				log_error(gettext("Warning!  DHCP Failover setup and no CARP virtual IPs defined!"));
488
			}
489
			if($skew > 10) {
490
				$type = "secondary";
491
				$my_port = "520";
492
				$peer_port = "519";
493
			} else {
494
				$my_port = "519";
495
				$peer_port = "520";
496
				$type = "primary";
497
				$dhcpdconf_pri  = "split 128;\n";
498
				$dhcpdconf_pri .= "  mclt 600;\n";
499
			}
500

    
501
			if (is_ipaddrv4($intip)) {
502
			$dhcpdconf .= <<<EOPP
503
failover peer "dhcp_{$dhcpif}" {
504
  {$type};
505
  address {$intip};
506
  port {$my_port};
507
  peer address {$dhcpifconf['failover_peerip']};
508
  peer port {$peer_port};
509
  max-response-delay 10;
510
  max-unacked-updates 10;
511
  {$dhcpdconf_pri}
512
  load balance max seconds 3;
513
}
514
\n
515
EOPP;
516
			}
517
		}
518
	}
519

    
520
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
521

    
522
		$newzone = array();
523
		$ifcfg = $config['interfaces'][$dhcpif];
524

    
525
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
526
			continue;
527
		$ifcfgip = get_interface_ip($dhcpif);
528
		$ifcfgsn = get_interface_subnet($dhcpif);
529
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
530
		$subnetmask = gen_subnet_mask($ifcfgsn);
531

    
532
		if (!is_ipaddr($subnet))
533
			continue;
534

    
535
		if($is_olsr_enabled == true)
536
			if($dhcpifconf['netmask'])
537
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
538

    
539
		$all_pools = array();
540
		$all_pools[] = $dhcpifconf;
541
		if (is_array($dhcpifconf['pool'])) {
542
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
543
		}
544

    
545
		$dnscfg = "";
546

    
547
		if ($dhcpifconf['domain']) {
548
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
549
		}
550

    
551
		if($dhcpifconf['domainsearchlist'] <> "") {
552
			$dnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpifconf['domainsearchlist'])) . "\";\n";
553
		}
554

    
555
		if (isset($dhcpifconf['ddnsupdate'])) {
556
			$need_ddns_updates = true;
557
			$newzone = array();
558
			if($dhcpifconf['ddnsdomain'] <> "") {
559
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
560
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
561
			} else {
562
				$newzone['domain-name'] = $config['system']['domain'];
563
			}
564
			$revsubnet = explode(".", $subnet);
565
			$revsubnet = array_reverse($revsubnet);
566
			foreach ($revsubnet as $octet) {
567
				if ($octet != "0")
568
					break;
569
				array_shift($revsubnet);
570
			}
571
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
572
		}
573

    
574
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
575
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
576
			if ($newzone['domain-name'])
577
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
578
		} else if (isset($config['dnsmasq']['enable'])) {
579
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
580
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0]))
581
				$newzone['dns-servers'] = $syscfg['dnsserver'];
582
		} else if (!empty($dns_arrv4)) {
583
			$dnscfg .= "	option domain-name-servers " . join(",", $dns_arrv4) . ";";
584
			if ($newzone['domain-name'])
585
				$newzone['dns-servers'] = $dns_arrv4;
586
		}
587

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

    
609
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
610

    
611
// Setup pool options
612
		foreach($all_pools as $poolconf) {
613
			$dhcpdconf .= "	pool {\n";
614
			/* is failover dns setup? */
615
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
616
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
617
				if($poolconf['dnsserver'][1] <> "")
618
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
619
				$dhcpdconf .= ";\n";
620
			}
621

    
622
			/* allow/deny MACs */
623
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
624
			foreach ($mac_allow_list as $mac) {
625
				if (empty($mac))
626
					continue;
627
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
628
			}
629
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
630
			foreach ($mac_deny_list as $mac) {
631
				if (empty($mac))
632
					continue;
633
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
634
			}
635

    
636
			if($poolconf['failover_peerip'] <> "")
637
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
638

    
639
			if (isset($poolconf['denyunknown']))
640
			   $dhcpdconf .= "		deny unknown-clients;\n";
641

    
642
			if ($poolconf['gateway'] && $poolconf['gateway'] != "none" && ($poolconf['gateway'] != $dhcpifconf['gateway']))
643
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
644

    
645
			if($dhcpifconf['failover_peerip'] <> "") {
646
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
647
			}
648

    
649
			$pdnscfg = "";
650

    
651
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
652
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
653
			}
654

    
655
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
656
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
657
			}
658

    
659
			if (isset($poolconf['ddnsupdate'])) {
660
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
661
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
662
				$pdnscfg .= "		ddns-update-style interim;\n";
663
			}
664

    
665
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
666
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
667
			}
668
			$dhcpdconf .= "{$pdnscfg}";
669

    
670
			// default-lease-time
671
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
672
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
673

    
674
			// max-lease-time
675
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
676
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
677

    
678
			// netbios-name*
679
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
680
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
681
				$dhcpdconf .= "		option netbios-node-type 8;\n";
682
			}
683

    
684
			// ntp-servers
685
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
686
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
687

    
688
			// tftp-server-name
689
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp']))
690
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
691

    
692
			// ldap-server
693
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
694
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
695

    
696
			// net boot information
697
			if(isset($poolconf['netboot'])) {
698
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
699
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
700
				}
701
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
702
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
703
				}
704
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
705
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
706
				}
707
			}
708
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
709
			$dhcpdconf .= "	}\n\n";
710
		}
711
// End of settings inside pools
712

    
713
		if ($dhcpifconf['gateway'] && $dhcpifconf['gateway'] != "none") {
714
			$routers = $dhcpifconf['gateway'];
715
			$add_routers = true;
716
		} elseif ($dhcpifconf['gateway'] == "none") {
717
			$add_routers = false;
718
		} else {
719
			$routers = $ifcfgip;
720
		}
721
		if($add_routers)
722
			$dhcpdconf .= "	option routers {$routers};\n";
723

    
724
		$dhcpdconf .= <<<EOD
725
$dnscfg
726

    
727
EOD;
728
    		// default-lease-time
729
		if ($dhcpifconf['defaultleasetime'])
730
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
731

    
732
		// max-lease-time
733
		if ($dhcpifconf['maxleasetime'])
734
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
735

    
736
		// netbios-name*
737
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
738
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
739
			$dhcpdconf .= "	option netbios-node-type 8;\n";
740
		}
741

    
742
		// ntp-servers
743
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
744
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
745

    
746
		// tftp-server-name
747
		if ($dhcpifconf['tftp'] <> "")
748
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
749

    
750
		// Handle option, number rowhelper values
751
		$dhcpdconf .= "\n";
752
		if($dhcpifconf['numberoptions']['item']) {
753
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
754
				if(empty($item['type']) || $item['type'] == "text")
755
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
756
				else
757
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
758
			}
759
		}
760

    
761
		// ldap-server
762
		if ($dhcpifconf['ldap'] <> "")
763
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
764

    
765
		// net boot information
766
		if(isset($dhcpifconf['netboot'])) {
767
			if ($dhcpifconf['nextserver'] <> "") {
768
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
769
			}
770
			if (!empty($dhcpifconf['filename']) && !empty($dhcpifconf['filename32']) && !empty($dhcpifconf['filename64'])) {
771
				$dhcpdconf .= "	if option arch = 00:06 {\n";
772
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename32']}\";\n";
773
				$dhcpdconf .= "	} else if option arch = 00:07 {\n";
774
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename64']}\";\n";
775
				$dhcpdconf .= "	} else {\n";
776
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename']}\";\n";
777
				$dhcpdconf .= "	}\n\n";
778
			} elseif (!empty($dhcpifconf['filename'])) {
779
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
780
			}
781
			if (!empty($dhcpifconf['rootpath'])) {
782
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
783
			}
784
		}
785

    
786
		$dhcpdconf .= <<<EOD
787
}
788

    
789
EOD;
790

    
791
		/* add static mappings */
792
		if (is_array($dhcpifconf['staticmap'])) {
793

    
794
			$i = 0;
795
			foreach ($dhcpifconf['staticmap'] as $sm) {
796
				$dhcpdconf .= "host s_{$dhcpif}_{$i} {\n";
797

    
798
                if ($sm['mac'])
799
                    $dhcpdconf .= "        hardware ethernet {$sm['mac']};\n";
800

    
801
                if ($sm['cid'])
802
                    $dhcpdconf .= "        option dhcp-client-identifier \"{$sm['cid']}\";\n";
803

    
804
				if ($sm['ipaddr'])
805
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
806

    
807
				if ($sm['hostname']) {
808
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
809
					$dhhostname = str_replace(".", "_", $dhhostname);
810
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
811
				}
812
				if ($sm['filename'])
813
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
814

    
815
				if ($sm['rootpath'])
816
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
817

    
818
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
819
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
820

    
821
				$smdnscfg = "";
822

    
823
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
824
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
825
				}
826

    
827
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
828
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
829
				}
830

    
831
				if (isset($sm['ddnsupdate'])) {
832
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain']))
833
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
834
					$pdnscfg .= "		ddns-update-style interim;\n";
835
				}
836

    
837
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
838
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
839
				}
840
				$dhcpdconf .= "{$smdnscfg}";
841

    
842
				// default-lease-time
843
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime']))
844
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
845

    
846
				// max-lease-time
847
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
848
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
849

    
850
				// netbios-name*
851
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
852
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
853
					$dhcpdconf .= "	option netbios-node-type 8;\n";
854
				}
855

    
856
				// ntp-servers
857
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
858
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
859

    
860
				// tftp-server-name
861
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
862
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
863

    
864
				$dhcpdconf .= "}\n";
865
				$i++;
866
			}
867
		}
868

    
869
		$dhcpdifs[] = get_real_interface($dhcpif);
870
		if ($newzone['domain-name'])
871
		{
872
			if ($need_ddns_updates)
873
			{
874
				$newzone['dns-servers'] = array($dhcpifconf['ddnsdomainprimary']);
875
			}
876
			$ddns_zones[] = $newzone;
877
		}
878
	}
879

    
880
	if ($need_ddns_updates) {
881
		$dhcpdconf .= "ddns-update-style interim;\n";
882
		$dhcpdconf .= "update-static-leases on;\n";
883

    
884
		$dhcpdconf .= dhcpdkey($dhcpifconf);
885
		$dhcpdconf .= dhcpdzones($ddns_zones, $dhcpifconf);
886
	}
887

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

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

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

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

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

    
913
	return 0;
914
}
915

    
916
function dhcpdkey($dhcpifconf)
917
{
918
	$dhcpdconf = "";
919
	if ($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "")
920
	{
921
		$dhcpdconf .= "key {$dhcpifconf['ddnsdomainkeyname']} {\n";
922
		$dhcpdconf .= "	algorithm hmac-md5;\n";
923
		$dhcpdconf .= "	secret {$dhcpifconf['ddnsdomainkey']};\n";
924
		$dhcpdconf .= "}\n";
925
	}
926

    
927
	return $dhcpdconf;
928
}
929

    
930
function dhcpdzones($ddns_zones, $dhcpifconf)
931
{
932
	$dhcpdconf = "";
933

    
934
	if (is_array($ddns_zones)) {
935
		$added_zones = array();
936
		foreach ($ddns_zones as $zone) {
937
			if (!is_array($zone) || empty($zone) || !is_array($zone['dns-servers']))
938
				continue;
939
			$primary = $zone['dns-servers'][0];
940
			$secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1];
941

    
942
			// Make sure we aren't using any invalid or IPv6 DNS servers.
943
			if (!is_ipaddrv4($primary)) {
944
				if (is_ipaddrv4($secondary)) {
945
					$primary = $secondary;
946
					$secondary = "";
947
				} else {
948
					continue;
949
				}
950
			}
951

    
952
			// We don't need to add zones multiple times.
953
			if ($zone['domain-name'] && !in_array($zone['domain-name'], $added_zones)) {
954
				$dhcpdconf .= "zone {$zone['domain-name']}. {\n";
955
				$dhcpdconf .= "	primary {$primary};\n";
956
				if (is_ipaddrv4($secondary))
957
					$dhcpdconf .= "	secondary {$secondary};\n";
958
				if($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "")
959
                    $dhcpdconf .= "	key {$dhcpifconf['ddnsdomainkeyname']};\n";
960
				$dhcpdconf .= "}\n";
961
				$added_zones[] = $zone['domain-name'];
962
			}
963
			if ($zone['ptr-domain'] && !in_array($zone['ptr-domain'], $added_zones)) {
964
				$dhcpdconf .= "zone {$zone['ptr-domain']} {\n";
965
				$dhcpdconf .= "	primary {$primary};\n";
966
				if (is_ipaddrv4($secondary))
967
					$dhcpdconf .= "	secondary {$secondary};\n";
968
				if($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "")
969
                    $dhcpdconf .= "	key {$dhcpifconf['ddnsdomainkeyname']};\n";
970
				$dhcpdconf .= "}\n";
971
				$added_zones[] = $zone['ptr-domain'];
972
			}
973
		}
974
	}
975

    
976
	return $dhcpdconf;
977
}
978

    
979
function services_dhcpdv6_configure($blacklist = array()) {
980
	global $config, $g;
981

    
982
	if($g['services_dhcp_server_enable'] == false)
983
		return;
984

    
985
	if(isset($config['system']['developerspew'])) {
986
		$mt = microtime();
987
		echo "services_dhcpd_configure($if) being called $mt\n";
988
	}
989

    
990
	/* kill any running dhcpd */
991
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
992
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
993
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
994
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
995

    
996
	/* DHCP enabled on any interfaces? */
997
	if (!is_dhcpv6_server_enabled())
998
		return 0;
999

    
1000
	if ($g['booting']) {
1001
		if ($g['platform'] != "pfSense") {
1002
			/* restore the leases, if we have them */
1003
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
1004
				$dhcprestore = "";
1005
				$dhcpreturn = "";
1006
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
1007
				$dhcprestore = implode(" ", $dhcprestore);
1008
				if($dhcpreturn <> 0) {
1009
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
1010
				}
1011
			}
1012
		}
1013
	}
1014

    
1015
	$syscfg = $config['system'];
1016
	if (!is_array($config['dhcpdv6']))
1017
		$config['dhcpdv6'] = array();
1018
	$dhcpdv6cfg = $config['dhcpdv6'];
1019
	$Iflist = get_configured_interface_list();
1020
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
1021

    
1022

    
1023
	if ($g['booting'])
1024
		echo "Starting DHCPv6 service...";
1025
	else
1026
		sleep(1);
1027

    
1028
	/* we add a fake entry for interfaces that are set to track6 another WAN */
1029
	foreach ($Iflist as $ifname) {
1030
		/* Do not put in the config an interface which is down */
1031
		if (isset($blacklist[$ifname]))
1032
			continue;
1033
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
1034
			$realif = get_real_interface($ifname, "inet6");
1035
			$ifcfgipv6 = get_interface_ipv6($ifname);
1036
			if(!is_ipaddrv6($ifcfgipv6))
1037
				continue;
1038
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
1039
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
1040
			$trackcfg = $config['interfaces'][$trackifname];
1041
			$pdlen = calculate_ipv6_delegation_length($trackifname);
1042
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
1043
			$dhcpdv6cfg[$ifname] = array();
1044
			$dhcpdv6cfg[$ifname]['enable'] = true;
1045
			/* range */
1046
			$ifcfgipv6arr[7] = "1000";
1047
			$dhcpdv6cfg[$ifname]['range'] = array();
1048
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
1049
			$ifcfgipv6arr[7] = "2000";
1050
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
1051
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
1052
			if($pdlen > 2) {
1053
				$pdlenmax = $pdlen;
1054
				$pdlenhalf = $pdlenmax -1;
1055
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
1056
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
1057
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
1058

    
1059
				/* set the delegation start to half the current address block */
1060
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
1061
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
1062

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

    
1067
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
1068
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
1069
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
1070
			}
1071
		}
1072
	}
1073

    
1074
	$custoptionsv6 = "";
1075
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1076
		if(is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
1077
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1078
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
1079
			}
1080
		}
1081
	}
1082

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

    
1086
	$dhcpdv6conf = <<<EOD
1087

    
1088
option domain-name "{$syscfg['domain']}";
1089
option ldap-server code 95 = text;
1090
option domain-search-list code 119 = text;
1091
{$custoptionsv6}
1092
default-lease-time 7200;
1093
max-lease-time 86400;
1094
log-facility local7;
1095
one-lease-per-client true;
1096
deny duplicates;
1097
ping-check true;
1098
update-conflict-detection false;
1099

    
1100
EOD;
1101

    
1102
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1103
		$dhcpdv6conf .= "authoritative;\n";
1104

    
1105
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1106
		$dhcpdv6conf .= "always-broadcast on\n";
1107

    
1108
	$dhcpdv6ifs = array();
1109

    
1110
	$dhcpv6num = 0;
1111
	$nsupdate = false;
1112

    
1113
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1114

    
1115
		$ddns_zones = array();
1116

    
1117
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1118

    
1119
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1120
			continue;
1121
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1122
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1123
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1124

    
1125
		if ($is_olsr_enabled == true) {
1126
			if($dhcpv6ifconf['netmask'])
1127
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1128
		}
1129

    
1130
		$dnscfgv6 = "";
1131

    
1132
		if ($dhcpv6ifconf['domain']) {
1133
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1134
		}
1135

    
1136
    	if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1137
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1138
    	}
1139

    
1140
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1141
			if($dhcpv6ifconf['ddnsdomain'] <> "") {
1142
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1143
			}
1144
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1145
			$nsupdate = true;
1146
		}
1147

    
1148
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1149
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1150
		} else if ((isset($config['dnsmasq']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1151
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1152
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1153
			$dns_arrv6 = array();
1154
			foreach($syscfg['dnsserver'] as $dnsserver) {
1155
				if (is_ipaddrv6($dnsserver)) {
1156
					$dns_arrv6[] = $dnsserver;
1157
				}
1158
			}
1159
			if(!empty($dns_arrv6))
1160
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1161
		}
1162

    
1163
		if ($dhcpv6ifconf['domain']) {
1164
			$newzone = array();
1165
			$newzone['domain-name'] = $dhcpv6ifconf['domain']; 
1166
			$newzone['dns-servers'][] = $dhcpv6ifconf['ddnsdomainprimary'];
1167
			$ddns_zones[] = $newzone;
1168
		}
1169

    
1170
		if (is_ipaddrv6($ifcfgipv6)) {
1171
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1172
		} else {
1173
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1174
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1175
		}
1176
		$dhcpdv6conf .= " {\n";
1177

    
1178
		$dhcpdv6conf .= <<<EOD
1179
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1180
$dnscfgv6
1181

    
1182
EOD;
1183

    
1184
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1185
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']}/{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1186
		}
1187
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1188
			$dhcpdv6conf .= "       option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1189
		}
1190
    		// default-lease-time
1191
		if ($dhcpv6ifconf['defaultleasetime'])
1192
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1193

    
1194
		// max-lease-time
1195
		if ($dhcpv6ifconf['maxleasetime'])
1196
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1197

    
1198
		// ntp-servers
1199
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1200
			$ntpservers = array();
1201
			foreach($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1202
				if(is_ipaddrv6($ntpserver))
1203
					$ntpservers[] = $ntpserver;
1204
			}
1205
			if(count($ntpservers) > 0 )
1206
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1207
		}
1208
		// tftp-server-name
1209
		/* Needs ISC DHCPD support
1210
		 if ($dhcpv6ifconf['tftp'] <> "")
1211
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1212
		*/
1213

    
1214
		// Handle option, number rowhelper values
1215
		$dhcpdv6conf .= "\n";
1216
		if ($dhcpv6ifconf['numberoptions']['item']) {
1217
			foreach($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1218
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1219
			}
1220
		}
1221

    
1222
		// ldap-server
1223
		if ($dhcpv6ifconf['ldap'] <> "")
1224
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1225

    
1226
		// net boot information
1227
		if(isset($dhcpv6ifconf['netboot'])) {
1228
			if (!empty($dhcpv6ifconf['bootfile_url'])) {
1229
				$dhcpdv6conf .= "	option dhcp6.bootfile-url \"{$dhcpv6ifconf['bootfile_url']}\";\n";
1230
			}
1231
		}
1232

    
1233
		$dhcpdv6conf .= "}\n";
1234

    
1235
		/* add static mappings */
1236
		/* Needs to use DUID */
1237
		if (is_array($dhcpv6ifconf['staticmap'])) {
1238
			$i = 0;
1239
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1240
				$dhcpdv6conf .= <<<EOD
1241
host s_{$dhcpv6if}_{$i} {
1242
	host-identifier option dhcp6.client-id {$sm['duid']};
1243

    
1244
EOD;
1245
				if ($sm['ipaddrv6'])
1246
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1247

    
1248
				if ($sm['hostname']) {
1249
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1250
					$dhhostname = str_replace(".", "_", $dhhostname);
1251
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1252
				}
1253
				if ($sm['filename'])
1254
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1255

    
1256
				if ($sm['rootpath'])
1257
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1258

    
1259
				$dhcpdv6conf .= "}\n";
1260
				$i++;
1261
			}
1262
		}
1263

    
1264
		if ($dhcpv6ifconf['domain'])
1265
		{
1266
			$dhcpdv6conf .= dhcpdkey($dhcpv6ifconf);
1267
			$dhcpdv6conf .= dhcpdzones($ddns_zones, $dhcpv6ifconf);
1268
		}
1269

    
1270
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged") {
1271
			if(preg_match("/poes/si", $dhcpv6if)) {
1272
				/* magic here */
1273
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1274
			} else {
1275
				$realif = get_real_interface($dhcpv6if, "inet6");
1276
				if (stristr("$realif", "bridge")) {
1277
					$mac = get_interface_mac($realif);
1278
					$v6address = generate_ipv6_from_mac($mac);
1279
					/* Create link local address for bridges */
1280
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1281
				}
1282
				$realif = escapeshellcmd($realif);
1283
				$dhcpdv6ifs[] = $realif;
1284
			}
1285
		}
1286
	}
1287

    
1288
	if ($nsupdate)
1289
	{
1290
		$dhcpdv6conf .= "ddns-update-style interim;\n";
1291
	}
1292
	else
1293
	{
1294
		$dhcpdv6conf .= "ddns-update-style none;\n";
1295
	}
1296

    
1297
	/* write dhcpdv6.conf */
1298
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1299
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1300
		if ($g['booting'])
1301
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1302
		unset($dhcpdv6conf);
1303
		return 1;
1304
	}
1305
	unset($dhcpdv6conf);
1306

    
1307
	/* create an empty leases v6 database */
1308
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1309
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1310

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

    
1315
	/* fire up dhcpd in a chroot */
1316
	if (count($dhcpdv6ifs) > 0) {
1317
		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 " .
1318
			join(" ", $dhcpdv6ifs));
1319
		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");
1320
	}
1321
	if ($g['booting'])
1322
		print gettext("done.") . "\n";
1323

    
1324
	return 0;
1325
}
1326

    
1327
function services_igmpproxy_configure() {
1328
        global $config, $g;
1329

    
1330
        /* kill any running igmpproxy */
1331
        killbyname("igmpproxy");
1332

    
1333
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1334
		return 1;
1335

    
1336
        $iflist = get_configured_interface_list();
1337

    
1338
        $igmpconf = <<<EOD
1339

    
1340
##------------------------------------------------------
1341
## Enable Quickleave mode (Sends Leave instantly)
1342
##------------------------------------------------------
1343
quickleave
1344

    
1345
EOD;
1346

    
1347
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1348
                unset($iflist[$igmpcf['ifname']]);
1349
                $realif = get_real_interface($igmpcf['ifname']);
1350
                if (empty($igmpcf['threshold']))
1351
                        $threshld = 1;
1352
                else
1353
                        $threshld = $igmpcf['threshold'];
1354
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1355

    
1356
                if ($igmpcf['address'] <> "") {
1357
                        $item = explode(" ", $igmpcf['address']);
1358
                        foreach($item as $iww)
1359
                                $igmpconf .= "altnet {$iww}\n";
1360
                }
1361
                $igmpconf .= "\n";
1362
        }
1363
        foreach ($iflist as $ifn) {
1364
                $realif = get_real_interface($ifn);
1365
                $igmpconf .= "phyint {$realif} disabled\n";
1366
        }
1367
	$igmpconf .= "\n";
1368

    
1369
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1370
        if (!$igmpfl) {
1371
                log_error(gettext("Could not write Igmpproxy configuration file!"));
1372
                return;
1373
        }
1374
        fwrite($igmpfl, $igmpconf);
1375
        fclose($igmpfl);
1376
	unset($igmpconf);
1377

    
1378
	/* NOTE: -d4 means everything LOG_WARNING and smaller */
1379
        mwexec("/usr/local/sbin/igmpproxy -d4 -c {$g['tmp_path']}/igmpproxy.conf");
1380
        log_error(gettext("Started IGMP proxy service."));
1381

    
1382
        return 0;
1383
}
1384

    
1385
function services_dhcrelay_configure() {
1386
	global $config, $g;
1387
	if ($g['platform'] == 'jail')
1388
		return;
1389
	if(isset($config['system']['developerspew'])) {
1390
		$mt = microtime();
1391
		echo "services_dhcrelay_configure() being called $mt\n";
1392
	}
1393

    
1394
	/* kill any running dhcrelay */
1395
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1396

    
1397
	$dhcrelaycfg =& $config['dhcrelay'];
1398

    
1399
	/* DHCPRelay enabled on any interfaces? */
1400
	if (!isset($dhcrelaycfg['enable']))
1401
		return 0;
1402

    
1403
	if ($g['booting'])
1404
		echo gettext("Starting DHCP relay service...");
1405
	else
1406
		sleep(1);
1407

    
1408
	$iflist = get_configured_interface_list();
1409

    
1410
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1411
	foreach ($dhcifaces as $dhcrelayif) {
1412
		if (!isset($iflist[$dhcrelayif]) ||
1413
			link_interface_to_bridge($dhcrelayif))
1414
			continue;
1415

    
1416
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1417
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1418
	}
1419

    
1420
	/*
1421
	 * In order for the relay to work, it needs to be active
1422
	 * on the interface in which the destination server sits.
1423
	 */
1424
	$srvips = explode(",", $dhcrelaycfg['server']);
1425
	foreach ($srvips as $srcidx => $srvip) {
1426
		unset($destif);
1427
		foreach ($iflist as $ifname) {
1428
			$subnet = get_interface_ip($ifname);
1429
			if (!is_ipaddr($subnet))
1430
				continue;
1431
			$subnet .=  "/" . get_interface_subnet($ifname);
1432
			if (ip_in_subnet($srvip, $subnet)) {
1433
				$destif = get_real_interface($ifname);
1434
				break;
1435
			}
1436
		}
1437
		if (!isset($destif)) {
1438
			foreach (get_staticroutes() as $rtent) {
1439
				if (ip_in_subnet($srvip, $rtent['network'])) {
1440
					$a_gateways = return_gateways_array(true);
1441
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1442
					break;
1443
				}
1444
			}
1445
		}
1446

    
1447
		if (!isset($destif)) {
1448
			/* Create a array from the existing route table */
1449
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
1450
        		array_shift($route_str);
1451
        		array_shift($route_str);
1452
        		array_shift($route_str);
1453
        		array_shift($route_str);
1454
        		$route_arr = array();
1455
        		foreach($route_str as $routeline) {
1456
				$items = preg_split("/[ ]+/i", $routeline);
1457
				if (is_subnetv4($items[0])) {
1458
					$subnet = $items[0];
1459
				} elseif (is_ipaddrv4($items[0])) {
1460
					$subnet = "{$items[0]}/32";
1461
				} else {
1462
					// Not a subnet or IP address, skip to the next line.
1463
					continue;
1464
				}
1465
				if (ip_in_subnet($srvip, $subnet)) {
1466
					$destif = trim($items[6]);
1467
					break;
1468
				}
1469
			}
1470
		}
1471

    
1472
		if (!isset($destif)) {
1473
			if (is_array($config['gateways']['gateway_item'])) {
1474
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1475
					if (isset($gateway['defaultgw'])) {
1476
						$destif = get_real_interface($gateway['interface']);
1477
						break;
1478
					}
1479
				}
1480
			} else
1481
				$destif = get_real_interface("wan");
1482
		}
1483

    
1484
		if (!empty($destif))
1485
			$dhcrelayifs[] = $destif;
1486
	}
1487
	$dhcrelayifs = array_unique($dhcrelayifs);
1488

    
1489
	/* fire up dhcrelay */
1490
	if (empty($dhcrelayifs)) {
1491
		log_error("No suitable interface found for running dhcrelay!");
1492
		return; /* XXX */
1493
	}
1494

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

    
1497
	if (isset($dhcrelaycfg['agentoption']))
1498
		$cmd .=  " -a -m replace";
1499

    
1500
	$cmd .= " " . implode(" ", $srvips);
1501
	mwexec($cmd);
1502
	unset($cmd);
1503

    
1504
	return 0;
1505
}
1506

    
1507
function services_dhcrelay6_configure() {
1508
	global $config, $g;
1509
	if ($g['platform'] == 'jail')
1510
		return;
1511
	if(isset($config['system']['developerspew'])) {
1512
		$mt = microtime();
1513
		echo "services_dhcrelay6_configure() being called $mt\n";
1514
	}
1515

    
1516
	/* kill any running dhcrelay */
1517
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1518

    
1519
	$dhcrelaycfg =& $config['dhcrelay6'];
1520

    
1521
	/* DHCPv6 Relay enabled on any interfaces? */
1522
	if (!isset($dhcrelaycfg['enable']))
1523
		return 0;
1524

    
1525
	if ($g['booting'])
1526
		echo gettext("Starting DHCPv6 relay service...");
1527
	else
1528
		sleep(1);
1529

    
1530
	$iflist = get_configured_interface_list();
1531

    
1532
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1533
	foreach ($dhcifaces as $dhcrelayif) {
1534
		if (!isset($iflist[$dhcrelayif]) ||
1535
			link_interface_to_bridge($dhcrelayif))
1536
			continue;
1537

    
1538
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1539
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1540
	}
1541
	$dhcrelayifs = array_unique($dhcrelayifs);
1542

    
1543
	/*
1544
	 * In order for the relay to work, it needs to be active
1545
	 * on the interface in which the destination server sits.
1546
	 */
1547
	$srvips = explode(",", $dhcrelaycfg['server']);
1548
        $srvifaces = array();
1549
	foreach ($srvips as $srcidx => $srvip) {
1550
		unset($destif);
1551
		foreach ($iflist as $ifname) {
1552
			$subnet = get_interface_ipv6($ifname);
1553
			if (!is_ipaddrv6($subnet))
1554
				continue;
1555
			$subnet .=  "/" . get_interface_subnetv6($ifname);
1556
			if (ip_in_subnet($srvip, $subnet)) {
1557
				$destif = get_real_interface($ifname);
1558
				break;
1559
			}
1560
		}
1561
		if (!isset($destif)) {
1562
			if (is_array($config['staticroutes']['route'])) {
1563
				foreach ($config['staticroutes']['route'] as $rtent) {
1564
					if (ip_in_subnet($srvip, $rtent['network'])) {
1565
						$a_gateways = return_gateways_array(true);
1566
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1567
						break;
1568
					}
1569
				}
1570
			}
1571
		}
1572

    
1573
		if (!isset($destif)) {
1574
			/* Create a array from the existing route table */
1575
        		exec("/usr/bin/netstat -rnWf inet6", $route_str);
1576
        		array_shift($route_str);
1577
        		array_shift($route_str);
1578
        		array_shift($route_str);
1579
        		array_shift($route_str);
1580
        		$route_arr = array();
1581
        		foreach($route_str as $routeline) {
1582
                		$items = preg_split("/[ ]+/i", $routeline);
1583
				if (ip_in_subnet($srvip, $items[0])) {
1584
					$destif = trim($items[6]);
1585
					break;
1586
				}
1587
        		}
1588
		}
1589

    
1590
		if (!isset($destif)) {
1591
			if (is_array($config['gateways']['gateway_item'])) {
1592
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1593
					if (isset($gateway['defaultgw'])) {
1594
						$destif = $gateway['interface'];
1595
						break;
1596
					}
1597
				}
1598
			} else
1599
				$destif = get_real_interface("wan");
1600
		}
1601

    
1602
		if (!empty($destif)) {
1603
			$srvifaces[] = "{$srvip}%{$destif}";
1604
		}
1605
	}
1606

    
1607
	/* fire up dhcrelay */
1608
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1609
		log_error("No suitable interface found for running dhcrelay -6!");
1610
		return; /* XXX */
1611
	}
1612

    
1613
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1614
	foreach ($dhcrelayifs as $dhcrelayif) {
1615
		$cmd .= " -l {$dhcrelayif}";
1616
	}
1617
	foreach ($srvifaces as $srviface) {
1618
		$cmd .= " -u \"{$srviface}\"";
1619
	}
1620
	mwexec($cmd);
1621
	unset($cmd);
1622

    
1623
	return 0;
1624
}
1625

    
1626
function services_dyndns_configure_client($conf) {
1627

    
1628
	if (!isset($conf['enable']))
1629
		return;
1630

    
1631
	/* load up the dyndns.class */
1632
	require_once("dyndns.class");
1633

    
1634
	$dns = new updatedns($dnsService = $conf['type'],
1635
		$dnsHost = $conf['host'],
1636
		$dnsUser = $conf['username'],
1637
		$dnsPass = $conf['password'],
1638
		$dnsWilcard = $conf['wildcard'],
1639
		$dnsMX = $conf['mx'],
1640
		$dnsIf = "{$conf['interface']}",
1641
		$dnsBackMX = NULL,
1642
		$dnsServer = NULL,
1643
		$dnsPort = NULL,
1644
		$dnsUpdateURL = "{$conf['updateurl']}",
1645
		$forceUpdate = $conf['force'],
1646
		$dnsZoneID=$conf['zoneid'],
1647
		$dnsTTL=$conf['ttl'],
1648
		$dnsResultMatch = "{$conf['resultmatch']}",
1649
		$dnsRequestIf = "{$conf['requestif']}",
1650
		$dnsID = "{$conf['id']}",
1651
		$dnsVerboseLog = $conf['verboselog'],
1652
		$curlIpresolveV4 = $conf['curl_ipresolve_v4'],
1653
		$curlSslVerifypeer = $conf['curl_ssl_verifypeer']);
1654
}
1655

    
1656
function services_dyndns_configure($int = "") {
1657
	global $config, $g;
1658
	if(isset($config['system']['developerspew'])) {
1659
		$mt = microtime();
1660
		echo "services_dyndns_configure() being called $mt\n";
1661
	}
1662

    
1663
	$dyndnscfg = $config['dyndnses']['dyndns'];
1664
	$gwgroups = return_gateway_groups_array();
1665
	if (is_array($dyndnscfg)) {
1666
		if ($g['booting'])
1667
			echo gettext("Starting DynDNS clients...");
1668

    
1669
		foreach ($dyndnscfg as $dyndns) {
1670
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1671
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1672
				$dyndns['curl_ipresolve_v4'] = isset($dyndns['curl_ipresolve_v4']);
1673
				$dyndns['curl_ssl_verifypeer'] = isset($dyndns['curl_ssl_verifypeer']);
1674
				services_dyndns_configure_client($dyndns);
1675
				sleep(1);
1676
			}
1677
		}
1678

    
1679
		if ($g['booting'])
1680
			echo gettext("done.") . "\n";
1681
	}
1682

    
1683
	return 0;
1684
}
1685

    
1686
function dyndnsCheckIP($int) {
1687
	global $config;
1688
	$ip_address = get_interface_ip($int);
1689
	if (is_private_ip($ip_address)) {
1690
		$gateways_status = return_gateways_status(true);
1691
		// If the gateway for this interface is down, then the external check cannot work.
1692
		// Avoid the long wait for the external check to timeout.
1693
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'],"down"))
1694
			return "down";
1695
		$hosttocheck = "http://checkip.dyndns.org";
1696
		$ip_ch = curl_init($hosttocheck);
1697
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1698
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1699
		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
1700
		curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1701
		curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1702
		curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1703
		$ip_result_page = curl_exec($ip_ch);
1704
		curl_close($ip_ch);
1705
		$ip_result_decoded = urldecode($ip_result_page);
1706
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1707
		$ip_address = trim($matches[1]);
1708
	}
1709
	return $ip_address;
1710
}
1711

    
1712
function services_dnsmasq_configure() {
1713
	global $config, $g;
1714
	$return = 0;
1715

    
1716
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1717
	$standard_args = array(
1718
		"dns-forward-max" => "--dns-forward-max=5000",
1719
		"cache-size" => "--cache-size=10000",
1720
		"local-ttl" => "--local-ttl=1"
1721
	);
1722

    
1723

    
1724
	if(isset($config['system']['developerspew'])) {
1725
		$mt = microtime();
1726
		echo "services_dnsmasq_configure() being called $mt\n";
1727
	}
1728

    
1729
	/* kill any running dnsmasq */
1730
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1731
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1732

    
1733
	if (isset($config['dnsmasq']['enable'])) {
1734

    
1735
		if ($g['booting'])
1736
			echo gettext("Starting DNS forwarder...");
1737
		else
1738
			sleep(1);
1739

    
1740
		$args = "";
1741

    
1742
		if (isset($config['dnsmasq']['regdhcp'])) {
1743
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1744
		}
1745

    
1746
		/* Setup listen port, if non-default */
1747
		if (is_port($config['dnsmasq']['port']))
1748
			$args .= " --port={$config['dnsmasq']['port']} ";
1749

    
1750
		$listen_addresses = "";
1751
		if(isset($config['dnsmasq']['interface'])) {
1752
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1753
			foreach ($interfaces as $interface) {
1754
				if (is_ipaddrv4($interface)) {
1755
					$listen_addresses .= " --listen-address={$interface} ";
1756
				} else if (is_ipaddrv6($interface)) {
1757
					/*
1758
					 * XXX: Since dnsmasq does not support link-local address
1759
					 * with scope specified. These checks are being done.
1760
					 */
1761
					if (is_linklocal($interface) && strstr($interface, "%")) {
1762
						$tmpaddrll6 = explode("%", $interface);
1763
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1764
					} else 
1765
						$listen_addresses .= " --listen-address={$interface} ";
1766
				} else {
1767
					$if = get_real_interface($interface);
1768
					if (does_interface_exist($if)) {
1769
						$laddr = find_interface_ip($if);
1770
						if (is_ipaddrv4($laddr))
1771
							$listen_addresses .= " --listen-address={$laddr} ";
1772
						$laddr6 = find_interface_ipv6($if);
1773
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
1774
							/*
1775
							 * XXX: Since dnsmasq does not support link-local address
1776
							 * with scope specified. These checks are being done.
1777
							 */
1778
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
1779
								$tmpaddrll6 = explode("%", $laddr6);
1780
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
1781
							} else
1782
								$listen_addresses .= " --listen-address={$laddr6} ";
1783
						}
1784
					}
1785
				}
1786
			}
1787
			if (!empty($listen_addresses)) {
1788
				$args .= " {$listen_addresses} ";
1789
				if (isset($config['dnsmasq']['strictbind']))
1790
					$args .= " --bind-interfaces ";
1791
			}
1792
		}
1793

    
1794
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
1795
		/* If any of these are duplicated by a user-specified domain override (e.g. 10.in-addr.arpa) then */
1796
		/* the user-specified entry made later on the command line below will be the one that is effective. */
1797
		if (isset($config['dnsmasq']['no_private_reverse'])) {
1798
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
1799
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
1800
			/* Just the pfSense WAN might get a CGN address from an ISP. */
1801
			$args .= " --server=/10.in-addr.arpa/ ";
1802
			$args .= " --server=/168.192.in-addr.arpa/ ";
1803
			/* Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme. */
1804
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) { 
1805
				$args .= " --server=/" . $subnet_num . ".172.in-addr.arpa/ ";
1806
			}
1807
		}
1808

    
1809
		/* Setup forwarded domains */
1810
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1811
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1812
				if ($override['ip'] == "!")
1813
					$override[ip] = "";
1814
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1815
			}
1816
		}
1817

    
1818
		/* Allow DNS Rebind for forwarded domains */
1819
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1820
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1821
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1822
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1823
				}
1824
			}
1825
		}
1826

    
1827
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1828
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1829

    
1830
		if (isset($config['dnsmasq']['strict_order'])) {
1831
			$args .= " --strict-order ";
1832
		}
1833

    
1834
		if (isset($config['dnsmasq']['domain_needed'])) {
1835
			$args .= " --domain-needed ";
1836
		}
1837

    
1838
		if ($config['dnsmasq']['custom_options'])
1839
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1840
				$args .= " " . escapeshellarg("--{$c}");
1841
				$p = explode('=', $c);
1842
				if (array_key_exists($p[0], $standard_args))
1843
					unset($standard_args[$p[0]]);
1844
			}
1845
		$args .= ' ' . implode(' ', array_values($standard_args));
1846

    
1847
		/* run dnsmasq */
1848
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1849
		//log_error("dnsmasq command: {$cmd}");
1850
		mwexec_bg($cmd);
1851
		unset($args);
1852

    
1853
		if ($g['booting'])
1854
			echo gettext("done.") . "\n";
1855
	}
1856

    
1857
	if (!$g['booting']) {
1858
		if(services_dhcpd_configure()!=0)
1859
			$return = 1;
1860
	}
1861

    
1862
	return $return;
1863
}
1864

    
1865
function services_unbound_configure() {
1866
	global $config, $g;
1867
	$return = 0;
1868

    
1869
	if (isset($config['system']['developerspew'])) {
1870
		$mt = microtime();
1871
		echo "services_unbound_configure() being called $mt\n";
1872
	}
1873

    
1874
	// kill any running Unbound instance
1875
	if (file_exists("{$g['varrun_path']}/unbound.pid"))
1876
		sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
1877

    
1878
	if (isset($config['unbound']['enable'])) {
1879
		if ($g['booting'])
1880
			echo gettext("Starting DNS Resolver...");
1881
		else
1882
			sleep(1);
1883

    
1884
		require_once('/etc/inc/unbound.inc');
1885
		sync_unbound_service();
1886
		if ($g['booting'])
1887
			echo gettext("done.") . "\n";
1888
	}
1889

    
1890
	if (!$g['booting']) {
1891
		if (services_dhcpd_configure()!=0)
1892
			$return = 1;
1893
	}
1894

    
1895
	return $return;
1896
}
1897

    
1898
function services_snmpd_configure() {
1899
	global $config, $g;
1900
	if(isset($config['system']['developerspew'])) {
1901
		$mt = microtime();
1902
		echo "services_snmpd_configure() being called $mt\n";
1903
	}
1904

    
1905
	/* kill any running snmpd */
1906
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1907
	sleep(2);
1908
	if(is_process_running("bsnmpd"))
1909
		mwexec("/usr/bin/killall bsnmpd", true);
1910

    
1911
	if (isset($config['snmpd']['enable'])) {
1912

    
1913
		if ($g['booting'])
1914
			echo gettext("Starting SNMP daemon... ");
1915

    
1916
		/* generate snmpd.conf */
1917
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1918
		if (!$fd) {
1919
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1920
			return 1;
1921
		}
1922

    
1923

    
1924
		$snmpdconf = <<<EOD
1925
location := "{$config['snmpd']['syslocation']}"
1926
contact := "{$config['snmpd']['syscontact']}"
1927
read := "{$config['snmpd']['rocommunity']}"
1928

    
1929
EOD;
1930

    
1931
/* No docs on what write strings do there for disable for now.
1932
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1933
		    $snmpdconf .= <<<EOD
1934
# write string
1935
write := "{$config['snmpd']['rwcommunity']}"
1936

    
1937
EOD;
1938
		}
1939
*/
1940

    
1941

    
1942
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1943
		    $snmpdconf .= <<<EOD
1944
# SNMP Trap support.
1945
traphost := {$config['snmpd']['trapserver']}
1946
trapport := {$config['snmpd']['trapserverport']}
1947
trap := "{$config['snmpd']['trapstring']}"
1948

    
1949

    
1950
EOD;
1951
		}
1952

    
1953
		$version = trim(file_get_contents('/etc/version'));
1954
		$platform = trim(file_get_contents('/etc/platform'));
1955
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1956
			$platform = $g['product_name'];
1957
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1958
			" {$version} {$platform} " . php_uname("s") .
1959
			" " . php_uname("r") . " " . php_uname("m");
1960

    
1961
		$snmpdconf .= <<<EOD
1962
system := 1     # pfSense
1963
%snmpd
1964
sysDescr			= "{$sysDescr}"
1965
begemotSnmpdDebugDumpPdus       = 2
1966
begemotSnmpdDebugSyslogPri      = 7
1967
begemotSnmpdCommunityString.0.1 = $(read)
1968

    
1969
EOD;
1970

    
1971
/* No docs on what write strings do there for disable for now.
1972
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1973
		    $snmpdconf .= <<<EOD
1974
begemotSnmpdCommunityString.0.2 = $(write)
1975

    
1976
EOD;
1977
		}
1978
*/
1979

    
1980

    
1981
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1982
		    $snmpdconf .= <<<EOD
1983
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1984
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1985
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1986

    
1987
EOD;
1988
		}
1989

    
1990

    
1991
		$snmpdconf .= <<<EOD
1992
begemotSnmpdCommunityDisable    = 1
1993

    
1994
EOD;
1995

    
1996
		if (isset($config['snmpd']['bindlan'])) {
1997
			$config['snmpd']['bindip'] = 'lan';
1998
			unset($config['snmpd']['bindlan']);
1999
		}
2000
		$bind_to_ip = "0.0.0.0";
2001
		if(isset($config['snmpd']['bindip'])) {
2002
			if (is_ipaddr($config['snmpd']['bindip'])) {
2003
				$bind_to_ip = $config['snmpd']['bindip'];
2004
			} else {
2005
				$if = get_real_interface($config['snmpd']['bindip']);
2006
				if (does_interface_exist($if))
2007
					$bind_to_ip = find_interface_ip($if);
2008
			}
2009
		}
2010

    
2011
		if(is_port( $config['snmpd']['pollport'] )) {
2012
		    $snmpdconf .= <<<EOD
2013
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
2014

    
2015
EOD;
2016

    
2017
		}
2018

    
2019
		$snmpdconf .= <<<EOD
2020
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
2021
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
2022

    
2023
# These are bsnmp macros not php vars.
2024
sysContact      = $(contact)
2025
sysLocation     = $(location)
2026
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
2027

    
2028
snmpEnableAuthenTraps = 2
2029

    
2030
EOD;
2031

    
2032
		if (is_array( $config['snmpd']['modules'] )) {
2033
		    if(isset($config['snmpd']['modules']['mibii'])) {
2034
			$snmpdconf .= <<<EOD
2035
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
2036

    
2037
EOD;
2038
		    }
2039

    
2040
		    if(isset($config['snmpd']['modules']['netgraph'])) {
2041
			$snmpdconf .= <<<EOD
2042
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
2043
%netgraph
2044
begemotNgControlNodeName = "snmpd"
2045

    
2046
EOD;
2047
		    }
2048

    
2049
		    if(isset($config['snmpd']['modules']['pf'])) {
2050
			$snmpdconf .= <<<EOD
2051
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
2052

    
2053
EOD;
2054
		    }
2055

    
2056
		    if(isset($config['snmpd']['modules']['hostres'])) {
2057
			$snmpdconf .= <<<EOD
2058
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
2059

    
2060
EOD;
2061
		    }
2062
		    if(isset($config['snmpd']['modules']['bridge'])) {
2063
			$snmpdconf .= <<<EOD
2064
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
2065
# config must end with blank line
2066

    
2067
EOD;
2068
		    }
2069
			if(isset($config['snmpd']['modules']['ucd'])) {
2070
				$snmpdconf .= <<<EOD
2071
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
2072

    
2073
EOD;
2074
			}
2075
			if(isset($config['snmpd']['modules']['regex'])) {
2076
				$snmpdconf .= <<<EOD
2077
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
2078

    
2079
EOD;
2080
			}
2081
		}
2082

    
2083
		fwrite($fd, $snmpdconf);
2084
		fclose($fd);
2085
		unset($snmpdconf);
2086

    
2087
		if (isset($config['snmpd']['bindlan'])) {
2088
			$bindlan = "";
2089
		}
2090

    
2091
		/* run bsnmpd */
2092
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
2093
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
2094

    
2095
		if ($g['booting'])
2096
			echo gettext("done.") . "\n";
2097
	}
2098

    
2099
	return 0;
2100
}
2101

    
2102
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
2103
	global $config, $g;
2104
	if(isset($config['system']['developerspew'])) {
2105
		$mt = microtime();
2106
		echo "services_dnsupdate_process() being called $mt\n";
2107
	}
2108

    
2109
	/* Dynamic DNS updating active? */
2110
	if (is_array($config['dnsupdates']['dnsupdate'])) {
2111
		$notify_text = "";
2112
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
2113
			if (!isset($dnsupdate['enable']))
2114
				continue;
2115
			if (!empty($int) && $int != $dnsupdate['interface'])
2116
				continue;
2117
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
2118
				continue;
2119

    
2120
			/* determine interface name */
2121
			$if = get_real_interface($dnsupdate['interface']);
2122
			
2123
			if (isset($dnsupdate['usepublicip']))
2124
                                $wanip = dyndnsCheckIP($dnsupdate['interface']);
2125
                        else
2126
                                $wanip = get_interface_ip($dnsupdate['interface']);
2127
			
2128
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2129
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2130
			$currentTime = time();
2131

    
2132
			if ($wanip || $wanipv6) {
2133
				$keyname = $dnsupdate['keyname'];
2134
				/* trailing dot */
2135
				if (substr($keyname, -1) != ".")
2136
					$keyname .= ".";
2137

    
2138
				$hostname = $dnsupdate['host'];
2139
				/* trailing dot */
2140
				if (substr($hostname, -1) != ".")
2141
					$hostname .= ".";
2142

    
2143
				/* write private key file
2144
				   this is dumb - public and private keys are the same for HMAC-MD5,
2145
				   but nsupdate insists on having both */
2146
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2147
				$privkey = <<<EOD
2148
Private-key-format: v1.2
2149
Algorithm: 157 (HMAC)
2150
Key: {$dnsupdate['keydata']}
2151

    
2152
EOD;
2153
				fwrite($fd, $privkey);
2154
				fclose($fd);
2155

    
2156
				/* write public key file */
2157
				if ($dnsupdate['keytype'] == "zone") {
2158
					$flags = 257;
2159
					$proto = 3;
2160
				} else if ($dnsupdate['keytype'] == "host") {
2161
					$flags = 513;
2162
					$proto = 3;
2163
				} else if ($dnsupdate['keytype'] == "user") {
2164
					$flags = 0;
2165
					$proto = 2;
2166
				}
2167

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

    
2172
				/* generate update instructions */
2173
				$upinst = "";
2174
				if (!empty($dnsupdate['server']))
2175
					$upinst .= "server {$dnsupdate['server']}\n";
2176

    
2177
				if (file_exists($cacheFile)) {
2178
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2179
				}
2180
				if (file_exists("{$cacheFile}.ipv6")) {
2181
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2182
				}
2183

    
2184
				// 25 Days
2185
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2186
				$need_update = false;
2187

    
2188
				conf_mount_rw();
2189
				/* Update IPv4 if we have it. */
2190
				if (is_ipaddrv4($wanip)) {
2191
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2192
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2193
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2194
						$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";
2195
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2196
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2197
						$need_update = true;
2198
					} else {
2199
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2200
					}
2201
				} else
2202
					@unlink($cacheFile);
2203

    
2204
				/* Update IPv6 if we have it. */
2205
				if (is_ipaddrv6($wanipv6)) {
2206
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2207
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2208
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2209
						$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";
2210
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2211
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2212
						$need_update = true;
2213
					} else {
2214
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2215
					}
2216
				} else
2217
					@unlink("{$cacheFile}.ipv6");
2218
				conf_mount_ro();
2219

    
2220
				$upinst .= "\n";	/* mind that trailing newline! */
2221

    
2222
				if ($need_update) {
2223
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2224
					unset($upinst);
2225
					/* invoke nsupdate */
2226
					$cmd = "/usr/local/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2227
					if (isset($dnsupdate['usetcp']))
2228
						$cmd .= " -v";
2229
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2230
					mwexec_bg($cmd);
2231
					unset($cmd);
2232
				}
2233
			}
2234
		}
2235
		if (!empty($notify_text)) {
2236
			notify_all_remote($notify_text);
2237
		}
2238
	}
2239

    
2240
	return 0;
2241
}
2242

    
2243
/* configure cron service */
2244
function configure_cron() {
2245
	global $g, $config;
2246

    
2247
	conf_mount_rw();
2248
	/* preserve existing crontab entries */
2249
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2250

    
2251
	for ($i = 0; $i < count($crontab_contents); $i++) {
2252
		$cron_item =& $crontab_contents[$i];
2253
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2254
			array_splice($crontab_contents, $i - 1);
2255
			break;
2256
		}
2257
	}
2258
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2259

    
2260

    
2261
	if (is_array($config['cron']['item'])) {
2262
		$crontab_contents .= "#\n";
2263
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2264
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2265
		$crontab_contents .= "#\n";
2266

    
2267
		foreach ($config['cron']['item'] as $item) {
2268
			$crontab_contents .= "\n{$item['minute']}\t";
2269
			$crontab_contents .= "{$item['hour']}\t";
2270
			$crontab_contents .= "{$item['mday']}\t";
2271
			$crontab_contents .= "{$item['month']}\t";
2272
			$crontab_contents .= "{$item['wday']}\t";
2273
			$crontab_contents .= "{$item['who']}\t";
2274
			$crontab_contents .= "{$item['command']}";
2275
		}
2276

    
2277
		$crontab_contents .= "\n#\n";
2278
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2279
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2280
		$crontab_contents .= "#\n\n";
2281
	}
2282

    
2283
	/* please maintain the newline at the end of file */
2284
	file_put_contents("/etc/crontab", $crontab_contents);
2285
	unset($crontab_contents);
2286

    
2287
	/* do a HUP kill to force sync changes */
2288
	sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
2289

    
2290
	conf_mount_ro();
2291
}
2292

    
2293
function upnp_action ($action) {
2294
	global $g, $config;
2295
	switch($action) {
2296
		case "start":
2297
			if (file_exists('/var/etc/miniupnpd.conf')) {
2298
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2299
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2300
			}
2301
			break;
2302
		case "stop":
2303
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2304
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2305
				mwexec('killall miniupnpd 2>/dev/null', true);
2306
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2307
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2308
			break;
2309
		case "restart":
2310
			upnp_action('stop');
2311
			upnp_action('start');
2312
			break;
2313
	}
2314
}
2315

    
2316
function upnp_start() {
2317
	global $config;
2318

    
2319
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2320
		return;
2321

    
2322
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2323
		echo gettext("Starting UPnP service... ");
2324
		require_once('/usr/local/pkg/miniupnpd.inc');
2325
		sync_package_miniupnpd();
2326
		echo "done.\n";
2327
	}
2328
}
2329

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

    
2333
	$is_installed = false;
2334

    
2335
	if (!is_array($config['cron']))
2336
		$config['cron'] = array();
2337
	if (!is_array($config['cron']['item']))
2338
		$config['cron']['item'] = array();
2339

    
2340
	$x=0;
2341
	foreach($config['cron']['item'] as $item) {
2342
		if(strstr($item['command'], $command)) {
2343
			$is_installed = true;
2344
			break;
2345
		}
2346
		$x++;
2347
	}
2348

    
2349
	if($active) {
2350
		$cron_item = array();
2351
		$cron_item['minute'] = $minute;
2352
		$cron_item['hour'] = $hour;
2353
		$cron_item['mday'] = $monthday;
2354
		$cron_item['month'] = $month;
2355
		$cron_item['wday'] = $weekday;
2356
		$cron_item['who'] = $who;
2357
		$cron_item['command'] = $command;
2358
		if(!$is_installed) {
2359
			$config['cron']['item'][] = $cron_item;
2360
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2361
		} else {
2362
			$config['cron']['item'][$x] = $cron_item;
2363
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2364
		}
2365
	} else {
2366
		if($is_installed == true) {
2367
			unset($config['cron']['item'][$x]);
2368
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2369
		}
2370
	}
2371
	configure_cron();
2372
}
2373

    
2374
?>
(50-50/68)