Project

General

Profile

Feature #3718 » radvd-routes-enhancment-2.3.2.patch

Marc Posch, 07/27/2016 04:16 PM

View differences:

/etc/inc/services.inc Wed Jul 27 22:56:08 2016
185 185
			case "stateless_dhcp":
186 186
				$radvdconf .= "\tAdvManagedFlag off;\n";
187 187
				$radvdconf .= "\tAdvOtherConfigFlag on;\n";
188 188
				break;
189 189
		}
190
		$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
191
		if ($racarpif == true) {
192
			$radvdconf .= "\t\tDeprecatePrefix off;\n";
193
		} else {
194
			$radvdconf .= "\t\tDeprecatePrefix on;\n";
195
		}
196
		switch ($dhcpv6ifconf['ramode']) {
197
			case "managed":
198
				$radvdconf .= "\t\tAdvOnLink on;\n";
199
				$radvdconf .= "\t\tAdvAutonomous off;\n";
200
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
201
				break;
202
			case "router":
203
				$radvdconf .= "\t\tAdvOnLink off;\n";
204
				$radvdconf .= "\t\tAdvAutonomous off;\n";
205
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
206
				break;
207
			case "stateless_dhcp":
208
			case "assist":
209
				$radvdconf .= "\t\tAdvOnLink on;\n";
210
				$radvdconf .= "\t\tAdvAutonomous on;\n";
211
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
212
				break;
213
			case "unmanaged":
214
				$radvdconf .= "\t\tAdvOnLink on;\n";
215
				$radvdconf .= "\t\tAdvAutonomous on;\n";
216
				$radvdconf .= "\t\tAdvRouterAddr on;\n";
217
				break;
218
		}
190
		/* If there are subnets defined, do not generate prefix for interface subnet, but use the user-specified subnets instead */
191
		if (is_array($dhcpv6ifconf['subnets']['item'])) {
192
		foreach ($dhcpv6ifconf['subnets']['item'] as $dhcpv6subnet) {
193
				$radvdconf .= "\tprefix {$dhcpv6subnet} {\n";
194
				if ($racarpif == true) {
195
					$radvdconf .= "\t\tDeprecatePrefix off;\n";
196
				} else {
197
					$radvdconf .= "\t\tDeprecatePrefix on;\n";
198
				}
199
				switch($dhcpv6ifconf['ramode']) {
200
					case "managed":
201
						$radvdconf .= "\t\tAdvOnLink on;\n";
202
						$radvdconf .= "\t\tAdvAutonomous off;\n";
203
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
204
						break;
205
					case "router":
206
						$radvdconf .= "\t\tAdvOnLink off;\n";
207
						$radvdconf .= "\t\tAdvAutonomous off;\n";
208
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
209
						break;
210
					case "stateless_dhcp":
211
					case "assist":
212
						$radvdconf .= "\t\tAdvOnLink on;\n";
213
						$radvdconf .= "\t\tAdvAutonomous on;\n";
214
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
215
						break;
216
					case "unmanaged":
217
						$radvdconf .= "\t\tAdvOnLink on;\n";
218
						$radvdconf .= "\t\tAdvAutonomous on;\n";
219
						$radvdconf .= "\t\tAdvRouterAddr on;\n";
220
						break;
221
						
222
				}
223
				if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
224
				  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
225
				} else {
226
				  $radvdconf .= "\t\tAdvValidLifetime 86400;\n";
227
				}
219 228

  
220
		if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
221
		  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
222
		} else {
223
		  $radvdconf .= "\t\tAdvValidLifetime 86400;\n";
229
				if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
230
				  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
231
				} else {
232
				  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
233
				}
234
				$radvdconf .= "\t};\n";
235
			}
224 236
		}
225 237

  
226
		if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
227
		  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
228
		} else {
229
		  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
238
		/* There are no user-specified subnets, so generate prefix for the interface subnet only */
239
		else {
240
			$radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n";
241
			if ($racarpif == true) {
242
				$radvdconf .= "\t\tDeprecatePrefix off;\n";
243
			} else {
244
				$radvdconf .= "\t\tDeprecatePrefix on;\n";
245
			}
246
			switch ($dhcpv6ifconf['ramode']) {
247
				case "managed":
248
					$radvdconf .= "\t\tAdvOnLink on;\n";
249
					$radvdconf .= "\t\tAdvAutonomous off;\n";
250
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
251
					break;
252
				case "router":
253
					$radvdconf .= "\t\tAdvOnLink off;\n";
254
					$radvdconf .= "\t\tAdvAutonomous off;\n";
255
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
256
					break;
257
				case "stateless_dhcp":
258
				case "assist":
259
					$radvdconf .= "\t\tAdvOnLink on;\n";
260
					$radvdconf .= "\t\tAdvAutonomous on;\n";
261
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
262
					break;
263
				case "unmanaged":
264
					$radvdconf .= "\t\tAdvOnLink on;\n";
265
					$radvdconf .= "\t\tAdvAutonomous on;\n";
266
					$radvdconf .= "\t\tAdvRouterAddr on;\n";
267
					break;
268
			}
269
			if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) {
270
			  $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n";
271
			} else {
272
			  $radvdconf .= "\t\tAdvValidLifetime 86400;\n";
273
			}
274
			if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) {
275
			  $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n";
276
			} else {
277
			  $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n";
278
			}
279
			$radvdconf .= "\t};\n";
230 280
		}
231

  
232
		$radvdconf .= "\t};\n";
233

  
234
		if (is_array($dhcpv6ifconf['subnets']['item'])) {
235
			foreach ($dhcpv6ifconf['subnets']['item'] as $subnet) {
236
				if (is_subnetv6($subnet)) {
237
					$radvdconf .= "\tprefix {$subnet} {\n";
238
					$radvdconf .= "\t\tDeprecatePrefix on;\n";
239
					switch ($dhcpv6ifconf['ramode']) {
240
						case "managed":
241
							$radvdconf .= "\t\tAdvOnLink on;\n";
242
							$radvdconf .= "\t\tAdvAutonomous off;\n";
243
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
244
							break;
245
						case "router":
246
							$radvdconf .= "\t\tAdvOnLink off;\n";
247
							$radvdconf .= "\t\tAdvAutonomous off;\n";
248
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
249
							break;
250
						case "assist":
251
							$radvdconf .= "\t\tAdvOnLink on;\n";
252
							$radvdconf .= "\t\tAdvAutonomous on;\n";
253
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
254
							break;
255
						case "unmanaged":
256
							$radvdconf .= "\t\tAdvOnLink on;\n";
257
							$radvdconf .= "\t\tAdvAutonomous on;\n";
258
							$radvdconf .= "\t\tAdvRouterAddr on;\n";
259
							break;
260
					}
261
					$radvdconf .= "\t};\n";
262
				}
281
		/* If there are routes defined, do not generate a default route, but use the user-specified routes instead */
282
		if (is_array($dhcpv6ifconf['routes']['item'])) {
283
			foreach ($dhcpv6ifconf['routes']['item'] as $dhcpv6route) {
284
				$radvdconf .= "\troute " . $dhcpv6route['destination'] . " {\n";
285
				$radvdconf .= "\t\tRemoveRoute on;\n";
286
				$radvdconf .= "\t\tAdvRoutePreference " . $dhcpv6route['priority'] . ";\n";
287
				$radvdconf .= "\t};\n";
263 288
			}
264 289
		}
265
		$radvdconf .= "\troute ::/0 {\n";
266
		$radvdconf .= "\t\tRemoveRoute on;\n";
267
		$radvdconf .= "\t};\n";
290
		/* There are no user-specified routes, so generate a default route entry */
291
		else {
292
			$radvdconf .= "\troute ::/0 {\n";
293
			$radvdconf .= "\t\tRemoveRoute on;\n";
294
			$radvdconf .= "\t};\n";
295
		}
268 296

  
269 297
		/* add DNS servers */
270 298
		$dnslist = array();
271 299
		if (isset($dhcpv6ifconf['rasamednsasdhcp6']) && is_array($dhcpv6ifconf['dnsserver']) && !empty($dhcpv6ifconf['dnsserver'])) {
272 300
			foreach ($dhcpv6ifconf['dnsserver'] as $server) {
273
-- /usr/local/www/services_router_advertisements.php.orig	Tue Jul 19 17:33:47 2016
301
++ /usr/local/www/services_router_advertisements.php	Wed Jul 27 22:58:26 2016
......
133 133
	$pconfig['radomainsearchlist'] = $config['dhcpdv6'][$if]['radomainsearchlist'];
134 134
	list($pconfig['radns1'], $pconfig['radns2'], $pconfig['radns3']) = $config['dhcpdv6'][$if]['radnsserver'];
135 135
	$pconfig['rasamednsasdhcp6'] = isset($config['dhcpdv6'][$if]['rasamednsasdhcp6']);
136 136

  
137 137
	$pconfig['subnets'] = $config['dhcpdv6'][$if]['subnets']['item'];
138
	$pconfig['routes'] = $config['dhcpdv6'][$if]['routes']['item'];
138 139
}
139 140
if (!is_array($pconfig['subnets'])) {
140 141
	$pconfig['subnets'] = array();
141 142
}
143
if (!is_array($pconfig['routes'])) {
144
	$pconfig['routes'] = array();
145
}
142 146

  
143 147
$advertise_modes = array(
144 148
	"disabled" => 	gettext("Disabled"),
145 149
	"router" => 	gettext("Router Only"),
146 150
	"unmanaged" => 	gettext("Unmanaged"),
......
156 160
	gettext("Subnets are specified in CIDR format.  " .
157 161
		"Select the CIDR mask that pertains to each entry.	" .
158 162
		"/128 specifies a single IPv6 host; /64 specifies a normal IPv6 network; etc.  " .
159 163
		"If no subnets are specified here, the Router Advertisement (RA) Daemon will advertise to the subnet to which the router's interface is assigned.") .
160 164
	'</span>';
165
$routes_help = '<span class="help-block">' .
166
	gettext("Routes are specified in CIDR format. " .
167
			"Enter subnets to which routes should be advertised, and their priority. " .
168
			"If you need a default route, specify it with ::/0 here.  " .
169
			"If no routes are specified here, the Router Advertisement (RA) Daemon will advertise only the default route.");
161 170

  
162 171
if ($_POST) {
163 172
	unset($input_errors);
164 173

  
165 174
	$pconfig = $_POST;
......
185 194
			if (!is_ipaddrv6($address)) {
186 195
				$input_errors[] = sprintf(gettext("An invalid subnet or alias was specified. [%s/%s]"), $address, $bits);
187 196
			}
188 197
		}
189 198
	}
199
	$pconfig['routes'] = array();
200
	for ($x = 0; $x < 5000; $x += 1) {
201
		$address = trim($_POST['route_address' . $x]);
202
		if ($address === "") {
203
			continue;
204
		}
205
		$bits = trim($_POST['route_bits' . $x]);
206
		if ($bits === "") {
207
			$bits = "128";
208
		}
209
		$priority = trim($_POST['route_priority' . $x]);
210
		if ($priority === "0") {
211
			$priority = "medium";
212
		}
213
		if (is_alias($address)) {
214
			$pconfig['routes'][] = array('destination' => $address);
215
		} else {
216
			$pconfig['routes'][] = array('destination' => $address . "/" . $bits, 'priority' => $priority);
217
			if (!is_ipaddrv6($address)) {
218
				$input_errors[] = sprintf(gettext("An invalid route was specified. [%s/%s]"), $address, $bits);
219
			}
220
		}
221
	}
190 222

  
191 223
	if (($_POST['radns1'] && !is_ipaddrv6($_POST['radns1'])) || ($_POST['radns2'] && !is_ipaddrv6($_POST['radns2'])) || ($_POST['radns3'] && !is_ipaddrv6($_POST['radns3']))) {
192 224
		$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
193 225
	}
194 226
	if ($_POST['radomainsearchlist']) {
......
262 294
		if (count($pconfig['subnets'])) {
263 295
			$config['dhcpdv6'][$if]['subnets']['item'] = $pconfig['subnets'];
264 296
		} else {
265 297
			unset($config['dhcpdv6'][$if]['subnets']);
266 298
		}
299
		if (count($pconfig['routes'])) {
300
			$config['dhcpdv6'][$if]['routes']['item'] = $pconfig['routes'];
301
		} else {
302
			unset($config['dhcpdv6'][$if]['routes']);
303
		}
267 304

  
268 305
		write_config();
269 306
		$retval = services_radvd_configure();
270 307
		$savemsg = get_std_save_message($retval);
271 308
	}
......
456 493
	'addrow',
457 494
	'Add',
458 495
	null,
459 496
	'fa-plus'
460 497
))->addClass('btn-success');
498
/*-----------------------------------------------------------------------------*/
499
$section->addInput(new Form_StaticText(
500
	'Routes',
501
	$routes_help
502
));
503
$route_counter = 0;
504
$numrows = count($pconfig['routes']) - 1;
505
$route_priority_modes = $priority_modes;
506
array_unshift($route_priority_modes, '');
507
foreach ($pconfig['routes'] as $route) {
508
	$route_address_name = "route_address" . $route_counter;
509
	$route_bits_name = "route_bits" . $route_counter;
510
	$route_priority_name = "route_priority" . $route_counter;
511
	list($address, $mask) = explode("/", $route['destination']);
512
	$priority = $route['priority'];
513
	$group = new Form_Group($route_counter == 0 ? 'Routes':'');
514
	$group->add(new Form_IpAddress(
515
		$route_address_name,
516
		null,
517
		$address
518
	))->addMask($route_bits_name, $mask, 128, 0);
519
	$group->add(new Form_Select(
520
	$route_priority_name,
521
	null,
522
	$priority,
523
	$route_priority_modes
524
	));
525
	$group->add(new Form_Button(
526
		'deleterow_routes' . $route_counter,
527
		'Delete',
528
		null,
529
		'fa-trash'
530
	))->removeClass('btn-primary')->addClass('btn-warning');
531
	$group->addClass('repeatable_routes');
532
	$section->add($group);
533
	$route_counter++;
534
}
535
$section->addInput(new Form_Button(
536
	'addrow_routes',
537
	'Add',
538
	null,
539
	'fa-plus'
540
))->addClass('btn-success');
541
/*-----------------------------------------------------------------------------*/
461 542

  
462 543
$form->add($section);
463 544

  
464 545
$section = new Form_Section('DNS Configuration');
465 546

  
......
499 580

  
500 581
<script type="text/javascript">
501 582
//<![CDATA[
502 583
events.push(function() {
503 584
	// Suppress "Delete row" button if there are fewer than two rows
504
	checkLastRow();
585
	checkLastRow(this.id);
505 586

  
506 587
	// --------- Autocomplete -----------------------------------------------------------------------------------------
507 588
	var addressarray = <?= json_encode(get_alias_list(array("host", "network", "openvpn", "urltable"))) ?>;
508 589

  
509 590
	$('#radns1, #radns2, #radns3').autocomplete({
510
-- /usr/local/www/js/pfSenseHelpers.js.orig	Tue Jul 19 17:33:47 2016
591
++ /usr/local/www/js/pfSenseHelpers.js	Wed Jul 27 22:59:53 2016
......
263 263
  return newStr || str;
264 264
}
265 265

  
266 266
// Called after a delete so that there are no gaps in the numbering. Most of the time the config system doesn't care about
267 267
// gaps, but I do :)
268
function renumber() {
268
function renumber(element_id) {
269 269
	var idx = 0;
270
	var groupName = getRowGroupName(element_id);
270 271

  
271
	$('.repeatable').each(function() {
272
	$('.repeatable' + groupName).each(function() {
272 273

  
273 274
		$(this).find('input').each(function() {
274 275
			$(this).prop("id", this.id.replace(/\d+$/, "") + idx);
275 276
			$(this).prop("name", this.name.replace(/\d+$/, "") + idx);
276 277
		});
......
284 285

  
285 286
		idx++;
286 287
	});
287 288
}
288 289

  
290
// Return the repeatable group number, if it is defined (=added as number to the end of the control's id, e.g. "addrow2")
291
function getRowGroupName(element_id) {
292
	var groupName = ''; // Always make sure we du return an empty string, so we can use it in a concatenation without doing additional if checks
293
	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
294
	var regexResult = regexString.exec(element_id);
295
	if (regexResult != null) { // the capture inside the parentheses has succeeded, so we have successfully captured a group name
296
		groupName = regexResult[1]; // only then, assign the second value to groupName
297
	}
298
	return groupName;
299
}
300

  
289 301
function delete_row(rowDelBtn) {
290 302
	var rowLabel;
303
	var groupName = getRowGroupName(rowDelBtn);
291 304

  
292 305
	// If we are deleting row zero, we need to save/restore the label
293
	if (rowDelBtn == "deleterow0") {
306
	if (rowDelBtn == "deleterow" + groupName + "0") {
294 307
		rowLabel = $('#' + rowDelBtn).parent('div').parent('div').find('label').text();
295 308
	}
296 309

  
297 310
	$('#' + rowDelBtn).parent('div').parent('div').remove();
298
	renumber();
299
	checkLastRow();
311
	renumber(rowDelBtn);
312
	checkLastRow(rowDelBtn);
300 313

  
301
	if (rowDelBtn == "deleterow0") {
314
	if (rowDelBtn == "deleterow" + groupName + "0") {
302 315
		$('#' + rowDelBtn).parent('div').parent('div').find('label').text(rowLabel);
303 316
	}
304 317
}
305 318

  
306
function checkLastRow() {
307
	if ($('.repeatable').length <= 1) {
308
		$('#deleterow0').hide();
319
function checkLastRow(element_id) {
320
	var groupName = getRowGroupName(element_id);
321
	if($('.repeatable' + groupName).length <= 1) {
322
		$('#deleterow' + groupName + '0').hide();
309 323
	} else {
310
		$('[id^=deleterow]').show();
324
		$('[id^=deleterow' + groupName + ']').show();
311 325
	}
312 326
}
313 327

  
314
function add_row() {
328
function add_row(rowAddBtn) {
329
	var groupName = getRowGroupName(rowAddBtn);
330
	
315 331
	// Find the last repeatable group
316
	var lastRepeatableGroup = $('.repeatable:last');
332
	var lastRepeatableGroup = $('.repeatable' + groupName + ':last');
317 333

  
318 334
	// Clone it
319 335
	var newGroup = lastRepeatableGroup.clone();
320 336
	// Increment the suffix number for each input element in the new group
321 337
	$(newGroup).find('input').each(function() {
......
346 362
				}));
347 363
			}
348 364
		}
349 365
	});
350 366

  
367
	// Somehow delete button IDs did not increment, so increment the suffix number for delete buttons also
368
	$(newGroup).find('button').each(function() {
369
		$(this).prop("id", bumpStringInt(this.id));
370
		$(this).prop("name", bumpStringInt(this.name));
371
	});
372

  
351 373
	// And for "for" tags
352 374
//	$(newGroup).find('label').attr('for', bumpStringInt($(newGroup).find('label').attr('for')));
353 375

  
354 376
	$(newGroup).find('label').text(""); // Clear the label. We only want it on the very first row
355 377

  
......
362 384
			$(this).remove();
363 385
	});
364 386

  
365 387
	setMasks();
366 388

  
367
	checkLastRow();
389
	checkLastRow(rowAddBtn);
368 390

  
369 391
	// Autocomplete
370 392
	if ( typeof addressarray !== 'undefined') {
371 393
		$('[id^=address]').each(function() {
372 394
			if (this.id.substring(0, 8) != "address_") {
......
378 400
	}
379 401

  
380 402
	// Now that we are no longer cloning the event handlers, we need to remove and re-add after a new row
381 403
	// has been added to the table
382 404
	$('[id^=delete]').unbind();
383
	$('[id^=delete]').click(function(event) {
384
		if ($('.repeatable').length > 1) {
405
	$('[id^=delete]').click(function() {
406
		var groupName = getRowGroupName(this.id);
407
		if($('.repeatable' + groupName).length > 1) {
385 408
			if ((typeof retainhelp) == "undefined")
386
				moveHelpText(event.target.id);
409
				moveHelpText(this.id);
387 410

  
388
			delete_row(event.target.id);
411
			delete_row(this.id);
389 412
		} else {
390 413
			alert('The last row may not be deleted.');
391 414
		}
392 415
	});
393 416

  
......
397 420
$('[id^=addrow]').prop('type','button');
398 421
$('[id^=delete]').prop('type','button');
399 422

  
400 423
// on click . .
401 424
$('[id^=addrow]').click(function() {
402
	add_row();
425
	add_row(this.id);
403 426
});
404 427

  
405
$('[id^=delete]').click(function(event) {
406
	if ($('.repeatable').length > 1) {
428
$('[id^=delete]').click(function() {
429
	var groupName = getRowGroupName(this.id);
430
	if($('.repeatable' + groupName).length > 1) {
407 431
		if ((typeof retainhelp) == "undefined")
408
			moveHelpText(event.target.id);
432
			moveHelpText(this.id);
409 433

  
410
		delete_row(event.target.id);
434
		delete_row(this.id);
411 435
	} else {
412 436
		alert('The last row may not be deleted.');
413 437
	}
414 438
});
415 439

  
(5-5/7)