]> git.decadent.org.uk Git - ap-utils.git/blob - src/stations.c
Imported Upstream version 1.5~pre2
[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  * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 from
9  * June 1991 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 #include <sys/wait.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <fcntl.h>
25 #include <signal.h>
26 #include <string.h>
27 #include "ap-utils.h"
28
29 #define MAX_LINES LINES-4
30
31 extern int LINES;
32 extern WINDOW *main_sub;
33 extern short ap_type, ap_vendorext;
34 extern int sts_viewtype;
35
36 void atmel_stations()
37 {
38     char bridgeOperationalMode[] = {
39         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
40     };
41     char AssociatedSTAsNum[] = {
42         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
43     };
44     char AssociatedSTAsInfo[] = {
45         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x02, 0x00
46     };
47
48     /* AP mode: connected APClients info */
49
50     struct AssociatedSTAsInfo_ATMEL410 ap_410;
51     struct AssociatedSTAsInfo_ATMEL12350 ap_12350;
52
53     struct MacListStat *first = NULL, *curr = NULL;
54     char message[1024];
55     int mac_idx, begin, end, total_mac;
56     varbind varbinds[1];
57
58
59     if (ap_type == ATMEL12350) {
60         bridgeOperationalMode[5] = 0xE0;
61         bridgeOperationalMode[6] = 0x3E;
62         AssociatedSTAsNum[5] = 0xE0;
63         AssociatedSTAsNum[6] = 0x3E;
64         AssociatedSTAsInfo[5] = 0xE0;
65         AssociatedSTAsInfo[6] = 0x3E;
66     }   
67
68     /* find out mode the device is currently in */
69     varbinds[0].oid = bridgeOperationalMode;
70     varbinds[0].len_oid = sizeof(bridgeOperationalMode);
71     varbinds[0].value = bridgeOperationalMode;
72     varbinds[0].len_val = 0;
73     varbinds[0].type = NULL_VALUE;
74     print_help(WAIT_RET);
75     if (snmp(varbinds, 1, GET) <= 0) {
76           print_helperr(ERR_RET);
77           goto exit;
78     }
79
80     /* Rule out all modes except AP(2). */
81     if (*(varbinds[0].value) != 2) {
82         mvwaddstr(main_sub, 1, 1, _("Not available (device not in AP mode)."));
83         print_help(ANY_KEY);
84         wrefresh(main_sub);
85         getch();
86         goto exit;
87     }
88
89     noecho();
90
91     wattrset(main_sub, COLOR_PAIR(13));
92     mvwaddstr(main_sub, 0, 0,
93         _("  #     MAC       Parent MAC  RSSI   LQ Sts MACn      IP        "));
94     wattrset(main_sub, A_NORMAL);
95
96 refresh:
97     /* find out how many STAtions is in the list */
98     varbinds[0].oid = AssociatedSTAsNum;
99     varbinds[0].len_oid = sizeof(AssociatedSTAsNum);
100     varbinds[0].value = AssociatedSTAsNum;
101     varbinds[0].type = NULL_VALUE;
102     varbinds[0].len_val = 0;
103
104     print_help(WAIT_RET);
105
106     if (snmp(varbinds, 1, GET) <= 0) {
107         print_helperr(ERR_RET);
108         getch();
109         goto exit;
110     }
111
112     total_mac = *(varbinds[0].value);
113     print_help(WAIT_SET);
114     mac_idx = 1;
115
116     while (mac_idx <= total_mac) {
117         /*
118          * Tell the AP we want mac_idx-th AssociatedSTAsInfo structure.
119          * Note: since:
120          * - position of 'Index' member in ap_* struct is always the same
121          * - only the 'Index' member is actually to be used
122          * - both structures have same size (24)
123          * we may pick *any* ap_* struct here.
124          */
125         varbinds[0].oid = AssociatedSTAsInfo;
126         varbinds[0].len_oid = sizeof(AssociatedSTAsInfo);
127         varbinds[0].type = INT_VALUE;
128         ap_410.Index = swap2(mac_idx);
129         varbinds[0].value = (char *)&ap_410;
130         varbinds[0].len_val = sizeof(ap_410);
131
132         if (snmp(varbinds, 1, SET) <= 0) {
133             print_helperr(ERR_RET);
134             getch();
135             goto exit;
136         }
137
138         if (varbinds[0].len_val != 24) {
139             print_helperr(_("AssociatedSTAsInfo packet error"));
140             goto exit;
141         }
142
143         if (first == NULL) {
144             first =
145                 (struct MacListStat *) calloc(1, sizeof(struct MacListStat));
146             curr = first;
147         } else {
148             curr->next =
149                 (struct MacListStat *) calloc(1, sizeof(struct MacListStat));
150             curr = curr->next;
151         }
152
153         /* lets not use black magic (casting) here, ok? */
154         if (ap_type == ATMEL410) {
155             memcpy(&ap_410, varbinds[0].value, sizeof(ap_410));
156
157             memcpy(curr->addr, ap_410.MacAddress, 6);
158             if (ap_vendorext == SBRIDGES) {
159                 memcpy(curr->ParentMacAddress, ap_410.ParentMacAddress, 6);
160                 memcpy(&(curr->IP.s_addr), ap_410.IP, 4);
161                 curr->rssi = ap_410.RSSI;
162                 curr->quality = ap_410.LinkQuality;
163                 curr->Status = ap_410.Status;
164                 curr->Port = ap_410.Port;
165             }
166         } else { /* ap_type == ATMEL12350 */
167             memcpy(&ap_12350, varbinds[0].value, sizeof(ap_12350));
168
169             memcpy(curr->addr, ap_12350.MacAddress, 6);
170             if (ap_vendorext == EZYNET) {
171                 memcpy(curr->ParentMacAddress, ap_12350.ParentMacAddress, 6);
172                 memcpy(&(curr->IP.s_addr), ap_12350.IP, 4);
173                 curr->rssi = ap_12350.RSSI;
174                 /* curr->quality stays empty */
175                 curr->Status = ap_12350.Status;
176                 curr->Port = ap_12350.Port;
177             }
178         }
179
180         curr->next = NULL;
181         mac_idx++;
182     }
183
184     begin = 1;
185     end = (MAX_LINES < mac_idx) ? MAX_LINES : mac_idx;
186
187     sprintf(message, "%s: %d", ST_TITLE, total_mac);
188     while (1) {
189         if ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
190             (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) {
191             print_top_rssi(message);
192             print_help(_("Arrows - scroll; S - save to file; Q - return; "
193                          "T - toggle view; Other - refresh"));
194         } else {
195             print_top(NULL, message);
196             print_help(_("Arrows - scroll; S - save to file; Q - return; "
197                          "Other key - refresh"));
198         }
199         scroll_rows(first, begin, end, 1, 2);
200
201         switch (getch()) {
202             case 'S':
203             case 's':
204                 save_Stations(first);
205                 continue;
206             case KEY_RIGHT:
207             case KEY_DOWN:
208                 if (end < mac_idx) {
209                     begin++;
210                     end++;
211                 }
212                 continue;
213             case KEY_UP:
214             case KEY_LEFT:
215                 if (begin > 1) {
216                     begin--;
217                     end--;
218                 }
219                 continue;
220             case 'Q':
221             case 'q':
222                 goto exit;
223             case 'T':
224             case 't':
225                 if ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
226                     (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) {
227                     sts_viewtype += 1;
228                     if (sts_viewtype == 3)
229                         sts_viewtype = 0;
230                 }
231                 continue;
232             default:
233                 while ((curr = first)) {
234                     first = curr->next;
235                     free(curr);
236                 }
237                 first = curr = NULL;
238                 goto refresh;
239         }
240     }
241
242 exit:
243     while ((curr = first)) {
244         first = curr->next;
245         free(curr);
246     }
247     print_top(NULL, NULL);
248     clear_main(0);
249 }
250
251 void nwn_stations()
252 {
253     unsigned char Mac[] = {
254         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
255         0x02, 0x01, 0x02, 0x80, 0x00 };
256     unsigned char Quality[] = {
257         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
258         0x02, 0x01, 0x03, 0x80, 0x00 };
259     unsigned char Age[] = {
260         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
261         0x02, 0x01, 0x04, 0x80, 0x00 };
262     unsigned char RSSI[] = {
263         0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
264         0x02, 0x01, 0x05, 0x80, 0x00 };
265
266     struct MacListStat *first = NULL, *curr = NULL;
267     char null[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, message[1024];
268     int mac_idx, begin, end;
269     varbind varbinds[4];
270     unsigned char next_num;
271
272
273     mac_idx = 0;
274     print_top(NULL, ST_TITLE);
275     mvwaddstr(main_sub, 0, 3,
276         _("Id       MAC address     Quality  Age  RSSI"));
277     noecho();
278     print_help(WAIT_RET);
279
280     varbinds[0].oid = Mac;
281     varbinds[0].len_oid = sizeof(Mac);
282     varbinds[0].len_val = 0;
283     varbinds[0].type = NULL_VALUE;
284     if (snmp(varbinds, 1, GET_NEXT) <= 0) {
285         print_helperr(ERR_RET);
286         goto exit;
287     }
288    next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
289
290    while (memcmp(varbinds[0].oid, Mac, sizeof(Mac) - 2) == 0) {
291
292         Mac[sizeof(Mac) - 1] = next_num;
293         Quality[sizeof(Mac) - 1] = next_num;
294         Age[sizeof(Mac) - 1] = next_num;
295         RSSI[sizeof(Mac) - 1] = next_num;
296
297         if(sizeof(Mac) == varbinds[0].len_oid) {
298                 Mac[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
299                 Quality[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
300                 Age[sizeof(Mac) - 2]  = varbinds[0].oid[varbinds[0].len_oid - 2];
301                 RSSI[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
302         }
303
304         varbinds[0].oid = Mac;
305         varbinds[0].len_oid = sizeof(Mac);
306         varbinds[0].len_val = 0;
307         varbinds[0].type = NULL_VALUE;
308         varbinds[1].oid = Quality;
309         varbinds[1].len_oid = sizeof(Quality);
310         varbinds[1].len_val = 0;
311         varbinds[1].type = NULL_VALUE;
312         varbinds[2].oid = Age;
313         varbinds[2].len_oid = sizeof(Age);
314         varbinds[2].len_val = 0;
315         varbinds[2].type = NULL_VALUE;
316         varbinds[3].oid = RSSI;
317         varbinds[3].len_oid = sizeof(RSSI);
318         varbinds[3].len_val = 0;
319         varbinds[3].type = NULL_VALUE;
320         if (snmp(varbinds, 4, GET) < 4) {
321             print_helperr(ERR_RET);
322             getch();
323             goto exit;
324         }
325
326         if (memcmp(null, varbinds[0].value, 6)) {
327             if (first == NULL) {
328                 first =
329                     (struct MacListStat *)
330                     malloc(sizeof(struct MacListStat));
331                 curr = first;
332             } else {
333                 curr->next =
334                     (struct MacListStat *)
335                     malloc(sizeof(struct MacListStat));
336                 curr = curr->next;
337             } 
338             memcpy(curr->addr, varbinds[0].value, 6);
339             curr->quality = *varbinds[1].value;
340             curr->idle = *varbinds[2].value;
341             curr->rssi = *varbinds[3].value;
342             curr->next = NULL;
343             mac_idx++;
344         }
345
346         varbinds[0].oid = Mac;
347         varbinds[0].len_oid = sizeof(Mac);
348         varbinds[0].len_val = 0;
349         varbinds[0].type = NULL_VALUE;
350         if (snmp(varbinds, 1, GET_NEXT) <= 0) {
351             print_helperr(ERR_RET);
352             goto exit;
353         }
354         next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
355                                                 
356     }
357
358    if(mac_idx) {
359
360     begin = 1;
361     end = (MAX_LINES < mac_idx + 1) ? MAX_LINES : mac_idx + 1;
362
363     while (1) {
364         print_help(_("Arrows - scroll; S - save to file; Q - return; "
365             "T - toggle view; Other - refresh"));
366
367         scroll_rows(first, begin, end, 1, 1);
368
369         sprintf(message, "%s: %d", ST_TITLE, mac_idx);
370         print_top_rssi(message);
371
372         switch (getch()) {
373         case 'S':
374         case 's':
375             save_Stations(first);
376             continue;
377         case KEY_DOWN:
378         case KEY_RIGHT:
379             if (end < mac_idx+1) {
380                 begin++;
381                 end++;
382             }
383             continue;
384         case KEY_UP:
385         case KEY_LEFT:
386             if (begin > 1) {
387                 begin--;
388                 end--;
389             }
390             continue;
391         case 'Q':
392         case 'q':
393             goto exit;
394         case 'T':
395         case 't':
396             sts_viewtype += 1;
397             if (sts_viewtype == 3)
398                 sts_viewtype = 0;
399
400             continue;
401         }
402     }
403    }
404    
405    print_help(ANY_KEY);
406    getch();
407    
408   exit:
409     while ((curr = first)) {
410         first = curr->next;
411         free(curr);
412     }
413     
414     print_top(NULL, NULL);
415     clear_main(0);
416 }
417