forked from reactphp/dns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConfig.php
137 lines (123 loc) · 5.29 KB
/
Config.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
namespace React\Dns\Config;
use RuntimeException;
final class Config
{
/**
* Loads the system DNS configuration
*
* Note that this method may block while loading its internal files and/or
* commands and should thus be used with care! While this should be
* relatively fast for most systems, it remains unknown if this may block
* under certain circumstances. In particular, this method should only be
* executed before the loop starts, not while it is running.
*
* Note that this method will try to access its files and/or commands and
* try to parse its output. Currently, this will only parse valid nameserver
* entries from its output and will ignore all other output without
* complaining.
*
* Note that the previous section implies that this may return an empty
* `Config` object if no valid nameserver entries can be found.
*
* @return self
* @codeCoverageIgnore
*/
public static function loadSystemConfigBlocking()
{
// Use WMIC output on Windows
if (DIRECTORY_SEPARATOR === '\\') {
return self::loadWmicBlocking();
}
// otherwise (try to) load from resolv.conf
try {
return self::loadResolvConfBlocking();
} catch (RuntimeException $ignored) {
// return empty config if parsing fails (file not found)
return new self();
}
}
/**
* Loads a resolv.conf file (from the given path or default location)
*
* Note that this method blocks while loading the given path and should
* thus be used with care! While this should be relatively fast for normal
* resolv.conf files, this may be an issue if this file is located on a slow
* device or contains an excessive number of entries. In particular, this
* method should only be executed before the loop starts, not while it is
* running.
*
* Note that this method will throw if the given file can not be loaded,
* such as if it is not readable or does not exist. In particular, this file
* is not available on Windows.
*
* Currently, this will only parse valid "nameserver X" lines from the
* given file contents. Lines can be commented out with "#" and ";" and
* invalid lines will be ignored without complaining. See also
* `man resolv.conf` for more details.
*
* Note that the previous section implies that this may return an empty
* `Config` object if no valid "nameserver X" lines can be found. See also
* `man resolv.conf` which suggests that the DNS server on the localhost
* should be used in this case. This is left up to higher level consumers
* of this API.
*
* @param ?string $path (optional) path to resolv.conf file or null=load default location
* @return self
* @throws RuntimeException if the path can not be loaded (does not exist)
*/
public static function loadResolvConfBlocking($path = null)
{
if ($path === null) {
$path = '/etc/resolv.conf';
}
$contents = @file_get_contents($path);
if ($contents === false) {
throw new RuntimeException('Unable to load resolv.conf file "' . $path . '"');
}
$matches = [];
preg_match_all('/^nameserver\s+(\S+)\s*$/m', $contents, $matches);
$config = new self();
foreach ($matches[1] as $ip) {
// remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`)
if (strpos($ip, ':') !== false && ($pos = strpos($ip, '%')) !== false) {
$ip = substr($ip, 0, $pos);
}
if (@inet_pton($ip) !== false) {
$config->nameservers[] = $ip;
}
}
return $config;
}
/**
* Loads the DNS configurations from Windows's WMIC (from the given command or default command)
*
* Note that this method blocks while loading the given command and should
* thus be used with care! While this should be relatively fast for normal
* WMIC commands, it remains unknown if this may block under certain
* circumstances. In particular, this method should only be executed before
* the loop starts, not while it is running.
*
* Note that this method will only try to execute the given command try to
* parse its output, irrespective of whether this command exists. In
* particular, this command is only available on Windows. Currently, this
* will only parse valid nameserver entries from the command output and will
* ignore all other output without complaining.
*
* Note that the previous section implies that this may return an empty
* `Config` object if no valid nameserver entries can be found.
*
* @param ?string $command (advanced) should not be given (NULL) unless you know what you're doing
* @return self
* @link https://ss64.com/nt/wmic.html
*/
public static function loadWmicBlocking($command = null)
{
$contents = shell_exec($command === null ? 'wmic NICCONFIG get "DNSServerSearchOrder" /format:CSV' : $command);
preg_match_all('/(?<=[{;,"])([\da-f.:]{4,})(?=[};,"])/i', $contents, $matches);
$config = new self();
$config->nameservers = $matches[1];
return $config;
}
public $nameservers = [];
}