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");
|