| Total Complexity | 131 |
| Total Lines | 990 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like Network often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Network, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 35 | class Network extends Injectable |
||
| 36 | { |
||
| 37 | public const INTERNET_FLAG_FILE = '/var/etc/internet_flag'; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * Starts the SIP dump process. |
||
| 41 | */ |
||
| 42 | public static function startSipDump(): void |
||
| 61 | ); |
||
| 62 | } |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Retrieves the names of all PCI network interfaces. |
||
| 67 | * |
||
| 68 | * @return array An array containing the names of the network interfaces. |
||
| 69 | */ |
||
| 70 | public function getInterfacesNames(): array |
||
| 84 | } |
||
| 85 | |||
| 86 | /** |
||
| 87 | * Configures the LAN settings inside the Docker container. |
||
| 88 | * |
||
| 89 | * If the environment is not Docker, this method does nothing. |
||
| 90 | * |
||
| 91 | * @return void |
||
| 92 | */ |
||
| 93 | public function configureLanInDocker(): void |
||
| 94 | { |
||
| 95 | // Check if the environment is Docker |
||
| 96 | if (!Util::isDocker()) { |
||
| 97 | return; |
||
| 98 | } |
||
| 99 | |||
| 100 | // Find the path to the busybox binary |
||
| 101 | $ifconfig = Util::which('ifconfig'); |
||
| 102 | $route = Util::which('route'); |
||
| 103 | $awk = Util::which('awk'); |
||
| 104 | $hostname = Util::which('hostname'); |
||
| 105 | |||
| 106 | // Retrieve the network settings |
||
| 107 | $networks = $this->getGeneralNetSettings(); |
||
| 108 | |||
| 109 | foreach ($networks as $if_data) { |
||
| 110 | |||
| 111 | $if_name = $if_data['interface']; |
||
| 112 | $if_name = escapeshellcmd(trim($if_name)); |
||
| 113 | |||
| 114 | $commands = [ |
||
| 115 | 'subnet' => $ifconfig . ' '.$if_name.' | '.$awk.' \'/Mask:/ {sub("Mask:", "", $NF); print $NF}\'', |
||
| 116 | 'ipaddr' => $ifconfig . ' '.$if_name.' | '.$awk.' \'/inet / {sub("addr:", "", $2); print $2}\'', |
||
| 117 | 'gateway' => $route . ' -n | '.$awk.' \'/^0.0.0.0/ {print $2}\'', |
||
| 118 | 'hostname' => $hostname, |
||
| 119 | ]; |
||
| 120 | |||
| 121 | $data = []; |
||
| 122 | foreach ($commands as $key => $command) { |
||
| 123 | $output = []; |
||
| 124 | if (Processes::MWExec($command, $output) === 0) { |
||
| 125 | $value = implode("", $output); |
||
| 126 | if ($key === 'subnet') { |
||
| 127 | $data[$key] = $this->netMaskToCidr($value); |
||
| 128 | } else { |
||
| 129 | $data[$key] = $value; |
||
| 130 | } |
||
| 131 | } |
||
| 132 | } |
||
| 133 | |||
| 134 | // Save information to the database. |
||
| 135 | $this->updateIfSettings($data, $if_name); |
||
| 136 | } |
||
| 137 | |||
| 138 | } |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Retrieves the general network settings and performs additional processing. |
||
| 142 | * |
||
| 143 | * @return array An array of network interfaces and their settings. |
||
| 144 | */ |
||
| 145 | public function getGeneralNetSettings(): array |
||
| 146 | { |
||
| 147 | // Get the list of network interfaces visible to the operating system |
||
| 148 | $src_array_eth = $this->getInterfacesNames(); |
||
| 149 | |||
| 150 | // Create a copy of the network interfaces array |
||
| 151 | $array_eth = $src_array_eth; |
||
| 152 | |||
| 153 | // Retrieve the LAN interface settings from the database |
||
| 154 | $res = LanInterfaces::find(['order' => 'interface,vlanid']); |
||
| 155 | $networks = $res->toArray(); |
||
| 156 | |||
| 157 | if (count($networks) > 0) { |
||
| 158 | // Additional data processing |
||
| 159 | foreach ($networks as &$if_data) { |
||
| 160 | $if_data['interface_orign'] = $if_data['interface']; |
||
| 161 | $if_data['interface'] = ($if_data['vlanid'] > 0) ? "vlan{$if_data['vlanid']}" : $if_data['interface']; |
||
| 162 | $if_data['dhcp'] = ($if_data['vlanid'] > 0) ? 0 : $if_data['dhcp']; |
||
| 163 | |||
| 164 | if (Verify::isIpAddress($if_data['subnet'])) { |
||
| 165 | $if_data['subnet'] = $this->netMaskToCidr($if_data['subnet']); |
||
| 166 | } |
||
| 167 | |||
| 168 | $key = array_search($if_data['interface_orign'], $src_array_eth, true); |
||
| 169 | if ($key !== false) { |
||
| 170 | // Interface found |
||
| 171 | // Remove the array element if it's not a VLAN |
||
| 172 | if ($if_data['vlanid'] === '0') { |
||
| 173 | unset($array_eth[$key]); |
||
| 174 | $this->enableLanInterface($if_data['interface_orign']); |
||
| 175 | } |
||
| 176 | } else { |
||
| 177 | // Interface does not exist |
||
| 178 | $this->disableLanInterface($if_data['interface_orign']); |
||
| 179 | // Disable the interface |
||
| 180 | $if_data['disabled'] = 1; |
||
| 181 | } |
||
| 182 | } |
||
| 183 | unset($if_data); |
||
| 184 | } elseif (count($array_eth) > 0) { |
||
| 185 | $networks = []; |
||
| 186 | // Configure the main interface |
||
| 187 | $networks[] = $this->addLanInterface($array_eth[0], true); |
||
| 188 | unset($array_eth[0]); |
||
| 189 | } |
||
| 190 | // $array_eth will contain only the elements without settings in the database |
||
| 191 | // Add the "default" settings for these interfaces |
||
| 192 | foreach ($array_eth as $eth) { |
||
| 193 | // Add the interface and disable it |
||
| 194 | $networks[] = $this->addLanInterface($eth, false); |
||
| 195 | } |
||
| 196 | |||
| 197 | // Check if there is an active internet interface, if not, set the first available interface as internet |
||
| 198 | $res = LanInterfaces::findFirst("internet = '1' AND disabled='0'"); |
||
| 199 | if (null === $res) { |
||
| 200 | /** @var LanInterfaces $eth_settings */ |
||
| 201 | $eth_settings = LanInterfaces::findFirst("disabled='0'"); |
||
| 202 | if ($eth_settings !== null) { |
||
| 203 | $eth_settings->internet = 1; |
||
| 204 | $eth_settings->save(); |
||
| 205 | } |
||
| 206 | } |
||
| 207 | |||
| 208 | return $networks; |
||
| 209 | } |
||
| 210 | |||
| 211 | /** |
||
| 212 | * Converts a net mask to CIDR notation. |
||
| 213 | * |
||
| 214 | * @param string $net_mask The net mask to convert. |
||
| 215 | * @return int The CIDR notation. |
||
| 216 | */ |
||
| 217 | public function netMaskToCidr(string $net_mask): int |
||
| 218 | { |
||
| 219 | $bits = 0; |
||
| 220 | $net_mask = explode(".", $net_mask); |
||
| 221 | |||
| 222 | foreach ($net_mask as $oct_ect) { |
||
| 223 | $bits += strlen(str_replace("0", "", decbin((int)$oct_ect))); |
||
| 224 | } |
||
| 225 | |||
| 226 | return $bits; |
||
| 227 | } |
||
| 228 | |||
| 229 | /** |
||
| 230 | * Enables a LAN interface |
||
| 231 | * |
||
| 232 | * @param string $name The name of the interface to enable. |
||
| 233 | * @return void |
||
| 234 | */ |
||
| 235 | public function enableLanInterface(string $name): void |
||
| 236 | { |
||
| 237 | $parameters = [ |
||
| 238 | 'conditions' => 'interface = :ifName: and disabled = :disabled:', |
||
| 239 | 'bind' => [ |
||
| 240 | 'ifName' => $name, |
||
| 241 | 'disabled' => 1, |
||
| 242 | ], |
||
| 243 | ]; |
||
| 244 | |||
| 245 | $if_data = LanInterfaces::findFirst($parameters); |
||
| 246 | if ($if_data !== null) { |
||
| 247 | $if_data->disabled = 0; |
||
| 248 | $if_data->update(); |
||
| 249 | } |
||
| 250 | } |
||
| 251 | |||
| 252 | /** |
||
| 253 | * Disables a LAN interface by setting its internet flag to 0 and disabled flag to 1. |
||
| 254 | * |
||
| 255 | * @param string $name The name of the interface to disable. |
||
| 256 | * @return void |
||
| 257 | */ |
||
| 258 | public function disableLanInterface(string $name): void |
||
| 259 | { |
||
| 260 | $if_data = LanInterfaces::findFirst("interface = '{$name}'"); |
||
| 261 | if ($if_data !== null) { |
||
| 262 | $if_data->internet = 0; |
||
| 263 | $if_data->disabled = 1; |
||
| 264 | $if_data->update(); |
||
| 265 | } |
||
| 266 | } |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Adds a LAN interface with the specified name and settings. |
||
| 270 | * |
||
| 271 | * @param string $name The name of the interface. |
||
| 272 | * @param bool $general Flag indicating if the interface is a general interface. |
||
| 273 | * @return array The array representation of the added interface. |
||
| 274 | */ |
||
| 275 | private function addLanInterface(string $name, bool $general = false): array |
||
| 276 | { |
||
| 277 | $data = new LanInterfaces(); |
||
| 278 | $data->name = $name; |
||
| 279 | $data->interface = $name; |
||
| 280 | $data->dhcp = '1'; |
||
| 281 | $data->internet = ($general === true) ? '1' : '0'; |
||
| 282 | $data->disabled = '0'; |
||
| 283 | $data->vlanid = '0'; |
||
| 284 | $data->hostname = 'MikoPBX'; |
||
| 285 | $data->domain = ''; |
||
| 286 | $data->topology = LanInterfaces::TOPOLOGY_PRIVATE; |
||
| 287 | $data->autoUpdateExtIp = ($general === true) ? '1' : '0';; |
||
| 288 | $data->primarydns = ''; |
||
| 289 | $data->save(); |
||
| 290 | |||
| 291 | return $data->toArray(); |
||
| 292 | } |
||
| 293 | |||
| 294 | /** |
||
| 295 | * Updates the interface settings with the provided data. |
||
| 296 | * |
||
| 297 | * @param array $data The data to update the interface settings with. |
||
| 298 | * @param string $name The name of the interface. |
||
| 299 | * |
||
| 300 | * @return void; |
||
| 301 | */ |
||
| 302 | public function updateIfSettings(array $data, string $name): void |
||
| 303 | { |
||
| 304 | /** @var LanInterfaces $res */ |
||
| 305 | $res = LanInterfaces::findFirst("interface = '$name' AND vlanid=0"); |
||
| 306 | if ($res === null || !$this->settingsIsChange($data, $res->toArray())) { |
||
| 307 | return; |
||
| 308 | } |
||
| 309 | foreach ($data as $key => $value) { |
||
| 310 | $res->writeAttribute($key, $value); |
||
| 311 | } |
||
| 312 | $res->save(); |
||
| 313 | } |
||
| 314 | |||
| 315 | /** |
||
| 316 | * Checks if the network settings have changed. |
||
| 317 | * |
||
| 318 | * @param array $data The new network settings. |
||
| 319 | * @param array $dbData The existing network settings from the database. |
||
| 320 | * |
||
| 321 | * @return bool Returns true if the settings have changed, false otherwise. |
||
| 322 | */ |
||
| 323 | public function settingsIsChange(array $data, array $dbData): bool |
||
| 324 | { |
||
| 325 | $isChange = false; |
||
| 326 | foreach ($dbData as $key => $value) { |
||
| 327 | if (!isset($data[$key]) || (string)$value === (string)$data[$key]) { |
||
| 328 | continue; |
||
| 329 | } |
||
| 330 | SystemMessages::sysLogMsg(__METHOD__, "Find new network settings: {$key} changed {$value}=>{$data[$key]}"); |
||
| 331 | $isChange = true; |
||
| 332 | } |
||
| 333 | return $isChange; |
||
| 334 | } |
||
| 335 | |||
| 336 | /** |
||
| 337 | * Updates the DNS settings with the provided data. |
||
| 338 | * |
||
| 339 | * @param array $data The data to update the DNS settings with. |
||
| 340 | * @param string $name The name of the interface. |
||
| 341 | * |
||
| 342 | * @return void |
||
| 343 | */ |
||
| 344 | public function updateDnsSettings(array $data, string $name): void |
||
| 345 | { |
||
| 346 | /** @var LanInterfaces $res */ |
||
| 347 | $res = LanInterfaces::findFirst("interface = '$name' AND vlanid=0"); |
||
| 348 | if ($res === null || !$this->settingsIsChange($data, $res->toArray())) { |
||
| 349 | return; |
||
| 350 | } |
||
| 351 | foreach ($data as $key => $value) { |
||
| 352 | $res->writeAttribute($key, $value); |
||
| 353 | } |
||
| 354 | if (empty($res->primarydns) && !empty($res->secondarydns)) { |
||
| 355 | // Swap primary and secondary DNS if primary is empty |
||
| 356 | $res->primarydns = $res->secondarydns; |
||
| 357 | $res->secondarydns = ''; |
||
| 358 | } |
||
| 359 | $res->save(); |
||
| 360 | } |
||
| 361 | |||
| 362 | /** |
||
| 363 | * Retrieves the interface name by its ID. |
||
| 364 | * |
||
| 365 | * @param string $id_net The ID of the network interface. |
||
| 366 | * |
||
| 367 | * @return string The interface name. |
||
| 368 | */ |
||
| 369 | public function getInterfaceNameById(string $id_net): string |
||
| 370 | { |
||
| 371 | $res = LanInterfaces::findFirstById($id_net); |
||
| 372 | if ($res !== null && $res->interface !== null) { |
||
| 373 | return $res->interface; |
||
| 374 | } |
||
| 375 | |||
| 376 | return ''; |
||
| 377 | } |
||
| 378 | |||
| 379 | /** |
||
| 380 | * Retrieves the enabled LAN interfaces. |
||
| 381 | * |
||
| 382 | * @return array An array of enabled LAN interfaces. |
||
| 383 | */ |
||
| 384 | public function getEnabledLanInterfaces(): array |
||
| 385 | { |
||
| 386 | /** @var LanInterfaces $res */ |
||
| 387 | $res = LanInterfaces::find('disabled=0'); |
||
| 388 | |||
| 389 | return $res->toArray(); |
||
| 390 | } |
||
| 391 | |||
| 392 | /** |
||
| 393 | * Updates the network settings with the provided data. |
||
| 394 | * @param array $data The network settings data to update. |
||
| 395 | */ |
||
| 396 | public function updateNetSettings(array $data): void |
||
| 397 | { |
||
| 398 | $res = LanInterfaces::findFirst("internet = '1'"); |
||
| 399 | $update_inet = false; |
||
| 400 | if ($res === null) { |
||
| 401 | // If no interface with internet connection is found, get the first interface. |
||
| 402 | $res = LanInterfaces::findFirst(); |
||
| 403 | $update_inet = true; |
||
| 404 | } |
||
| 405 | |||
| 406 | if ($res !== null) { |
||
| 407 | foreach ($data as $key => $value) { |
||
| 408 | $res->$key = $value; |
||
| 409 | } |
||
| 410 | if ($update_inet === true) { |
||
| 411 | $res->internet = 1; |
||
| 412 | } |
||
| 413 | $res->save(); |
||
| 414 | } |
||
| 415 | } |
||
| 416 | |||
| 417 | /** |
||
| 418 | * Update external IP address |
||
| 419 | */ |
||
| 420 | public function updateExternalIp(): void |
||
| 421 | { |
||
| 422 | $ipInfoResult = GetExternalIpInfoAction::main(); |
||
| 423 | if ($ipInfoResult->success && isset($ipInfoResult->data['ip'])) { |
||
| 424 | $currentIP = $ipInfoResult->data['ip']; |
||
| 425 | $lanData = LanInterfaces::find('autoUpdateExtIp=1'); |
||
| 426 | foreach ($lanData as $lan) { |
||
| 427 | $oldExtIp = $lan->extipaddr; |
||
| 428 | $parts = explode(':', $oldExtIp); |
||
| 429 | $oldIP = $parts[0]; // Only IP part of the address |
||
| 430 | $port = isset($parts[1]) ? ':' . $parts[1] : ''; |
||
| 431 | if ($oldIP !== $currentIP) { |
||
| 432 | $newExtIp = $currentIP . $port; |
||
| 433 | $lan->extipaddr = $newExtIp; |
||
| 434 | if ($lan->save()) { |
||
| 435 | SystemMessages::sysLogMsg(__METHOD__, "External IP address updated for interface {$lan->interface}"); |
||
| 436 | } |
||
| 437 | } |
||
| 438 | } |
||
| 439 | } |
||
| 440 | } |
||
| 441 | |||
| 442 | /** |
||
| 443 | * Execute cli command to set up network |
||
| 444 | * @param string $action Action to perform (start or stop) |
||
| 445 | * @return void |
||
| 446 | */ |
||
| 447 | public function cliAction(string $action): void |
||
| 494 | } |
||
| 495 | } |
||
| 496 | } |
||
| 497 | |||
| 498 | /** |
||
| 499 | * Generates the resolv.conf file based on system configuration. |
||
| 500 | */ |
||
| 501 | public function resolvConfGenerate(): void |
||
| 502 | { |
||
| 503 | if (Util::isDocker()) { |
||
| 504 | return; |
||
| 505 | } |
||
| 506 | |||
| 507 | // Initialize resolv.conf content |
||
| 508 | $resolv_conf = ''; |
||
| 509 | |||
| 510 | // Get hostname information |
||
| 511 | $data_hostname = self::getHostName(); |
||
| 512 | |||
| 513 | // Append domain to resolv.conf if it is not empty |
||
| 514 | if (trim($data_hostname['domain']) !== '') { |
||
| 515 | $resolv_conf .= "domain {$data_hostname['domain']}\n"; |
||
| 516 | } |
||
| 517 | |||
| 518 | // Append local nameserver to resolv.conf |
||
| 519 | $resolv_conf .= "nameserver 127.0.0.1\n"; |
||
| 520 | |||
| 521 | // Initialize an array to store named DNS servers |
||
| 522 | $named_dns = []; |
||
| 523 | |||
| 524 | // Retrieve host DNS settings |
||
| 525 | $dns = $this->getHostDNS(); |
||
| 526 | |||
| 527 | // Iterate over each DNS server |
||
| 528 | foreach ($dns as $ns) { |
||
| 529 | // Skip empty DNS servers |
||
| 530 | if (trim($ns) === '') { |
||
| 531 | continue; |
||
| 532 | } |
||
| 533 | // Add the DNS server to the named_dns array |
||
| 534 | $named_dns[] = $ns; |
||
| 535 | |||
| 536 | // Append the DNS server to resolv.conf |
||
| 537 | $resolv_conf .= "nameserver {$ns}\n"; |
||
| 538 | } |
||
| 539 | |||
| 540 | // If no DNS servers were found, use default ones and add them to named_dns |
||
| 541 | if (count($dns) === 0) { |
||
| 542 | $resolv_conf .= "nameserver 4.4.4.4\n"; |
||
| 543 | $named_dns[] .= "8.8.8.8"; |
||
| 544 | } |
||
| 545 | |||
| 546 | // Check if systemctl is available |
||
| 547 | if (Util::isSystemctl()) { |
||
| 548 | |||
| 549 | // Generate resolved.conf content for systemd-resolved |
||
| 550 | $s_resolv_conf = "[Resolve]\n" |
||
| 551 | . "DNS=127.0.0.1\n"; |
||
| 552 | |||
| 553 | // Append domain to resolved.conf if it is not empty |
||
| 554 | if (trim($data_hostname['domain']) !== '') { |
||
| 555 | $s_resolv_conf .= "Domains={$data_hostname['domain']}\n"; |
||
| 556 | } |
||
| 557 | |||
| 558 | // Write resolved.conf content to the file |
||
| 559 | file_put_contents('/etc/systemd/resolved.conf', $s_resolv_conf); |
||
| 560 | |||
| 561 | // Restart systemd-resolved service |
||
| 562 | $systemctlPath = Util::which('systemctl'); |
||
| 563 | Processes::mwExec("{$systemctlPath} restart systemd-resolved"); |
||
| 564 | } else { |
||
| 565 | // Write resolv.conf content to the file |
||
| 566 | file_put_contents('/etc/resolv.conf', $resolv_conf); |
||
| 567 | } |
||
| 568 | |||
| 569 | // Generate pdnsd configuration using named_dns |
||
| 570 | $this->generatePdnsdConfig($named_dns); |
||
| 571 | } |
||
| 572 | |||
| 573 | /** |
||
| 574 | * Retrieves the hostname and domain information. |
||
| 575 | * |
||
| 576 | * @return array An array containing the hostname and domain. |
||
| 577 | */ |
||
| 578 | public static function getHostName(): array |
||
| 579 | { |
||
| 580 | // Initialize default hostname and domain |
||
| 581 | $data = [ |
||
| 582 | 'hostname' => 'mikopbx', |
||
| 583 | 'domain' => '', |
||
| 584 | ]; |
||
| 585 | |||
| 586 | // Find the first LanInterfaces record with internet set to '1' |
||
| 587 | /** @var LanInterfaces $res */ |
||
| 588 | $res = LanInterfaces::findFirst("internet = '1'"); |
||
| 589 | |||
| 590 | // If a matching record is found, update the hostname and domain |
||
| 591 | if (null !== $res) { |
||
| 592 | $data['hostname'] = $res->hostname; |
||
| 593 | $data['domain'] = $res->domain; |
||
| 594 | } |
||
| 595 | |||
| 596 | // If the hostname is empty, set it to the default value 'mikopbx' |
||
| 597 | $data['hostname'] = (empty($data['hostname'])) ? 'mikopbx' : $data['hostname']; |
||
| 598 | |||
| 599 | return $data; |
||
| 600 | } |
||
| 601 | |||
| 602 | /** |
||
| 603 | * Retrieves the DNS servers configured for the host. |
||
| 604 | * |
||
| 605 | * @return array An array containing the DNS servers. |
||
| 606 | */ |
||
| 607 | public function getHostDNS(): array |
||
| 608 | { |
||
| 609 | $dns = []; |
||
| 610 | |||
| 611 | // Find the first LanInterfaces record with internet set to '1' |
||
| 612 | /** @var LanInterfaces $res */ |
||
| 613 | $res = LanInterfaces::findFirst("internet = '1'"); |
||
| 614 | |||
| 615 | // If a matching record is found, check and add primary and secondary DNS servers |
||
| 616 | if (null !== $res) { |
||
| 617 | // Check and add primary DNS server if not empty and not '127.0.0.1' |
||
| 618 | if (!empty($res->primarydns) && '127.0.0.1' !== $res->primarydns) { |
||
| 619 | $dns[] = $res->primarydns; |
||
| 620 | } |
||
| 621 | // Check and add secondary DNS server if not empty and not '127.0.0.1' |
||
| 622 | if (!empty($res->secondarydns) && '127.0.0.1' !== $res->secondarydns) { |
||
| 623 | $dns[] = $res->secondarydns; |
||
| 624 | } |
||
| 625 | } |
||
| 626 | |||
| 627 | return $dns; |
||
| 628 | } |
||
| 629 | |||
| 630 | /** |
||
| 631 | * Generates the pdnsd configuration file and restarts the pdnsd service if necessary. |
||
| 632 | * |
||
| 633 | * @param array $named_dns An array of named DNS servers. |
||
| 634 | */ |
||
| 635 | public function generatePdnsdConfig(array $named_dns): void |
||
| 636 | { |
||
| 637 | $tempDir = $this->di->getShared('config')->path('core.tempDir'); |
||
| 638 | $cache_dir = $tempDir . '/pdnsd/cache'; |
||
| 639 | Util::mwMkdir($cache_dir); |
||
| 640 | |||
| 641 | $conf = 'global {' . "\n" . |
||
| 642 | ' perm_cache=10240;' . "\n" . |
||
| 643 | ' cache_dir="' . $cache_dir . '";' . "\n" . |
||
| 644 | ' pid_file = /var/run/pdnsd.pid;' . "\n" . |
||
| 645 | ' run_as="nobody";' . "\n" . |
||
| 646 | ' server_ip = 127.0.0.1;' . "\n" . |
||
| 647 | ' status_ctl = on;' . "\n" . |
||
| 648 | ' query_method=udp_tcp;' . "\n" . |
||
| 649 | ' min_ttl=15m;' . "\n" . |
||
| 650 | ' max_ttl=1w;' . "\n" . |
||
| 651 | ' timeout=10;' . "\n" . |
||
| 652 | ' neg_domain_pol=on;' . "\n" . |
||
| 653 | ' run_as=root;' . "\n" . |
||
| 654 | ' daemon=on;' . "\n" . |
||
| 655 | '}' . "\n" . |
||
| 656 | 'server {' . "\n" . |
||
| 657 | ' label = "main";' . "\n" . |
||
| 658 | ' ip = ' . implode(', ', $named_dns) . ';' . "\n" . |
||
| 659 | ' interface=lo;' . "\n" . |
||
| 660 | ' uptest=if;' . "\n" . |
||
| 661 | ' interval=10m;' . "\n" . |
||
| 662 | ' purge_cache=off;' . "\n" . |
||
| 663 | '}'; |
||
| 664 | |||
| 665 | $pdnsdConfFile = '/etc/pdnsd.conf'; |
||
| 666 | |||
| 667 | // Update the pdnsd.conf file if it has changed |
||
| 668 | $savedConf = ''; |
||
| 669 | if (file_exists($pdnsdConfFile)) { |
||
| 670 | $savedConf = file_get_contents($pdnsdConfFile); |
||
| 671 | } |
||
| 672 | if ($savedConf !== $conf) { |
||
| 673 | file_put_contents($pdnsdConfFile, $conf); |
||
| 674 | } |
||
| 675 | $pdnsdPath = Util::which('pdnsd'); |
||
| 676 | $pid = Processes::getPidOfProcess($pdnsdPath); |
||
| 677 | |||
| 678 | // Check if pdnsd process is running and the configuration has not changed |
||
| 679 | if (!empty($pid) && $savedConf === $conf) { |
||
| 680 | |||
| 681 | // Perform additional check if the DNS server is working |
||
| 682 | $resultResolve = gethostbynamel('lic.miko.ru'); |
||
| 683 | if ($resultResolve !== false) { |
||
| 684 | // Configuration has not changed and the DNS server is working, |
||
| 685 | // no need to restart or reload the service |
||
| 686 | return; |
||
| 687 | } |
||
| 688 | // Perform a reload of the DNS server |
||
| 689 | } |
||
| 690 | |||
| 691 | // If pdnsd process is running, terminate the process |
||
| 692 | if (!empty($pid)) { |
||
| 693 | $kill = Util::which('kill'); |
||
| 694 | Processes::mwExec("$kill '$pid'"); |
||
| 695 | } |
||
| 696 | |||
| 697 | // Start the pdnsd service with the updated configuration |
||
| 698 | Processes::mwExec("{$pdnsdPath} -c /etc/pdnsd.conf -4"); |
||
| 699 | } |
||
| 700 | |||
| 701 | /** |
||
| 702 | * Configures the loopback interface (lo) with the IP address 127.0.0.1. |
||
| 703 | * |
||
| 704 | * @return void |
||
| 705 | */ |
||
| 706 | public function loConfigure(): void |
||
| 707 | { |
||
| 708 | $ifconfig = Util::which('ifconfig'); |
||
| 709 | Processes::mwExec("$ifconfig lo 127.0.0.1"); |
||
| 710 | } |
||
| 711 | |||
| 712 | /** |
||
| 713 | * Configures the LAN interfaces and performs related network operations. |
||
| 714 | * |
||
| 715 | * @return int The result of the configuration process. |
||
| 716 | */ |
||
| 717 | public function lanConfigure(): int |
||
| 718 | { |
||
| 719 | if (Util::isDocker()) { |
||
| 720 | return 0; |
||
| 721 | } |
||
| 722 | |||
| 723 | // Retrieve the network settings |
||
| 724 | $networks = $this->getGeneralNetSettings(); |
||
| 725 | |||
| 726 | // Retrieve the paths of required commands |
||
| 727 | $vconfig = Util::which('vconfig'); |
||
| 728 | $killall = Util::which('killall'); |
||
| 729 | $ifconfig = Util::which('ifconfig'); |
||
| 730 | |||
| 731 | |||
| 732 | $arr_commands = []; |
||
| 733 | $arr_commands[] = "$killall udhcpc"; |
||
| 734 | $eth_mtu = []; |
||
| 735 | foreach ($networks as $if_data) { |
||
| 736 | if ($if_data['disabled'] === '1') { |
||
| 737 | continue; |
||
| 738 | } |
||
| 739 | |||
| 740 | $if_name = $if_data['interface']; |
||
| 741 | $if_name = escapeshellcmd(trim($if_name)); |
||
| 742 | if (empty($if_name)) { |
||
| 743 | continue; |
||
| 744 | } |
||
| 745 | |||
| 746 | $data_hostname = self::getHostName(); |
||
| 747 | $hostname = $data_hostname['hostname']; |
||
| 748 | |||
| 749 | if ($if_data['vlanid'] > 0) { |
||
| 750 | // Override the interface name for VLAN interfaces |
||
| 751 | $arr_commands[] = "$vconfig set_name_type VLAN_PLUS_VID_NO_PAD"; |
||
| 752 | // Add the new VLAN interface |
||
| 753 | $arr_commands[] = "$vconfig add {$if_data['interface_orign']} {$if_data['vlanid']}"; |
||
| 754 | } |
||
| 755 | // Disable and reset the interface |
||
| 756 | $arr_commands[] = "$ifconfig $if_name down"; |
||
| 757 | $arr_commands[] = "$ifconfig $if_name 0.0.0.0"; |
||
| 758 | |||
| 759 | $gw_param = ''; |
||
| 760 | if (trim($if_data['dhcp']) === '1') { |
||
| 761 | // DHCP configuration |
||
| 762 | /* |
||
| 763 | * -t - number of attempts. |
||
| 764 | * -T - timeout for each attempt. |
||
| 765 | * -v - enable debugging. |
||
| 766 | * -S - log messages to syslog. |
||
| 767 | * -q - exit after obtaining lease. |
||
| 768 | * -n - exit if lease is not obtained. |
||
| 769 | */ |
||
| 770 | $pid_file = "/var/run/udhcpc_{$if_name}"; |
||
| 771 | $pid_pcc = Processes::getPidOfProcess($pid_file); |
||
| 772 | if (!empty($pid_pcc) && file_exists($pid_file)) { |
||
| 773 | // Terminate the old udhcpc process |
||
| 774 | $kill = Util::which('kill'); |
||
| 775 | $cat = Util::which('cat'); |
||
| 776 | system("$kill `$cat {$pid_file}` {$pid_pcc}"); |
||
| 777 | } |
||
| 778 | $udhcpc = Util::which('udhcpc'); |
||
| 779 | $nohup = Util::which('nohup'); |
||
| 780 | |||
| 781 | // Obtain IP and wait for the process to finish |
||
| 782 | $workerPath = '/etc/rc/udhcpc_configure'; |
||
| 783 | $options = '-t 6 -T 5 -q -n'; |
||
| 784 | $arr_commands[] = "$udhcpc $options -i $if_name -x hostname:$hostname -s $workerPath"; |
||
| 785 | // Start a new udhcpc process in the background |
||
| 786 | $options = '-t 6 -T 5 -S -b -n'; |
||
| 787 | $arr_commands[] = "$nohup $udhcpc $options -p {$pid_file} -i $if_name -x hostname:$hostname -s $workerPath 2>&1 &"; |
||
| 788 | /* |
||
| 789 | udhcpc - utility for configuring the interface |
||
| 790 | - configures /etc/resolv.conf |
||
| 791 | Further route configuration will be performed in udhcpcConfigureRenewBound(); |
||
| 792 | and udhcpcConfigureDeconfig(). These methods will be called by the script WorkerUdhcpcConfigure.php. |
||
| 793 | // man udhcp |
||
| 794 | // http://pwet.fr/man/linux/administration_systeme/udhcpc/ |
||
| 795 | |||
| 796 | */ |
||
| 797 | } else { |
||
| 798 | // Static IP configuration |
||
| 799 | $ipaddr = trim($if_data['ipaddr']); |
||
| 800 | $subnet = trim($if_data['subnet']); |
||
| 801 | $gateway = trim($if_data['gateway']); |
||
| 802 | if (empty($ipaddr)) { |
||
| 803 | continue; |
||
| 804 | } |
||
| 805 | try { |
||
| 806 | // Calculate the short subnet mask |
||
| 807 | $calc_subnet = new SubnetCalculator($ipaddr, $subnet); |
||
| 808 | $subnet = $calc_subnet->getSubnetMask(); |
||
| 809 | } catch (Throwable $e) { |
||
| 810 | echo "Caught exception: $ipaddr $subnet", $e->getMessage(), "\n"; |
||
| 811 | continue; |
||
| 812 | } |
||
| 813 | |||
| 814 | $ifconfig = Util::which('ifconfig'); |
||
| 815 | $arr_commands[] = "$ifconfig $if_name $ipaddr netmask $subnet"; |
||
| 816 | |||
| 817 | if ("" !== trim($gateway)) { |
||
| 818 | $gw_param = "gw $gateway"; |
||
| 819 | } |
||
| 820 | |||
| 821 | $route = Util::which('route'); |
||
| 822 | $arr_commands[] = "$route del default $if_name"; |
||
| 823 | |||
| 824 | /** @var LanInterfaces $if_data */ |
||
| 825 | $if_data = LanInterfaces::findFirst("id = '{$if_data['id']}'"); |
||
| 826 | $is_inet = ($if_data !== null) ? (string)$if_data->internet : '0'; |
||
| 827 | |||
| 828 | if ($is_inet === '1') { |
||
| 829 | // Create default route only if the interface is for internet |
||
| 830 | $arr_commands[] = "$route add default $gw_param dev $if_name"; |
||
| 831 | } |
||
| 832 | // Bring up the interface |
||
| 833 | $arr_commands[] = "$ifconfig $if_name up"; |
||
| 834 | |||
| 835 | $eth_mtu[] = $if_name; |
||
| 836 | } |
||
| 837 | } |
||
| 838 | $out = null; |
||
| 839 | Processes::mwExecCommands($arr_commands, $out, 'net'); |
||
| 840 | $this->hostsGenerate(); |
||
| 841 | |||
| 842 | foreach ($eth_mtu as $eth) { |
||
| 843 | Processes::mwExecBg("/etc/rc/networking_set_mtu '{$eth}'"); |
||
| 844 | } |
||
| 845 | |||
| 846 | // Additional "manual" routes |
||
| 847 | $this->addCustomStaticRoutes(); |
||
| 848 | $this->openVpnConfigure(); |
||
| 849 | return 0; |
||
| 850 | } |
||
| 851 | |||
| 852 | /** |
||
| 853 | * Generates the hosts configuration. |
||
| 854 | * |
||
| 855 | * @return void |
||
| 856 | */ |
||
| 857 | public function hostsGenerate(): void |
||
| 860 | } |
||
| 861 | |||
| 862 | /** |
||
| 863 | * Configures the hostname and hosts file. |
||
| 864 | * |
||
| 865 | * @return void |
||
| 866 | */ |
||
| 867 | public function hostnameConfigure(): void |
||
| 868 | { |
||
| 869 | $data = self::getHostName(); |
||
| 870 | $hosts_conf = "127.0.0.1 localhost\n" . |
||
| 871 | "127.0.0.1 {$data['hostname']}\n"; |
||
| 872 | if (!empty($data['domain'])) { |
||
| 873 | $hosts_conf .= "127.0.0.1 {$data['hostname']}.{$data['domain']}\n"; |
||
| 874 | } |
||
| 875 | $hostnamePath = Util::which('hostname'); |
||
| 876 | if (Util::isDocker()) { |
||
| 877 | $realHostName = shell_exec($hostnamePath); |
||
| 878 | $hosts_conf .= "127.0.0.1 $realHostName\n"; |
||
| 879 | } |
||
| 880 | Util::fileWriteContent('/etc/hosts', $hosts_conf); |
||
| 881 | Processes::mwExec($hostnamePath . ' ' . escapeshellarg($data['hostname'])); |
||
| 882 | } |
||
| 883 | |||
| 884 | /** |
||
| 885 | * Add custom static routes based on the `/etc/static-routes` file. |
||
| 886 | * |
||
| 887 | * @param string $interface The network interface to add routes to, e.g., eth0 (optional) |
||
| 888 | * @return void |
||
| 889 | */ |
||
| 890 | protected function addCustomStaticRoutes(string $interface = ''): void |
||
| 891 | { |
||
| 892 | Util::fileWriteContent('/etc/static-routes', ''); |
||
| 893 | |||
| 894 | $grep = Util::which('grep'); |
||
| 895 | $awk = Util::which('awk'); |
||
| 896 | $cat = Util::which('cat'); |
||
| 897 | if (empty($interface)) { |
||
| 898 | $command = "$cat /etc/static-routes | $grep '^rout' | $awk -F ';' '{print $1}'"; |
||
| 899 | } else { |
||
| 900 | $command = "$cat /etc/static-routes | $grep '^rout' | $awk -F ';' '{print $1}' | $grep '{$interface}'"; |
||
| 901 | } |
||
| 902 | $arr_commands = []; |
||
| 903 | Processes::mwExec($command, $arr_commands); |
||
| 904 | Processes::mwExecCommands($arr_commands, $out, 'rout'); |
||
| 905 | } |
||
| 906 | |||
| 907 | /** |
||
| 908 | * Configuring OpenVPN. If a custom configuration file is specified in the system file customization, the network will be brought up. |
||
| 909 | */ |
||
| 910 | public function openVpnConfigure(): void |
||
| 911 | { |
||
| 912 | $confFile = '/etc/openvpn.ovpn'; |
||
| 913 | Util::fileWriteContent($confFile, ''); |
||
| 914 | $data = file_get_contents($confFile); |
||
| 915 | |||
| 916 | $pidFile = '/var/run/openvpn.pid'; |
||
| 917 | $pid = Processes::getPidOfProcess('openvpn'); |
||
| 918 | if (!empty($pid)) { |
||
| 919 | // Terminate the process. |
||
| 920 | $kill = Util::which('kill'); |
||
| 921 | Processes::mwExec("$kill '$pid'"); |
||
| 922 | } |
||
| 923 | if (!empty($data)) { |
||
| 924 | $openvpn = Util::which('openvpn'); |
||
| 925 | Processes::mwExecBg("$openvpn --config /etc/openvpn.ovpn --writepid {$pidFile}", '/dev/null', 5); |
||
| 926 | } |
||
| 927 | } |
||
| 928 | |||
| 929 | /** |
||
| 930 | * Retrieves information about all network interfaces. |
||
| 931 | * @return array An array of network interfaces with their respective information. |
||
| 932 | */ |
||
| 933 | public function getInterfaces(): array |
||
| 943 | } |
||
| 944 | |||
| 945 | /** |
||
| 946 | * Retrieves information about a specific network interface. |
||
| 947 | * @param string $name The name of the network interface. |
||
| 948 | * @return array An array containing the interface information. |
||
| 949 | */ |
||
| 950 | public function getInterface(string $name): array |
||
| 951 | { |
||
| 952 | $interface = []; |
||
| 1008 | } |
||
| 1009 | |||
| 1010 | /** |
||
| 1011 | * Refreshes networks configs and restarts network daemon. |
||
| 1012 | * |
||
| 1013 | * @return void |
||
| 1014 | */ |
||
| 1015 | public static function networkReload(): void |
||
| 1016 | { |
||
| 1017 | // Create Network object and configure settings |
||
| 1025 | } |
||
| 1026 | } |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.