]> git.decadent.org.uk Git - ap-utils.git/blob - lib/set_oeminfo.c
Finalise 1.5-1
[ap-utils.git] / lib / set_oeminfo.c
1 /*
2  *      set_oeminfo.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
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
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include "ap-utils.h"
27
28 #define S_STRUCTVERSION _("Info structure version: ")
29 #define S_MAC _("[M] Device MAC address: ")
30 #define V_OUI _("    Manufacturer with this OUI: ")
31 #define S_REGDOM _("[D] Regulatory domain: ")
32 #define S_PRODTYPE _("[T] Product type: ")
33 #define S_OEMNAME _("[E] OEM name: ")
34 #define S_OEMID _("[I] OEM ID: ")
35 #define S_PRODNAME _("[N] Product name: ")
36 #define S_HWREV _("[H] Hardware revision: ")
37 #define S_COUNTRYC _("[O] Country code: ")
38 #define S_DEFCHAN _("[C] Default channel: ")
39 #define S_CHANNELS _("[A] Calibrated channels: ")
40 #define S_TXPOWER _("[P] Nominal Tx Power (CR31) value for calibrated channels: ")
41 #define OEMSET_HELP _("Keys in brackets - set corresponding option; W - write conf; Q - quit to menu")
42
43 extern WINDOW *main_sub;
44 extern short ap_type;
45 extern char *channels[];
46 extern rdprops regdom_types[];
47
48 // TODO: test & fix for big-endian archs
49
50 void atmel_set_oeminfo()
51 {
52     char sysDeviceInfo[] = {
53         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x05, 0x00
54     };
55     // Following one is only available in newer ATMEL12350 MIBs
56     char sysDeviceMoreInfo[] = {
57         0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x08, 0x00
58     };
59
60     char message[200], c;
61     char **regdoms;
62     int i, rd_idx, st_len;
63     varbind varbinds[1];
64     struct sysDeviceInfo_128 str128; /* SHORTst */
65     struct sysDeviceInfo_160 str160; /* LONGst */
66
67     /*
68      * These have to represent used sysDeviceInfo_{128,160} members
69      * Note that sysOIDSize, sysOID and PID_VID can NOT be written
70      * using sysDevice*Info OIDs at all - the only way to change them
71      * (highly discouraged !) is in OEM configuration file, using AP RFMD
72      * or AP INTERSIL configuration editor, followed by uploading this file
73      * to the AP using ATMEL tftp client - this way, *all* defaults
74      * can be changed.
75      */
76     uint32_t StructVersion;     // [4]
77     char *MacAddress;           // [6]
78                                 // [2 reserved for SHORTst; 0 for LONGst] 
79     char Channel = 0; // LONGst specific: [0 for SHORTst; 1 for LONGst]
80     uint32_t RegulatoryDomain;  // [4 for SHORTst; 1 for LONGst]
81     uint32_t ProductType;       // [4]
82     char *OEMName;              // [32]
83     uint32_t OEMID;             // [4]
84     char *ProductName;          // [32]
85     uint32_t HardwareRevision;  // [4]
86     /* the rest is LONGst specific */
87     char *PID_VID = NULL;       // [0 for SHORTst; 4 for LONGst]
88     uint32_t sysOIDSize = 0;    // [0 for SHORTst; 4 for LONGst]
89     uint16_t *sysOID = NULL;    // [0 for SHORTst; 32 for LONGst]
90     char *CountryCode = NULL;   // [0 for SHORTst; 3 for LONGst]
91                                 // [0 for SHORTst; 1 reserved for LONGst]
92     uint16_t ChannelInformation = 0; // [0 for SHORTst; 2 for LONGst]
93                                 // [0 for SHORTst; 2 reserved for LONGst]
94     char *TxPower = NULL;       // [0 for SHORTst; 14 for LONGst]
95                                 // [0 for SHORTst; 10 reserved for LONGst]
96     clear_main(0);
97     noecho();
98
99     wattrset(main_sub, A_BOLD);
100     mvwaddstr(main_sub, 2, 4,
101         _("THIS IS A SECRET MENU LEADING TO VERY DANGEROUS OPTIONS."));
102     mvwaddstr(main_sub, 3, 8,
103         _("It is intended only for WISPs and repair shops."));
104     wattrset(main_sub, A_NORMAL);
105
106     mvwaddstr(main_sub, 5, 1,
107         _("It allows to set OEM information stored in the AP (like its"));
108     mvwaddstr(main_sub, 6, 1,
109         _("MAC address, manuf. name, OEM ID, etc.). BE ABSOLUTELY SURE"));
110     mvwaddstr(main_sub, 7, 1,
111         _("THAT YOU KNOW WHAT YOU ARE DOING, AND THAT YOU HAVE THE"));
112     mvwaddstr(main_sub, 8, 1,
113         _("LEGAL RIGHT TO DO ANY MODIFICATION. Disobserving of these"));
114     mvwaddstr(main_sub, 9, 1,
115         _("rules may lead you into a conflict with your local"));
116     mvwaddstr(main_sub, 10, 1,
117         _("regulations and/or law."));
118     mvwaddstr(main_sub, 11, 1,
119         _("Also be warned that the setting of any from these options"));
120     mvwaddstr(main_sub, 12, 1,
121         _("may DAMAGE YOUR AP (other reason why this menu is hidden)."));
122     mvwaddstr(main_sub, 13, 1,
123         _("Values changed here will NOT be restored upon reset"));
124     mvwaddstr(main_sub, 14, 1,
125         _("of the device to factory defaults! It is advisable to"));
126     mvwaddstr(main_sub, 15, 1,
127         _("write them down somewhere prior their changing."));
128     mvwaddstr(main_sub, 16, 1,
129         _("Finally, note that you need to use MANUFACTURER community, "));
130     mvwaddstr(main_sub, 17, 1,
131         _("in order to be able to do any OEM info modification."));
132     mvwaddstr(main_sub, 18, 1,
133         _("Proceed further only at your full risk and responsibility. "));
134     mvwaddstr(main_sub, 19, 1,
135         _("You got the warnings."));
136     wrefresh(main_sub);
137
138     if (help_ysn())
139         return;
140
141     print_top(NULL, _("OEM Info settings"));
142
143     if (ap_type == ATMEL12350) {
144         sysDeviceInfo[5] = 0xE0;
145         sysDeviceInfo[6] = 0x3E;
146     }
147
148     varbinds[0].oid = sysDeviceInfo;
149     varbinds[0].len_oid = sizeof(sysDeviceInfo);
150     varbinds[0].value = sysDeviceInfo;
151     varbinds[0].len_val = 0;
152     varbinds[0].type = NULL_VALUE;
153
154     print_help(WAIT_RET);
155     if (snmp(varbinds, 1, GET) <= 0) {
156         print_helperr(ERR_RET);
157         goto exit;
158     }
159
160     st_len = varbinds[0].len_val;
161
162     if (st_len == 92 || st_len == 128) { /* SHORTst */
163         memcpy(&str128, varbinds[0].value,
164             sizeof(struct sysDeviceInfo_128));
165         StructVersion           = str128.StructVersion;
166         MacAddress              = str128.MacAddress;
167         RegulatoryDomain        = str128.RegulatoryDomain;
168         ProductType             = str128.ProductType;
169         OEMName                 = str128.OEMName;
170         OEMID                   = str128.OEMID;
171         ProductName             = str128.ProductName;
172         HardwareRevision        = str128.HardwareRevision;
173     } else { /* st_len == 160 => LONGst */
174         memcpy(&str160, varbinds[0].value,
175             sizeof(struct sysDeviceInfo_160));
176         StructVersion           = str160.StructVersion;
177         MacAddress              = str160.MacAddress;
178         Channel                 = str160.Channel;
179         RegulatoryDomain        = str160.RegulatoryDomain;
180         ProductType             = str160.ProductType;
181         OEMName                 = str160.OEMName;
182         OEMID                   = str160.OEMID;
183         ProductName             = str160.ProductName;
184         HardwareRevision        = str160.HardwareRevision;
185         PID_VID                 = str160.PID_VID;
186         sysOIDSize              = str160.sysOIDSize;
187         sysOID                  = str160.sysOID;
188         CountryCode             = str160.CountryCode;
189         ChannelInformation      = str160.ChannelInformation;
190         TxPower                 = str160.TxPower;
191     }
192
193     clear_main(0);
194
195     sprintf(message, "%s%u", S_STRUCTVERSION, StructVersion);
196     mvwaddstr(main_sub, 0, 0, message);
197
198     sprintf(message, "%s%02X%02X%02X%02X%02X%02X", S_MAC,
199         MacAddress[0] & 0xFF, MacAddress[1] & 0xFF, MacAddress[2] & 0xFF,
200         MacAddress[3] & 0xFF, MacAddress[4] & 0xFF, MacAddress[5] & 0xFF);
201     mvwaddstr(main_sub, 1, 0, message);
202     sprintf(message, "%s%s", V_OUI, oui2manufacturer(MacAddress));
203     mvwaddstr(main_sub, 2, 0, message);
204
205     rd_idx = regdom_idx(RegulatoryDomain);
206     sprintf(message, "%s%s [%d]", S_REGDOM,
207         regdom_types[rd_idx].desc, RegulatoryDomain);
208     mvwaddstr(main_sub, 3, 0, message);
209
210     mvwaddstr(main_sub, 4, 0, S_OEMNAME);
211     for (i = 0; i < 32 && OEMName[i]; i++)
212         waddch(main_sub, OEMName[i]);
213
214     sprintf(message, "%s%u", S_OEMID, OEMID);
215     mvwaddstr(main_sub, 5, 0, message);
216
217     mvwaddstr(main_sub, 6, 0, S_PRODNAME);
218     for (i = 0; i < 32 && ProductName[i]; i++)
219         waddch(main_sub, ProductName[i]);
220
221     sprintf(message, _("%s%u"), S_PRODTYPE, ProductType);
222     mvwaddstr(main_sub, 7, 0, message);
223
224     sprintf(message, "%s%u", S_HWREV, HardwareRevision);
225     mvwaddstr(main_sub, 8, 0, message);
226
227     wmove(main_sub, 9, 0);
228     for (i = 0; ++i < COLS - MCOLS; waddch(main_sub, ACS_BSBS));
229
230     if (st_len == 160) {
231         sprintf(message, "%s%s", S_COUNTRYC, CountryCode);
232         mvwaddstr(main_sub, 10, 0, message);
233
234         sprintf(message, "%s%02u (%u MHz)", S_DEFCHAN, Channel,
235             2407 + 5 * Channel);
236         mvwaddstr(main_sub, 11, 0, message);
237
238         i = 1;
239         while(ChannelInformation >> i) i++;
240         sprintf(message, "%s%i", S_CHANNELS, i);
241         mvwaddstr(main_sub, 12, 0, message);
242
243         sprintf(message, "%s%u", S_TXPOWER,
244             TxPower[regdom_types[rd_idx].first_ch] & 0xFF);
245         mvwaddstr(main_sub, 13, 0, message);
246 #if 0 /* DEBUG */
247         wmove(main_sub, 18, 0);
248         for (i = 0; i < 14; i++) {
249             sprintf(message, "%-3u ", TxPower[i] & 0xFF);
250             waddstr(main_sub, message);
251         }
252 #endif /* DEBUG */
253
254         wmove(main_sub, 14, 0);
255         for (i = 0; ++i < COLS - MCOLS; waddch(main_sub, ACS_BSBS));
256
257         sprintf(message, "System control OID part [%u elements]: ", sysOIDSize);
258         mvwaddstr(main_sub, 15, 0, message);
259         i = 0;
260         while (i < (int)sysOIDSize) {
261             sprintf(message, ".%u", sysOID[i++]);
262             waddstr(main_sub, message);
263         }
264
265         sprintf(message, "USB Vendor ID: 0x%04X", (PID_VID[0] & 0xFF) |
266             ((PID_VID[1] & 0xFF) << 8));
267         mvwaddstr(main_sub, 16, 0, message);
268
269         sprintf(message, "USB Product ID: 0x%04X", (PID_VID[2] & 0xFF) |
270             ((PID_VID[3] & 0xFF) << 8));
271         mvwaddstr(main_sub, 17, 0, message);
272
273     }
274     wrefresh(main_sub);
275
276     print_help(OEMSET_HELP);
277
278     while (1) {
279         c = getch();
280         switch (c) {
281             case 'm':
282             case 'M':
283                 get_mac(MacAddress, 1, strlen(S_MAC));
284                 clear_main_new(2, 3);
285                 sprintf(message, "%s%s", V_OUI, oui2manufacturer(MacAddress));
286                 mvwaddstr(main_sub, 2, 0, message);
287                 wrefresh(main_sub);
288                 continue;
289             case 'd':
290             case 'D':
291                 for (i = 0; regdom_types[i].code; i++);
292                 regdoms = malloc(i * sizeof(char *));
293
294                 for (i = 0; regdom_types[i].code; i++) {
295                     sprintf(message, "[%3u] %s", regdom_types[i].code,
296                         regdom_types[i].desc);
297                     regdoms[i] = (char *)
298                         malloc(strlen(message) + 1);
299                     strcpy(regdoms[i], message);
300                 }
301
302                 rd_idx = menu_choose(3, strlen(S_REGDOM), regdoms, i);
303                 clear_main_new(3, 4);
304                 RegulatoryDomain = regdom_types[rd_idx].code;
305                 sprintf(message, "%s [%d]", regdom_types[rd_idx].desc,
306                     RegulatoryDomain);
307                 print_menusel(3, 0, S_REGDOM, message);
308
309                 while (i-- != 0)
310                     free(regdoms[i]);
311
312                 free(regdoms);
313
314                 if (st_len == 160) {
315                     Channel = regdom_types[rd_idx].first_ch;
316                     sprintf(message, "%02u (%u MHz)", Channel,
317                         2407 + 5 * Channel);
318                     print_menusel(11, 0, S_DEFCHAN, message);
319                 }
320                 continue;
321             case 'e':
322             case 'E':
323                 get_value(OEMName, 4, strlen(S_OEMNAME), -32, ANY_STRING,
324                     0, 0, NULL);
325                 continue;
326             case 'i':
327             case 'I':
328                 get_value(message, 5, strlen(S_OEMID), 11, INT_STRING,
329                     0, 0xFFFFFFFF, OEMSET_HELP);
330                 OEMID = atoi(message);
331                 continue;
332             case 'n':
333             case 'N':
334                 get_value(ProductName, 6, strlen(S_PRODNAME), -32, ANY_STRING,
335                     0, 0, NULL);
336                 continue;
337             case 't':
338             case 'T':
339                 get_value(message, 7, strlen(S_PRODTYPE), 11, INT_STRING,
340                     0, 0xFFFFFFFF, OEMSET_HELP);
341                 ProductType = atoi(message);
342                 continue;
343             case 'h':
344             case 'H':
345                 get_value(message, 8, strlen(S_HWREV), 11,
346                     INT_STRING, 0, 0xFFFFFFFF, OEMSET_HELP);
347                 HardwareRevision = atoi(message);
348                 continue;
349             case 'o':
350             case 'O':
351                 if (st_len == 92 || st_len == 128)
352                     continue;
353
354                 get_value(CountryCode, 10, strlen(S_COUNTRYC), 3, ANY_STRING,
355                     0, 0, NULL);
356                 continue;
357             case 'c':
358             case 'C':
359                 if (st_len == 92 || st_len == 128)
360                     continue;
361
362                 Channel = menu_choose(11 - regdom_types[rd_idx].chans / 2,
363                 strlen(S_DEFCHAN) - 2,
364 #ifndef NO_REG_DOMAIN
365                 channels + regdom_types[rd_idx].first_ch - 1,
366                 regdom_types[rd_idx].chans) + regdom_types[rd_idx].first_ch;
367 #else
368                 channels, 14) + 1;
369 #endif
370                 sprintf(message, "%02u (%u MHz)", Channel, 2407 + 5 * Channel);
371                 print_menusel(11, 0, S_DEFCHAN, message);
372                 continue;
373             case 'a':
374             case 'A':
375                 if (st_len == 92 || st_len == 128)
376                     continue;
377
378                 get_value(message, 12, strlen(S_CHANNELS), 3, INT_STRING, 1, 14,
379                     OEMSET_HELP);
380                 memset((void *)TxPower + 1, 0, 13);
381                 for(i = 1; i < atoi(message); i++)
382                     TxPower[i] = TxPower[0];
383
384                 i = 1 << (atoi(message) - 1);
385                 ChannelInformation = i | (i - 1);
386                 continue;
387             case 'p':
388             case 'P':
389                 if (st_len == 92 || st_len == 128)
390                     continue;
391
392                 get_value(message, 13, strlen(S_TXPOWER), 4, INT_STRING, 0, 255,
393                     OEMSET_HELP);
394                 c = atoi(message) & 0xFF;
395
396                 memset((void *)TxPower, 0, 14);
397                 i = 0;
398                 while(ChannelInformation >> i) {
399                     TxPower[i] = c;
400                     i++;
401                 }
402 /*
403                 memset((void *)TxPower, 0, 14);
404                 for (i = regdom_types[rd_idx].first_ch; i <
405                 regdom_types[rd_idx].first_ch + regdom_types[rd_idx].chans; i++)
406                    TxPower[i - 1] = c;
407 */
408                 continue;
409             case 'q':
410             case 'Q':
411                 goto quit;
412             case 'w':
413             case 'W':
414                 varbinds[0].oid = sysDeviceInfo;
415                 varbinds[0].len_oid = sizeof(sysDeviceInfo);
416                 varbinds[0].type = STRING_VALUE;
417
418                 if (st_len == 92 || st_len == 128) { /* SHORTst */
419                     str128.RegulatoryDomain     = RegulatoryDomain;
420                     str128.ProductType          = ProductType;
421                     str128.OEMID                = OEMID;
422                     str128.HardwareRevision     = HardwareRevision;
423                     varbinds[0].value = (char *) &str128;
424                     varbinds[0].len_val =
425                         sizeof(struct sysDeviceInfo_128);
426                 } else { /* st_len == 160 => LONGst */
427                     str160.Channel              = Channel;
428                     str160.RegulatoryDomain     = RegulatoryDomain;
429                     str160.ProductType  = ProductType;
430                     str160.OEMID                = OEMID;
431                     str160.HardwareRevision     = HardwareRevision;
432                     str160.ChannelInformation   = ChannelInformation;
433                     varbinds[0].value = (char *) &str160;
434                     /* first 92 bytes of struct sysDeviceInfo_160 here */
435                     varbinds[0].len_val = 92;
436                 }
437
438                 print_help(WAIT_SET);
439                 if (snmp(varbinds, 1, SET) <= 0) {
440                     print_helperr(ERR_SET);
441                     goto exit;
442                 }
443
444                 if (st_len == 160) {
445                     varbinds[0].oid = sysDeviceMoreInfo;
446                     varbinds[0].len_oid = sizeof(sysDeviceMoreInfo);
447                     varbinds[0].type = STRING_VALUE;
448                     /* last 32 bytes of struct sysDeviceInfo_160 here */
449                     varbinds[0].value = (char *) &str160.CountryCode;
450                     varbinds[0].len_val = 32;
451                     if (snmp(varbinds, 1, SET) <= 0) {
452                         print_helperr(ERR_SET);
453                         goto exit;
454                     }
455                 }
456
457                 wbkgd(main_sub, A_NORMAL);
458                 wrefresh(main_sub);
459                 print_help(DONE_SET);
460                 goto exit;
461         }
462     }
463
464   exit:
465     getch();
466   quit:
467     print_top(NULL, NULL);
468     clear_main(0);
469 }
470