Project

General

Profile

Download (8.57 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php-cgi -f
2
<?php
3
/*
4
 * rc.linkup
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-2024 Rubicon Communications, LLC (Netgate)
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
/* parse the configuration and include all functions used below */
26
require_once("globals.inc");
27
require_once("config.inc");
28
require_once("filter.inc");
29
require_once("shaper.inc");
30
require_once("interfaces.inc");
31
require_once("gwlb.inc");
32

    
33
function handle_argument_group($iface, $action) {
34
	global $g, $config;
35

    
36
	if (empty(config_get_path("interfaces/{$iface}"))) {
37
		log_error("Cannot find interface configuration for {$iface}");
38
		return;
39
	}
40

    
41
	if (!config_path_enabled("interfaces/{$iface}")) {
42
		log_error("Linkup detected on disabled interface...Ignoring");
43
		return;
44
	}
45

    
46
	$ipaddr = config_get_path("interfaces/{$iface}/ipaddr", '');
47
	$ip6addr = config_get_path("interfaces/{$iface}/ipaddrv6", '');
48

    
49
	$staticv4 = empty($ipaddr) ? true : is_ipaddrv4($ipaddr);
50
	$staticv6 = empty($ip6addr) ? true : is_ipaddrv6($ip6addr);
51

    
52
	/* Take care of events on bridge members when IP is configured on bridge */
53
	$bridge_if = link_interface_to_bridge($iface);
54
	if (!empty($bridge_if) && empty($ipaddr) && empty($ip6addr)) {
55
		log_error("Ignoring link event for bridge member without IP address configuration");
56
		return;
57
	}
58

    
59
	/* Ignore events on LAGG members without IP address configuration */
60
	$lagg_if = link_interface_to_lagg($iface);
61
	if (!empty($lagg_if) && empty($ipaddr) && empty($ip6addr)) {
62
		log_error("Ignoring link event for LAGG member without IP address configuration");
63
		return;
64
	}
65

    
66
	$friendly = convert_friendly_interface_to_friendly_descr($iface);
67
	$addrs = [];
68
	if (!empty($ipaddr)) {
69
		$addrs[] = "4: {$ipaddr}";
70
	}
71
	if (!empty($ip6addr)) {
72
		$addrs[] = "6: {$ip6addr}";
73
	}
74
	$addrs = implode(', ', $addrs);
75
	if (($staticv4 === true) && ($staticv6 === true)) {
76
		log_error("Hotplug event detected for {$friendly}({$iface}) static IP address ({$addrs})");
77
		interfaces_staticarp_configure($iface);
78
		switch ($action) {
79
			case "stop":
80
				log_error("DEVD Ethernet detached event for {$iface}");
81
				/* Restart unbound on interface down (static),
82
				 * only when this interface is referenced in resolver configuration.
83
				 * https://redmine.pfsense.org/issues/13254
84
				 */
85
				if (config_path_enabled('unbound')) {
86
					services_unbound_configure(true, $iface);
87
				}
88
				break;
89
			case 'start':
90
				log_error("DEVD Ethernet attached event for {$iface}");
91
				$realif = get_real_interface($iface);
92
				/* NOTE: Do not generate event for OpenVPN since the daemon does that for us. */
93
				if (substr($realif, 0, 4) != "ovpn") {
94
					log_error("HOTPLUG: Triggering address refresh on {$iface} ({$realif})");
95
					touch("{$g['tmp_path']}/{$iface}_upstart4");
96
					touch("{$g['tmp_path']}/{$iface}_upstart6");
97
					send_event("interface newip {$realif}");
98
				}
99
				break;
100
			default:
101
				/* Do nothing, invalid action */
102
		}
103
	} else {
104
		log_error("Hotplug event detected for {$friendly}({$iface}) dynamic IP address ({$addrs})");
105
		switch ($action) {
106
			case "stop":
107
				log_error("DEVD Ethernet detached event for {$iface}");
108

    
109
				/* Locate interface gateways, if any exist. */
110
				$gw4 = get_interface_gateway_name($iface, 'inet');
111
				$gw6 = get_interface_gateway_name($iface, 'inet6');
112

    
113
				/* Tear down interface for dynamic types except if the only
114
				 * dynamic part is track6
115
				 * https://redmine.pfsense.org/issues/14756
116
				 */
117
				if (!($staticv4 && ($ip6addr == 'track6'))) {
118
					interface_bring_down($iface);
119
				}
120

    
121
				if (!$staticv4) {
122
					/* If there is a gateway on this interface, we may want to take additional actions */
123
					if (!empty($gw4)) {
124
						$gw4d = false;
125
						$gw4ip = get_interface_gateway($iface, $gw4d);
126
						if (empty($gw4ip)) {
127
							$gw4ip = get_interface_gateway_last($iface, 'inet');
128
						}
129

    
130
						/* Force a gateway alarm since dpinger isn't in a state to do so
131
						 * https://redmine.pfsense.org/issues/14829
132
						 * https://redmine.pfsense.org/issues/14626
133
						 */
134
						mwexec_bg("/etc/rc.gateway_alarm " .
135
								escapeshellarg($gw4) . " " .
136
								escapeshellarg($gw4ip) . " " .
137
								'down 0 0 100');
138
					}
139
				}
140
				if (!$staticv6) {
141
					/* If there is a gateway on this interface, we may want to take additional actions */
142
					if (!empty($gw6)) {
143
						$gw6d = false;
144
						$gw6ip = get_interface_gateway_v6($iface, $gw6d);
145
						if (empty($gw6ip)) {
146
							$gw6ip = get_interface_gateway_last($iface, 'inet6');
147
						}
148
						/* Force a gateway alarm since dpinger isn't in a state to do so
149
						 * https://redmine.pfsense.org/issues/14829
150
						 * https://redmine.pfsense.org/issues/14626
151
						 */
152
						mwexec_bg("/etc/rc.gateway_alarm " .
153
								escapeshellarg($gw6) . " " .
154
								escapeshellarg($gw6ip) . " " .
155
								'down 0 0 100');
156
					}
157
				}
158
				/* Restart unbound on interface down (dynamic),
159
				 * only when this interface is referenced in resolver configuration.
160
				 * https://redmine.pfsense.org/issues/11547
161
				 * https://redmine.pfsense.org/issues/13254
162
				 */
163
				if (config_path_enabled('unbound')) {
164
					services_unbound_configure(true, $iface);
165
				}
166
				break;
167
			case "start":
168
				log_error("DEVD Ethernet attached event for {$iface}");
169
				log_error("HOTPLUG: Configuring interface {$iface}");
170
				/* trigger services restart
171
				 * see https://redmine.pfsense.org/issues/11570 */
172
				if (!$staticv4) {
173
					touch("{$g['tmp_path']}/{$iface}_upstart4");
174
					touch("{$g['tmp_path']}/{$iface}_upstart6");
175
				}
176
				// Do not try to readd to bridge otherwise em(4) has problems
177
				interface_configure($iface, true, true);
178
				/* Make sure gw monitor is configured */
179
				if ($ip6addr == 'slaac' ||
180
				    $ip6addr == 'dhcp6') {
181
					setup_gateways_monitor();
182
				}
183
				break;
184
			default:
185
				/* Do nothing, invalid action */
186
		}
187
	}
188
}
189

    
190
if (isset($_GET['interface'])) {
191
	if (!empty($_GET['interface'])) {
192
		$realiface = $_GET['interface'];
193
	}
194
	$action = $_GET['action'];
195
} else {
196
	if ($argc < 3) {
197
		log_error("HOTPLUG event: The required number of parameters not passed!");
198
		return;
199
	}
200
	$action = $argv[1];
201
	$realiface = $argv[2];
202
}
203
$action = ltrim($action, '$');
204
$realiface = ltrim($realiface, '$');
205

    
206
if (!in_array($action, ['start', 'stop'])) {
207
		log_error("HOTPLUG event: Action parameter ($action) passed is wrong - only start/stop are allowed!");
208
		return;
209
}
210

    
211
if (platform_booting()) {
212
	if (!empty($realiface)) {
213
		$interface = convert_real_interface_to_friendly_interface_name($realiface);
214
	}
215
	if (!empty($interface) &&
216
	    (config_get_path("interfaces/{$interface}/ipaddr", '') == 'dhcp')) {
217
		if (find_dhclient_process($realiface) == 0) {
218
			/* dhclient is not running */
219
			log_error("DHCP Client not running on {$interface} ($realiface), reconfiguring dhclient.");
220
			interface_dhcp_configure($interface);
221
		}
222
	} else {
223
		log_error("Ignoring link event during boot sequence.");
224
	}
225
	return;
226
}
227

    
228
if (!empty($realiface)) {
229
	if (substr($realiface, 0, 4) == 'ovpn') {
230
		log_error("Ignoring link event for OpenVPN interface");
231
		return;
232
	}
233
	$rclinkuplock = lock("rclinkup{$realiface}", LOCK_EX);
234
	$interface = convert_real_interface_to_friendly_interface_name($realiface);
235
	if (!empty($interface)) {
236
		handle_argument_group($interface, $action);
237
	}
238
	/* Check if there is any child on this one as ppp types and trigger them */
239
	foreach(config_get_path('ppps/ppp', []) as $ppp) {
240
		if (array_get_path($ppp, 'type') == 'ppp') {
241
			continue;
242
		}
243
		foreach (explode(',', array_get_path($ppp, 'ports', '')) as $parent_if) {
244
			/* The loop here is because ppp types can have real and assigned interfaces as members */
245
			$tmpiface = get_real_interface($parent_if);
246
			if ($tmpiface != $realiface) {
247
				continue;
248
			}
249
			$tmpiface = convert_real_interface_to_friendly_interface_name(array_get_path($ppp, 'if'));
250
			if (!empty($tmpiface)) {
251
				switch ($action) {
252
					case "stop":
253
						interface_bring_down($tmpiface);
254
						break;
255
					case "start":
256
						interface_configure($tmpiface, true, true);
257
						break;
258
					default:
259
						/* Do nothing, invalid action */
260
				}
261
			}
262
		}
263
	}
264
	filter_configure();
265
	unlock($rclinkuplock);
266
}
267
?>
(54-54/85)