2 * stations.c from Access Point SNMP Utils for Linux
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>
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.
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.
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
29 #define MAX_LINES LINES-4
32 extern WINDOW *main_sub;
33 extern short ap_type, ap_vendorext;
34 extern int sts_viewtype;
38 char bridgeOperationalMode[] = {
39 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
41 char AssociatedSTAsNum[] = {
42 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
44 char AssociatedSTAsInfo[] = {
45 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x02, 0x00
48 /* AP mode: connected APClients info */
50 struct AssociatedSTAsInfo_ATMEL410 ap_410;
51 struct AssociatedSTAsInfo_ATMEL12350 ap_12350;
53 struct MacListStat *first = NULL, *curr = NULL;
55 int mac_idx, begin, end, total_mac;
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;
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;
75 if (snmp(varbinds, 1, GET) <= 0) {
76 print_helperr(ERR_RET);
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)."));
90 wattrset(main_sub, COLOR_PAIR(13));
91 mvwaddstr(main_sub, 0, 0,
92 _(" # MAC Parent MAC RSSI LQ Sts MACn IP "));
93 wattrset(main_sub, A_NORMAL);
96 /* find out how many STAtions is in the list */
97 varbinds[0].oid = AssociatedSTAsNum;
98 varbinds[0].len_oid = sizeof(AssociatedSTAsNum);
99 varbinds[0].value = AssociatedSTAsNum;
100 varbinds[0].type = NULL_VALUE;
101 varbinds[0].len_val = 0;
103 print_help(WAIT_RET);
105 if (snmp(varbinds, 1, GET) <= 0) {
106 print_helperr(ERR_RET);
110 total_mac = *(varbinds[0].value);
111 print_help(WAIT_SET);
114 while (mac_idx <= total_mac) {
116 * Tell the AP we want mac_idx-th AssociatedSTAsInfo structure.
118 * - position of 'Index' member in ap_* struct is always the same
119 * - only the 'Index' member is actually to be used
120 * - both structures have same size (24)
121 * we may pick *any* ap_* struct here.
123 varbinds[0].oid = AssociatedSTAsInfo;
124 varbinds[0].len_oid = sizeof(AssociatedSTAsInfo);
125 varbinds[0].type = INT_VALUE;
126 ap_410.Index = swap2(mac_idx);
127 varbinds[0].value = (char *)&ap_410;
128 varbinds[0].len_val = sizeof(ap_410);
130 if (snmp(varbinds, 1, SET) <= 0) {
131 print_helperr(ERR_RET);
135 if (varbinds[0].len_val != 24) {
136 print_helperr(_("AssociatedSTAsInfo packet error"));
142 (struct MacListStat *) calloc(1, sizeof(struct MacListStat));
146 (struct MacListStat *) calloc(1, sizeof(struct MacListStat));
150 /* lets not use black magic (casting) here, ok? */
151 if (ap_type == ATMEL410) {
152 memcpy(&ap_410, varbinds[0].value, sizeof(ap_410));
154 memcpy(curr->addr, ap_410.MacAddress, 6);
155 if (ap_vendorext == SBRIDGES) {
156 memcpy(curr->ParentMacAddress, ap_410.ParentMacAddress, 6);
157 memcpy(&(curr->IP.s_addr), ap_410.IP, 4);
158 curr->rssi = ap_410.RSSI;
159 curr->quality = 100 - (minimum(ap_410.LinkQuality,40))*2,5;
160 curr->Status = ap_410.Status;
161 curr->Port = ap_410.Port;
163 } else { /* ap_type == ATMEL12350 */
164 memcpy(&ap_12350, varbinds[0].value, sizeof(ap_12350));
166 memcpy(curr->addr, ap_12350.MacAddress, 6);
167 if (ap_vendorext == EZYNET) {
168 memcpy(curr->ParentMacAddress, ap_12350.ParentMacAddress, 6);
169 memcpy(&(curr->IP.s_addr), ap_12350.IP, 4);
170 curr->rssi = ap_12350.RSSI;
171 /* curr->quality stays empty */
172 curr->Status = ap_12350.Status;
173 curr->Port = ap_12350.Port;
182 end = (MAX_LINES < mac_idx) ? MAX_LINES : mac_idx;
184 sprintf(message, "%s: %d", ST_TITLE, total_mac);
186 if ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
187 (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) {
188 print_top_rssi(message);
189 print_help(_("Arrows - scroll; S - save to file; Q - return; "
190 "T - toggle view; Other - refresh"));
192 print_top(NULL, message);
193 print_help(_("Arrows - scroll; S - save to file; Q - return; "
194 "Other key - refresh"));
196 scroll_rows(first, begin, end, 1, 2);
201 save_Stations(first);
222 if ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
223 (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) {
225 if (sts_viewtype == 3)
230 while ((curr = first)) {
242 while ((curr = first)) {
246 print_top(NULL, NULL);
252 unsigned char Mac[] = {
253 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
254 0x02, 0x01, 0x02, 0x80, 0x00 };
255 unsigned char Quality[] = {
256 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
257 0x02, 0x01, 0x03, 0x80, 0x00 };
258 unsigned char Age[] = {
259 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
260 0x02, 0x01, 0x04, 0x80, 0x00 };
261 unsigned char RSSI[] = {
262 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x01,
263 0x02, 0x01, 0x05, 0x80, 0x00 };
265 struct MacListStat *first = NULL, *curr = NULL;
266 char null[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, message[1024];
267 int mac_idx, begin, end;
269 unsigned char next_num;
273 print_top(NULL, ST_TITLE);
274 mvwaddstr(main_sub, 0, 3,
275 _("Id MAC address Quality Age RSSI"));
277 print_help(WAIT_RET);
279 varbinds[0].oid = Mac;
280 varbinds[0].len_oid = sizeof(Mac);
281 varbinds[0].len_val = 0;
282 varbinds[0].type = NULL_VALUE;
283 if (snmp(varbinds, 1, GET_NEXT) <= 0) {
284 print_helperr(ERR_RET);
287 next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
289 while (memcmp(varbinds[0].oid, Mac, sizeof(Mac) - 2) == 0) {
291 Mac[sizeof(Mac) - 1] = next_num;
292 Quality[sizeof(Mac) - 1] = next_num;
293 Age[sizeof(Mac) - 1] = next_num;
294 RSSI[sizeof(Mac) - 1] = next_num;
296 if(sizeof(Mac) == varbinds[0].len_oid) {
297 Mac[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
298 Quality[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
299 Age[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
300 RSSI[sizeof(Mac) - 2] = varbinds[0].oid[varbinds[0].len_oid - 2];
303 varbinds[0].oid = Mac;
304 varbinds[0].len_oid = sizeof(Mac);
305 varbinds[0].len_val = 0;
306 varbinds[0].type = NULL_VALUE;
307 varbinds[1].oid = Quality;
308 varbinds[1].len_oid = sizeof(Quality);
309 varbinds[1].len_val = 0;
310 varbinds[1].type = NULL_VALUE;
311 varbinds[2].oid = Age;
312 varbinds[2].len_oid = sizeof(Age);
313 varbinds[2].len_val = 0;
314 varbinds[2].type = NULL_VALUE;
315 varbinds[3].oid = RSSI;
316 varbinds[3].len_oid = sizeof(RSSI);
317 varbinds[3].len_val = 0;
318 varbinds[3].type = NULL_VALUE;
319 if (snmp(varbinds, 4, GET) < 4) {
320 print_helperr(ERR_RET);
325 if (memcmp(null, varbinds[0].value, 6)) {
328 (struct MacListStat *)
329 malloc(sizeof(struct MacListStat));
333 (struct MacListStat *)
334 malloc(sizeof(struct MacListStat));
337 memcpy(curr->addr, varbinds[0].value, 6);
338 curr->quality = 100 - (minimum(*varbinds[1].value,40))*2,5;
339 // curr->quality = *varbinds[1].value;
340 curr->idle = *varbinds[2].value;
341 curr->rssi = *varbinds[3].value;
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);
354 next_num = varbinds[0].oid[varbinds[0].len_oid - 1];
361 end = (MAX_LINES < mac_idx + 1) ? MAX_LINES : mac_idx + 1;
364 print_help(_("Arrows - scroll; S - save to file; Q - return; "
365 "T - toggle view; Other - refresh"));
367 scroll_rows(first, begin, end, 1, 1);
369 sprintf(message, "%s: %d", ST_TITLE, mac_idx);
370 print_top_rssi(message);
375 save_Stations(first);
379 if (end < mac_idx+1) {
397 if (sts_viewtype == 3)
409 while ((curr = first)) {
414 print_top(NULL, NULL);