Project

General

Profile

Download (17.3 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php-cgi -q
2
<?php
3
/*
4
 * rc.initial.setlanip
5
 *
6
 * part of pfSense (https://www.pfsense.org)
7
 * Copyright (c) 2004-2013 BSD Perimeter
8
 * Copyright (c) 2013-2016 Electric Sheep Fencing
9
 * Copyright (c) 2014-2022 Rubicon Communications, LLC (Netgate)
10
 * All rights reserved.
11
 *
12
 * originally part of 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
$options = getopt("hn", array("dry-run", "help"));
30
$restart_webgui = false;
31

    
32
if (isset($options["h"]) || isset($options["help"])) {
33
	echo "usage: /etc/rc.initial.setlanip [option ...]\n";
34
	echo "  -h, --help       show this message\n";
35
	echo "  -n, --dry-run    do not make any configuration changes\n";
36
	return 0;
37
}
38

    
39
$dry_run = isset($options["n"]) || isset($options["dry-run"]);
40
if ($dry_run) {
41
	echo "DRY RUN MODE IS ON\n";
42
}
43

    
44
/* parse the configuration and include all functions used below */
45
require_once("config.inc");
46
require_once("functions.inc");
47
require_once("filter.inc");
48
require_once("shaper.inc");
49
require_once("rrd.inc");
50

    
51
function console_prompt_for_yn ($prompt_text) {
52
	global $fp;
53

    
54
	$good_answer = false;
55

    
56
	do {
57
		echo "\n" . $prompt_text . " (y/n) ";
58
		$yn = strtolower(chop(fgets($fp)));
59
		if (($yn == "y") || ($yn == "yes")) {
60
			$boolean_answer = true;
61
			$good_answer = true;
62
		}
63
		if (($yn == "n") || ($yn == "no")) {
64
			$boolean_answer = false;
65
			$good_answer = true;
66
		}
67
	} while (!$good_answer);
68

    
69
	return $boolean_answer;
70
}
71

    
72
function console_get_interface_from_ppp($realif) {
73
	global $config;
74

    
75
	foreach (config_get_path('ppps/ppp', []) as $pppid => $ppp) {
76
		if ($realif == $ppp['if']) {
77
			$ifaces = explode(",", $ppp['ports']);
78
			return $ifaces[0];
79
		}
80
	}
81

    
82
	return "";
83
}
84

    
85
function prompt_for_enable_dhcp_server($version = 4) {
86
	global $config, $fp, $interface;
87

    
88
	/* only allow DHCP server to be enabled when static IP is
89
	   configured on this interface */
90
	if ($version === 6) {
91
		$is_ipaddr = is_ipaddrv6($config['interfaces'][$interface]['ipaddrv6']);
92
	} else {
93
		$is_ipaddr = is_ipaddrv4($config['interfaces'][$interface]['ipaddr']);
94
	}
95
	if (!($is_ipaddr)) {
96
		return false;
97
	}
98

    
99
	$label_DHCP = ($version === 6) ? "DHCP6" : "DHCP";
100
	$upperifname = strtoupper($interface);
101
	return console_prompt_for_yn (sprintf(gettext('Do you want to enable the %1$s server on %2$s?'), $label_DHCP, $upperifname));
102
}
103

    
104
function get_interface_config_description($iface) {
105
	global $config;
106
	$c = $config['interfaces'][$iface];
107
	if (!$c) {
108
		return null;
109
	}
110
	$if = $c['if'];
111
	$result = $if;
112
	$result2 = array();
113
	$ipaddr = $c['ipaddr'];
114
	$ipaddrv6 = $c['ipaddrv6'];
115
	if (is_ipaddr($ipaddr)) {
116
		$result2[] = "static";
117
	} else if ($ipaddr == "dhcp") {
118
		$result2[] = "dhcp";
119
	}
120
	if (is_ipaddr($ipaddrv6)) {
121
		$result2[] = "staticv6";
122
	} else if ($ipaddrv6 == "dhcp6") {
123
		$result2[] = "dhcp6";
124
	}
125
	if (count($result2)) {
126
		$result .= " - " . implode(", ", $result2);
127
	}
128
	return $result;
129
}
130

    
131
$fp = fopen('php://stdin', 'r');
132

    
133
/* build an interface collection */
134
$ifdescrs = get_configured_interface_with_descr(true);
135
$count = count($ifdescrs);
136

    
137
/* grab interface that we will operate on, unless there is only one interface */
138
if ($count > 1) {
139
	echo "Available interfaces:\n\n";
140
	$x=1;
141
	foreach ($ifdescrs as $iface => $ifdescr) {
142
		$config_descr = get_interface_config_description($iface);
143
		echo "{$x} - {$ifdescr} ({$config_descr})\n";
144
		$x++;
145
	}
146
	echo "\nEnter the number of the interface you wish to configure: ";
147
	$intnum = chop(fgets($fp));
148
} else {
149
	$intnum = $count;
150
}
151

    
152
if ($intnum < 1) {
153
	return;
154
}
155
if ($intnum > $count) {
156
	return;
157
}
158

    
159
$index = 1;
160
foreach ($ifdescrs as $ifname => $ifdesc) {
161
	if ($intnum == $index) {
162
		$interface = $ifname;
163
		break;
164
	} else {
165
		$index++;
166
	}
167
}
168
if (!$interface) {
169
	echo "Invalid interface!\n";
170
	return;
171
}
172

    
173
$ifaceassigned = "";
174

    
175
function next_unused_gateway_name($interface, $inet_type = 'inet') {
176
	global $g, $config;
177

    
178
	if ($inet_type == 'inet') {
179
		$name_suffix = "GW";
180
	} else {
181
		$name_suffix = "GWv6";
182
	}
183

    
184
	$new_name = strtoupper($interface) . $name_suffix;
185

    
186
	if (!is_array($config['gateways']['gateway_item'])) {
187
		return $new_name;
188
	}
189
	$count = 1;
190
	do {
191
		$existing = false;
192
		foreach ($config['gateways']['gateway_item'] as $item) {
193
			if ($item['name'] === $new_name) {
194
				$existing = true;
195
				break;
196
			}
197
		}
198
		if ($existing) {
199
			$count += 1;
200
			$new_name = strtoupper($interface) . $name_suffix . "_" . $count;
201
		}
202
	} while ($existing);
203
	return $new_name;
204
}
205

    
206
function add_gateway_to_config($interface, $gatewayip, $inet_type, $nonlocalgateway=false) {
207
	global $g, $config, $dry_run;
208
	init_config_arr(array('gateways', 'gateway_item'));
209
	$a_gateways = &$config['gateways']['gateway_item'];
210
	if ($dry_run) {
211
		print_r($a_gateways);
212
	}
213
	$new_name = '';
214
	foreach ($a_gateways as $item) {
215
		if ($item['ipprotocol'] === $inet_type) {
216
			if (($item['interface'] === $interface) && ($item['gateway'] === $gatewayip)) {
217
				$new_name = $item['name'];
218
			}
219
		}
220
	}
221
	if ($new_name == '') {
222
		$new_name = next_unused_gateway_name($interface, $inet_type);
223
		$item = array(
224
			"interface" => $interface,
225
			"gateway" => $gatewayip,
226
			"name" => $new_name,
227
			"weight" => 1,
228
			"ipprotocol" => $inet_type,
229
			"interval" => true,
230
			"descr" => "Interface $interface Gateway"
231
		);
232
		if ($nonlocalgateway) {
233
			$item['nonlocalgateway'] = true;
234
		}
235
		if ($dry_run) {
236
			print_r($item);
237
		}
238
		$a_gateways[] = $item;
239
	}
240

    
241
	//set the new GW as the default if there isnt one set yet
242
	init_config_arr(array('gateways'));
243
	if (console_prompt_for_yn (gettext("Should this gateway be set as the default gateway?"))) {
244
		if ($item['ipprotocol'] == "inet") {
245
			config_set_path('gateways/defaultgw4', $new_name);
246
		}
247
		if ($item['ipprotocol'] == "inet6") {
248
			config_set_path('gateways/defaultgw6', $new_name);
249
		}
250
	}
251

    
252
	return $new_name;
253
}
254

    
255
function console_configure_ip_address($version) {
256
	global $g, $config, $interface, $restart_dhcpd, $ifaceassigned, $fp;
257

    
258
	$label_IPvX = ($version === 6) ? "IPv6"   : "IPv4";
259
	$maxbits    = ($version === 6) ? 128      : 32;
260
	$label_DHCP = ($version === 6) ? "DHCP6"  : "DHCP";
261

    
262
	$upperifname = strtoupper($interface);
263

    
264
	if (console_prompt_for_yn (sprintf(gettext('Configure %1$s address %2$s interface via %3$s?'), $label_IPvX, $upperifname, $label_DHCP))) {
265
		$ifppp = console_get_interface_from_ppp(get_real_interface($interface));
266
		if (!empty($ifppp)) {
267
			$ifaceassigned = $ifppp;
268
		}
269
		$intip = ($version === 6) ? "dhcp6" : "dhcp";
270
		$intbits = "";
271
		$isintdhcp = true;
272
		$restart_dhcpd = true;
273
	}
274

    
275
	if ($isintdhcp == false) {
276
		while (true) {
277
			do {
278
				echo "\n" . sprintf(gettext('Enter the new %1$s %2$s address.  Press <ENTER> for none:'),
279
							$upperifname, $label_IPvX) . "\n> ";
280
				$intip = chop(fgets($fp));
281
				$intbits_ok = false;
282
				if (strstr($intip, "/")) {
283
					list($intip, $intbits) = explode("/", $intip);
284
					$intbits_ok = (is_numeric($intbits) && (($intbits >= 1) && ($intbits <= $maxbits))) ? true : false;
285
				}
286
				$is_ipaddr = ($version === 6) ? is_ipaddrv6($intip) : is_ipaddrv4($intip);
287
				if ($is_ipaddr && is_ipaddr_configured($intip, $interface, true)) {
288
					$ip_conflict = true;
289
					echo gettext("This IP address conflicts with another interface or a VIP") . "\n";
290
				} else {
291
					$ip_conflict = false;
292
				}
293
			} while (($ip_conflict === true) || !($is_ipaddr || $intip == ''));
294
			if ($is_ipaddr && $intip != '') {
295
				if ($intbits_ok == false) {
296
					echo "\n" . sprintf(gettext("Subnet masks are entered as bit counts (as in CIDR notation) in %s."),
297
							$g['product_label']) . "\n";
298
					if ($version === 6) {
299
						echo "e.g. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00 = 120\n";
300
						echo "     ffff:ffff:ffff:ffff:ffff:ffff:ffff:0    = 112\n";
301
						echo "     ffff:ffff:ffff:ffff:ffff:ffff:0:0       =  96\n";
302
						echo "     ffff:ffff:ffff:ffff:ffff:0:0:0          =  80\n";
303
						echo "     ffff:ffff:ffff:ffff:0:0:0:0             =  64\n";
304
					} else {
305
						echo "e.g. 255.255.255.0 = 24\n";
306
						echo "     255.255.0.0   = 16\n";
307
						echo "     255.0.0.0     = 8\n";
308
					}
309
				}
310
				while ($intbits_ok == false) {
311
					$upperifname = strtoupper($interface);
312
					echo "\n" . sprintf(gettext('Enter the new %1$s %2$s subnet bit count (1 to %3$s):'),
313
								$upperifname, $label_IPvX, $maxbits) . "\n> ";
314
					$intbits = chop(fgets($fp));
315
					$intbits_ok = is_numeric($intbits) && (($intbits >= 1) && ($intbits <= $maxbits));
316
					$restart_dhcpd = true;
317

    
318
					if ($version === 4 && $intbits < $maxbits) {
319
						if ($intip == gen_subnet($intip, $intbits)) {
320
							echo gettext("You cannot set network address to an interface");
321
							continue 2;
322
							$intbits_ok = false;
323
						} else if ($intip == gen_subnet_max($intip, $intbits)) {
324
							echo gettext("You cannot set broadcast address to an interface");
325
							continue 2;
326
							$intbits_ok = false;
327
						}
328
					}
329
				}
330

    
331
				if ($version === 6) {
332
					$subnet = gen_subnetv6($intip, $intbits);
333
				} else {
334
					$subnet = gen_subnet($intip, $intbits);
335
				}
336
				do {
337
					echo "\n" . sprintf(gettext('For a WAN, enter the new %1$s %2$s upstream gateway address.'), $upperifname, $label_IPvX) . "\n" .
338
								gettext("For a LAN, press <ENTER> for none:") . "\n> ";
339
					$gwip = chop(fgets($fp));
340
					$is_ipaddr = ($version === 6) ? is_ipaddrv6($gwip) : is_ipaddrv4($gwip);
341
					$is_in_subnet = $is_ipaddr && ip_in_subnet($gwip, $subnet . "/" . $intbits);
342
					$nonlocalgateway = false;
343
					if ($gwip != '') {
344
						if (!$is_ipaddr) {
345
							echo sprintf(gettext("not an %s IP address!"), $label_IPvX) . "\n";
346
						} else if (!$is_in_subnet) {
347
							$nonlocalgateway = true;
348
							echo gettext("Non-local gateway detected.");
349
						}
350
					}
351
				} while (!(empty($gwip) || $is_ipaddr));
352

    
353
				if ($gwip != '') {
354
					$inet_type = ($version === 6) ? "inet6" : "inet";
355
					$gwname = add_gateway_to_config($interface, $gwip, $inet_type, $nonlocalgateway);
356
				}
357
			}
358
			$ifppp = console_get_interface_from_ppp(get_real_interface($interface));
359
			if (!empty($ifppp)) {
360
				$ifaceassigned = $ifppp;
361
			}
362
			break;
363
		}
364
	}
365

    
366
	return array($intip, $intbits, $gwname);
367
}
368

    
369
list($intip,  $intbits,  $gwname)  = console_configure_ip_address(4);
370
list($intip6, $intbits6, $gwname6) = console_configure_ip_address(6);
371

    
372
if (!empty($ifaceassigned)) {
373
	$config['interfaces'][$interface]['if'] = $ifaceassigned;
374
}
375
$config['interfaces'][$interface]['ipaddr']    = $intip;
376
$config['interfaces'][$interface]['subnet']    = $intbits;
377
$config['interfaces'][$interface]['gateway']   = $gwname;
378
$config['interfaces'][$interface]['ipaddrv6']  = $intip6;
379
$config['interfaces'][$interface]['subnetv6']  = $intbits6;
380
$config['interfaces'][$interface]['gatewayv6'] = $gwname6;
381
$config['interfaces'][$interface]['enable']    = true;
382

    
383
function console_configure_dhcpd($version = 4) {
384
	global $g, $config, $restart_dhcpd, $fp, $interface, $dry_run, $intip, $intbits, $intip6, $intbits6;
385

    
386
	$label_IPvX = ($version === 6) ? "IPv6"    : "IPv4";
387
	$dhcpd      = ($version === 6) ? "dhcpdv6" : "dhcpd";
388

    
389
	if ($g['services_dhcp_server_enable'] && prompt_for_enable_dhcp_server($version)) {
390
		$subnet_start = ($version === 6) ? gen_subnetv6($intip6, $intbits6) : gen_subnet($intip, $intbits);
391
		$subnet_end = ($version === 6) ? gen_subnetv6_max($intip6, $intbits6) : gen_subnet_max($intip, $intbits);
392
		do {
393
			do {
394
				echo sprintf(gettext("Enter the start address of the %s client address range:"), $label_IPvX) . " ";
395
				$dhcpstartip = chop(fgets($fp));
396
				if ($dhcpstartip === "") {
397
					fclose($fp);
398
					return 0;
399
				}
400
				$is_ipaddr = ($version === 6) ? is_ipaddrv6($dhcpstartip) : is_ipaddrv4($dhcpstartip);
401
				$is_inrange = is_inrange($dhcpstartip, $subnet_start, $subnet_end);
402
				if (!$is_inrange) {
403
					echo gettext("This IP address must be in the interface's subnet") . "\n";
404
				}
405
			} while (!$is_ipaddr || !$is_inrange);
406

    
407
			do {
408
				echo sprintf(gettext("Enter the end address of the %s client address range:"), $label_IPvX) . " ";
409
				$dhcpendip = chop(fgets($fp));
410
				if ($dhcpendip === "") {
411
					fclose($fp);
412
					return 0;
413
				}
414
				$is_ipaddr = ($version === 6) ? is_ipaddrv6($dhcpendip) : is_ipaddrv4($dhcpendip);
415
				$is_inrange = is_inrange($dhcpendip, $subnet_start, $subnet_end);
416
				if (!$is_inrange) {
417
					echo gettext("This IP address must be in the interface's subnet") . "\n";
418
				}
419
				$not_inorder = ($version === 6) ? (inet_pton($dhcpendip) < inet_pton($dhcpstartip)) : ip_less_than($dhcpendip, $dhcpstartip);
420
				if ($not_inorder) {
421
					echo gettext("The end address of the DHCP range must be >= the start address") . "\n";
422
				}
423
			} while (!$is_ipaddr || !$is_inrange);
424
		} while ($not_inorder);
425
		$restart_dhcpd = true;
426
		init_config_arr(array($dhcpd, $interface, 'range'));
427
		$config[$dhcpd][$interface]['enable'] = true;
428
		$config[$dhcpd][$interface]['range']['from'] = $dhcpstartip;
429
		$config[$dhcpd][$interface]['range']['to'] = $dhcpendip;
430
	} else {
431
		if (isset($config[$dhcpd][$interface]['enable'])) {
432
			unset($config[$dhcpd][$interface]['enable']);
433
			$restart_dhcpd = true;
434
		}
435
		/* disable RA mode, see https://redmine.pfsense.org/issues/11609 */
436
		if (isset($config[$dhcpd][$interface]['ramode']) &&
437
		    ($config[$dhcpd][$interface]['ramode'] != 'disabled')) {
438
			$config[$dhcpd][$interface]['ramode'] = 'disabled';
439
			$restart_dhcpd = true;
440
		}
441
		if ($restart_dhcpd) {
442
			printf(gettext("Disabling %s DHCPD...") . "\n", $label_IPvX);
443
		}
444
	}
445
	return 1;
446
}
447

    
448
if (console_configure_dhcpd(4) == 0) {
449
	return 0;
450
}
451
if (console_configure_dhcpd(6) == 0) {
452
	return 0;
453
}
454

    
455
//*****************************************************************************
456

    
457
if ($config['system']['webgui']['protocol'] == "https") {
458
	if (console_prompt_for_yn (gettext("Do you want to revert to HTTP as the webConfigurator protocol?"))) {
459
		$config['system']['webgui']['protocol'] = "http";
460
		$restart_webgui = true;
461
	}
462
}
463

    
464
if (config_path_enabled('system/webgui', 'noantilockout')) {
465
	echo "\n" . sprintf(gettext("Note: the anti-lockout rule on %s has been re-enabled."), $interface) . "\n";
466
	config_del_path('system/webgui/noantilockout');
467
}
468

    
469
if (config_get_path('interfaces/lan')) {
470
	$paths = ['dhcpd/wan', 'dhcpdv6/wan'];
471
	foreach ($paths as $path) {
472
		if (config_get_path($path)) {
473
			config_del_path($path);
474
		}
475
    	}
476
}
477

    
478
if (!config_get_path('interfaces/lan')) {
479
	$paths = ['interfaces/lan', 'dhcpd/lan', 'dhcpdv6/lan',
480
			'shaper', 'ezshaper', 'nat'];
481
    	foreach ($paths as $path) {
482
		if (config_get_path($path)) {
483
			config_del_path($path);
484
		}
485
    	}
486
    	if (!$dry_run) {
487
		system("rm /var/dhcpd/var/db/* >/dev/null 2>/dev/null");
488
		$restart_dhcpd = true;
489
    	}
490
}
491

    
492
$upperifname = strtoupper($interface);
493
if (!$dry_run) {
494
	echo "\nPlease wait while the changes are saved to {$upperifname}...";
495
	write_config(sprintf(gettext("%s IP configuration from console menu"), $interface));
496
	if (file_exists("{$g['conf_path']}/trigger_initial_wizard")) {
497
		// if any of the interfaces is manually configured, it means that the assignment is OK
498
		touch("{$g['conf_path']}/assign_complete");
499
	}
500
	interface_reconfigure(strtolower($upperifname));
501
	echo "\n Reloading filter...";
502
	filter_configure_sync();
503
	echo "\n Reloading routing configuration...";
504
	system_routing_configure();
505
	if ($restart_dhcpd) {
506
		echo "\n DHCPD...";
507
		services_dhcpd_configure();
508
	}
509
	if ($restart_webgui) {
510
		echo "\n Restarting webConfigurator... ";
511
		mwexec("/etc/rc.restart_webgui");
512
	}
513
}
514

    
515
if ($intip != '') {
516
	if (is_ipaddr($intip)) {
517
		$intipstr = "{$intip}/{$intbits}";
518
	} else {
519
		$intipstr = $intip;
520
	}
521
	echo "\n\n" . sprintf(gettext('The IPv4 %1$s address has been set to %2$s'), $upperifname, $intipstr) . "\n";
522
}
523
if ($intip6 != '') {
524
	if (is_ipaddr($intip6)) {
525
		$intip6str = "${intip6}/${intbits6}";
526
	} else {
527
		$intip6str = $intip6;
528
	}
529
	echo "\n\n" . sprintf(gettext('The IPv6 %1$s address has been set to %2$s'), $upperifname, $intip6str) . "\n";
530
}
531

    
532
if ($intip != '' || $intip6 != '') {
533
	if ((count($ifdescrs) == "1") ||
534
	    (!interface_has_gateway($interface) && !interface_has_gatewayv6($interface))) {
535
		if ($debug) {
536
			echo "ifdescrs count is " . count($ifdescrs) . "\n";
537
			echo "interface is {$interface} \n";
538
		}
539
		echo gettext('You can now access the webConfigurator by opening the following URL in your web browser:') . "\n";
540
		if (!empty($config['system']['webgui']['port'])) {
541
			$webuiport = $config['system']['webgui']['port'];
542
			if ($intip != '') {
543
				echo "		{$config['system']['webgui']['protocol']}://{$intip}:{$webuiport}/\n";
544
			}
545
			if ($intip6 != '') {
546
				if (is_ipaddr($intip6)) {
547
					echo "		{$config['system']['webgui']['protocol']}://[{$intip6}]:{$webuiport}/\n";
548
				} else {
549
					echo "		{$config['system']['webgui']['protocol']}://{$intip6}:{$webuiport}/\n";
550
				}
551
			}
552
		} else {
553
			if ($intip != '') {
554
				echo "		{$config['system']['webgui']['protocol']}://{$intip}/\n";
555
			}
556
			if ($intip6 != '') {
557
				if (is_ipaddr($intip6)) {
558
					echo "		{$config['system']['webgui']['protocol']}://[{$intip6}]/\n";
559
				} else {
560
					echo "		{$config['system']['webgui']['protocol']}://{$intip6}/\n";
561
				}
562
			}
563
		}
564
	}
565
}
566

    
567
echo "\n" . gettext('Press <ENTER> to continue.');
568

    
569
fgets($fp);
570
fclose($fp);
571

    
572
?>
(45-45/85)