Project

General

Profile

Download (18.7 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_get_path("dhcpdv6/{$if}/radvd-dns") != 'disabled') ? true : false;
79
	$pconfig['rasamednsasdhcp6'] = config_path_enabled("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
		config_init_path("dhcpdv6/{$if}");
206
		$dhcpd6_config = config_get_path("dhcpdv6/{$if}");
207

    
208
		$dhcpd6_config['ramode'] = $_POST['ramode'];
209
		$dhcpd6_config['rapriority'] = $_POST['rapriority'];
210
		$dhcpd6_config['rainterface'] = $_POST['rainterface'];
211

    
212
		$dhcpd6_config['ravalidlifetime'] = $_POST['ravalidlifetime'];
213
		$dhcpd6_config['rapreferredlifetime'] = $_POST['rapreferredlifetime'];
214
		$dhcpd6_config['raminrtradvinterval'] = $_POST['raminrtradvinterval'];
215
		$dhcpd6_config['ramaxrtradvinterval'] = $_POST['ramaxrtradvinterval'];
216
		$dhcpd6_config['raadvdefaultlifetime'] = $_POST['raadvdefaultlifetime'];
217

    
218
		$dhcpd6_config['radomainsearchlist'] = $_POST['radomainsearchlist'];
219
		array_del_path($dhcpd6_config, 'radnsserver');
220
		if ($_POST['radns1']) {
221
			$dhcpd6_config['radnsserver'][] = $_POST['radns1'];
222
		}
223
		if ($_POST['radns2']) {
224
			$dhcpd6_config['radnsserver'][] = $_POST['radns2'];
225
		}
226
		if ($_POST['radns3']) {
227
			$dhcpd6_config['radnsserver'][] = $_POST['radns3'];
228
		}
229

    
230
		$dhcpd6_config['radvd-dns'] = ($_POST['radvd-dns']) ? "enabled" : "disabled";
231
		$dhcpd6_config['rasamednsasdhcp6'] = ($_POST['rasamednsasdhcp6']) ? true : false;
232

    
233
		if (count($pconfig['subnets'])) {
234
			$dhcpd6_config['subnets']['item'] = $pconfig['subnets'];
235
		} else {
236
			array_del_path($dhcpd6_config, 'subnets');
237
		}
238

    
239
		config_set_path("dhcpdv6/{$if}", $dhcpd6_config);
240
		write_config("Router Advertisements settings saved");
241
		$changes_applied = true;
242
		$retval = 0;
243
		$retval |= services_radvd_configure();
244
	}
245
}
246

    
247
$pgtitle = [gettext('Services'), gettext('Router Advertisement')];
248
$pglinks = [null, 'services_radvd.php'];
249

    
250
if (!empty($if) && isset($iflist[$if])) {
251
	$pgtitle[] = $iflist[$if];
252
	$pglinks[] = 'services_radvd.php?if=' . $if;
253
}
254
$shortcut_section = 'radvd';
255

    
256
include('head.inc');
257

    
258
if ($input_errors) {
259
	print_input_errors($input_errors);
260
}
261

    
262
if ($changes_applied) {
263
	print_apply_result_box($retval);
264
}
265

    
266
if ($info_msg) {
267
	print_info_box($info_msg, 'success');
268
}
269

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

    
283
	if ($ifent == $if) {
284
		$active = true;
285
	} else {
286
		$active = false;
287
	}
288

    
289
	$tab_array[] = array($ifname, $active, 'services_radvd.php?if='.$ifent);
290
	$tabscounter++;
291
}
292

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

    
299
$valid_ra = in_array(config_get_path('dhcpdv6/'.$if.'/ramode', 'disabled'), ['managed', 'assist', 'stateless_dhcp']);
300
if (config_path_enabled('dhcpdv6/'.$if) && !$valid_ra) {
301
	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);
302
}
303

    
304
display_top_tabs($tab_array);
305

    
306
$form = new Form();
307

    
308
$section = new Form_Section(gettext('Router Advertisement'));
309

    
310
$section->addInput(new Form_Select(
311
	'ramode',
312
	'*'.gettext('Router Mode'),
313
	$pconfig['ramode'],
314
	$advertise_modes
315
))->setHelp($ramode_help);
316

    
317
$section->addInput(new Form_Select(
318
	'rapriority',
319
	'*'.gettext('Router Priority'),
320
	$pconfig['rapriority'],
321
	$priority_modes
322
))->setHelp(gettext('Select the Priority for the RA Daemon.'));
323

    
324
$carplist = get_configured_vip_list("inet6", VIP_CARP);
325

    
326
$carplistif = array();
327

    
328
if (count($carplist) > 0) {
329
	foreach ($carplist as $ifname => $vip) {
330
		if (get_configured_vip_interface($ifname) == $if) {
331
			$carplistif[$ifname] = $vip;
332
		}
333
	}
334
}
335

    
336
if (count($carplistif) > 0) {
337
	$iflist = array();
338

    
339
	$iflist['interface'] = convert_friendly_interface_to_friendly_descr($if);
340
	foreach ($carplistif as $ifname => $vip) {
341
		$iflist[$ifname] = get_vip_descr($vip) . " - " . $vip;
342
	}
343

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

    
352
$section->addInput(new Form_Input(
353
	'ravalidlifetime',
354
	gettext('Valid Lifetime'),
355
	'number',
356
	$pconfig['ravalidlifetime'],
357
	['min' => 1, 'max' => 655350, 'placeholder' => 86400]
358
))->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' .
359
'The default is 86400 seconds.'), '<br />');
360

    
361
$section->addInput(new Form_Input(
362
	'rapreferredlifetime',
363
	gettext('Preferred Lifetime'),
364
	'number',
365
	$pconfig['rapreferredlifetime'],
366
	['placeholder' => 14400]
367
))->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' .
368
			'The default is 14400 seconds.'), '<br />');
369

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

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

    
388
if (isset($pconfig['raadvdefaultlifetime']) &&
389
    is_numeric($pconfig['raadvdefaultlifetime'])) {
390
	$raadvdefaultlifetime = $pconfig['raadvdefaultlifetime'];
391
} elseif (isset($pconfig['ramaxrtradvinterval']) &&
392
    is_numeric($pconfig['ramaxrtradvinterval'])) {
393
	$raadvdefaultlifetime = $pconfig['ramaxrtradvinterval'] * 3;
394
} else {
395
	$raadvdefaultlifetime = 1800;
396
}
397

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

    
407

    
408
if (empty($pconfig['subnets'])) {
409
	$pconfig['subnets'] = array('0' => '/128');
410
}
411

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

    
418
	[$address, $subnet] = explode('/', $subnet);
419
	$group->add(new Form_IpAddress(
420
		'subnet_address' . $counter,
421
		gettext('RA Subnet'),
422
		$address,
423
		'V6'
424
	))->addClass('autotrim')
425
          ->addMask('subnet_bits' . $counter, $subnet)
426
	  ->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.') : '');
427

    
428
	$group->add(new Form_Button(
429
		'deleterow' . $counter,
430
		gettext('Delete'),
431
		null,
432
		'fa-solid fa-trash-can'
433
	))->addClass('btn-sm btn-warning');
434

    
435
	$section->add($group);
436
	$counter++;
437
}
438

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

    
449
$section->add($group);
450

    
451
$form->add($section);
452

    
453
$section = new Form_Section(gettext('DNS Configuration'));
454

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

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

    
470
$ifipv6 = get_interface_ipv6($if);
471

    
472
$dns_arrv6 = [];
473
foreach (config_get_path('system/dnsserver', []) as $dnsserver) {
474
	if (is_ipaddrv6($dnsserver)) {
475
		$dns_arrv6[] = $dnsserver;
476
	}
477
}
478

    
479
if (config_path_enabled('dnsmasq') ||
480
    config_path_enabled('unbound')) {
481
	$dns_arrv6 = [$ifipv6];
482
}
483

    
484
if (is_numeric($pool) || ($act === 'newpool')) {
485
	$subnet_dnsservers = config_get_path('dhcpdv6/'.$if.'/dnsserver', []);
486
	if (!empty($subnet_dnsservers)) {
487
		$dns_arrv6 = $subnet_dnsservers;
488
	}
489
}
490

    
491
for ($idx = 1; $idx <= 4; $idx++) {
492
	$last = $section->addInput(new Form_IpAddress(
493
		'radns' . $idx,
494
		gettext('DNS Server') . ' '. $idx,
495
		$pconfig['radns' . $idx],
496
		'ALIASV6'
497
	))->addClass('autotrim')
498
	  ->setAttribute('placeholder', $dns_arrv6[$idx - 1] ?? sprintf(gettext('DNS Server %s'), $idx));
499
}
500
$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.'));
501

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

    
511
$form->addGlobal(new Form_Input(
512
	'if',
513
	null,
514
	'hidden',
515
	$if
516
));
517

    
518

    
519
$form->add($section);
520
print($form);
521
?>
522

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

    
529
	// --------- Autocomplete -----------------------------------------------------------------------------------------
530
	var addressarray = <?= json_encode(get_alias_list('host,network,urltable')) ?>;
531

    
532
	$('#radns1, #radns2, #radns3, #radns4').autocomplete({
533
		source: addressarray
534
	});
535

    
536
});
537
//]]>
538
</script>
539

    
540
<?php
541
include("foot.inc");
(141-141/232)