summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/pciid.inc.php
blob: 38a2c56d8806e2a31ceb66f7d952e3efe70c186a (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
<?php

class PciId
{

	const DEVICE = 'DEVICE';
	const VENDOR = 'VENDOR';
	const DEVCLASS = 'CLASS';
	const AUTO = 'AUTO';


	/**
	 * @param string $cat type of query - self::DEVICE, self::VENDOR, self::DEVCLASS or self::AUTO for auto detection
	 * @param string $id the id to query - depends on $cat
	 * @return string|false Name of Class/Vendor/Device, false if not found
	 */
	public static function getPciId(string $cat, string $id, bool $dnsQuery = false)
	{
		static $cache = [];
		if ($cat === self::DEVCLASS && $id[1] === '.') {
			$id = substr($id, 2);
		}
		if ($cat === self::AUTO) {
			if (preg_match('/^([a-f0-9]{4})[:._-]?([a-f0-9]{4})$/', $id, $out)) {
				$cat = 'DEVICE';
				$host = $out[2] . '.' . $out[1];
				$id = $out[1] . ':' . $out[2];
			} elseif (preg_match('/^[a-f0-9]{4}$/', $id)) {
				$cat = 'VENDOR';
				$host = $id;
			} elseif (preg_match('/^c[.-]([a-f0-9]{2})([a-f0-9]{2})$/', $id)) {
				$cat = 'CLASS';
				$host = $out[2] . '.' . $out[1] . '.c';
				$id = substr($id, 2);
			} else {
				error_log('Invalid PCIID lookup format: ' . $id);
				return false;
			}
		} elseif ($cat === self::DEVICE && preg_match('/^([a-f0-9]{4})[:._-]?([a-f0-9]{4})$/', $id, $out)) {
			$host = $out[2] . '.' . $out[1];
			$id = $out[1] . ':' . $out[2];
		} elseif ($cat === self::VENDOR && preg_match('/^([a-f0-9]{4})$/', $id)) {
			$host = $id;
		} elseif ($cat === self::DEVCLASS && preg_match('/^(?:c[.-])?([a-f0-9]{2})([a-f0-9]{2})$/', $id, $out)) {
			$host = $out[2] . '.' . $out[1] . '.c';
			$id = 'c.' . $out[1] . $out[2];
		} else {
			error_log("getPciId called with unknown format: ($cat) ($id)");
			return false;
		}
		$key = $cat . '-' . $id;
		if (isset($cache[$key]))
			return $cache[$key];
		$row = Database::queryFirst('SELECT value, dateline FROM pciid WHERE category = :cat AND id = :id LIMIT 1',
			array('cat' => $cat, 'id' => $id));
		if ($row !== false && $row['dateline'] >= time()) {
			return $cache[$key] = $row['value'];
		}
		if (!$dnsQuery)
			return false;
		// Unknown, query
		$res = dns_get_record($host . '.pci.id.ucw.cz', DNS_TXT);
		if (!is_array($res))
			return false;
		foreach ($res as $entry) {
			if (isset($entry['txt']) && substr($entry['txt'], 0, 2) === 'i=') {
				$string = substr($entry['txt'], 2);
				Database::exec('INSERT INTO pciid (category, id, value, dateline) VALUES (:cat, :id, :value, :timeout)'
					. ' ON DUPLICATE KEY UPDATE value = VALUES(value), dateline = VALUES(dateline)',
					array(
						'cat' => $cat,
						'id' => $id,
						'value' => $string,
						'timeout' => time() + mt_rand(10, 30) * 86400,
					), true);
				return $cache[$key] = $string;
			}
		}
		return $cache[$key] = ($row['value'] ?? false);
	}

}