Advertisement
poodad

wificlients

Jun 13th, 2022
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.22 KB | None | 0 0
  1. use strict;
  2. use Net::SNMP;
  3. use LWP::UserAgent;
  4. use HTTP::Request::Common qw(POST GET DELETE);
  5. use Data::Dumper;
  6. use Net::DNS;
  7. use JSON;
  8.  
  9. my $dns;
  10. my $dbh;
  11.  
  12. my $community = 'public';
  13.  
  14. my $t0 = time();
  15.  
  16. my @hosts = (
  17. "wlc#1",
  18. "wlc#2",
  19. #etc
  20. );
  21.  
  22. if( ! scalar @hosts ) {
  23. print "No WLCs found in inventory matching location $loc\n";
  24. exit 0;
  25. }
  26.  
  27. # get client counts per SSID
  28.  
  29. my @meas;
  30.  
  31. foreach my $host (@hosts) {
  32.  
  33. print "$host\n";
  34.  
  35. (my $snmp, my $err) = Net::SNMP::Table->session( -hostname => $host, -community => $community, -timeout => 5, -port => "161", -version => '2c', -translate=>[-octetstring => 0]);
  36.  
  37. if( ! $snmp ) {
  38. print STDERR "Could not open SNMP session to $host\n";
  39. next;
  40. }
  41.  
  42. my $objApName = $snmp->table("1.3.6.1.4.1.14179.2.2.1.1.3", 6); # get AP names
  43. my $objApMac = $snmp->table("1.3.6.1.4.1.14179.2.2.1.1.1", 6); # get AP MAC addresses
  44. my $objApModel = $snmp->table("1.3.6.1.4.1.14179.2.2.1.1.16", 6); # get AP model
  45.  
  46. my %apnames; # AP MAC to AP name
  47. my %apmodels; # AP MAC to model
  48.  
  49. my @keys = $objApMac->keys();
  50. foreach my $i (@keys) {
  51. my $apname = $objApName->item($i);
  52. my $apmac = unpack "H*", $objApMac->item($i); # we told Net::SNMP to not translate octets, so translate now
  53. $apnames{$apmac} = $apname;
  54. my $apmodel = $objApModel->item($i);
  55. $apmodel =~ s/^air\-[a-z]+//i; # clean up model
  56. $apmodel =~ s/\-..*//;
  57. $apmodels{$apmac} = $apmodel;
  58.  
  59. print "AP: $apname MODEL: $apmodel MAC: $apmac\n";
  60. }
  61.  
  62. my $objClientMac = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.1", 6); # get client MAC addresses
  63. my $objClientIP = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.2", 6); # get client IP addresses
  64. my $objClientName = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.3", 6); # get client name
  65. my $objClientSSID = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.7", 6); # get client SSID
  66. my $objClientProto = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.25", 6); # get client IP addresses
  67. my $objClientRSSI = $snmp->table("1.3.6.1.4.1.14179.2.1.6.1.1", 6); # get client RSSI
  68. my $objClientSNR = $snmp->table("1.3.6.1.4.1.14179.2.1.6.1.26", 6); # get client SNR
  69. my $objClientApMac = $snmp->table("1.3.6.1.4.1.14179.2.1.4.1.4", 6); # get client AP MAC address
  70.  
  71.  
  72. @keys = $objClientIP->keys();
  73.  
  74. # get the per client info
  75.  
  76. foreach my $i (@keys) {
  77.  
  78.  
  79. my $mac = unpack "H*", $objClientMac->item($i); # decode clinet MAC address since we told Net::SNMP to not translate
  80. my $apmac = unpack "H*", $objClientApMac->item($i); # decode AP MAC address since we told Net::SNMP to not translate
  81.  
  82. my $ip = $objClientIP->item($i);
  83. my $name = $objClientName->item($i);
  84. my $ssid = $objClientSSID->item($i);
  85. my $proto = $objClientProto->item($i);
  86. my $rssi = $objClientRSSI->item($i);
  87. my $snr = $objClientSNR->item($i);
  88.  
  89.  
  90. next if $ip eq '0.0.0.0'; # not a valid connection
  91. next unless $ssid; # not valid
  92.  
  93. $mac =~ s/^0x//;
  94. $proto = proto($proto);
  95.  
  96. my $id; # human friendly ID for this client
  97.  
  98. if( $name =~ /^host\//i) { # workstation name ?
  99. $id = $name; # best case, use the client name
  100. $id =~ s/^host\///i; # get rid of HOST/ prefix
  101. }
  102.  
  103. $id = GetHostName($ip) unless $id; # next best option, reverse DNS lookup
  104. $id = $ip unless $id; # next best, use IP address
  105. $id = $mac unless $id; # punt, use MAC address
  106.  
  107. $id = lc $id; # lower case
  108.  
  109. my $apname = $apnames{$apmac} || $apmac;
  110. my $apmodel = $apmodels{$apmac} || '?';
  111.  
  112. $rssi .= 'i'; # store as integer
  113. $snr .= 'i'; # ditto
  114.  
  115. push @meas, qq(client,SSID=$ssid,ip=$ip,id=$id,wlc=$host,mac=$mac,ap=$apname,apmodel=$apmodel proto="$proto",RSSI=$rssi,SNR=$snr);
  116.  
  117. # After 75 client mesaurements, send to InfluxDB and empty @meas
  118.  
  119. if( scalar @meas > 75 ) {
  120. print join "\n", @meas;
  121. print "\n";
  122. WriteInflux("yourinfluxserver", "yourdatabase", @meas);
  123. @meas = ();
  124. }
  125. }
  126. }
  127.  
  128. # Get remaining measurements
  129.  
  130. if( scalar @meas ) {
  131. print join "\n", @meas;
  132. print "\n";
  133. WriteInflux("yourinfluxserver", "yourdatabase", @meas);
  134. }
  135.  
  136. print "\n";
  137. print "Run time : ", time() - $t0, " seconds\n";
  138. print "CPU time (user) : ", (times)[0], " seconds\n";
  139. print "CPU time (system): ", (times)[1], " seconds\n";
  140.  
  141. exit 0;
  142.  
  143.  
  144. ####################
  145.  
  146. sub WriteInflux {
  147. my $server = shift;
  148. my $db = shift;
  149. my @dat = @_;
  150.  
  151. my $body = join "\n", @dat;
  152.  
  153. my $url = "http://$server:8086/write?db=$db&precision=s";
  154.  
  155. my $ua = LWP::UserAgent->new;
  156. my $req = (POST $url, Content=>$body);
  157. my $res = $ua->request($req);
  158.  
  159. print "code: ", $res->code, "\n";
  160. print "content: ", $res->content, "\n";
  161.  
  162. }
  163.  
  164. ###############################################################################
  165. #
  166. # Translate numeric values of bsnMobileStationProtocol to human readable
  167. #
  168. ###############################################################################
  169.  
  170. sub proto {
  171. my $i = shift;
  172.  
  173. return 'dot11a' if $i == 1;
  174. return 'dot11b' if $i == 2;
  175. return 'dot11g' if $i == 3;
  176. return 'unknown' if $i == 4;
  177. return 'mobile' if $i == 5;
  178. return 'dot11n24' if $i == 6;
  179. return 'dot11n5' if $i == 7;
  180. return $i;
  181. }
  182.  
  183. sub GetHostName {
  184. my $ip = shift;
  185.  
  186. return undef unless $ip;
  187.  
  188. if( ! $dns ) {
  189. $dns = Net::DNS::Resolver->new();
  190. }
  191.  
  192. my $reverse = join( '.', reverse( split /\./, $ip )) . '.in-addr.arpa';
  193. if (my $ap = $dns->query( $reverse, 'PTR' )) {
  194. for my $pa ($ap->answer) {
  195. return $pa->ptrdname;
  196. }
  197. }
  198. return undef;
  199. }
  200.  
  201.  
  202. ###############################################################################
  203. #
  204. # This code lets us create a "table" object from data returned by an SNMP walk
  205. # $oid is the OID to fetch
  206. # $n is the number of righmost data points to use as an index.
  207. #
  208. ###############################################################################
  209.  
  210. package Net::SNMP::Table;
  211. use parent 'Net::SNMP';
  212.  
  213. sub table {
  214. my $self = shift;
  215. my $oid = shift;
  216. my $n = shift;
  217.  
  218. my $obj = TableItem::new($oid, $n);
  219.  
  220. my $res = $self->SUPER::get_table(-baseoid => $oid, -maxrepetitions => 30);
  221.  
  222. foreach my $x ( keys %{$res} ) {
  223. my @tmp = split /\./, $x;
  224. my $key = join ".", splice(@tmp, -1 * $n);
  225. $obj->item($key, $res->{$x});
  226. }
  227.  
  228. return $obj;
  229.  
  230. }
  231.  
  232. sub get {
  233. my $self = shift;
  234. my $oid = shift;
  235.  
  236. my $res = $self->SUPER::get_request(-varbindlist => [ $oid ]);
  237.  
  238. return undef if $res->{$oid} =~ /^noSuch/; # skip odd stuff that sometimes gets returned
  239. return undef if $res->{$oid} =~ /^0x/; # even odder...
  240.  
  241. return $res->{$oid};
  242.  
  243. }
  244.  
  245. ###############################################################################
  246. #
  247. # This is a container for SNMP table data
  248. #
  249. ###############################################################################
  250.  
  251. package TableItem;
  252.  
  253. sub new {
  254. my $class = shift;
  255. my $oid = shift;
  256. my $n = shift;
  257.  
  258.  
  259. my $self = {};
  260. $self->{oid} = $oid;
  261. $self->{n} = $n;
  262. $self->{table} = {};
  263.  
  264. bless $self;
  265.  
  266. return $self;
  267. }
  268.  
  269.  
  270. sub keys {
  271. my $self = shift;
  272.  
  273. return keys %{$self->{table}};
  274. }
  275.  
  276. sub item {
  277. my $self = shift;
  278. my $key = shift;
  279. my $data = shift;
  280.  
  281. $self->{table}->{$key} = $data if defined $data;
  282. return $self->{table}->{$key};
  283. }
  284.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement