aboutsummaryrefslogtreecommitdiffstats
path: root/include/nms.pm
blob: ce304d84c63af6f76d139254171996589f545832 (plain)
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
#! /usr/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
use FileHandle;
use JSON;
use AnyEvent::InfluxDB;
package nms;

use base 'Exporter';
our @EXPORT = qw(db_connect convert_mac convert_decimal);

BEGIN {
	require "config.pm";
	eval {
		require "config.local.pm";
	};
}


sub db_connect {
	my $connstr = "dbi:Pg:dbname=" . $nms::config::db_name;
	$connstr .= ";host=" . $nms::config::db_host unless (!defined($nms::config::db_host));

	my $dbh = DBI->connect($connstr,
	                       $nms::config::db_username,
	                       $nms::config::db_password, {AutoCommit => 0})
	        or die "Couldn't connect to database";
	return $dbh;
}

sub influx_connect {
	my $ix = AnyEvent::InfluxDB->new(
		server => $nms::config::influx_host,
		username => $nms::config::influx_username,
		password => $nms::config::influx_password,
	) or die "Couldn't connect to InfluxDB";
	return $ix;
}

# A few utilities to convert from SNMP binary address format to human-readable.

sub convert_mac {
	return join(':', map { sprintf "%02x", $_ } unpack('C*', shift));
}

sub convert_ipv4 {
	return join('.', map { sprintf "%d", $_ } unpack('C*', shift));
}

sub convert_ipv6 {
	return join(':', map { sprintf "%x", $_ } unpack('n*', shift));
}

sub convert_addr {
	my ($data, $type) = @_;
	if ($type == 1) {
		return convert_ipv4($data);
	} elsif ($type == 2) {
		return convert_ipv6($data);
	} else {
		die "Unknown address type $type";
	}
}

# I am not a perl programmer
sub convert_decimal {
	return join("",(map { sprintf "%c", $_ } split(/\./,shift)));
}

# Convert raw binary SNMP data to list of bits.
sub convert_bytelist {
	return split //, unpack("B*", shift);
}

sub convert_lldp_caps {
	my ($caps_data, $data) = @_;

        my @caps = convert_bytelist($caps_data);
        my @caps_names = qw(other repeater bridge ap router telephone docsis stationonly);
        for (my $i = 0; $i < scalar @caps && $i < scalar @caps_names; ++$i) {
		$data->{'cap_enabled_' . $caps_names[$i]} = $caps[$i];
        }
}

1;
an>} } void ssl_init( void ) { PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); NSS_NoDB_Init(NULL); NSS_SetDomesticPolicy(); initialized = TRUE; } void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); conn->fd = proxy_connect( host, port, ssl_connected, conn ); conn->func = func; conn->data = data; if( conn->fd < 0 ) { g_free( conn ); return( NULL ); } if( !initialized ) { ssl_init(); } return( conn ); } static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); } void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); conn->fd = fd; conn->func = func; conn->data = data; /* This function should be called via a (short) timeout instead of directly from here, because these SSL calls are *supposed* to be *completely* asynchronous and not ready yet when this function (or *_connect, for examle) returns. Also, errors are reported via the callback function, not via this function's return value. In short, doing things like this makes the rest of the code a lot simpler. */ b_timeout_add( 1, ssl_starttls_real, conn ); return conn; } static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; if( source == -1 ) goto ssl_connected_failure; /* Until we find out how to handle non-blocking I/O with NSS... */ sock_make_blocking( conn->fd ); conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL); SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB()); SSL_ResetHandshake(conn->prfd, PR_FALSE); if (SSL_ForceHandshake(conn->prfd)) { goto ssl_connected_failure; } conn->established = TRUE; conn->func( conn->data, conn, cond ); return FALSE; ssl_connected_failure: conn->func( conn->data, NULL, cond ); PR_Close( conn -> prfd ); if( source >= 0 ) closesocket( source ); g_free( conn ); return FALSE; } int ssl_read( void *conn, char *buf, int len ) { if( !((struct scd*)conn)->established ) return( 0 ); return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) ); } int ssl_write( void *conn, const char *buf, int len ) { if( !((struct scd*)conn)->established ) return( 0 ); return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); } /* See ssl_openssl.c for an explanation. */ int ssl_pending( void *conn ) { struct scd *c = (struct scd *) conn; if( c == NULL ) { return 0; } return ( c->established && SSL_DataPending( c->prfd ) > 0 ); } void ssl_disconnect( void *conn_ ) { struct scd *conn = conn_; PR_Close( conn->prfd ); closesocket( conn->fd ); g_free( conn ); } int ssl_getfd( void *conn ) { return( ((struct scd*)conn)->fd ); } b_input_condition ssl_getdirection( void *conn ) { /* Just in case someone calls us, let's return the most likely case: */ return B_EV_IO_READ; }