Projet

Général

Profil

Télécharger (76,4 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / services.inc @ 992f60d0

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
				if($poolconf['dnsserver'][2] <> "")
620
					$dhcpdconf .= ",{$poolconf['dnsserver'][2]}";
621
				if($poolconf['dnsserver'][3] <> "")
622
					$dhcpdconf .= ",{$poolconf['dnsserver'][3]}";
623
				$dhcpdconf .= ";\n";
624
			}
625

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

    
640
			if($poolconf['failover_peerip'] <> "")
641
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
642

    
643
			if (isset($poolconf['denyunknown']))
644
			   $dhcpdconf .= "		deny unknown-clients;\n";
645

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

    
649
			if($dhcpifconf['failover_peerip'] <> "") {
650
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
651
			}
652

    
653
			$pdnscfg = "";
654

    
655
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
656
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
657
			}
658

    
659
			if(!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
660
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
661
			}
662

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

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

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

    
678
			// max-lease-time
679
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime']))
680
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
681

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

    
688
			// ntp-servers
689
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
690
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
691

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

    
696
			// ldap-server
697
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap']))
698
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
699

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

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

    
728
		$dhcpdconf .= <<<EOD
729
$dnscfg
730

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

    
736
		// max-lease-time
737
		if ($dhcpifconf['maxleasetime'])
738
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
739

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

    
746
		// ntp-servers
747
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
748
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
749

    
750
		// tftp-server-name
751
		if ($dhcpifconf['tftp'] <> "")
752
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
753

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

    
765
		// ldap-server
766
		if ($dhcpifconf['ldap'] <> "")
767
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
768

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

    
790
		$dhcpdconf .= <<<EOD
791
}
792

    
793
EOD;
794

    
795
		/* add static mappings */
796
		if (is_array($dhcpifconf['staticmap'])) {
797

    
798
			$i = 0;
799
			foreach ($dhcpifconf['staticmap'] as $sm) {
800
				$dhcpdconf .= "host s_{$dhcpif}_{$i} {\n";
801

    
802
                if ($sm['mac'])
803
                    $dhcpdconf .= "        hardware ethernet {$sm['mac']};\n";
804

    
805
                if ($sm['cid'])
806
                    $dhcpdconf .= "        option dhcp-client-identifier \"{$sm['cid']}\";\n";
807

    
808
				if ($sm['ipaddr'])
809
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
810

    
811
				if ($sm['hostname']) {
812
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
813
					$dhhostname = str_replace(".", "_", $dhhostname);
814
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
815
				}
816
				if ($sm['filename'])
817
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
818

    
819
				if ($sm['rootpath'])
820
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
821

    
822
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway']))
823
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
824

    
825
				$smdnscfg = "";
826

    
827
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
828
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
829
				}
830

    
831
				if(!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
832
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
833
				}
834

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

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

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

    
850
				// max-lease-time
851
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime']))
852
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
853

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

    
860
				// ntp-servers
861
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0]))
862
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
863

    
864
				// tftp-server-name
865
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp']))
866
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
867

    
868
				$dhcpdconf .= "}\n";
869
				$i++;
870
			}
871
		}
872

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

    
884
	if ($need_ddns_updates) {
885
		$dhcpdconf .= "ddns-update-style interim;\n";
886
		$dhcpdconf .= "update-static-leases on;\n";
887

    
888
		$dhcpdconf .= dhcpdkey($dhcpifconf);
889
		$dhcpdconf .= dhcpdzones($ddns_zones, $dhcpifconf);
890
	}
891

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

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

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

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

    
914
	if ($g['booting'])
915
		print "done.\n";
916

    
917
	return 0;
918
}
919

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

    
931
	return $dhcpdconf;
932
}
933

    
934
function dhcpdzones($ddns_zones, $dhcpifconf)
935
{
936
	$dhcpdconf = "";
937

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

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

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

    
980
	return $dhcpdconf;
981
}
982

    
983
function services_dhcpdv6_configure($blacklist = array()) {
984
	global $config, $g;
985

    
986
	if($g['services_dhcp_server_enable'] == false)
987
		return;
988

    
989
	if(isset($config['system']['developerspew'])) {
990
		$mt = microtime();
991
		echo "services_dhcpd_configure($if) being called $mt\n";
992
	}
993

    
994
	/* kill any running dhcpd */
995
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid"))
996
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
997
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid"))
998
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
999

    
1000
	/* DHCP enabled on any interfaces? */
1001
	if (!is_dhcpv6_server_enabled())
1002
		return 0;
1003

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

    
1019
	$syscfg = $config['system'];
1020
	if (!is_array($config['dhcpdv6']))
1021
		$config['dhcpdv6'] = array();
1022
	$dhcpdv6cfg = $config['dhcpdv6'];
1023
	$Iflist = get_configured_interface_list();
1024
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
1025

    
1026

    
1027
	if ($g['booting'])
1028
		echo "Starting DHCPv6 service...";
1029
	else
1030
		sleep(1);
1031

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

    
1063
				/* set the delegation start to half the current address block */
1064
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
1065
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
1066

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

    
1071
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
1072
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
1073
				$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
1074
			}
1075
		}
1076
	}
1077

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

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

    
1090
	$dhcpdv6conf = <<<EOD
1091

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

    
1104
EOD;
1105

    
1106
	if(!isset($dhcpv6ifconf['disableauthoritative']))
1107
		$dhcpdv6conf .= "authoritative;\n";
1108

    
1109
	if(isset($dhcpv6ifconf['alwaysbroadcast']))
1110
		$dhcpdv6conf .= "always-broadcast on\n";
1111

    
1112
	$dhcpdv6ifs = array();
1113

    
1114
	$dhcpv6num = 0;
1115
	$nsupdate = false;
1116

    
1117
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1118

    
1119
		$ddns_zones = array();
1120

    
1121
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1122

    
1123
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]))
1124
			continue;
1125
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1126
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1127
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1128

    
1129
		if ($is_olsr_enabled == true) {
1130
			if($dhcpv6ifconf['netmask'])
1131
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1132
		}
1133

    
1134
		$dnscfgv6 = "";
1135

    
1136
		if ($dhcpv6ifconf['domain']) {
1137
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1138
		}
1139

    
1140
    	if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1141
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1142
    	}
1143

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

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

    
1167
		if ($dhcpv6ifconf['domain']) {
1168
			$newzone = array();
1169
			$newzone['domain-name'] = $dhcpv6ifconf['domain']; 
1170
			$newzone['dns-servers'][] = $dhcpv6ifconf['ddnsdomainprimary'];
1171
			$ddns_zones[] = $newzone;
1172
		}
1173

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

    
1182
		$dhcpdv6conf .= <<<EOD
1183
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1184
$dnscfgv6
1185

    
1186
EOD;
1187

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

    
1198
		// max-lease-time
1199
		if ($dhcpv6ifconf['maxleasetime'])
1200
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1201

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

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

    
1226
		// ldap-server
1227
		if ($dhcpv6ifconf['ldap'] <> "")
1228
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1229

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

    
1237
		$dhcpdv6conf .= "}\n";
1238

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

    
1248
EOD;
1249
				if ($sm['ipaddrv6'])
1250
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1251

    
1252
				if ($sm['hostname']) {
1253
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1254
					$dhhostname = str_replace(".", "_", $dhhostname);
1255
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1256
				}
1257
				if ($sm['filename'])
1258
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1259

    
1260
				if ($sm['rootpath'])
1261
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1262

    
1263
				$dhcpdv6conf .= "}\n";
1264
				$i++;
1265
			}
1266
		}
1267

    
1268
		if ($dhcpv6ifconf['domain'])
1269
		{
1270
			$dhcpdv6conf .= dhcpdkey($dhcpv6ifconf);
1271
			$dhcpdv6conf .= dhcpdzones($ddns_zones, $dhcpv6ifconf);
1272
		}
1273

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

    
1292
	if ($nsupdate)
1293
	{
1294
		$dhcpdv6conf .= "ddns-update-style interim;\n";
1295
	}
1296
	else
1297
	{
1298
		$dhcpdv6conf .= "ddns-update-style none;\n";
1299
	}
1300

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

    
1311
	/* create an empty leases v6 database */
1312
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"))
1313
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1314

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

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

    
1328
	return 0;
1329
}
1330

    
1331
function services_igmpproxy_configure() {
1332
        global $config, $g;
1333

    
1334
        /* kill any running igmpproxy */
1335
        killbyname("igmpproxy");
1336

    
1337
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0))
1338
		return 1;
1339

    
1340
        $iflist = get_configured_interface_list();
1341

    
1342
        $igmpconf = <<<EOD
1343

    
1344
##------------------------------------------------------
1345
## Enable Quickleave mode (Sends Leave instantly)
1346
##------------------------------------------------------
1347
quickleave
1348

    
1349
EOD;
1350

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

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

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

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

    
1386
        return 0;
1387
}
1388

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

    
1398
	/* kill any running dhcrelay */
1399
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1400

    
1401
	$dhcrelaycfg =& $config['dhcrelay'];
1402

    
1403
	/* DHCPRelay enabled on any interfaces? */
1404
	if (!isset($dhcrelaycfg['enable']))
1405
		return 0;
1406

    
1407
	if ($g['booting'])
1408
		echo gettext("Starting DHCP relay service...");
1409
	else
1410
		sleep(1);
1411

    
1412
	$iflist = get_configured_interface_list();
1413

    
1414
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1415
	foreach ($dhcifaces as $dhcrelayif) {
1416
		if (!isset($iflist[$dhcrelayif]) ||
1417
			link_interface_to_bridge($dhcrelayif))
1418
			continue;
1419

    
1420
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
1421
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1422
	}
1423

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

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

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

    
1488
		if (!empty($destif))
1489
			$dhcrelayifs[] = $destif;
1490
	}
1491
	$dhcrelayifs = array_unique($dhcrelayifs);
1492

    
1493
	/* fire up dhcrelay */
1494
	if (empty($dhcrelayifs)) {
1495
		log_error("No suitable interface found for running dhcrelay!");
1496
		return; /* XXX */
1497
	}
1498

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

    
1501
	if (isset($dhcrelaycfg['agentoption']))
1502
		$cmd .=  " -a -m replace";
1503

    
1504
	$cmd .= " " . implode(" ", $srvips);
1505
	mwexec($cmd);
1506
	unset($cmd);
1507

    
1508
	return 0;
1509
}
1510

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

    
1520
	/* kill any running dhcrelay */
1521
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1522

    
1523
	$dhcrelaycfg =& $config['dhcrelay6'];
1524

    
1525
	/* DHCPv6 Relay enabled on any interfaces? */
1526
	if (!isset($dhcrelaycfg['enable']))
1527
		return 0;
1528

    
1529
	if ($g['booting'])
1530
		echo gettext("Starting DHCPv6 relay service...");
1531
	else
1532
		sleep(1);
1533

    
1534
	$iflist = get_configured_interface_list();
1535

    
1536
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1537
	foreach ($dhcifaces as $dhcrelayif) {
1538
		if (!isset($iflist[$dhcrelayif]) ||
1539
			link_interface_to_bridge($dhcrelayif))
1540
			continue;
1541

    
1542
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif)))
1543
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1544
	}
1545
	$dhcrelayifs = array_unique($dhcrelayifs);
1546

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

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

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

    
1606
		if (!empty($destif)) {
1607
			$srvifaces[] = "{$srvip}%{$destif}";
1608
		}
1609
	}
1610

    
1611
	/* fire up dhcrelay */
1612
	if (empty($dhcrelayifs) || empty($srvifaces) ) {
1613
		log_error("No suitable interface found for running dhcrelay -6!");
1614
		return; /* XXX */
1615
	}
1616

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

    
1627
	return 0;
1628
}
1629

    
1630
function services_dyndns_configure_client($conf) {
1631

    
1632
	if (!isset($conf['enable']))
1633
		return;
1634

    
1635
	/* load up the dyndns.class */
1636
	require_once("dyndns.class");
1637

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

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

    
1667
	$dyndnscfg = $config['dyndnses']['dyndns'];
1668
	$gwgroups = return_gateway_groups_array();
1669
	if (is_array($dyndnscfg)) {
1670
		if ($g['booting'])
1671
			echo gettext("Starting DynDNS clients...");
1672

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

    
1683
		if ($g['booting'])
1684
			echo gettext("done.") . "\n";
1685
	}
1686

    
1687
	return 0;
1688
}
1689

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

    
1716
function services_dnsmasq_configure() {
1717
	global $config, $g;
1718
	$return = 0;
1719

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

    
1727

    
1728
	if(isset($config['system']['developerspew'])) {
1729
		$mt = microtime();
1730
		echo "services_dnsmasq_configure() being called $mt\n";
1731
	}
1732

    
1733
	/* kill any running dnsmasq */
1734
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
1735
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1736

    
1737
	if (isset($config['dnsmasq']['enable'])) {
1738

    
1739
		if ($g['booting'])
1740
			echo gettext("Starting DNS forwarder...");
1741
		else
1742
			sleep(1);
1743

    
1744
                /* generate hosts file */
1745
                if(system_hosts_generate()!=0)
1746
                        $return = 1;
1747

    
1748
		$args = "";
1749

    
1750
		if (isset($config['dnsmasq']['regdhcp'])) {
1751
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1752
		}
1753

    
1754
		/* Setup listen port, if non-default */
1755
		if (is_port($config['dnsmasq']['port']))
1756
			$args .= " --port={$config['dnsmasq']['port']} ";
1757

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

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

    
1817
		/* Setup forwarded domains */
1818
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1819
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
1820
				if ($override['ip'] == "!")
1821
					$override[ip] = "";
1822
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
1823
			}
1824
		}
1825

    
1826
		/* Allow DNS Rebind for forwarded domains */
1827
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
1828
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
1829
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
1830
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
1831
				}
1832
			}
1833
		}
1834

    
1835
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
1836
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
1837

    
1838
		if (isset($config['dnsmasq']['strict_order'])) {
1839
			$args .= " --strict-order ";
1840
		}
1841

    
1842
		if (isset($config['dnsmasq']['domain_needed'])) {
1843
			$args .= " --domain-needed ";
1844
		}
1845

    
1846
		if ($config['dnsmasq']['custom_options'])
1847
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
1848
				$args .= " " . escapeshellarg("--{$c}");
1849
				$p = explode('=', $c);
1850
				if (array_key_exists($p[0], $standard_args))
1851
					unset($standard_args[$p[0]]);
1852
			}
1853
		$args .= ' ' . implode(' ', array_values($standard_args));
1854

    
1855
		/* run dnsmasq */
1856
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
1857
		//log_error("dnsmasq command: {$cmd}");
1858
		mwexec_bg($cmd);
1859
		unset($args);
1860

    
1861
		if ($g['booting'])
1862
			echo gettext("done.") . "\n";
1863
	}
1864

    
1865
	if (!$g['booting']) {
1866
		if(services_dhcpd_configure()!=0)
1867
			$return = 1;
1868
	}
1869

    
1870
	return $return;
1871
}
1872

    
1873
function services_unbound_configure() {
1874
	global $config, $g;
1875
	$return = 0;
1876

    
1877
	if (isset($config['system']['developerspew'])) {
1878
		$mt = microtime();
1879
		echo "services_unbound_configure() being called $mt\n";
1880
	}
1881

    
1882
	// kill any running Unbound instance
1883
	if (file_exists("{$g['varrun_path']}/unbound.pid"))
1884
		sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
1885

    
1886
	if (isset($config['unbound']['enable'])) {
1887
		if ($g['booting'])
1888
			echo gettext("Starting DNS Resolver...");
1889
		else
1890
			sleep(1);
1891

    
1892
		require_once('/etc/inc/unbound.inc');
1893
		sync_unbound_service();
1894
		if ($g['booting'])
1895
			echo gettext("done.") . "\n";
1896
	}
1897

    
1898
	if (!$g['booting']) {
1899
		if (services_dhcpd_configure()!=0)
1900
			$return = 1;
1901
	}
1902

    
1903
	return $return;
1904
}
1905

    
1906
function services_snmpd_configure() {
1907
	global $config, $g;
1908
	if(isset($config['system']['developerspew'])) {
1909
		$mt = microtime();
1910
		echo "services_snmpd_configure() being called $mt\n";
1911
	}
1912

    
1913
	/* kill any running snmpd */
1914
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
1915
	sleep(2);
1916
	if(is_process_running("bsnmpd"))
1917
		mwexec("/usr/bin/killall bsnmpd", true);
1918

    
1919
	if (isset($config['snmpd']['enable'])) {
1920

    
1921
		if ($g['booting'])
1922
			echo gettext("Starting SNMP daemon... ");
1923

    
1924
		/* generate snmpd.conf */
1925
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
1926
		if (!$fd) {
1927
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"),"\n");
1928
			return 1;
1929
		}
1930

    
1931

    
1932
		$snmpdconf = <<<EOD
1933
location := "{$config['snmpd']['syslocation']}"
1934
contact := "{$config['snmpd']['syscontact']}"
1935
read := "{$config['snmpd']['rocommunity']}"
1936

    
1937
EOD;
1938

    
1939
/* No docs on what write strings do there for disable for now.
1940
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1941
		    $snmpdconf .= <<<EOD
1942
# write string
1943
write := "{$config['snmpd']['rwcommunity']}"
1944

    
1945
EOD;
1946
		}
1947
*/
1948

    
1949

    
1950
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1951
		    $snmpdconf .= <<<EOD
1952
# SNMP Trap support.
1953
traphost := {$config['snmpd']['trapserver']}
1954
trapport := {$config['snmpd']['trapserverport']}
1955
trap := "{$config['snmpd']['trapstring']}"
1956

    
1957

    
1958
EOD;
1959
		}
1960

    
1961
		$version = trim(file_get_contents('/etc/version'));
1962
		$platform = trim(file_get_contents('/etc/platform'));
1963
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense"))
1964
			$platform = $g['product_name'];
1965
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
1966
			" {$version} {$platform} " . php_uname("s") .
1967
			" " . php_uname("r") . " " . php_uname("m");
1968

    
1969
		$snmpdconf .= <<<EOD
1970
system := 1     # pfSense
1971
%snmpd
1972
sysDescr			= "{$sysDescr}"
1973
begemotSnmpdDebugDumpPdus       = 2
1974
begemotSnmpdDebugSyslogPri      = 7
1975
begemotSnmpdCommunityString.0.1 = $(read)
1976

    
1977
EOD;
1978

    
1979
/* No docs on what write strings do there for disable for now.
1980
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
1981
		    $snmpdconf .= <<<EOD
1982
begemotSnmpdCommunityString.0.2 = $(write)
1983

    
1984
EOD;
1985
		}
1986
*/
1987

    
1988

    
1989
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
1990
		    $snmpdconf .= <<<EOD
1991
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
1992
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
1993
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
1994

    
1995
EOD;
1996
		}
1997

    
1998

    
1999
		$snmpdconf .= <<<EOD
2000
begemotSnmpdCommunityDisable    = 1
2001

    
2002
EOD;
2003

    
2004
		if (isset($config['snmpd']['bindlan'])) {
2005
			$config['snmpd']['bindip'] = 'lan';
2006
			unset($config['snmpd']['bindlan']);
2007
		}
2008
		$bind_to_ip = "0.0.0.0";
2009
		if(isset($config['snmpd']['bindip'])) {
2010
			if (is_ipaddr($config['snmpd']['bindip'])) {
2011
				$bind_to_ip = $config['snmpd']['bindip'];
2012
			} else {
2013
				$if = get_real_interface($config['snmpd']['bindip']);
2014
				if (does_interface_exist($if))
2015
					$bind_to_ip = find_interface_ip($if);
2016
			}
2017
		}
2018

    
2019
		if(is_port( $config['snmpd']['pollport'] )) {
2020
		    $snmpdconf .= <<<EOD
2021
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
2022

    
2023
EOD;
2024

    
2025
		}
2026

    
2027
		$snmpdconf .= <<<EOD
2028
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
2029
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
2030

    
2031
# These are bsnmp macros not php vars.
2032
sysContact      = $(contact)
2033
sysLocation     = $(location)
2034
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
2035

    
2036
snmpEnableAuthenTraps = 2
2037

    
2038
EOD;
2039

    
2040
		if (is_array( $config['snmpd']['modules'] )) {
2041
		    if(isset($config['snmpd']['modules']['mibii'])) {
2042
			$snmpdconf .= <<<EOD
2043
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
2044

    
2045
EOD;
2046
		    }
2047

    
2048
		    if(isset($config['snmpd']['modules']['netgraph'])) {
2049
			$snmpdconf .= <<<EOD
2050
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
2051
%netgraph
2052
begemotNgControlNodeName = "snmpd"
2053

    
2054
EOD;
2055
		    }
2056

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

    
2061
EOD;
2062
		    }
2063

    
2064
		    if(isset($config['snmpd']['modules']['hostres'])) {
2065
			$snmpdconf .= <<<EOD
2066
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
2067

    
2068
EOD;
2069
		    }
2070
		    if(isset($config['snmpd']['modules']['bridge'])) {
2071
			$snmpdconf .= <<<EOD
2072
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
2073
# config must end with blank line
2074

    
2075
EOD;
2076
		    }
2077
			if(isset($config['snmpd']['modules']['ucd'])) {
2078
				$snmpdconf .= <<<EOD
2079
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
2080

    
2081
EOD;
2082
			}
2083
			if(isset($config['snmpd']['modules']['regex'])) {
2084
				$snmpdconf .= <<<EOD
2085
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
2086

    
2087
EOD;
2088
			}
2089
		}
2090

    
2091
		fwrite($fd, $snmpdconf);
2092
		fclose($fd);
2093
		unset($snmpdconf);
2094

    
2095
		if (isset($config['snmpd']['bindlan'])) {
2096
			$bindlan = "";
2097
		}
2098

    
2099
		/* run bsnmpd */
2100
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
2101
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
2102

    
2103
		if ($g['booting'])
2104
			echo gettext("done.") . "\n";
2105
	}
2106

    
2107
	return 0;
2108
}
2109

    
2110
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
2111
	global $config, $g;
2112
	if(isset($config['system']['developerspew'])) {
2113
		$mt = microtime();
2114
		echo "services_dnsupdate_process() being called $mt\n";
2115
	}
2116

    
2117
	/* Dynamic DNS updating active? */
2118
	if (is_array($config['dnsupdates']['dnsupdate'])) {
2119
		$notify_text = "";
2120
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
2121
			if (!isset($dnsupdate['enable']))
2122
				continue;
2123
			if (!empty($int) && $int != $dnsupdate['interface'])
2124
				continue;
2125
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host']))
2126
				continue;
2127

    
2128
			/* determine interface name */
2129
			$if = get_real_interface($dnsupdate['interface']);
2130
			
2131
			if (isset($dnsupdate['usepublicip']))
2132
                                $wanip = dyndnsCheckIP($dnsupdate['interface']);
2133
                        else
2134
                                $wanip = get_interface_ip($dnsupdate['interface']);
2135
			
2136
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2137
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2138
			$currentTime = time();
2139

    
2140
			if ($wanip || $wanipv6) {
2141
				$keyname = $dnsupdate['keyname'];
2142
				/* trailing dot */
2143
				if (substr($keyname, -1) != ".")
2144
					$keyname .= ".";
2145

    
2146
				$hostname = $dnsupdate['host'];
2147
				/* trailing dot */
2148
				if (substr($hostname, -1) != ".")
2149
					$hostname .= ".";
2150

    
2151
				/* write private key file
2152
				   this is dumb - public and private keys are the same for HMAC-MD5,
2153
				   but nsupdate insists on having both */
2154
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2155
				$privkey = <<<EOD
2156
Private-key-format: v1.2
2157
Algorithm: 157 (HMAC)
2158
Key: {$dnsupdate['keydata']}
2159

    
2160
EOD;
2161
				fwrite($fd, $privkey);
2162
				fclose($fd);
2163

    
2164
				/* write public key file */
2165
				if ($dnsupdate['keytype'] == "zone") {
2166
					$flags = 257;
2167
					$proto = 3;
2168
				} else if ($dnsupdate['keytype'] == "host") {
2169
					$flags = 513;
2170
					$proto = 3;
2171
				} else if ($dnsupdate['keytype'] == "user") {
2172
					$flags = 0;
2173
					$proto = 2;
2174
				}
2175

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

    
2180
				/* generate update instructions */
2181
				$upinst = "";
2182
				if (!empty($dnsupdate['server']))
2183
					$upinst .= "server {$dnsupdate['server']}\n";
2184

    
2185
				if (file_exists($cacheFile)) {
2186
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2187
				}
2188
				if (file_exists("{$cacheFile}.ipv6")) {
2189
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2190
				}
2191

    
2192
				// 25 Days
2193
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2194
				$need_update = false;
2195

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

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

    
2228
				$upinst .= "\n";	/* mind that trailing newline! */
2229

    
2230
				if ($need_update) {
2231
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2232
					unset($upinst);
2233
					/* invoke nsupdate */
2234
					$cmd = "/usr/local/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2235
					if (isset($dnsupdate['usetcp']))
2236
						$cmd .= " -v";
2237
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2238
					mwexec_bg($cmd);
2239
					unset($cmd);
2240
				}
2241
			}
2242
		}
2243
		if (!empty($notify_text)) {
2244
			notify_all_remote($notify_text);
2245
		}
2246
	}
2247

    
2248
	return 0;
2249
}
2250

    
2251
/* configure cron service */
2252
function configure_cron() {
2253
	global $g, $config;
2254

    
2255
	conf_mount_rw();
2256
	/* preserve existing crontab entries */
2257
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2258

    
2259
	for ($i = 0; $i < count($crontab_contents); $i++) {
2260
		$cron_item =& $crontab_contents[$i];
2261
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2262
			array_splice($crontab_contents, $i - 1);
2263
			break;
2264
		}
2265
	}
2266
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2267

    
2268

    
2269
	if (is_array($config['cron']['item'])) {
2270
		$crontab_contents .= "#\n";
2271
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2272
		$crontab_contents .= "# " .gettext( "Created:") . " " . date("F j, Y, g:i a") . "\n";
2273
		$crontab_contents .= "#\n";
2274

    
2275
		if (isset($config['system']['proxyurl']) && !empty($config['system']['proxyurl'])) {
2276
			$http_proxy = $config['system']['proxyurl'];
2277
			if (isset($config['system']['proxyport']) && !empty($config['system']['proxyport']))
2278
				$http_proxy .= ':' . $config['system']['proxyport'];
2279
			$crontab_contents .= "HTTP_PROXY={$http_proxy}";
2280
		}
2281

    
2282
		foreach ($config['cron']['item'] as $item) {
2283
			$crontab_contents .= "\n{$item['minute']}\t";
2284
			$crontab_contents .= "{$item['hour']}\t";
2285
			$crontab_contents .= "{$item['mday']}\t";
2286
			$crontab_contents .= "{$item['month']}\t";
2287
			$crontab_contents .= "{$item['wday']}\t";
2288
			$crontab_contents .= "{$item['who']}\t";
2289
			$crontab_contents .= "{$item['command']}";
2290
		}
2291

    
2292
		$crontab_contents .= "\n#\n";
2293
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2294
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2295
		$crontab_contents .= "#\n\n";
2296
	}
2297

    
2298
	/* please maintain the newline at the end of file */
2299
	file_put_contents("/etc/crontab", $crontab_contents);
2300
	unset($crontab_contents);
2301

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

    
2305
	conf_mount_ro();
2306
}
2307

    
2308
function upnp_action ($action) {
2309
	global $g, $config;
2310
	switch($action) {
2311
		case "start":
2312
			if (file_exists('/var/etc/miniupnpd.conf')) {
2313
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2314
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2315
			}
2316
			break;
2317
		case "stop":
2318
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2319
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
2320
				mwexec('killall miniupnpd 2>/dev/null', true);
2321
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2322
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2323
			break;
2324
		case "restart":
2325
			upnp_action('stop');
2326
			upnp_action('start');
2327
			break;
2328
	}
2329
}
2330

    
2331
function upnp_start() {
2332
	global $config;
2333

    
2334
	if(!isset($config['installedpackages']['miniupnpd']['config']))
2335
		return;
2336

    
2337
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2338
		echo gettext("Starting UPnP service... ");
2339
		require_once('/usr/local/pkg/miniupnpd.inc');
2340
		sync_package_miniupnpd();
2341
		echo "done.\n";
2342
	}
2343
}
2344

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

    
2348
	$is_installed = false;
2349

    
2350
	if (!is_array($config['cron']))
2351
		$config['cron'] = array();
2352
	if (!is_array($config['cron']['item']))
2353
		$config['cron']['item'] = array();
2354

    
2355
	$x=0;
2356
	foreach($config['cron']['item'] as $item) {
2357
		if(strstr($item['command'], $command)) {
2358
			$is_installed = true;
2359
			break;
2360
		}
2361
		$x++;
2362
	}
2363

    
2364
	if($active) {
2365
		$cron_item = array();
2366
		$cron_item['minute'] = $minute;
2367
		$cron_item['hour'] = $hour;
2368
		$cron_item['mday'] = $monthday;
2369
		$cron_item['month'] = $month;
2370
		$cron_item['wday'] = $weekday;
2371
		$cron_item['who'] = $who;
2372
		$cron_item['command'] = $command;
2373
		if(!$is_installed) {
2374
			$config['cron']['item'][] = $cron_item;
2375
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2376
		} else {
2377
			$config['cron']['item'][$x] = $cron_item;
2378
			write_config(sprintf(gettext("Updated cron job for %s"), $command));
2379
		}
2380
	} else {
2381
		if($is_installed == true) {
2382
			unset($config['cron']['item'][$x]);
2383
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2384
		}
2385
	}
2386
	configure_cron();
2387
}
2388

    
2389
?>
(50-50/68)