Project

General

Profile

pfSense-radvd.patch

radvd-routes-enhancement-2.4.4.patch - Magnus Holmgren, 11/14/2019 10:44 AM

View differences:

pfSense-radvd-patch/etc/inc/services.inc 2019-11-14 17:22:48.548598176 +0100
156 156
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
157 157
				break;
158 158
		}
159
		$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
160
		if ($racarpif == true) {
161
			$radvdconf .= "\t\tDeprecatePrefix off;\n";
162
		} else {
163
			$radvdconf .= "\t\tDeprecatePrefix on;\n";
164
		}
165
		switch ($dhcpv6ifconf['ramode']) {
166
			case "managed":
167
				$radvdconf .= "\t\tAdvOnLink on;\n";
168
				$radvdconf .= "\t\tAdvAutonomous off;\n";
169
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
170
				break;
171
			case "router":
172
				$radvdconf .= "\t\tAdvOnLink off;\n";
173
				$radvdconf .= "\t\tAdvAutonomous off;\n";
174
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
175
				break;
176
			case "stateless_dhcp":
177
			case "assist":
178
				$radvdconf .= "\t\tAdvOnLink on;\n";
179
				$radvdconf .= "\t\tAdvAutonomous on;\n";
180
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
181
				break;
182
			case "unmanaged":
183
				$radvdconf .= "\t\tAdvOnLink on;\n";
184
				$radvdconf .= "\t\tAdvAutonomous on;\n";
185
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
186
				break;
187
		}
188

  
189
		if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
190
		  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
191
		} else {
192
		  $radvdconf .= "\t\tAdvValidLifetime 86400;\n";
193
		}
194

  
195
		if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
196
		  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
197
		} else {
198
		  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
199
		}
200

  
201
		$radvdconf .= "\t};\n";
202

  
159
		/* If there are subnets defined, do not generate prefix for interface subnet, but use the user-specified subnets instead */
203 160
		if (is_array($dhcpv6ifconf['subnets']['item'])) {
204
			foreach ($dhcpv6ifconf['subnets']['item'] as $subnet) {
205
				if (is_subnetv6($subnet)) {
206
					$radvdconf .= "\tprefix {$subnet} {\n";
161
		foreach ($dhcpv6ifconf['subnets']['item'] as $dhcpv6subnet) {
162
				$radvdconf .= "\tprefix {$dhcpv6subnet} {\n";
163
				if ($racarpif == true) {
164
					$radvdconf .= "\t\tDeprecatePrefix off;\n";
165
				} else {
207 166
					$radvdconf .= "\t\tDeprecatePrefix on;\n";
208
					switch ($dhcpv6ifconf['ramode']) {
209
						case "managed":
210
							$radvdconf .= "\t\tAdvOnLink on;\n";
211
							$radvdconf .= "\t\tAdvAutonomous off;\n";
212
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
213
							break;
214
						case "router":
215
							$radvdconf .= "\t\tAdvOnLink off;\n";
216
							$radvdconf .= "\t\tAdvAutonomous off;\n";
217
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
218
							break;
219
						case "assist":
220
							$radvdconf .= "\t\tAdvOnLink on;\n";
221
							$radvdconf .= "\t\tAdvAutonomous on;\n";
222
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
223
							break;
224
						case "unmanaged":
225
							$radvdconf .= "\t\tAdvOnLink on;\n";
226
							$radvdconf .= "\t\tAdvAutonomous on;\n";
227
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
228
							break;
229
					}
230
					$radvdconf .= "\t};\n";
231 167
				}
168
				switch($dhcpv6ifconf['ramode']) {
169
					case "managed":
170
						$radvdconf .= "\t\tAdvOnLink on;\n";
171
						$radvdconf .= "\t\tAdvAutonomous off;\n";
172
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
173
						break;
174
					case "router":
175
						$radvdconf .= "\t\tAdvOnLink off;\n";
176
						$radvdconf .= "\t\tAdvAutonomous off;\n";
177
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
178
						break;
179
					case "stateless_dhcp":
180
					case "assist":
181
						$radvdconf .= "\t\tAdvOnLink on;\n";
182
						$radvdconf .= "\t\tAdvAutonomous on;\n";
183
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
184
						break;
185
					case "unmanaged":
186
						$radvdconf .= "\t\tAdvOnLink on;\n";
187
						$radvdconf .= "\t\tAdvAutonomous on;\n";
188
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
189
						break;
190
						
191
				}
192
				if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
193
				  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
194
				} else {
195
				  $radvdconf .= "\t\tAdvValidLifetime 14400;\n";
196
				}
197
				if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
198
				  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
199
				} else {
200
				  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
201
				}
202
				$radvdconf .= "\t};\n";
232 203
			}
233 204
		}
234
		$radvdconf .= "\troute ::/0 {\n";
235
		switch ($dhcpv6ifconf['rapriority']) {
236
			case "low":
237
				$radvdconf .= "\t\tAdvRoutePreference low;\n";
238
				break;
239
			case "high":
240
				$radvdconf .= "\t\tAdvRoutePreference high;\n";
241
				break;
242
			default:
243
				$radvdconf .= "\t\tAdvRoutePreference medium;\n";
244
				break;
205

  
206
		/* There are no user-specified subnets, so generate prefix for the interface subnet only */
207
		else {
208
			$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
209
			if ($racarpif == true) {
210
				$radvdconf .= "\t\tDeprecatePrefix off;\n";
211
			} else {
212
				$radvdconf .= "\t\tDeprecatePrefix on;\n";
213
			}
214
			switch ($dhcpv6ifconf['ramode']) {
215
				case "managed":
216
					$radvdconf .= "\t\tAdvOnLink on;\n";
217
					$radvdconf .= "\t\tAdvAutonomous off;\n";
218
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
219
					break;
220
				case "router":
221
					$radvdconf .= "\t\tAdvOnLink off;\n";
222
					$radvdconf .= "\t\tAdvAutonomous off;\n";
223
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
224
					break;
225
				case "stateless_dhcp":
226
				case "assist":
227
					$radvdconf .= "\t\tAdvOnLink on;\n";
228
					$radvdconf .= "\t\tAdvAutonomous on;\n";
229
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
230
					break;
231
				case "unmanaged":
232
					$radvdconf .= "\t\tAdvOnLink on;\n";
233
					$radvdconf .= "\t\tAdvAutonomous on;\n";
234
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
235
					break;
236
			}
237
			if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
238
			  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
239
			} else {
240
			  $radvdconf .= "\t\tAdvValidLifetime 86400;\n";
241
			}
242
			if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
243
			  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
244
			} else {
245
			  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
246
			}
247
			$radvdconf .= "\t};\n";
248
		}
249
		/* If there are routes defined, do not generate a default route, but use the user-specified routes instead */
250
		if (is_array($dhcpv6ifconf['routes']['item'])) {
251
			foreach ($dhcpv6ifconf['routes']['item'] as $dhcpv6route) {
252
				$radvdconf .= "\troute " . $dhcpv6route['destination'] . " {\n";
253
				$radvdconf .= "\t\tRemoveRoute on;\n";
254
				$radvdconf .= "\t\tAdvRoutePreference " . $dhcpv6route['priority'] . ";\n";
255
				$radvdconf .= "\t};\n";
256
			}
257
		}
258
		/* There are no user-specified routes, so generate a default route entry */
259
		else {
260
			$radvdconf .= "\troute ::/0 {\n";
261
			switch ($dhcpv6ifconf['rapriority']) {
262
				case "low":
263
					$radvdconf .= "\t\tAdvRoutePreference low;\n";
264
					break;
265
				case "high":
266
					$radvdconf .= "\t\tAdvRoutePreference high;\n";
267
					break;
268
				default:
269
					$radvdconf .= "\t\tAdvRoutePreference medium;\n";
270
					break;
271
			}
272
			$radvdconf .= "\t\tRemoveRoute on;\n";
273
			$radvdconf .= "\t};\n";
245 274
		}
246
		$radvdconf .= "\t\tRemoveRoute on;\n";
247
		$radvdconf .= "\t};\n";
248 275

  
249 276
		/* add DNS servers */
250 277
		$dnslist = array();
pfSense-radvd-patch/usr/local/www/js/pfSenseHelpers.js 2019-11-14 17:42:09.320492103 +0100
254 254

  
255 255
// Called after a delete so that there are no gaps in the numbering. Most of the time the config system doesn't care about
256 256
// gaps, but I do :)
257
function renumber() {
257
function renumber(element_id) {
258 258
	var idx = 0;
259
	var groupName = getRowGroupName(element_id);
259 260

  
260
	$('.repeatable').each(function() {
261
	$('.repeatable' + groupName).each(function() {
261 262

  
262 263
		$(this).find('input').each(function() {
263 264
			$(this).prop("id", this.id.replace(/\d+$/, "") + idx);
......
280 281
	});
281 282
}
282 283

  
284
// Return the repeatable group number, if it is defined (=added as number to the end of the control's id, e.g. "addrow2")
285
function getRowGroupName(element_id) {
286
	var groupName = ''; // Always make sure we du return an empty string, so we can use it in a concatenation without doing additional if checks
287
	var regexString = /^[a-zA-Z]+(_[a-zA-Z]+)[0-9]*$/; // match any string that begins with one or more characters, has a group name after a '_' and ends with nothing or numbers
288
	var regexResult = regexString.exec(element_id);
289
	if (regexResult != null) { // the capture inside the parentheses has succeeded, so we have successfully captured a group name
290
		groupName = regexResult[1]; // only then, assign the second value to groupName
291
	}
292
	return groupName;
293
}
294

  
283 295
function delete_row(rowDelBtn) {
284 296
	var rowLabel;
297
	var groupName = getRowGroupName(rowDelBtn);
285 298

  
286 299
	// If we are deleting row zero, we need to save/restore the label
287
	if ( (rowDelBtn == "deleterow0") && ((typeof retainhelp) == "undefined")) {
300
	if ((rowDelBtn == "deleterow" + groupName + "0") && ((typeof retainhelp) == "undefined")) {
288 301
		rowLabel = $('#' + rowDelBtn).parent('div').parent('div').find('label:first').text();
289 302
	}
290 303

  
......
292 305

  
293 306
	renumber();
294 307
	checkLastRow();
308
	renumber(rowDelBtn);
309
	checkLastRow(rowDelBtn);
295 310

  
296
	if (rowDelBtn == "deleterow0") {
311
	if (rowDelBtn == "deleterow" + groupName + "0") {
297 312
		$('#' + rowDelBtn).parent('div').parent('div').find('label:first').text(rowLabel);
298 313
	}
299 314
}
300 315

  
301
function checkLastRow() {
302
	if (($('.repeatable').length <= 1) && (! $('#deleterow0').hasClass("nowarn"))) {
303
		$('#deleterow0').hide();
316
function checkLastRow(element_id) {
317
	var groupName = getRowGroupName(element_id);
318
	if($('.repeatable' + groupName).length <= 1 && (! $('#deleterow' + groupName + '0').hasClass("nowarn"))) {
319
		$('#deleterow' + groupName + '0').hide();
304 320
	} else {
305
		$('[id^=deleterow]').show();
321
		$('[id^=deleterow' + groupName + ']').show();
306 322
	}
307 323
}
308 324

  
......
337 353
		}
338 354
	});
339 355
}
340
function add_row() {
356
function add_row(rowAddBtn) {
357
	var groupName = getRowGroupName(rowAddBtn);
358
	
341 359
	// Find the last repeatable group
342
	var lastRepeatableGroup = $('.repeatable:last');
360
	var lastRepeatableGroup = $('.repeatable' + groupName + ':last');
343 361

  
344 362
	// If the number of repeats exceeds the maximum, do not add another clone
345 363
	if ($('.repeatable').length >= lastRepeatableGroup.attr('max_repeats')) {
......
356 374
	// Increment the suffix number for each input element in the new group
357 375
	bump_input_id(newGroup);
358 376

  
377
	// Somehow delete button IDs did not increment, so increment the suffix number for delete buttons also
378
	$(newGroup).find('button').each(function() {
379
		$(this).prop("id", bumpStringInt(this.id));
380
		$(this).prop("name", bumpStringInt(this.name));
381
	});
359 382
	// And for "for" tags
360 383
//	$(newGroup).find('label').attr('for', bumpStringInt($(newGroup).find('label').attr('for')));
361 384

  
......
372 395

  
373 396
	setMasks();
374 397

  
375
	checkLastRow();
398
	checkLastRow(rowAddBtn);
376 399

  
377 400
	// Autocomplete
378 401
	if ( typeof addressarray !== 'undefined') {
......
388 411
	// Now that we are no longer cloning the event handlers, we need to remove and re-add after a new row
389 412
	// has been added to the table
390 413
	$('[id^=delete]').unbind();
391
	$('[id^=delete]').click(function(event) {
392
		if ($('.repeatable').length > 1) {
414
	$('[id^=delete]').click(function() {
415
		var groupName = getRowGroupName(this.id);
416
		if($('.repeatable' + groupName).length > 1) {
393 417
			if ((typeof retainhelp) == "undefined")
394
				moveHelpText($(this).attr("id"));
418
				moveHelpText(this.id);
395 419

  
396
			delete_row($(this).attr("id"));
420
			delete_row(this.id);
397 421
		} else if ($(this).hasClass("nowarn")) {
398 422
			clearRow0();
399 423
		} else {
......
408 432

  
409 433
// on click . .
410 434
$('[id^=addrow]').click(function() {
411
	add_row();
435
	add_row(this.id);
412 436
});
413 437

  
414
$('[id^=delete]').click(function(event) {
415
	if ($('.repeatable').length > 1) {
438
$('[id^=delete]').click(function() {
439
	var groupName = getRowGroupName(this.id);
440
	if($('.repeatable' + groupName).length > 1) {
416 441
		if ((typeof retainhelp) == "undefined")
417 442
			moveHelpText($(this).attr("id"));
418 443

  
pfSense-radvd-patch/usr/local/www/services_router_advertisements.php 2019-11-14 17:18:53.719623488 +0100
85 85
	$pconfig['rasamednsasdhcp6'] = isset($config['dhcpdv6'][$if]['rasamednsasdhcp6']);
86 86

  
87 87
	$pconfig['subnets'] = $config['dhcpdv6'][$if]['subnets']['item'];
88
	$pconfig['routes'] = $config['dhcpdv6'][$if]['routes']['item'];
88 89
}
89 90
if (!is_array($pconfig['subnets'])) {
90 91
	$pconfig['subnets'] = array();
91 92
}
93
if (!is_array($pconfig['routes'])) {
94
	$pconfig['routes'] = array();
95
}
92 96

  
93 97
$advertise_modes = array(
94 98
	"disabled" => 	gettext("Disabled"),
......
108 112
		"/128 specifies a single IPv6 host; /64 specifies a normal IPv6 network; etc.  " .
109 113
		"If no subnets are specified here, the Router Advertisement (RA) Daemon will advertise to the subnet to which the router's interface is assigned.") .
110 114
	'</span>';
115
$routes_help = '<span class="help-block">' .
116
	gettext("Routes are specified in CIDR format. " .
117
			"Enter subnets to which routes should be advertised, and their priority. " .
118
			"If you need a default route, specify it with ::/0 here.  " .
119
			"If no routes are specified here, the Router Advertisement (RA) Daemon will advertise only the default route.");
111 120

  
112 121
// THe use of <div class="infoblock"> here causes the text to be hidden until the user clicks the "info" icon
113 122
$ramode_help = gettext('Select the Operating Mode for the Router Advertisement (RA) Daemon.') .
......
151 160
			}
152 161
		}
153 162
	}
163
	$pconfig['routes'] = array();
164
	for ($x = 0; $x < 5000; $x += 1) {
165
		$address = trim($_POST['route_address' . $x]);
166
		if ($address === "") {
167
			continue;
168
		}
169
		$bits = trim($_POST['route_bits' . $x]);
170
		if ($bits === "") {
171
			$bits = "128";
172
		}
173
		$priority = trim($_POST['route_priority' . $x]);
174
		if ($priority === "0") {
175
			$priority = "medium";
176
		}
177
		if (is_alias($address)) {
178
			$pconfig['routes'][] = array('destination' => $address);
179
		} else {
180
			$pconfig['routes'][] = array('destination' => $address . "/" . $bits, 'priority' => $priority);
181
			if (!is_ipaddrv6($address)) {
182
				$input_errors[] = sprintf(gettext("An invalid route was specified. [%s/%s]"), $address, $bits);
183
			}
184
		}
185
	}
154 186

  
155 187
	if (($_POST['radns1'] && !is_ipaddrv6($_POST['radns1'])) || ($_POST['radns2'] && !is_ipaddrv6($_POST['radns2'])) || ($_POST['radns3'] && !is_ipaddrv6($_POST['radns3']))) {
156 188
		$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
......
232 264
		} else {
233 265
			unset($config['dhcpdv6'][$if]['subnets']);
234 266
		}
267
		if (count($pconfig['routes'])) {
268
			$config['dhcpdv6'][$if]['routes']['item'] = $pconfig['routes'];
269
		} else {
270
			unset($config['dhcpdv6'][$if]['routes']);
271
		}
235 272

  
236 273
		write_config();
237 274
		$changes_applied = true;
......
430 467
	null,
431 468
	'fa-plus'
432 469
))->addClass('btn-success');
470
/*-----------------------------------------------------------------------------*/
471
$section->addInput(new Form_StaticText(
472
	'Routes',
473
	$routes_help
474
));
475

  
476
if (empty($pconfig['routes'])) {
477
	$pconfig['routes'] = array('0' => '/128');
478
}
479

  
480
$route_counter = 0;
481
$numrows = count($pconfig['routes']) - 1;
482
$route_priority_modes = $priority_modes;
483
array_unshift($route_priority_modes, '');
484
foreach ($pconfig['routes'] as $route) {
485
	$route_address_name = "route_address" . $route_counter;
486
	$route_bits_name = "route_bits" . $route_counter;
487
	$route_priority_name = "route_priority" . $route_counter;
488
	list($address, $mask) = explode("/", $route['destination']);
489
	$priority = $route['priority'];
490
	$group = new Form_Group($route_counter == 0 ? 'Routes':'');
491
	$group->add(new Form_IpAddress(
492
		$route_address_name,
493
		null,
494
		$address
495
	))->addMask($route_bits_name, $mask, 128, 0);
496
	$group->add(new Form_Select(
497
	$route_priority_name,
498
	null,
499
	$priority,
500
	$route_priority_modes
501
	));
502
	$group->add(new Form_Button(
503
		'deleterow_routes' . $route_counter,
504
		'Delete',
505
		null,
506
		'fa-trash'
507
	))->removeClass('btn-primary')->addClass('btn-warning');
508
	$group->addClass('repeatable_routes');
509
	$section->add($group);
510
	$route_counter++;
511
}
512
$section->addInput(new Form_Button(
513
	'addrow_routes',
514
	'Add',
515
	null,
516
	'fa-plus'
517
))->addClass('btn-success');
518
/*-----------------------------------------------------------------------------*/
433 519

  
434 520
$form->add($section);
435 521

  
......
474 560
//<![CDATA[
475 561
events.push(function() {
476 562
	// Suppress "Delete row" button if there are fewer than two rows
477
	checkLastRow();
563
	checkLastRow(this.id);
478 564

  
479 565
	// --------- Autocomplete -----------------------------------------------------------------------------------------
480 566
	var addressarray = <?= json_encode(get_alias_list(array("host", "network", "openvpn", "urltable"))) ?>;