Completed
Pull Request — master (#2936)
by
unknown
04:53
created

includes/common.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * LibreNMS - Common Functions
4
 *
5
 * Original Observium version by: Adam Armstrong, Tom Laermans
6
 * Copyright (c) 2009-2012 Adam Armstrong.
7
 *
8
 * Additions for LibreNMS by: Neil Lathwood, Paul Gear, Tim DuFrane
9
 * Copyright (c) 2014-2015 Neil Lathwood <http://www.lathwood.co.uk>
10
 * Copyright (c) 2014-2015 Gear Consulting Pty Ltd <http://libertysys.com.au/>
11
 *
12
 * This program is free software: you can redistribute it and/or modify it
13
 * under the terms of the GNU General Public License as published by the
14
 * Free Software Foundation, either version 3 of the License, or (at your
15
 * option) any later version.  Please see LICENSE.txt at the top level of
16
 * the source code distribution for details.
17
 */
18
19
function format_number_short($number, $sf) {
20
    // This formats a number so that we only send back three digits plus an optional decimal point.
21
    // Example: 723.42 -> 723    72.34 -> 72.3    2.23 -> 2.23
22
23
    list($whole, $decimal) = explode (".", $number);
24
25
    if (strlen($whole) >= $sf || !is_numeric($decimal)) {
26
        $number = $whole;
27
    }
28
    elseif(strlen($whole) < $sf) {
29
        $diff = $sf - strlen($whole);
30
        $number = $whole .".".substr($decimal, 0, $diff);
31
    }
32
    return $number;
33
}
34
35
function external_exec($command) {
36
    global $debug,$vdebug;
37 View Code Duplication
    if ($debug && !$vdebug) {
38
        $debug_command = preg_replace('/-c [\S]+/','-c COMMUNITY',$command);
39
        $debug_command = preg_replace('/(udp|udp6|tcp|tcp6):(.*):([\d]+)/','\1:HOSTNAME:\3',$debug_command);
40
        d_echo($debug_command);
41
    }
42
    elseif ($vdebug) {
43
        d_echo($command."\n");
44
    }
45
46
    $output = shell_exec($command);
47
48 View Code Duplication
    if ($debug && !$vdebug) {
49
        $debug_output = preg_replace('/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/', '*', $output);
50
        d_echo("$debug_output\n");
51
    }
52
    elseif ($vdebug) {
53
        d_echo($output."\n");
54
    }
55
56
    return $output;
57
}
58
59
function shorthost($hostname, $len=12) {
60
    // IP addresses should not be shortened
61
    if (filter_var($hostname, FILTER_VALIDATE_IP))
62
        return $hostname;
63
64
    $parts = explode(".", $hostname);
65
    $shorthost = $parts[0];
66
    $i = 1;
67
    while ($i < count($parts) && strlen($shorthost.'.'.$parts[$i]) < $len) {
68
        $shorthost = $shorthost.'.'.$parts[$i];
69
        $i++;
70
    }
71
    return ($shorthost);
72
}
73
74 View Code Duplication
function isCli() {
0 ignored issues
show
The function isCli() has been defined more than once; this definition is ignored, only the first definition in config_to_json.php (L15-23) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
75
    if (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR'])) {
76
        return true;
77
    }
78
    else {
79
        return false;
80
    }
81
}
82
83
function print_error($text) {
84
    global $console_color;
85
    if (isCli()) {
86
        print $console_color->convert("%r".$text."%n\n", false);
87
    }
88
    else {
89
        echo('<div class="alert alert-danger"><img src="images/16/exclamation.png" align="absmiddle"> '.$text.'</div>');
90
    }
91
}
92
93
function print_message($text) {
94
    if (isCli()) {
95
        print Console_Color2::convert("%g".$text."%n\n", false);
96
    }
97
    else {
98
        echo('<div class="alert alert-success"><img src="images/16/tick.png" align="absmiddle"> '.$text.'</div>');
99
    }
100
}
101
102
function delete_port($int_id) {
103
    global $config;
104
105
    $interface = dbFetchRow("SELECT * FROM `ports` AS P, `devices` AS D WHERE P.port_id = ? AND D.device_id = P.device_id", array($int_id));
106
107
    $interface_tables = array('adjacencies', 'ipaddr', 'ip6adjacencies', 'ip6addr', 'mac_accounting', 'bill_ports', 'pseudowires', 'ports');
108
109
    foreach ($interface_tables as $table) {
110
        dbDelete($table, "`port_id` =  ?", array($int_id));
111
    }
112
113
    dbDelete('links', "`local_port_id` =  ?", array($int_id));
114
    dbDelete('links', "`remote_port_id` =  ?", array($int_id));
115
    dbDelete('bill_ports', "`port_id` =  ?", array($int_id));
116
117
    unlink(get_port_rrdfile_path ($interface['hostname'], $interface['port_id']));
118
}
119
120
function sgn($int) {
121
    if ($int < 0) {
122
        return -1;
123
    }
124
    elseif ($int == 0) {
125
        return 0;
126
    }
127
    else {
128
        return 1;
129
    }
130
}
131
132
function get_sensor_rrd($device, $sensor) {
133
    global $config;
134
135
    # For IPMI, sensors tend to change order, and there is no index, so we prefer to use the description as key here.
136
    if ($config['os'][$device['os']]['sensor_descr'] || $sensor['poller_type'] == "ipmi") {
137
        $rrd_file = $config['rrd_dir']."/".$device['hostname']."/".safename("sensor-".$sensor['sensor_class']."-".$sensor['sensor_type']."-".$sensor['sensor_descr'] . ".rrd");
138
    }
139
    else {
140
        $rrd_file = $config['rrd_dir']."/".$device['hostname']."/".safename("sensor-".$sensor['sensor_class']."-".$sensor['sensor_type']."-".$sensor['sensor_index'] . ".rrd");
141
    }
142
143
    return($rrd_file);
144
}
145
146
function get_port_rrdfile_path ($hostname, $port_id, $suffix = '') {
147
    global $config;
148
149
    if (! empty ($suffix))
150
        $suffix = '-' . $suffix;
151
152
    return trim ($config['rrd_dir']) . '/' . safename ($hostname) . '/' . 'port-id' . safename($port_id) . safename ($suffix) . '.rrd';
153
}
154
155
function get_port_by_index_cache($device_id, $ifIndex) {
156
    global $port_index_cache;
157
158
    if (isset($port_index_cache[$device_id][$ifIndex]) && is_array($port_index_cache[$device_id][$ifIndex])) {
159
        $port = $port_index_cache[$device_id][$ifIndex];
160
    }
161
    else {
162
        $port = get_port_by_ifIndex($device_id, $ifIndex);
163
        $port_index_cache[$device_id][$ifIndex] = $port;
164
    }
165
166
    return $port;
167
}
168
169
function get_port_by_ifIndex($device_id, $ifIndex) {
170
    return dbFetchRow("SELECT * FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?", array($device_id, $ifIndex));
171
}
172
173
function get_all_devices($device, $type = "") {
174
    global $cache;
175
    $devices = array();
176
177
    // FIXME needs access control checks!
178
    // FIXME respect $type (server, network, etc) -- needs an array fill in topnav.
179
180
    if (isset($cache['devices']['hostname'])) {
181
        $devices = array_keys($cache['devices']['hostname']);
182
    }
183
    else {
184
        foreach (dbFetchRows("SELECT `hostname` FROM `devices`") as $data) {
185
            $devices[] = $data['hostname'];
186
        }
187
    }
188
189
    return $devices;
190
}
191
192
function port_by_id_cache($port_id) {
193
    return get_port_by_id_cache('port', $port_id);
194
}
195
196
function table_from_entity_type($type) {
197
    // Fuck you, english pluralisation.
198
    if ($type == "storage") {
199
        return $type;
200
    }
201
    else {
202
        return $type."s";
203
    }
204
}
205
206
function get_entity_by_id_cache($type, $id) {
207
    global $entity_cache;
208
209
    $table = table_from_entity_type($type);
210
211
    if (is_array($entity_cache[$type][$id])) {
212
        $entity = $entity_cache[$type][$id];
213
    }
214
    else {
215
        $entity = dbFetchRow("SELECT * FROM `".$table."` WHERE `".$type."_id` = ?", array($id));
216
        $entity_cache[$type][$id] = $entity;
217
    }
218
    return $entity;
219
}
220
221
function get_port_by_id($port_id) {
222 View Code Duplication
    if (is_numeric($port_id)) {
223
        $port = dbFetchRow("SELECT * FROM `ports` WHERE `port_id` = ?", array($port_id));
224
        if (is_array($port)) {
225
            return $port;
226
        }
227
        else {
228
            return FALSE;
229
        }
230
    }
231
}
232
233
function get_application_by_id($application_id) {
234 View Code Duplication
    if (is_numeric($application_id)) {
235
        $application = dbFetchRow("SELECT * FROM `applications` WHERE `app_id` = ?", array($application_id));
236
        if (is_array($application)) {
237
            return $application;
238
        }
239
        else {
240
            return FALSE;
241
        }
242
    }
243
}
244
245
function get_sensor_by_id($sensor_id) {
246 View Code Duplication
    if (is_numeric($sensor_id)) {
247
        $sensor = dbFetchRow("SELECT * FROM `sensors` WHERE `sensor_id` = ?", array($sensor_id));
248
        if (is_array($sensor)) {
249
            return $sensor;
250
        }
251
        else {
252
            return FALSE;
253
        }
254
    }
255
}
256
257 View Code Duplication
function get_device_id_by_port_id($port_id) {
258
    if (is_numeric($port_id)) {
259
        $device_id = dbFetchCell("SELECT `device_id` FROM `ports` WHERE `port_id` = ?", array($port_id));
260
        if (is_numeric($device_id)) {
261
            return $device_id;
262
        }
263
        else {
264
            return FALSE;
265
        }
266
    }
267
}
268
269 View Code Duplication
function get_device_id_by_app_id($app_id) {
270
    if (is_numeric($app_id)) {
271
        $device_id = dbFetchCell("SELECT `device_id` FROM `applications` WHERE `app_id` = ?", array($app_id));
272
        if (is_numeric($device_id)) {
273
            return $device_id;
274
        }
275
        else {
276
            return FALSE;
277
        }
278
    }
279
}
280
281
function ifclass($ifOperStatus, $ifAdminStatus) {
282
    $ifclass = "interface-upup";
283
    if ($ifAdminStatus == "down") {
284
        $ifclass = "interface-admindown";
285
    }
286
    if ($ifAdminStatus == "up" && $ifOperStatus== "down") {
287
        $ifclass = "interface-updown";
288
    }
289
    if ($ifAdminStatus == "up" && $ifOperStatus== "up") {
290
        $ifclass = "interface-upup";
291
    }
292
    return $ifclass;
293
}
294
295
function device_by_name($name, $refresh = 0) {
296
    // FIXME - cache name > id too.
297
    return device_by_id_cache(getidbyname($name), $refresh);
298
}
299
300
301
function accesspoint_by_id($ap_id, $refresh = '0') {
302
303
    $ap = dbFetchRow("SELECT * FROM `access_points` WHERE `accesspoint_id` = ?", array($ap_id));
304
305
    return $ap;
306
307
}
308
309
310
function device_by_id_cache($device_id, $refresh = '0') {
311
    global $cache;
312
313
    if (!$refresh && isset($cache['devices']['id'][$device_id]) && is_array($cache['devices']['id'][$device_id])) {
314
        $device = $cache['devices']['id'][$device_id];
315
    }
316
    else {
317
        $device = dbFetchRow("SELECT * FROM `devices` WHERE `device_id` = ?", array($device_id));
318
        $cache['devices']['id'][$device_id] = $device;
319
    }
320
    return $device;
321
}
322
323
function truncate($substring, $max = 50, $rep = '...') {
324
    if (strlen($substring) < 1) {
325
        $string = $rep;
326
    }
327
    else {
328
        $string = $substring;
329
    }
330
    $leave = $max - strlen ($rep);
331
    if (strlen($string) > $max) {
332
        return substr_replace($string, $rep, $leave);
333
    }
334
    else {
335
        return $string;
336
    }
337
}
338
339
function mres($string) {
340
    // short function wrapper because the real one is stupidly long and ugly. aesthetics.
341
    global $config, $database_link;
342
    if ($config['db']['extension'] == 'mysqli') {
343
        return mysqli_real_escape_string($database_link,$string);
344
    }
345
    else {
346
        return mysql_real_escape_string($string);
347
    }
348
}
349
350
function getifhost($id) {
351
    return dbFetchCell("SELECT `device_id` from `ports` WHERE `port_id` = ?", array($id));
352
}
353
354 View Code Duplication
function gethostbyid($id) {
355
    global $cache;
356
357
    if (isset($cache['devices']['id'][$id]['hostname'])) {
358
        $hostname = $cache['devices']['id'][$id]['hostname'];
359
    }
360
    else {
361
        $hostname = dbFetchCell("SELECT `hostname` FROM `devices` WHERE `device_id` = ?", array($id));
362
    }
363
364
    return $hostname;
365
}
366
367
function strgen ($length = 16) {
368
    $entropy = array(0,1,2,3,4,5,6,7,8,9,'a','A','b','B','c','C','d','D','e',
369
        'E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m','M','n',
370
        'N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w',
371
        'W','x','X','y','Y','z','Z');
372
    $string = "";
373
374
    for ($i=0; $i<$length; $i++) {
375
        $key = mt_rand(0,61);
376
        $string .= $entropy[$key];
377
    }
378
379
    return $string;
380
}
381
382
function getpeerhost($id) {
383
    return dbFetchCell("SELECT `device_id` from `bgpPeers` WHERE `bgpPeer_id` = ?", array($id));
384
}
385
386
function getifindexbyid($id) {
387
    return dbFetchCell("SELECT `ifIndex` FROM `ports` WHERE `port_id` = ?", array($id));
388
}
389
390
function getifbyid($id) {
391
    return dbFetchRow("SELECT * FROM `ports` WHERE `port_id` = ?", array($id));
392
}
393
394
function getifdescrbyid($id) {
395
    return dbFetchCell("SELECT `ifDescr` FROM `ports` WHERE `port_id` = ?", array($id));
396
}
397
398 View Code Duplication
function getidbyname($hostname) {
399
    global $cache;
400
401
    if (isset($cache['devices']['hostname'][$hostname])) {
402
        $id = $cache['devices']['hostname'][$hostname];
403
    }
404
    else {
405
        $id = dbFetchCell("SELECT `device_id` FROM `devices` WHERE `hostname` = ?", array($hostname));
406
    }
407
408
    return $id;
409
}
410
411 View Code Duplication
function gethostosbyid($id) {
412
    global $cache;
413
414
    if (isset($cache['devices']['id'][$id]['os'])) {
415
        $os = $cache['devices']['id'][$id]['os'];
416
    }
417
    else {
418
        $os = dbFetchCell("SELECT `os` FROM `devices` WHERE `device_id` = ?", array($id));
419
    }
420
421
    return $os;
422
}
423
424
function safename($name) {
425
    return preg_replace('/[^a-zA-Z0-9,._\-]/', '_', $name);
426
}
427
428
function zeropad($num, $length = 2) {
429
    while (strlen($num) < $length) {
430
        $num = '0'.$num;
431
    }
432
433
    return $num;
434
}
435
436
function set_dev_attrib($device, $attrib_type, $attrib_value) {
437
    if (dbFetchCell("SELECT COUNT(*) FROM devices_attribs WHERE `device_id` = ? AND `attrib_type` = ?", array($device['device_id'],$attrib_type))) {
438
        $return = dbUpdate(array('attrib_value' => $attrib_value), 'devices_attribs', 'device_id=? and attrib_type=?', array($device['device_id'], $attrib_type));
439
    }
440
    else {
441
        $return = dbInsert(array('device_id' => $device['device_id'], 'attrib_type' => $attrib_type, 'attrib_value' => $attrib_value), 'devices_attribs');
442
    }
443
    return $return;
444
}
445
446
function get_dev_attribs($device) {
447
    $attribs = array();
448
    foreach (dbFetchRows("SELECT * FROM devices_attribs WHERE `device_id` = ?", array($device)) as $entry) {
449
        $attribs[$entry['attrib_type']] = $entry['attrib_value'];
450
    }
451
    return $attribs;
452
}
453
454
function get_dev_entity_state($device) {
455
    $state = array();
456
    foreach (dbFetchRows("SELECT * FROM entPhysical_state WHERE `device_id` = ?", array($device)) as $entity) {
457
        $state['group'][$entity['group']][$entity['entPhysicalIndex']][$entity['subindex']][$entity['key']] = $entity['value'];
458
        $state['index'][$entity['entPhysicalIndex']][$entity['subindex']][$entity['group']][$entity['key']] = $entity['value'];
459
    }
460
    return $state;
461
}
462
463
function get_dev_attrib($device, $attrib_type, $attrib_value='') {
464
    $sql = '';
465
    $params = array($device['device_id'], $attrib_type);
466
    if (!empty($attrib_value)) {
467
        $sql = " AND `attrib_value`=?";
468
        array_push($params, $attrib_value);
469
    }
470
    if ($row = dbFetchRow("SELECT attrib_value FROM devices_attribs WHERE `device_id` = ? AND `attrib_type` = ? $sql", $params)) {
471
        return $row['attrib_value'];
472
    }
473
    else {
474
        return NULL;
475
    }
476
}
477
478
function is_dev_attrib_enabled($device, $attrib, $default = true) {
479
    $val = get_dev_attrib($device, $attrib);
480
    if ($val != NULL) {
481
        // attribute is set
482
        return ($val != 0);
483
    }
484
    else {
485
        // attribute not set
486
        return $default;
487
    }
488
}
489
490
function del_dev_attrib($device, $attrib_type) {
491
    return dbDelete('devices_attribs', "`device_id` = ? AND `attrib_type` = ?", array($device['device_id'], $attrib_type));
492
}
493
494
function formatRates($value, $round = '2', $sf = '3') {
495
    $value = format_si($value, $round, $sf) . "bps";
496
    return $value;
497
}
498
499
function formatStorage($value, $round = '2', $sf = '3') {
500
    $value = format_bi($value, $round) . "B";
501
    return $value;
502
}
503
504
function format_si($value, $round = '2', $sf = '3') {
505
    $neg = 0;
506
    if ($value < "0") {
507
        $neg = 1;
508
        $value = $value * -1;
509
    }
510
511
    if ($value >= "0.1") {
512
        $sizes = Array('', 'k', 'M', 'G', 'T', 'P', 'E');
513
        $ext = $sizes[0];
514 View Code Duplication
        for ($i = 1; (($i < count($sizes)) && ($value >= 1000)); $i++) {
515
            $value = $value / 1000;
516
            $ext  = $sizes[$i];
517
        }
518
    }
519
    else {
520
        $sizes = Array('', 'm', 'u', 'n');
521
        $ext = $sizes[0];
522 View Code Duplication
        for ($i = 1; (($i < count($sizes)) && ($value != 0) && ($value <= 0.1)); $i++) {
523
            $value = $value * 1000;
524
            $ext  = $sizes[$i];
525
        }
526
    }
527
528
    if ($neg == 1) {
529
        $value = $value * -1;
530
    }
531
532
        return format_number_short(round($value, $round),$sf).$ext;
533
}
534
535
function format_bi($value, $round = '2', $sf = '3'){
536
    if ($value < "0") {
537
        $neg = 1;
538
        $value = $value * -1;
539
    }
540
    $sizes = Array('', 'k', 'M', 'G', 'T', 'P', 'E');
541
    $ext = $sizes[0];
542 View Code Duplication
    for ($i = 1; (($i < count($sizes)) && ($value >= 1024)); $i++) {
543
        $value = $value / 1024;
544
        $ext  = $sizes[$i];
545
    }
546
547
    if ($neg) {
548
        $value = $value * -1;
549
    }
550
551
    return format_number_short(round($value, $round), $sf).$ext;
552
}
553
554
function format_number($value, $base = '1000', $round=2, $sf=3) {
555
    if ($base == '1000') {
556
        return format_si($value, $round, $sf);
557
    }
558
    else {
559
        return format_bi($value, $round, $sf);
560
    }
561
}
562
563
function is_valid_hostname($hostname) {
564
    // The Internet standards (Request for Comments) for protocols mandate that
565
    // component hostname labels may contain only the ASCII letters 'a' through 'z'
566
    // (in a case-insensitive manner), the digits '0' through '9', and the hyphen
567
    // ('-'). The original specification of hostnames in RFC 952, mandated that
568
    // labels could not start with a digit or with a hyphen, and must not end with
569
    // a hyphen. However, a subsequent specification (RFC 1123) permitted hostname
570
    // labels to start with digits. No other symbols, punctuation characters, or
571
    // white space are permitted. While a hostname may not contain other characters,
572
    // such as the underscore character (_), other DNS names may contain the underscore
573
574
    return ctype_alnum(str_replace('_','',str_replace('-','',str_replace('.','',$hostname))));
575
}
576
577
function add_service($device, $service, $descr, $service_ip, $service_param = "", $service_ignore = 0) {
578
579
    if (!is_array($device)) {
580
        $device = device_by_id_cache($device);
581
    }
582
583
    if (empty($service_ip)) {
584
        $service_ip = $device['hostname'];
585
    }
586
587
    $insert = array('device_id' => $device['device_id'], 'service_ip' => $service_ip, 'service_type' => $service,
588
        'service_changed' => array('UNIX_TIMESTAMP(NOW())'), 'service_desc' => $descr, 'service_param' => $service_param, 'service_ignore' => $service_ignore);
589
590
    return dbInsert($insert, 'services');
591
}
592
593
function edit_service($service, $descr, $service_ip, $service_param = "", $service_ignore = 0) {
594
595
    if (!is_numeric($service)) {
596
        return false;
597
    }
598
599
    $update = array('service_ip' => $service_ip,
600
        'service_changed' => array('UNIX_TIMESTAMP(NOW())'),
601
        'service_desc' => $descr,
602
        'service_param' => $service_param,
603
        'service_ignore' => $service_ignore);
604
    return dbUpdate($update, 'services', '`service_id`=?', array($service));
605
606
}
607
608
609
/*
610
 * convenience function - please use this instead of 'if ($debug) { echo ...; }'
611
 */
612
function d_echo($text, $no_debug_text = null) {
613
    global $debug;
614
    if ($debug) {
615
        if (is_array($text)) {
616
            print_r($text);
617
        }
618
        else {
619
            echo "$text";
620
        }
621
    }
622
    elseif ($no_debug_text) {
623
        echo "$no_debug_text";
624
    }
625
} // d_echo
626
627
628
/*
629
 * convenience function - please use this instead of 'if ($debug) { print_r ...; }'
630
 */
631
function d_print_r($var, $no_debug_text = null) {
632
    global $debug;
633
    if ($debug) {
634
        print_r($var);
635
    }
636
    elseif ($no_debug_text) {
637
        echo "$no_debug_text";
638
    }
639
} // d_print_r
640
641
642
/*
643
 * @return true if the given graph type is a dynamic MIB graph
644
 */
645
function is_mib_graph($type, $subtype) {
646
    global $config;
647
    return $config['graph_types'][$type][$subtype]['section'] == 'mib';
648
} // is_mib_graph
649
650
651
/*
652
 * @return true if client IP address is authorized to access graphs
653
 */
654
function is_client_authorized($clientip) {
655
    global $config;
656
657
    if (isset($config['allow_unauth_graphs']) && $config['allow_unauth_graphs']) {
658
        d_echo("Unauthorized graphs allowed\n");
659
        return true;
660
    }
661
662
    if (isset($config['allow_unauth_graphs_cidr'])) {
663
        foreach ($config['allow_unauth_graphs_cidr'] as $range) {
664
            if (Net_IPv4::ipInNetwork($clientip, $range)) {
665
                d_echo("Unauthorized graphs allowed from $range\n");
666
                return true;
667
            }
668
        }
669
    }
670
671
    return false;
672
} // is_client_authorized
673
674
675
/*
676
 * @return an array of all graph subtypes for the given type
677
 */
678
function get_graph_subtypes($type, $device = null)
679
{
680
    global $config;
681
682
    $types = array();
683
684
    // find the subtypes defined in files
685 View Code Duplication
    if ($handle = opendir($config['install_dir'] . "/html/includes/graphs/$type/")) {
686
        while (false !== ($file = readdir($handle))) {
687
            if ($file != "." && $file != ".." && $file != "auth.inc.php" && strstr($file, ".inc.php")) {
688
                $types[] = str_replace(".inc.php", "", $file);
689
            }
690
        }
691
        closedir($handle);
692
    }
693
694
    // find the MIB subtypes
695
    foreach ($config['graph_types'] as $type => $unused1) {
696
        foreach ($config['graph_types'][$type] as $subtype => $unused2) {
697
            if (is_mib_graph($type, $subtype)  &&  $device != null  &&  is_device_graph($device, $subtype)) {
698
                $types[] = $subtype;
699
            }
700
        }
701
    }
702
703
    sort($types);
704
    return $types;
705
} // get_graph_subtypes
706
707
708
function is_device_graph($device, $subtype)
709
{
710
    $query = 'SELECT COUNT(*) FROM `device_graphs` WHERE `device_id` = ? AND `graph` = ?';
711
    return dbFetchCell($query, array($device['device_id'], $subtype)) > 0;
712
} // is_device_graph
713
714
715
function get_smokeping_files($device) {
716
    global $config;
717
    $smokeping_files = array();
718
    if (isset($config['smokeping']['dir'])) {
719
        $smokeping_dir = generate_smokeping_file($device);
720
        if ($handle = opendir($smokeping_dir)) {
721
            while (false !== ($file = readdir($handle))) {
722
                if ($file != '.' && $file != '..') {
723
                    if (eregi('.rrd', $file)) {
724
                        if (eregi('~', $file)) {
725
                            list($target,$slave) = explode('~', str_replace('.rrd', '', $file));
726
                            $target = str_replace('_', '.', $target);
727
                            $smokeping_files['in'][$target][$slave] = $file;
728
                            $smokeping_files['out'][$slave][$target] = $file;
729
                        }
730
                        else {
731
                            $target = str_replace('.rrd', '', $file);
732
                            $target = str_replace('_', '.', $target);
733
                            $smokeping_files['in'][$target][$config['own_hostname']] = $file;
734
                            $smokeping_files['out'][$config['own_hostname']][$target] = $file;
735
                        }
736
                    }
737
                }
738
            }
739
        }
740
    }
741
    return $smokeping_files;
742
} // end get_smokeping_files
743
744
745
function generate_smokeping_file($device,$file='') {
746
    global $config;
747
    if ($config['smokeping']['integration'] === true) {
748
        return $config['smokeping']['dir'] .'/'. $device['type'] .'/' . $file;
749
    }
750
    else {
751
        return $config['smokeping']['dir'] . '/' . $file;
752
    }
753
} // generate_smokeping_file
754
755
756
/*
757
 * @return rounded value to 10th/100th/1000th depending on input (valid: 10, 100, 1000)
758
 */
759
function round_Nth($val = 0, $round_to) {
760
    if (($round_to == "10") || ($round_to == "100") || ($round_to == "1000")) {
761
        $diff = $val % $round_to;
762
        if ($diff >= ($round_to / 2)) {
763
            $ret = $val + ($round_to-$diff);
764
        } else {
765
            $ret = $val - $diff;
766
        }
767
        return $ret;
768
    }
769
} // end round_Nth 
770
771
772
/*
773
 * @return true if this device should be polled with MIB-based discovery
774
 */
775
function is_mib_poller_enabled($device)
776
{
777
    if (!is_module_enabled('poller', 'mib')) {
778
        return false;
779
    }
780
781
    if (!is_dev_attrib_enabled($device, 'poll_mib')) {
782
        d_echo('MIB module disabled for '.$device['hostname']."\n");
783
        return false;
784
    }
785
786
    return true;
787
} // is_mib_poller_enabled
788
789
790
/*
791
 * FIXME: Dummy implementation
792
 */
793
function count_mib_mempools($device)
794
{
795
    if (is_mib_poller_enabled($device) && $device['os'] == 'ruckuswireless') {
796
        return 1;
797
    }
798
    return 0;
799
} // count_mib_mempools
800
801
802
/*
803
 * FIXME: Dummy implementation
804
 */
805
function count_mib_processors($device)
806
{
807
    if (is_mib_poller_enabled($device) && $device['os'] == 'ruckuswireless') {
808
        return 1;
809
    }
810
    return 0;
811
} // count_mib_processors
812
813
814
function count_mib_health($device)
815
{
816
    return count_mib_mempools($device) + count_mib_processors($device);
817
} // count_mib_health
818
819
820
function get_mibval($device, $oid)
821
{
822
    $sql = 'SELECT * FROM `device_oids` WHERE `device_id` = ? AND `oid` = ?';
823
    return dbFetchRow($sql, array($device['device_id'], $oid));
824
} // get_mibval
825
826
827
/*
828
 * FIXME: Dummy implementation - needs an abstraction for each device
829
 */
830
function get_mib_mempools($device)
831
{
832
    $mempools = array();
833
    if (is_mib_poller_enabled($device) && $device['os'] == 'ruckuswireless') {
834
        $mempool = array();
835
        $mibvals = get_mibval($device, '.1.3.6.1.4.1.25053.1.2.1.1.1.15.14.0');
836
        $mempool['mempool_descr'] = $mibvals['object_type'];
837
        $mempool['mempool_id'] = 0;
838
        $mempool['mempool_total'] = 100;
839
        $mempool['mempool_used'] = $mibvals['numvalue'];
840
        $mempool['mempool_free'] = 100 - $mibvals['numvalue'];
841
        $mempool['percentage'] = true;
842
        $mempools[] = $mempool;
843
    }
844
    return $mempools;
845
} // get_mib_mempools
846
847
848
/*
849
 * FIXME: Dummy implementation - needs an abstraction for each device
850
 */
851
function get_mib_processors($device)
852
{
853
    $processors = array();
854
    if (is_mib_poller_enabled($device) && $device['os'] == 'ruckuswireless') {
855
        $proc = array();
856
        $mibvals = get_mibval($device, '.1.3.6.1.4.1.25053.1.2.1.1.1.15.13.0');
857
        $proc['processor_descr'] = $mibvals['object_type'];
858
        $proc['processor_id'] = 0;
859
        $proc['processor_usage'] = $mibvals['numvalue'];
860
        $processors[] = $proc;
861
    }
862
    return $processors;
863
} // get_mib_processors
864
865
866
/*
867
 * FIXME: Dummy implementation - needs an abstraction for each device
868
 * @return true if there is a custom graph defined for this type, subtype, and device
869
 */
870
function is_custom_graph($type, $subtype, $device)
871
{
872
    if (is_mib_poller_enabled($device) && $device['os'] == 'ruckuswireless' && $type == 'device') {
873
        switch ($subtype) {
874
        case 'cpumem':
875
        case 'mempool':
876
        case 'processor':
877
            return true;
878
        }
879
    }
880
    return false;
881
} // is_custom_graph
882
883
884
/*
885
 * FIXME: Dummy implementation
886
 * Set section/graph entries in $graph_enable for graphs specific to $os.
887
 */
888
function enable_os_graphs($os, &$graph_enable)
889
{
890
    /*
891
    foreach (dbFetchRows("SELECT * FROM graph_conditions WHERE graph_type = 'device' AND condition_name = 'os' AND condition_value = ?", array($os)) as $graph) {
892
        $graph_enable[$graph['graph_section']][$graph['graph_subtype']] = "device_".$graph['graph_subtype'];
893
    }
894
    */
895
} // enable_os_graphs
896
897
898
/*
899
 * For each os-based or global graph relevant to $device, set its section/graph entry in $graph_enable.
900
 */
901
function enable_graphs($device, &$graph_enable)
902
{
903
    // These are standard graphs we should have for all systems
904
    $graph_enable['poller']['poller_perf']         = 'device_poller_perf';
905
    $graph_enable['poller']['poller_modules_perf'] = 'device_poller_modules_perf';
906
    if (can_ping_device($device) === true) {
907
        $graph_enable['poller']['ping_perf'] = 'device_ping_perf';
908
    }
909
910
    enable_os_graphs($device['os'], $graph_enable);
911
} // enable_graphs
912
913
914
//
915
// maintain a simple cache of objects
916
//
917
918
function object_add_cache($section, $obj)
919
{
920
    global $object_cache;
921
    $object_cache[$section][$obj] = true;
922
} // object_add_cache
923
924
925
function object_is_cached($section, $obj)
926
{
927
    global $object_cache;
928
    if (array_key_exists($obj, $object_cache)) {
929
        return $object_cache[$section][$obj];
930
    }
931
    else {
932
        return false;
933
    }
934
} // object_is_cached
935
936
937
/**
938
 * Checks if config allows us to ping this device
939
 * $attribs contains an array of all of this devices
940
 * attributes
941
 * @param array $attribs Device attributes
942
 * @return bool
943
**/
944
function can_ping_device($attribs) {
945
    global $config;
946
    if ($config['icmp_check'] === true && $attribs['override_icmp_disable'] != "true") {
947
        return true;
948
    }
949
    else {
950
        return false;
951
    }
952
} // end can_ping_device
953
954
955
/*
956
 * @return true if the requested module type & name is globally enabled
957
 */
958
function is_module_enabled($type, $module)
959
{
960
    global $config;
961
    if (isset($config[$type.'_modules'][$module])) {
962
        return $config[$type.'_modules'][$module] == 1;
963
    }
964
    else {
965
        return false;
966
    }
967
} // is_module_enabled
968
969
970
/*
971
 * @return true if every string in $arr begins with $str
972
 */
973
function begins_with($str, $arr)
974
{
975
    foreach ($arr as $s) {
976
        $pos = strpos($s, $str);
977
        if ($pos === false || $pos > 0) {
978
            return false;
979
        }
980
    }
981
    return true;
982
} // begins_with
983
984
985
/*
986
 * @return the longest starting portion of $str that matches everything in $arr
987
 */
988
function longest_matching_prefix($str, $arr)
989
{
990
    $len = strlen($str);
991
    while ($len > 0) {
992
        $prefix = substr($str, 0, $len);
993
        if (begins_with($prefix, $arr)) {
994
            return $prefix;
995
        }
996
        $len -= 1;
997
    }
998
    return '';
999
} // longest_matching_prefix
1000
1001
1002
function search_phrase_column($c)
1003
{
1004
    global $searchPhrase;
1005
    return "$c LIKE '%$searchPhrase%'";
1006
} // search_phrase_column
1007
1008
1009
function print_mib_poller_disabled() {
1010
    echo '<h4>MIB polling is not enabled</h4>
1011
<p>
1012
Set <tt>$config[\'poller_modules\'][\'mib\'] = 1;</tt> in <tt>config.php</tt> to enable.
1013
</p>';
1014
} // print_mib_poller_disabled
1015
1016
1017
/**
1018
 * Constructs the path to an RRD for the Ceph application
1019
 * @param string $gtype The type of rrd we're looking for
1020
 * @return string
1021
**/
1022
function ceph_rrd($gtype) {
1023
    global $device;
1024
    global $vars;
1025
    global $config;
1026
1027
    if ($gtype == "osd") {
1028
        $var = $vars['osd'];
1029
    }
1030
    else {
1031
        $var = $vars['pool'];
1032
    }
1033
1034
    $rrd = join('-', array('app', 'ceph', $vars['id'], $gtype, $var)).'.rrd';
1035
    return join('/', array($config['rrd_dir'], $device['hostname'], $rrd));
1036
} // ceph_rrd
1037
1038
/**
1039
 * Parse location field for coordinates
1040
 * @param string location The location field to look for coords in.
1041
 * @return array Containing the lat and lng coords
1042
**/
1043
function parse_location($location) {
1044
    preg_match('/(\[)(-?[0-9\. ]+),[ ]*(-?[0-9\. ]+)(\])/', $location, $tmp_loc);
1045
    if (!empty($tmp_loc[2]) && !empty($tmp_loc[3])) {
1046
        return array('lat' => $tmp_loc[2], 'lng' => $tmp_loc[3]);
1047
    }
1048
}//end parse_location()
1049
1050
/**
1051
 * Returns version info
1052
 * @return array
1053
**/
1054
function version_info($remote=true) {
1055
    global $config;
1056
    $output = array();
1057
    if ($remote === true && $config['update_channel'] == 'master') {
1058
        $api = curl_init();
1059
        set_curl_proxy($api);
1060
        curl_setopt($api, CURLOPT_USERAGENT,'LibreNMS');
1061
        curl_setopt($api, CURLOPT_URL, $config['github_api'].'commits/master');
1062
        curl_setopt($api, CURLOPT_RETURNTRANSFER, 1);
1063
        $output['github'] = json_decode(curl_exec($api),true);
1064
    }
1065
    $output['local_sha']   = chop(`git rev-parse HEAD`);
1066
    $output['db_schema']   = dbFetchCell('SELECT version FROM dbSchema');
1067
    $output['php_ver']     = phpversion();
1068
    $output['mysql_ver']   = dbFetchCell('SELECT version()');
1069
    $output['rrdtool_ver'] = implode(' ', array_slice(explode(' ', shell_exec($config['rrdtool'].' --version |head -n1')), 1, 1));
1070
    $output['netsnmp_ver'] = shell_exec($config['snmpget'].' --version 2>&1');
1071
1072
    return $output;
1073
1074
}//end version_info()
1075
1076
/**
1077
* Convert a MySQL binary v4 (4-byte) or v6 (16-byte) IP address to a printable string.
1078
* @param string $ip A binary string containing an IP address, as returned from MySQL's INET6_ATON function
1079
* @return string Empty if not valid.
1080
*/
1081
// Fuction is from http://uk3.php.net/manual/en/function.inet-ntop.php
1082
function inet6_ntop($ip) {
1083
    $l = strlen($ip);
1084
    if ($l == 4 or $l == 16) {
1085
        return inet_ntop(pack('A' . $l, $ip));
1086
    }
1087
    return '';
1088
}
1089
1090
/**
1091
 * Convert IP to use sysName
1092
 * @param array device
1093
 * @param string ip address
1094
 * @return string
1095
**/
1096
function ip_to_sysname($device,$ip) {
1097
    global $config;
1098
    if ($config['force_ip_to_sysname'] === true) {
1099
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) == true || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) == true) {
1100
            $ip = $device['sysName'];
1101
        }
1102
    }
1103
    return $ip;
1104
}//end ip_to_sysname
1105
1106
/**
1107
 * Return valid port association modes
1108
 * @param bool $no_cache No-Cache flag (optional, default false)
1109
 * @return array
1110
 */
1111
function get_port_assoc_modes ($no_cache = false) {
1112
    global $config;
1113
1114
    if ($config['memcached']['enable'] && $no_cache === false) {
1115
        $assoc_modes = $config['memcached']['resource']->get (hash ('sha512', "port_assoc_modes"));
1116
        if (! empty ($assoc_modes))
1117
            return $assoc_modes;
1118
    }
1119
1120
    $assoc_modes = Null;
1121
        foreach (dbFetchRows ("SELECT `name` FROM `port_association_mode` ORDER BY pom_id") as $row)
1122
        $assoc_modes[] = $row['name'];
1123
1124
    if ($config['memcached']['enable'] && $no_cache === false)
1125
        $config['memcached']['resource']->set (hash ('sha512', "port_assoc_modes"), $assoc_modes, $config['memcached']['ttl']);
1126
1127
    return $assoc_modes;
1128
}
1129
1130
/**
1131
 * Validate port_association_mode
1132
 * @param string $port_assoc_mode
1133
 * @return bool
1134
 */
1135
function is_valid_port_assoc_mode ($port_assoc_mode) {
1136
    return in_array ($port_assoc_mode, get_port_assoc_modes ());
1137
}
1138
1139
/**
1140
 * Get DB id of given port association mode name
1141
 * @param string $port_assoc_mode
1142
 * @param bool $no_cache No-Cache flag (optional, default false)
1143
 */
1144 View Code Duplication
function get_port_assoc_mode_id ($port_assoc_mode, $no_cache = false) {
1145
    global $config;
1146
1147
    if ($config['memcached']['enable'] && $no_cache === false) {
1148
        $id = $config['memcached']['resource']->get (hash ('sha512', "port_assoc_mode_id|$port_assoc_mode"));
1149
        if (! empty ($id))
1150
            return $id;
1151
    }
1152
1153
    $id = Null;
1154
    $row = dbFetchRow ("SELECT `pom_id` FROM `port_association_mode` WHERE name = ?", array ($port_assoc_mode));
1155
    if ($row) {
1156
        $id = $row['pom_id'];
1157
        if ($config['memcached']['enable'] && $no_cache === false)
1158
            $config['memcached']['resource']->set (hash ('sha512', "port_assoc_mode_id|$port_assoc_mode"), $id, $config['memcached']['ttl']);
1159
    }
1160
1161
    return $id;
1162
}
1163
1164
/**
1165
 * Get name of given port association_mode ID
1166
 * @param int $port_assoc_mode_id Port association mode ID
1167
 * @param bool $no_cache No-Cache flag (optional, default false)
1168
 * @return bool
1169
 */
1170 View Code Duplication
function get_port_assoc_mode_name ($port_assoc_mode_id, $no_cache = false) {
1171
    global $config;
1172
1173
    if ($config['memcached']['enable'] && $no_cache === false) {
1174
        $name = $config['memcached']['resource']->get (hash ('sha512', "port_assoc_mode_name|$port_assoc_mode_id"));
1175
        if (! empty ($name))
1176
            return $name;
1177
    }
1178
1179
    $name = Null;
1180
    $row = dbFetchRow ("SELECT `name` FROM `port_association_mode` WHERE pom_id = ?", array ($port_assoc_mode_id));
1181
    if ($row) {
1182
        $name = $row['name'];
1183
        if ($config['memcached']['enable'] && $no_cache === false)
1184
            $config['memcached']['resource']->set (hash ('sha512', "port_assoc_mode_name|$port_assoc_mode_id"), $name, $config['memcached']['ttl']);
1185
    }
1186
1187
    return $name;
1188
}
1189
1190
/**
1191
 * Query all ports of the given device (by ID) and build port array and
1192
 * port association maps for ifIndex, ifName, ifDescr. Query port stats
1193
 * if told to do so, too.
1194
 * @param int $device_id ID of device to query ports for
1195
 * @param bool $with_statistics Query port statistics, too. (optional, default false)
1196
 * @return array
1197
 */
1198
function get_ports_mapped ($device_id, $with_statistics = false) {
1199
    $ports = array();
1200
    $maps = array(
1201
        'ifIndex' => array(),
1202
        'ifName'  => array(),
1203
        'ifDescr' => array(),
1204
    );
1205
1206
    /* Query all information available for ports for this device ... */
1207
    $query = 'SELECT * FROM `ports` WHERE `device_id` = ? ORDER BY port_id';
1208
    if ($with_statistics) {
1209
        /* ... including any related ports_statistics if requested */
1210
        $query = 'SELECT *, `ports_statistics`.`port_id` AS `ports_statistics_port_id`, `ports`.`port_id` AS `port_id` FROM `ports` LEFT OUTER JOIN `ports_statistics` ON `ports`.`port_id` = `ports_statistics`.`port_id` WHERE `ports`.`device_id` = ? ORDER BY ports.port_id';
1211
    }
1212
1213
    // Query known ports in order of discovery to make sure the latest
1214
    // discoverd/polled port is in the mapping tables.
1215
    foreach (dbFetchRows ($query, array ($device_id)) as $port) {
1216
        // Store port information by ports port_id from DB
1217
        $ports[$port['port_id']] = $port;
1218
1219
        // Build maps from ifIndex, ifName, ifDescr to port_id
1220
        $maps['ifIndex'][$port['ifIndex']] = $port['port_id'];
1221
        $maps['ifName'][$port['ifName']]   = $port['port_id'];
1222
        $maps['ifDescr'][$port['ifDescr']] = $port['port_id'];
1223
    }
1224
1225
    return array(
1226
        'ports' => $ports,
1227
        'maps'  => $maps,
1228
    );
1229
}
1230
1231
/**
1232
 * Calculate port_id of given port using given devices port information and port association mode
1233
 * @param array $ports_mapped Port information of device queried by get_ports_mapped()
1234
 * @param array $port Port information as fetched from DB
1235
 * @param string $port_association_mode Port association mode to use for mapping
1236
 * @return int port_id (or Null)
1237
 */
1238
function get_port_id ($ports_mapped, $port, $port_association_mode) {
1239
    // Get port_id according to port_association_mode used for this device
1240
    $port_id = Null;
1241
1242
    /*
1243
     * Information an all ports is available through $ports_mapped['ports']
1244
     * This might come in handy sometime in the future to add you nifty new
1245
     * port mapping schema:
1246
     *
1247
     * $ports = $ports_mapped['ports'];
1248
    */
1249
    $maps  = $ports_mapped['maps'];
1250
1251
    if (in_array ($port_association_mode, array ('ifIndex', 'ifName', 'ifDescr'))) {
1252
        $port_id = $maps[$port_association_mode][$port[$port_association_mode]];
1253
    }
1254
1255
    return $port_id;
1256
}
1257