Project

General

Profile

Download (18.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * services_radvd.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2024 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2010 Seth Mos <seth.mos@dds.nl>
10
 * All rights reserved.
11
 *
12
 * originally based on m0n0wall (http://m0n0.ch/wall)
13
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
 * All rights reserved.
15
 *
16
 * Licensed under the Apache License, Version 2.0 (the "License");
17
 * you may not use this file except in compliance with the License.
18
 * You may obtain a copy of the License at
19
 *
20
 * http://www.apache.org/licenses/LICENSE-2.0
21
 *
22
 * Unless required by applicable law or agreed to in writing, software
23
 * distributed under the License is distributed on an "AS IS" BASIS,
24
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
 * See the License for the specific language governing permissions and
26
 * limitations under the License.
27
 */
28

    
29
##|+PRIV
30
##|*IDENT=page-services-router-advertisement
31
##|*NAME=Services: Router Advertisement
32
##|*DESCR=Allow access to the 'Services: Router Advertisement' page.
33
##|*MATCH=services_radvd.php*
34
##|-PRIV
35

    
36
require_once('guiconfig.inc');
37

    
38
if (!g_get('services_dhcp_server_enable')) {
39
	header('Location: /');
40
	exit;
41
}
42

    
43
$if = $_REQUEST['if'];
44
$iflist = get_configured_interface_with_descr();
45

    
46
/* set the starting interface */
47
if (!$if || !isset($iflist[$if])) {
48
	foreach ($iflist as $ifent => $ifname) {
49
		$ifaddr = config_get_path("interfaces/{$ifent}/ipaddrv6", 'none');
50
		if (!config_path_enabled("dhcpdv6/{$ifent}") &&
51
		    !(($ifaddr == 'track6') || ($ifaddr == 'none') ||
52
		    (is_ipaddrv6($ifaddr) &&
53
		    !is_linklocal($ifaddr)))) {
54
			continue;
55
		}
56
		$if = $ifent;
57
		break;
58
	}
59
}
60

    
61
if (!empty(config_get_path("dhcpdv6/{$if}"))) {
62
	/* RA specific */
63
	$pconfig['ramode'] = config_get_path("dhcpdv6/{$if}/ramode");
64
	$pconfig['rapriority'] = config_get_path("dhcpdv6/{$if}/rapriority");
65
	$pconfig['rainterface'] = config_get_path("dhcpdv6/{$if}/rainterface");
66
	if ($pconfig['rapriority'] == "") {
67
		$pconfig['rapriority'] = "medium";
68
	}
69

    
70
	$pconfig['ravalidlifetime'] = config_get_path("dhcpdv6/{$if}/ravalidlifetime");
71
	$pconfig['rapreferredlifetime'] = config_get_path("dhcpdv6/{$if}/rapreferredlifetime");
72
	$pconfig['raminrtradvinterval'] = config_get_path("dhcpdv6/{$if}/raminrtradvinterval");
73
	$pconfig['ramaxrtradvinterval'] = config_get_path("dhcpdv6/{$if}/ramaxrtradvinterval");
74
	$pconfig['raadvdefaultlifetime'] = config_get_path("dhcpdv6/{$if}/raadvdefaultlifetime");
75

    
76
	$pconfig['radomainsearchlist'] = config_get_path("dhcpdv6/{$if}/radomainsearchlist");
77
	list($pconfig['radns1'], $pconfig['radns2'], $pconfig['radns3']) = config_get_path("dhcpdv6/{$if}/radnsserver");
78
	$pconfig['radvd-dns'] = ($config['dhcpdv6'][$if]['radvd-dns'] != 'disabled') ? true : false;
79
	$pconfig['rasamednsasdhcp6'] = isset($config['dhcpdv6'][$if]['rasamednsasdhcp6']);
80

    
81
	$pconfig['subnets'] = config_get_path("dhcpdv6/{$if}/subnets/item");
82
}
83
if (!is_array($pconfig['subnets'])) {
84
	$pconfig['subnets'] = array();
85
}
86

    
87
$advertise_modes = array(
88
	"disabled" => 	gettext("Disabled"),
89
	"router" => 	gettext("Router Only - RA Flags [none], Prefix Flags [router]"),
90
	"unmanaged" => 	gettext("Unmanaged - RA Flags [none], Prefix Flags [onlink, auto, router]"),
91
	"managed" => 	gettext("Managed - RA Flags [managed, other stateful], Prefix Flags [onlink, router]"),
92
	"assist" => 	gettext("Assisted - RA Flags [managed, other stateful], Prefix Flags [onlink, auto, router]"),
93
	"stateless_dhcp" => gettext("Stateless DHCP - RA Flags [other stateful], Prefix Flags [onlink, auto, router]"));
94
$priority_modes = array(
95
	"low" => 	gettext("Low"),
96
	"medium" => gettext("Normal"),
97
	"high" => 	gettext("High"));
98

    
99

    
100

    
101
// THe use of <div class="infoblock"> here causes the text to be hidden until the user clicks the "info" icon
102
$ramode_help = gettext('Select the Operating Mode for the Router Advertisement (RA) Daemon.') .
103
	'<div class="infoblock">' .
104
	'<dl class="dl-horizontal responsive">' .
105
	'<dt>' . gettext('Disabled') . 		 '</dt><dd>' . gettext('RADVD will not be enabled on this interface.') . '</dd>' .
106
	'<dt>' . gettext('Router Only') . 	 '</dt><dd>' . gettext('Will advertise this router.') . '</dd>' .
107
	'<dt>' . gettext('Unmanaged') . 	 '</dt><dd>' . gettext('Will advertise this router with Stateless Address Auto-Configuration (SLAAC).') . '</dd>' .
108
	'<dt>' . gettext('Managed') . 		 '</dt><dd>' . gettext('Will advertise this router with all configuration through a DHCPv6 server.') . '</dd>' .
109
	'<dt>' . gettext('Assisted') . 		 '</dt><dd>' . gettext('Will advertise this router with configuration through a DHCPv6 server and/or SLAAC.') . '</dd>' .
110
	'<dt>' . gettext('Stateless DHCP') . '</dt><dd>' . gettext('Will advertise this router with SLAAC and other configuration information available via DHCPv6.') . '</dd>' .
111
	'</dl>' .
112
	sprintf(gettext('It is not required to activate DHCPv6 server on %s ' .
113
	    'when set to "Managed", "Assisted" or "Stateless DHCP", it can ' .
114
	    'be another host on the network.'), g_get('product_label')) .
115
	'</div>';
116

    
117
if ($_POST['save']) {
118
	unset($input_errors);
119

    
120
	$pconfig = $_POST;
121

    
122
	/* input validation */
123

    
124
	if (config_get_path("interfaces/{$if}/ipaddrv6", 'none') == "none" && $_POST['ramode'] != 'disabled') {
125
		$input_errors[] = gettext("Router Advertisements can only be enabled on interfaces configured with static IPv6 or Track Interface.");
126
	}
127

    
128
	$pconfig['subnets'] = array();
129
	for ($x = 0; $x < 5000; $x += 1) {
130
		$address = trim($_POST['subnet_address' . $x]);
131
		if ($address === "") {
132
			continue;
133
		}
134

    
135
		$bits = trim($_POST['subnet_bits' . $x]);
136
		if ($bits === "") {
137
			$bits = "128";
138
		}
139

    
140
		if (is_alias($address)) {
141
			$pconfig['subnets'][] = $address;
142
		} else {
143
			$pconfig['subnets'][] = $address . "/" . $bits;
144
			if (!is_ipaddrv6($address)) {
145
				$input_errors[] = sprintf(gettext('An invalid subnet or alias was specified. [%1$s/%2$s]'), $address, $bits);
146
			}
147
		}
148
	}
149

    
150
	if (($_POST['radns1'] && !is_ipaddrv6($_POST['radns1'])) || ($_POST['radns2'] && !is_ipaddrv6($_POST['radns2'])) || ($_POST['radns3'] && !is_ipaddrv6($_POST['radns3']))) {
151
		$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
152
	}
153
	if ($_POST['radomainsearchlist']) {
154
		$domain_array=preg_split("/[ ;]+/", $_POST['radomainsearchlist']);
155
		foreach ($domain_array as $curdomain) {
156
			if (!is_domain($curdomain)) {
157
				$input_errors[] = gettext("A valid domain search list must be specified.");
158
				break;
159
			}
160
		}
161
	}
162

    
163
	if ($_POST['ravalidlifetime'] && ($_POST['ravalidlifetime'] < 7200)) {
164
		$input_errors[] = gettext("A valid lifetime below 2 hours will be ignored by clients (RFC 4862 Section 5.5.3 point e)");
165
	}
166
	if ($_POST['ravalidlifetime'] && !is_numericint($_POST['ravalidlifetime'])) {
167
		$input_errors[] = gettext("Valid lifetime must be an integer.");
168
	}
169
	if ($_POST['raminrtradvinterval']) {
170
		if (!is_numericint($_POST['raminrtradvinterval'])) {
171
			$input_errors[] = gettext("Minimum advertisement interval must be an integer.");
172
		}
173
		if ($_POST['raminrtradvinterval'] < 3) {
174
			$input_errors[] = gettext("Minimum advertisement interval must be no less than 3.");
175
		}
176
		if ($_POST['ramaxrtradvinterval'] && $_POST['raminrtradvinterval'] > (0.75 * $_POST['ramaxrtradvinterval'])) {
177
			$input_errors[] = gettext("Minimum advertisement interval must be no greater than 0.75 * Maximum advertisement interval");
178
		}
179
	}
180
	if ($_POST['ramaxrtradvinterval']) {
181
		if (!is_numericint($_POST['ramaxrtradvinterval'])) {
182
			$input_errors[] = gettext("Maximum advertisement interval must be an integer.");
183
		}
184
		if ($_POST['ramaxrtradvinterval'] < 4 || $_POST['ramaxrtradvinterval'] > 1800) {
185
			$input_errors[] = gettext("Maximum advertisement interval must be no less than 4 and no greater than 1800.");
186
		}
187
	}
188
	if ($_POST['rapreferredlifetime']) {
189
		if (!is_numericint($_POST['rapreferredlifetime'])) {
190
			$input_errors[] = gettext("Default preferred lifetime must be an integer.");
191
		}
192
	}
193
	if ($_POST['raadvdefaultlifetime'] && (($_POST['raadvdefaultlifetime'] < 1) || ($_POST['raadvdefaultlifetime'] > 9000))) {
194
		$input_errors[] = gettext("Router lifetime must be an integer between 1 and 9000.");
195
	}
196
	if (($_POST['ravalidlifetime'] && $_POST['rapreferredlifetime'] &&
197
	    ($_POST['ravalidlifetime'] < $_POST['rapreferredlifetime'])) ||
198
	    ($_POST['ravalidlifetime'] && empty($_POST['rapreferredlifetime']) &&
199
	    ($_POST['ravalidlifetime'] < 14400)) || (empty($_POST['ravalidlifetime']) &&
200
	    $_POST['rapreferredlifetime'] && ($_POST['rapreferredlifetime'] > 86400))) {
201
		$input_errors[] = gettext("Default valid lifetime must be greater than Default preferred lifetime.");
202
	}
203

    
204
	if (!$input_errors) {
205
		if (!is_array($config['dhcpdv6'])) {
206
			config_set_path('dhcpdv6', array());
207
		}
208

    
209
		if (!is_array($config['dhcpdv6'][$if])) {
210
			$config['dhcpdv6'][$if] = array();
211
		}
212

    
213
		$config['dhcpdv6'][$if]['ramode'] = $_POST['ramode'];
214
		$config['dhcpdv6'][$if]['rapriority'] = $_POST['rapriority'];
215
		$config['dhcpdv6'][$if]['rainterface'] = $_POST['rainterface'];
216

    
217
		$config['dhcpdv6'][$if]['ravalidlifetime'] = $_POST['ravalidlifetime'];
218
		$config['dhcpdv6'][$if]['rapreferredlifetime'] = $_POST['rapreferredlifetime'];
219
		$config['dhcpdv6'][$if]['raminrtradvinterval'] = $_POST['raminrtradvinterval'];
220
		$config['dhcpdv6'][$if]['ramaxrtradvinterval'] = $_POST['ramaxrtradvinterval'];
221
		$config['dhcpdv6'][$if]['raadvdefaultlifetime'] = $_POST['raadvdefaultlifetime'];
222

    
223
		$config['dhcpdv6'][$if]['radomainsearchlist'] = $_POST['radomainsearchlist'];
224
		config_del_path("dhcpdv6/{$if}/radnsserver");
225
		if ($_POST['radns1']) {
226
			$config['dhcpdv6'][$if]['radnsserver'][] = $_POST['radns1'];
227
		}
228
		if ($_POST['radns2']) {
229
			$config['dhcpdv6'][$if]['radnsserver'][] = $_POST['radns2'];
230
		}
231
		if ($_POST['radns3']) {
232
			$config['dhcpdv6'][$if]['radnsserver'][] = $_POST['radns3'];
233
		}
234

    
235
		$config['dhcpdv6'][$if]['radvd-dns'] = ($_POST['radvd-dns']) ? "enabled" : "disabled";
236
		$config['dhcpdv6'][$if]['rasamednsasdhcp6'] = ($_POST['rasamednsasdhcp6']) ? true : false;
237

    
238
		if (count($pconfig['subnets'])) {
239
			$config['dhcpdv6'][$if]['subnets']['item'] = $pconfig['subnets'];
240
		} else {
241
			config_del_path("dhcpdv6/{$if}/subnets");
242
		}
243

    
244
		write_config("Router Advertisements settings saved");
245
		$changes_applied = true;
246
		$retval = 0;
247
		$retval |= services_radvd_configure();
248
	}
249
}
250

    
251
$pgtitle = [gettext('Services'), gettext('Router Advertisement')];
252
$pglinks = [null, 'services_radvd.php'];
253

    
254
if (!empty($if) && isset($iflist[$if])) {
255
	$pgtitle[] = $iflist[$if];
256
	$pglinks[] = 'services_radvd.php?if=' . $if;
257
}
258
$shortcut_section = 'radvd';
259

    
260
include('head.inc');
261

    
262
if ($input_errors) {
263
	print_input_errors($input_errors);
264
}
265

    
266
if ($changes_applied) {
267
	print_apply_result_box($retval);
268
}
269

    
270
if ($info_msg) {
271
	print_info_box($info_msg, 'success');
272
}
273

    
274
/* active tabs */
275
$tab_array = array();
276
$tabscounter = 0;
277
$i = 0;
278
foreach ($iflist as $ifent => $ifname) {
279
	$oc = config_get_path("interfaces/{$ifent}");
280
	/* We need interfaces configured with a static IPv6 address or track6 for PD.
281
	   Also show those configured as none to allow disabling the service. See:
282
	   https://redmine.pfsense.org/issues/14967 */
283
	if (!is_ipaddrv6($oc['ipaddrv6']) && $oc['ipaddrv6'] != "track6" && array_get_path($oc, 'ipaddrv6', 'none') != 'none') {
284
		continue;
285
	}
286

    
287
	if ($ifent == $if) {
288
		$active = true;
289
	} else {
290
		$active = false;
291
	}
292

    
293
	$tab_array[] = array($ifname, $active, 'services_radvd.php?if='.$ifent);
294
	$tabscounter++;
295
}
296

    
297
if ($tabscounter == 0) {
298
	print_info_box(gettext('Router Advertisements can only be enabled on interfaces configured with static IPv6 or Track Interface.'), 'danger', false);
299
	include('foot.inc');
300
	exit;
301
}
302

    
303
$valid_ra = in_array(config_get_path('dhcpdv6/'.$if.'/ramode', 'disabled'), ['managed', 'assist', 'stateless_dhcp']);
304
if (config_path_enabled('dhcpdv6/'.$if) && !$valid_ra) {
305
	print_info_box(sprintf(gettext('DHCPv6 is enabled but not being advertised to clients on %1$s. Router Advertisement must be enabled and Router Mode set to "Managed", "Assisted" or "Stateless DHCP."'), $iflist[$if]), 'danger', false);
306
}
307

    
308
display_top_tabs($tab_array);
309

    
310
$form = new Form();
311

    
312
$section = new Form_Section(gettext('Router Advertisement'));
313

    
314
$section->addInput(new Form_Select(
315
	'ramode',
316
	'*'.gettext('Router Mode'),
317
	$pconfig['ramode'],
318
	$advertise_modes
319
))->setHelp($ramode_help);
320

    
321
$section->addInput(new Form_Select(
322
	'rapriority',
323
	'*'.gettext('Router Priority'),
324
	$pconfig['rapriority'],
325
	$priority_modes
326
))->setHelp(gettext('Select the Priority for the RA Daemon.'));
327

    
328
$carplist = get_configured_vip_list("inet6", VIP_CARP);
329

    
330
$carplistif = array();
331

    
332
if (count($carplist) > 0) {
333
	foreach ($carplist as $ifname => $vip) {
334
		if (get_configured_vip_interface($ifname) == $if) {
335
			$carplistif[$ifname] = $vip;
336
		}
337
	}
338
}
339

    
340
if (count($carplistif) > 0) {
341
	$iflist = array();
342

    
343
	$iflist['interface'] = convert_friendly_interface_to_friendly_descr($if);
344
	foreach ($carplistif as $ifname => $vip) {
345
		$iflist[$ifname] = get_vip_descr($vip) . " - " . $vip;
346
	}
347

    
348
	$section->addInput(new Form_Select(
349
		'rainterface',
350
		gettext('RA Interface'),
351
		$pconfig['rainterface'],
352
		$iflist
353
	))->setHelp(gettext('Select the Interface for the Router Advertisement (RA) Daemon.'));
354
}
355

    
356
$section->addInput(new Form_Input(
357
	'ravalidlifetime',
358
	gettext('Valid Lifetime'),
359
	'number',
360
	$pconfig['ravalidlifetime'],
361
	['min' => 1, 'max' => 655350, 'placeholder' => 86400]
362
))->setHelp(gettext('The length of time in seconds (relative to the time the packet is sent) that the prefix is valid for the purpose of on-link determination.%1$s' .
363
'The default is 86400 seconds.'), '<br />');
364

    
365
$section->addInput(new Form_Input(
366
	'rapreferredlifetime',
367
	gettext('Preferred Lifetime'),
368
	'number',
369
	$pconfig['rapreferredlifetime'],
370
	['placeholder' => 14400]
371
))->setHelp(gettext('The length of time in seconds (relative to the time the packet is sent) that addresses generated from the prefix via SLAAC remain preferred.%1$s' .
372
			'The default is 14400 seconds.'), '<br />');
373

    
374
$section->addInput(new Form_Input(
375
	'raminrtradvinterval',
376
	gettext('Minimum RA Interval'),
377
	'number',
378
	$pconfig['raminrtradvinterval'],
379
	['min' => 3, 'max' => 1350, 'placeholder' => 200]
380
))->setHelp(gettext('The minimum time allowed between sending unsolicited multicast router advertisements in seconds.%1$s' .
381
'The default is 200 seconds.'), '<br />');
382

    
383
$section->addInput(new Form_Input(
384
	'ramaxrtradvinterval',
385
	gettext('Maximum RA Interval'),
386
	'number',
387
	$pconfig['ramaxrtradvinterval'],
388
	['min' => 4, 'max' => 1800, 'placeholder' => 600]
389
))->setHelp(gettext('The maximum time allowed between sending unsolicited multicast router advertisements in seconds.%1$s' .
390
'The default is 600 seconds.'), '<br />');
391

    
392
if (isset($pconfig['raadvdefaultlifetime']) &&
393
    is_numeric($pconfig['raadvdefaultlifetime'])) {
394
	$raadvdefaultlifetime = $pconfig['raadvdefaultlifetime'];
395
} elseif (isset($pconfig['ramaxrtradvinterval']) &&
396
    is_numeric($pconfig['ramaxrtradvinterval'])) {
397
	$raadvdefaultlifetime = $pconfig['ramaxrtradvinterval'] * 3;
398
} else {
399
	$raadvdefaultlifetime = 1800;
400
}
401

    
402
$section->addInput(new Form_Input(
403
	'raadvdefaultlifetime',
404
	gettext('Router Lifetime'),
405
	'number',
406
	$pconfig['raadvdefaultlifetime'],
407
	['min' => 1, 'max' => 9000, 'placeholder' => $raadvdefaultlifetime]
408
))->setHelp(gettext('The lifetime associated with the default router in seconds.%1$s' .
409
'The default is 3 * Maximum RA interval seconds.'), '<br />');
410

    
411

    
412
if (empty($pconfig['subnets'])) {
413
	$pconfig['subnets'] = array('0' => '/128');
414
}
415

    
416
$counter = 0;
417
$last = (count($pconfig['subnets']) - 1);
418
foreach ($pconfig['subnets'] as $subnet) {
419
	$group = new Form_Group(($counter == 0) ? gettext('RA Subnet(s)') : '');
420
	$group->addClass('repeatable');
421

    
422
	[$address, $subnet] = explode('/', $subnet);
423
	$group->add(new Form_IpAddress(
424
		'subnet_address' . $counter,
425
		gettext('RA Subnet'),
426
		$address,
427
		'V6'
428
	))->addClass('autotrim')
429
          ->addMask('subnet_bits' . $counter, $subnet)
430
	  ->setHelp(($counter === $last) ? gettext('Subnets are specified in CIDR format. Select the CIDR mask that pertains to each entry. If no subnets are specified here, the RA Daemon will advertise to the subnet to which the router\'s interface is assigned.') : '');
431

    
432
	$group->add(new Form_Button(
433
		'deleterow' . $counter,
434
		gettext('Delete'),
435
		null,
436
		'fa-solid fa-trash-can'
437
	))->addClass('btn-sm btn-warning');
438

    
439
	$section->add($group);
440
	$counter++;
441
}
442

    
443
$group = new Form_Group(null);
444
$input = new Form_Button(
445
	'addrow',
446
	gettext('Add RA Subnet'),
447
	null,
448
	'fa-solid fa-plus'
449
);
450
$input->addClass('btn-success');
451
$group->add($input);
452

    
453
$section->add($group);
454

    
455
$form->add($section);
456

    
457
$section = new Form_Section(gettext('DNS Configuration'));
458

    
459
$section->addInput(new Form_Checkbox(
460
	'radvd-dns',
461
	gettext('Enable DNS'),
462
	gettext('Provide DNS Configuration via the RA Daemon'),
463
	$pconfig['radvd-dns']
464
))->setHelp(gettext('Unchecking this box disables the RA Daemon RDNSS/DNSSL options. ' .
465
			'Use with caution, as the resulting behavior may violate some RFCs.'));
466

    
467
$section->addInput(new Form_Checkbox(
468
	'rasamednsasdhcp6',
469
	gettext('Mirror DHCPv6'),
470
	gettext('Mirror DHCPv6 DNS Configuration'),
471
	$pconfig['rasamednsasdhcp6']
472
))->setHelp(gettext('When checked, the DNS configuration will be copied from the primary DHCPv6 options automatically.'));
473

    
474
$ifipv6 = get_interface_ipv6($if);
475

    
476
$dns_arrv6 = [];
477
foreach (config_get_path('system/dnsserver', []) as $dnsserver) {
478
	if (is_ipaddrv6($dnsserver)) {
479
		$dns_arrv6[] = $dnsserver;
480
	}
481
}
482

    
483
if (config_path_enabled('dnsmasq') ||
484
    config_path_enabled('unbound')) {
485
	$dns_arrv6 = [$ifipv6];
486
}
487

    
488
if (is_numeric($pool) || ($act === 'newpool')) {
489
	$subnet_dnsservers = config_get_path('dhcpdv6/'.$if.'/dnsserver', []);
490
	if (!empty($subnet_dnsservers)) {
491
		$dns_arrv6 = $subnet_dnsservers;
492
	}
493
}
494

    
495
for ($idx = 1; $idx <= 4; $idx++) {
496
	$last = $section->addInput(new Form_IpAddress(
497
		'radns' . $idx,
498
		gettext('DNS Server') . ' '. $idx,
499
		$pconfig['radns' . $idx],
500
		'ALIASV6'
501
	))->addClass('autotrim')
502
	  ->setAttribute('placeholder', $dns_arrv6[$idx - 1] ?? sprintf(gettext('DNS Server %s'), $idx));
503
}
504
$last->setHelp(gettext('Leave blank to use the IP address of this firewall interface if DNS Resolver or Forwarder is enabled, the servers configured in General settings or those obtained dynamically.'));
505

    
506
$section->addInput(new Form_Input(
507
	'radomainsearchlist',
508
	gettext('Domain Search List'),
509
	'text',
510
	$pconfig['radomainsearchlist']
511
))->addClass('autotrim')
512
  ->setAttribute('placeholder', 'example.com;sub.example.com')
513
  ->setHelp(gettext('The RA Daemon can optionally provide a domain search list. Use the semicolon character as separator.'));
514

    
515
$form->addGlobal(new Form_Input(
516
	'if',
517
	null,
518
	'hidden',
519
	$if
520
));
521

    
522

    
523
$form->add($section);
524
print($form);
525
?>
526

    
527
<script type="text/javascript">
528
//<![CDATA[
529
events.push(function() {
530
	// Suppress "Delete row" button if there are fewer than two rows
531
	checkLastRow();
532

    
533
	// --------- Autocomplete -----------------------------------------------------------------------------------------
534
	var addressarray = <?= json_encode(get_alias_list(array("host", "network", "urltable"))) ?>;
535

    
536
	$('#radns1, #radns2, #radns3, #radns4').autocomplete({
537
		source: addressarray
538
	});
539

    
540
});
541
//]]>
542
</script>
543

    
544
<?php
545
include("foot.inc");
(139-139/230)