]> git.decadent.org.uk Git - ap-utils.git/blob - src/stations.c
5eb272d3815f08c7e6f9a625abc0418c9a8f94e6
[ap-utils.git] / src / stations.c
1 /*
2  *      stations.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 <sys/wait.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <string.h>
26 #include "ap-utils.h"
27 #include "ap-curses.h"
28
29 #define STAS _("Associated Stations")
30 #define STAS_HEADER \
31         _(" #            MAC                                               ")
32 /* following for VERNET-enhanced ATMEL12350 MIB */
33 #define STAS_HEADER_VERNET \
34         _(" #     MAC       Parent MAC    RSSI  Status MACn      IP        ")
35
36 #define MAX_LINES LINES-4
37
38 extern int LINES;
39 extern WINDOW *main_sub;
40 extern short ap_type;
41 extern char IS_ATMEL12350_VERNET;
42 extern int sts_viewtype;
43
44 void stations()
45 {
46     char bridgeOperationalMode[] = {
47         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
48     };
49     char StasNum[] = {
50         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
51     };
52     char StasMac[] = {
53         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x02, 0x00
54     };
55
56     struct AssociatedSTAsInfo {
57         unsigned short Num;
58         unsigned char MacAddress[6];
59         /* following ones are specific for enhanced ATMEL 12350 MIB by VERNET */
60         unsigned char Status;
61         unsigned char Port;
62         unsigned char ParentMacAddress[6];
63         unsigned char RSSI;
64         unsigned char IP[4];
65     } *mac = NULL, get;
66
67     struct MacListStat *first = NULL, *curr = NULL;
68     char message[1024];
69     int mac_idx, begin, end, total_mac;
70     varbind varbinds[1];
71
72
73     if (ap_type == ATMEL12350) {
74         bridgeOperationalMode[5] = 0xE0;
75         bridgeOperationalMode[6] = 0x3E;
76         StasNum[5] = 0xE0;
77         StasNum[6] = 0x3E;
78         StasMac[5] = 0xE0;
79         StasMac[6] = 0x3E;
80     }   
81
82     /* find out in what mode the AP currently is */
83     varbinds[0].oid = bridgeOperationalMode;
84     varbinds[0].len_oid = sizeof(bridgeOperationalMode);
85     varbinds[0].value = bridgeOperationalMode;
86     varbinds[0].len_val = 0;
87     varbinds[0].type = NULL_VALUE;
88     print_help(WAIT_RET);
89     if (snmp(varbinds, 1, GET) <= 0) {
90           print_helperr(ERR_RET);
91           goto exit;
92     }
93
94     /* for AP in AP-Client mode & without VERNET firmware, disable status */
95     if (*(varbinds[0].value) == 3 && !IS_ATMEL12350_VERNET) {
96         mvwaddstr(main_sub, 3, 1, _("AP is currently in AP Client Mode => "
97             "no associated STAtions."));
98         print_help(ANY_KEY);
99         wrefresh(main_sub);
100         getch();
101         goto exit;
102     }
103
104     noecho();
105     wattrset(main_sub, COLOR_PAIR(3));
106     if (IS_ATMEL12350_VERNET)
107         mvwaddstr(main_sub, 0, 0, STAS_HEADER_VERNET);
108     else
109         mvwaddstr(main_sub, 0, 0, STAS_HEADER);
110     wattrset(main_sub, A_NORMAL);
111
112 refresh:
113     /* find out how many STAtions is in the list */
114     varbinds[0].oid = StasNum;
115     varbinds[0].len_oid = sizeof(StasNum);
116     varbinds[0].value = StasNum;
117     varbinds[0].type = NULL_VALUE;
118     varbinds[0].len_val = 0;
119
120     print_help(WAIT_RET);
121
122     if (snmp(varbinds, 1, GET) <= 0) {
123         print_helperr(ERR_RET);
124         getch();
125         goto exit;
126     }
127
128     total_mac = *(varbinds[0].value);
129     print_help(WAIT_SET);
130     mac_idx = 1;
131     while (mac_idx <= total_mac) {
132
133         /* tell the AP we want first mac_idx-th MAC */
134         varbinds[0].oid = StasMac;
135         varbinds[0].len_oid = sizeof(StasMac);
136         varbinds[0].type = INT_VALUE;
137         get.Num = swap2(mac_idx);
138         varbinds[0].value = (char *) &get;
139         varbinds[0].len_val = sizeof(get);
140
141         if (snmp(varbinds, 1, SET) <= 0) {
142             print_helperr(ERR_RET);
143             getch();
144             goto exit;
145         }
146
147         if (varbinds[0].len_val == 24) {
148             if (mac)
149                 free(mac);
150             mac =
151                 (struct AssociatedSTAsInfo *) malloc(varbinds[0].len_val);
152             memcpy(mac, varbinds[0].value, varbinds[0].len_val);
153             /* mac = (struct AssociatedSTAsInfo *) varbinds[0].value; */
154         } else {
155             print_helperr(_("AssociatedSTAsInfo packet error"));
156             goto exit;
157         }
158
159         if (first == NULL) {
160             first =
161                 (struct MacListStat *) malloc(sizeof(struct MacListStat));
162             curr = first;
163         } else {
164             curr->next =
165                 (struct MacListStat *) malloc(sizeof(struct MacListStat));
166             curr = curr->next;
167         }
168
169         memcpy(curr->addr, mac->MacAddress, 6);
170
171         if (IS_ATMEL12350_VERNET) {
172             curr->Status = mac->Status;
173             curr->Port = mac->Port;
174             memcpy(curr->ParentMacAddress, mac->ParentMacAddress, 6);
175             curr->rssi = mac->RSSI;
176             memcpy(&(curr->IP.s_addr), mac->IP, 4);
177         }
178
179         curr->next = NULL;
180         mac_idx++;
181     }
182
183     begin = 1;
184     end = (MAX_LINES < mac_idx) ? MAX_LINES : mac_idx;
185
186     if (IS_ATMEL12350_VERNET)
187         print_help(_("Arrows - scroll; S - save to file; Q - return; "
188                      "T - toggle view; Other key - refresh"));
189     else
190         print_help(_("Arrows - scroll; S - save to file; Q - return; "
191                      "Other key - refresh"));
192
193     while (1) {
194         sprintf(message, "%s: %d", STAS, total_mac);
195         print_title(message);
196
197         if (IS_ATMEL12350_VERNET) {
198             print_viewtype_rssi();
199             scroll_rows(first, begin, end, 1, 3);
200         } else
201             scroll_rows(first, begin, end, 1, 0);
202
203         switch (getch()) {
204             case 'S':
205             case 's':
206                 save_Stations(first);
207                 continue;
208             case KEY_RIGHT:
209             case KEY_DOWN:
210                 if (end < mac_idx) {
211                     begin++;
212                     end++;
213                 }
214                 continue;
215             case KEY_UP:
216             case KEY_LEFT:
217                 if (begin > 1) {
218                     begin--;
219                     end--;
220                 }
221                 continue;
222             case 'Q':
223             case 'q':
224                 goto exit;
225             case 'T':
226             case 't':
227                 if (IS_ATMEL12350_VERNET) {
228                     sts_viewtype += 1;
229                     if (sts_viewtype == 3)
230                         sts_viewtype = 0;
231                 }
232                 continue;
233             default:
234                 while ((curr = first)) {
235                     first = curr->next;
236                     free(curr);
237                 }
238                 first = curr = NULL;
239                 goto refresh;
240         }
241     }
242
243 exit:
244     while ((curr = first)) {
245         first = curr->next;
246         free(curr);
247     }
248     print_title("");
249     clear_main(0);
250 }
251
252 void nwn_stations()
253 {
254     unsigned char Mac[] = {
255         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
256         0x02, 0x01, 0x02, 0x80, 0x00 };
257     unsigned char Quality[] = {
258         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
259         0x02, 0x01, 0x03, 0x80, 0x00 };
260     unsigned char Age[] = {
261         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
262         0x02, 0x01, 0x04, 0x80, 0x00 };
263     unsigned char RSSI[] = {
264         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
265         0x02, 0x01, 0x05, 0x80, 0x00 };
266
267     struct MacListStat *first = NULL, *curr = NULL;
268     char null[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, message[1024];
269     int mac_idx, begin, end;
270     varbind varbinds[4];
271     unsigned char next_num;
272
273
274     mac_idx = 0;
275     print_title(_("Associated stations"));
276     mvwaddstr(main_sub, 0, 3,
277               _("Id       MAC address     Quality  Age  RSSI"));
278     noecho();
279     print_help(WAIT_RET);
280
281     varbinds[0].oid = Mac;
282     varbinds[0].len_oid = sizeof(Mac);
283     varbinds[0].len_val = 0;
284     varbinds[0].type = NULL_VALUE;
285     if (snmp(varbinds, 1, GET_NEXT) <= 0) {
286         print_helperr(ERR_RET);
287         goto exit;
288     }
289    next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
290
291    while (memcmp(varbinds[0].oid, Mac, sizeof(Mac) - 2) == 0) {
292
293         Mac[sizeof(Mac) - 1] = next_num;
294         Quality[sizeof(Mac) - 1] = next_num;
295         Age[sizeof(Mac) - 1] = next_num;
296         RSSI[sizeof(Mac) - 1] = next_num;
297
298         if(sizeof(Mac) == varbinds[0].len_oid) {
299                 Mac[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
300                 Quality[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
301                 Age[sizeof(Mac) - 2]  = varbinds[0].oid[varbinds[0].len_oid - 2];
302                 RSSI[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
303         }
304
305         varbinds[0].oid = Mac;
306         varbinds[0].len_oid = sizeof(Mac);
307         varbinds[0].len_val = 0;
308         varbinds[0].type = NULL_VALUE;
309         varbinds[1].oid = Quality;
310         varbinds[1].len_oid = sizeof(Quality);
311         varbinds[1].len_val = 0;
312         varbinds[1].type = NULL_VALUE;
313         varbinds[2].oid = Age;
314         varbinds[2].len_oid = sizeof(Age);
315         varbinds[2].len_val = 0;
316         varbinds[2].type = NULL_VALUE;
317         varbinds[3].oid = RSSI;
318         varbinds[3].len_oid = sizeof(RSSI);
319         varbinds[3].len_val = 0;
320         varbinds[3].type = NULL_VALUE;
321         if (snmp(varbinds, 4, GET) <= 0) {
322             print_helperr(ERR_RET);
323             getch();
324             goto exit;
325         }
326
327         if (memcmp(null, varbinds[0].value, 6)) {
328             if (first == NULL) {
329                 first =
330                     (struct MacListStat *)
331                     malloc(sizeof(struct MacListStat));
332                 curr = first;
333             } else {
334                 curr->next =
335                     (struct MacListStat *)
336                     malloc(sizeof(struct MacListStat));
337                 curr = curr->next;
338             } 
339             memcpy(curr->addr, varbinds[0].value, 6);
340             curr->quality = *varbinds[1].value;
341             curr->idle = *varbinds[2].value;
342             curr->rssi = *varbinds[3].value;
343             curr->next = NULL;
344             mac_idx++;
345         }
346
347         varbinds[0].oid = Mac;
348         varbinds[0].len_oid = sizeof(Mac);
349         varbinds[0].len_val = 0;
350         varbinds[0].type = NULL_VALUE;
351         if (snmp(varbinds, 1, GET_NEXT) <= 0) {
352             print_helperr(ERR_RET);
353             goto exit;
354         }
355         next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
356                                                 
357     }
358    sprintf(message, "%s: %d", _("Associated stations"), mac_idx);
359    print_title(message);
360    if(mac_idx) {
361     begin = 1;
362     end = (MAX_LINES < mac_idx+1) ? MAX_LINES : mac_idx+1;
363     scroll_rows(first, begin, end, 1, 1);
364     print_help(_("Arrows - scroll; S - save to file; Q - quit to menu."));
365     while (1) {
366         switch (getch()) {
367         case 'S':
368         case 's':
369             save_Stations(first);
370             continue;
371         case KEY_DOWN:
372         case KEY_RIGHT:
373             if (end < mac_idx+1) {
374                 begin++;
375                 end++;
376                 scroll_rows(first, begin, end, 1, 1);
377             }
378             continue;
379         case KEY_UP:
380         case KEY_LEFT:
381             if (begin > 1) {
382                 begin--;
383                 end--;
384                 scroll_rows(first, begin, end, 1, 1);
385             }
386             continue;
387         case 'Q':
388         case 'q':
389             goto exit;
390         }
391     }
392    }
393    
394    print_help(ANY_KEY);
395    getch();
396    
397   exit:
398     while ((curr = first)) {
399         first = curr->next;
400         free(curr);
401     }
402     
403     print_title("");
404     clear_main(0);
405 }
406