2 * ap-mrtg.c from Access Point SNMP Utils for Linux
4 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License Version 2 from
8 * June 1991 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #if defined (__GLIBC__)
32 #define ERR_STR_V "\n\n-\n\n"
33 #define ERR_STR_N "999999999\n999999999\n-\n\n"
36 char *community = NULL;
42 printf(_("\nUsage:\n"));
43 printf(_("\tap-mrtg -i ip -c community -t type [-b bssid] [-n name] "
44 "[-v] [-h] [-r]\n\n"));
45 printf(_("Get stats from AP and return it in MRTG parsable format\n\n"));
46 printf(_("-i ip - AP ip address\n"));
47 printf(_("-c community - SNMP community string\n"));
48 printf(_("-t type - statistics type <w>ireless, <e>thernet, "
49 "associated <s>tations or <l>ink quality (last one will only "));
50 printf(_("work with ATMEL410 MIB devices in AP Client mode)\n"));
51 printf(_("-b bssid - mac address of the AP from which get link quality"
52 ", only if type=l\n"));
53 printf(_("-n name - AP name - for check only\n"));
54 printf(_("-v - report MRTG about problems connecting to AP\n"));
55 printf(_("-r - reset AP when getting LinkQuality stats\n"));
56 printf(_("-h - print this help screen\n\n"));
57 printf(_("ap-mrtg %s Copyright (c) 2002-2003 Roman Festchook\n\n"),
61 int main(int argc, char **argv)
73 unsigned char channel;
75 unsigned char options;
77 unsigned char essid[32];
80 char sysDescr_NWN[] = {
81 0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
83 char sysDescr_ATMEL[] = {
84 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
86 char bridgeOperationalMode[] = {
87 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
89 char EthRxStatistics[] = {
90 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x01, 0x00
92 char EthTxStatistics[] = {
93 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x02, 0x00
95 char operAccessPointName[] = {
96 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0A, 0x00
98 char wirelessStatistics[] = {
99 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01, 0x00
101 char AssociatedSTAsNum[] = {
102 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
104 char wirelessKnownAPs[] = {
105 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x07, 0x01, 0x00
108 struct EthRxStatistics_s *EthRxStat = NULL;
109 struct EthTxStatistics_s *EthTxStat = NULL;
110 struct wirelessStatistics_s *WirelessStat = NULL;
113 char message[12], bssid_flag, stat_type = 0, *ERR_STR =
114 ERR_STR_N, *bssid = NULL, *name = NULL, *cp;
115 struct sockaddr_in client;
118 setlocale(LC_ALL, "");
119 bindtextdomain("ap-utils", LOCALEDIR);
120 textdomain("ap-utils");
123 memset(&client, 0, sizeof client);
124 client.sin_family = AF_INET;
125 client.sin_port = INADDR_ANY;
126 client.sin_addr.s_addr = INADDR_ANY;
135 switch (opt = getopt(argc, argv, "i:c:t:b:n:rv")) {
137 for (cp = optarg, i = 0; *cp && (cp = index(cp, '.')); cp++, i++);
138 if (i < 3 || inet_aton(optarg, &ap_ip) == 0) {
139 printf(_("Error: invalid IP-address.\n"));
144 stat_type = optarg[0];
150 community = malloc(strlen(optarg) + 1);
151 strncpy(community, optarg, strlen(optarg) + 1);
154 bssid = malloc(strlen(optarg) + 1);
155 strncpy(bssid, optarg, strlen(optarg) + 1);
158 name = malloc(strlen(optarg) + 1);
159 strncpy(name, optarg, strlen(optarg) + 1);
177 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
178 perror(_("Create socket error"));
181 if (bind(sockfd, (struct sockaddr *) &client, SIZE) == -1) {
182 perror(_("Bind socket error"));
187 * Part detecting ap_type (ATMEL AP MIB type) follows.
188 * We could use get_mib_details() here with advantage, but it would
189 * have to involve 1. putting it to separate file in lib/ and
190 * 2. patch it so it would not contain curses-related commands (TODO)
193 /* determine private MIB type according to enterprises ID */
194 varbinds[0].oid = sysDescr_NWN;
195 varbinds[0].len_oid = sizeof(sysDescr_NWN);
196 varbinds[0].value = NULL;
197 varbinds[0].len_val = 0;
198 varbinds[0].type = NULL_VALUE;
199 if (snmp(varbinds, 1, GET) > 0) {
202 varbinds[0].oid = sysDescr_ATMEL;
203 varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
204 varbinds[0].value = NULL;
205 varbinds[0].len_val = 0;
206 varbinds[0].type = NULL_VALUE;
207 if (snmp(varbinds, 1, GET) > 0) {
210 sysDescr_ATMEL[5] = 0xE0;
211 sysDescr_ATMEL[6] = 0x3E;
212 varbinds[0].oid = sysDescr_ATMEL;
213 varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
214 varbinds[0].value = NULL;
215 varbinds[0].len_val = 0;
216 varbinds[0].type = NULL_VALUE;
217 if (snmp(varbinds, 1, GET) > 0) {
218 ap_type = ATMEL12350;
220 printf(_("Unable to determine AP MIB type "
221 "(no response from AP)."));
227 if (ap_type == NWN) {
228 printf("NWN devices are not yet supported.");
232 if (ap_type == ATMEL12350) {
233 bridgeOperationalMode[5] = 0xE0;
234 bridgeOperationalMode[6] = 0x3E;
235 EthRxStatistics[5] = 0xE0;
236 EthRxStatistics[6] = 0x3E;
237 EthTxStatistics[5] = 0xE0;
238 EthTxStatistics[6] = 0x3E;
239 operAccessPointName[5] = 0xE0;
240 operAccessPointName[6] = 0x3E;
241 wirelessStatistics[5] = 0xE0;
242 wirelessStatistics[6] = 0x3E;
243 AssociatedSTAsNum[5] = 0xE0;
244 AssociatedSTAsNum[6] = 0x3E;
245 wirelessKnownAPs[5] = 0xE0;
246 wirelessKnownAPs[6] = 0x3E;
252 varbinds[0].oid = EthRxStatistics;
253 varbinds[0].len_oid = sizeof(EthRxStatistics);
254 varbinds[0].value = EthRxStatistics;
255 varbinds[0].len_val = 0;
256 varbinds[0].type = NULL_VALUE;
257 varbinds[1].oid = EthTxStatistics;
258 varbinds[1].len_oid = sizeof(EthTxStatistics);
259 varbinds[1].value = EthTxStatistics;
260 varbinds[1].len_val = 0;
261 varbinds[1].type = NULL_VALUE;
263 if (snmp(varbinds, 2, GET) < 2) {
268 if (varbinds[0].len_val == 64) {
272 (struct EthRxStatistics_s *) malloc(varbinds[0].
274 memcpy(EthRxStat, varbinds[0].value, varbinds[0].len_val);
280 if (varbinds[1].len_val == 56) {
284 (struct EthTxStatistics_s *) malloc(varbinds[1].
286 memcpy(EthTxStat, varbinds[1].value, varbinds[1].len_val);
291 printf("%u\n%u\n", swap4(EthRxStat->TotalBytesRx),
292 swap4(EthTxStat->TotalBytesTx));
299 varbinds[0].oid = wirelessStatistics;
300 varbinds[0].len_oid = sizeof(wirelessStatistics);
301 varbinds[0].value = wirelessStatistics;
302 varbinds[0].len_val = 0;
303 varbinds[0].type = NULL_VALUE;
305 if (snmp(varbinds, 1, GET) <= 0) {
310 if (varbinds[0].len_val == 88 || varbinds[0].len_val == 104) {
312 * 88 ... using traditional ATMEL 12350 MIB
313 * 104 .. using functionally enhanced ATMEL 12350 MIB by EZYNET
318 (struct wirelessStatistics_s *) malloc(varbinds[0].len_val);
319 memcpy(WirelessStat, varbinds[0].value, varbinds[0].len_val);
325 swap4(WirelessStat->UnicastReceivedPackets) +
326 swap4(WirelessStat->BroadcastReceivedPackets) +
327 swap4(WirelessStat->MulticastReceivedPackets),
328 swap4(WirelessStat->UnicastTransmittedPackets) +
329 swap4(WirelessStat->BroadcastTransmittedPackets) +
330 swap4(WirelessStat->MulticastTransmittedPackets));
334 varbinds[0].oid = AssociatedSTAsNum;
335 varbinds[0].len_oid = sizeof(AssociatedSTAsNum);
336 varbinds[0].value = AssociatedSTAsNum;
337 varbinds[0].len_val = 0;
338 varbinds[0].type = NULL_VALUE;
340 if (snmp(varbinds, 1, GET) <= 0) {
345 printf("%u\n0\n", *varbinds[0].value);
349 varbinds[0].oid = bridgeOperationalMode;
350 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
351 varbinds[0].len_val = 0;
352 varbinds[0].type = NULL_VALUE;
354 if (snmp(varbinds, 1, GET) <= 0) {
359 if (!(ap_type == ATMEL410 && *(varbinds[0].value) == 3)) {
372 varbinds[0].oid = wirelessKnownAPs;
373 varbinds[0].len_oid = sizeof(wirelessKnownAPs);
374 varbinds[0].type = NULL_VALUE;
375 varbinds[0].len_val = 0;
377 if (snmp(varbinds, 1, GET) <= 0) {
382 for (i = 0; i < varbinds[0].len_val; i += 48) {
385 app = (struct ap *) malloc(48);
386 memcpy(app, varbinds[0].value + i, 48);
390 sprintf(message, "%02X%02X%02X%02X%02X%02X",
391 app->mac[0] & 0xFF, app->mac[1] & 0xFF,
392 app->mac[2] & 0xFF, app->mac[3] & 0xFF,
393 app->mac[4] & 0xFF, app->mac[5] & 0xFF);
394 if (memcmp(message, bssid, 12))
397 printf("%d\n%d\n", app->q2,
412 if ( name != NULL ) {
413 varbinds[0].oid = operAccessPointName;
414 varbinds[0].len_oid = sizeof(operAccessPointName);
415 varbinds[0].len_val = 0;
416 varbinds[0].type = NULL_VALUE;
417 if (snmp(varbinds, 1, GET) <= 0) {
422 for (i = 0; i < 32 && *(varbinds[0].value + i); i++)
423 putchar(*(varbinds[0].value + i));
425 if (strncmp(name,varbinds[0].value,strlen(name)) ){