]> git.decadent.org.uk Git - ap-utils.git/blob - src/ap-trapd.c
Update config.{sub,guess} in the right place at build time - closes: #534825
[ap-utils.git] / src / ap-trapd.c
1 /*
2  *      ap-trapd.c from Access Point SNMP Utils for Linux
3  *      SNMP traps processing daemon code
4  *
5  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
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
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <pwd.h>
27 #include <syslog.h>
28 #include <stdio.h>
29 #include "ap-utils.h"
30
31 #define TRAPD_USER "nobody"
32
33 int main(int argc, char **argv)
34 {
35     extern char *optarg;
36     extern int optind;
37     extern int opterr;
38     extern int optopt;
39     int opt = 0;
40
41     char *user=NULL, *device=NULL;
42     
43
44     pid_t pid;
45     struct passwd *pwd;
46     struct sockaddr_in server;
47     struct sockaddr_in client;
48     int sockfd, len;
49     unsigned int client_len = SIZE, hand, sec, min;
50     unsigned char buf[512], *start, snmp_version,
51         *community = NULL, generic_trap, specific_trap;
52     unsigned int i, atmel_ap_type = 0;
53     size_t time_stamp;
54     char mac[6], *enterprise_oid = NULL, c, mac_info[31], mac_flag = 0;
55     struct in_addr agent_addr;
56     char enterprise_410[] = { 0x2b, 0x06, 1, 4, 1, 0x83, 0x1a, 1, 1 };
57     char enterprise_12350[] = { 0x2b, 0x06, 1, 4, 1, 0xe0, 0x3e, 1, 1 };
58     char *generic_traps[8] = {
59         "ColdStart",
60         "WarmStart",
61         "LinkDown",
62         "LinkUp",
63         "AuthenticationFailure",
64         "EgpNeighborLoss",
65         "EnterpriseSpecific",
66         "unknown"
67     };
68     char *specific_traps[22] = {
69         "Reassociation",
70         "RoamOut",
71         "Association",
72         "Disassociation",
73         "AssociationExpire",
74         "Reset",
75         "SettingPingIPAddress",
76         "StartUp",
77         "FailedToEraseFlash",
78         "APClientScanning",
79         "APClientAuthenticating",
80         "APClientAssociating",
81         "APClientReAssociating",
82         "APClientAuthenticationFailed",
83         "APClientAssociationFailed",
84         "APClientConnected",
85         "APClientDisconnected",
86         "APClientScanFailed",
87         "APClientJoinFailed",
88         "APClientJoining",
89         "unknown",
90         "APClientScanFinished" /* I think:) /roma */
91     };
92
93     char *specific_traps_sb[22] = {
94         "Reassociation",
95         "RoamOut",
96         "Association",
97         "Disassociation",
98         "AssociationExpire",
99         "Reset",
100         "SettingPingIPAddress",
101         "StartUp",
102         "FailedToEraseFlash",
103         "APClientAssociating",
104         "APClientScanning",
105         "MultiAttachedStation",
106         "unknown",
107         "unknown",
108         "unknown",
109         "unknown",
110         "unknown",
111         "unknown",
112         "unknown",
113         "unknown",
114         "unknown",
115         "unknown"
116 };
117
118     memset(&server, 0, sizeof server);
119     server.sin_family = AF_INET;
120     server.sin_port = htons(162);
121     server.sin_addr.s_addr = INADDR_ANY;
122
123 #ifdef HAVE_GETTEXT
124     /* locale support init */
125     setlocale(LC_ALL, "");
126     bindtextdomain("ap-utils", LOCALEDIR);
127     textdomain("ap-utils");
128 #endif
129
130     if (argc > 1)
131      do {
132         opterr = 0;
133         switch (opt = getopt(argc, argv, "u:i:s")) {
134         case 'i':
135             device = malloc(strlen(optarg) + 1);
136             strncpy(device, optarg, strlen(optarg) + 1);
137             break;
138         case 'u':
139             user = malloc(strlen(optarg) + 1);
140             strncpy(user, optarg, strlen(optarg) + 1);
141             break;
142         case 's':
143             atmel_ap_type = 1;
144             break;
145         }
146     } while (opt != -1);
147
148
149     openlog("ap-trapd", LOG_PID, LOG_LOCAL0);
150     syslog(LOG_INFO, _("ap-trapd %s started%s%s."), VERSION,
151            (device) ? _(" on ") : "", (device) ? device : "");
152
153     pid = fork();
154     if (pid > 0) {              /* parent */
155         return 0;
156     } else if (pid < 0) {       /* failed */
157         syslog(LOG_ERR, _("Unable to fork. Exiting."));
158         return 1;
159     }
160     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
161         syslog(LOG_ERR, _("Can't create socket. Exiting."));
162         return 1;
163     }
164
165
166     if (bind(sockfd, (struct sockaddr *) &server, SIZE) == -1) {
167         syslog(LOG_ERR, _("Can't bind socket. Exiting."));
168         return 1;
169     }
170 #ifdef OS_LINUX
171     if (device) {
172         if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, device,
173                        strlen(device) + 1) == -1) {
174             syslog(LOG_ERR, _("Can't bind to device %s. Exiting."),
175                    device);
176             return 1;
177         }
178     }
179 #endif
180
181     if (user == NULL)
182         user = TRAPD_USER;
183     /* after opening socket change userid  */
184     if ((pwd = getpwnam(user)) == NULL) {
185         syslog(LOG_ERR, _("Unable to process username %s. Error: %m."),
186                user);
187         return 1;
188     }
189     if (setgid(pwd->pw_gid) == -1 || setuid(pwd->pw_uid) == -1) {
190         syslog(LOG_ERR, _("Unable to change to uid %d."), pwd->pw_uid);
191         return 1;
192     }
193
194     while (1) {
195         if ((len =
196              recvfrom(sockfd, buf, 512, 0, (struct sockaddr *) &client,
197                       &client_len)) == -1)
198             continue;
199         if (buf[0] != ASN_HEADER) {
200             continue;
201         }
202         start = buf;
203         if (buf[1] & 0x80) {
204             start += (buf[1] & 0x7F) + 2;
205         } else {
206             start += 2;
207         }
208         snmp_version = start[2];
209
210         if (community)
211             free(community);
212         community = malloc(start[4] + 1);
213         memcpy(community, start + 5, start[4]);
214         community[start[4]] = '\0';
215         start += *(start + 4) + 5;
216
217         if (start[0] != TRAP) {
218             continue;
219         }
220
221         if (start[1] & 0x80) {
222             start += (start[1] & 0x7F) + 2;
223         } else {
224             start += 2;
225         }
226
227         if (enterprise_oid)
228             free(enterprise_oid);
229         enterprise_oid = malloc(start[1] + 1);
230         memcpy(enterprise_oid, start + 2, start[1]);
231         enterprise_oid[start[1]] = '\0';
232         start += start[1] + 2;
233         memcpy(&agent_addr.s_addr, start + 2, 4);
234         if (memcmp(enterprise_oid, enterprise_410, sizeof(enterprise_410)) &&
235             memcmp(enterprise_oid, enterprise_12350, sizeof(enterprise_12350)))
236         {
237             syslog(LOG_INFO,
238                    _
239                    ("Received unknown SNMP ver %d trap. From %s:%d. Agent: %s. Community: %s."),
240                    snmp_version + 1, inet_ntoa(client.sin_addr),
241                    ntohs(client.sin_port), inet_ntoa(agent_addr),
242                    community);
243             continue;
244         }
245
246         start += 6;
247         generic_trap = start[2];
248         if (generic_trap > 6)
249             generic_trap = 7;
250         specific_trap = start[5];
251         if (specific_trap > 22)
252             specific_trap = 21;
253
254         time_stamp = 0;
255         c = 0;
256         i = 1;
257         while (c < start[7]) {
258             time_stamp += (unsigned char) *(start + 7 + start[7] - c) * i;
259             i *= 256;
260             c++;
261         }
262         hand = time_stamp % 100;
263         time_stamp = time_stamp / 100;
264         sec = time_stamp % 60;
265         time_stamp = time_stamp / 60;
266         min = time_stamp % 60;
267         time_stamp = time_stamp / 60;
268
269         start += start[7] + 8;
270
271
272         mac_flag = 0;
273         if ((start - buf < len) && *(start) == ASN_HEADER) {
274
275             if (start[1] & 0x80) {
276                 start += (start[1] & 0x7F) + 2;
277                 len -= ((start[1] & 0x7F) + 2);
278             } else {
279                 start += 2;
280                 len -= 2;
281             }
282
283             if (*(start) == ASN_HEADER) {
284                 if (start[1] & 0x80) {
285                     start += (start[1] & 0x7F) + 2;
286                     len -= ((start[1] & 0x7F) + 2);
287                 } else {
288                     start += 2;
289                     len -= 2;
290                 }
291                 start += start[1] + 4;
292                 memcpy(mac, start, 6);
293                 if (generic_trap == 6 && specific_trap >= 1
294                     && (specific_trap <= 5 || specific_trap >= 9)) {
295                     sprintf(mac_info, "%02X%02X%02X%02X%02X%02X",
296                             mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
297                             mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF);
298                     mac_flag = 1;
299                 }
300                 if (generic_trap == 6 && specific_trap == 7) {
301                     sprintf(mac_info,
302                             "%d.%d.%d.%d",
303                             mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
304                             mac[3] & 0xFF);
305                     mac_flag = 1;
306                 }
307             }
308         }
309         syslog(LOG_INFO,
310                _
311                ("Agent:v%d %s (%s@%s:%d) Trap %i: %s%s%s. "
312                 "SysUptime %d:%02d:%02d.%02d"),
313                snmp_version + 1,  inet_ntoa(agent_addr),
314                community, inet_ntoa(client.sin_addr), ntohs(client.sin_port),
315                (generic_trap == 6) ? specific_trap: generic_trap + 1,
316                (generic_trap == 6) ?
317                 (atmel_ap_type == 1) ? specific_traps_sb[specific_trap-1] : specific_traps[specific_trap-1] :
318                generic_traps[generic_trap], (mac_flag) ? " " : "",
319                (mac_flag) ? mac_info : "", time_stamp, min, sec, hand);
320     }
321
322     /* not reachable */
323     return 0;
324 }