Project

General

Profile

Download (83.1 KB) Statistics
| Branch: | Tag: | Revision:
1 17f6eafa Scott Ullrich
<?php
2 5b237745 Scott Ullrich
/*
3
	services.inc
4 5721595b Chris Buechler
	part of the pfSense project (https://www.pfsense.org)
5 a25183c5 Scott Ullrich
6 417fc5c4 Scott Ullrich
	originally part of m0n0wall (http://m0n0.ch/wall)
7 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8 d98a2e6a Jose Luis Duran
	Copyright (C) 2010	Ermal Luçi
9 5b237745 Scott Ullrich
	All rights reserved.
10 a25183c5 Scott Ullrich
11 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13 a25183c5 Scott Ullrich
14 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16 a25183c5 Scott Ullrich
17 5b237745 Scott Ullrich
	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 a25183c5 Scott Ullrich
21 5b237745 Scott Ullrich
	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 523855b0 Scott Ullrich
/*
34 05c4bfa0 Ermal
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/bin/pgrep	/bin/sh	/usr/local/sbin/dhcpd	/usr/local/sbin/igmpproxy
35 1944af41 Ermal
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig		/usr/local/sbin/dnsmasq
36 950c9a18 Warren Baker
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/miniupnpd	/usr/sbin/radvd
37 1944af41 Ermal
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dhcleases6	/usr/sbin/bsnmpd
38 523855b0 Scott Ullrich
	pfSense_MODULE:	utils
39
*/
40
41 34c9962b Chris Buechler
define('DYNDNS_PROVIDER_VALUES', 'citynetwork cloudflare custom custom-v6 dnsexit dnsimple dnsmadeeasy dnsomatic dyndns dyndns-custom dyndns-static dyns easydns eurodns freedns glesys googledomains gratisdns he-net he-net-v6 he-net-tunnelbroker loopia namecheap noip noip-free ods opendns ovh-dynhost route53 selfhost zoneedit');
42
define('DYNDNS_PROVIDER_DESCRIPTIONS', 'City Network,CloudFlare,Custom,Custom (v6),DNSexit,DNSimple,DNS Made Easy,DNS-O-Matic,DynDNS (dynamic),DynDNS (custom),DynDNS (static),DyNS,easyDNS,Euro Dns,freeDNS,GleSYS,Google Domains,GratisDNS,HE.net,HE.net (v6),HE.net Tunnelbroker,Loopia,Namecheap,No-IP,No-IP (free),ODS.org,OpenDNS,OVH DynHOST,Route 53,SelfHost,ZoneEdit');
43 0e3aeb6b Phil Davis
44 3aa55bbe Phil Davis
/* implement ipv6 route advertising daemon */
45 92977616 Ermal
function services_radvd_configure($blacklist = array()) {
46 d57293a4 Seth Mos
	global $config, $g;
47 61e047a5 Phil Davis
48
	if (isset($config['system']['developerspew'])) {
49 d57293a4 Seth Mos
		$mt = microtime();
50 3f9cc8e4 smos
		echo "services_radvd_configure() being called $mt\n";
51 d57293a4 Seth Mos
	}
52
53 61e047a5 Phil Davis
	if (!is_array($config['dhcpdv6'])) {
54 d57293a4 Seth Mos
		$config['dhcpdv6'] = array();
55 61e047a5 Phil Davis
	}
56 d57293a4 Seth Mos
57
	$Iflist = get_configured_interface_list();
58 e9ab2ddb smos
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
59 abdd01f5 Ermal
	$carplist = get_configured_carp_interface_list();
60 d57293a4 Seth Mos
61 3f9cc8e4 smos
	$radvdconf = "# Automatically Generated, do not edit\n";
62 4a3ff493 Seth Mos
63 753bd64d Seth Mos
	/* Process all links which need the router advertise daemon */
64 3f9cc8e4 smos
	$radvdifs = array();
65 668e8961 smos
66 3f9cc8e4 smos
	/* handle manually configured DHCP6 server settings first */
67 dfac167c Ermal
	foreach ($config['dhcpdv6'] as $dhcpv6if => $dhcpv6ifconf) {
68 61e047a5 Phil Davis
		if (!is_array($config['interfaces'][$dhcpv6if])) {
69 dfac167c Ermal
			continue;
70 61e047a5 Phil Davis
		}
71
		if (!isset($config['interfaces'][$dhcpv6if]['enable'])) {
72 d7d2dc52 smos
			continue;
73 61e047a5 Phil Davis
		}
74 5078cd76 smos
75 92977616 Ermal
		/* Do not put in the config an interface which is down */
76 61e047a5 Phil Davis
		if (isset($blacklist[$dhcpv6if])) {
77 92977616 Ermal
			continue;
78 61e047a5 Phil Davis
		}
79
		if (!isset($dhcpv6ifconf['ramode'])) {
80 8ca73e85 smos
			$dhcpv6ifconf['ramode'] = $dhcpv6ifconf['mode'];
81 61e047a5 Phil Davis
		}
82 8ca73e85 smos
83 3f9cc8e4 smos
		/* are router advertisements enabled? */
84 61e047a5 Phil Davis
		if ($dhcpv6ifconf['ramode'] == "disabled") {
85 361bb4a9 smos
			continue;
86 61e047a5 Phil Davis
		}
87 d57293a4 Seth Mos
88 61e047a5 Phil Davis
		if (!isset($dhcpv6ifconf['rapriority'])) {
89 8ca73e85 smos
			$dhcpv6ifconf['rapriority'] = "medium";
90 61e047a5 Phil Davis
		}
91 8ca73e85 smos
92 25d1c6b2 smos
		/* always start with the real parent, we override with the carp if later */
93 83973bfb smos
		$carpif = false;
94 fe838158 smos
		/* check if we need to listen on a CARP interface */
95 dfac167c Ermal
		if (!empty($dhcpv6ifconf['rainterface'])) {
96 abdd01f5 Ermal
			if (!empty($carplist[$dhcpv6ifconf['rainterface']])) {
97
				$dhcpv6if = $dhcpv6ifconf['rainterface'];
98 83973bfb smos
				$carpif = true;
99 fe838158 smos
			}
100
		}
101 5078cd76 smos
102 2f74d9d8 Chris Buechler
		if (strstr($dhcpv6if, "_vip")) {
103 560d1b53 Renato Botelho
			// CARP IP, check if it's enabled and find parent
104 61e047a5 Phil Davis
			if (!get_carp_status() || get_carp_interface_status($dhcpv6if) != "MASTER") {
105 52b5a223 Renato Botelho
				continue;
106 61e047a5 Phil Davis
			}
107 2f74d9d8 Chris Buechler
			$ifparent = link_carp_interface_to_parent($dhcpv6if);
108
			$realif = convert_friendly_interface_to_real_interface_name($ifparent);
109
		} else {
110
			$realif = get_real_interface($dhcpv6if, "inet6");
111
		}
112 61e047a5 Phil Davis
113
		if (isset($radvdifs[$realif])) {
114 c18a10cc smos
			continue;
115 61e047a5 Phil Davis
		}
116 c18a10cc smos
117 2626cbd1 Ermal
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
118 61e047a5 Phil Davis
		if (!is_ipaddrv6($ifcfgipv6)) {
119 5078cd76 smos
			continue;
120 61e047a5 Phil Davis
		}
121 5078cd76 smos
122 d57293a4 Seth Mos
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
123
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
124 60c05056 Ermal
		$radvdifs[$realif] = $realif;
125 d57293a4 Seth Mos
126 3f9cc8e4 smos
		$radvdconf .= "# Generated for DHCPv6 Server $dhcpv6if\n";
127
		$radvdconf .= "interface {$realif} {\n";
128 e03b6bbc Chris Buechler
		if (strstr($realif, "ovpn")) {
129
			$radvdconf .= "\tUnicastOnly on;\n";
130
		}
131 3f9cc8e4 smos
		$radvdconf .= "\tAdvSendAdvert on;\n";
132 8859c0a6 smos
		$radvdconf .= "\tMinRtrAdvInterval 5;\n";
133
		$radvdconf .= "\tMaxRtrAdvInterval 20;\n";
134 a6bc492f Ermal
		$mtu = get_interface_mtu($realif);
135 61e047a5 Phil Davis
		if (is_numeric($mtu)) {
136 a6bc492f Ermal
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
137 61e047a5 Phil Davis
		} else {
138 a6bc492f Ermal
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
139 61e047a5 Phil Davis
		}
140 3f9cc8e4 smos
		// $radvdconf .= "\tDeprecatePrefix on;\n";
141 61e047a5 Phil Davis
		switch ($dhcpv6ifconf['rapriority']) {
142 fe838158 smos
			case "low":
143
				$radvdconf .= "\tAdvDefaultPreference low;\n";
144
				break;
145
			case "high":
146
				$radvdconf .= "\tAdvDefaultPreference high;\n";
147 838a1ecb smos
				break;
148
			default:
149
				$radvdconf .= "\tAdvDefaultPreference medium;\n";
150
				break;
151 fe838158 smos
		}
152 61e047a5 Phil Davis
		switch ($dhcpv6ifconf['ramode']) {
153 656f1763 Seth Mos
			case "managed":
154 3f9cc8e4 smos
			case "assist":
155 8c78e692 plinss
				$radvdconf .= "\tAdvManagedFlag on;\n";
156 3f9cc8e4 smos
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
157
				break;
158 bd7ce993 aqueeb
			case "stateless_dhcp":
159
				$radvdconf .= "\tAdvManagedFlag off;\n";
160
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
161
				break;
162 3f9cc8e4 smos
		}
163
		$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
164 61e047a5 Phil Davis
		if ($carpif == true) {
165 83973bfb smos
			$radvdconf .= "\t\tDeprecatePrefix off;\n";
166 a99b2b08 smos
		} else {
167 83973bfb smos
			$radvdconf .= "\t\tDeprecatePrefix on;\n";
168 a99b2b08 smos
		}
169 61e047a5 Phil Davis
		switch ($dhcpv6ifconf['ramode']) {
170 3f9cc8e4 smos
			case "managed":
171
				$radvdconf .= "\t\tAdvOnLink on;\n";
172
				$radvdconf .= "\t\tAdvAutonomous off;\n";
173
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
174 826ac52c smos
				break;
175
			case "router":
176 3f9cc8e4 smos
				$radvdconf .= "\t\tAdvOnLink off;\n";
177
				$radvdconf .= "\t\tAdvAutonomous off;\n";
178
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
179 656f1763 Seth Mos
				break;
180 bd7ce993 aqueeb
			case "stateless_dhcp":
181 656f1763 Seth Mos
			case "assist":
182 3f9cc8e4 smos
				$radvdconf .= "\t\tAdvOnLink on;\n";
183
				$radvdconf .= "\t\tAdvAutonomous on;\n";
184
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
185 107e8acc Ovidiu Predescu
				break;
186 3f9cc8e4 smos
			case "unmanaged":
187
				$radvdconf .= "\t\tAdvOnLink on;\n";
188
				$radvdconf .= "\t\tAdvAutonomous on;\n";
189
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
190 61e047a5 Phil Davis
				break;
191 656f1763 Seth Mos
		}
192 3f9cc8e4 smos
		$radvdconf .= "\t};\n";
193
194 686e53c0 Chris Buechler
		if (is_array($dhcpv6ifconf['subnets']['item'])) {
195
			foreach ($dhcpv6ifconf['subnets']['item'] as $subnet) {
196
				if (is_subnetv6($subnet)) {
197
					$radvdconf .= "\tprefix {$subnet} {\n";
198 cf3904bd Phil Davis
					if ($carpif == true) {
199 686e53c0 Chris Buechler
						$radvdconf .= "\t\tDeprecatePrefix off;\n";
200
					} else {
201
						$radvdconf .= "\t\tDeprecatePrefix on;\n";
202
					}
203 cf3904bd Phil Davis
					switch ($dhcpv6ifconf['ramode']) {
204 686e53c0 Chris Buechler
						case "managed":
205
							$radvdconf .= "\t\tAdvOnLink on;\n";
206
							$radvdconf .= "\t\tAdvAutonomous off;\n";
207
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
208
							break;
209
						case "router":
210
							$radvdconf .= "\t\tAdvOnLink off;\n";
211
							$radvdconf .= "\t\tAdvAutonomous off;\n";
212
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
213
							break;
214
						case "assist":
215
							$radvdconf .= "\t\tAdvOnLink on;\n";
216
							$radvdconf .= "\t\tAdvAutonomous on;\n";
217
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
218
							break;
219
						case "unmanaged":
220
							$radvdconf .= "\t\tAdvOnLink on;\n";
221
							$radvdconf .= "\t\tAdvAutonomous on;\n";
222
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
223 086cf944 Phil Davis
							break;
224 686e53c0 Chris Buechler
					}
225
					$radvdconf .= "\t};\n";
226
				}
227
			}
228
		}
229 61e047a5 Phil Davis
		if ($carpif === true) {
230 dc131dfe smos
			$radvdconf .= "\troute ::/0 {\n";
231 8859c0a6 smos
			$radvdconf .= "\t\tRemoveRoute off;\n";
232
			$radvdconf .= "\t};\n";
233
		} else {
234 dc131dfe smos
			$radvdconf .= "\troute ::/0 {\n";
235
			$radvdconf .= "\t\tRemoveRoute on;\n";
236 8859c0a6 smos
			$radvdconf .= "\t};\n";
237
		}
238
239 f535d5a0 Seth Mos
		/* add DNS servers */
240 3aa114d5 Seth Mos
		$dnslist = array();
241 3d73a44d Renato Botelho
		if (isset($dhcpv6ifconf['rasamednsasdhcp6']) && is_array($dhcpv6ifconf['dnsserver']) && !empty($dhcpv6ifconf['dnsserver'])) {
242 61e047a5 Phil Davis
			foreach ($dhcpv6ifconf['dnsserver'] as $server) {
243
				if (is_ipaddrv6($server)) {
244 3d73a44d Renato Botelho
					$dnslist[] = $server;
245 61e047a5 Phil Davis
				}
246
			}
247 3d73a44d Renato Botelho
		} elseif (!isset($dhcpv6ifconf['rasamednsasdhcp6']) && isset($dhcpv6ifconf['radnsserver']) && is_array($dhcpv6ifconf['radnsserver'])) {
248 61e047a5 Phil Davis
			foreach ($dhcpv6ifconf['radnsserver'] as $server) {
249
				if (is_ipaddrv6($server)) {
250 3aa114d5 Seth Mos
					$dnslist[] = $server;
251 61e047a5 Phil Davis
				}
252
			}
253 f4620b36 Chris Buechler
		} elseif (isset($config['dnsmasq']['enable']) || isset($config['unbound']['enable'])) {
254 9a933304 smos
			$dnslist[] = get_interface_ipv6($realif);
255 abdd01f5 Ermal
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
256 61e047a5 Phil Davis
			foreach ($config['system']['dnsserver'] as $server) {
257
				if (is_ipaddrv6($server)) {
258 3aa114d5 Seth Mos
					$dnslist[] = $server;
259 61e047a5 Phil Davis
				}
260 3aa114d5 Seth Mos
			}
261
		}
262 abdd01f5 Ermal
		if (count($dnslist) > 0) {
263 3f9cc8e4 smos
			$dnsstring = implode(" ", $dnslist);
264 61e047a5 Phil Davis
			if ($dnsstring <> "") {
265 6c582308 smos
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
266 61e047a5 Phil Davis
			}
267 f535d5a0 Seth Mos
		}
268 abdd01f5 Ermal
		if (!empty($dhcpv6ifconf['domain'])) {
269 6c582308 smos
			$radvdconf .= "\tDNSSL {$dhcpv6ifconf['domain']} { };\n";
270 abdd01f5 Ermal
		} elseif (!empty($config['system']['domain'])) {
271 6c582308 smos
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
272 f535d5a0 Seth Mos
		}
273 3f9cc8e4 smos
		$radvdconf .= "};\n";
274 ed395640 Seth Mos
	}
275
276 3f9cc8e4 smos
	/* handle DHCP-PD prefixes and 6RD dynamic interfaces */
277 ed395640 Seth Mos
	foreach ($Iflist as $if => $ifdescr) {
278 61e047a5 Phil Davis
		if (!isset($config['interfaces'][$if]['track6-interface'])) {
279 ed395640 Seth Mos
			continue;
280 61e047a5 Phil Davis
		}
281
		if (!isset($config['interfaces'][$if]['enable'])) {
282 d7d2dc52 smos
			continue;
283 61e047a5 Phil Davis
		}
284 92977616 Ermal
		/* Do not put in the config an interface which is down */
285 61e047a5 Phil Davis
		if (isset($blacklist[$if])) {
286 92977616 Ermal
			continue;
287 61e047a5 Phil Davis
		}
288 60c05056 Ermal
		$trackif = $config['interfaces'][$if]['track6-interface'];
289 61e047a5 Phil Davis
		if (empty($config['interfaces'][$trackif])) {
290 60c05056 Ermal
			continue;
291 61e047a5 Phil Davis
		}
292 60c05056 Ermal
293 2f74d9d8 Chris Buechler
		if (strstr($if, "_vip")) {
294
			// CARP IP, find parent
295
			$ifparent = link_carp_interface_to_parent($if);
296
			$realif = convert_friendly_interface_to_real_interface_name($ifparent);
297
		} else {
298
			$realif = get_real_interface($if, "inet6");
299
		}
300 61e047a5 Phil Davis
301 3f9cc8e4 smos
		/* prevent duplicate entries, manual overrides */
302 61e047a5 Phil Davis
		if (isset($radvdifs[$realif])) {
303 7492f21d smos
			continue;
304 61e047a5 Phil Davis
		}
305 7492f21d smos
306 ed395640 Seth Mos
		$ifcfgipv6 = get_interface_ipv6($if);
307 61e047a5 Phil Davis
		if (!is_ipaddrv6($ifcfgipv6)) {
308 75aec77a Ermal
			$subnetv6 = "::";
309
			$ifcfgsnv6 = "64";
310
		} else {
311
			$ifcfgsnv6 = get_interface_subnetv6($if);
312
			$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
313
		}
314 60c05056 Ermal
		$radvdifs[$realif] = $realif;
315 c18a10cc smos
316 20a7cb15 smos
		$autotype = $config['interfaces'][$trackif]['ipaddrv6'];
317 61e047a5 Phil Davis
318
		if ($g['debug']) {
319 dfac167c Ermal
			log_error("configuring RA on {$if} for type {$autotype} radvd subnet {$subnetv6}/{$ifcfgsnv6}");
320 61e047a5 Phil Davis
		}
321 668e8961 smos
322 60c05056 Ermal
		$radvdconf .= "# Generated config for {$autotype} delegation from {$trackif} on {$if}\n";
323
		$radvdconf .= "interface {$realif} {\n";
324
		$radvdconf .= "\tAdvSendAdvert on;\n";
325
		$radvdconf .= "\tMinRtrAdvInterval 3;\n";
326
		$radvdconf .= "\tMaxRtrAdvInterval 10;\n";
327
		$mtu = get_interface_mtu($realif);
328 61e047a5 Phil Davis
		if (is_numeric($mtu)) {
329 60c05056 Ermal
			$radvdconf .= "\tAdvLinkMTU {$mtu};\n";
330 61e047a5 Phil Davis
		} else {
331 60c05056 Ermal
			$radvdconf .= "\tAdvLinkMTU 1280;\n";
332 61e047a5 Phil Davis
		}
333 60c05056 Ermal
		$radvdconf .= "\tAdvOtherConfigFlag on;\n";
334
		$radvdconf .= "\t\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
335
		$radvdconf .= "\t\tAdvOnLink on;\n";
336
		$radvdconf .= "\t\tAdvAutonomous on;\n";
337
		$radvdconf .= "\t\tAdvRouterAddr on;\n";
338
		$radvdconf .= "\t};\n";
339
340
		/* add DNS servers */
341 668e8961 smos
		$dnslist = array();
342 f4620b36 Chris Buechler
		if (isset($config['dnsmasq']['enable']) || isset($config['unbound']['enable'])) {
343 60c05056 Ermal
			$dnslist[] = $ifcfgipv6;
344
		} elseif (is_array($config['system']['dnsserver']) && !empty($config['system']['dnsserver'])) {
345 61e047a5 Phil Davis
			foreach ($config['system']['dnsserver'] as $server) {
346
				if (is_ipaddrv6($server)) {
347 60c05056 Ermal
					$dnslist[] = $server;
348 61e047a5 Phil Davis
				}
349 60c05056 Ermal
			}
350 668e8961 smos
		}
351 60c05056 Ermal
		if (count($dnslist) > 0) {
352
			$dnsstring = implode(" ", $dnslist);
353 61e047a5 Phil Davis
			if (!empty($dnsstring)) {
354 60c05056 Ermal
				$radvdconf .= "\tRDNSS {$dnsstring} { };\n";
355 61e047a5 Phil Davis
			}
356 60c05056 Ermal
		}
357
		if (!empty($config['system']['domain'])) {
358
			$radvdconf .= "\tDNSSL {$config['system']['domain']} { };\n";
359
		}
360
		$radvdconf .= "};\n";
361 668e8961 smos
	}
362
363 928d4416 Ermal
	/* write radvd.conf */
364 abdd01f5 Ermal
	if (!@file_put_contents("{$g['varetc_path']}/radvd.conf", $radvdconf)) {
365
		log_error("Error: cannot open radvd.conf in services_radvd_configure().\n");
366 61e047a5 Phil Davis
		if (platform_booting()) {
367 abdd01f5 Ermal
			printf("Error: cannot open radvd.conf in services_radvd_configure().\n");
368 61e047a5 Phil Davis
		}
369 abdd01f5 Ermal
	}
370 928d4416 Ermal
	unset($radvdconf);
371 d57293a4 Seth Mos
372 abdd01f5 Ermal
	if (count($radvdifs) > 0) {
373 61e047a5 Phil Davis
		if (isvalidpid("{$g['varrun_path']}/radvd.pid")) {
374 abdd01f5 Ermal
			sigkillbypid("{$g['varrun_path']}/radvd.pid", "HUP");
375 61e047a5 Phil Davis
		} else {
376 abdd01f5 Ermal
			mwexec("/usr/local/sbin/radvd -p {$g['varrun_path']}/radvd.pid -C {$g['varetc_path']}/radvd.conf -m syslog");
377 61e047a5 Phil Davis
		}
378 6afeb202 smos
	} else {
379
		/* we need to shut down the radvd cleanly, it will send out the prefix
380
		 * information with a lifetime of 0 to notify clients of a (possible) new prefix */
381 abdd01f5 Ermal
		if (isvalidpid("{$g['varrun_path']}/radvd.pid")) {
382 6afeb202 smos
			log_error("Shutting down Router Advertisment daemon cleanly");
383 abdd01f5 Ermal
			killbypid("{$g['varrun_path']}/radvd.pid");
384 dfac167c Ermal
			@unlink("{$g['varrun_path']}/radvd.pid");
385 6afeb202 smos
		}
386 d57293a4 Seth Mos
	}
387
	return 0;
388
}
389
390 92977616 Ermal
function services_dhcpd_configure($family = "all", $blacklist = array()) {
391 f19d3b7a Scott Ullrich
	global $config, $g;
392 2fb056d8 Seth Mos
393
	/* configure DHCPD chroot once */
394 4de8f7ba Phil Davis
	$fd = fopen("{$g['tmp_path']}/dhcpd.sh", "w");
395 d6c82882 Ermal
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}\n");
396
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/dev\n");
397
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/etc\n");
398
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr/local/sbin\n");
399
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db\n");
400
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/run\n");
401
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/usr\n");
402
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/lib\n");
403
	fwrite($fd, "/bin/mkdir -p {$g['dhcpd_chroot_path']}/run\n");
404
	fwrite($fd, "/usr/sbin/chown -R dhcpd:_dhcp {$g['dhcpd_chroot_path']}/*\n");
405 06886ae3 Ermal
	fwrite($fd, "/bin/cp -n /lib/libc.so.* {$g['dhcpd_chroot_path']}/lib/\n");
406
	fwrite($fd, "/bin/cp -n /usr/local/sbin/dhcpd {$g['dhcpd_chroot_path']}/usr/local/sbin/\n");
407 60214e06 bcyrill
	fwrite($fd, "/bin/chmod a+rx {$g['dhcpd_chroot_path']}/usr/local/sbin/dhcpd\n");
408 d6c82882 Ermal
409 4de8f7ba Phil Davis
	$status = `/sbin/mount | /usr/bin/grep -v grep | /usr/bin/grep "{$g['dhcpd_chroot_path']}/dev"`;
410 61e047a5 Phil Davis
	if (!trim($status)) {
411 d6c82882 Ermal
		fwrite($fd, "/sbin/mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
412 61e047a5 Phil Davis
	}
413 2fb056d8 Seth Mos
	fclose($fd);
414
	mwexec("/bin/sh {$g['tmp_path']}/dhcpd.sh");
415
416 61e047a5 Phil Davis
	if ($family == "all" || $family == "inet") {
417 3084ba6e Ermal
		services_dhcpdv4_configure();
418 61e047a5 Phil Davis
	}
419 3084ba6e Ermal
	if ($family == "all" || $family == "inet6") {
420 92977616 Ermal
		services_dhcpdv6_configure($blacklist);
421
		services_radvd_configure($blacklist);
422 3084ba6e Ermal
	}
423 2fb056d8 Seth Mos
}
424 1c903aa4 Ermal
425 2fb056d8 Seth Mos
function services_dhcpdv4_configure() {
426
	global $config, $g;
427 3df2dbfd jim-p
	$need_ddns_updates = false;
428
	$ddns_zones = array();
429 107e8acc Ovidiu Predescu
430 61e047a5 Phil Davis
	if ($g['services_dhcp_server_enable'] == false) {
431 e3a13b00 Scott Ullrich
		return;
432 61e047a5 Phil Davis
	}
433 e3a13b00 Scott Ullrich
434 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
435 acd910bf Scott Ullrich
		$mt = microtime();
436 2fb056d8 Seth Mos
		echo "services_dhcpdv4_configure($if) being called $mt\n";
437 acd910bf Scott Ullrich
	}
438 107e8acc Ovidiu Predescu
439 af25d415 Chris Buechler
	/* kill any running dhcpd */
440 61e047a5 Phil Davis
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid")) {
441 ed395640 Seth Mos
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
442 61e047a5 Phil Davis
	}
443 a25183c5 Scott Ullrich
444 15be1722 Ermal Luçi
	/* DHCP enabled on any interfaces? */
445 61e047a5 Phil Davis
	if (!is_dhcp_server_enabled()) {
446 15be1722 Ermal Luçi
		return 0;
447 61e047a5 Phil Davis
	}
448 15be1722 Ermal Luçi
449 48ab0cd2 Scott Ullrich
	/* if OLSRD is enabled, allow WAN to house DHCP. */
450 61e047a5 Phil Davis
	if (!function_exists('is_package_installed')) {
451 86ce2df7 Renato Botelho
		require_once('pkg-utils.inc');
452 61e047a5 Phil Davis
	}
453
	if (is_package_installed('olsrd') && isset($config['installedpackages']['olsrd'])) {
454
		foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
455 86ce2df7 Renato Botelho
			if (isset($olsrd['enable']) && $olsrd['enable'] == "on") {
456
				$is_olsr_enabled = true;
457
				break;
458
			}
459 61e047a5 Phil Davis
		}
460
	}
461 48ab0cd2 Scott Ullrich
462 285ef132 Ermal LUÇI
	if (platform_booting()) {
463 e92e83d4 jim-p
		/* restore the leases, if we have them */
464
		if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
465
			$dhcprestore = "";
466
			$dhcpreturn = "";
467
			exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
468
			$dhcprestore = implode(" ", $dhcprestore);
469 61e047a5 Phil Davis
			if ($dhcpreturn <> 0) {
470 e92e83d4 jim-p
				log_error(sprintf(gettext('DHCP leases restore failed exited with %1$s, the error is: %2$s%3$s'), $dhcpreturn, $dhcprestore, "\n"));
471 381e43e0 jim-p
			}
472
		}
473 e92e83d4 jim-p
		/* 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. */
474 2344bed4 Renato Botelho
		if (($g['platform'] == $g['product_name']) && !isset($config['system']['use_mfs_tmpvar'])) {
475 e92e83d4 jim-p
			unlink_if_exists("{$g['cf_conf_path']}/dhcpleases.tgz");
476
		}
477 381e43e0 jim-p
	}
478
479 5b237745 Scott Ullrich
	$syscfg = $config['system'];
480 61e047a5 Phil Davis
	if (!is_array($config['dhcpd'])) {
481 a8a98fb4 Seth Mos
		$config['dhcpd'] = array();
482 61e047a5 Phil Davis
	}
483 d57293a4 Seth Mos
	$dhcpdcfg = $config['dhcpd'];
484 6f9b8073 Ermal Luçi
	$Iflist = get_configured_interface_list();
485 107e8acc Ovidiu Predescu
486 3ad6b569 Phil Davis
	/* Only consider DNS servers with IPv4 addresses for the IPv4 DHCP server. */
487
	$dns_arrv4 = array();
488 68169a55 jim-p
	if (is_array($syscfg['dnsserver'])) {
489 61e047a5 Phil Davis
		foreach ($syscfg['dnsserver'] as $dnsserver) {
490 68169a55 jim-p
			if (is_ipaddrv4($dnsserver)) {
491
				$dns_arrv4[] = $dnsserver;
492
			}
493 3ad6b569 Phil Davis
		}
494
	}
495
496 61e047a5 Phil Davis
	if (platform_booting()) {
497 f1a44a3a Carlos Eduardo Ramos
		echo gettext("Starting DHCP service...");
498 61e047a5 Phil Davis
	} else {
499 5b237745 Scott Ullrich
		sleep(1);
500 61e047a5 Phil Davis
	}
501 a25183c5 Scott Ullrich
502 518030b3 Scott Ullrich
	$custoptions = "";
503 107e8acc Ovidiu Predescu
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
504 61e047a5 Phil Davis
		if (is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) {
505
			foreach ($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
506
				if (!empty($item['type'])) {
507 678dfd0f Erik Fonnesbeck
					$itemtype = $item['type'];
508 61e047a5 Phil Davis
				} else {
509 678dfd0f Erik Fonnesbeck
					$itemtype = "text";
510 61e047a5 Phil Davis
				}
511 678dfd0f Erik Fonnesbeck
				$custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n";
512 518030b3 Scott Ullrich
			}
513
		}
514
	}
515 4cab31d0 Scott Ullrich
516 5b237745 Scott Ullrich
	$dhcpdconf = <<<EOD
517 107e8acc Ovidiu Predescu
518 5b237745 Scott Ullrich
option domain-name "{$syscfg['domain']}";
519 6c23757b Martin Fuchs
option ldap-server code 95 = text;
520 9be23653 Martin Fuchs
option domain-search-list code 119 = text;
521 fdb116a9 Donald A. Cupp Jr
option arch code 93 = unsigned integer 16; # RFC4578
522 518030b3 Scott Ullrich
{$custoptions}
523 5b237745 Scott Ullrich
default-lease-time 7200;
524
max-lease-time 86400;
525
log-facility local7;
526 175fe82b Scott Ullrich
one-lease-per-client true;
527 436a0f50 Scott Ullrich
deny duplicates;
528 9c88328f Scott Ullrich
ping-check true;
529 87019fc4 Andres Petralli
update-conflict-detection false;
530 5b237745 Scott Ullrich
531
EOD;
532 a25183c5 Scott Ullrich
533 61e047a5 Phil Davis
	if (!isset($dhcpifconf['disableauthoritative'])) {
534 d8912c6b Chris Buechler
		$dhcpdconf .= "authoritative;\n";
535 61e047a5 Phil Davis
	}
536 d8912c6b Chris Buechler
537 61e047a5 Phil Davis
	if (isset($dhcpifconf['alwaysbroadcast'])) {
538 5252b98d Scott Ullrich
		$dhcpdconf .= "always-broadcast on\n";
539 61e047a5 Phil Davis
	}
540 5252b98d Scott Ullrich
541 5b237745 Scott Ullrich
	$dhcpdifs = array();
542 3f141c9d Phil Davis
	$enable_add_routers = false;
543 c08a5659 smos
	$gateways_arr = return_gateways_array();
544
	/* only add a routers line if the system has any IPv4 gateway at all */
545
	/* a static route has a gateway, manually overriding this field always works */
546 61e047a5 Phil Davis
	foreach ($gateways_arr as $gwitem) {
547
		if ($gwitem['ipprotocol'] == "inet") {
548 3f141c9d Phil Davis
			$enable_add_routers = true;
549 c08a5659 smos
			break;
550
		}
551
	}
552 c7f44ae0 Scott Ullrich
553 4494cf6a Chris Buechler
	/*    loop through and determine if we need to setup
554 8fa56d1f Scott Ullrich
	 *    failover peer "bleh" entries
555
	 */
556
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
557 53f32329 Scott Ullrich
558 61e047a5 Phil Davis
		if (!isset($config['interfaces'][$dhcpif]['enable'])) {
559 57006646 Renato Botelho
			continue;
560 61e047a5 Phil Davis
		}
561 57006646 Renato Botelho
562 09f11c71 jim-p
		interfaces_staticarp_configure($dhcpif);
563
564 61e047a5 Phil Davis
		if (!isset($dhcpifconf['enable'])) {
565 6f9b8073 Ermal Luçi
			continue;
566 61e047a5 Phil Davis
		}
567 6f9b8073 Ermal Luçi
568 61e047a5 Phil Davis
		if ($dhcpifconf['failover_peerip'] <> "") {
569 a01f8bfc Ermal
			$intip = get_interface_ip($dhcpif);
570 8fa56d1f Scott Ullrich
			/*
571
			 *    yep, failover peer is defined.
572
			 *    does it match up to a defined vip?
573
			 */
574 d2edbd8a Scott Ullrich
			$skew = 110;
575 61e047a5 Phil Davis
			if (is_array($config['virtualip']['vip'])) {
576 9d7ca11f Ermal
				foreach ($config['virtualip']['vip'] as $vipent) {
577 61e047a5 Phil Davis
					if ($vipent['interface'] == $dhcpif) {
578 a01f8bfc Ermal
						$carp_nw = gen_subnet($vipent['subnet'], $vipent['subnet_bits']);
579
						if (ip_in_subnet($dhcpifconf['failover_peerip'], "{$carp_nw}/{$vipent['subnet_bits']}")) {
580
							/* this is the interface! */
581 61e047a5 Phil Davis
							if (is_numeric($vipent['advskew']) && (intval($vipent['advskew']) < 20)) {
582 a01f8bfc Ermal
								$skew = 0;
583
								break;
584
							}
585
						}
586 6181b36f Scott Ullrich
					}
587 8fa56d1f Scott Ullrich
				}
588 25066204 Scott Ullrich
			} else {
589 959dc96b Chris Buechler
				log_error(gettext("Warning!  DHCP Failover setup and no CARP virtual IPs defined!"));
590 8fa56d1f Scott Ullrich
			}
591 61e047a5 Phil Davis
			if ($skew > 10) {
592 8fa56d1f Scott Ullrich
				$type = "secondary";
593 0e93097a Scott Ullrich
				$my_port = "520";
594
				$peer_port = "519";
595 8fa56d1f Scott Ullrich
			} else {
596 0e93097a Scott Ullrich
				$my_port = "519";
597
				$peer_port = "520";
598 8fa56d1f Scott Ullrich
				$type = "primary";
599 4de8f7ba Phil Davis
				$dhcpdconf_pri = "split 128;\n";
600 1a0bb737 Scott Ullrich
				$dhcpdconf_pri .= "  mclt 600;\n";
601 8fa56d1f Scott Ullrich
			}
602 a01f8bfc Ermal
603
			if (is_ipaddrv4($intip)) {
604 61e047a5 Phil Davis
				$dhcpdconf .= <<<EOPP
605 d5e4f7c9 jim-p
failover peer "dhcp_{$dhcpif}" {
606 8fa56d1f Scott Ullrich
  {$type};
607
  address {$intip};
608 0e93097a Scott Ullrich
  port {$my_port};
609 8fa56d1f Scott Ullrich
  peer address {$dhcpifconf['failover_peerip']};
610 0e93097a Scott Ullrich
  peer port {$peer_port};
611 2cd5ce14 Scott Ullrich
  max-response-delay 10;
612 b865d178 Scott Ullrich
  max-unacked-updates 10;
613
  {$dhcpdconf_pri}
614 b259d1c6 Scott Ullrich
  load balance max seconds 3;
615 8fa56d1f Scott Ullrich
}
616 959dc96b Chris Buechler
\n
617 8fa56d1f Scott Ullrich
EOPP;
618 a01f8bfc Ermal
			}
619 8fa56d1f Scott Ullrich
		}
620
	}
621
622 5b237745 Scott Ullrich
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
623 a25183c5 Scott Ullrich
624 3df2dbfd jim-p
		$newzone = array();
625 5b237745 Scott Ullrich
		$ifcfg = $config['interfaces'][$dhcpif];
626 a25183c5 Scott Ullrich
627 61e047a5 Phil Davis
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif])) {
628 5b237745 Scott Ullrich
			continue;
629 61e047a5 Phil Davis
		}
630 a55e9c70 Ermal Lu?i
		$ifcfgip = get_interface_ip($dhcpif);
631
		$ifcfgsn = get_interface_subnet($dhcpif);
632
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
633
		$subnetmask = gen_subnet_mask($ifcfgsn);
634 a25183c5 Scott Ullrich
635 61e047a5 Phil Davis
		if (!is_ipaddr($subnet)) {
636 85e3f445 Ermal
			continue;
637 61e047a5 Phil Davis
		}
638 85e3f445 Ermal
639 61e047a5 Phil Davis
		if ($is_olsr_enabled == true) {
640
			if ($dhcpifconf['netmask']) {
641 9a537862 Scott Ullrich
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
642 61e047a5 Phil Davis
			}
643
		}
644 48ab0cd2 Scott Ullrich
645 cba980f6 jim-p
		$all_pools = array();
646
		$all_pools[] = $dhcpifconf;
647
		if (is_array($dhcpifconf['pool'])) {
648
			$all_pools = array_merge($all_pools, $dhcpifconf['pool']);
649
		}
650
651 5b237745 Scott Ullrich
		$dnscfg = "";
652 a25183c5 Scott Ullrich
653 5b237745 Scott Ullrich
		if ($dhcpifconf['domain']) {
654
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
655
		}
656 107e8acc Ovidiu Predescu
657 61e047a5 Phil Davis
		if ($dhcpifconf['domainsearchlist'] <> "") {
658 a3de8b9e Pierre POMES
			$dnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpifconf['domainsearchlist'])) . "\";\n";
659 84931046 jim-p
		}
660 9be23653 Martin Fuchs
661 4e9cd828 Seth Mos
		if (isset($dhcpifconf['ddnsupdate'])) {
662 3df2dbfd jim-p
			$need_ddns_updates = true;
663
			$newzone = array();
664 61e047a5 Phil Davis
			if ($dhcpifconf['ddnsdomain'] <> "") {
665 3df2dbfd jim-p
				$newzone['domain-name'] = $dhcpifconf['ddnsdomain'];
666 4e9cd828 Seth Mos
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
667 3df2dbfd jim-p
			} else {
668
				$newzone['domain-name'] = $config['system']['domain'];
669
			}
670
			$revsubnet = explode(".", $subnet);
671
			$revsubnet = array_reverse($revsubnet);
672
			foreach ($revsubnet as $octet) {
673 61e047a5 Phil Davis
				if ($octet != "0") {
674 3df2dbfd jim-p
					break;
675 61e047a5 Phil Davis
				}
676 3df2dbfd jim-p
				array_shift($revsubnet);
677 4e9cd828 Seth Mos
			}
678 3df2dbfd jim-p
			$newzone['ptr-domain'] = implode(".", $revsubnet) . ".in-addr.arpa";
679 4e9cd828 Seth Mos
		}
680
681 aff9d6ab Scott Ullrich
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
682 8ee01642 Scott Ullrich
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
683 61e047a5 Phil Davis
			if ($newzone['domain-name']) {
684 3df2dbfd jim-p
				$newzone['dns-servers'] = $dhcpifconf['dnsserver'];
685 61e047a5 Phil Davis
			}
686 aff9d6ab Scott Ullrich
		} else if (isset($config['dnsmasq']['enable'])) {
687 a55e9c70 Ermal Lu?i
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
688 61e047a5 Phil Davis
			if ($newzone['domain-name'] && is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
689 3df2dbfd jim-p
				$newzone['dns-servers'] = $syscfg['dnsserver'];
690 61e047a5 Phil Davis
			}
691 88a0937d Chris Buechler
		} else if (isset($config['unbound']['enable'])) {
692
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
693 3ad6b569 Phil Davis
		} else if (!empty($dns_arrv4)) {
694
			$dnscfg .= "	option domain-name-servers " . join(",", $dns_arrv4) . ";";
695 61e047a5 Phil Davis
			if ($newzone['domain-name']) {
696 3ad6b569 Phil Davis
				$newzone['dns-servers'] = $dns_arrv4;
697 61e047a5 Phil Davis
			}
698 aff9d6ab Scott Ullrich
		}
699
700 61e047a5 Phil Davis
		/* Create classes - These all contain comma separated lists. Join them into one
701 cba980f6 jim-p
		   big comma separated string then split them all up. */
702
		$all_mac_strings = array();
703
		if (is_array($dhcpifconf['pool'])) {
704 61e047a5 Phil Davis
			foreach ($all_pools as $poolconf) {
705 cba980f6 jim-p
				$all_mac_strings[] = $poolconf['mac_allow'];
706
				$all_mac_strings[] = $poolconf['mac_deny'];
707
			}
708
		}
709
		$all_mac_strings[] = $dhcpifconf['mac_allow'];
710
		$all_mac_strings[] = $dhcpifconf['mac_deny'];
711 7fd93993 Ermal LUÇI
		if (!empty($all_mac_strings)) {
712 4de8f7ba Phil Davis
			$all_mac_list = array_unique(explode(',', implode(',', $all_mac_strings)));
713
			foreach ($all_mac_list as $mac) {
714
				if (empty($mac)) {
715
					continue;
716
				}
717
				$dhcpdconf .= 'class "' . str_replace(':', '', $mac) . '" {' . "\n";
718
				// Skip the first octet of the MAC address - for media type, typically Ethernet ("01") and match the rest.
719
				$dhcpdconf .= '	match if substring (hardware, 1, ' . (substr_count($mac, ':') + 1) . ') = ' . $mac . ';' . "\n";
720
				$dhcpdconf .= '}' . "\n";
721 61e047a5 Phil Davis
			}
722 1f1a08c8 jim-p
		}
723
724 85e3f445 Ermal
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
725 c7f44ae0 Scott Ullrich
726 61e047a5 Phil Davis
		// Setup pool options
727
		foreach ($all_pools as $poolconf) {
728 9228166f Phil Davis
			if (!(ip_in_subnet($poolconf['range']['from'], "{$subnet}/{$ifcfgsn}") && ip_in_subnet($poolconf['range']['to'], "{$subnet}/{$ifcfgsn}"))) {
729
				// If the user has changed the subnet from the interfaces page and applied,
730
				// but has not updated the DHCP range, then the range to/from of the pool can be outside the subnet.
731 f8cc55bf Phil Davis
				// This can also happen when implementing the batch of changes when the setup wizard reloads the new settings.
732 9228166f Phil Davis
				$error_msg = sprintf(gettext("Invalid DHCP pool %s - %s for %s subnet %s/%s detected. Please correct the settings in Services, DHCP Server"), $poolconf['range']['from'], $poolconf['range']['to'], convert_real_interface_to_friendly_descr($dhcpif), $subnet, $ifcfgsn);
733 f8cc55bf Phil Davis
				$do_file_notice = true;
734
				$conf_ipv4_address = $ifcfg['ipaddr'];
735
				$conf_ipv4_subnetmask = $ifcfg['subnet'];
736
				if (is_ipaddrv4($conf_ipv4_address) && is_subnet("{$conf_ipv4_address}/{$conf_ipv4_subnetmask}")) {
737
					$conf_subnet_base = gen_subnet($conf_ipv4_address, $conf_ipv4_subnetmask);
738
					if (ip_in_subnet($poolconf['range']['from'], "{$conf_subnet_base}/{$conf_ipv4_subnetmask}") &&
739
					    ip_in_subnet($poolconf['range']['to'], "{$conf_subnet_base}/{$conf_ipv4_subnetmask}")) {
740
						// Even though the running interface subnet does not match the pool range,
741
						// the interface subnet in the config file contains the pool range.
742
						// We are somewhere part-way through a settings reload, e.g. after running the setup wizard.
743
						// services_dhcpdv4_configure will be called again later when the new interface settings from
744
						// the config are applied and at that time everything will match up.
745
						// Ignore this pool on this interface for now and just log the error to the system log.
746
						log_error($error_msg);
747
						$do_file_notice = false;
748
					}
749
				}
750
				if ($do_file_notice) {
751
					file_notice("DHCP", $error_msg);
752
				}
753 9228166f Phil Davis
				continue;
754
			}
755 cba980f6 jim-p
			$dhcpdconf .= "	pool {\n";
756
			/* is failover dns setup? */
757
			if (is_array($poolconf['dnsserver']) && $poolconf['dnsserver'][0] <> "") {
758
				$dhcpdconf .= "		option domain-name-servers {$poolconf['dnsserver'][0]}";
759 61e047a5 Phil Davis
				if ($poolconf['dnsserver'][1] <> "") {
760 cba980f6 jim-p
					$dhcpdconf .= ",{$poolconf['dnsserver'][1]}";
761 61e047a5 Phil Davis
				}
762
				if ($poolconf['dnsserver'][2] <> "") {
763 8cbb140a Phil Davis
					$dhcpdconf .= ",{$poolconf['dnsserver'][2]}";
764 61e047a5 Phil Davis
				}
765
				if ($poolconf['dnsserver'][3] <> "") {
766 8cbb140a Phil Davis
					$dhcpdconf .= ",{$poolconf['dnsserver'][3]}";
767 61e047a5 Phil Davis
				}
768 cba980f6 jim-p
				$dhcpdconf .= ";\n";
769
			}
770
771
			/* allow/deny MACs */
772
			$mac_allow_list = array_unique(explode(',', $poolconf['mac_allow']));
773
			foreach ($mac_allow_list as $mac) {
774 61e047a5 Phil Davis
				if (empty($mac)) {
775 cba980f6 jim-p
					continue;
776 61e047a5 Phil Davis
				}
777 cba980f6 jim-p
				$dhcpdconf .= "		allow members of \"" . str_replace(':', '', $mac) . "\";\n";
778
			}
779
			$mac_deny_list = array_unique(explode(',', $poolconf['mac_deny']));
780
			foreach ($mac_deny_list as $mac) {
781 61e047a5 Phil Davis
				if (empty($mac)) {
782 cba980f6 jim-p
					continue;
783 61e047a5 Phil Davis
				}
784 cba980f6 jim-p
				$dhcpdconf .= "		deny members of \"" . str_replace(':', '', $mac) . "\";\n";
785
			}
786
787 61e047a5 Phil Davis
			if ($poolconf['failover_peerip'] <> "") {
788 cba980f6 jim-p
				$dhcpdconf .= "		deny dynamic bootp clients;\n";
789 61e047a5 Phil Davis
			}
790 cba980f6 jim-p
791 61e047a5 Phil Davis
			if (isset($poolconf['denyunknown'])) {
792 cba980f6 jim-p
			   $dhcpdconf .= "		deny unknown-clients;\n";
793 61e047a5 Phil Davis
			}
794 cba980f6 jim-p
795 61e047a5 Phil Davis
			if ($poolconf['gateway'] && $poolconf['gateway'] != "none" && ($poolconf['gateway'] != $dhcpifconf['gateway'])) {
796 f9f6f7d4 jim-p
				$dhcpdconf .= "		option routers {$poolconf['gateway']};\n";
797 61e047a5 Phil Davis
			}
798 cba980f6 jim-p
799 61e047a5 Phil Davis
			if ($dhcpifconf['failover_peerip'] <> "") {
800 d5e4f7c9 jim-p
				$dhcpdconf .= "		failover peer \"dhcp_{$dhcpif}\";\n";
801 cba980f6 jim-p
			}
802
803
			$pdnscfg = "";
804
805
			if ($poolconf['domain'] && ($poolconf['domain'] != $dhcpifconf['domain'])) {
806
				$pdnscfg .= "		option domain-name \"{$poolconf['domain']}\";\n";
807
			}
808
809 61e047a5 Phil Davis
			if (!empty($poolconf['domainsearchlist']) && ($poolconf['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
810 cba980f6 jim-p
				$pdnscfg .= "		option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $poolconf['domainsearchlist'])) . "\";\n";
811
			}
812
813 7309ff39 Renato Botelho
			if (isset($poolconf['ddnsupdate'])) {
814 61e047a5 Phil Davis
				if (($poolconf['ddnsdomain'] <> "") && ($poolconf['ddnsdomain'] != $dhcpifconf['ddnsdomain'])) {
815 cba980f6 jim-p
					$pdnscfg .= "		ddns-domainname \"{$poolconf['ddnsdomain']}\";\n";
816 61e047a5 Phil Davis
				}
817 cba980f6 jim-p
				$pdnscfg .= "		ddns-update-style interim;\n";
818
			}
819
820 fa7b825f Renato Botelho
			if (is_array($poolconf['dnsserver']) && ($poolconf['dnsserver'][0]) && ($poolconf['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
821 cba980f6 jim-p
				$pdnscfg .= "		option domain-name-servers " . join(",", $poolconf['dnsserver']) . ";\n";
822
			}
823
			$dhcpdconf .= "{$pdnscfg}";
824 1f1a08c8 jim-p
825 cba980f6 jim-p
			// default-lease-time
826 61e047a5 Phil Davis
			if ($poolconf['defaultleasetime'] && ($poolconf['defaultleasetime'] != $dhcpifconf['defaultleasetime'])) {
827 cba980f6 jim-p
				$dhcpdconf .= "		default-lease-time {$poolconf['defaultleasetime']};\n";
828 61e047a5 Phil Davis
			}
829 cba980f6 jim-p
830
			// max-lease-time
831 61e047a5 Phil Davis
			if ($poolconf['maxleasetime'] && ($poolconf['maxleasetime'] != $dhcpifconf['maxleasetime'])) {
832 cba980f6 jim-p
				$dhcpdconf .= "		max-lease-time {$poolconf['maxleasetime']};\n";
833 61e047a5 Phil Davis
			}
834 cba980f6 jim-p
835
			// netbios-name*
836 fa7b825f Renato Botelho
			if (is_array($poolconf['winsserver']) && $poolconf['winsserver'][0] && ($poolconf['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
837 cba980f6 jim-p
				$dhcpdconf .= "		option netbios-name-servers " . join(",", $poolconf['winsserver']) . ";\n";
838
				$dhcpdconf .= "		option netbios-node-type 8;\n";
839
			}
840 c7f44ae0 Scott Ullrich
841 cba980f6 jim-p
			// ntp-servers
842 61e047a5 Phil Davis
			if (is_array($poolconf['ntpserver']) && $poolconf['ntpserver'][0] && ($poolconf['ntpserver'][0] != $dhcpifconf['ntpserver'][0])) {
843 cba980f6 jim-p
				$dhcpdconf .= "		option ntp-servers " . join(",", $poolconf['ntpserver']) . ";\n";
844 61e047a5 Phil Davis
			}
845 cba980f6 jim-p
846
			// tftp-server-name
847 61e047a5 Phil Davis
			if (!empty($poolconf['tftp']) && ($poolconf['tftp'] != $dhcpifconf['tftp'])) {
848 cba980f6 jim-p
				$dhcpdconf .= "		option tftp-server-name \"{$poolconf['tftp']}\";\n";
849 61e047a5 Phil Davis
			}
850 cba980f6 jim-p
851
			// ldap-server
852 61e047a5 Phil Davis
			if (!empty($poolconf['ldap']) && ($poolconf['ldap'] != $dhcpifconf['ldap'])) {
853 cba980f6 jim-p
				$dhcpdconf .= "		option ldap-server \"{$poolconf['ldap']}\";\n";
854 61e047a5 Phil Davis
			}
855 cba980f6 jim-p
856
			// net boot information
857 61e047a5 Phil Davis
			if (isset($poolconf['netboot'])) {
858 cba980f6 jim-p
				if (!empty($poolconf['nextserver']) && ($poolconf['nextserver'] != $dhcpifconf['nextserver'])) {
859
					$dhcpdconf .= "		next-server {$poolconf['nextserver']};\n";
860
				}
861
				if (!empty($poolconf['filename']) && ($poolconf['filename'] != $dhcpifconf['filename'])) {
862
					$dhcpdconf .= "		filename \"{$poolconf['filename']}\";\n";
863
				}
864
				if (!empty($poolconf['rootpath']) && ($poolconf['rootpath'] != $dhcpifconf['rootpath'])) {
865
					$dhcpdconf .= "		option root-path \"{$poolconf['rootpath']}\";\n";
866
				}
867
			}
868
			$dhcpdconf .= "		range {$poolconf['range']['from']} {$poolconf['range']['to']};\n";
869
			$dhcpdconf .= "	}\n\n";
870
		}
871
// End of settings inside pools
872 a25183c5 Scott Ullrich
873 4208f7b1 timdufrane
		if ($dhcpifconf['gateway'] && $dhcpifconf['gateway'] != "none") {
874 5b237745 Scott Ullrich
			$routers = $dhcpifconf['gateway'];
875 c08a5659 smos
			$add_routers = true;
876 4208f7b1 timdufrane
		} elseif ($dhcpifconf['gateway'] == "none") {
877
			$add_routers = false;
878 c08a5659 smos
		} else {
879 3f141c9d Phil Davis
			$add_routers = $enable_add_routers;
880 a55e9c70 Ermal Lu?i
			$routers = $ifcfgip;
881 c08a5659 smos
		}
882 61e047a5 Phil Davis
		if ($add_routers) {
883 c08a5659 smos
			$dhcpdconf .= "	option routers {$routers};\n";
884 61e047a5 Phil Davis
		}
885 cba980f6 jim-p
886 c08a5659 smos
		$dhcpdconf .= <<<EOD
887 5b237745 Scott Ullrich
$dnscfg
888
889
EOD;
890 61e047a5 Phil Davis
		// default-lease-time
891
		if ($dhcpifconf['defaultleasetime']) {
892 5b237745 Scott Ullrich
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
893 61e047a5 Phil Davis
		}
894 518030b3 Scott Ullrich
895
		// max-lease-time
896 61e047a5 Phil Davis
		if ($dhcpifconf['maxleasetime']) {
897 5b237745 Scott Ullrich
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
898 61e047a5 Phil Davis
		}
899 a25183c5 Scott Ullrich
900 518030b3 Scott Ullrich
		// netbios-name*
901 5b237745 Scott Ullrich
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
902
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
903
			$dhcpdconf .= "	option netbios-node-type 8;\n";
904
		}
905 a25183c5 Scott Ullrich
906 518030b3 Scott Ullrich
		// ntp-servers
907 61e047a5 Phil Davis
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0]) {
908 ad171999 Seth Mos
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
909 61e047a5 Phil Davis
		}
910 ad171999 Seth Mos
911 518030b3 Scott Ullrich
		// tftp-server-name
912 61e047a5 Phil Davis
		if ($dhcpifconf['tftp'] <> "") {
913 6c23757b Martin Fuchs
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
914 61e047a5 Phil Davis
		}
915 6c23757b Martin Fuchs
916 518030b3 Scott Ullrich
		// Handle option, number rowhelper values
917
		$dhcpdconf .= "\n";
918 61e047a5 Phil Davis
		if ($dhcpifconf['numberoptions']['item']) {
919
			foreach ($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
920
				if (empty($item['type']) || $item['type'] == "text") {
921 678dfd0f Erik Fonnesbeck
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
922 61e047a5 Phil Davis
				} else {
923 678dfd0f Erik Fonnesbeck
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
924 61e047a5 Phil Davis
				}
925 518030b3 Scott Ullrich
			}
926
		}
927
928
		// ldap-server
929 61e047a5 Phil Davis
		if ($dhcpifconf['ldap'] <> "") {
930 6c23757b Martin Fuchs
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
931 61e047a5 Phil Davis
		}
932 6c23757b Martin Fuchs
933 518030b3 Scott Ullrich
		// net boot information
934 61e047a5 Phil Davis
		if (isset($dhcpifconf['netboot'])) {
935 a2578c27 Anthony Wrather
			if ($dhcpifconf['nextserver'] <> "") {
936
				$dhcpdconf .= "	next-server {$dhcpifconf['nextserver']};\n";
937
			}
938 fdb116a9 Donald A. Cupp Jr
			if (!empty($dhcpifconf['filename']) && !empty($dhcpifconf['filename32']) && !empty($dhcpifconf['filename64'])) {
939
				$dhcpdconf .= "	if option arch = 00:06 {\n";
940
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename32']}\";\n";
941
				$dhcpdconf .= "	} else if option arch = 00:07 {\n";
942
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename64']}\";\n";
943 08bcd379 Phil Davis
				$dhcpdconf .= "	} else if option arch = 00:09 {\n";
944
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename64']}\";\n";
945 fdb116a9 Donald A. Cupp Jr
				$dhcpdconf .= "	} else {\n";
946
				$dhcpdconf .= "		filename \"{$dhcpifconf['filename']}\";\n";
947
				$dhcpdconf .= "	}\n\n";
948
			} elseif (!empty($dhcpifconf['filename'])) {
949 4e9cd828 Seth Mos
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
950
			}
951 fdb116a9 Donald A. Cupp Jr
			if (!empty($dhcpifconf['rootpath'])) {
952 ca126e03 Martin Fuchs
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
953 cba980f6 jim-p
			}
954 4e9cd828 Seth Mos
		}
955 107e8acc Ovidiu Predescu
956 5b237745 Scott Ullrich
		$dhcpdconf .= <<<EOD
957
}
958
959
EOD;
960
961
		/* add static mappings */
962
		if (is_array($dhcpifconf['staticmap'])) {
963 a25183c5 Scott Ullrich
964 5b237745 Scott Ullrich
			$i = 0;
965
			foreach ($dhcpifconf['staticmap'] as $sm) {
966 449f1dd2 Will Boyce
				$dhcpdconf .= "host s_{$dhcpif}_{$i} {\n";
967
968 61e047a5 Phil Davis
				if ($sm['mac']) {
969
					$dhcpdconf .= "        hardware ethernet {$sm['mac']};\n";
970
				}
971 449f1dd2 Will Boyce
972 61e047a5 Phil Davis
				if ($sm['cid']) {
973
					$dhcpdconf .= "        option dhcp-client-identifier \"{$sm['cid']}\";\n";
974
				}
975 5b237745 Scott Ullrich
976 61e047a5 Phil Davis
				if ($sm['ipaddr']) {
977 5b237745 Scott Ullrich
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
978 61e047a5 Phil Davis
				}
979 a25183c5 Scott Ullrich
980 ad30055f Ermal Lu?i
				if ($sm['hostname']) {
981
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
982 46c5b763 pierrepomes
					$dhhostname = str_replace(".", "_", $dhhostname);
983 2f590513 smos
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
984 ad30055f Ermal Lu?i
				}
985 61e047a5 Phil Davis
				if ($sm['filename']) {
986 a2578c27 Anthony Wrather
					$dhcpdconf .= "	filename \"{$sm['filename']}\";\n";
987 61e047a5 Phil Davis
				}
988 a2578c27 Anthony Wrather
989 61e047a5 Phil Davis
				if ($sm['rootpath']) {
990 a2578c27 Anthony Wrather
					$dhcpdconf .= "	option root-path \"{$sm['rootpath']}\";\n";
991 61e047a5 Phil Davis
				}
992 80717709 Martin Fuchs
993 61e047a5 Phil Davis
				if ($sm['gateway'] && ($sm['gateway'] != $dhcpifconf['gateway'])) {
994 7309ff39 Renato Botelho
					$dhcpdconf .= "	option routers {$sm['gateway']};\n";
995 61e047a5 Phil Davis
				}
996 7309ff39 Renato Botelho
997
				$smdnscfg = "";
998
999
				if ($sm['domain'] && ($sm['domain'] != $dhcpifconf['domain'])) {
1000
					$smdnscfg .= "	option domain-name \"{$sm['domain']}\";\n";
1001
				}
1002
1003 61e047a5 Phil Davis
				if (!empty($sm['domainsearchlist']) && ($sm['domainsearchlist'] != $dhcpifconf['domainsearchlist'])) {
1004 7309ff39 Renato Botelho
					$smdnscfg .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $sm['domainsearchlist'])) . "\";\n";
1005
				}
1006
1007
				if (isset($sm['ddnsupdate'])) {
1008 61e047a5 Phil Davis
					if (($sm['ddnsdomain'] <> "") && ($sm['ddnsdomain'] != $dhcpifconf['ddnsdomain'])) {
1009 7309ff39 Renato Botelho
						$pdnscfg .= "		ddns-domainname \"{$sm['ddnsdomain']}\";\n";
1010 61e047a5 Phil Davis
					}
1011 7309ff39 Renato Botelho
					$pdnscfg .= "		ddns-update-style interim;\n";
1012
				}
1013
1014
				if (is_array($sm['dnsserver']) && ($sm['dnsserver'][0]) && ($sm['dnsserver'][0] != $dhcpifconf['dnsserver'][0])) {
1015
					$smdnscfg .= "	option domain-name-servers " . join(",", $sm['dnsserver']) . ";\n";
1016
				}
1017
				$dhcpdconf .= "{$smdnscfg}";
1018
1019
				// default-lease-time
1020 61e047a5 Phil Davis
				if ($sm['defaultleasetime'] && ($sm['defaultleasetime'] != $dhcpifconf['defaultleasetime'])) {
1021 7309ff39 Renato Botelho
					$dhcpdconf .= "	default-lease-time {$sm['defaultleasetime']};\n";
1022 61e047a5 Phil Davis
				}
1023 7309ff39 Renato Botelho
1024
				// max-lease-time
1025 61e047a5 Phil Davis
				if ($sm['maxleasetime'] && ($sm['maxleasetime'] != $dhcpifconf['maxleasetime'])) {
1026 7309ff39 Renato Botelho
					$dhcpdconf .= "	max-lease-time {$sm['maxleasetime']};\n";
1027 61e047a5 Phil Davis
				}
1028 7309ff39 Renato Botelho
1029
				// netbios-name*
1030
				if (is_array($sm['winsserver']) && $sm['winsserver'][0] && ($sm['winsserver'][0] != $dhcpifconf['winsserver'][0])) {
1031
					$dhcpdconf .= "	option netbios-name-servers " . join(",", $sm['winsserver']) . ";\n";
1032
					$dhcpdconf .= "	option netbios-node-type 8;\n";
1033
				}
1034
1035
				// ntp-servers
1036 61e047a5 Phil Davis
				if (is_array($sm['ntpserver']) && $sm['ntpserver'][0] && ($sm['ntpserver'][0] != $dhcpifconf['ntpserver'][0])) {
1037 7309ff39 Renato Botelho
					$dhcpdconf .= "	option ntp-servers " . join(",", $sm['ntpserver']) . ";\n";
1038 61e047a5 Phil Davis
				}
1039 7309ff39 Renato Botelho
1040
				// tftp-server-name
1041 61e047a5 Phil Davis
				if (!empty($sm['tftp']) && ($sm['tftp'] != $dhcpifconf['tftp'])) {
1042 7309ff39 Renato Botelho
					$dhcpdconf .= "	option tftp-server-name \"{$sm['tftp']}\";\n";
1043 61e047a5 Phil Davis
				}
1044 7309ff39 Renato Botelho
1045 5b237745 Scott Ullrich
				$dhcpdconf .= "}\n";
1046
				$i++;
1047
			}
1048
		}
1049 a25183c5 Scott Ullrich
1050 6f9b8073 Ermal Luçi
		$dhcpdifs[] = get_real_interface($dhcpif);
1051 61e047a5 Phil Davis
		if ($newzone['domain-name']) {
1052
			if ($need_ddns_updates) {
1053 87019fc4 Andres Petralli
				$newzone['dns-servers'] = array($dhcpifconf['ddnsdomainprimary']);
1054
			}
1055 3df2dbfd jim-p
			$ddns_zones[] = $newzone;
1056 87019fc4 Andres Petralli
		}
1057 3df2dbfd jim-p
	}
1058
1059
	if ($need_ddns_updates) {
1060
		$dhcpdconf .= "ddns-update-style interim;\n";
1061 3cdef187 Andres Petralli
		$dhcpdconf .= "update-static-leases on;\n";
1062 87019fc4 Andres Petralli
1063
		$dhcpdconf .= dhcpdkey($dhcpifconf);
1064
		$dhcpdconf .= dhcpdzones($ddns_zones, $dhcpifconf);
1065 5b237745 Scott Ullrich
	}
1066
1067 abdd01f5 Ermal
	/* write dhcpd.conf */
1068
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", $dhcpdconf)) {
1069
		printf(gettext("Error: cannot open dhcpd.conf in services_dhcpdv4_configure().%s"), "\n");
1070
		unset($dhcpdconf);
1071
		return 1;
1072
	}
1073 928d4416 Ermal
	unset($dhcpdconf);
1074 2fb056d8 Seth Mos
1075
	/* create an empty leases database */
1076 61e047a5 Phil Davis
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases")) {
1077 abdd01f5 Ermal
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
1078 61e047a5 Phil Davis
	}
1079 2fb056d8 Seth Mos
1080 b075c1e2 Chris Buechler
	/* make sure there isn't a stale dhcpd.pid file, which can make dhcpd fail to start.   */
1081 61e047a5 Phil Davis
	/* if we get here, dhcpd has been killed and is not started yet                        */
1082 b075c1e2 Chris Buechler
	unlink_if_exists("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpd.pid");
1083
1084 2fb056d8 Seth Mos
	/* fire up dhcpd in a chroot */
1085 abdd01f5 Ermal
	if (count($dhcpdifs) > 0) {
1086 2fb056d8 Seth Mos
		mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf /etc/dhcpd.conf -pf {$g['varrun_path']}/dhcpd.pid " .
1087
			join(" ", $dhcpdifs));
1088
	}
1089
1090 61e047a5 Phil Davis
	if (platform_booting()) {
1091 2fb056d8 Seth Mos
		print "done.\n";
1092 61e047a5 Phil Davis
	}
1093 2fb056d8 Seth Mos
1094
	return 0;
1095
}
1096
1097 086cf944 Phil Davis
function dhcpdkey($dhcpifconf) {
1098 87019fc4 Andres Petralli
	$dhcpdconf = "";
1099 61e047a5 Phil Davis
	if ($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "") {
1100 87019fc4 Andres Petralli
		$dhcpdconf .= "key {$dhcpifconf['ddnsdomainkeyname']} {\n";
1101
		$dhcpdconf .= "	algorithm hmac-md5;\n";
1102
		$dhcpdconf .= "	secret {$dhcpifconf['ddnsdomainkey']};\n";
1103
		$dhcpdconf .= "}\n";
1104
	}
1105
1106
	return $dhcpdconf;
1107
}
1108
1109 086cf944 Phil Davis
function dhcpdzones($ddns_zones, $dhcpifconf) {
1110 87019fc4 Andres Petralli
	$dhcpdconf = "";
1111
1112
	if (is_array($ddns_zones)) {
1113
		$added_zones = array();
1114
		foreach ($ddns_zones as $zone) {
1115 61e047a5 Phil Davis
			if (!is_array($zone) || empty($zone) || !is_array($zone['dns-servers'])) {
1116 87019fc4 Andres Petralli
				continue;
1117 61e047a5 Phil Davis
			}
1118 87019fc4 Andres Petralli
			$primary = $zone['dns-servers'][0];
1119
			$secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1];
1120
1121
			// Make sure we aren't using any invalid or IPv6 DNS servers.
1122
			if (!is_ipaddrv4($primary)) {
1123
				if (is_ipaddrv4($secondary)) {
1124
					$primary = $secondary;
1125
					$secondary = "";
1126
				} else {
1127
					continue;
1128
				}
1129
			}
1130
1131
			// We don't need to add zones multiple times.
1132
			if ($zone['domain-name'] && !in_array($zone['domain-name'], $added_zones)) {
1133
				$dhcpdconf .= "zone {$zone['domain-name']}. {\n";
1134
				$dhcpdconf .= "	primary {$primary};\n";
1135 61e047a5 Phil Davis
				if (is_ipaddrv4($secondary)) {
1136 87019fc4 Andres Petralli
					$dhcpdconf .= "	secondary {$secondary};\n";
1137 61e047a5 Phil Davis
				}
1138
				if ($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "") {
1139
					$dhcpdconf .= "	key {$dhcpifconf['ddnsdomainkeyname']};\n";
1140
				}
1141 87019fc4 Andres Petralli
				$dhcpdconf .= "}\n";
1142
				$added_zones[] = $zone['domain-name'];
1143
			}
1144
			if ($zone['ptr-domain'] && !in_array($zone['ptr-domain'], $added_zones)) {
1145
				$dhcpdconf .= "zone {$zone['ptr-domain']} {\n";
1146
				$dhcpdconf .= "	primary {$primary};\n";
1147 61e047a5 Phil Davis
				if (is_ipaddrv4($secondary)) {
1148 87019fc4 Andres Petralli
					$dhcpdconf .= "	secondary {$secondary};\n";
1149 61e047a5 Phil Davis
				}
1150
				if ($dhcpifconf['ddnsdomainkeyname'] <> "" && $dhcpifconf['ddnsdomainkey'] <> "") {
1151
					$dhcpdconf .= "	key {$dhcpifconf['ddnsdomainkeyname']};\n";
1152
				}
1153 87019fc4 Andres Petralli
				$dhcpdconf .= "}\n";
1154
				$added_zones[] = $zone['ptr-domain'];
1155
			}
1156
		}
1157
	}
1158
1159
	return $dhcpdconf;
1160
}
1161
1162 92977616 Ermal
function services_dhcpdv6_configure($blacklist = array()) {
1163 2fb056d8 Seth Mos
	global $config, $g;
1164 107e8acc Ovidiu Predescu
1165 61e047a5 Phil Davis
	if ($g['services_dhcp_server_enable'] == false) {
1166 2fb056d8 Seth Mos
		return;
1167 61e047a5 Phil Davis
	}
1168 2fb056d8 Seth Mos
1169 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1170 2fb056d8 Seth Mos
		$mt = microtime();
1171
		echo "services_dhcpd_configure($if) being called $mt\n";
1172
	}
1173 107e8acc Ovidiu Predescu
1174 2fb056d8 Seth Mos
	/* kill any running dhcpd */
1175 61e047a5 Phil Davis
	if (isvalidpid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid")) {
1176 bfb3e717 Seth Mos
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
1177 61e047a5 Phil Davis
	}
1178
	if (isvalidpid("{$g['varrun_path']}/dhcpleases6.pid")) {
1179 f7cd5647 smos
		killbypid("{$g['varrun_path']}/dhcpleases6.pid");
1180 61e047a5 Phil Davis
	}
1181 e9ab2ddb smos
1182 2fb056d8 Seth Mos
	/* DHCP enabled on any interfaces? */
1183 61e047a5 Phil Davis
	if (!is_dhcpv6_server_enabled()) {
1184 2fb056d8 Seth Mos
		return 0;
1185 61e047a5 Phil Davis
	}
1186 2fb056d8 Seth Mos
1187 285ef132 Ermal LUÇI
	if (platform_booting()) {
1188 2344bed4 Renato Botelho
		if ($g['platform'] != $g['product_name']) {
1189 2fb056d8 Seth Mos
			/* restore the leases, if we have them */
1190
			if (file_exists("{$g['cf_conf_path']}/dhcp6leases.tgz")) {
1191
				$dhcprestore = "";
1192
				$dhcpreturn = "";
1193
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcp6leases.tgz 2>&1", $dhcprestore, $dhcpreturn);
1194
				$dhcprestore = implode(" ", $dhcprestore);
1195 61e047a5 Phil Davis
				if ($dhcpreturn <> 0) {
1196 2fb056d8 Seth Mos
					log_error("DHCP leases v6 restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
1197
				}
1198
			}
1199
		}
1200
	}
1201
1202
	$syscfg = $config['system'];
1203 61e047a5 Phil Davis
	if (!is_array($config['dhcpdv6'])) {
1204 2fb056d8 Seth Mos
		$config['dhcpdv6'] = array();
1205 61e047a5 Phil Davis
	}
1206 2fb056d8 Seth Mos
	$dhcpdv6cfg = $config['dhcpdv6'];
1207
	$Iflist = get_configured_interface_list();
1208 e9ab2ddb smos
	$Iflist = array_merge($Iflist, get_configured_pppoe_server_interfaces());
1209
1210 107e8acc Ovidiu Predescu
1211 61e047a5 Phil Davis
	if (platform_booting()) {
1212 2fb056d8 Seth Mos
		echo "Starting DHCPv6 service...";
1213 61e047a5 Phil Davis
	} else {
1214 2fb056d8 Seth Mos
		sleep(1);
1215 61e047a5 Phil Davis
	}
1216 2fb056d8 Seth Mos
1217 a6610d82 smos
	/* we add a fake entry for interfaces that are set to track6 another WAN */
1218 abdd01f5 Ermal
	foreach ($Iflist as $ifname) {
1219 92977616 Ermal
		/* Do not put in the config an interface which is down */
1220 61e047a5 Phil Davis
		if (isset($blacklist[$ifname])) {
1221 92977616 Ermal
			continue;
1222 61e047a5 Phil Davis
		}
1223 abdd01f5 Ermal
		if (!empty($config['interfaces'][$ifname]['track6-interface'])) {
1224 06886ae3 Ermal
			$realif = get_real_interface($ifname, "inet6");
1225 c55a0f0c Ermal
			$ifcfgipv6 = get_interface_ipv6($ifname);
1226 61e047a5 Phil Davis
			if (!is_ipaddrv6($ifcfgipv6)) {
1227 c55a0f0c Ermal
				continue;
1228 61e047a5 Phil Davis
			}
1229 c55a0f0c Ermal
			$ifcfgipv6 = Net_IPv6::getNetmask($ifcfgipv6, 64);
1230 a6610d82 smos
			$trackifname = $config['interfaces'][$ifname]['track6-interface'];
1231
			$trackcfg = $config['interfaces'][$trackifname];
1232 319c2bfd smos
			$pdlen = calculate_ipv6_delegation_length($trackifname);
1233 a6610d82 smos
			$ifcfgipv6arr =explode(":", $ifcfgipv6);
1234
			$dhcpdv6cfg[$ifname] = array();
1235
			$dhcpdv6cfg[$ifname]['enable'] = true;
1236
			/* range */
1237
			$ifcfgipv6arr[7] = "1000";
1238 6fb66736 Ermal
			$dhcpdv6cfg[$ifname]['range'] = array();
1239 a6610d82 smos
			$dhcpdv6cfg[$ifname]['range']['from'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
1240
			$ifcfgipv6arr[7] = "2000";
1241 91f026b0 ayvis
			$dhcpdv6cfg[$ifname]['range']['to'] = Net_IPv6::compress(implode(":", $ifcfgipv6arr));
1242 a6610d82 smos
			/* prefix length > 0? We can add dhcp6 prefix delegation server */
1243 61e047a5 Phil Davis
			if ($pdlen > 2) {
1244 c45b079d smos
				$pdlenmax = $pdlen;
1245 4aab9c6c smos
				$pdlenhalf = $pdlenmax -1;
1246
				$pdlenmin = (64 - ceil($pdlenhalf / 4));
1247 6fb66736 Ermal
				$dhcpdv6cfg[$ifname]['prefixrange'] = array();
1248 4aab9c6c smos
				$dhcpdv6cfg[$ifname]['prefixrange']['prefixlength'] = $pdlenmin;
1249
1250
				/* set the delegation start to half the current address block */
1251 c45b079d smos
				$range = Net_IPv6::parseAddress($ifcfgipv6, (64 - $pdlenmax));
1252 4aab9c6c smos
				$range['start'] = Net_IPv6::getNetmask($range['end'], (64 - $pdlenhalf));
1253
1254
				/* set the end range to a multiple of the prefix delegation size, required by dhcpd */
1255 c45b079d smos
				$range = Net_IPv6::parseAddress($range['end'], (64 - $pdlenhalf));
1256 4aab9c6c smos
				$range['end'] = Net_IPv6::getNetmask($range['end'], (64 - round($pdlen / 2)));
1257
1258 a6610d82 smos
				$dhcpdv6cfg[$ifname]['prefixrange']['from'] = Net_IPv6::compress($range['start']);
1259
				$dhcpdv6cfg[$ifname]['prefixrange']['to'] = Net_IPv6::compress($range['end']);
1260
			}
1261 8fd42722 Daniel Becker
			$dhcpdv6cfg[$ifname]['dns6ip'] = get_interface_ipv6($ifname);
1262 a6610d82 smos
		}
1263
	}
1264
1265 2fb056d8 Seth Mos
	$custoptionsv6 = "";
1266 107e8acc Ovidiu Predescu
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1267 61e047a5 Phil Davis
		if (is_array($dhcpv6ifconf['numberoptions']) && is_array($dhcpv6ifconf['numberoptions']['item'])) {
1268
			foreach ($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1269 2fb056d8 Seth Mos
				$custoptionsv6 .= "option custom-{$dhcpv6if}-{$itemv6idx} code {$itemv6['number']} = text;\n";
1270
			}
1271
		}
1272
	}
1273
1274 61e047a5 Phil Davis
	if (isset($dhcpv6ifconf['netboot']) && !empty($dhcpv6ifconf['bootfile_url'])) {
1275 bd942860 Renato Botelho
		$custoptionsv6 .= "option dhcp6.bootfile-url code 59 = string;\n";
1276 61e047a5 Phil Davis
	}
1277 bd942860 Renato Botelho
1278 2fb056d8 Seth Mos
	$dhcpdv6conf = <<<EOD
1279 107e8acc Ovidiu Predescu
1280 2fb056d8 Seth Mos
option domain-name "{$syscfg['domain']}";
1281
option ldap-server code 95 = text;
1282
option domain-search-list code 119 = text;
1283 547f1e65 Renato Botelho
{$custoptionsv6}
1284 2fb056d8 Seth Mos
default-lease-time 7200;
1285
max-lease-time 86400;
1286
log-facility local7;
1287
one-lease-per-client true;
1288
deny duplicates;
1289
ping-check true;
1290 87019fc4 Andres Petralli
update-conflict-detection false;
1291 2fb056d8 Seth Mos
1292
EOD;
1293
1294 61e047a5 Phil Davis
	if (!isset($dhcpv6ifconf['disableauthoritative'])) {
1295 2fb056d8 Seth Mos
		$dhcpdv6conf .= "authoritative;\n";
1296 61e047a5 Phil Davis
	}
1297 2fb056d8 Seth Mos
1298 61e047a5 Phil Davis
	if (isset($dhcpv6ifconf['alwaysbroadcast'])) {
1299 2fb056d8 Seth Mos
		$dhcpdv6conf .= "always-broadcast on\n";
1300 61e047a5 Phil Davis
	}
1301 2fb056d8 Seth Mos
1302
	$dhcpdv6ifs = array();
1303
1304 693833cb Seth Mos
	$dhcpv6num = 0;
1305 87019fc4 Andres Petralli
	$nsupdate = false;
1306
1307 693833cb Seth Mos
	foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) {
1308
1309 87019fc4 Andres Petralli
		$ddns_zones = array();
1310
1311 693833cb Seth Mos
		$ifcfgv6 = $config['interfaces'][$dhcpv6if];
1312
1313 61e047a5 Phil Davis
		if (!isset($dhcpv6ifconf['enable']) || !isset($Iflist[$dhcpv6if]) || !isset($ifcfgv6['enable'])) {
1314 693833cb Seth Mos
			continue;
1315 61e047a5 Phil Davis
		}
1316 693833cb Seth Mos
		$ifcfgipv6 = get_interface_ipv6($dhcpv6if);
1317
		$ifcfgsnv6 = get_interface_subnetv6($dhcpv6if);
1318 d57293a4 Seth Mos
		$subnetv6 = gen_subnetv6($ifcfgipv6, $ifcfgsnv6);
1319 693833cb Seth Mos
1320 1944af41 Ermal
		if ($is_olsr_enabled == true) {
1321 61e047a5 Phil Davis
			if ($dhcpv6ifconf['netmask']) {
1322 bfb3e717 Seth Mos
				$subnetmask = gen_subnet_maskv6($dhcpv6ifconf['netmask']);
1323 61e047a5 Phil Davis
			}
1324 1944af41 Ermal
		}
1325 693833cb Seth Mos
1326
		$dnscfgv6 = "";
1327
1328
		if ($dhcpv6ifconf['domain']) {
1329 3c009080 Seth Mos
			$dnscfgv6 .= "	option domain-name \"{$dhcpv6ifconf['domain']}\";\n";
1330 693833cb Seth Mos
		}
1331 107e8acc Ovidiu Predescu
1332 61e047a5 Phil Davis
		if ($dhcpv6ifconf['domainsearchlist'] <> "") {
1333 a3de8b9e Pierre POMES
			$dnscfgv6 .= "	option domain-search \"" . join("\",\"", preg_split("/[ ;]+/", $dhcpv6ifconf['domainsearchlist'])) . "\";\n";
1334 61e047a5 Phil Davis
		}
1335 693833cb Seth Mos
1336
		if (isset($dhcpv6ifconf['ddnsupdate'])) {
1337 61e047a5 Phil Davis
			if ($dhcpv6ifconf['ddnsdomain'] <> "") {
1338 3c009080 Seth Mos
				$dnscfgv6 .= "	ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n";
1339 693833cb Seth Mos
			}
1340 3c009080 Seth Mos
			$dnscfgv6 .= "	ddns-update-style interim;\n";
1341 87019fc4 Andres Petralli
			$nsupdate = true;
1342 693833cb Seth Mos
		}
1343
1344
		if (is_array($dhcpv6ifconf['dnsserver']) && ($dhcpv6ifconf['dnsserver'][0])) {
1345
			$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dhcpv6ifconf['dnsserver']) . ";";
1346 f4620b36 Chris Buechler
		} else if (((isset($config['dnsmasq']['enable'])) || isset($config['unbound']['enable'])) && (is_ipaddrv6($ifcfgipv6))) {
1347 693833cb Seth Mos
			$dnscfgv6 .= "	option dhcp6.name-servers {$ifcfgipv6};";
1348
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1349 2521266a Seth Mos
			$dns_arrv6 = array();
1350 61e047a5 Phil Davis
			foreach ($syscfg['dnsserver'] as $dnsserver) {
1351 1944af41 Ermal
				if (is_ipaddrv6($dnsserver)) {
1352 2521266a Seth Mos
					$dns_arrv6[] = $dnsserver;
1353
				}
1354
			}
1355 61e047a5 Phil Davis
			if (!empty($dns_arrv6)) {
1356 2816c5a1 Seth Mos
				$dnscfgv6 .= "	option dhcp6.name-servers " . join(",", $dns_arrv6) . ";";
1357 61e047a5 Phil Davis
			}
1358 693833cb Seth Mos
		}
1359
1360 87019fc4 Andres Petralli
		if ($dhcpv6ifconf['domain']) {
1361
			$newzone = array();
1362 61e047a5 Phil Davis
			$newzone['domain-name'] = $dhcpv6ifconf['domain'];
1363 87019fc4 Andres Petralli
			$newzone['dns-servers'][] = $dhcpv6ifconf['ddnsdomainprimary'];
1364
			$ddns_zones[] = $newzone;
1365
		}
1366
1367 1944af41 Ermal
		if (is_ipaddrv6($ifcfgipv6)) {
1368
			$dhcpdv6conf .= "subnet6 {$subnetv6}/{$ifcfgsnv6}";
1369 e9ab2ddb smos
		} else {
1370 88cc00db Ermal
			$subnet6 = gen_subnetv6($dhcpv6ifconf['range']['from'], "64");
1371 1944af41 Ermal
			$dhcpdv6conf .= "subnet6 {$subnet6}/64";
1372 abdd01f5 Ermal
		}
1373 1944af41 Ermal
		$dhcpdv6conf .= " {\n";
1374 693833cb Seth Mos
1375
		$dhcpdv6conf .= <<<EOD
1376
	range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']};
1377
$dnscfgv6
1378
1379
EOD;
1380 bfb3e717 Seth Mos
1381 1944af41 Ermal
		if (is_ipaddrv6($dhcpv6ifconf['prefixrange']['from']) && is_ipaddrv6($dhcpv6ifconf['prefixrange']['to'])) {
1382 978b8f50 Chris Buechler
			$dhcpdv6conf .= "	prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']} /{$dhcpv6ifconf['prefixrange']['prefixlength']};\n";
1383 bfb3e717 Seth Mos
		}
1384 70da4172 Jean Cyr
		if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) {
1385 8fd42722 Daniel Becker
			$dhcpdv6conf .= "	option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n";
1386 70da4172 Jean Cyr
		}
1387 61e047a5 Phil Davis
		// default-lease-time
1388
		if ($dhcpv6ifconf['defaultleasetime']) {
1389 693833cb Seth Mos
			$dhcpdv6conf .= "	default-lease-time {$dhcpv6ifconf['defaultleasetime']};\n";
1390 61e047a5 Phil Davis
		}
1391 693833cb Seth Mos
1392
		// max-lease-time
1393 61e047a5 Phil Davis
		if ($dhcpv6ifconf['maxleasetime']) {
1394 693833cb Seth Mos
			$dhcpdv6conf .= "	max-lease-time {$dhcpv6ifconf['maxleasetime']};\n";
1395 61e047a5 Phil Davis
		}
1396 693833cb Seth Mos
1397
		// ntp-servers
1398 4096fe5d smos
		if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) {
1399
			$ntpservers = array();
1400 61e047a5 Phil Davis
			foreach ($dhcpv6ifconf['ntpserver'] as $ntpserver) {
1401
				if (is_ipaddrv6($ntpserver)) {
1402 4096fe5d smos
					$ntpservers[] = $ntpserver;
1403 61e047a5 Phil Davis
				}
1404 4096fe5d smos
			}
1405 61e047a5 Phil Davis
			if (count($ntpservers) > 0) {
1406 4096fe5d smos
				$dhcpdv6conf .= "       option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n";
1407 61e047a5 Phil Davis
			}
1408 4096fe5d smos
		}
1409 693833cb Seth Mos
		// tftp-server-name
1410 7d504365 smos
		/* Needs ISC DHCPD support
1411 61e047a5 Phil Davis
		 if ($dhcpv6ifconf['tftp'] <> "") {
1412 693833cb Seth Mos
			$dhcpdv6conf .= "	option tftp-server-name \"{$dhcpv6ifconf['tftp']}\";\n";
1413 61e047a5 Phil Davis
		 }
1414 7d504365 smos
		*/
1415 693833cb Seth Mos
1416
		// Handle option, number rowhelper values
1417
		$dhcpdv6conf .= "\n";
1418 1944af41 Ermal
		if ($dhcpv6ifconf['numberoptions']['item']) {
1419 61e047a5 Phil Davis
			foreach ($dhcpv6ifconf['numberoptions']['item'] as $itemv6idx => $itemv6) {
1420 693833cb Seth Mos
				$dhcpdv6conf .= "	option custom-{$dhcpv6if}-{$itemv6idx} \"{$itemv6['value']}\";\n";
1421
			}
1422
		}
1423
1424
		// ldap-server
1425 61e047a5 Phil Davis
		if ($dhcpv6ifconf['ldap'] <> "") {
1426 693833cb Seth Mos
			$dhcpdv6conf .= "	option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n";
1427 61e047a5 Phil Davis
		}
1428 693833cb Seth Mos
1429
		// net boot information
1430 61e047a5 Phil Davis
		if (isset($dhcpv6ifconf['netboot'])) {
1431 bd942860 Renato Botelho
			if (!empty($dhcpv6ifconf['bootfile_url'])) {
1432
				$dhcpdv6conf .= "	option dhcp6.bootfile-url \"{$dhcpv6ifconf['bootfile_url']}\";\n";
1433 abdd01f5 Ermal
			}
1434
		}
1435 107e8acc Ovidiu Predescu
1436 1c903aa4 Ermal
		$dhcpdv6conf .= "}\n";
1437 693833cb Seth Mos
1438
		/* add static mappings */
1439 2fb056d8 Seth Mos
		/* Needs to use DUID */
1440 693833cb Seth Mos
		if (is_array($dhcpv6ifconf['staticmap'])) {
1441
			$i = 0;
1442
			foreach ($dhcpv6ifconf['staticmap'] as $sm) {
1443
				$dhcpdv6conf .= <<<EOD
1444
host s_{$dhcpv6if}_{$i} {
1445 2fb056d8 Seth Mos
	host-identifier option dhcp6.client-id {$sm['duid']};
1446 693833cb Seth Mos
1447
EOD;
1448 61e047a5 Phil Davis
				if ($sm['ipaddrv6']) {
1449 2fb056d8 Seth Mos
					$dhcpdv6conf .= "	fixed-address6 {$sm['ipaddrv6']};\n";
1450 61e047a5 Phil Davis
				}
1451 693833cb Seth Mos
1452
				if ($sm['hostname']) {
1453
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
1454
					$dhhostname = str_replace(".", "_", $dhhostname);
1455
					$dhcpdv6conf .= "	option host-name {$dhhostname};\n";
1456
				}
1457 61e047a5 Phil Davis
				if ($sm['filename']) {
1458 a2578c27 Anthony Wrather
					$dhcpdv6conf .= "	filename \"{$sm['filename']}\";\n";
1459 61e047a5 Phil Davis
				}
1460 a2578c27 Anthony Wrather
1461 61e047a5 Phil Davis
				if ($sm['rootpath']) {
1462 a2578c27 Anthony Wrather
					$dhcpdv6conf .= "	option root-path \"{$sm['rootpath']}\";\n";
1463 61e047a5 Phil Davis
				}
1464 693833cb Seth Mos
1465
				$dhcpdv6conf .= "}\n";
1466
				$i++;
1467
			}
1468
		}
1469 107e8acc Ovidiu Predescu
1470 61e047a5 Phil Davis
		if ($dhcpv6ifconf['domain']) {
1471 87019fc4 Andres Petralli
			$dhcpdv6conf .= dhcpdkey($dhcpv6ifconf);
1472
			$dhcpdv6conf .= dhcpdzones($ddns_zones, $dhcpv6ifconf);
1473
		}
1474
1475 57006646 Renato Botelho
		if ($config['dhcpdv6'][$dhcpv6if]['ramode'] <> "unmanaged" && isset($config['interfaces'][$dhcpv6if]['enable'])) {
1476 61e047a5 Phil Davis
			if (preg_match("/poes/si", $dhcpv6if)) {
1477 e9ab2ddb smos
				/* magic here */
1478
				$dhcpdv6ifs = array_merge($dhcpdv6ifs, get_pppoes_child_interfaces($dhcpv6if));
1479
			} else {
1480 1944af41 Ermal
				$realif = get_real_interface($dhcpv6if, "inet6");
1481 029b377a Ermal
				if (stristr("$realif", "bridge")) {
1482
					$mac = get_interface_mac($realif);
1483
					$v6address = generate_ipv6_from_mac($mac);
1484
					/* Create link local address for bridges */
1485 e9ab2ddb smos
					mwexec("/sbin/ifconfig {$realif} inet6 {$v6address}");
1486
				}
1487 029b377a Ermal
				$realif = escapeshellcmd($realif);
1488
				$dhcpdv6ifs[] = $realif;
1489 656f1763 Seth Mos
			}
1490 de140730 Seth Mos
		}
1491 693833cb Seth Mos
	}
1492
1493 61e047a5 Phil Davis
	if ($nsupdate) {
1494 87019fc4 Andres Petralli
		$dhcpdv6conf .= "ddns-update-style interim;\n";
1495 61e047a5 Phil Davis
	} else {
1496 87019fc4 Andres Petralli
		$dhcpdv6conf .= "ddns-update-style none;\n";
1497
	}
1498
1499 abdd01f5 Ermal
	/* write dhcpdv6.conf */
1500
	if (!@file_put_contents("{$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf", $dhcpdv6conf)) {
1501 1c903aa4 Ermal
		log_error("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1502 61e047a5 Phil Davis
		if (platform_booting()) {
1503 1c903aa4 Ermal
			printf("Error: cannot open {$g['dhcpd_chroot_path']}/etc/dhcpdv6.conf in services_dhcpdv6_configure().\n");
1504 61e047a5 Phil Davis
		}
1505 abdd01f5 Ermal
		unset($dhcpdv6conf);
1506
		return 1;
1507
	}
1508 928d4416 Ermal
	unset($dhcpdv6conf);
1509
1510 693833cb Seth Mos
	/* create an empty leases v6 database */
1511 61e047a5 Phil Davis
	if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases")) {
1512 abdd01f5 Ermal
		@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1513 61e047a5 Phil Davis
	}
1514 107e8acc Ovidiu Predescu
1515 61e047a5 Phil Davis
	/* make sure there isn't a stale dhcpdv6.pid file, which may make dhcpdv6 fail to start.  */
1516
	/* if we get here, dhcpdv6 has been killed and is not started yet                         */
1517
	unlink_if_exists("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
1518 b075c1e2 Chris Buechler
1519 68a0e4fc Scott Ullrich
	/* fire up dhcpd in a chroot */
1520 abdd01f5 Ermal
	if (count($dhcpdv6ifs) > 0) {
1521 2fb056d8 Seth Mos
		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 " .
1522 2a1bd027 Seth Mos
			join(" ", $dhcpdv6ifs));
1523 cb7d18d5 Renato Botelho
		mwexec("/usr/local/sbin/dhcpleases6 -c \"/usr/local/bin/php-cgi -f /usr/local/sbin/prefixes.php|/bin/sh\" -l {$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases");
1524 2a1bd027 Seth Mos
	}
1525 61e047a5 Phil Davis
	if (platform_booting()) {
1526 f1a44a3a Carlos Eduardo Ramos
		print gettext("done.") . "\n";
1527 61e047a5 Phil Davis
	}
1528 a25183c5 Scott Ullrich
1529 5b237745 Scott Ullrich
	return 0;
1530
}
1531
1532 41997fbb Ermal Luci
function services_igmpproxy_configure() {
1533 61e047a5 Phil Davis
	global $config, $g;
1534 41997fbb Ermal Luci
1535 61e047a5 Phil Davis
	/* kill any running igmpproxy */
1536
	killbyname("igmpproxy");
1537 41997fbb Ermal Luci
1538 61e047a5 Phil Davis
	if (!is_array($config['igmpproxy']['igmpentry']) || (count($config['igmpproxy']['igmpentry']) == 0)) {
1539 41997fbb Ermal Luci
		return 1;
1540 61e047a5 Phil Davis
	}
1541 41997fbb Ermal Luci
1542 61e047a5 Phil Davis
	$iflist = get_configured_interface_list();
1543 f206afb5 Ermal
1544 61e047a5 Phil Davis
	$igmpconf = <<<EOD
1545 41997fbb Ermal Luci
1546
##------------------------------------------------------
1547
## Enable Quickleave mode (Sends Leave instantly)
1548
##------------------------------------------------------
1549
quickleave
1550
1551
EOD;
1552
1553 61e047a5 Phil Davis
	foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
1554
		unset($iflist[$igmpcf['ifname']]);
1555
		$realif = get_real_interface($igmpcf['ifname']);
1556
		if (empty($igmpcf['threshold'])) {
1557
			$threshld = 1;
1558
		} else {
1559
			$threshld = $igmpcf['threshold'];
1560
		}
1561
		$igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
1562
1563
		if ($igmpcf['address'] <> "") {
1564
			$item = explode(" ", $igmpcf['address']);
1565
			foreach ($item as $iww) {
1566
				$igmpconf .= "altnet {$iww}\n";
1567
			}
1568
		}
1569
		$igmpconf .= "\n";
1570
	}
1571
	foreach ($iflist as $ifn) {
1572
		$realif = get_real_interface($ifn);
1573
		$igmpconf .= "phyint {$realif} disabled\n";
1574
	}
1575 3bae60be Ermal
	$igmpconf .= "\n";
1576 41997fbb Ermal Luci
1577 61e047a5 Phil Davis
	$igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
1578
	if (!$igmpfl) {
1579
		log_error(gettext("Could not write Igmpproxy configuration file!"));
1580
		return;
1581
	}
1582
	fwrite($igmpfl, $igmpconf);
1583
	fclose($igmpfl);
1584 928d4416 Ermal
	unset($igmpconf);
1585 41997fbb Ermal Luci
1586 d629f1ca Renato Botelho
	/* NOTE: -d4 means everything LOG_WARNING and smaller */
1587 61e047a5 Phil Davis
	mwexec("/usr/local/sbin/igmpproxy -d4 -c {$g['tmp_path']}/igmpproxy.conf");
1588
	log_error(gettext("Started IGMP proxy service."));
1589 41997fbb Ermal Luci
1590 61e047a5 Phil Davis
	return 0;
1591 41997fbb Ermal Luci
}
1592
1593 5b237745 Scott Ullrich
function services_dhcrelay_configure() {
1594 f19d3b7a Scott Ullrich
	global $config, $g;
1595 6fa9f38c Renato Botelho
1596 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1597 acd910bf Scott Ullrich
		$mt = microtime();
1598 f19d3b7a Scott Ullrich
		echo "services_dhcrelay_configure() being called $mt\n";
1599 acd910bf Scott Ullrich
	}
1600 a25183c5 Scott Ullrich
1601 5b237745 Scott Ullrich
	/* kill any running dhcrelay */
1602
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1603 a25183c5 Scott Ullrich
1604 2f06cc3f Ermal
	$dhcrelaycfg =& $config['dhcrelay'];
1605 a25183c5 Scott Ullrich
1606 5b237745 Scott Ullrich
	/* DHCPRelay enabled on any interfaces? */
1607 61e047a5 Phil Davis
	if (!isset($dhcrelaycfg['enable'])) {
1608 5b237745 Scott Ullrich
		return 0;
1609 61e047a5 Phil Davis
	}
1610 a25183c5 Scott Ullrich
1611 61e047a5 Phil Davis
	if (platform_booting()) {
1612 f1a44a3a Carlos Eduardo Ramos
		echo gettext("Starting DHCP relay service...");
1613 61e047a5 Phil Davis
	} else {
1614 5b237745 Scott Ullrich
		sleep(1);
1615 61e047a5 Phil Davis
	}
1616 a25183c5 Scott Ullrich
1617 2f06cc3f Ermal
	$iflist = get_configured_interface_list();
1618 a25183c5 Scott Ullrich
1619 2f06cc3f Ermal
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1620
	foreach ($dhcifaces as $dhcrelayif) {
1621
		if (!isset($iflist[$dhcrelayif]) ||
1622 61e047a5 Phil Davis
		    link_interface_to_bridge($dhcrelayif)) {
1623 5b237745 Scott Ullrich
			continue;
1624 61e047a5 Phil Davis
		}
1625 a25183c5 Scott Ullrich
1626 61e047a5 Phil Davis
		if (is_ipaddr(get_interface_ip($dhcrelayif))) {
1627 2f06cc3f Ermal
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1628 61e047a5 Phil Davis
		}
1629 5b237745 Scott Ullrich
	}
1630
1631 d7827421 Renato Botelho
	/*
1632
	 * In order for the relay to work, it needs to be active
1633
	 * on the interface in which the destination server sits.
1634
	 */
1635 2f06cc3f Ermal
	$srvips = explode(",", $dhcrelaycfg['server']);
1636 c58879a9 Ermal LUÇI
	if (!is_array($srvips)) {
1637 578ae21f Renato Botelho
		log_error("No destination IP has been configured!");
1638 c58879a9 Ermal LUÇI
		return;
1639 4de8f7ba Phil Davis
	}
1640 a25183c5 Scott Ullrich
1641 d7827421 Renato Botelho
	foreach ($srvips as $srcidx => $srvip) {
1642
		unset($destif);
1643
		foreach ($iflist as $ifname) {
1644
			$subnet = get_interface_ip($ifname);
1645
			if (!is_ipaddr($subnet)) {
1646
				continue;
1647
			}
1648
			$subnet .= "/" . get_interface_subnet($ifname);
1649
			if (ip_in_subnet($srvip, $subnet)) {
1650
				$destif = get_real_interface($ifname);
1651
				break;
1652
			}
1653
		}
1654
		if (!isset($destif)) {
1655
			foreach (get_staticroutes() as $rtent) {
1656
				if (ip_in_subnet($srvip, $rtent['network'])) {
1657
					$a_gateways = return_gateways_array(true);
1658
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1659
					break;
1660
				}
1661
			}
1662
		}
1663
1664
		if (!isset($destif)) {
1665
			/* Create a array from the existing route table */
1666
			exec("/usr/bin/netstat -rnWf inet", $route_str);
1667
			array_shift($route_str);
1668
			array_shift($route_str);
1669
			array_shift($route_str);
1670
			array_shift($route_str);
1671
			$route_arr = array();
1672
			foreach ($route_str as $routeline) {
1673
				$items = preg_split("/[ ]+/i", $routeline);
1674
				if (is_subnetv4($items[0])) {
1675
					$subnet = $items[0];
1676
				} elseif (is_ipaddrv4($items[0])) {
1677
					$subnet = "{$items[0]}/32";
1678
				} else {
1679
					// Not a subnet or IP address, skip to the next line.
1680
					continue;
1681
				}
1682
				if (ip_in_subnet($srvip, $subnet)) {
1683
					$destif = trim($items[6]);
1684
					break;
1685
				}
1686
			}
1687
		}
1688
1689
		if (!isset($destif)) {
1690
			if (is_array($config['gateways']['gateway_item'])) {
1691
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1692
					if (isset($gateway['defaultgw'])) {
1693
						$destif = get_real_interface($gateway['interface']);
1694
						break;
1695
					}
1696
				}
1697
			} else {
1698
				$destif = get_real_interface("wan");
1699
			}
1700
		}
1701
1702
		if (!empty($destif)) {
1703
			$dhcrelayifs[] = $destif;
1704
		}
1705
	}
1706 5b237745 Scott Ullrich
	$dhcrelayifs = array_unique($dhcrelayifs);
1707
1708
	/* fire up dhcrelay */
1709 24997966 Ermal
	if (empty($dhcrelayifs)) {
1710 5a171fb7 Warren Baker
		log_error("No suitable interface found for running dhcrelay!");
1711 24997966 Ermal
		return; /* XXX */
1712
	}
1713
1714 4de8f7ba Phil Davis
	$cmd = "/usr/local/sbin/dhcrelay -i " . implode(" -i ", $dhcrelayifs);
1715 5b237745 Scott Ullrich
1716 61e047a5 Phil Davis
	if (isset($dhcrelaycfg['agentoption'])) {
1717 4de8f7ba Phil Davis
		$cmd .= " -a -m replace";
1718 61e047a5 Phil Davis
	}
1719 5b237745 Scott Ullrich
1720 2f06cc3f Ermal
	$cmd .= " " . implode(" ", $srvips);
1721 5b237745 Scott Ullrich
	mwexec($cmd);
1722 928d4416 Ermal
	unset($cmd);
1723 a25183c5 Scott Ullrich
1724 5b237745 Scott Ullrich
	return 0;
1725
}
1726
1727 b7a15cf8 Seth Mos
function services_dhcrelay6_configure() {
1728
	global $config, $g;
1729 6fa9f38c Renato Botelho
1730 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1731 b7a15cf8 Seth Mos
		$mt = microtime();
1732 874f099a Phil Davis
		echo "services_dhcrelay6_configure() being called $mt\n";
1733 b7a15cf8 Seth Mos
	}
1734
1735
	/* kill any running dhcrelay */
1736
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1737
1738
	$dhcrelaycfg =& $config['dhcrelay6'];
1739
1740
	/* DHCPv6 Relay enabled on any interfaces? */
1741 61e047a5 Phil Davis
	if (!isset($dhcrelaycfg['enable'])) {
1742 b7a15cf8 Seth Mos
		return 0;
1743 61e047a5 Phil Davis
	}
1744 b7a15cf8 Seth Mos
1745 61e047a5 Phil Davis
	if (platform_booting()) {
1746 b7a15cf8 Seth Mos
		echo gettext("Starting DHCPv6 relay service...");
1747 61e047a5 Phil Davis
	} else {
1748 b7a15cf8 Seth Mos
		sleep(1);
1749 61e047a5 Phil Davis
	}
1750 b7a15cf8 Seth Mos
1751
	$iflist = get_configured_interface_list();
1752
1753
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1754
	foreach ($dhcifaces as $dhcrelayif) {
1755
		if (!isset($iflist[$dhcrelayif]) ||
1756 086cf944 Phil Davis
		    link_interface_to_bridge($dhcrelayif)) {
1757 b7a15cf8 Seth Mos
			continue;
1758 086cf944 Phil Davis
		}
1759 b7a15cf8 Seth Mos
1760 61e047a5 Phil Davis
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif))) {
1761 b7a15cf8 Seth Mos
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1762 61e047a5 Phil Davis
		}
1763 b7a15cf8 Seth Mos
	}
1764 69dd7088 Michael Tharp
	$dhcrelayifs = array_unique($dhcrelayifs);
1765 b7a15cf8 Seth Mos
1766 d7827421 Renato Botelho
	/*
1767
	 * In order for the relay to work, it needs to be active
1768
	 * on the interface in which the destination server sits.
1769
	 */
1770 b7a15cf8 Seth Mos
	$srvips = explode(",", $dhcrelaycfg['server']);
1771 d7827421 Renato Botelho
	$srvifaces = array();
1772
	foreach ($srvips as $srcidx => $srvip) {
1773
		unset($destif);
1774
		foreach ($iflist as $ifname) {
1775
			$subnet = get_interface_ipv6($ifname);
1776
			if (!is_ipaddrv6($subnet)) {
1777
				continue;
1778
			}
1779
			$subnet .= "/" . get_interface_subnetv6($ifname);
1780
			if (ip_in_subnet($srvip, $subnet)) {
1781
				$destif = get_real_interface($ifname);
1782
				break;
1783
			}
1784
		}
1785
		if (!isset($destif)) {
1786
			if (is_array($config['staticroutes']['route'])) {
1787
				foreach ($config['staticroutes']['route'] as $rtent) {
1788
					if (ip_in_subnet($srvip, $rtent['network'])) {
1789
						$a_gateways = return_gateways_array(true);
1790
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1791
						break;
1792
					}
1793
				}
1794
			}
1795
		}
1796
1797
		if (!isset($destif)) {
1798
			/* Create a array from the existing route table */
1799
			exec("/usr/bin/netstat -rnWf inet6", $route_str);
1800
			array_shift($route_str);
1801
			array_shift($route_str);
1802
			array_shift($route_str);
1803
			array_shift($route_str);
1804
			$route_arr = array();
1805
			foreach ($route_str as $routeline) {
1806
				$items = preg_split("/[ ]+/i", $routeline);
1807
				if (ip_in_subnet($srvip, $items[0])) {
1808
					$destif = trim($items[6]);
1809
					break;
1810
				}
1811
			}
1812
		}
1813
1814
		if (!isset($destif)) {
1815
			if (is_array($config['gateways']['gateway_item'])) {
1816
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1817
					if (isset($gateway['defaultgw'])) {
1818
						$destif = get_real_interface($gateway['interface']);
1819
						break;
1820
					}
1821
				}
1822
			} else {
1823
				$destif = get_real_interface("wan");
1824
			}
1825
		}
1826
1827
		if (!empty($destif)) {
1828
			$srvifaces[] = "{$srvip}%{$destif}";
1829
		}
1830 b7a15cf8 Seth Mos
	}
1831
1832
	/* fire up dhcrelay */
1833 61e047a5 Phil Davis
	if (empty($dhcrelayifs) || empty($srvifaces)) {
1834 b7a15cf8 Seth Mos
		log_error("No suitable interface found for running dhcrelay -6!");
1835
		return; /* XXX */
1836
	}
1837
1838 54a9d71d Phil Davis
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1839 69dd7088 Michael Tharp
	foreach ($dhcrelayifs as $dhcrelayif) {
1840
		$cmd .= " -l {$dhcrelayif}";
1841
	}
1842
	foreach ($srvifaces as $srviface) {
1843
		$cmd .= " -u \"{$srviface}\"";
1844
	}
1845 b7a15cf8 Seth Mos
	mwexec($cmd);
1846 928d4416 Ermal
	unset($cmd);
1847 b7a15cf8 Seth Mos
1848
	return 0;
1849
}
1850
1851 181d7c95 Ermal Luçi
function services_dyndns_configure_client($conf) {
1852
1853 61e047a5 Phil Davis
	if (!isset($conf['enable'])) {
1854 65996399 Ermal
		return;
1855 61e047a5 Phil Davis
	}
1856 d2946062 Ermal
1857 181d7c95 Ermal Luçi
	/* load up the dyndns.class */
1858
	require_once("dyndns.class");
1859
1860
	$dns = new updatedns($dnsService = $conf['type'],
1861
		$dnsHost = $conf['host'],
1862
		$dnsUser = $conf['username'],
1863
		$dnsPass = $conf['password'],
1864 3aa55bbe Phil Davis
		$dnsWildcard = $conf['wildcard'],
1865 107e8acc Ovidiu Predescu
		$dnsMX = $conf['mx'],
1866 f3b2b2a4 Yehuda Katz
		$dnsIf = "{$conf['interface']}",
1867
		$dnsBackMX = NULL,
1868
		$dnsServer = NULL,
1869
		$dnsPort = NULL,
1870 37f3e704 Matt Corallo
		$dnsUpdateURL = "{$conf['updateurl']}",
1871 cd132e86 Edson Brandi
		$forceUpdate = $conf['force'],
1872 4de8f7ba Phil Davis
		$dnsZoneID = $conf['zoneid'],
1873
		$dnsTTL = $conf['ttl'],
1874 37f3e704 Matt Corallo
		$dnsResultMatch = "{$conf['resultmatch']}",
1875
		$dnsRequestIf = "{$conf['requestif']}",
1876 1e503870 Phil Davis
		$dnsID = "{$conf['id']}",
1877 aa79f351 Sebastian Chrostek
		$dnsVerboseLog = $conf['verboselog'],
1878
		$curlIpresolveV4 = $conf['curl_ipresolve_v4'],
1879
		$curlSslVerifypeer = $conf['curl_ssl_verifypeer']);
1880 181d7c95 Ermal Luçi
}
1881
1882 0be93267 Ermal Lu?i
function services_dyndns_configure($int = "") {
1883 f19d3b7a Scott Ullrich
	global $config, $g;
1884 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1885 59a63553 Scott Ullrich
		$mt = microtime();
1886
		echo "services_dyndns_configure() being called $mt\n";
1887
	}
1888
1889 67ee1ec5 Ermal Luçi
	$dyndnscfg = $config['dyndnses']['dyndns'];
1890 017817c2 smos
	$gwgroups = return_gateway_groups_array();
1891 67ee1ec5 Ermal Luçi
	if (is_array($dyndnscfg)) {
1892 61e047a5 Phil Davis
		if (platform_booting()) {
1893 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting DynDNS clients...");
1894 61e047a5 Phil Davis
		}
1895 181d7c95 Ermal Luçi
1896 67ee1ec5 Ermal Luçi
		foreach ($dyndnscfg as $dyndns) {
1897 786ff5eb phildd
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1898 1e503870 Phil Davis
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1899 d9bdc020 Sebastian Chrostek
				$dyndns['curl_ipresolve_v4'] = isset($dyndns['curl_ipresolve_v4']);
1900
				$dyndns['curl_ssl_verifypeer'] = isset($dyndns['curl_ssl_verifypeer']);
1901 768eb89c smos
				services_dyndns_configure_client($dyndns);
1902
				sleep(1);
1903
			}
1904 67ee1ec5 Ermal Luçi
		}
1905 59a63553 Scott Ullrich
1906 61e047a5 Phil Davis
		if (platform_booting()) {
1907 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
1908 61e047a5 Phil Davis
		}
1909 59a63553 Scott Ullrich
	}
1910
1911
	return 0;
1912
}
1913
1914 0e3aeb6b Phil Davis
function dyndnsCheckIP($int) {
1915 873e4b28 phildd
	global $config;
1916 0e3aeb6b Phil Davis
	$ip_address = get_interface_ip($int);
1917
	if (is_private_ip($ip_address)) {
1918 873e4b28 phildd
		$gateways_status = return_gateways_status(true);
1919
		// If the gateway for this interface is down, then the external check cannot work.
1920
		// Avoid the long wait for the external check to timeout.
1921 61e047a5 Phil Davis
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'], "down")) {
1922 873e4b28 phildd
			return "down";
1923 61e047a5 Phil Davis
		}
1924 5244c510 Florian Asche
		$hosttocheck = "http://checkip.dyndns.org";
1925
		$ip_ch = curl_init($hosttocheck);
1926 0e3aeb6b Phil Davis
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1927
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1928 e1eee3d2 Renato Botelho
		curl_setopt($ip_ch, CURLOPT_INTERFACE, 'host!' . $ip_address);
1929 181386d6 Florian Asche
		curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1930
		curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1931 3c6f29c0 Florian Asche
		curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1932 0e3aeb6b Phil Davis
		$ip_result_page = curl_exec($ip_ch);
1933
		curl_close($ip_ch);
1934
		$ip_result_decoded = urldecode($ip_result_page);
1935
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1936
		$ip_address = trim($matches[1]);
1937
	}
1938
	return $ip_address;
1939
}
1940
1941 5b237745 Scott Ullrich
function services_dnsmasq_configure() {
1942 f19d3b7a Scott Ullrich
	global $config, $g;
1943 6a01ea44 Bill Marquette
	$return = 0;
1944 107e8acc Ovidiu Predescu
1945 683992fc stilez
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1946
	$standard_args = array(
1947
		"dns-forward-max" => "--dns-forward-max=5000",
1948
		"cache-size" => "--cache-size=10000",
1949
		"local-ttl" => "--local-ttl=1"
1950
	);
1951
1952
1953 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1954 acd910bf Scott Ullrich
		$mt = microtime();
1955 f19d3b7a Scott Ullrich
		echo "services_dnsmasq_configure() being called $mt\n";
1956 acd910bf Scott Ullrich
	}
1957
1958 5b237745 Scott Ullrich
	/* kill any running dnsmasq */
1959 61e047a5 Phil Davis
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid")) {
1960 d224df18 Ermal
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1961 61e047a5 Phil Davis
	}
1962 5b237745 Scott Ullrich
1963
	if (isset($config['dnsmasq']['enable'])) {
1964 a25183c5 Scott Ullrich
1965 61e047a5 Phil Davis
		if (platform_booting()) {
1966 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting DNS forwarder...");
1967 61e047a5 Phil Davis
		} else {
1968 5b237745 Scott Ullrich
			sleep(1);
1969 61e047a5 Phil Davis
		}
1970 5b237745 Scott Ullrich
1971 61e047a5 Phil Davis
		/* generate hosts file */
1972 4de8f7ba Phil Davis
		if (system_hosts_generate() != 0) {
1973 61e047a5 Phil Davis
			$return = 1;
1974
		}
1975 cbc6a13f Chris Buechler
1976 5b237745 Scott Ullrich
		$args = "";
1977 a25183c5 Scott Ullrich
1978 0261381a Ermal
		if (isset($config['dnsmasq']['regdhcp'])) {
1979
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1980
		}
1981 107e8acc Ovidiu Predescu
1982 e6c49e3d jim-p
		/* Setup listen port, if non-default */
1983 61e047a5 Phil Davis
		if (is_port($config['dnsmasq']['port'])) {
1984 e6c49e3d jim-p
			$args .= " --port={$config['dnsmasq']['port']} ";
1985 61e047a5 Phil Davis
		}
1986 e6c49e3d jim-p
1987 b4323f39 jim-p
		$listen_addresses = "";
1988 61e047a5 Phil Davis
		if (isset($config['dnsmasq']['interface'])) {
1989 b4323f39 jim-p
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1990
			foreach ($interfaces as $interface) {
1991 55909a9a Ermal
				if (is_ipaddrv4($interface)) {
1992 b4323f39 jim-p
					$listen_addresses .= " --listen-address={$interface} ";
1993 55909a9a Ermal
				} else if (is_ipaddrv6($interface)) {
1994
					/*
1995
					 * XXX: Since dnsmasq does not support link-local address
1996
					 * with scope specified. These checks are being done.
1997
					 */
1998
					if (is_linklocal($interface) && strstr($interface, "%")) {
1999
						$tmpaddrll6 = explode("%", $interface);
2000
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
2001 61e047a5 Phil Davis
					} else {
2002 55909a9a Ermal
						$listen_addresses .= " --listen-address={$interface} ";
2003 61e047a5 Phil Davis
					}
2004 9e7e2c94 Chris Buechler
				} else if (strstr($interface, "_vip")) {
2005
					$laddr = get_configured_carp_interface_list($interface);
2006 61e047a5 Phil Davis
					if (is_ipaddr($laddr)) {
2007 9e7e2c94 Chris Buechler
						$listen_addresses .= " --listen-address={$laddr} ";
2008 61e047a5 Phil Davis
					}
2009 b4323f39 jim-p
				} else {
2010
					$if = get_real_interface($interface);
2011
					if (does_interface_exist($if)) {
2012 89f171b0 Ermal LUÇI
						$laddr = get_interface_ip($interface);
2013 61e047a5 Phil Davis
						if (is_ipaddrv4($laddr)) {
2014 b4323f39 jim-p
							$listen_addresses .= " --listen-address={$laddr} ";
2015 61e047a5 Phil Davis
						}
2016 89f171b0 Ermal LUÇI
						$laddr6 = get_interface_ipv6($interface);
2017 b77d19c7 Ermal
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
2018
							/*
2019
							 * XXX: Since dnsmasq does not support link-local address
2020
							 * with scope specified. These checks are being done.
2021
							 */
2022
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
2023
								$tmpaddrll6 = explode("%", $laddr6);
2024
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
2025 61e047a5 Phil Davis
							} else {
2026 b77d19c7 Ermal
								$listen_addresses .= " --listen-address={$laddr6} ";
2027 61e047a5 Phil Davis
							}
2028 b77d19c7 Ermal
						}
2029 b4323f39 jim-p
					}
2030
				}
2031
			}
2032
			if (!empty($listen_addresses)) {
2033
				$args .= " {$listen_addresses} ";
2034 61e047a5 Phil Davis
				if (isset($config['dnsmasq']['strictbind'])) {
2035 b4323f39 jim-p
					$args .= " --bind-interfaces ";
2036 61e047a5 Phil Davis
				}
2037 b4323f39 jim-p
			}
2038
		}
2039
2040 fc27d3f4 Phil Davis
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
2041 153613e3 Phil Davis
		/* Only make entries for reverse domains that do not have a matching domain override. */
2042 0a7985ba Phil Davis
		if (isset($config['dnsmasq']['no_private_reverse'])) {
2043
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
2044
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
2045
			/* Just the pfSense WAN might get a CGN address from an ISP. */
2046 153613e3 Phil Davis
2047
			// Build an array of domain overrides to help in checking for matches.
2048
			$override_a = array();
2049
			if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2050
				foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2051
					$override_a[$override['domain']] = "y";
2052
				}
2053 0a7985ba Phil Davis
			}
2054 153613e3 Phil Davis
2055
			// Build an array of the private reverse lookup domain names
2056
			$reverse_domain_a = array("10.in-addr.arpa", "168.192.in-addr.arpa");
2057
			// Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme.
2058 61e047a5 Phil Davis
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) {
2059 153613e3 Phil Davis
				$reverse_domain_a[] = "$subnet_num.172.in-addr.arpa";
2060
			}
2061
2062
			// Set the --server parameter to nowhere for each reverse domain name that was not specifically specified in a domain override.
2063 61e047a5 Phil Davis
			foreach ($reverse_domain_a as $reverse_domain) {
2064
				if (!isset($override_a[$reverse_domain])) {
2065 153613e3 Phil Davis
					$args .= " --server=/$reverse_domain/ ";
2066 61e047a5 Phil Davis
				}
2067 0a7985ba Phil Davis
			}
2068 153613e3 Phil Davis
			unset($override_a);
2069
			unset($reverse_domain_a);
2070 0a7985ba Phil Davis
		}
2071
2072 fc27d3f4 Phil Davis
		/* Setup forwarded domains */
2073
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2074 61e047a5 Phil Davis
			foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2075
				if ($override['ip'] == "!") {
2076 fc27d3f4 Phil Davis
					$override[ip] = "";
2077 61e047a5 Phil Davis
				}
2078 fc27d3f4 Phil Davis
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
2079
			}
2080
		}
2081
2082 2c46f11f Scott Ullrich
		/* Allow DNS Rebind for forwarded domains */
2083 29721fe6 Scott Ullrich
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2084 61e047a5 Phil Davis
			if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
2085
				foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2086 30d20e7d Scott Ullrich
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
2087
				}
2088 2c46f11f Scott Ullrich
			}
2089
		}
2090 91adc5c1 Scott Ullrich
2091 61e047a5 Phil Davis
		if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
2092 30d20e7d Scott Ullrich
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
2093 61e047a5 Phil Davis
		}
2094 30d20e7d Scott Ullrich
2095 96ea7162 N0YB
		if (isset($config['dnsmasq']['strict_order'])) {
2096
			$args .= " --strict-order ";
2097
		}
2098
2099
		if (isset($config['dnsmasq']['domain_needed'])) {
2100
			$args .= " --domain-needed ";
2101
		}
2102
2103 61e047a5 Phil Davis
		if ($config['dnsmasq']['custom_options']) {
2104 683992fc stilez
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
2105 071f6059 jim-p
				$args .= " " . escapeshellarg("--{$c}");
2106 683992fc stilez
				$p = explode('=', $c);
2107 61e047a5 Phil Davis
				if (array_key_exists($p[0], $standard_args)) {
2108 683992fc stilez
					unset($standard_args[$p[0]]);
2109 61e047a5 Phil Davis
				}
2110 683992fc stilez
			}
2111 61e047a5 Phil Davis
		}
2112 41567e06 jim-p
		$args .= ' ' . implode(' ', array_values($standard_args));
2113 8f9bffbc Andrew Thompson
2114 5b237745 Scott Ullrich
		/* run dnsmasq */
2115 683992fc stilez
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
2116 b4323f39 jim-p
		//log_error("dnsmasq command: {$cmd}");
2117
		mwexec_bg($cmd);
2118 928d4416 Ermal
		unset($args);
2119 5b237745 Scott Ullrich
2120 61e047a5 Phil Davis
		system_dhcpleases_configure();
2121 0a5a8df9 Warren Baker
2122 61e047a5 Phil Davis
		if (platform_booting()) {
2123 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
2124 61e047a5 Phil Davis
		}
2125 5b237745 Scott Ullrich
	}
2126 a25183c5 Scott Ullrich
2127 285ef132 Ermal LUÇI
	if (!platform_booting()) {
2128 4de8f7ba Phil Davis
		if (services_dhcpd_configure() != 0) {
2129 6a01ea44 Bill Marquette
			$return = 1;
2130 61e047a5 Phil Davis
		}
2131 5b237745 Scott Ullrich
	}
2132
2133 6a01ea44 Bill Marquette
	return $return;
2134 5b237745 Scott Ullrich
}
2135
2136 175dc861 Warren Baker
function services_unbound_configure() {
2137
	global $config, $g;
2138
	$return = 0;
2139
2140
	if (isset($config['system']['developerspew'])) {
2141
		$mt = microtime();
2142
		echo "services_unbound_configure() being called $mt\n";
2143
	}
2144
2145
	// kill any running Unbound instance
2146 61e047a5 Phil Davis
	if (file_exists("{$g['varrun_path']}/unbound.pid")) {
2147 175dc861 Warren Baker
		sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
2148 61e047a5 Phil Davis
	}
2149 175dc861 Warren Baker
2150
	if (isset($config['unbound']['enable'])) {
2151 61e047a5 Phil Davis
		if (platform_booting()) {
2152 5bb1c495 Warren Baker
			echo gettext("Starting DNS Resolver...");
2153 61e047a5 Phil Davis
		} else {
2154 175dc861 Warren Baker
			sleep(1);
2155 61e047a5 Phil Davis
		}
2156 175dc861 Warren Baker
2157 b3c6783f Renato Botelho
		/* generate hosts file */
2158 4de8f7ba Phil Davis
		if (system_hosts_generate() != 0) {
2159 b3c6783f Renato Botelho
			$return = 1;
2160 61e047a5 Phil Davis
		}
2161 b3c6783f Renato Botelho
2162 175dc861 Warren Baker
		require_once('/etc/inc/unbound.inc');
2163
		sync_unbound_service();
2164 61e047a5 Phil Davis
		if (platform_booting()) {
2165 175dc861 Warren Baker
			echo gettext("done.") . "\n";
2166 61e047a5 Phil Davis
		}
2167 0a5a8df9 Warren Baker
2168 61e047a5 Phil Davis
		system_dhcpleases_configure();
2169 175dc861 Warren Baker
	}
2170
2171 285ef132 Ermal LUÇI
	if (!platform_booting()) {
2172 4de8f7ba Phil Davis
		if (services_dhcpd_configure() != 0) {
2173 175dc861 Warren Baker
			$return = 1;
2174 61e047a5 Phil Davis
		}
2175 175dc861 Warren Baker
	}
2176
2177
	return $return;
2178
}
2179
2180 5b237745 Scott Ullrich
function services_snmpd_configure() {
2181 f19d3b7a Scott Ullrich
	global $config, $g;
2182 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
2183 acd910bf Scott Ullrich
		$mt = microtime();
2184 f19d3b7a Scott Ullrich
		echo "services_snmpd_configure() being called $mt\n";
2185
	}
2186 5b237745 Scott Ullrich
2187
	/* kill any running snmpd */
2188
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
2189 dd18038e Ermal
	sleep(2);
2190 61e047a5 Phil Davis
	if (is_process_running("bsnmpd")) {
2191 a976fa82 Scott Ullrich
		mwexec("/usr/bin/killall bsnmpd", true);
2192 61e047a5 Phil Davis
	}
2193 5b237745 Scott Ullrich
2194
	if (isset($config['snmpd']['enable'])) {
2195 a25183c5 Scott Ullrich
2196 61e047a5 Phil Davis
		if (platform_booting()) {
2197 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting SNMP daemon... ");
2198 61e047a5 Phil Davis
		}
2199 5b237745 Scott Ullrich
2200
		/* generate snmpd.conf */
2201
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
2202
		if (!$fd) {
2203 4de8f7ba Phil Davis
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"), "\n");
2204 5b237745 Scott Ullrich
			return 1;
2205
		}
2206 a25183c5 Scott Ullrich
2207 142da8f7 John Fleming
2208 5b237745 Scott Ullrich
		$snmpdconf = <<<EOD
2209 d47a8a69 Scott Ullrich
location := "{$config['snmpd']['syslocation']}"
2210
contact := "{$config['snmpd']['syscontact']}"
2211
read := "{$config['snmpd']['rocommunity']}"
2212 142da8f7 John Fleming
2213
EOD;
2214
2215
/* No docs on what write strings do there for disable for now.
2216 61e047a5 Phil Davis
		if (isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])) {
2217
			$snmpdconf .= <<<EOD
2218 142da8f7 John Fleming
# write string
2219
write := "{$config['snmpd']['rwcommunity']}"
2220
2221
EOD;
2222
		}
2223
*/
2224
2225
2226 61e047a5 Phil Davis
		if (isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])) {
2227
			$snmpdconf .= <<<EOD
2228 142da8f7 John Fleming
# SNMP Trap support.
2229 dbeeb008 John Fleming
traphost := {$config['snmpd']['trapserver']}
2230
trapport := {$config['snmpd']['trapserverport']}
2231
trap := "{$config['snmpd']['trapstring']}"
2232 142da8f7 John Fleming
2233
2234
EOD;
2235
		}
2236
2237 dadf8ebb jim-p
		$platform = trim(file_get_contents('/etc/platform'));
2238 61e047a5 Phil Davis
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense")) {
2239 e52cb3a4 jim-p
			$platform = $g['product_name'];
2240 61e047a5 Phil Davis
		}
2241 dadf8ebb jim-p
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
2242 5779ade6 Renato Botelho
			" {$g['product_version']} {$platform} " . php_uname("s") .
2243 dadf8ebb jim-p
			" " . php_uname("r") . " " . php_uname("m");
2244 142da8f7 John Fleming
2245
		$snmpdconf .= <<<EOD
2246 d47a8a69 Scott Ullrich
system := 1     # pfSense
2247
%snmpd
2248 dadf8ebb jim-p
sysDescr			= "{$sysDescr}"
2249 d47a8a69 Scott Ullrich
begemotSnmpdDebugDumpPdus       = 2
2250
begemotSnmpdDebugSyslogPri      = 7
2251
begemotSnmpdCommunityString.0.1 = $(read)
2252 142da8f7 John Fleming
2253
EOD;
2254
2255
/* No docs on what write strings do there for disable for now.
2256 61e047a5 Phil Davis
		if (isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])) {
2257
			$snmpdconf .= <<<EOD
2258 142da8f7 John Fleming
begemotSnmpdCommunityString.0.2 = $(write)
2259
2260
EOD;
2261
		}
2262
*/
2263
2264 c7f44ae0 Scott Ullrich
2265 61e047a5 Phil Davis
		if (isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])) {
2266
			$snmpdconf .= <<<EOD
2267 142da8f7 John Fleming
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
2268
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
2269
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
2270
2271
EOD;
2272
		}
2273
2274
2275
		$snmpdconf .= <<<EOD
2276 d47a8a69 Scott Ullrich
begemotSnmpdCommunityDisable    = 1
2277 03ba7a0f John Fleming
2278
EOD;
2279
2280 de5aec97 jim-p
		if (isset($config['snmpd']['bindlan'])) {
2281
			$config['snmpd']['bindip'] = 'lan';
2282
			unset($config['snmpd']['bindlan']);
2283
		}
2284 c82b2c3f jim-p
		$bind_to_ip = "0.0.0.0";
2285 61e047a5 Phil Davis
		if (isset($config['snmpd']['bindip'])) {
2286 c82b2c3f jim-p
			if (is_ipaddr($config['snmpd']['bindip'])) {
2287
				$bind_to_ip = $config['snmpd']['bindip'];
2288
			} else {
2289
				$if = get_real_interface($config['snmpd']['bindip']);
2290 61e047a5 Phil Davis
				if (does_interface_exist($if)) {
2291 89f171b0 Ermal LUÇI
					$bind_to_ip = get_interface_ip($config['snmpd']['bindip']);
2292 61e047a5 Phil Davis
				}
2293 c82b2c3f jim-p
			}
2294 7cbad422 Scott Ullrich
		}
2295
2296 61e047a5 Phil Davis
		if (is_port($config['snmpd']['pollport'])) {
2297
			$snmpdconf .= <<<EOD
2298 7cbad422 Scott Ullrich
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
2299 03ba7a0f John Fleming
2300
EOD;
2301
2302
		}
2303
2304
		$snmpdconf .= <<<EOD
2305 d47a8a69 Scott Ullrich
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
2306
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
2307 142da8f7 John Fleming
2308 03ba7a0f John Fleming
# These are bsnmp macros not php vars.
2309 9cc8c59e Scott Ullrich
sysContact      = $(contact)
2310
sysLocation     = $(location)
2311
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
2312 142da8f7 John Fleming
2313 d47a8a69 Scott Ullrich
snmpEnableAuthenTraps = 2
2314 03ba7a0f John Fleming
2315
EOD;
2316
2317 61e047a5 Phil Davis
		if (is_array($config['snmpd']['modules'])) {
2318
			if (isset($config['snmpd']['modules']['mibii'])) {
2319 03ba7a0f John Fleming
			$snmpdconf .= <<<EOD
2320 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
2321 03ba7a0f John Fleming
2322
EOD;
2323 61e047a5 Phil Davis
			}
2324 03ba7a0f John Fleming
2325 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['netgraph'])) {
2326
				$snmpdconf .= <<<EOD
2327 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
2328
%netgraph
2329
begemotNgControlNodeName = "snmpd"
2330 03ba7a0f John Fleming
2331
EOD;
2332 61e047a5 Phil Davis
			}
2333 03ba7a0f John Fleming
2334 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['pf'])) {
2335
				$snmpdconf .= <<<EOD
2336 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
2337 95fb49e8 Seth Mos
2338
EOD;
2339 61e047a5 Phil Davis
			}
2340 95fb49e8 Seth Mos
2341 a03974a3 Renato Botelho
			if (isset($config['snmpd']['modules']['hostres'])) {
2342
				/* XXX: hostres module crashes APU - ticket #4403 */
2343
				$specplatform = system_identify_specific_platform();
2344
				if ($specplatform['name'] == 'APU') {
2345
					log_error("'Host Resources' SNMP module was ignored because it can potentially crash system on APU boards");
2346
				} else {
2347
					$snmpdconf .= <<<EOD
2348 95fb49e8 Seth Mos
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
2349
2350
EOD;
2351 a03974a3 Renato Botelho
				}
2352
				unset($specplatform);
2353 61e047a5 Phil Davis
			}
2354 05036071 Renato Botelho
2355 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['bridge'])) {
2356
				$snmpdconf .= <<<EOD
2357 95fb49e8 Seth Mos
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
2358 d47a8a69 Scott Ullrich
# config must end with blank line
2359 5b237745 Scott Ullrich
2360
EOD;
2361 61e047a5 Phil Davis
			}
2362
			if (isset($config['snmpd']['modules']['ucd'])) {
2363 671914b2 jim-p
				$snmpdconf .= <<<EOD
2364
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
2365
2366
EOD;
2367
			}
2368 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['regex'])) {
2369 671914b2 jim-p
				$snmpdconf .= <<<EOD
2370
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
2371
2372
EOD;
2373
			}
2374 03ba7a0f John Fleming
		}
2375 5b237745 Scott Ullrich
2376
		fwrite($fd, $snmpdconf);
2377
		fclose($fd);
2378 928d4416 Ermal
		unset($snmpdconf);
2379 5b237745 Scott Ullrich
2380 7cbad422 Scott Ullrich
		if (isset($config['snmpd']['bindlan'])) {
2381
			$bindlan = "";
2382
		}
2383
2384 853e003a Scott Ullrich
		/* run bsnmpd */
2385
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
2386 7cbad422 Scott Ullrich
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
2387 5b237745 Scott Ullrich
2388 61e047a5 Phil Davis
		if (platform_booting()) {
2389 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
2390 61e047a5 Phil Davis
		}
2391 5b237745 Scott Ullrich
	}
2392
2393
	return 0;
2394
}
2395
2396 7c9da7be jim-p
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
2397 f19d3b7a Scott Ullrich
	global $config, $g;
2398 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
2399 acd910bf Scott Ullrich
		$mt = microtime();
2400 f19d3b7a Scott Ullrich
		echo "services_dnsupdate_process() being called $mt\n";
2401 acd910bf Scott Ullrich
	}
2402 f19d3b7a Scott Ullrich
2403 a23d7248 Scott Ullrich
	/* Dynamic DNS updating active? */
2404 67ee1ec5 Ermal Luçi
	if (is_array($config['dnsupdates']['dnsupdate'])) {
2405 7c9da7be jim-p
		$notify_text = "";
2406 67ee1ec5 Ermal Luçi
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
2407 61e047a5 Phil Davis
			if (!isset($dnsupdate['enable'])) {
2408 2ec2a374 Ermal Lu?i
				continue;
2409 61e047a5 Phil Davis
			}
2410
			if (!empty($int) && $int != $dnsupdate['interface']) {
2411 67ee1ec5 Ermal Luçi
				continue;
2412 61e047a5 Phil Davis
			}
2413
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host'])) {
2414 7c9da7be jim-p
				continue;
2415 61e047a5 Phil Davis
			}
2416 67ee1ec5 Ermal Luçi
2417 2ec2a374 Ermal Lu?i
			/* determine interface name */
2418 26586f7a Ermal Lu?i
			$if = get_real_interface($dnsupdate['interface']);
2419 61e047a5 Phil Davis
2420
			if (isset($dnsupdate['usepublicip'])) {
2421
				$wanip = dyndnsCheckIP($dnsupdate['interface']);
2422
			} else {
2423
				$wanip = get_interface_ip($dnsupdate['interface']);
2424
			}
2425
2426 fc1f4960 jim-p
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2427 7c9da7be jim-p
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2428
			$currentTime = time();
2429
2430
			if ($wanip || $wanipv6) {
2431 67ee1ec5 Ermal Luçi
				$keyname = $dnsupdate['keyname'];
2432
				/* trailing dot */
2433 61e047a5 Phil Davis
				if (substr($keyname, -1) != ".") {
2434 67ee1ec5 Ermal Luçi
					$keyname .= ".";
2435 61e047a5 Phil Davis
				}
2436 67ee1ec5 Ermal Luçi
2437
				$hostname = $dnsupdate['host'];
2438
				/* trailing dot */
2439 61e047a5 Phil Davis
				if (substr($hostname, -1) != ".") {
2440 67ee1ec5 Ermal Luçi
					$hostname .= ".";
2441 61e047a5 Phil Davis
				}
2442 67ee1ec5 Ermal Luçi
2443
				/* write private key file
2444
				   this is dumb - public and private keys are the same for HMAC-MD5,
2445
				   but nsupdate insists on having both */
2446
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2447 8ec0a8bc jim-p
				$privkey = <<<EOD
2448 a23d7248 Scott Ullrich
Private-key-format: v1.2
2449
Algorithm: 157 (HMAC)
2450 67ee1ec5 Ermal Luçi
Key: {$dnsupdate['keydata']}
2451 a23d7248 Scott Ullrich
2452
EOD;
2453 67ee1ec5 Ermal Luçi
				fwrite($fd, $privkey);
2454
				fclose($fd);
2455
2456
				/* write public key file */
2457
				if ($dnsupdate['keytype'] == "zone") {
2458
					$flags = 257;
2459
					$proto = 3;
2460
				} else if ($dnsupdate['keytype'] == "host") {
2461
					$flags = 513;
2462
					$proto = 3;
2463
				} else if ($dnsupdate['keytype'] == "user") {
2464
					$flags = 0;
2465
					$proto = 2;
2466
				}
2467 c7f44ae0 Scott Ullrich
2468 26586f7a Ermal Lu?i
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.key", "w");
2469 67ee1ec5 Ermal Luçi
				fwrite($fd, "{$keyname} IN KEY {$flags} {$proto} 157 {$dnsupdate['keydata']}\n");
2470
				fclose($fd);
2471
2472
				/* generate update instructions */
2473
				$upinst = "";
2474 61e047a5 Phil Davis
				if (!empty($dnsupdate['server'])) {
2475 67ee1ec5 Ermal Luçi
					$upinst .= "server {$dnsupdate['server']}\n";
2476 61e047a5 Phil Davis
				}
2477 7c9da7be jim-p
2478
				if (file_exists($cacheFile)) {
2479
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2480
				}
2481
				if (file_exists("{$cacheFile}.ipv6")) {
2482
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2483
				}
2484
2485
				// 25 Days
2486
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2487
				$need_update = false;
2488 819a603c jim-p
2489
				conf_mount_rw();
2490 fc1f4960 jim-p
				/* Update IPv4 if we have it. */
2491 ea08d2b2 Robert Nelson
				if (is_ipaddrv4($wanip) && $dnsupdate['recordtype'] != "AAAA") {
2492 7c9da7be jim-p
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2493
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2494
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2495
						$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";
2496
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2497
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2498
						$need_update = true;
2499
					} else {
2500
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2501
					}
2502 61e047a5 Phil Davis
				} else {
2503 7c9da7be jim-p
					@unlink($cacheFile);
2504 61e047a5 Phil Davis
				}
2505 7c9da7be jim-p
2506 fc1f4960 jim-p
				/* Update IPv6 if we have it. */
2507 ea08d2b2 Robert Nelson
				if (is_ipaddrv6($wanipv6) && $dnsupdate['recordtype'] != "A") {
2508 7c9da7be jim-p
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2509
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2510
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2511
						$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";
2512
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2513
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2514
						$need_update = true;
2515
					} else {
2516
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2517
					}
2518 61e047a5 Phil Davis
				} else {
2519 7c9da7be jim-p
					@unlink("{$cacheFile}.ipv6");
2520 61e047a5 Phil Davis
				}
2521 819a603c jim-p
				conf_mount_ro();
2522 67ee1ec5 Ermal Luçi
2523 7c9da7be jim-p
				$upinst .= "\n";	/* mind that trailing newline! */
2524 107e8acc Ovidiu Predescu
2525 7c9da7be jim-p
				if ($need_update) {
2526
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2527
					unset($upinst);
2528
					/* invoke nsupdate */
2529 22cc6582 Renato Botelho
					$cmd = "/usr/local/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2530 61e047a5 Phil Davis
					if (isset($dnsupdate['usetcp'])) {
2531 7c9da7be jim-p
						$cmd .= " -v";
2532 61e047a5 Phil Davis
					}
2533 7c9da7be jim-p
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2534
					mwexec_bg($cmd);
2535
					unset($cmd);
2536
				}
2537 67ee1ec5 Ermal Luçi
			}
2538 a23d7248 Scott Ullrich
		}
2539 7c9da7be jim-p
		if (!empty($notify_text)) {
2540
			notify_all_remote($notify_text);
2541
		}
2542 a23d7248 Scott Ullrich
	}
2543 c7f44ae0 Scott Ullrich
2544 a23d7248 Scott Ullrich
	return 0;
2545 5b237745 Scott Ullrich
}
2546
2547 1071e028 Scott Ullrich
/* configure cron service */
2548
function configure_cron() {
2549
	global $g, $config;
2550 e7d3fc15 Ermal
2551 251ca022 Scott Ullrich
	conf_mount_rw();
2552 1071e028 Scott Ullrich
	/* preserve existing crontab entries */
2553 e7d3fc15 Ermal
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2554 107e8acc Ovidiu Predescu
2555 e7d3fc15 Ermal
	for ($i = 0; $i < count($crontab_contents); $i++) {
2556
		$cron_item =& $crontab_contents[$i];
2557
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2558
			array_splice($crontab_contents, $i - 1);
2559 1071e028 Scott Ullrich
			break;
2560
		}
2561
	}
2562 e7d3fc15 Ermal
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2563 107e8acc Ovidiu Predescu
2564
2565 1071e028 Scott Ullrich
	if (is_array($config['cron']['item'])) {
2566
		$crontab_contents .= "#\n";
2567 f1a44a3a Carlos Eduardo Ramos
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2568 61e047a5 Phil Davis
		$crontab_contents .= "# " .gettext("Created:") . " " . date("F j, Y, g:i a") . "\n";
2569 1071e028 Scott Ullrich
		$crontab_contents .= "#\n";
2570
2571 992f60d0 Renato Botelho
		if (isset($config['system']['proxyurl']) && !empty($config['system']['proxyurl'])) {
2572
			$http_proxy = $config['system']['proxyurl'];
2573 61e047a5 Phil Davis
			if (isset($config['system']['proxyport']) && !empty($config['system']['proxyport'])) {
2574 992f60d0 Renato Botelho
				$http_proxy .= ':' . $config['system']['proxyport'];
2575 61e047a5 Phil Davis
			}
2576 992f60d0 Renato Botelho
			$crontab_contents .= "HTTP_PROXY={$http_proxy}";
2577
		}
2578
2579 1071e028 Scott Ullrich
		foreach ($config['cron']['item'] as $item) {
2580
			$crontab_contents .= "\n{$item['minute']}\t";
2581
			$crontab_contents .= "{$item['hour']}\t";
2582
			$crontab_contents .= "{$item['mday']}\t";
2583
			$crontab_contents .= "{$item['month']}\t";
2584
			$crontab_contents .= "{$item['wday']}\t";
2585
			$crontab_contents .= "{$item['who']}\t";
2586
			$crontab_contents .= "{$item['command']}";
2587
		}
2588 107e8acc Ovidiu Predescu
2589 1071e028 Scott Ullrich
		$crontab_contents .= "\n#\n";
2590 f1a44a3a Carlos Eduardo Ramos
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2591
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2592 1071e028 Scott Ullrich
		$crontab_contents .= "#\n\n";
2593
	}
2594 107e8acc Ovidiu Predescu
2595 1071e028 Scott Ullrich
	/* please maintain the newline at the end of file */
2596
	file_put_contents("/etc/crontab", $crontab_contents);
2597 c2d97111 Ermal
	unset($crontab_contents);
2598 41d507a5 Scott Ullrich
2599 8fe38524 doktornotor
	/* make sure that cron is running and start it if it got killed somehow */
2600
	if (!is_process_running("cron")) {
2601
		exec("cd /tmp && /usr/sbin/cron -s 2>/dev/null");
2602
	} else {
2603 41d507a5 Scott Ullrich
	/* do a HUP kill to force sync changes */
2604 c0020b97 doktornotor
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
2605 8fe38524 doktornotor
	}
2606 41d507a5 Scott Ullrich
2607 6d6bca27 Ermal Lu?i
	conf_mount_ro();
2608 1071e028 Scott Ullrich
}
2609
2610 431484c8 Ryan Wagoner
function upnp_action ($action) {
2611 aa6798c0 Scott Ullrich
	global $g, $config;
2612 61e047a5 Phil Davis
	switch ($action) {
2613 431484c8 Ryan Wagoner
		case "start":
2614 c1ac2424 Ermal
			if (file_exists('/var/etc/miniupnpd.conf')) {
2615
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2616
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2617
			}
2618 431484c8 Ryan Wagoner
			break;
2619
		case "stop":
2620 c1ac2424 Ermal
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2621 61e047a5 Phil Davis
			while ((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0) {
2622 73239086 Seth Mos
				mwexec('killall miniupnpd 2>/dev/null', true);
2623 61e047a5 Phil Davis
			}
2624 431484c8 Ryan Wagoner
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2625
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2626
			break;
2627
		case "restart":
2628
			upnp_action('stop');
2629
			upnp_action('start');
2630
			break;
2631
	}
2632
}
2633
2634 6f20377b Scott Ullrich
function upnp_start() {
2635 dcc897e5 Ermal
	global $config;
2636 0c331f1e Ermal Lu?i
2637 61e047a5 Phil Davis
	if (!isset($config['installedpackages']['miniupnpd']['config'])) {
2638 0c331f1e Ermal Lu?i
		return;
2639 61e047a5 Phil Davis
	}
2640 0c331f1e Ermal Lu?i
2641 61e047a5 Phil Davis
	if ($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2642 54bdff75 Vinicius Coque
		echo gettext("Starting UPnP service... ");
2643 dcc897e5 Ermal
		require_once('/usr/local/pkg/miniupnpd.inc');
2644
		sync_package_miniupnpd();
2645
		echo "done.\n";
2646 6f20377b Scott Ullrich
	}
2647
}
2648
2649 4de8f7ba Phil Davis
function install_cron_job($command, $active = false, $minute = "0", $hour = "*", $monthday = "*", $month = "*", $weekday = "*", $who = "root") {
2650 85405c11 jim-p
	global $config, $g;
2651
2652
	$is_installed = false;
2653 4de8f7ba Phil Davis
	$cron_changed = true;
2654 85405c11 jim-p
2655 61e047a5 Phil Davis
	if (!is_array($config['cron'])) {
2656 c2d97111 Ermal
		$config['cron'] = array();
2657 61e047a5 Phil Davis
	}
2658
	if (!is_array($config['cron']['item'])) {
2659 c2d97111 Ermal
		$config['cron']['item'] = array();
2660 61e047a5 Phil Davis
	}
2661 85405c11 jim-p
2662 4de8f7ba Phil Davis
	$x = 0;
2663 61e047a5 Phil Davis
	foreach ($config['cron']['item'] as $item) {
2664
		if (strstr($item['command'], $command)) {
2665 85405c11 jim-p
			$is_installed = true;
2666
			break;
2667
		}
2668
		$x++;
2669
	}
2670
2671 61e047a5 Phil Davis
	if ($active) {
2672 85405c11 jim-p
		$cron_item = array();
2673
		$cron_item['minute'] = $minute;
2674
		$cron_item['hour'] = $hour;
2675
		$cron_item['mday'] = $monthday;
2676
		$cron_item['month'] = $month;
2677
		$cron_item['wday'] = $weekday;
2678
		$cron_item['who'] = $who;
2679
		$cron_item['command'] = $command;
2680 61e047a5 Phil Davis
		if (!$is_installed) {
2681 85405c11 jim-p
			$config['cron']['item'][] = $cron_item;
2682 f1a44a3a Carlos Eduardo Ramos
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2683 85405c11 jim-p
		} else {
2684 4de8f7ba Phil Davis
			if ($config['cron']['item'][$x] == $cron_item) {
2685
				$cron_changed = false;
2686
				log_error(sprintf(gettext("Checked cron job for %s, no change needed"), $command));
2687
			} else {
2688
				$config['cron']['item'][$x] = $cron_item;
2689
				write_config(sprintf(gettext("Updated cron job for %s"), $command));
2690
			}
2691 85405c11 jim-p
		}
2692
	} else {
2693 61e047a5 Phil Davis
		if ($is_installed == true) {
2694 85405c11 jim-p
			unset($config['cron']['item'][$x]);
2695 149ed85e bcyrill
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2696 85405c11 jim-p
		}
2697
	}
2698 994a0644 Phil Davis
2699 61e047a5 Phil Davis
	if ($cron_changed) {
2700 994a0644 Phil Davis
		configure_cron();
2701 61e047a5 Phil Davis
	}
2702 85405c11 jim-p
}
2703
2704 693833cb Seth Mos
?>