Project

General

Profile

Download (82.6 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 f3ee8545 Rene Schuster
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 spdns spdns-v6 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,SPDNS,SPDNS (v6),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 1ebd1b10 Chris Buechler
	mwexec_bg("/usr/local/sbin/igmpproxy -v {$g['tmp_path']}/igmpproxy.conf");
1587 61e047a5 Phil Davis
	log_error(gettext("Started IGMP proxy service."));
1588 41997fbb Ermal Luci
1589 61e047a5 Phil Davis
	return 0;
1590 41997fbb Ermal Luci
}
1591
1592 5b237745 Scott Ullrich
function services_dhcrelay_configure() {
1593 f19d3b7a Scott Ullrich
	global $config, $g;
1594 6fa9f38c Renato Botelho
1595 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1596 acd910bf Scott Ullrich
		$mt = microtime();
1597 f19d3b7a Scott Ullrich
		echo "services_dhcrelay_configure() being called $mt\n";
1598 acd910bf Scott Ullrich
	}
1599 a25183c5 Scott Ullrich
1600 5b237745 Scott Ullrich
	/* kill any running dhcrelay */
1601
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
1602 a25183c5 Scott Ullrich
1603 2f06cc3f Ermal
	$dhcrelaycfg =& $config['dhcrelay'];
1604 a25183c5 Scott Ullrich
1605 5b237745 Scott Ullrich
	/* DHCPRelay enabled on any interfaces? */
1606 61e047a5 Phil Davis
	if (!isset($dhcrelaycfg['enable'])) {
1607 5b237745 Scott Ullrich
		return 0;
1608 61e047a5 Phil Davis
	}
1609 a25183c5 Scott Ullrich
1610 61e047a5 Phil Davis
	if (platform_booting()) {
1611 f1a44a3a Carlos Eduardo Ramos
		echo gettext("Starting DHCP relay service...");
1612 61e047a5 Phil Davis
	} else {
1613 5b237745 Scott Ullrich
		sleep(1);
1614 61e047a5 Phil Davis
	}
1615 a25183c5 Scott Ullrich
1616 2f06cc3f Ermal
	$iflist = get_configured_interface_list();
1617 a25183c5 Scott Ullrich
1618 2f06cc3f Ermal
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1619
	foreach ($dhcifaces as $dhcrelayif) {
1620
		if (!isset($iflist[$dhcrelayif]) ||
1621 61e047a5 Phil Davis
		    link_interface_to_bridge($dhcrelayif)) {
1622 5b237745 Scott Ullrich
			continue;
1623 61e047a5 Phil Davis
		}
1624 a25183c5 Scott Ullrich
1625 61e047a5 Phil Davis
		if (is_ipaddr(get_interface_ip($dhcrelayif))) {
1626 2f06cc3f Ermal
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1627 61e047a5 Phil Davis
		}
1628 5b237745 Scott Ullrich
	}
1629
1630 d7827421 Renato Botelho
	/*
1631
	 * In order for the relay to work, it needs to be active
1632
	 * on the interface in which the destination server sits.
1633
	 */
1634 2f06cc3f Ermal
	$srvips = explode(",", $dhcrelaycfg['server']);
1635 c58879a9 Ermal LUÇI
	if (!is_array($srvips)) {
1636 578ae21f Renato Botelho
		log_error("No destination IP has been configured!");
1637 c58879a9 Ermal LUÇI
		return;
1638 4de8f7ba Phil Davis
	}
1639 a25183c5 Scott Ullrich
1640 d7827421 Renato Botelho
	foreach ($srvips as $srcidx => $srvip) {
1641
		unset($destif);
1642
		foreach ($iflist as $ifname) {
1643
			$subnet = get_interface_ip($ifname);
1644
			if (!is_ipaddr($subnet)) {
1645
				continue;
1646
			}
1647
			$subnet .= "/" . get_interface_subnet($ifname);
1648
			if (ip_in_subnet($srvip, $subnet)) {
1649
				$destif = get_real_interface($ifname);
1650
				break;
1651
			}
1652
		}
1653
		if (!isset($destif)) {
1654
			foreach (get_staticroutes() as $rtent) {
1655
				if (ip_in_subnet($srvip, $rtent['network'])) {
1656
					$a_gateways = return_gateways_array(true);
1657
					$destif = $a_gateways[$rtent['gateway']]['interface'];
1658
					break;
1659
				}
1660
			}
1661
		}
1662
1663
		if (!isset($destif)) {
1664
			/* Create a array from the existing route table */
1665
			exec("/usr/bin/netstat -rnWf inet", $route_str);
1666
			array_shift($route_str);
1667
			array_shift($route_str);
1668
			array_shift($route_str);
1669
			array_shift($route_str);
1670
			$route_arr = array();
1671
			foreach ($route_str as $routeline) {
1672
				$items = preg_split("/[ ]+/i", $routeline);
1673
				if (is_subnetv4($items[0])) {
1674
					$subnet = $items[0];
1675
				} elseif (is_ipaddrv4($items[0])) {
1676
					$subnet = "{$items[0]}/32";
1677
				} else {
1678
					// Not a subnet or IP address, skip to the next line.
1679
					continue;
1680
				}
1681
				if (ip_in_subnet($srvip, $subnet)) {
1682
					$destif = trim($items[6]);
1683
					break;
1684
				}
1685
			}
1686
		}
1687
1688
		if (!isset($destif)) {
1689
			if (is_array($config['gateways']['gateway_item'])) {
1690
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1691
					if (isset($gateway['defaultgw'])) {
1692
						$destif = get_real_interface($gateway['interface']);
1693
						break;
1694
					}
1695
				}
1696
			} else {
1697
				$destif = get_real_interface("wan");
1698
			}
1699
		}
1700
1701
		if (!empty($destif)) {
1702
			$dhcrelayifs[] = $destif;
1703
		}
1704
	}
1705 5b237745 Scott Ullrich
	$dhcrelayifs = array_unique($dhcrelayifs);
1706
1707
	/* fire up dhcrelay */
1708 24997966 Ermal
	if (empty($dhcrelayifs)) {
1709 5a171fb7 Warren Baker
		log_error("No suitable interface found for running dhcrelay!");
1710 24997966 Ermal
		return; /* XXX */
1711
	}
1712
1713 4de8f7ba Phil Davis
	$cmd = "/usr/local/sbin/dhcrelay -i " . implode(" -i ", $dhcrelayifs);
1714 5b237745 Scott Ullrich
1715 61e047a5 Phil Davis
	if (isset($dhcrelaycfg['agentoption'])) {
1716 4de8f7ba Phil Davis
		$cmd .= " -a -m replace";
1717 61e047a5 Phil Davis
	}
1718 5b237745 Scott Ullrich
1719 2f06cc3f Ermal
	$cmd .= " " . implode(" ", $srvips);
1720 5b237745 Scott Ullrich
	mwexec($cmd);
1721 928d4416 Ermal
	unset($cmd);
1722 a25183c5 Scott Ullrich
1723 5b237745 Scott Ullrich
	return 0;
1724
}
1725
1726 b7a15cf8 Seth Mos
function services_dhcrelay6_configure() {
1727
	global $config, $g;
1728 6fa9f38c Renato Botelho
1729 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1730 b7a15cf8 Seth Mos
		$mt = microtime();
1731 874f099a Phil Davis
		echo "services_dhcrelay6_configure() being called $mt\n";
1732 b7a15cf8 Seth Mos
	}
1733
1734
	/* kill any running dhcrelay */
1735
	killbypid("{$g['varrun_path']}/dhcrelay6.pid");
1736
1737
	$dhcrelaycfg =& $config['dhcrelay6'];
1738
1739
	/* DHCPv6 Relay enabled on any interfaces? */
1740 61e047a5 Phil Davis
	if (!isset($dhcrelaycfg['enable'])) {
1741 b7a15cf8 Seth Mos
		return 0;
1742 61e047a5 Phil Davis
	}
1743 b7a15cf8 Seth Mos
1744 61e047a5 Phil Davis
	if (platform_booting()) {
1745 b7a15cf8 Seth Mos
		echo gettext("Starting DHCPv6 relay service...");
1746 61e047a5 Phil Davis
	} else {
1747 b7a15cf8 Seth Mos
		sleep(1);
1748 61e047a5 Phil Davis
	}
1749 b7a15cf8 Seth Mos
1750
	$iflist = get_configured_interface_list();
1751
1752
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
1753
	foreach ($dhcifaces as $dhcrelayif) {
1754
		if (!isset($iflist[$dhcrelayif]) ||
1755 086cf944 Phil Davis
		    link_interface_to_bridge($dhcrelayif)) {
1756 b7a15cf8 Seth Mos
			continue;
1757 086cf944 Phil Davis
		}
1758 b7a15cf8 Seth Mos
1759 61e047a5 Phil Davis
		if (is_ipaddrv6(get_interface_ipv6($dhcrelayif))) {
1760 b7a15cf8 Seth Mos
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
1761 61e047a5 Phil Davis
		}
1762 b7a15cf8 Seth Mos
	}
1763 69dd7088 Michael Tharp
	$dhcrelayifs = array_unique($dhcrelayifs);
1764 b7a15cf8 Seth Mos
1765 d7827421 Renato Botelho
	/*
1766
	 * In order for the relay to work, it needs to be active
1767
	 * on the interface in which the destination server sits.
1768
	 */
1769 b7a15cf8 Seth Mos
	$srvips = explode(",", $dhcrelaycfg['server']);
1770 d7827421 Renato Botelho
	$srvifaces = array();
1771
	foreach ($srvips as $srcidx => $srvip) {
1772
		unset($destif);
1773
		foreach ($iflist as $ifname) {
1774
			$subnet = get_interface_ipv6($ifname);
1775
			if (!is_ipaddrv6($subnet)) {
1776
				continue;
1777
			}
1778
			$subnet .= "/" . get_interface_subnetv6($ifname);
1779
			if (ip_in_subnet($srvip, $subnet)) {
1780
				$destif = get_real_interface($ifname);
1781
				break;
1782
			}
1783
		}
1784
		if (!isset($destif)) {
1785
			if (is_array($config['staticroutes']['route'])) {
1786
				foreach ($config['staticroutes']['route'] as $rtent) {
1787
					if (ip_in_subnet($srvip, $rtent['network'])) {
1788
						$a_gateways = return_gateways_array(true);
1789
						$destif = $a_gateways[$rtent['gateway']]['interface'];
1790
						break;
1791
					}
1792
				}
1793
			}
1794
		}
1795
1796
		if (!isset($destif)) {
1797
			/* Create a array from the existing route table */
1798
			exec("/usr/bin/netstat -rnWf inet6", $route_str);
1799
			array_shift($route_str);
1800
			array_shift($route_str);
1801
			array_shift($route_str);
1802
			array_shift($route_str);
1803
			$route_arr = array();
1804
			foreach ($route_str as $routeline) {
1805
				$items = preg_split("/[ ]+/i", $routeline);
1806
				if (ip_in_subnet($srvip, $items[0])) {
1807
					$destif = trim($items[6]);
1808
					break;
1809
				}
1810
			}
1811
		}
1812
1813
		if (!isset($destif)) {
1814
			if (is_array($config['gateways']['gateway_item'])) {
1815
				foreach ($config['gateways']['gateway_item'] as $gateway) {
1816
					if (isset($gateway['defaultgw'])) {
1817
						$destif = get_real_interface($gateway['interface']);
1818
						break;
1819
					}
1820
				}
1821
			} else {
1822
				$destif = get_real_interface("wan");
1823
			}
1824
		}
1825
1826
		if (!empty($destif)) {
1827
			$srvifaces[] = "{$srvip}%{$destif}";
1828
		}
1829 b7a15cf8 Seth Mos
	}
1830
1831
	/* fire up dhcrelay */
1832 61e047a5 Phil Davis
	if (empty($dhcrelayifs) || empty($srvifaces)) {
1833 b7a15cf8 Seth Mos
		log_error("No suitable interface found for running dhcrelay -6!");
1834
		return; /* XXX */
1835
	}
1836
1837 54a9d71d Phil Davis
	$cmd = "/usr/local/sbin/dhcrelay -6 -pf \"{$g['varrun_path']}/dhcrelay6.pid\"";
1838 69dd7088 Michael Tharp
	foreach ($dhcrelayifs as $dhcrelayif) {
1839
		$cmd .= " -l {$dhcrelayif}";
1840
	}
1841
	foreach ($srvifaces as $srviface) {
1842
		$cmd .= " -u \"{$srviface}\"";
1843
	}
1844 b7a15cf8 Seth Mos
	mwexec($cmd);
1845 928d4416 Ermal
	unset($cmd);
1846 b7a15cf8 Seth Mos
1847
	return 0;
1848
}
1849
1850 181d7c95 Ermal Luçi
function services_dyndns_configure_client($conf) {
1851
1852 61e047a5 Phil Davis
	if (!isset($conf['enable'])) {
1853 65996399 Ermal
		return;
1854 61e047a5 Phil Davis
	}
1855 d2946062 Ermal
1856 181d7c95 Ermal Luçi
	/* load up the dyndns.class */
1857
	require_once("dyndns.class");
1858
1859
	$dns = new updatedns($dnsService = $conf['type'],
1860
		$dnsHost = $conf['host'],
1861
		$dnsUser = $conf['username'],
1862
		$dnsPass = $conf['password'],
1863 3aa55bbe Phil Davis
		$dnsWildcard = $conf['wildcard'],
1864 107e8acc Ovidiu Predescu
		$dnsMX = $conf['mx'],
1865 f3b2b2a4 Yehuda Katz
		$dnsIf = "{$conf['interface']}",
1866
		$dnsBackMX = NULL,
1867
		$dnsServer = NULL,
1868
		$dnsPort = NULL,
1869 37f3e704 Matt Corallo
		$dnsUpdateURL = "{$conf['updateurl']}",
1870 cd132e86 Edson Brandi
		$forceUpdate = $conf['force'],
1871 4de8f7ba Phil Davis
		$dnsZoneID = $conf['zoneid'],
1872
		$dnsTTL = $conf['ttl'],
1873 37f3e704 Matt Corallo
		$dnsResultMatch = "{$conf['resultmatch']}",
1874
		$dnsRequestIf = "{$conf['requestif']}",
1875 1e503870 Phil Davis
		$dnsID = "{$conf['id']}",
1876 aa79f351 Sebastian Chrostek
		$dnsVerboseLog = $conf['verboselog'],
1877
		$curlIpresolveV4 = $conf['curl_ipresolve_v4'],
1878
		$curlSslVerifypeer = $conf['curl_ssl_verifypeer']);
1879 181d7c95 Ermal Luçi
}
1880
1881 0be93267 Ermal Lu?i
function services_dyndns_configure($int = "") {
1882 f19d3b7a Scott Ullrich
	global $config, $g;
1883 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1884 59a63553 Scott Ullrich
		$mt = microtime();
1885
		echo "services_dyndns_configure() being called $mt\n";
1886
	}
1887
1888 67ee1ec5 Ermal Luçi
	$dyndnscfg = $config['dyndnses']['dyndns'];
1889 017817c2 smos
	$gwgroups = return_gateway_groups_array();
1890 67ee1ec5 Ermal Luçi
	if (is_array($dyndnscfg)) {
1891 61e047a5 Phil Davis
		if (platform_booting()) {
1892 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting DynDNS clients...");
1893 61e047a5 Phil Davis
		}
1894 181d7c95 Ermal Luçi
1895 67ee1ec5 Ermal Luçi
		foreach ($dyndnscfg as $dyndns) {
1896 786ff5eb phildd
			if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
1897 1e503870 Phil Davis
				$dyndns['verboselog'] = isset($dyndns['verboselog']);
1898 d9bdc020 Sebastian Chrostek
				$dyndns['curl_ipresolve_v4'] = isset($dyndns['curl_ipresolve_v4']);
1899
				$dyndns['curl_ssl_verifypeer'] = isset($dyndns['curl_ssl_verifypeer']);
1900 768eb89c smos
				services_dyndns_configure_client($dyndns);
1901
				sleep(1);
1902
			}
1903 67ee1ec5 Ermal Luçi
		}
1904 59a63553 Scott Ullrich
1905 61e047a5 Phil Davis
		if (platform_booting()) {
1906 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
1907 61e047a5 Phil Davis
		}
1908 59a63553 Scott Ullrich
	}
1909
1910
	return 0;
1911
}
1912
1913 0e3aeb6b Phil Davis
function dyndnsCheckIP($int) {
1914 873e4b28 phildd
	global $config;
1915 0e3aeb6b Phil Davis
	$ip_address = get_interface_ip($int);
1916
	if (is_private_ip($ip_address)) {
1917 873e4b28 phildd
		$gateways_status = return_gateways_status(true);
1918
		// If the gateway for this interface is down, then the external check cannot work.
1919
		// Avoid the long wait for the external check to timeout.
1920 61e047a5 Phil Davis
		if (stristr($gateways_status[$config['interfaces'][$int]['gateway']]['status'], "down")) {
1921 873e4b28 phildd
			return "down";
1922 61e047a5 Phil Davis
		}
1923 5244c510 Florian Asche
		$hosttocheck = "http://checkip.dyndns.org";
1924
		$ip_ch = curl_init($hosttocheck);
1925 0e3aeb6b Phil Davis
		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
1926
		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
1927 e1eee3d2 Renato Botelho
		curl_setopt($ip_ch, CURLOPT_INTERFACE, 'host!' . $ip_address);
1928 181386d6 Florian Asche
		curl_setopt($ip_ch, CURLOPT_CONNECTTIMEOUT, '30');
1929
		curl_setopt($ip_ch, CURLOPT_TIMEOUT, 120);
1930 3c6f29c0 Florian Asche
		curl_setopt($ip_ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1931 0e3aeb6b Phil Davis
		$ip_result_page = curl_exec($ip_ch);
1932
		curl_close($ip_ch);
1933
		$ip_result_decoded = urldecode($ip_result_page);
1934
		preg_match('=Current IP Address: (.*)</body>=siU', $ip_result_decoded, $matches);
1935
		$ip_address = trim($matches[1]);
1936
	}
1937
	return $ip_address;
1938
}
1939
1940 5b237745 Scott Ullrich
function services_dnsmasq_configure() {
1941 f19d3b7a Scott Ullrich
	global $config, $g;
1942 6a01ea44 Bill Marquette
	$return = 0;
1943 107e8acc Ovidiu Predescu
1944 683992fc stilez
	// hard coded args: will be removed to avoid duplication if specified in custom_options
1945
	$standard_args = array(
1946
		"dns-forward-max" => "--dns-forward-max=5000",
1947
		"cache-size" => "--cache-size=10000",
1948
		"local-ttl" => "--local-ttl=1"
1949
	);
1950
1951
1952 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
1953 acd910bf Scott Ullrich
		$mt = microtime();
1954 f19d3b7a Scott Ullrich
		echo "services_dnsmasq_configure() being called $mt\n";
1955 acd910bf Scott Ullrich
	}
1956
1957 5b237745 Scott Ullrich
	/* kill any running dnsmasq */
1958 61e047a5 Phil Davis
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid")) {
1959 d224df18 Ermal
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
1960 61e047a5 Phil Davis
	}
1961 5b237745 Scott Ullrich
1962
	if (isset($config['dnsmasq']['enable'])) {
1963 a25183c5 Scott Ullrich
1964 61e047a5 Phil Davis
		if (platform_booting()) {
1965 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting DNS forwarder...");
1966 61e047a5 Phil Davis
		} else {
1967 5b237745 Scott Ullrich
			sleep(1);
1968 61e047a5 Phil Davis
		}
1969 5b237745 Scott Ullrich
1970 61e047a5 Phil Davis
		/* generate hosts file */
1971 4de8f7ba Phil Davis
		if (system_hosts_generate() != 0) {
1972 61e047a5 Phil Davis
			$return = 1;
1973
		}
1974 cbc6a13f Chris Buechler
1975 5b237745 Scott Ullrich
		$args = "";
1976 a25183c5 Scott Ullrich
1977 0261381a Ermal
		if (isset($config['dnsmasq']['regdhcp'])) {
1978
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
1979
		}
1980 107e8acc Ovidiu Predescu
1981 e6c49e3d jim-p
		/* Setup listen port, if non-default */
1982 61e047a5 Phil Davis
		if (is_port($config['dnsmasq']['port'])) {
1983 e6c49e3d jim-p
			$args .= " --port={$config['dnsmasq']['port']} ";
1984 61e047a5 Phil Davis
		}
1985 e6c49e3d jim-p
1986 b4323f39 jim-p
		$listen_addresses = "";
1987 61e047a5 Phil Davis
		if (isset($config['dnsmasq']['interface'])) {
1988 b4323f39 jim-p
			$interfaces = explode(",", $config['dnsmasq']['interface']);
1989
			foreach ($interfaces as $interface) {
1990 55909a9a Ermal
				if (is_ipaddrv4($interface)) {
1991 b4323f39 jim-p
					$listen_addresses .= " --listen-address={$interface} ";
1992 55909a9a Ermal
				} else if (is_ipaddrv6($interface)) {
1993
					/*
1994
					 * XXX: Since dnsmasq does not support link-local address
1995
					 * with scope specified. These checks are being done.
1996
					 */
1997
					if (is_linklocal($interface) && strstr($interface, "%")) {
1998
						$tmpaddrll6 = explode("%", $interface);
1999
						$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
2000 61e047a5 Phil Davis
					} else {
2001 55909a9a Ermal
						$listen_addresses .= " --listen-address={$interface} ";
2002 61e047a5 Phil Davis
					}
2003 9e7e2c94 Chris Buechler
				} else if (strstr($interface, "_vip")) {
2004
					$laddr = get_configured_carp_interface_list($interface);
2005 61e047a5 Phil Davis
					if (is_ipaddr($laddr)) {
2006 9e7e2c94 Chris Buechler
						$listen_addresses .= " --listen-address={$laddr} ";
2007 61e047a5 Phil Davis
					}
2008 b4323f39 jim-p
				} else {
2009
					$if = get_real_interface($interface);
2010
					if (does_interface_exist($if)) {
2011 89f171b0 Ermal LUÇI
						$laddr = get_interface_ip($interface);
2012 61e047a5 Phil Davis
						if (is_ipaddrv4($laddr)) {
2013 b4323f39 jim-p
							$listen_addresses .= " --listen-address={$laddr} ";
2014 61e047a5 Phil Davis
						}
2015 89f171b0 Ermal LUÇI
						$laddr6 = get_interface_ipv6($interface);
2016 b77d19c7 Ermal
						if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
2017
							/*
2018
							 * XXX: Since dnsmasq does not support link-local address
2019
							 * with scope specified. These checks are being done.
2020
							 */
2021
							if (is_linklocal($laddr6) && strstr($laddr6, "%")) {
2022
								$tmpaddrll6 = explode("%", $laddr6);
2023
								$listen_addresses .= " --listen-address={$tmpaddrll6[0]} ";
2024 61e047a5 Phil Davis
							} else {
2025 b77d19c7 Ermal
								$listen_addresses .= " --listen-address={$laddr6} ";
2026 61e047a5 Phil Davis
							}
2027 b77d19c7 Ermal
						}
2028 b4323f39 jim-p
					}
2029
				}
2030
			}
2031
			if (!empty($listen_addresses)) {
2032
				$args .= " {$listen_addresses} ";
2033 61e047a5 Phil Davis
				if (isset($config['dnsmasq']['strictbind'])) {
2034 b4323f39 jim-p
					$args .= " --bind-interfaces ";
2035 61e047a5 Phil Davis
				}
2036 b4323f39 jim-p
			}
2037
		}
2038
2039 fc27d3f4 Phil Davis
		/* If selected, then first forward reverse lookups for private IPv4 addresses to nowhere. */
2040 153613e3 Phil Davis
		/* Only make entries for reverse domains that do not have a matching domain override. */
2041 0a7985ba Phil Davis
		if (isset($config['dnsmasq']['no_private_reverse'])) {
2042
			/* Note: Carrier Grade NAT (CGN) addresses 100.64.0.0/10 are intentionally not here. */
2043
			/* End-users should not be aware of CGN addresses, so reverse lookups for these should not happen. */
2044
			/* Just the pfSense WAN might get a CGN address from an ISP. */
2045 153613e3 Phil Davis
2046
			// Build an array of domain overrides to help in checking for matches.
2047
			$override_a = array();
2048
			if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2049
				foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2050
					$override_a[$override['domain']] = "y";
2051
				}
2052 0a7985ba Phil Davis
			}
2053 153613e3 Phil Davis
2054
			// Build an array of the private reverse lookup domain names
2055
			$reverse_domain_a = array("10.in-addr.arpa", "168.192.in-addr.arpa");
2056
			// Unfortunately the 172.16.0.0/12 range does not map nicely to the in-addr.arpa scheme.
2057 61e047a5 Phil Davis
			for ($subnet_num = 16; $subnet_num < 32; $subnet_num++) {
2058 153613e3 Phil Davis
				$reverse_domain_a[] = "$subnet_num.172.in-addr.arpa";
2059
			}
2060
2061
			// Set the --server parameter to nowhere for each reverse domain name that was not specifically specified in a domain override.
2062 61e047a5 Phil Davis
			foreach ($reverse_domain_a as $reverse_domain) {
2063
				if (!isset($override_a[$reverse_domain])) {
2064 153613e3 Phil Davis
					$args .= " --server=/$reverse_domain/ ";
2065 61e047a5 Phil Davis
				}
2066 0a7985ba Phil Davis
			}
2067 153613e3 Phil Davis
			unset($override_a);
2068
			unset($reverse_domain_a);
2069 0a7985ba Phil Davis
		}
2070
2071 fc27d3f4 Phil Davis
		/* Setup forwarded domains */
2072
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2073 61e047a5 Phil Davis
			foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2074
				if ($override['ip'] == "!") {
2075 fc27d3f4 Phil Davis
					$override[ip] = "";
2076 61e047a5 Phil Davis
				}
2077 fc27d3f4 Phil Davis
				$args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
2078
			}
2079
		}
2080
2081 2c46f11f Scott Ullrich
		/* Allow DNS Rebind for forwarded domains */
2082 29721fe6 Scott Ullrich
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
2083 61e047a5 Phil Davis
			if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
2084
				foreach ($config['dnsmasq']['domainoverrides'] as $override) {
2085 30d20e7d Scott Ullrich
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
2086
				}
2087 2c46f11f Scott Ullrich
			}
2088
		}
2089 91adc5c1 Scott Ullrich
2090 61e047a5 Phil Davis
		if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
2091 30d20e7d Scott Ullrich
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
2092 61e047a5 Phil Davis
		}
2093 30d20e7d Scott Ullrich
2094 96ea7162 N0YB
		if (isset($config['dnsmasq']['strict_order'])) {
2095
			$args .= " --strict-order ";
2096
		}
2097
2098
		if (isset($config['dnsmasq']['domain_needed'])) {
2099
			$args .= " --domain-needed ";
2100
		}
2101
2102 61e047a5 Phil Davis
		if ($config['dnsmasq']['custom_options']) {
2103 683992fc stilez
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c) {
2104 071f6059 jim-p
				$args .= " " . escapeshellarg("--{$c}");
2105 683992fc stilez
				$p = explode('=', $c);
2106 61e047a5 Phil Davis
				if (array_key_exists($p[0], $standard_args)) {
2107 683992fc stilez
					unset($standard_args[$p[0]]);
2108 61e047a5 Phil Davis
				}
2109 683992fc stilez
			}
2110 61e047a5 Phil Davis
		}
2111 41567e06 jim-p
		$args .= ' ' . implode(' ', array_values($standard_args));
2112 8f9bffbc Andrew Thompson
2113 5b237745 Scott Ullrich
		/* run dnsmasq */
2114 683992fc stilez
		$cmd = "/usr/local/sbin/dnsmasq --all-servers {$dns_rebind} {$args}";
2115 b4323f39 jim-p
		//log_error("dnsmasq command: {$cmd}");
2116
		mwexec_bg($cmd);
2117 928d4416 Ermal
		unset($args);
2118 5b237745 Scott Ullrich
2119 61e047a5 Phil Davis
		system_dhcpleases_configure();
2120 0a5a8df9 Warren Baker
2121 61e047a5 Phil Davis
		if (platform_booting()) {
2122 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
2123 61e047a5 Phil Davis
		}
2124 5b237745 Scott Ullrich
	}
2125 a25183c5 Scott Ullrich
2126 285ef132 Ermal LUÇI
	if (!platform_booting()) {
2127 4de8f7ba Phil Davis
		if (services_dhcpd_configure() != 0) {
2128 6a01ea44 Bill Marquette
			$return = 1;
2129 61e047a5 Phil Davis
		}
2130 5b237745 Scott Ullrich
	}
2131
2132 6a01ea44 Bill Marquette
	return $return;
2133 5b237745 Scott Ullrich
}
2134
2135 175dc861 Warren Baker
function services_unbound_configure() {
2136
	global $config, $g;
2137
	$return = 0;
2138
2139
	if (isset($config['system']['developerspew'])) {
2140
		$mt = microtime();
2141
		echo "services_unbound_configure() being called $mt\n";
2142
	}
2143
2144
	// kill any running Unbound instance
2145 61e047a5 Phil Davis
	if (file_exists("{$g['varrun_path']}/unbound.pid")) {
2146 175dc861 Warren Baker
		sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM");
2147 61e047a5 Phil Davis
	}
2148 175dc861 Warren Baker
2149
	if (isset($config['unbound']['enable'])) {
2150 61e047a5 Phil Davis
		if (platform_booting()) {
2151 5bb1c495 Warren Baker
			echo gettext("Starting DNS Resolver...");
2152 61e047a5 Phil Davis
		} else {
2153 175dc861 Warren Baker
			sleep(1);
2154 61e047a5 Phil Davis
		}
2155 175dc861 Warren Baker
2156 b3c6783f Renato Botelho
		/* generate hosts file */
2157 4de8f7ba Phil Davis
		if (system_hosts_generate() != 0) {
2158 b3c6783f Renato Botelho
			$return = 1;
2159 61e047a5 Phil Davis
		}
2160 b3c6783f Renato Botelho
2161 175dc861 Warren Baker
		require_once('/etc/inc/unbound.inc');
2162
		sync_unbound_service();
2163 61e047a5 Phil Davis
		if (platform_booting()) {
2164 175dc861 Warren Baker
			echo gettext("done.") . "\n";
2165 61e047a5 Phil Davis
		}
2166 0a5a8df9 Warren Baker
2167 61e047a5 Phil Davis
		system_dhcpleases_configure();
2168 175dc861 Warren Baker
	}
2169
2170 285ef132 Ermal LUÇI
	if (!platform_booting()) {
2171 4de8f7ba Phil Davis
		if (services_dhcpd_configure() != 0) {
2172 175dc861 Warren Baker
			$return = 1;
2173 61e047a5 Phil Davis
		}
2174 175dc861 Warren Baker
	}
2175
2176
	return $return;
2177
}
2178
2179 5b237745 Scott Ullrich
function services_snmpd_configure() {
2180 f19d3b7a Scott Ullrich
	global $config, $g;
2181 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
2182 acd910bf Scott Ullrich
		$mt = microtime();
2183 f19d3b7a Scott Ullrich
		echo "services_snmpd_configure() being called $mt\n";
2184
	}
2185 5b237745 Scott Ullrich
2186
	/* kill any running snmpd */
2187
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
2188 dd18038e Ermal
	sleep(2);
2189 61e047a5 Phil Davis
	if (is_process_running("bsnmpd")) {
2190 a976fa82 Scott Ullrich
		mwexec("/usr/bin/killall bsnmpd", true);
2191 61e047a5 Phil Davis
	}
2192 5b237745 Scott Ullrich
2193
	if (isset($config['snmpd']['enable'])) {
2194 a25183c5 Scott Ullrich
2195 61e047a5 Phil Davis
		if (platform_booting()) {
2196 f1a44a3a Carlos Eduardo Ramos
			echo gettext("Starting SNMP daemon... ");
2197 61e047a5 Phil Davis
		}
2198 5b237745 Scott Ullrich
2199
		/* generate snmpd.conf */
2200
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
2201
		if (!$fd) {
2202 4de8f7ba Phil Davis
			printf(gettext("Error: cannot open snmpd.conf in services_snmpd_configure().%s"), "\n");
2203 5b237745 Scott Ullrich
			return 1;
2204
		}
2205 a25183c5 Scott Ullrich
2206 142da8f7 John Fleming
2207 5b237745 Scott Ullrich
		$snmpdconf = <<<EOD
2208 d47a8a69 Scott Ullrich
location := "{$config['snmpd']['syslocation']}"
2209
contact := "{$config['snmpd']['syscontact']}"
2210
read := "{$config['snmpd']['rocommunity']}"
2211 142da8f7 John Fleming
2212
EOD;
2213
2214
/* No docs on what write strings do there for disable for now.
2215 61e047a5 Phil Davis
		if (isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])) {
2216
			$snmpdconf .= <<<EOD
2217 142da8f7 John Fleming
# write string
2218
write := "{$config['snmpd']['rwcommunity']}"
2219
2220
EOD;
2221
		}
2222
*/
2223
2224
2225 61e047a5 Phil Davis
		if (isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])) {
2226
			$snmpdconf .= <<<EOD
2227 142da8f7 John Fleming
# SNMP Trap support.
2228 dbeeb008 John Fleming
traphost := {$config['snmpd']['trapserver']}
2229
trapport := {$config['snmpd']['trapserverport']}
2230
trap := "{$config['snmpd']['trapstring']}"
2231 142da8f7 John Fleming
2232
2233
EOD;
2234
		}
2235
2236 dadf8ebb jim-p
		$platform = trim(file_get_contents('/etc/platform'));
2237 61e047a5 Phil Davis
		if (($platform == "pfSense") && ($g['product_name'] != "pfSense")) {
2238 e52cb3a4 jim-p
			$platform = $g['product_name'];
2239 61e047a5 Phil Davis
		}
2240 dadf8ebb jim-p
		$sysDescr = "{$g['product_name']} " . php_uname("n") .
2241 5779ade6 Renato Botelho
			" {$g['product_version']} {$platform} " . php_uname("s") .
2242 dadf8ebb jim-p
			" " . php_uname("r") . " " . php_uname("m");
2243 142da8f7 John Fleming
2244
		$snmpdconf .= <<<EOD
2245 d47a8a69 Scott Ullrich
system := 1     # pfSense
2246
%snmpd
2247 dadf8ebb jim-p
sysDescr			= "{$sysDescr}"
2248 d47a8a69 Scott Ullrich
begemotSnmpdDebugDumpPdus       = 2
2249
begemotSnmpdDebugSyslogPri      = 7
2250
begemotSnmpdCommunityString.0.1 = $(read)
2251 142da8f7 John Fleming
2252
EOD;
2253
2254
/* No docs on what write strings do there for disable for now.
2255 61e047a5 Phil Davis
		if (isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])) {
2256
			$snmpdconf .= <<<EOD
2257 142da8f7 John Fleming
begemotSnmpdCommunityString.0.2 = $(write)
2258
2259
EOD;
2260
		}
2261
*/
2262
2263 c7f44ae0 Scott Ullrich
2264 61e047a5 Phil Davis
		if (isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])) {
2265
			$snmpdconf .= <<<EOD
2266 142da8f7 John Fleming
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
2267
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
2268
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
2269
2270
EOD;
2271
		}
2272
2273
2274
		$snmpdconf .= <<<EOD
2275 d47a8a69 Scott Ullrich
begemotSnmpdCommunityDisable    = 1
2276 03ba7a0f John Fleming
2277
EOD;
2278
2279 c82b2c3f jim-p
		$bind_to_ip = "0.0.0.0";
2280 61e047a5 Phil Davis
		if (isset($config['snmpd']['bindip'])) {
2281 c82b2c3f jim-p
			if (is_ipaddr($config['snmpd']['bindip'])) {
2282
				$bind_to_ip = $config['snmpd']['bindip'];
2283
			} else {
2284
				$if = get_real_interface($config['snmpd']['bindip']);
2285 61e047a5 Phil Davis
				if (does_interface_exist($if)) {
2286 89f171b0 Ermal LUÇI
					$bind_to_ip = get_interface_ip($config['snmpd']['bindip']);
2287 61e047a5 Phil Davis
				}
2288 c82b2c3f jim-p
			}
2289 7cbad422 Scott Ullrich
		}
2290
2291 61e047a5 Phil Davis
		if (is_port($config['snmpd']['pollport'])) {
2292
			$snmpdconf .= <<<EOD
2293 7cbad422 Scott Ullrich
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
2294 03ba7a0f John Fleming
2295
EOD;
2296
2297
		}
2298
2299
		$snmpdconf .= <<<EOD
2300 d47a8a69 Scott Ullrich
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
2301
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
2302 142da8f7 John Fleming
2303 03ba7a0f John Fleming
# These are bsnmp macros not php vars.
2304 9cc8c59e Scott Ullrich
sysContact      = $(contact)
2305
sysLocation     = $(location)
2306
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
2307 142da8f7 John Fleming
2308 d47a8a69 Scott Ullrich
snmpEnableAuthenTraps = 2
2309 03ba7a0f John Fleming
2310
EOD;
2311
2312 61e047a5 Phil Davis
		if (is_array($config['snmpd']['modules'])) {
2313
			if (isset($config['snmpd']['modules']['mibii'])) {
2314 03ba7a0f John Fleming
			$snmpdconf .= <<<EOD
2315 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
2316 03ba7a0f John Fleming
2317
EOD;
2318 61e047a5 Phil Davis
			}
2319 03ba7a0f John Fleming
2320 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['netgraph'])) {
2321
				$snmpdconf .= <<<EOD
2322 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
2323
%netgraph
2324
begemotNgControlNodeName = "snmpd"
2325 03ba7a0f John Fleming
2326
EOD;
2327 61e047a5 Phil Davis
			}
2328 03ba7a0f John Fleming
2329 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['pf'])) {
2330
				$snmpdconf .= <<<EOD
2331 d47a8a69 Scott Ullrich
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
2332 95fb49e8 Seth Mos
2333
EOD;
2334 61e047a5 Phil Davis
			}
2335 95fb49e8 Seth Mos
2336 a03974a3 Renato Botelho
			if (isset($config['snmpd']['modules']['hostres'])) {
2337 c64e401c jim-p
				$snmpdconf .= <<<EOD
2338 95fb49e8 Seth Mos
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
2339
2340
EOD;
2341 61e047a5 Phil Davis
			}
2342 05036071 Renato Botelho
2343 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['bridge'])) {
2344
				$snmpdconf .= <<<EOD
2345 95fb49e8 Seth Mos
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
2346 d47a8a69 Scott Ullrich
# config must end with blank line
2347 5b237745 Scott Ullrich
2348
EOD;
2349 61e047a5 Phil Davis
			}
2350
			if (isset($config['snmpd']['modules']['ucd'])) {
2351 671914b2 jim-p
				$snmpdconf .= <<<EOD
2352
begemotSnmpdModulePath."ucd"     = "/usr/local/lib/snmp_ucd.so"
2353
2354
EOD;
2355
			}
2356 61e047a5 Phil Davis
			if (isset($config['snmpd']['modules']['regex'])) {
2357 671914b2 jim-p
				$snmpdconf .= <<<EOD
2358
begemotSnmpdModulePath."regex"     = "/usr/local/lib/snmp_regex.so"
2359
2360
EOD;
2361
			}
2362 03ba7a0f John Fleming
		}
2363 5b237745 Scott Ullrich
2364
		fwrite($fd, $snmpdconf);
2365
		fclose($fd);
2366 928d4416 Ermal
		unset($snmpdconf);
2367 5b237745 Scott Ullrich
2368 853e003a Scott Ullrich
		/* run bsnmpd */
2369
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
2370 2073c2d5 Phil Davis
			" -p {$g['varrun_path']}/snmpd.pid");
2371 5b237745 Scott Ullrich
2372 61e047a5 Phil Davis
		if (platform_booting()) {
2373 f1a44a3a Carlos Eduardo Ramos
			echo gettext("done.") . "\n";
2374 61e047a5 Phil Davis
		}
2375 5b237745 Scott Ullrich
	}
2376
2377
	return 0;
2378
}
2379
2380 7c9da7be jim-p
function services_dnsupdate_process($int = "", $updatehost = "", $forced = false) {
2381 f19d3b7a Scott Ullrich
	global $config, $g;
2382 61e047a5 Phil Davis
	if (isset($config['system']['developerspew'])) {
2383 acd910bf Scott Ullrich
		$mt = microtime();
2384 f19d3b7a Scott Ullrich
		echo "services_dnsupdate_process() being called $mt\n";
2385 acd910bf Scott Ullrich
	}
2386 f19d3b7a Scott Ullrich
2387 a23d7248 Scott Ullrich
	/* Dynamic DNS updating active? */
2388 67ee1ec5 Ermal Luçi
	if (is_array($config['dnsupdates']['dnsupdate'])) {
2389 7c9da7be jim-p
		$notify_text = "";
2390 67ee1ec5 Ermal Luçi
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
2391 61e047a5 Phil Davis
			if (!isset($dnsupdate['enable'])) {
2392 2ec2a374 Ermal Lu?i
				continue;
2393 61e047a5 Phil Davis
			}
2394
			if (!empty($int) && $int != $dnsupdate['interface']) {
2395 67ee1ec5 Ermal Luçi
				continue;
2396 61e047a5 Phil Davis
			}
2397
			if (!empty($updatehost) && ($updatehost != $dnsupdate['host'])) {
2398 7c9da7be jim-p
				continue;
2399 61e047a5 Phil Davis
			}
2400 67ee1ec5 Ermal Luçi
2401 2ec2a374 Ermal Lu?i
			/* determine interface name */
2402 26586f7a Ermal Lu?i
			$if = get_real_interface($dnsupdate['interface']);
2403 61e047a5 Phil Davis
2404
			if (isset($dnsupdate['usepublicip'])) {
2405
				$wanip = dyndnsCheckIP($dnsupdate['interface']);
2406
			} else {
2407
				$wanip = get_interface_ip($dnsupdate['interface']);
2408
			}
2409
2410 fc1f4960 jim-p
			$wanipv6 = get_interface_ipv6($dnsupdate['interface']);
2411 7c9da7be jim-p
			$cacheFile = "{$g['conf_path']}/dyndns_{$dnsupdate['interface']}_rfc2136_" . escapeshellarg($dnsupdate['host']) . "_{$dnsupdate['server']}.cache";
2412
			$currentTime = time();
2413
2414
			if ($wanip || $wanipv6) {
2415 67ee1ec5 Ermal Luçi
				$keyname = $dnsupdate['keyname'];
2416
				/* trailing dot */
2417 61e047a5 Phil Davis
				if (substr($keyname, -1) != ".") {
2418 67ee1ec5 Ermal Luçi
					$keyname .= ".";
2419 61e047a5 Phil Davis
				}
2420 67ee1ec5 Ermal Luçi
2421
				$hostname = $dnsupdate['host'];
2422
				/* trailing dot */
2423 61e047a5 Phil Davis
				if (substr($hostname, -1) != ".") {
2424 67ee1ec5 Ermal Luçi
					$hostname .= ".";
2425 61e047a5 Phil Davis
				}
2426 67ee1ec5 Ermal Luçi
2427
				/* write private key file
2428
				   this is dumb - public and private keys are the same for HMAC-MD5,
2429
				   but nsupdate insists on having both */
2430
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
2431 8ec0a8bc jim-p
				$privkey = <<<EOD
2432 a23d7248 Scott Ullrich
Private-key-format: v1.2
2433
Algorithm: 157 (HMAC)
2434 67ee1ec5 Ermal Luçi
Key: {$dnsupdate['keydata']}
2435 a23d7248 Scott Ullrich
2436
EOD;
2437 67ee1ec5 Ermal Luçi
				fwrite($fd, $privkey);
2438
				fclose($fd);
2439
2440
				/* write public key file */
2441
				if ($dnsupdate['keytype'] == "zone") {
2442
					$flags = 257;
2443
					$proto = 3;
2444
				} else if ($dnsupdate['keytype'] == "host") {
2445
					$flags = 513;
2446
					$proto = 3;
2447
				} else if ($dnsupdate['keytype'] == "user") {
2448
					$flags = 0;
2449
					$proto = 2;
2450
				}
2451 c7f44ae0 Scott Ullrich
2452 26586f7a Ermal Lu?i
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.key", "w");
2453 67ee1ec5 Ermal Luçi
				fwrite($fd, "{$keyname} IN KEY {$flags} {$proto} 157 {$dnsupdate['keydata']}\n");
2454
				fclose($fd);
2455
2456
				/* generate update instructions */
2457
				$upinst = "";
2458 61e047a5 Phil Davis
				if (!empty($dnsupdate['server'])) {
2459 67ee1ec5 Ermal Luçi
					$upinst .= "server {$dnsupdate['server']}\n";
2460 61e047a5 Phil Davis
				}
2461 7c9da7be jim-p
2462
				if (file_exists($cacheFile)) {
2463
					list($cachedipv4, $cacheTimev4) = explode("|", file_get_contents($cacheFile));
2464
				}
2465
				if (file_exists("{$cacheFile}.ipv6")) {
2466
					list($cachedipv6, $cacheTimev6) = explode("|", file_get_contents("{$cacheFile}.ipv6"));
2467
				}
2468
2469
				// 25 Days
2470
				$maxCacheAgeSecs = 25 * 24 * 60 * 60;
2471
				$need_update = false;
2472 819a603c jim-p
2473
				conf_mount_rw();
2474 fc1f4960 jim-p
				/* Update IPv4 if we have it. */
2475 ea08d2b2 Robert Nelson
				if (is_ipaddrv4($wanip) && $dnsupdate['recordtype'] != "AAAA") {
2476 7c9da7be jim-p
					if (($wanip != $cachedipv4) || (($currentTime - $cacheTimev4) > $maxCacheAgeSecs) || $forced) {
2477
						$upinst .= "update delete {$dnsupdate['host']}. A\n";
2478
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n";
2479
						$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";
2480
						@file_put_contents($cacheFile, "{$wanip}|{$currentTime}");
2481
						log_error("phpDynDNS: updating cache file {$cacheFile}: {$wanip}");
2482
						$need_update = true;
2483
					} else {
2484
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed.");
2485
					}
2486 61e047a5 Phil Davis
				} else {
2487 7c9da7be jim-p
					@unlink($cacheFile);
2488 61e047a5 Phil Davis
				}
2489 7c9da7be jim-p
2490 fc1f4960 jim-p
				/* Update IPv6 if we have it. */
2491 ea08d2b2 Robert Nelson
				if (is_ipaddrv6($wanipv6) && $dnsupdate['recordtype'] != "A") {
2492 7c9da7be jim-p
					if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) {
2493
						$upinst .= "update delete {$dnsupdate['host']}. AAAA\n";
2494
						$upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n";
2495
						$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";
2496
						@file_put_contents("{$cacheFile}.ipv6", "{$wanipv6}|{$currentTime}");
2497
						log_error("phpDynDNS: updating cache file {$cacheFile}.ipv6: {$wanipv6}");
2498
						$need_update = true;
2499
					} else {
2500
						log_error("phpDynDNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed.");
2501
					}
2502 61e047a5 Phil Davis
				} else {
2503 7c9da7be jim-p
					@unlink("{$cacheFile}.ipv6");
2504 61e047a5 Phil Davis
				}
2505 819a603c jim-p
				conf_mount_ro();
2506 67ee1ec5 Ermal Luçi
2507 7c9da7be jim-p
				$upinst .= "\n";	/* mind that trailing newline! */
2508 107e8acc Ovidiu Predescu
2509 7c9da7be jim-p
				if ($need_update) {
2510
					@file_put_contents("{$g['varetc_path']}/nsupdatecmds{$i}", $upinst);
2511
					unset($upinst);
2512
					/* invoke nsupdate */
2513 22cc6582 Renato Botelho
					$cmd = "/usr/local/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
2514 61e047a5 Phil Davis
					if (isset($dnsupdate['usetcp'])) {
2515 7c9da7be jim-p
						$cmd .= " -v";
2516 61e047a5 Phil Davis
					}
2517 7c9da7be jim-p
					$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
2518
					mwexec_bg($cmd);
2519
					unset($cmd);
2520
				}
2521 67ee1ec5 Ermal Luçi
			}
2522 a23d7248 Scott Ullrich
		}
2523 7c9da7be jim-p
		if (!empty($notify_text)) {
2524
			notify_all_remote($notify_text);
2525
		}
2526 a23d7248 Scott Ullrich
	}
2527 c7f44ae0 Scott Ullrich
2528 a23d7248 Scott Ullrich
	return 0;
2529 5b237745 Scott Ullrich
}
2530
2531 1071e028 Scott Ullrich
/* configure cron service */
2532
function configure_cron() {
2533
	global $g, $config;
2534 e7d3fc15 Ermal
2535 251ca022 Scott Ullrich
	conf_mount_rw();
2536 1071e028 Scott Ullrich
	/* preserve existing crontab entries */
2537 e7d3fc15 Ermal
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
2538 107e8acc Ovidiu Predescu
2539 e7d3fc15 Ermal
	for ($i = 0; $i < count($crontab_contents); $i++) {
2540
		$cron_item =& $crontab_contents[$i];
2541
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
2542
			array_splice($crontab_contents, $i - 1);
2543 1071e028 Scott Ullrich
			break;
2544
		}
2545
	}
2546 e7d3fc15 Ermal
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
2547 107e8acc Ovidiu Predescu
2548
2549 1071e028 Scott Ullrich
	if (is_array($config['cron']['item'])) {
2550
		$crontab_contents .= "#\n";
2551 f1a44a3a Carlos Eduardo Ramos
		$crontab_contents .= "# " . gettext("pfSense specific crontab entries") . "\n";
2552 61e047a5 Phil Davis
		$crontab_contents .= "# " .gettext("Created:") . " " . date("F j, Y, g:i a") . "\n";
2553 1071e028 Scott Ullrich
		$crontab_contents .= "#\n";
2554
2555 992f60d0 Renato Botelho
		if (isset($config['system']['proxyurl']) && !empty($config['system']['proxyurl'])) {
2556
			$http_proxy = $config['system']['proxyurl'];
2557 61e047a5 Phil Davis
			if (isset($config['system']['proxyport']) && !empty($config['system']['proxyport'])) {
2558 992f60d0 Renato Botelho
				$http_proxy .= ':' . $config['system']['proxyport'];
2559 61e047a5 Phil Davis
			}
2560 992f60d0 Renato Botelho
			$crontab_contents .= "HTTP_PROXY={$http_proxy}";
2561
		}
2562
2563 1071e028 Scott Ullrich
		foreach ($config['cron']['item'] as $item) {
2564
			$crontab_contents .= "\n{$item['minute']}\t";
2565
			$crontab_contents .= "{$item['hour']}\t";
2566
			$crontab_contents .= "{$item['mday']}\t";
2567
			$crontab_contents .= "{$item['month']}\t";
2568
			$crontab_contents .= "{$item['wday']}\t";
2569
			$crontab_contents .= "{$item['who']}\t";
2570
			$crontab_contents .= "{$item['command']}";
2571
		}
2572 107e8acc Ovidiu Predescu
2573 1071e028 Scott Ullrich
		$crontab_contents .= "\n#\n";
2574 f1a44a3a Carlos Eduardo Ramos
		$crontab_contents .= "# " . gettext("If possible do not add items to this file manually.") . "\n";
2575
		$crontab_contents .= "# " . gettext("If you do so, this file must be terminated with a blank line (e.g. new line)") . "\n";
2576 1071e028 Scott Ullrich
		$crontab_contents .= "#\n\n";
2577
	}
2578 107e8acc Ovidiu Predescu
2579 1071e028 Scott Ullrich
	/* please maintain the newline at the end of file */
2580
	file_put_contents("/etc/crontab", $crontab_contents);
2581 c2d97111 Ermal
	unset($crontab_contents);
2582 41d507a5 Scott Ullrich
2583 8fe38524 doktornotor
	/* make sure that cron is running and start it if it got killed somehow */
2584
	if (!is_process_running("cron")) {
2585
		exec("cd /tmp && /usr/sbin/cron -s 2>/dev/null");
2586
	} else {
2587 41d507a5 Scott Ullrich
	/* do a HUP kill to force sync changes */
2588 c0020b97 doktornotor
		sigkillbypid("{$g['varrun_path']}/cron.pid", "HUP");
2589 8fe38524 doktornotor
	}
2590 41d507a5 Scott Ullrich
2591 6d6bca27 Ermal Lu?i
	conf_mount_ro();
2592 1071e028 Scott Ullrich
}
2593
2594 431484c8 Ryan Wagoner
function upnp_action ($action) {
2595 aa6798c0 Scott Ullrich
	global $g, $config;
2596 61e047a5 Phil Davis
	switch ($action) {
2597 431484c8 Ryan Wagoner
		case "start":
2598 c1ac2424 Ermal
			if (file_exists('/var/etc/miniupnpd.conf')) {
2599
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
2600
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
2601
			}
2602 431484c8 Ryan Wagoner
			break;
2603
		case "stop":
2604 c1ac2424 Ermal
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
2605 61e047a5 Phil Davis
			while ((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0) {
2606 3459814a doktornotor
				mwexec('/usr/bin/killall miniupnpd 2>/dev/null', true);
2607 61e047a5 Phil Davis
			}
2608 431484c8 Ryan Wagoner
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
2609
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
2610
			break;
2611
		case "restart":
2612
			upnp_action('stop');
2613
			upnp_action('start');
2614
			break;
2615
	}
2616
}
2617
2618 6f20377b Scott Ullrich
function upnp_start() {
2619 dcc897e5 Ermal
	global $config;
2620 0c331f1e Ermal Lu?i
2621 61e047a5 Phil Davis
	if (!isset($config['installedpackages']['miniupnpd']['config'])) {
2622 0c331f1e Ermal Lu?i
		return;
2623 61e047a5 Phil Davis
	}
2624 0c331f1e Ermal Lu?i
2625 61e047a5 Phil Davis
	if ($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
2626 54bdff75 Vinicius Coque
		echo gettext("Starting UPnP service... ");
2627 dcc897e5 Ermal
		require_once('/usr/local/pkg/miniupnpd.inc');
2628
		sync_package_miniupnpd();
2629
		echo "done.\n";
2630 6f20377b Scott Ullrich
	}
2631
}
2632
2633 4de8f7ba Phil Davis
function install_cron_job($command, $active = false, $minute = "0", $hour = "*", $monthday = "*", $month = "*", $weekday = "*", $who = "root") {
2634 85405c11 jim-p
	global $config, $g;
2635
2636
	$is_installed = false;
2637 4de8f7ba Phil Davis
	$cron_changed = true;
2638 85405c11 jim-p
2639 61e047a5 Phil Davis
	if (!is_array($config['cron'])) {
2640 c2d97111 Ermal
		$config['cron'] = array();
2641 61e047a5 Phil Davis
	}
2642
	if (!is_array($config['cron']['item'])) {
2643 c2d97111 Ermal
		$config['cron']['item'] = array();
2644 61e047a5 Phil Davis
	}
2645 85405c11 jim-p
2646 4de8f7ba Phil Davis
	$x = 0;
2647 61e047a5 Phil Davis
	foreach ($config['cron']['item'] as $item) {
2648
		if (strstr($item['command'], $command)) {
2649 85405c11 jim-p
			$is_installed = true;
2650
			break;
2651
		}
2652
		$x++;
2653
	}
2654
2655 61e047a5 Phil Davis
	if ($active) {
2656 85405c11 jim-p
		$cron_item = array();
2657
		$cron_item['minute'] = $minute;
2658
		$cron_item['hour'] = $hour;
2659
		$cron_item['mday'] = $monthday;
2660
		$cron_item['month'] = $month;
2661
		$cron_item['wday'] = $weekday;
2662
		$cron_item['who'] = $who;
2663
		$cron_item['command'] = $command;
2664 61e047a5 Phil Davis
		if (!$is_installed) {
2665 85405c11 jim-p
			$config['cron']['item'][] = $cron_item;
2666 f1a44a3a Carlos Eduardo Ramos
			write_config(sprintf(gettext("Installed cron job for %s"), $command));
2667 85405c11 jim-p
		} else {
2668 4de8f7ba Phil Davis
			if ($config['cron']['item'][$x] == $cron_item) {
2669
				$cron_changed = false;
2670
				log_error(sprintf(gettext("Checked cron job for %s, no change needed"), $command));
2671
			} else {
2672
				$config['cron']['item'][$x] = $cron_item;
2673
				write_config(sprintf(gettext("Updated cron job for %s"), $command));
2674
			}
2675 85405c11 jim-p
		}
2676
	} else {
2677 61e047a5 Phil Davis
		if ($is_installed == true) {
2678 85405c11 jim-p
			unset($config['cron']['item'][$x]);
2679 149ed85e bcyrill
			write_config(sprintf(gettext("Removed cron job for %s"), $command));
2680 85405c11 jim-p
		}
2681
	}
2682 994a0644 Phil Davis
2683 61e047a5 Phil Davis
	if ($cron_changed) {
2684 994a0644 Phil Davis
		configure_cron();
2685 61e047a5 Phil Davis
	}
2686 85405c11 jim-p
}
2687
2688 693833cb Seth Mos
?>