]> git.decadent.org.uk Git - ap-utils.git/blob - src/ap-mrtg.c
Update config.{sub,guess} in the right place at build time - closes: #534825
[ap-utils.git] / src / ap-mrtg.c
1 /*
2  *      ap-mrtg.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
5  *
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.
9  *
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.
14  *
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
18  *
19  */
20 #include <stdio.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #if defined (__GLIBC__)
28 #include <libgen.h>
29 #endif
30 #include "ap-utils.h"
31
32 #define ERR_STR_V "\n\n-\n\n"
33 #define ERR_STR_N "999999999\n999999999\n-\n\n"
34
35 short ap_type;
36 char *community = NULL;
37 struct in_addr ap_ip;
38
39 void usage()
40 {
41     printf(_("\nUsage:\n"));
42     printf(_("\tap-mrtg -i ip -c community -t type [-b bssid] [-n name] "
43              "[-v] [-h] [-r]\n\n"));
44     printf(_("Get stats from AP and return it in MRTG parsable format\n\n"));
45     printf(_("-i ip        - AP ip address\n"));
46     printf(_("-c community - SNMP community string\n"));
47     printf(_("-t type      - statistics type <w>ireless, <e>thernet, "
48              "associated <s>tations or <l>ink quality (last one will only "));
49     printf(_("work with ATMEL410 MIB devices in AP Client mode)\n"));
50     printf(_("-b bssid     - mac address of the AP from which get link quality"
51              ", only if type=l\n"));
52     printf(_("-n name      - AP name - for check only\n")); 
53     printf(_("-v           - report MRTG about problems connecting to AP\n"));
54     printf(_("-r           - reset AP when getting LinkQuality stats\n"));
55     printf(_("-h           - print this help screen\n\n"));
56     printf(_("ap-mrtg %s Copyright (c) 2002-2003 Roman Festchook\n\n"),
57            VERSION);
58 }
59
60 int main(int argc, char **argv)
61 {
62     extern char *optarg;
63     extern int optind;
64     extern int opterr;
65     extern int optopt;
66     int opt = 0;
67
68     struct ap {
69         char mac[6];
70         unsigned char q1;
71         unsigned char q2;
72         unsigned char channel;
73         unsigned char x2;
74         unsigned char options;
75         unsigned char x3[5];
76         unsigned char essid[32];
77     } *app = NULL;
78
79     char sysDescr_NWN[] = {
80         0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
81     };
82     char sysDescr_ATMEL[] = {
83         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
84     };
85     char bridgeOperationalMode[] = {
86         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
87     };
88     char EthRxStatistics[] = {
89         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x01, 0x00
90     };
91     char EthTxStatistics[] = {
92         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x02, 0x00
93     };
94     char operAccessPointName[] = {
95         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0A, 0x00
96     };
97     char wirelessStatistics[] = {
98         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01, 0x00
99     };
100     char AssociatedSTAsNum[] = {
101         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
102     };
103     char wirelessKnownAPs[] = {
104         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x07, 0x01, 0x00
105     };
106
107     struct EthRxStatistics_s *EthRxStat = NULL;
108     struct EthTxStatistics_s *EthTxStat = NULL;
109     struct wirelessStatistics_s *WirelessStat = NULL;
110     varbind varbinds[2];
111     int i, reset_flag=0;
112     char message[12], bssid_flag,  stat_type = 0, *ERR_STR =
113         ERR_STR_N, *bssid = NULL, *name = NULL, *cp;
114
115 #ifdef HAVE_GETTEXT
116     setlocale(LC_ALL, "");
117     bindtextdomain("ap-utils", LOCALEDIR);
118     textdomain("ap-utils");
119 #endif
120
121     if (argc < 4) {
122         usage();
123         exit(0);
124     }
125
126     do {
127         opterr = 0;
128         switch (opt = getopt(argc, argv, "i:c:t:b:n:rv")) {
129         case 'i':
130             for (cp = optarg, i = 0; *cp && (cp = index(cp, '.')); cp++, i++);
131             if (i < 3 || inet_aton(optarg, &ap_ip) == 0) {
132                 printf(_("Error: invalid IP-address.\n"));
133                 return 1;
134             }
135             break;
136         case 't':
137             stat_type = optarg[0];
138             break;
139         case 'v':
140             ERR_STR = ERR_STR_V;
141             break;
142         case 'c':
143             community = malloc(strlen(optarg) + 1);
144             strncpy(community, optarg, strlen(optarg) + 1);
145             break;
146         case 'b':
147             bssid = malloc(strlen(optarg) + 1);
148             strncpy(bssid, optarg, strlen(optarg) + 1);
149             break;
150         case 'n':
151             name = malloc(strlen(optarg) + 1);
152             strncpy(name, optarg, strlen(optarg) + 1);
153             break;
154         case 'r':
155             reset_flag=1;
156             break;
157         case -1:
158             break;
159         default:
160             usage();
161             goto quit;
162         }
163     } while (opt != -1);
164
165     if (!community) {
166         usage();
167         goto quit;
168     }
169
170     /*
171      * Part detecting ap_type (ATMEL AP MIB type) follows.
172      * We could use get_mib_details() here with advantage, but it would
173      * have to involve 1. putting it to separate file in lib/ and
174      * 2. patch it so it would not contain curses-related commands (TODO)
175      */
176
177     /* determine private MIB type according to enterprises ID */
178     varbinds[0].oid = sysDescr_NWN;
179     varbinds[0].len_oid = sizeof(sysDescr_NWN);
180     varbinds[0].value = NULL;
181     varbinds[0].len_val = 0;
182     varbinds[0].type = NULL_VALUE;
183     if (snmp(varbinds, 1, GET) > 0) {
184         ap_type = NWN;
185     } else {
186         varbinds[0].oid = sysDescr_ATMEL;
187         varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
188         varbinds[0].value = NULL;
189         varbinds[0].len_val = 0;
190         varbinds[0].type = NULL_VALUE;
191         if (snmp(varbinds, 1, GET) > 0) {
192             ap_type = ATMEL410;
193         } else {
194             sysDescr_ATMEL[5] = 0xE0;
195             sysDescr_ATMEL[6] = 0x3E;
196             varbinds[0].oid = sysDescr_ATMEL;
197             varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
198             varbinds[0].value = NULL;
199             varbinds[0].len_val = 0;
200             varbinds[0].type = NULL_VALUE;
201             if (snmp(varbinds, 1, GET) > 0) {
202                 ap_type = ATMEL12350;
203             } else {
204                 printf(_("Unable to determine AP MIB type "
205                     "(no response from AP)."));
206                 return 1;
207             }
208         }
209     }
210
211     if (ap_type == NWN) {
212         printf("NWN devices are not yet supported.");
213         return 1;
214     }
215
216     if (ap_type == ATMEL12350) {
217         bridgeOperationalMode[5] = 0xE0;
218         bridgeOperationalMode[6] = 0x3E;
219         EthRxStatistics[5] = 0xE0;
220         EthRxStatistics[6] = 0x3E;
221         EthTxStatistics[5] = 0xE0;
222         EthTxStatistics[6] = 0x3E;
223         operAccessPointName[5] = 0xE0;
224         operAccessPointName[6] = 0x3E;
225         wirelessStatistics[5] = 0xE0;
226         wirelessStatistics[6] = 0x3E;
227         AssociatedSTAsNum[5] = 0xE0;
228         AssociatedSTAsNum[6] = 0x3E;
229         wirelessKnownAPs[5] = 0xE0;
230         wirelessKnownAPs[6] = 0x3E;
231     }
232
233     switch (stat_type) {
234
235     case 'e':
236         varbinds[0].oid = EthRxStatistics;
237         varbinds[0].len_oid = sizeof(EthRxStatistics);
238         varbinds[0].value = EthRxStatistics;
239         varbinds[0].len_val = 0;
240         varbinds[0].type = NULL_VALUE;
241         varbinds[1].oid = EthTxStatistics;
242         varbinds[1].len_oid = sizeof(EthTxStatistics);
243         varbinds[1].value = EthTxStatistics;
244         varbinds[1].len_val = 0;
245         varbinds[1].type = NULL_VALUE;
246
247         if (snmp(varbinds, 2, GET) < 2) {
248             printf(ERR_STR);
249             return 1;
250         }
251
252         if (varbinds[0].len_val == 64) {
253             if (EthRxStat)
254                 free(EthRxStat);
255             EthRxStat =
256                 (struct EthRxStatistics_s *) malloc(varbinds[0].
257                                                        len_val);
258             memcpy(EthRxStat, varbinds[0].value, varbinds[0].len_val);
259         } else {
260             printf(ERR_STR);
261             return 1;
262         }
263
264         if (varbinds[1].len_val == 56) {
265             if (EthTxStat)
266                 free(EthTxStat);
267             EthTxStat =
268                 (struct EthTxStatistics_s *) malloc(varbinds[1].
269                                                        len_val);
270             memcpy(EthTxStat, varbinds[1].value, varbinds[1].len_val);
271         } else {
272             printf(ERR_STR);
273             return 1;
274         }
275         printf("%u\n%u\n", swap4(EthRxStat->TotalBytesRx),
276                swap4(EthTxStat->TotalBytesTx));
277         if (EthRxStat)
278             free(EthRxStat);
279         if (EthTxStat)
280             free(EthTxStat);
281         break;
282     case 'w':
283         varbinds[0].oid = wirelessStatistics;
284         varbinds[0].len_oid = sizeof(wirelessStatistics);
285         varbinds[0].value = wirelessStatistics;
286         varbinds[0].len_val = 0;
287         varbinds[0].type = NULL_VALUE;
288
289         if (snmp(varbinds, 1, GET) <= 0) {
290             printf(ERR_STR);
291             return 1;
292         }
293
294         if (varbinds[0].len_val == 88 || varbinds[0].len_val == 104) {
295             /*
296              * 88 ... using traditional ATMEL 12350 MIB
297              * 104 .. using functionally enhanced ATMEL 12350 MIB by EZYNET
298              */
299             if (WirelessStat)
300                 free(WirelessStat);
301             WirelessStat =
302                 (struct wirelessStatistics_s *) malloc(varbinds[0].len_val);
303             memcpy(WirelessStat, varbinds[0].value, varbinds[0].len_val);
304         } else {
305             printf(ERR_STR);
306             return 1;
307         }
308         printf("%u\n%u\n",
309                swap4(WirelessStat->UnicastReceivedPackets) +
310                swap4(WirelessStat->BroadcastReceivedPackets) +
311                swap4(WirelessStat->MulticastReceivedPackets),
312                swap4(WirelessStat->UnicastTransmittedPackets) +
313                swap4(WirelessStat->BroadcastTransmittedPackets) +
314                swap4(WirelessStat->MulticastTransmittedPackets));
315         break;
316
317     case 's':
318         varbinds[0].oid = AssociatedSTAsNum;
319         varbinds[0].len_oid = sizeof(AssociatedSTAsNum);
320         varbinds[0].value = AssociatedSTAsNum;
321         varbinds[0].len_val = 0;
322         varbinds[0].type = NULL_VALUE;
323
324         if (snmp(varbinds, 1, GET) <= 0) {
325             printf(ERR_STR);
326             return 1;
327         }
328
329         printf("%u\n0\n", *varbinds[0].value);
330         break;
331
332     case 'l':
333         varbinds[0].oid = bridgeOperationalMode;
334         varbinds[0].len_oid = sizeof(bridgeOperationalMode);
335         varbinds[0].len_val = 0;
336         varbinds[0].type = NULL_VALUE;
337
338         if (snmp(varbinds, 1, GET) <= 0) {
339             printf(ERR_STR);
340             return 1;
341         }
342
343         if (!(ap_type == ATMEL410 && *(varbinds[0].value) == 3)) {
344             printf(ERR_STR);
345             return 1;
346         }
347
348         if (reset_flag) {
349                 if (SysReset()) {
350                     printf(ERR_STR);
351                     return 1;
352                 }
353                 sleep(10);
354         }
355
356         varbinds[0].oid = wirelessKnownAPs;
357         varbinds[0].len_oid = sizeof(wirelessKnownAPs);
358         varbinds[0].type = NULL_VALUE;
359         varbinds[0].len_val = 0;
360
361         if (snmp(varbinds, 1, GET) <= 0) {
362             printf(ERR_STR);
363             return 1;
364         }
365         bssid_flag = 1;
366         for (i = 0; i < varbinds[0].len_val; i += 48) {
367             if (app)
368                 free(app);
369             app = (struct ap *) malloc(48);
370             memcpy(app, varbinds[0].value + i, 48);
371             if (!app->channel)
372                 continue;
373             if (bssid) {
374                 sprintf(message, "%02X%02X%02X%02X%02X%02X",
375                         app->mac[0] & 0xFF, app->mac[1] & 0xFF,
376                         app->mac[2] & 0xFF, app->mac[3] & 0xFF,
377                         app->mac[4] & 0xFF, app->mac[5] & 0xFF);
378                 if (memcmp(message, bssid, 12))
379                     continue;
380             };
381             printf("%d\n%d\n", app->q2,
382                    96 - app->q1);
383             bssid_flag = 0;
384             break;
385         }
386         if (bssid_flag)
387             printf(ERR_STR);
388         break;
389     default:
390         usage();
391         goto quit;
392     }
393
394     printf("-\n");
395
396     if ( name != NULL ) {
397         varbinds[0].oid = operAccessPointName;
398         varbinds[0].len_oid = sizeof(operAccessPointName);
399         varbinds[0].len_val = 0;
400         varbinds[0].type = NULL_VALUE;
401         if (snmp(varbinds, 1, GET) <= 0) {
402                 printf("\n");
403                 return 1;
404         }
405
406         for (i = 0; i < 32 && *(varbinds[0].value + i); i++)
407                 putchar(*(varbinds[0].value + i));
408                 putchar('\n');
409           if (strncmp(name,varbinds[0].value,strlen(name)) ){
410                 return 2;
411         }
412     } else {
413         printf("-\n");
414     }
415
416   quit:
417     if (community)
418         free(community);
419     if (app)
420         free(app);
421     if (bssid)
422         free(bssid);
423     if (name)
424         free(name);
425     return 0;
426 }