aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php
blob: e3c080199d630cc6fc57f85f5d55800fbfe1d307 (plain) (blame)
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
<?php
/**
 * This file is part of the ramsey/uuid library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
 * @license http://opensource.org/licenses/MIT MIT
 * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
 * @link https://packagist.org/packages/ramsey/uuid Packagist
 * @link https://github.com/ramsey/uuid GitHub
 */

namespace Ramsey\Uuid\Provider\Node;

use Ramsey\Uuid\Provider\NodeProviderInterface;

/**
 * SystemNodeProvider provides functionality to get the system node ID (MAC
 * address) using external system calls
 */
class SystemNodeProvider implements NodeProviderInterface
{
    /**
     * Returns the system node ID
     *
     * @return string|false System node ID as a hexadecimal string, or false if it is not found
     */
    public function getNode()
    {
        static $node = null;

        if ($node !== null) {
            return $node;
        }

        $pattern = '/[^:]([0-9A-Fa-f]{2}([:-])[0-9A-Fa-f]{2}(\2[0-9A-Fa-f]{2}){4})[^:]/';
        $matches = [];

        // first try a  linux specific way
        $node = $this->getSysfs();

        // Search the ifconfig output for all MAC addresses and return
        // the first one found
        if ($node === false) {
            if (preg_match_all($pattern, $this->getIfconfig(), $matches, PREG_PATTERN_ORDER)) {
                $node = $matches[1][0];
            }
        }
        if ($node !== false) {
            $node = str_replace([':', '-'], '', $node);
        }
        return $node;
    }

    /**
     * Returns the network interface configuration for the system
     *
     * @codeCoverageIgnore
     * @return string
     */
    protected function getIfconfig()
    {
        if (strpos(strtolower(ini_get('disable_functions')), 'passthru') !== false) {
            return '';
        }

        ob_start();
        switch (strtoupper(substr(constant('PHP_OS'), 0, 3))) {
            case 'WIN':
                passthru('ipconfig /all 2>&1');
                break;
            case 'DAR':
                passthru('ifconfig 2>&1');
                break;
            case 'FRE':
                passthru('netstat -i -f link 2>&1');
                break;
            case 'LIN':
            default:
                passthru('netstat -ie 2>&1');
                break;
        }

        return ob_get_clean();
    }

    /**
     * Returns mac address from the first system interface via the sysfs interface
     *
     * @return string|bool
     */
    protected function getSysfs()
    {
        $mac = false;

        if (strtoupper(constant('PHP_OS')) === 'LINUX') {
            $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);

            if (empty($addressPaths)) {
                return false;
            }

            array_walk($addressPaths, function ($addressPath) use (&$macs) {
                $macs[] = file_get_contents($addressPath);
            });

            $macs = array_map('trim', $macs);

            // remove invalid entries
            $macs = array_filter($macs, function ($mac) {
                return
                    // localhost adapter
                    $mac !== '00:00:00:00:00:00' &&
                    // must match  mac adress
                    preg_match('/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i', $mac);
            });

            $mac = reset($macs);
        }

        return $mac;
    }
}