Project

General

Profile

« Previous | Next » 

Revision 2ca58ffd

Added by Reid Linnemann almost 3 years ago

Replace several direct config accesses in filter.inc

Major overhauls done in: * filter_generate_gateways(0 * filter_get_vpns_list() * filter_generate_optcfg_arry() * filter_generate_reflection_proxy() * filter_nat_rules_automatic_tonathosts() * filter_nat_rules_generate()

View differences:

src/etc/inc/filter.inc
103 103
global $filter_interface_remove;
104 104
$filter_interface_remove = array();
105 105

  
106
if ($config['ipsec']['filtermode'] == 'if_ipsec') {
106
if (config_get_path('ipsec/filtermode') == 'if_ipsec') {
107 107
	$filter_interface_remove[] = 'enc';
108 108
} else {
109 109
	$filter_interface_remove[] = 'ipsec';
......
1137 1137

  
1138 1138
/* returns space separated list of vpn subnets */
1139 1139
function filter_get_vpns_list() {
1140
	global $config;
1141

  
1142 1140
	$vpns = "";
1143 1141
	$vpns_arr = array();
1144 1142

  
......
1149 1147
	if (ipsec_enabled()) {
1150 1148
		/* Include mobile IPsec client subnet in the VPN network list.
1151 1149
		   See https://redmine.pfsense.org/issues/7005 */
1152
		if (is_array($config['ipsec']['client'])
1153
		    && isset($config['ipsec']['client']['enable'])
1154
		    && isset($config['ipsec']['client']['pool_address'])
1155
		    && isset($config['ipsec']['client']['pool_netbits'])) {
1156
			$client_subnet = "{$config['ipsec']['client']['pool_address']}/{$config['ipsec']['client']['pool_netbits']}";
1150
		$pool_address = config_get_path('ipsec/client/pool_address');
1151
		$pool_netbits = config_get_path('ipsec/client/pool_netbits');
1152
		if (config_path_enabled('ipsec/client')
1153
			&& isset($pool_address)
1154
			&& isset($pool_netbits)) {
1155
			$client_subnet = "{$pool_address}/{$pool_netbits}";
1157 1156
			if (is_subnet($client_subnet)) {
1158 1157
				 $vpns_arr[] = $client_subnet;
1159 1158
			}
1160 1159
		}
1161
		if (is_array($config['ipsec']['phase2'])) {
1162
			foreach ($config['ipsec']['phase2'] as $ph2ent) {
1163
				if ((!$ph2ent['mobile']) && ($ph2ent['mode'] != 'transport') &&
1164
				    !isset($ph2ent['disabled'])) {
1165
					if (!is_array($ph2ent['remoteid'])) {
1166
						continue;
1167
					}
1168
					$ph2ent['remoteid']['mode'] = $ph2ent['mode'];
1169
					$vpns_subnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], true);
1170
					if (!is_subnet($vpns_subnet) || $vpns_subnet == "0.0.0.0/0" || $vpns_subnet == "::/0") {
1171
						continue;
1172
					}
1173
					$vpns_arr[] = $vpns_subnet;
1160
		foreach (config_get_path('ipsec/phase2', []) as $ph2ent) {
1161
			if ((!$ph2ent['mobile']) && ($ph2ent['mode'] != 'transport') &&
1162
				!isset($ph2ent['disabled'])) {
1163
				if (!is_array($ph2ent['remoteid'])) {
1164
					continue;
1165
				}
1166
				$ph2ent['remoteid']['mode'] = $ph2ent['mode'];
1167
				$vpns_subnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], true);
1168
				if (!is_subnet($vpns_subnet)
1169
					|| $vpns_subnet == "0.0.0.0/0"
1170
					|| $vpns_subnet == "::/0") {
1171
					continue;
1174 1172
				}
1173
				$vpns_arr[] = $vpns_subnet;
1175 1174
			}
1176 1175
		}
1177 1176
	}
......
1379 1378
		$FilterIflist[$if] = $oic;
1380 1379
	}
1381 1380

  
1382
	if ($config['l2tp']['mode'] == "server") {
1381
	if (config_get_path('l2tp/mode') == "server") {
1383 1382
		$oic = array();
1384 1383
		$oic['if'] = 'l2tp';
1385 1384
		$oic['descr'] = 'L2TP';
......
1394 1393
		$oic['virtual'] = true;
1395 1394
		$FilterIflist['l2tp'] = $oic;
1396 1395
	}
1397
	if (is_array($config['pppoes']['pppoe']) && (count($config['pppoes']['pppoe']) > 0)) {
1398
		$pppoeifs = array();
1399
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1400
			if ($pppoe['mode'] == "server") {
1401
				$oic = array();
1402
				$oic['if'] = 'pppoe';
1403
				$oic['descr'] = 'pppoe';
1404
				$oic['ip'] = $pppoe['localip'];
1405
				$oic['sa'] = $pppoe['remoteip'];
1406
				$oic['mode'] = $pppoe['mode'];
1407
				$oic['virtual'] = true;
1408
				if ($pppoe['pppoe_subnet'] <> "") {
1409
					$oic['sn'] = $pppoe['pppoe_subnet'];
1410
				} else {
1411
					$oic['sn'] = "32";
1412
				}
1413
				$pppoeifs[] = $oic;
1396
	$pppoeifs = array();
1397
	foreach (config_get_path('pppoes/pppoe', []) as $pppoe) {
1398
		if ($pppoe['mode'] == "server") {
1399
			$oic = array();
1400
			$oic['if'] = 'pppoe';
1401
			$oic['descr'] = 'pppoe';
1402
			$oic['ip'] = $pppoe['localip'];
1403
			$oic['sa'] = $pppoe['remoteip'];
1404
			$oic['mode'] = $pppoe['mode'];
1405
			$oic['virtual'] = true;
1406
			if ($pppoe['pppoe_subnet'] <> "") {
1407
				$oic['sn'] = $pppoe['pppoe_subnet'];
1408
			} else {
1409
				$oic['sn'] = "32";
1414 1410
			}
1415
		}
1416
		if (count($pppoeifs)) {
1417
			$FilterIflist['pppoe'] = $pppoeifs;
1411
			$pppoeifs[] = $oic;
1418 1412
		}
1419 1413
	}
1414
	if (count($pppoeifs)) {
1415
		$FilterIflist['pppoe'] = $pppoeifs;
1416
	}
1420 1417
	/* add ipsec interfaces */
1421 1418
	if (!function_exists('ipsec_enabled')) {
1422 1419
		require_once("ipsec.inc");
......
1824 1821
}
1825 1822

  
1826 1823
function filter_nat_rules_automatic_tonathosts($with_descr = false) {
1827
	global $config, $FilterIflist, $GatewaysList;
1824
	global $FilterIflist, $GatewaysList;
1828 1825

  
1829 1826
	$tonathosts = array("127.0.0.0/8", "::1/128");
1830 1827
	$descriptions = array(gettext("localhost"), gettext("localhost"));
......
1910 1907

  
1911 1908
	// OpenVPN CSO
1912 1909
	init_config_arr(array('openvpn', 'openvpn-csc'));
1913
	foreach ($config['openvpn']['openvpn-csc'] as $ovpnent) {
1910
	foreach (config_get_path('openvpn/openvpn-csc') as $ovpnent) {
1914 1911
		if (is_array($ovpnent) && !isset($ovpnent['disable']) && !empty($ovpnent['tunnel_network'])) {
1915 1912
			$tonathosts[] = implode('/', openvpn_gen_tunnel_network($ovpnent['tunnel_network']));
1916 1913
			$descriptions[] = gettext("OpenVPN CSO");
......
1918 1915
	}
1919 1916

  
1920 1917
	/* IPsec mode_cfg subnet */
1918
	$ipsc_pool_addr = config_get_path('ipsec/client/pool_address');
1919
	$ipsc_pool_netbits = config_get_path('ipsec/client/pool_netbits');
1921 1920
	if (config_path_enabled('ipsec/client') &&
1922
	    (!empty($config['ipsec']['client']['pool_address'])) &&
1923
	    (!empty($config['ipsec']['client']['pool_netbits']))) {
1924
		$tonathosts[] = "{$config['ipsec']['client']['pool_address']}/{$config['ipsec']['client']['pool_netbits']}";
1921
	    (!empty($ipsc_pool_addr)) &&
1922
	    (!empty($ipsc_pool_netbits))) {
1923
		$tonathosts[] = "{$ipsc_pool_addr}/{$ipsc_pool_netbits}";
1925 1924
		$descriptions[] = gettext("IPsec client");
1926 1925
	}
1927
	if (config_path_enabled('ipsec/client') &&
1928
	    isset($config['ipsec']['mobilekey'])) {
1929
		foreach ($config['ipsec']['mobilekey'] as $key) {
1926
	if (config_path_enabled('ipsec/client')) {
1927
		foreach (config_get_path('ipsec/mobilekey', []) as $key) {
1930 1928
			if (in_array("{$key['pool_address']}/{$key['pool_netbits']}", $tonathosts)) {
1931 1929
				continue;
1932 1930
			}
......
1937 1935
			}
1938 1936
		}
1939 1937
	}
1940
	if (is_array($config['ipsec']) && is_array($config['ipsec']['phase1']) && is_array($config['ipsec']['phase2'])) {
1941
		foreach ($config['ipsec']['phase1'] as $ph1ent) {
1942
			$vti_addrs = ipsec_vti($ph1ent, true);
1943
			// Skip non-VTI tunnels
1944
			if (!$vti_addrs || !is_array($vti_addrs)) {
1945
				continue;
1946
			}
1947
			// If any of the VTI remotes is v4, then we can make a v4 gw
1948
			foreach ($vti_addrs as $vtia) {
1949
				if (is_ipaddrv4($vtia['right'])) {
1950
					$tonathosts[] = $vtia['right'];
1951
					$descriptions[] = gettext("IPsec VTI: {$ph1ent['descr']}");
1952
				}
1938
	foreach (config_get_path('ipsec/phase1', []) as $ph1ent) {
1939
		$vti_addrs = ipsec_vti($ph1ent, true);
1940
		// Skip non-VTI tunnels
1941
		if (!$vti_addrs || !is_array($vti_addrs)) {
1942
			continue;
1943
		}
1944
		// If any of the VTI remotes is v4, then we can make a v4 gw
1945
		foreach ($vti_addrs as $vtia) {
1946
			if (is_ipaddrv4($vtia['right'])) {
1947
				$tonathosts[] = $vtia['right'];
1948
				$descriptions[] = gettext("IPsec VTI: {$ph1ent['descr']}");
1953 1949
			}
1954 1950
		}
1955 1951
	}
......
2180 2176
}
2181 2177

  
2182 2178
function filter_nat_rules_generate() {
2183
	global $config, $g, $FilterIflist;
2179
	global $g, $FilterIflist;
2184 2180

  
2185 2181
	init_config_arr(array('ipsec', 'client'));
2186
	$ipsec_client = $config['ipsec']['client'];
2182
	$ipsec_client = config_get_path('ipsec/client');
2187 2183

  
2188 2184
	$natrules = "no nat proto carp\n";
2189 2185
	$natrules .= "no rdr proto carp\n";
......
2198 2194
	$route_table = "";
2199 2195

  
2200 2196
	/* any 1:1 mappings? */
2201
	if (is_array($config['nat']['onetoone'])) {
2202
		foreach ($config['nat']['onetoone'] as $rule) {
2203
			if (isset($rule['disabled'])) {
2204
				continue;
2205
			}
2197
	foreach (config_get_path('nat/onetoone', []) as $rule) {
2198
		if (isset($rule['disabled'])) {
2199
			continue;
2200
		}
2206 2201

  
2207
			$sn = "";
2208
			$sn1 = "";
2202
		$sn = "";
2203
		$sn1 = "";
2209 2204

  
2210
			if (($rule['ipprotocol'] == 'inet6') || is_ipaddrv6($rule['external'])) {
2211
				$ipproto = 'inet6';
2212
			} else {
2213
				$ipproto = 'inet';
2214
			}
2205
		if (($rule['ipprotocol'] == 'inet6') || is_ipaddrv6($rule['external'])) {
2206
			$ipproto = 'inet6';
2207
		} else {
2208
			$ipproto = 'inet';
2209
		}
2215 2210

  
2216
			if (is_ipaddr($rule['external'])) {
2217
				$target = $rule['external'];
2218
			} else {
2219
				$tmprule = array();
2220
				$tmprule['external']['network'] = $rule['external'];
2221
				$tmprule['ipprotocol'] = $ipproto;
2222
				$target = filter_generate_address($tmprule, 'external');
2223
			}
2224
			if (!$target) {
2225
				$natrules .= "# Unresolvable alias {$rule['target']}\n";
2226
				continue;               /* unresolvable alias */
2227
			}
2211
		if (is_ipaddr($rule['external'])) {
2212
			$target = $rule['external'];
2213
		} else {
2214
			$tmprule = array();
2215
			$tmprule['external']['network'] = $rule['external'];
2216
			$tmprule['ipprotocol'] = $ipproto;
2217
			$target = filter_generate_address($tmprule, 'external');
2218
		}
2219
		if (!$target) {
2220
			$natrules .= "# Unresolvable alias {$rule['target']}\n";
2221
			continue;               /* unresolvable alias */
2222
		}
2228 2223

  
2229
			if (!$rule['interface']) {
2230
				$natif = "wan";
2231
			} else {
2232
				$natif = $rule['interface'];
2233
			}
2234
			if (!isset($FilterIflist[$natif])) {
2235
				continue;
2236
			}
2224
		if (!$rule['interface']) {
2225
			$natif = "wan";
2226
		} else {
2227
			$natif = $rule['interface'];
2228
		}
2229
		if (!isset($FilterIflist[$natif])) {
2230
			continue;
2231
		}
2237 2232

  
2238
			$srcaddr = filter_generate_address($rule, 'source');
2239
			$dstaddr = filter_generate_address($rule, 'destination');
2240
			$srcaddr = trim($srcaddr);
2241
			$dstaddr = trim($dstaddr);
2233
		$srcaddr = filter_generate_address($rule, 'source');
2234
		$dstaddr = filter_generate_address($rule, 'destination');
2235
		$srcaddr = trim($srcaddr);
2236
		$dstaddr = trim($dstaddr);
2242 2237

  
2243
			if (empty($srcaddr) || empty($dstaddr)) {
2244
				continue;
2245
			}
2238
		if (empty($srcaddr) || empty($dstaddr)) {
2239
			continue;
2240
		}
2246 2241

  
2247
			if (($srcaddr != 'any') && !is_ipaddr($srcaddr) && !is_subnet($srcaddr)) {
2248
				$srcaddr = explode(' ', $srcaddr)[1];
2249
			}
2250
			$tmp = explode('/', $srcaddr);
2251
			$srcip = $tmp[0];
2252
			if (!empty($tmp[1]) && is_numeric($tmp[1])) {
2253
				$sn = $tmp[1];
2254
				$sn1 = "/{$sn}";
2255
			}
2242
		if (($srcaddr != 'any') && !is_ipaddr($srcaddr) && !is_subnet($srcaddr)) {
2243
			$srcaddr = explode(' ', $srcaddr)[1];
2244
		}
2245
		$tmp = explode('/', $srcaddr);
2246
		$srcip = $tmp[0];
2247
		if (!empty($tmp[1]) && is_numeric($tmp[1])) {
2248
			$sn = $tmp[1];
2249
			$sn1 = "/{$sn}";
2250
		}
2256 2251

  
2257
			$natifname = $FilterIflist[$natif]['if'];
2258
			if ((($srcaddr == 'any') || is_ipaddrv6($tmp[0])) &&
2259
			    ($ipproto == 'inet6') &&
2260
			    (($FilterIflist[$natif]['type6'] == '6rd') ||
2261
			    ($FilterIflist[$natif]['type6'] == '6to4'))) {
2262
				$natif = strtolower($FilterIflist[$natif]['descr']) . "_stf";
2263
			} else {
2264
				$natif = $natifname;
2265
			}
2252
		$natifname = $FilterIflist[$natif]['if'];
2253
		if ((($srcaddr == 'any') || is_ipaddrv6($tmp[0])) &&
2254
			($ipproto == 'inet6') &&
2255
			(($FilterIflist[$natif]['type6'] == '6rd') ||
2256
			 ($FilterIflist[$natif]['type6'] == '6to4'))) {
2257
			$natif = strtolower($FilterIflist[$natif]['descr']) . "_stf";
2258
		} else {
2259
			$natif = $natifname;
2260
		}
2266 2261

  
2267
			$nat_if_list = array();
2268
			if (isset($rule['nobinat'])) {
2269
				$natrules .= "no binat on {$natif} {$ipproto} from {$srcaddr} to {$dstaddr}\n";
2270
			} else {
2271
				/*
2272
				 * If reflection is enabled, turn on extra redirections
2273
				 * for this rule by adding other interfaces to an rdr rule.
2274
				 */
2275
				if ((isset($config['system']['enablebinatreflection']) || $rule['natreflection'] == "enable") &&
2276
				    ($rule['natreflection'] != "disable")) {
2277
					$nat_if_list = filter_get_reflection_interfaces($natifname);
2278
				}
2262
		$nat_if_list = array();
2263
		if (isset($rule['nobinat'])) {
2264
			$natrules .= "no binat on {$natif} {$ipproto} from {$srcaddr} to {$dstaddr}\n";
2265
		} else {
2266
			/*
2267
			 * If reflection is enabled, turn on extra redirections
2268
			 * for this rule by adding other interfaces to an rdr rule.
2269
			 */
2270
			if ((config_path_enabled('system','enablebinatreflection') ||
2271
				 $rule['natreflection'] == "enable") &&
2272
				($rule['natreflection'] != "disable")) {
2273
				$nat_if_list = filter_get_reflection_interfaces($natifname);
2274
			}
2279 2275

  
2280
				$natrules .= "binat on {$natif} {$ipproto} from {$srcaddr} to {$dstaddr} -> {$target}{$sn1}\n";
2276
			$natrules .= "binat on {$natif} {$ipproto} from {$srcaddr} to {$dstaddr} -> {$target}{$sn1}\n";
2281 2277

  
2282
				if (!empty($nat_if_list)) {
2283
					$binat_if_list = implode(" ", $nat_if_list);
2284
					$binat_if_list = "{ {$binat_if_list} }";
2285
					$reflection_txt .= "rdr on {$binat_if_list} {$ipproto} from {$dstaddr} to {$target}{$sn1} -> {$srcaddr} bitmask\n";
2286
				}
2278
			if (!empty($nat_if_list)) {
2279
				$binat_if_list = implode(" ", $nat_if_list);
2280
				$binat_if_list = "{ {$binat_if_list} }";
2281
				$reflection_txt .= "rdr on {$binat_if_list} {$ipproto} from {$dstaddr} to {$target}{$sn1} -> {$srcaddr} bitmask\n";
2287 2282
			}
2288

  
2289
			$nat_if_list = array_merge(array($natif), $nat_if_list);
2290
			$reflection_txt .= filter_generate_reflection_nat($rule, $route_table, $nat_if_list, "", $srcaddr, $srcip, $sn);
2291 2283
		}
2284

  
2285
		$nat_if_list = array_merge(array($natif), $nat_if_list);
2286
		$reflection_txt .= filter_generate_reflection_nat($rule, $route_table, $nat_if_list, "", $srcaddr, $srcip, $sn);
2292 2287
	}
2293 2288

  
2294 2289
	/* Add binat rules for Network Prefix translation */
2295
	if (is_array($config['nat']['npt'])) {
2296
		foreach ($config['nat']['npt'] as $rule) {
2297
			if (isset($rule['disabled'])) {
2298
				continue;
2299
			}
2300
			$rule['ipprotocol'] = 'inet6';
2290
	foreach (config_get_path('nat/npt', []) as $rule) {
2291
		if (isset($rule['disabled'])) {
2292
			continue;
2293
		}
2294
		$rule['ipprotocol'] = 'inet6';
2301 2295

  
2302
			if (!$rule['interface']) {
2303
				$natif = "wan";
2304
			} else {
2305
				$natif = $rule['interface'];
2306
			}
2307
			if (!isset($FilterIflist[$natif])) {
2308
				continue;
2309
			}
2296
		if (!$rule['interface']) {
2297
			$natif = "wan";
2298
		} else {
2299
			$natif = $rule['interface'];
2300
		}
2301
		if (!isset($FilterIflist[$natif])) {
2302
			continue;
2303
		}
2310 2304

  
2311
			$srcaddr = filter_generate_address($rule, 'source');
2312
			if (isset($rule['destination']['network']) && !is_subnetv6($rule['destination']['network'])) {
2313
				$dst_arr = explode("/", $rule['destination']['network']);
2314
				if (count($dst_arr) > 1) {
2315
					$track6ip = get_interface_track6ip($dst_arr[0]);
2316
					$pdsubnet = gen_subnetv6($track6ip[0], $dst_arr[1]);
2317
					$rule['destination']['address'] = $pdsubnet . "/" . $dst_arr[1];
2318
					unset($rule['destination']['network']);
2319
				}
2305
		$srcaddr = filter_generate_address($rule, 'source');
2306
		if (isset($rule['destination']['network']) && !is_subnetv6($rule['destination']['network'])) {
2307
			$dst_arr = explode("/", $rule['destination']['network']);
2308
			if (count($dst_arr) > 1) {
2309
				$track6ip = get_interface_track6ip($dst_arr[0]);
2310
				$pdsubnet = gen_subnetv6($track6ip[0], $dst_arr[1]);
2311
				$rule['destination']['address'] = $pdsubnet . "/" . $dst_arr[1];
2312
				unset($rule['destination']['network']);
2320 2313
			}
2321
			$dstaddr = filter_generate_address($rule, 'destination');
2314
		}
2315
		$dstaddr = filter_generate_address($rule, 'destination');
2322 2316

  
2323
			$srcaddr = trim($srcaddr);
2324
			$dstaddr = trim($dstaddr);
2317
		$srcaddr = trim($srcaddr);
2318
		$dstaddr = trim($dstaddr);
2325 2319

  
2326
			if (($FilterIflist[$natif]['type6'] == '6rd') || ($FilterIflist[$natif]['type6'] == '6to4')) {
2320
		if (($FilterIflist[$natif]['type6'] == '6rd') || ($FilterIflist[$natif]['type6'] == '6to4')) {
2327 2321
				$natif = $FilterIflist[$natif]['descr'] . "_STF";
2328
			} else {
2329
				$natif = $FilterIflist[$natif]['descr'];
2330
			}
2331

  
2332
			/* Do not form an invalid NPt rule.
2333
			 * See https://redmine.pfsense.org/issues/8575 */
2334
			if (!(is_subnetv6($srcaddr) || is_ipaddrv6($srcaddr)) ||
2335
			    !(is_subnetv6($dstaddr) || is_ipaddrv6($dstaddr))) {
2336
				continue;
2337
			}
2338

  
2339
			$natrules .= "binat on \${$natif} inet6 from {$srcaddr} to any -> {$dstaddr}\n";
2340
			$natrules .= "binat on \${$natif} inet6 from any to {$dstaddr} -> {$srcaddr}\n";
2322
		} else {
2323
			$natif = $FilterIflist[$natif]['descr'];
2324
		}
2341 2325

  
2326
		/* Do not form an invalid NPt rule.
2327
		 * See https://redmine.pfsense.org/issues/8575 */
2328
		if (!(is_subnetv6($srcaddr) || is_ipaddrv6($srcaddr)) ||
2329
			!(is_subnetv6($dstaddr) || is_ipaddrv6($dstaddr))) {
2330
			continue;
2342 2331
		}
2332

  
2333
		$natrules .= "binat on \${$natif} inet6 from {$srcaddr} to any -> {$dstaddr}\n";
2334
		$natrules .= "binat on \${$natif} inet6 from any to {$dstaddr} -> {$srcaddr}\n";
2343 2335
	}
2344 2336

  
2345 2337
	/* ipsec nat */
......
2347 2339
		require_once("ipsec.inc");
2348 2340
	}
2349 2341
	if (ipsec_enabled()) {
2350
		if (is_array($config['ipsec']['phase2'])) {
2351
			foreach ($config['ipsec']['phase2'] as $ph2ent) {
2352
				if ($ph2ent['mode'] != 'transport' && !empty($ph2ent['natlocalid']) && !isset($ph2ent['disabled'])) {
2353
					if (!ipsec_lookup_phase1($ph2ent, $ph1ent)) {
2354
						continue;
2355
					}
2356
					if (isset($ph1ent['disabled'])) {
2357
						continue;
2358
					}
2359
					if (!is_array($ph2ent['localid'])) {
2360
						$ph2ent['localid'] = array();
2361
					}
2362
					$ph2ent['localid']['mode'] = $ph2ent['mode'];
2363
					$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid']);
2364
					if (empty($local_subnet) || $local_subnet == "0.0.0.0/0") {
2365
						continue;
2366
					}
2367
					if (!is_subnet($local_subnet) && !is_ipaddr($local_subnet)) {
2368
						continue;
2369
					}
2370
					if (!is_array($ph2ent['natlocalid'])) {
2371
						$ph2ent['natlocalid'] = array();
2372
					}
2373
					$ph2ent['natlocalid']['mode'] = $ph2ent['mode'];
2374
					$natlocal_subnet = ipsec_idinfo_to_cidr($ph2ent['natlocalid']);
2375
					if (empty($natlocal_subnet) || $natlocal_subnet == "0.0.0.0/0") {
2376
						continue;
2377
					}
2378
					if (!is_subnet($natlocal_subnet) && !is_ipaddr($natlocal_subnet)) {
2379
						continue;
2380
					}
2381
					if (!is_array($ph2ent['remoteid'])) {
2382
						$ph2ent['remoteid'] = array();
2383
					}
2384
					$ph2ent['remoteid']['mode'] = $ph2ent['mode'];
2385
					if (!isset($ph2ent['mobile'])) {
2386
						$remote_subnet = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
2387
					} elseif (!empty($ipsec_client['pool_address'])) {
2388
						$remote_subnet = "{$ipsec_client['pool_address']}/{$ipsec_client['pool_netbits']}";
2389
					}
2390
					if (empty($remote_subnet)) {
2391
						continue;
2392
					}
2393
					if (!is_subnet($remote_subnet) && !is_ipaddr($remote_subnet)) {
2394
						continue;
2395
					}
2396
					if ($remote_subnet == "0.0.0.0/0") {
2397
						$remote_subnet = "any";
2398
					}
2399
					if (is_ipaddr($natlocal_subnet) && !is_ipaddr($local_subnet)) {
2342
		foreach (config_get_path('ipsec/phase2', []) as $ph2ent) {
2343
			if ($ph2ent['mode'] != 'transport' && !empty($ph2ent['natlocalid']) && !isset($ph2ent['disabled'])) {
2344
				if (!ipsec_lookup_phase1($ph2ent, $ph1ent)) {
2345
					continue;
2346
				}
2347
				if (isset($ph1ent['disabled'])) {
2348
					continue;
2349
				}
2350
				if (!is_array($ph2ent['localid'])) {
2351
					$ph2ent['localid'] = array();
2352
				}
2353
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
2354
				$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid']);
2355
				if (empty($local_subnet) || $local_subnet == "0.0.0.0/0") {
2356
					continue;
2357
				}
2358
				if (!is_subnet($local_subnet) && !is_ipaddr($local_subnet)) {
2359
					continue;
2360
				}
2361
				if (!is_array($ph2ent['natlocalid'])) {
2362
					$ph2ent['natlocalid'] = array();
2363
				}
2364
				$ph2ent['natlocalid']['mode'] = $ph2ent['mode'];
2365
				$natlocal_subnet = ipsec_idinfo_to_cidr($ph2ent['natlocalid']);
2366
				if (empty($natlocal_subnet) || $natlocal_subnet == "0.0.0.0/0") {
2367
					continue;
2368
				}
2369
				if (!is_subnet($natlocal_subnet) && !is_ipaddr($natlocal_subnet)) {
2370
					continue;
2371
				}
2372
				if (!is_array($ph2ent['remoteid'])) {
2373
					$ph2ent['remoteid'] = array();
2374
				}
2375
				$ph2ent['remoteid']['mode'] = $ph2ent['mode'];
2376
				if (!isset($ph2ent['mobile'])) {
2377
					$remote_subnet = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
2378
				} elseif (!empty($ipsec_client['pool_address'])) {
2379
					$remote_subnet = "{$ipsec_client['pool_address']}/{$ipsec_client['pool_netbits']}";
2380
				}
2381
				if (empty($remote_subnet)) {
2382
					continue;
2383
				}
2384
				if (!is_subnet($remote_subnet) && !is_ipaddr($remote_subnet)) {
2385
					continue;
2386
				}
2387
				if ($remote_subnet == "0.0.0.0/0") {
2388
					$remote_subnet = "any";
2389
				}
2390
				if (is_ipaddr($natlocal_subnet) && !is_ipaddr($local_subnet)) {
2391
					$nattype = "nat";
2392
				} else {
2393
					list($natnet, $natmask) = explode('/', $natlocal_subnet);
2394
					list($locnet, $locmask) = explode('/', $local_subnet);
2395
					if (intval($natmask) != intval($locmask)) {
2400 2396
						$nattype = "nat";
2401 2397
					} else {
2402
						list($natnet, $natmask) = explode('/', $natlocal_subnet);
2403
						list($locnet, $locmask) = explode('/', $local_subnet);
2404
						if (intval($natmask) != intval($locmask)) {
2405
							$nattype = "nat";
2406
						} else {
2407
							$nattype = "binat";
2408
						}
2409
						unset($natnet, $natmask, $locnet, $locmask);
2398
						$nattype = "binat";
2410 2399
					}
2411
					$natrules .= "{$nattype} on enc0 from {$local_subnet} to {$remote_subnet} -> {$natlocal_subnet}\n";
2400
					unset($natnet, $natmask, $locnet, $locmask);
2412 2401
				}
2402
				$natrules .= "{$nattype} on enc0 from {$local_subnet} to {$remote_subnet} -> {$natlocal_subnet}\n";
2413 2403
			}
2414 2404
		}
2415 2405
	}
2416 2406

  
2417
	if ($config['nat']['outbound']['mode'] == "disabled") {
2407
	$natomode = config_get_path('nat/outbound/mode');
2408
	switch ($natomode) {
2409
	case "disabled":
2418 2410
		$natrules .= "\n# Outbound NAT rules are disabled\n";
2419
	}
2420

  
2421
	if ($config['nat']['outbound']['mode'] == "advanced" || $config['nat']['outbound']['mode'] == "hybrid") {
2411
		break;
2412
	case "advanced": /* fallthrough */
2413
	case "hybrid":
2422 2414
		$natrules .= "\n# Outbound NAT rules (manual)\n";
2423 2415
		/* advanced outbound rules */
2424
		if (is_array($config['nat']['outbound']['rule'])) {
2425
			foreach ($config['nat']['outbound']['rule'] as $obent) {
2426
				if (isset($obent['disabled'])) {
2427
					continue;
2428
				}
2429
				update_filter_reload_status(sprintf(gettext("Creating advanced outbound rule %s"), $obent['descr']));
2430
				$src = alias_expand($obent['source']['network']);
2431
				if (!$src) {
2432
					$src = $obent['source']['network'];
2433
				}
2434
				$dst = alias_expand($obent['destination']['address']);
2435
				if (!$dst) {
2436
					$dst = $obent['destination']['address'];
2437
				}
2438
				if (isset($obent['destination']['not']) && !isset($obent['destination']['any'])) {
2439
					$dst = "!" . $dst;
2440
				}
2441

  
2442
				if (!$obent['interface'] || !isset($FilterIflist[$obent['interface']])) {
2443
					continue;
2444
				}
2445

  
2446
				$obtarget = ($obent['target'] == "other-subnet") ? $obent['targetip'] . '/' . $obent['targetip_subnet']: $obent['target'];
2447
				$poolopts = (is_subnet($obtarget) || is_alias($obtarget)) ? $obent['poolopts'] : "";
2416
		foreach (config_get_path('nat/outbound/rule') as $obent) {
2417
			if (isset($obent['disabled'])) {
2418
				continue;
2419
			}
2420
			update_filter_reload_status(sprintf(gettext("Creating advanced outbound rule %s"), $obent['descr']));
2421
			$src = alias_expand($obent['source']['network']);
2422
			if (!$src) {
2423
				$src = $obent['source']['network'];
2424
			}
2425
			$dst = alias_expand($obent['destination']['address']);
2426
			if (!$dst) {
2427
				$dst = $obent['destination']['address'];
2428
			}
2429
			if (isset($obent['destination']['not']) && !isset($obent['destination']['any'])) {
2430
				$dst = "!" . $dst;
2431
			}
2448 2432

  
2449
				/* pool option source-hash allows specification of an optional source-hash key */
2450
				if ($poolopts == "source-hash" && !empty($obent['source_hash_key'])) {
2451
					$poolopts = "source-hash ".$obent['source_hash_key'];
2452
				}
2433
			if (!$obent['interface'] || !isset($FilterIflist[$obent['interface']])) {
2434
				continue;
2435
			}
2453 2436

  
2454
				$natrules .= filter_nat_rules_generate_if($obent['interface'],
2455
					$obent['descr'],
2456
					$obent['ipprotocol'],
2457
					$src,
2458
					$obent['sourceport'],
2459
					$dst,
2460
					$obent['dstport'],
2461
					$obtarget,
2462
					$obent['natport'],
2463
					isset($obent['nonat']),
2464
					isset($obent['staticnatport']),
2465
					$obent['protocol'],
2466
					$poolopts
2437
			$obtarget = ($obent['target'] == "other-subnet") ? $obent['targetip'] . '/' . $obent['targetip_subnet']: $obent['target'];
2438
			$poolopts = (is_subnet($obtarget) || is_alias($obtarget)) ? $obent['poolopts'] : "";
2439

  
2440
			/* pool option source-hash allows specification of an optional source-hash key */
2441
			if ($poolopts == "source-hash" && !empty($obent['source_hash_key'])) {
2442
				$poolopts = "source-hash ".$obent['source_hash_key'];
2443
			}
2444

  
2445
			$natrules .= filter_nat_rules_generate_if(
2446
				$obent['interface'],
2447
				$obent['descr'],
2448
				$obent['ipprotocol'],
2449
				$src,
2450
				$obent['sourceport'],
2451
				$dst,
2452
				$obent['dstport'],
2453
				$obtarget,
2454
				$obent['natport'],
2455
				isset($obent['nonat']),
2456
				isset($obent['staticnatport']),
2457
				$obent['protocol'],
2458
				$poolopts
2467 2459
				);
2468
			}
2469 2460
		}
2461
		break;
2462
	default:
2463
		;//noop
2470 2464
	}
2471 2465

  
2472 2466
	/* outbound rules */
2473
	if ((!isset($config['nat']['outbound']['mode'])) ||
2474
	    ($config['nat']['outbound']['mode'] == "automatic") ||
2475
	    ($config['nat']['outbound']['mode'] == "hybrid")) {
2467
	if ((!isset($natomode)) ||
2468
	    ($natomode == "automatic") ||
2469
	    ($natomode == "hybrid")) {
2476 2470
		$natrules .= "\n# Outbound NAT rules (automatic)\n";
2477 2471
		/* standard outbound rules (one for each interface) */
2478 2472
		update_filter_reload_status(gettext("Creating outbound NAT rules"));
......
2514 2508
	$natrules .= "# TFTP proxy\n";
2515 2509
	$natrules .= "rdr-anchor \"tftp-proxy/*\"\n";
2516 2510

  
2517
	if (!empty($config['system']['tftpinterface'])) {
2518
		$tftpifs = explode(",", $config['system']['tftpinterface']);
2511
	$tftpinterface = config_get_path('system/tftpinterface');
2512
	if (!empty($tftpinterface)) {
2513
		$tftpifs = explode(",", $tftpinterface);
2519 2514
		foreach ($tftpifs as $tftpif) {
2520 2515
			if ($FilterIflist[$tftpif]) {
2521 2516
				$natrules .= "rdr pass on {$FilterIflist[$tftpif]['if']} proto udp from any to any port tftp -> 127.0.0.1 port 6969\n";
......
2527 2522
	$natrules .= filter_captiveportal_rdr();
2528 2523

  
2529 2524
	/* DIAG: add ipv6 NAT, if requested */
2530
	if ((isset($config['diag']['ipv6nat']['enable'])) &&
2531
	    (is_ipaddr($config['diag']['ipv6nat']['ipaddr'])) &&
2525
	$ipv6nataddr = config_get_path('diag/ipv6nat/ipaddr');
2526
	if (config_path_enabled('diag/ipv6nat') &&
2527
	    (is_ipaddr($ipv6nataddr)) &&
2532 2528
	    (is_array($FilterIflist['wan']))) {
2533 2529
		/* XXX: FIX ME!	 IPV6 */
2534
		$natrules .= "rdr on \${$FilterIflist['wan']['descr']} proto ipv6 from any to any -> {$config['diag']['ipv6nat']['ipaddr']}\n";
2530
		$natrules .= "rdr on \${$FilterIflist['wan']['descr']} proto ipv6 from any to any -> {$pv6nataddr}\n";
2535 2531
	}
2536 2532

  
2537 2533
	unlink_if_exists("{$g['varetc_path']}/xinetd.conf");
2538 2534
	// Open xinetd.conf write handle
2539 2535
	$xinetd_fd = fopen("{$g['varetc_path']}/xinetd.conf", "w");
2540 2536

  
2541
	if (!empty($config['system']['tftpinterface'])) {
2537
	if (!empty(config_get_path('system/tftpinterface'))) {
2542 2538
		/* add tftp helper */
2543 2539
		$ftp_proxy_entry = array(
2544 2540
			'port' => 6969,
......
2552 2548
		fwrite($xinetd_fd, xinetd_service_entry($ftp_proxy_entry));
2553 2549
	}
2554 2550

  
2555
	if (isset($config['nat']['rule'])) {
2556
		/* start reflection redirects on port 19000 of localhost */
2557
		$starting_localhost_port = 19000;
2558
		$natrules .= "# NAT Inbound Redirects\n";
2559
		$nonatrule = array();
2560
		foreach ($config['nat']['rule'] as $rule) {
2561
			update_filter_reload_status(sprintf(gettext("Creating NAT rule %s"), $rule['descr']));
2551
	/* start reflection redirects on port 19000 of localhost */
2552
	$starting_localhost_port = 19000;
2553
	$natrules .= "# NAT Inbound Redirects\n";
2554
	$nonatrule = array();
2555
	foreach (config_get_path('nat/rule', []) as $rule) {
2556
		update_filter_reload_status(sprintf(gettext("Creating NAT rule %s"), $rule['descr']));
2562 2557

  
2563
			if (isset($rule['disabled'])) {
2564
				continue;
2565
			}
2558
		if (isset($rule['disabled'])) {
2559
			continue;
2560
		}
2566 2561

  
2567
			/* if item is an alias, expand */
2568
			$dstport = array();
2569
			$dstport[0] = alias_expand($rule['destination']['port']);
2570
			if (!$dstport[0]) {
2571
				$dstport = explode("-", $rule['destination']['port']);
2562
		/* if item is an alias, expand */
2563
		$dstport = array();
2564
		$dstport[0] = alias_expand($rule['destination']['port']);
2565
		if (!$dstport[0]) {
2566
			$dstport = explode("-", $rule['destination']['port']);
2572 2567
			}
2573 2568

  
2574
			/* if item is an alias, expand */
2575
			$localport = alias_expand($rule['local-port']);
2576
			if (!$localport || $dstport[0] == $localport) {
2577
				$localport = "";
2578
			} else if (is_alias($rule['local-port'])) {
2579
				$localport = filter_expand_alias($rule['local-port']);
2580
				if ($localport) {
2581
					$localport = explode(" ", trim($localport));
2582
					$localport = $localport[0];
2583
					$localport = " port {$localport}";
2584
				}
2585
			} else if (is_alias($rule['destination']['port'])) {
2569
		/* if item is an alias, expand */
2570
		$localport = alias_expand($rule['local-port']);
2571
		if (!$localport || $dstport[0] == $localport) {
2572
			$localport = "";
2573
		} else if (is_alias($rule['local-port'])) {
2574
			$localport = filter_expand_alias($rule['local-port']);
2575
			if ($localport) {
2576
				$localport = explode(" ", trim($localport));
2577
				$localport = $localport[0];
2586 2578
				$localport = " port {$localport}";
2587
			} else {
2588
				if (($dstport[1]) && ($dstport[0] != $dstport[1])) {
2589
					$localendport = $localport + ($dstport[1] - $dstport[0]);
2579
			}
2580
		} else if (is_alias($rule['destination']['port'])) {
2581
			$localport = " port {$localport}";
2582
		} else {
2583
			if (($dstport[1]) && ($dstport[0] != $dstport[1])) {
2584
				$localendport = $localport + ($dstport[1] - $dstport[0]);
2585
				
2586
				$localport .= ":$localendport";
2587
			}
2590 2588

  
2591
					$localport .= ":$localendport";
2592
				}
2589
			$localport = " port {$localport}";
2590
		}
2593 2591

  
2594
				$localport = " port {$localport}";
2595
			}
2592
		if ($rule['ipprotocol'] == 'inet6') {
2593
			$ipproto = 'inet6';
2594
		} else {
2595
			$ipproto = 'inet';
2596
		}
2596 2597

  
2597
			if ($rule['ipprotocol'] == 'inet6') {
2598
				$ipproto = 'inet6';
2599
			} else {
2600
				$ipproto = 'inet';
2601
			}
2598
		switch (strtolower($rule['protocol'])) {
2599
		case "tcp/udp":
2600
			$protocol = "{ tcp udp }";
2601
			break;
2602
		case "tcp":
2603
		case "udp":
2604
			$protocol = strtolower($rule['protocol']);
2605
			break;
2606
		default:
2607
			$protocol = strtolower($rule['protocol']);
2608
			$localport = "";
2609
			break;
2610
		}
2602 2611

  
2603
			switch (strtolower($rule['protocol'])) {
2604
				case "tcp/udp":
2605
					$protocol = "{ tcp udp }";
2606
					break;
2607
				case "tcp":
2608
				case "udp":
2609
					$protocol = strtolower($rule['protocol']);
2610
					break;
2611
				default:
2612
					$protocol = strtolower($rule['protocol']);
2613
					$localport = "";
2614
					break;
2615
			}
2612
		if (is_ipaddr($rule['target'])) {
2613
			$target = $rule['target'];
2614
		} elseif (is_alias($rule['target'])) {
2615
			$target = alias_expand($rule['target']);
2616
		} else {
2617
			$tmprule = array();
2618
			$tmprule['localip']['network'] = $rule['target'];
2619
			$tmprule['ipprotocol'] = $ipproto;
2620
			$target = filter_generate_address($tmprule, 'localip');
2621
		}
2622
		if (!$target && !isset($rule['nordr'])) {
2623
			$natrules .= "# Unresolvable alias {$rule['target']}\n";
2624
			continue;		/* unresolvable alias */
2625
		}
2616 2626

  
2617
			if (is_ipaddr($rule['target'])) {
2618
				$target = $rule['target'];
2619
			} elseif (is_alias($rule['target'])) {
2620
				$target = alias_expand($rule['target']);
2621
			} else {
2622
				$tmprule = array();
2623
				$tmprule['localip']['network'] = $rule['target'];
2624
				$tmprule['ipprotocol'] = $ipproto;
2625
				$target = filter_generate_address($tmprule, 'localip');
2626
			}
2627
			if (!$target && !isset($rule['nordr'])) {
2628
				$natrules .= "# Unresolvable alias {$rule['target']}\n";
2629
				continue;		/* unresolvable alias */
2630
			}
2631

  
2632
			if (is_alias($rule['target'])) {
2633
				$target_ip = filter_expand_alias($rule['target']);
2634
			} else if (is_ipaddr($rule['target'])) {
2635
				$target_ip = $rule['target'];
2636
			} else if (is_ipaddr($FilterIflist[$rule['target']]['ip'])) {
2637
				$target_ip = $FilterIflist[$rule['target']]['ip'];
2638
			} else {
2639
				$target_ip = $rule['target'];
2640
			}
2641
			$target_ip = trim($target_ip);
2627
		if (is_alias($rule['target'])) {
2628
			$target_ip = filter_expand_alias($rule['target']);
2629
		} else if (is_ipaddr($rule['target'])) {
2630
			$target_ip = $rule['target'];
2631
		} else if (is_ipaddr($FilterIflist[$rule['target']]['ip'])) {
2632
			$target_ip = $FilterIflist[$rule['target']]['ip'];
2633
		} else {
2634
			$target_ip = $rule['target'];
2635
		}
2636
		$target_ip = trim($target_ip);
2642 2637

  
2643
			if ($rule['associated-rule-id'] == "pass") {
2644
				$rdrpass = "pass ";
2645
			} else {
2646
				$rdrpass = "";
2647
			}
2638
		if ($rule['associated-rule-id'] == "pass") {
2639
			$rdrpass = "pass ";
2640
		} else {
2641
			$rdrpass = "";
2642
		}
2648 2643

  
2649
			if (isset($rule['nordr'])) {
2650
				$nordr = "no ";
2651
				$rdrpass = "";
2652
			} else {
2653
				$nordr = "";
2654
			}
2644
		if (isset($rule['nordr'])) {
2645
			$nordr = "no ";
2646
			$rdrpass = "";
2647
		} else {
2648
			$nordr = "";
2649
		}
2655 2650

  
2656
			if (!$rule['interface']) {
2657
				$natif = "wan";
2658
			} else {
2659
				$natif = $rule['interface'];
2660
			}
2651
		if (!$rule['interface']) {
2652
			$natif = "wan";
2653
		} else {
2654
			$natif = $rule['interface'];
2655
		}
2661 2656

  
2662
			if (!isset($FilterIflist[$natif])) {
2663
				continue;
2664
			}
2657
		if (!isset($FilterIflist[$natif])) {
2658
			continue;
2659
		}
2665 2660

  
2666
			if (($ipproto == 'inet6') && is_stf_interface($natif)) {
2667
				$rdrif = $natif . "_stf";
2668
			} elseif ($natif == 'pppoe') {
2669
				$rdrif = 'pppoe';
2661
		if (($ipproto == 'inet6') && is_stf_interface($natif)) {
2662
			$rdrif = $natif . "_stf";
2663
		} elseif ($natif == 'pppoe') {
2664
			$rdrif = 'pppoe';
2665
		} else {
2666
			$rdrif = $FilterIflist[$natif]['if'];
2667
		}
2668

  
2669
		$srcaddr = filter_generate_address($rule, 'source', true);
2670
		$dstaddr = filter_generate_address($rule, 'destination', true);
2671
		$srcaddr = trim($srcaddr);
2672
		$dstaddr = trim($dstaddr);
2673

  
2674
		$dstaddr_port = explode(" ", $dstaddr);
2675
		if (empty($dstaddr_port[0]) || strtolower(trim($dstaddr_port[0])) == "port") {
2676
			continue; // Skip port forward if no destination address found
2677
		}
2678
		$dstaddr_reflect = $dstaddr;
2679
		$natref_disabled = config_path_enabled('system','disablenatreflection');
2680
		if (isset($rule['destination']['any']) && 
2681
			((!isset($rule['natreflection']) && !$natref_disabled) ||
2682
			 ($rule['natreflection'] == "purenat") || ($rule['natreflection'] == "enable"))) { 
2683
			/* With reflection enabled, destination of 'any' has side effects
2684
			 * that most people would not expect, so change it on reflection rules. */
2685
			
2686
			if (!empty($FilterIflist[$natif]['ip'])) {
2687
				$dstaddr_reflect = $FilterIflist[$natif]['ip'];
2670 2688
			} else {
2671
				$rdrif = $FilterIflist[$natif]['if'];
2689
				// no IP, bail
2690
				continue;
2672 2691
			}
2673 2692

  
2674
			$srcaddr = filter_generate_address($rule, 'source', true);
2675
			$dstaddr = filter_generate_address($rule, 'destination', true);
2676
			$srcaddr = trim($srcaddr);
2677
			$dstaddr = trim($dstaddr);
2678

  
2679
			$dstaddr_port = explode(" ", $dstaddr);
2680
			if (empty($dstaddr_port[0]) || strtolower(trim($dstaddr_port[0])) == "port") {
2681
				continue; // Skip port forward if no destination address found
2693
			if (!empty($FilterIflist[$natif]['sn'])) {
2694
				$dstaddr_reflect = gen_subnet($dstaddr_reflect, $FilterIflist[$natif]['sn']) . '/' . $FilterIflist[$natif]['sn'];
2682 2695
			}
2683
			$dstaddr_reflect = $dstaddr;
2684
			if (isset($rule['destination']['any']) && 
2685
			    ((!isset($rule['natreflection']) && !isset($config['system']['disablenatreflection'])) ||
2686
			    ($rule['natreflection'] == "purenat") || ($rule['natreflection'] == "enable"))) { 
2687
				/* With reflection enabled, destination of 'any' has side effects
2688
				 * that most people would not expect, so change it on reflection rules. */
2689 2696

  
2690
				if (!empty($FilterIflist[$natif]['ip'])) {
2691
					$dstaddr_reflect = $FilterIflist[$natif]['ip'];
2692
				} else {
2693
					// no IP, bail
2694
					continue;
2695
				}
2696

  
2697
				if (!empty($FilterIflist[$natif]['sn'])) {
2698
					$dstaddr_reflect = gen_subnet($dstaddr_reflect, $FilterIflist[$natif]['sn']) . '/' . $FilterIflist[$natif]['sn'];
2699
				}
2700

  
2701
				if ($dstaddr_port[count($dstaddr_port)-1]) {
2702
					$dstaddr_reflect .= " port " . $dstaddr_port[count($dstaddr_port)-1];
2703
				}
2697
			if ($dstaddr_port[count($dstaddr_port)-1]) {
2698
				$dstaddr_reflect .= " port " . $dstaddr_port[count($dstaddr_port)-1];
2704 2699
			}
2700
		}
2705 2701

  
2706
			if ($natif != 'pppoe') {
2707
				$natif = $FilterIflist[$natif]['if'];
2708
			}
2702
		if ($natif != 'pppoe') {
2703
			$natif = $FilterIflist[$natif]['if'];
2704
		}
2709 2705

  
2710
			$reflection_type = "none";
2711
			if (($rule['natreflection'] != "disable") && ($dstaddr_port[0] != "0.0.0.0") && 
2712
			    ($dstaddr_port[0] != "::")) {
2713
				if ($rule['natreflection'] == "enable") {
2714
					$reflection_type = "proxy";
2715
				} else if ($rule['natreflection'] == "purenat") {
2706
		$reflection_type = "none";
2707
		if (($rule['natreflection'] != "disable") && ($dstaddr_port[0] != "0.0.0.0") && 
2708
			($dstaddr_port[0] != "::")) {
2709
			if ($rule['natreflection'] == "enable") {
2710
				$reflection_type = "proxy";
2711
			} else if ($rule['natreflection'] == "purenat") {
2712
				$reflection_type = "purenat";
2713
			} else if (!$natref_disabled) {
2714
				if (config_path_enabled('system','enablenatreflectionpurenat')) {
2716 2715
					$reflection_type = "purenat";
2717
				} else if (!isset($config['system']['disablenatreflection'])) {
2718
					if (isset($config['system']['enablenatreflectionpurenat'])) {
2719
						$reflection_type = "purenat";
2720
					} else {
2721
						$reflection_type = "proxy";
2722
					}
2716
				} else {
2717
					$reflection_type = "proxy";
2723 2718
				}
2724 2719
			}
2720
		}
2725 2721

  
2726
			if ($reflection_type != "none") {
2727
				$nat_if_list = filter_get_reflection_interfaces($natif);
2728
			} else {
2729
				$nat_if_list = array();
2730
			}
2722
		if ($reflection_type != "none") {
2723
			$nat_if_list = filter_get_reflection_interfaces($natif);
2724
		} else {
2725
			$nat_if_list = array();
2726
		}
2731 2727

  
2732
			if (empty($nat_if_list)) {
2733
				$reflection_type = "none";
2734
			}
2728
		if (empty($nat_if_list)) {
2729
			$reflection_type = "none";
2730
		}
2735 2731

  
2736
			$localport_nat = $localport;
2737
			if (empty($localport_nat) && is_port($dstaddr_port[count($dstaddr_port)-1])) {
2738
				$localport_nat = " port " . $dstaddr_port[count($dstaddr_port)-1];
2739
			}
2732
		$localport_nat = $localport;
2733
		if (empty($localport_nat) && is_port($dstaddr_port[count($dstaddr_port)-1])) {
2734
			$localport_nat = " port " . $dstaddr_port[count($dstaddr_port)-1];
2735
		}
2740 2736

  
2741
			if ($srcaddr <> "" && $dstaddr <> "" && $natif) {
2742
				if ($protocol == 'any') {
2743
					$proto = '';
2737
		if ($srcaddr <> "" && $dstaddr <> "" && $natif) {
2738
			if ($protocol == 'any') {
2739
				$proto = '';
2740
			} else {
2741
				$proto = "proto {$protocol}";
2742
			}
2743
			$natrules .= "{$nordr}rdr {$rdrpass}on {$rdrif} {$ipproto} {$proto} from {$srcaddr} to {$dstaddr}" . ($nordr == "" ? " -> {$target}{$localport}" : "");
2744

  
2745
			/* Does this rule redirect back to a internal host? */
2746
			if (isset($rule['destination']['any'])
2747
				&& !isset($rule['nordr'])
2748
				&& !config_path_enabled('system','enablenatreflectionhelper')
2749
				&& !interface_has_gateway($rule['interface'])) {
2750
				if ($ipproto == 'inet') {
2751
					$rule_interface_ip = find_interface_ip($natif);
2752
					$rule_interface_subnet = find_interface_subnet($natif);
2744 2753
				} else {
2745
					$proto = "proto {$protocol}";
2754
					$rule_interface_ip = find_interface_ipv6($natif);
2755
					$rule_interface_subnet = find_interface_subnetv6($natif);
2746 2756
				}
2747
				$natrules .= "{$nordr}rdr {$rdrpass}on {$rdrif} {$ipproto} {$proto} from {$srcaddr} to {$dstaddr}" . ($nordr == "" ? " -> {$target}{$localport}" : "");
2748

  
2749
				/* Does this rule redirect back to a internal host? */
2750
				if (isset($rule['destination']['any']) && !isset($rule['nordr']) && !isset($config['system']['enablenatreflectionhelper']) && !interface_has_gateway($rule['interface'])) {
2751
					if ($ipproto == 'inet') {
2752
						$rule_interface_ip = find_interface_ip($natif);
2753
						$rule_interface_subnet = find_interface_subnet($natif);
2754
					} else {
2755
						$rule_interface_ip = find_interface_ipv6($natif);
2756
						$rule_interface_subnet = find_interface_subnetv6($natif);
2757
					}
2758
					if (!empty($rule_interface_ip) && !empty($rule_interface_subnet)) {
2759
						$rule_subnet = gen_subnet($rule_interface_ip, $rule_interface_subnet);
2760
						$nonatnet = $rule_subnet . '/' . $rule_interface_subnet;
2761
						$natrules .= "\n";
2762
						/* Do not generate a rule with an interface source if that interface has no IP address.
2763
						 * See https://redmine.pfsense.org/issues/8604 */
2764
						if (((($ipproto == 'inet') && !empty(get_interface_ip($natif))) ||
2765
						    (($ipproto == 'inet6') && !empty(get_interface_ipv6($natif)))) &&
2766
						    (!$nonatrule[$natif])) {
2767
							$natrules .= "no nat on {$rdrif} {$ipproto} proto tcp from ({$natif}) to {$nonatnet}\n";
2768
							$nonatrule[$natif] = true;
2769
						}
2770
						$natrules .= "nat on {$rdrif} {$ipproto} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$dstport[0]} -> ({$natif})\n";
2757
				if (!empty($rule_interface_ip) && !empty($rule_interface_subnet)) {
2758
					$rule_subnet = gen_subnet($rule_interface_ip, $rule_interface_subnet);
2759
					$nonatnet = $rule_subnet . '/' . $rule_interface_subnet;
2760
					$natrules .= "\n";
2761
					/* Do not generate a rule with an interface source if that interface has no IP address.
2762
					 * See https://redmine.pfsense.org/issues/8604 */
2763
					if (((($ipproto == 'inet') && !empty(get_interface_ip($natif))) ||
2764
					    (($ipproto == 'inet6') && !empty(get_interface_ipv6($natif)))) &&
2765
					    (!$nonatrule[$natif])) {
2766
						$natrules .= "no nat on {$rdrif} {$ipproto} proto tcp from ({$natif}) to {$nonatnet}\n";
2767
						$nonatrule[$natif] = true;
2771 2768
					}
2769
					$natrules .= "nat on {$rdrif} {$ipproto} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$dstport[0]} -> ({$natif})\n";
2772 2770
				}
2771
			}
2773 2772

  
2774
				if ($reflection_type != "none") {
2775
					if ($reflection_type == "proxy" && !isset($rule['nordr'])) {
2776
						$natrules .= filter_generate_reflection_proxy($rule, $nordr, $nat_if_list, $srcaddr, $dstaddr, $starting_localhost_port, $reflection_rules);
2777
						$nat_if_list = array($natif);
2778
						foreach ($reflection_rules as $reflection_rule) {
2779
							fwrite($xinetd_fd, xinetd_service_entry($reflection_rule));
2780
						}
2781
					} else if ($reflection_type == "purenat" || isset($rule['nordr'])) {
2782
						$rdr_if_list = implode(" ", $nat_if_list);
2783
						if (count($nat_if_list) > 1) {
2784
							$rdr_if_list = "{ {$rdr_if_list} }";
2785
						}
2786
						$natrules .= "\n# Reflection redirect\n";
2787
						$natrules .= "{$nordr}rdr {$rdrpass}on {$rdr_if_list} {$ipproto} {$proto} from {$srcaddr} to {$dstaddr_reflect}" . ($nordr == "" ? " -> {$target}{$localport}" : "");
2788
						$nat_if_list = array_merge(array($natif), $nat_if_list);
2773
			if ($reflection_type != "none") {
2774
				if ($reflection_type == "proxy" && !isset($rule['nordr'])) {
2775
					$natrules .= filter_generate_reflection_proxy($rule, $nordr, $nat_if_list, $srcaddr, $dstaddr, $starting_localhost_port, $reflection_rules);
2776
					$nat_if_list = array($natif);
2777
					foreach ($reflection_rules as $reflection_rule) {
2778
						fwrite($xinetd_fd, xinetd_service_entry($reflection_rule));
2779
					}
2780
				} else if ($reflection_type == "purenat" || isset($rule['nordr'])) {
2781
					$rdr_if_list = implode(" ", $nat_if_list);
2782
					if (count($nat_if_list) > 1) {
2783
						$rdr_if_list = "{ {$rdr_if_list} }";
2789 2784
					}
2785
					$natrules .= "\n# Reflection redirect\n";
2786
					$natrules .= "{$nordr}rdr {$rdrpass}on {$rdr_if_list} {$ipproto} {$proto} from {$srcaddr} to {$dstaddr_reflect}" . ($nordr == "" ? " -> {$target}{$localport}" : "");
2787
					$nat_if_list = array_merge(array($natif), $nat_if_list);
2790 2788
				}
2789
			}
2791 2790

  
2792
				if (empty($nat_if_list)) {
2793
					$nat_if_list = array($natif);
2794
				}
2791
			if (empty($nat_if_list)) {
2792
				$nat_if_list = array($natif);
2793
			}
2795 2794

  
2796
				$natrules .= "\n";
2797
				if (!isset($rule['nordr'])) {
2798
					$natrules .= filter_generate_reflection_nat($rule, $route_table, $nat_if_list, $protocol, "{$target}{$localport_nat}", $target_ip);
2799
				}
2795
			$natrules .= "\n";
2796
			if (!isset($rule['nordr'])) {
2797
				$natrules .= filter_generate_reflection_nat($rule, $route_table, $nat_if_list, $protocol, "{$target}{$localport_nat}", $target_ip);
2800 2798
			}
2801 2799
		}
2802 2800
	}

Also available in: Unified diff