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[] = { 0x2b, 0x06, 1, 4, 1, 0x83, 0x1a, 1, 1 };
57 char *generic_traps[8] = { "ColdStart",
61 "AuthenticationFailure",
66 char *specific_traps[22] = {
73 "SettingPingIPAddress",
77 "APClientAuthenticating",
78 "APClientAssociating",
79 "APClientReAssociating",
80 "APClientAuthenticationFailed",
81 "APClientAssociationFailed",
83 "APClientDisconnected",
88 "APClientScanFinished" /* I think:) /roma */
91 char *specific_traps_sb[22] = {
98 "SettingPingIPAddress",
100 "FailedToEraseFlash",
101 "APClientAssociating",
103 "MultiAttachedStation",
116 memset(&server, 0, sizeof server);
117 server.sin_family = AF_INET;
118 server.sin_port = htons(162);
119 server.sin_addr.s_addr = INADDR_ANY;
122 /* locale support init */
123 setlocale(LC_ALL, "");
124 bindtextdomain("ap-utils", LOCALEDIR);
125 textdomain("ap-utils");
131 switch (opt = getopt(argc, argv, "u:i:s")) {
133 device = malloc(strlen(optarg) + 1);
134 strncpy(device, optarg, strlen(optarg) + 1);
137 user = malloc(strlen(optarg) + 1);
138 strncpy(user, optarg, strlen(optarg) + 1);
147 openlog("ap-trapd", LOG_PID, LOG_LOCAL0);
148 syslog(LOG_INFO, _("ap-trapd %s started%s%s."), VERSION,
149 (device) ? _(" on ") : "", (device) ? device : "");
152 if (pid > 0) { /* parent */
154 } else if (pid < 0) { /* failed */
155 syslog(LOG_ERR, _("Unable to fork. Exiting."));
158 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
159 syslog(LOG_ERR, _("Can't create socket. Exiting."));
164 if (bind(sockfd, (struct sockaddr *) &server, SIZE) == -1) {
165 syslog(LOG_ERR, _("Can't bind socket. Exiting."));
170 if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, device,
171 strlen(device) + 1) == -1) {
172 syslog(LOG_ERR, _("Can't bind to device %s. Exiting."),
181 /* after opening socket change userid */
182 if ((pwd = getpwnam(user)) == NULL) {
183 syslog(LOG_ERR, _("Unable to process username %s. Error: %m."),
187 if (setgid(pwd->pw_gid) == -1 || setuid(pwd->pw_uid) == -1) {
188 syslog(LOG_ERR, _("Unable to change to uid %d."), pwd->pw_uid);
194 recvfrom(sockfd, buf, 512, 0, (struct sockaddr *) &client,
197 if (buf[0] != ASN_HEADER) {
202 start += (buf[1] & 0x7F) + 2;
206 snmp_version = start[2];
210 community = malloc(start[4] + 1);
211 memcpy(community, start + 5, start[4]);
212 community[start[4]] = '\0';
213 start += *(start + 4) + 5;
215 if (start[0] != TRAP) {
219 if (start[1] & 0x80) {
220 start += (start[1] & 0x7F) + 2;
226 free(enterprise_oid);
227 enterprise_oid = malloc(start[1] + 1);
228 memcpy(enterprise_oid, start + 2, start[1]);
229 enterprise_oid[start[1]] = '\0';
230 start += start[1] + 2;
231 memcpy(&agent_addr.s_addr, start + 2, 4);
232 if (memcmp(enterprise_oid, enterprise, sizeof(enterprise))) {
235 ("Received unknown SNMP ver %d trap. From %s:%d. Agent: %s. Community: %s."),
236 snmp_version + 1, inet_ntoa(client.sin_addr),
237 ntohs(client.sin_port), inet_ntoa(agent_addr),
243 generic_trap = start[2];
244 if (generic_trap > 6)
246 specific_trap = start[5];
247 if (specific_trap > 22)
253 while (c < start[7]) {
254 time_stamp += (unsigned char) *(start + 7 + start[7] - c) * i;
258 hand = time_stamp % 100;
259 time_stamp = time_stamp / 100;
260 sec = time_stamp % 60;
261 time_stamp = time_stamp / 60;
262 min = time_stamp % 60;
263 time_stamp = time_stamp / 60;
265 start += start[7] + 8;
269 if ((start - buf < len) && *(start) == ASN_HEADER) {
271 if (start[1] & 0x80) {
272 start += (start[1] & 0x7F) + 2;
273 len -= ((start[1] & 0x7F) + 2);
279 if (*(start) == ASN_HEADER) {
280 if (start[1] & 0x80) {
281 start += (start[1] & 0x7F) + 2;
282 len -= ((start[1] & 0x7F) + 2);
287 start += start[1] + 4;
288 memcpy(mac, start, 6);
289 if (generic_trap == 6 && specific_trap >= 1
290 && (specific_trap <= 5 || specific_trap >= 9)) {
291 sprintf(mac_info, "%02X%02X%02X%02X%02X%02X",
292 mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
293 mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF);
296 if (generic_trap == 6 && specific_trap == 7) {
299 mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF,
307 ("Agent:v%d %s (%s@%s:%d) %s%s%s. SysUptime %d:%02d:%02d.%02d"),
308 snmp_version + 1, inet_ntoa(agent_addr),
309 community, inet_ntoa(client.sin_addr), ntohs(client.sin_port),
311 6) ? (atmel_ap_type == 1) ? specific_traps[specific_trap-1] : specific_traps_sb[specific_trap-1] :
312 generic_traps[generic_trap], (mac_flag) ? " " : "",
313 (mac_flag) ? mac_info : "", time_stamp, min, sec, hand);