]> git.decadent.org.uk Git - ap-utils.git/blob - src/ap-auth.c
Imported Upstream version 1.5~pre2
[ap-utils.git] / src / ap-auth.c
1 /*
2  *      ap-auth.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2004 Teemu Kiviniemi <teemuki at fotokone.fi>
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 ERROR_PACKET _("AuthorizedMacTableString packet error")
33 #define ERROR_DATA _("Invalid data in source file")
34 #define ERROR_FILE_OPEN _("Can't open file")
35 #define ERROR_FILE_WRITE _("Can't write to file")
36 #define ERROR_FILE_CLOSE _("Error closing file")
37
38 short ap_type;
39 char *community = NULL;
40 int sockfd;
41 struct in_addr ap_ip;
42
43 void usage()
44 {
45     printf(_("\nUsage:\n"));
46     printf(_("\tap-auth -i ip -c community -d filename [-h]\n"));
47     printf(_("\tap-auth -i ip -c community -u filename [-h]\n\n"));
48     printf(_("Change accesspoint's list of authorised MAC addresses\n\n"));
49     printf(_("-i ip        - AP ip address\n"));
50     printf(_("-c community - SNMP community string\n"));
51     printf(_("-d filename  - download list of authorised MAC addresses from AP"
52         " to a file\n"));
53     printf(_("-u filename  - upload list of authorised MAC addresses from"
54         " a file to AP\n"));
55     printf(_("-h           - print this help screen\n\n"));
56     printf(_("ap-auth %s Copyright (c) 2004 Teemu Kiviniemi\n\n"),
57            VERSION);
58 }
59
60 int write_addr (FILE *f, const struct MacListStat *n)
61 {
62     if (fprintf (f, "%02x%02x%02x%02x%02x%02x\n", n->addr[0], n->addr[1],
63                                                   n->addr[2], n->addr[3],
64                                                   n->addr[4], n->addr[5])
65                                                 != 13)
66         return 1;
67
68     return 0;
69 }
70
71 int get_addr (struct MacListStat *ml, char *addr)
72 {
73     int i;
74     char tmp[3];
75
76     if (strlen (addr) != 12)
77         return 1;
78
79     tmp[2] = '\0';
80
81     for (i = 0; i < 6 ; i++) {
82         tmp[0] = addr[2 * i];
83         tmp[1] = addr[2 * i + 1];
84         ml->addr[i] = strtol (tmp, NULL, 16);
85     }
86
87     return 0;
88 }
89
90 int main(int argc, char **argv)
91 {
92     extern char *optarg;
93     extern int optind;
94     extern int opterr;
95     extern int optopt;
96     int opt = 0;
97     int mode = 0; /* 1 = download, 2 = upload */
98
99     FILE *f;
100     char *filename = NULL;
101     struct sockaddr_in client;
102
103     struct AuthorizedMacTableString {
104         unsigned int short Action;
105         unsigned int short NumOfAllTableAddresses;
106         unsigned int short NumOfCurrentAddress;
107         unsigned char MacAddress[6];
108     } *AuthMac = NULL, get;
109
110     struct MacListStat *first = NULL, *curr = NULL;
111
112     char sysDescr_NWN[] = {
113         0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
114     };
115     char sysDescr_ATMEL[] = {
116         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
117     };
118     char AutorizedMac_ATMEL[] = {
119         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x02, 0x00
120     };
121
122     int total_mac, mac_num = 0;
123     varbind varbinds[1];
124     char mac_tmp[13];
125     char *cp;
126     struct MacListStat ml_tmp;
127     int i, tmp;
128
129 #ifdef HAVE_GETTEXT
130     setlocale(LC_ALL, "");
131     bindtextdomain("ap-utils", LOCALEDIR);
132     textdomain("ap-utils");
133 #endif
134
135     memset(&client, 0, sizeof client);
136     client.sin_family = AF_INET;
137     client.sin_port = INADDR_ANY;
138     client.sin_addr.s_addr = INADDR_ANY;
139
140     do {
141         opterr = 0;
142         switch (opt = getopt(argc, argv, "i:c:d:u:")) {
143         case 'i':
144             for (cp = optarg, i = 0; *cp && (cp = index(cp, '.')); cp++, i++);
145             if (i < 3 || inet_aton(optarg, &ap_ip) == 0) {
146                 printf(_("Error: invalid IP-address.\n"));
147                 return 1;
148             }
149             break;
150         case 'c':
151             community = malloc(strlen(optarg) + 1);
152             strncpy(community, optarg, strlen(optarg) + 1);
153             break;
154         case 'd':
155             filename = malloc(strlen(optarg) + 1);
156             strncpy(filename, optarg, strlen(optarg) + 1);
157             mode = 1;
158             break;
159         case 'u':
160             filename = malloc(strlen(optarg) + 1);
161             strncpy(filename, optarg, strlen(optarg) + 1);
162             mode = 2;
163             break;
164         case -1:
165             break;
166         default:
167             usage();
168             return 1;
169         }
170     } while (opt != -1);
171
172     if (!community) {
173         usage();
174         return 1;
175     }
176
177     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
178         perror(_("Create socket error"));
179         return 1;
180     }
181     if (bind(sockfd, (struct sockaddr *) &client, SIZE) == -1) {
182         perror(_("Bind socket error"));
183         return 1;
184     }
185
186     /*
187      * Part detecting ap_type (ATMEL AP MIB type) follows.
188      * We could use get_mib_details() here with advantage, but it would
189      * have to involve 1. putting it to separate file in lib/ and
190      * 2. patch it so it would not contain curses-related commands (TODO)
191      */
192
193     /* determine private MIB type according to enterprises ID */
194     varbinds[0].oid = sysDescr_NWN;
195     varbinds[0].len_oid = sizeof(sysDescr_NWN);
196     varbinds[0].value = NULL;
197     varbinds[0].len_val = 0;
198     varbinds[0].type = NULL_VALUE;
199     if (snmp(varbinds, 1, GET) > 0) {
200         ap_type = NWN;
201     } else {
202         varbinds[0].oid = sysDescr_ATMEL;
203         varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
204         varbinds[0].value = NULL;
205         varbinds[0].len_val = 0;
206         varbinds[0].type = NULL_VALUE;
207         if (snmp(varbinds, 1, GET) > 0) {
208             ap_type = ATMEL410;
209         } else {
210             sysDescr_ATMEL[5] = 0xE0;
211             sysDescr_ATMEL[6] = 0x3E;
212             varbinds[0].oid = sysDescr_ATMEL;
213             varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
214             varbinds[0].value = NULL;
215             varbinds[0].len_val = 0;
216             varbinds[0].type = NULL_VALUE;
217             if (snmp(varbinds, 1, GET) > 0) {
218                 ap_type = ATMEL12350;
219             } else {
220                 printf(_("Unable to determine AP MIB type "
221                     "(no response from AP)."));
222                 return 1;
223             }
224         }
225     }
226
227     if (ap_type == NWN) {
228         printf(_("NWN devices are not yet supported."));
229         return 1;
230     }
231
232     if (ap_type == ATMEL12350) {
233         AutorizedMac_ATMEL[5] = 0xE0;
234         AutorizedMac_ATMEL[6] = 0x3E;
235     }
236
237     switch (mode) {
238
239     case 1: /* download */
240
241         total_mac = 0;
242         mac_num = 0;
243
244         while (mac_num <= total_mac) {
245             get.Action = 0x02; rshort(get.Action);
246             get.NumOfAllTableAddresses = total_mac; rshort(get.NumOfAllTableAddresses);
247             get.NumOfCurrentAddress = mac_num; rshort(get.NumOfCurrentAddress);
248             
249             varbinds[0].oid = AutorizedMac_ATMEL;
250             varbinds[0].len_oid = sizeof(AutorizedMac_ATMEL);
251             varbinds[0].value = (char *) &get;
252             varbinds[0].len_val = 12;
253             varbinds[0].type = STRING_VALUE;
254             
255             if (snmp(varbinds, 1, SET) <= 0) {
256                 printf(ERR_RET);
257                 printf("\n");
258                 return 1;
259             }
260
261             if (varbinds[0].len_val == 12) {
262                 if (AuthMac)
263                     free(AuthMac);
264                 AuthMac = 
265                     (struct AuthorizedMacTableString *) malloc(varbinds[0].
266                                                                len_val);
267                 memcpy(AuthMac, varbinds[0].value, varbinds[0].len_val);
268             } else {
269                 printf(ERROR_PACKET);
270                 printf("\n");
271                 return 1;
272             }
273
274             rshort(AuthMac->NumOfAllTableAddresses);
275             total_mac =
276                 (AuthMac->NumOfAllTableAddresses ==
277                  65535) ? 0 : AuthMac->NumOfAllTableAddresses;
278
279             if (mac_num) {
280                 if (first == NULL) {
281                     first = (struct MacListStat *)
282                         malloc(sizeof(struct MacListStat));
283                     curr = first;
284                 } else {
285                     curr->next = (struct MacListStat *)
286                         malloc(sizeof(struct MacListStat));
287                     curr = curr->next;
288                 }
289                 memcpy(curr->addr, AuthMac->MacAddress, 6);
290                 curr->next = NULL;
291             }
292             mac_num++;
293         }
294         f = fopen(filename, "w");
295         if(f == NULL) {
296             perror(ERROR_FILE_OPEN);
297             return 1;
298         }
299         if (first == NULL) {
300             /* no authorised addresses */
301         } else {
302             curr = first;
303             while (curr != NULL) {
304                 if(write_addr (f, curr) != 0) {
305                     perror(ERROR_FILE_WRITE);
306                     return 1;
307                 }
308                 curr = curr->next;
309             }
310         }
311         if(fclose(f) != 0) {
312             perror(ERROR_FILE_CLOSE);
313             return 1;
314         }
315         break;
316     case 2: /* upload */
317         f = fopen(filename, "r");
318         if (f == NULL) {
319             perror(ERROR_FILE_OPEN);
320             return 1;
321         }
322         mac_num  = 0;
323         while (!feof (f)) {
324             tmp = fread (mac_tmp, 1, sizeof (mac_tmp), f);
325
326             if (tmp == sizeof (mac_tmp)) {
327                 if (mac_tmp[12] != '\n') {
328                     printf(ERROR_DATA);
329                     printf("\n");
330                     return 1;
331                 }
332                 mac_tmp[12] = '\0';
333
334                 if (get_addr (&ml_tmp, mac_tmp) != 0) {
335                     printf(ERROR_DATA);
336                     printf("\n");
337                     return 1;
338                 }
339                 if (first == NULL) {
340                     first = (struct MacListStat *)
341                         malloc (sizeof (struct MacListStat));
342                     curr = first;
343                 } else {
344                     curr->next = (struct MacListStat *)
345                         malloc (sizeof (struct MacListStat));
346                     curr = curr->next;
347                 }
348                 memcpy (curr, &ml_tmp, sizeof (struct MacListStat));
349                 curr->next = NULL;
350                 mac_num++;
351             }
352         }
353         fclose(f);
354
355         curr = first;
356         i = 1;
357         while (curr != NULL) {
358             get.Action = 0x01;
359             rshort(get.Action);
360             get.NumOfAllTableAddresses = mac_num;
361             rshort(get.NumOfAllTableAddresses);
362             get.NumOfCurrentAddress = i;
363             rshort(get.NumOfCurrentAddress);
364             memcpy(get.MacAddress, curr->addr, 6);
365             varbinds[0].oid = AutorizedMac_ATMEL;
366             varbinds[0].len_oid = sizeof(AutorizedMac_ATMEL);
367             varbinds[0].value = (char *) &get;
368             varbinds[0].len_val = 12;
369             varbinds[0].type = STRING_VALUE;
370             if (snmp(varbinds, 1, SET) <= 0) {
371                 printf(ERR_RET);
372                 printf("\n");
373                 return 1;
374             }
375             if (varbinds[0].len_val != 12) {
376                 printf(ERROR_PACKET);
377                 printf("\n");
378                 return 1;
379             }
380             curr = curr->next;
381             i++;
382         }
383         break;
384     default:
385         usage();
386         return 1;
387     }
388
389     close(sockfd);
390
391     curr = first;
392     while (curr != NULL) {
393         curr = curr->next;
394         free (first);
395         first = curr;
396     }
397
398     if (community)
399         free(community);
400     if (filename)
401         free(filename);
402     return 0;
403 }