2 * ap-trapd.c from Access Point SNMP Utils for Linux
3 * SNMP traps processing daemon code
5 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
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
22 #include <sys/types.h>
31 #define TRAPD_USER "nobody"
33 int main(int argc, char **argv)
41 char *user=NULL, *device=NULL;
46 struct sockaddr_in server;
47 struct sockaddr_in client;
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;
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] = {
63 "AuthenticationFailure",
68 char *specific_traps[22] = {
75 "SettingPingIPAddress",
79 "APClientAuthenticating",
80 "APClientAssociating",
81 "APClientReAssociating",
82 "APClientAuthenticationFailed",
83 "APClientAssociationFailed",
85 "APClientDisconnected",
90 "APClientScanFinished" /* I think:) /roma */
93 char *specific_traps_sb[22] = {
100 "SettingPingIPAddress",
102 "FailedToEraseFlash",
103 "APClientAssociating",
105 "MultiAttachedStation",
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;
124 /* locale support init */
125 setlocale(LC_ALL, "");
126 bindtextdomain("ap-utils", LOCALEDIR);
127 textdomain("ap-utils");
133 switch (opt = getopt(argc, argv, "u:i:s")) {
135 device = malloc(strlen(optarg) + 1);
136 strncpy(device, optarg, strlen(optarg) + 1);
139 user = malloc(strlen(optarg) + 1);
140 strncpy(user, optarg, strlen(optarg) + 1);
149 openlog("ap-trapd", LOG_PID, LOG_LOCAL0);
150 syslog(LOG_INFO, _("ap-trapd %s started%s%s."), VERSION,
151 (device) ? _(" on ") : "", (device) ? device : "");
154 if (pid > 0) { /* parent */
156 } else if (pid < 0) { /* failed */
157 syslog(LOG_ERR, _("Unable to fork. Exiting."));
160 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
161 syslog(LOG_ERR, _("Can't create socket. Exiting."));
166 if (bind(sockfd, (struct sockaddr *) &server, SIZE) == -1) {
167 syslog(LOG_ERR, _("Can't bind socket. Exiting."));
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."),
183 /* after opening socket change userid */
184 if ((pwd = getpwnam(user)) == NULL) {
185 syslog(LOG_ERR, _("Unable to process username %s. Error: %m."),
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);
196 recvfrom(sockfd, buf, 512, 0, (struct sockaddr *) &client,
199 if (buf[0] != ASN_HEADER) {
204 start += (buf[1] & 0x7F) + 2;
208 snmp_version = start[2];
212 community = malloc(start[4] + 1);
213 memcpy(community, start + 5, start[4]);
214 community[start[4]] = '\0';
215 start += *(start + 4) + 5;
217 if (start[0] != TRAP) {
221 if (start[1] & 0x80) {
222 start += (start[1] & 0x7F) + 2;
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)))
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),
247 generic_trap = start[2];
248 if (generic_trap > 6)
250 specific_trap = start[5];
251 if (specific_trap > 22)
257 while (c < start[7]) {
258 time_stamp += (unsigned char) *(start + 7 + start[7] - c) * i;
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;
269 start += start[7] + 8;
273 if ((start - buf < len) && *(start) == ASN_HEADER) {
275 if (start[1] & 0x80) {
276 start += (start[1] & 0x7F) + 2;
277 len -= ((start[1] & 0x7F) + 2);
283 if (*(start) == ASN_HEADER) {
284 if (start[1] & 0x80) {
285 start += (start[1] & 0x7F) + 2;
286 len -= ((start[1] & 0x7F) + 2);
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);
300 if (generic_trap == 6 && specific_trap == 7) {
303 mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
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);