1 /* $Id: snmp.c,v 1.47 2005/10/12 03:04:38 jared Exp $ */
2
3 #include "config.h"
4
5 /* One of the many include files defines a 'clear' macro
6 which breaks the build on Mac OS X */
7 #undef clear
8
9 /* SNMP specific includes */
10 #ifdef ENABLE_SNMP
11
12 #ifdef HAVE_UCD_SNMP_VERSION_H
13 #include <ucd-snmp/ucd-snmp-config.h>
14 #include <ucd-snmp/ucd-snmp-includes.h>
15 #endif
16
17 #ifdef HAVE_NET_SNMP_VERSION_H
18 #include <net-snmp/net-snmp-config.h>
19 #include <net-snmp/net-snmp-includes.h>
20 #include <net-snmp/library/snmp_client.h>
21 #endif
22
23
24 /* SNMP - The not so SIMPLE NETWORK MANAGMENT PROTOCOL */
25
26 struct snmpdata {
27 struct snmp_pdu *req;
28 oid oid_value[MAX_OID_LEN];
29 int oid_len;
30 unsigned long snmp_retval;
31 time_t snmp_response_time;
32 bool snmp_response;
33 struct snmp_session *sess;
34 };
35 #endif /* ENABLE_SNMP */
36
37 int snmp_debug = 0;
38
process_snmp_trap(int skt)39 void process_snmp_trap(int skt)
40 {
41 /* Read the packet off the socket, read the src, process
42 the trap, etc.. */
43
44 /* For now, just log the raw packet dump via print_err(0,*) */
45 char buffer[4096];
46 int len;
47 /* struct sockaddr from; */
48 char from[16];
49 int fromlen;
50 struct in_addr foo;
51
52 len = recvfrom(skt, buffer, 4095, 0, (struct sockaddr*)from, &fromlen);
53 memcpy(&foo, (from+4), 4);
54 print_err(1, "caught a snmp trap from %s that was %d bytes", inet_ntoa(foo), len);
55
56 print_in_hex(buffer, len);
57
58 printf("\nfrom+fromlen\n");
59 print_in_hex(from, fromlen);
60
61 if (len == -1)
62 {
63 perror("snmp.c:recvfrom");
64 }
65
66 #ifdef FOO
67 print_err(1, "received a packet from %s of length %d",
68 inet_ntoa((struct in_addr*)from), fromlen);
69 #endif /* FOO */
70 }
71
72 #ifdef ENABLE_SNMP
73
74 /*
75 * extract the data from the snmp packet
76 */
extract_snmp_result(int status,struct snmp_session * sp,struct snmp_pdu * pdu,struct snmpdata * snmp_nfo)77 int extract_snmp_result (int status, struct snmp_session *sp,
78 struct snmp_pdu *pdu, struct snmpdata *snmp_nfo)
79 {
80 struct variable_list *vp;
81 int ix;
82
83 /*
84 (gdb) print *pdu->variables->val->counter64
85 $6 = {high = 0, low = 1854873}
86
87 eg: pdu->variables->val->counter64.low
88 */
89
90 #warning need to correctly differentiate btw 32 and 64 bit responses
91
92 switch (status)
93 {
94 case STAT_SUCCESS:
95 {
96 vp = pdu->variables;
97 if (pdu->errstat == SNMP_ERR_NOERROR)
98 {
99 if (vp->val.integer)
100 {
101 snmp_nfo->snmp_retval = (unsigned long)(*vp->val.integer);
102 if ((snmp_nfo->snmp_retval == 0) &&
103 (vp->val.counter64->low != 0))
104 snmp_nfo->snmp_retval = (unsigned long)(vp->val.counter64->low);
105 snmp_nfo->snmp_response = TRUE;
106 time(&snmp_nfo->snmp_response_time);
107 }
108 } else {
109 for (ix = 1; vp && ix != pdu->errindex; vp = vp->next_variable, ix++);
110 if (vp != NULL)
111 {
112 if (vp->val.integer)
113 {
114 snmp_nfo->snmp_retval = (unsigned long)(*vp->val.integer);
115 if ((snmp_nfo->snmp_retval == 0) &&
116 (vp->val.counter64->low != 0))
117 snmp_nfo->snmp_retval = (unsigned long)(vp->val.counter64->low);
118 snmp_nfo->snmp_response = TRUE;
119 time(&snmp_nfo->snmp_response_time);
120 }
121 }
122 }
123 return 1;
124 }
125 case STAT_TIMEOUT:
126 {
127 return -1;
128 }
129
130 }
131 return 0;
132 }
133
134
snmp_callback_response(int operation,struct snmp_session * sp,int reqid,struct snmp_pdu * pdu,void * magic)135 int snmp_callback_response(int operation, struct snmp_session *sp, int reqid,
136 struct snmp_pdu *pdu, void *magic)
137 {
138 struct monitorent *here = (struct monitorent *)magic;
139 struct snmpdata *localstruct;
140
141 if (debug|snmp_debug)
142 {
143 print_err(1, "snmp.c:inside snmp_callback_response %x",
144 here->monitordata);
145 }
146
147 localstruct = here->monitordata;
148
149 #ifndef RECEIVED_MESSAGE
150 #define RECEIVED_MESSAGE NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE
151 #endif /* RECEIVED_MESSAGE */
152 if (operation == RECEIVED_MESSAGE)
153 {
154 if (extract_snmp_result(STAT_SUCCESS, localstruct->sess, pdu, localstruct))
155 {
156 if (debug|snmp_debug)
157 print_err(1, "snmp.c:snmp_callback_response:snmp_retval = %d on %s", localstruct->snmp_retval, here->checkent->hostname);
158 return 1;
159 }
160 }
161
162 here->retval = SYSM_NORESP;
163
164 return 0;
165 }
166
167 /*
168 * start snmp query
169 */
start_test_snmp(struct monitorent * here)170 void start_test_snmp(struct monitorent *here)
171 {
172 struct snmpdata *localstruct;
173 struct snmp_session startup_sess;
174
175 localstruct = MALLOC(sizeof(struct snmpdata), "snmpdata");
176
177 here->monitordata = localstruct;
178
179 localstruct->snmp_retval = 0;
180 localstruct->snmp_response = FALSE;
181
182 snmp_sess_init(&startup_sess); /* initialize session */
183
184 startup_sess.version = SNMP_VERSION_2c;
185 startup_sess.peername = here->checkent->hostname;
186 startup_sess.community = here->checkent->snmp_community;
187
188 startup_sess.remote_port = SNMP_DEFAULT_REMPORT;
189 startup_sess.timeout = SNMP_DEFAULT_TIMEOUT;
190 startup_sess.retries = SNMP_DEFAULT_RETRIES;
191
192 startup_sess.community_len =strlen(here->checkent->snmp_community);
193
194 /* set function to get callback data */
195 startup_sess.callback = snmp_callback_response;
196 startup_sess.callback_magic = here;
197
198 /* call snmp_open */
199
200 localstruct->sess = snmp_open(&startup_sess);
201
202 if (localstruct->sess == NULL)
203 {
204 print_err(1, "snmp_open returned an error");
205 /* return an error */
206 here->retval = -2;
207 return;
208 }
209
210 /* create pdu */
211
212 localstruct->req = snmp_pdu_create(SNMP_MSG_GET);
213
214 memset(localstruct->oid_value, 0, MAX_OID_LEN);
215
216 localstruct->oid_len = sizeof(localstruct->oid_value);
217
218 if (!read_objid(here->checkent->snmp_oid, localstruct->oid_value,
219 &localstruct->oid_len))
220 {
221 snmp_perror("snmp.c:read_objid");
222 here->retval = -2;
223 return;
224 }
225
226 snmp_add_null_var(localstruct->req,
227 localstruct->oid_value,
228 localstruct->oid_len);
229
230 /* send snmp packet */
231 if (debug|snmp_debug) print_err(1, "calling snmp_send");
232
233 /* snmp_send returns 0 on error, 1 on success */
234 if (snmp_send(localstruct->sess, localstruct->req) == 0)
235 {
236 perror("snmp_send");
237 }
238
239 return;
240 }
241
stop_test_snmp(struct monitorent * here)242 void stop_test_snmp(struct monitorent *here)
243 {
244 struct snmpdata *localstruct = NULL;
245
246 localstruct = here->monitordata;
247 if (localstruct == NULL)
248 {
249 print_err(1, "snmp.c:stop_test_snmp localstruct is null");
250 return;
251 }
252
253 /* close the snmp socket */
254 snmp_close(localstruct->sess);
255
256 free(localstruct);
257 here->monitordata = NULL;
258
259 return;
260 }
261
service_test_snmp(struct monitorent * here)262 void service_test_snmp(struct monitorent *here)
263 {
264 struct snmpdata *localstruct = NULL;
265 fd_set fdset;
266 int max_fd = 0;
267 int block = 1;
268 int ret = 0;
269 unsigned long rate_time;
270 unsigned long rate_time_val;
271 unsigned long rate_avg_val;
272 struct timeval timeout;
273 struct timeval now;
274
275 localstruct = here->monitordata;
276 if (localstruct == NULL)
277 {
278 print_err(1, "snmp.c:service_test_snmp localstruct is null");
279 return;
280 }
281
282 FD_ZERO(&fdset);
283 snmp_select_info(&max_fd, &fdset, &timeout, &block);
284
285 timeout.tv_sec = 0;
286 timeout.tv_usec = 0;
287
288 ret = select(max_fd, &fdset, NULL, NULL, &timeout);
289 if (ret)
290 {
291 snmp_read(&fdset);
292 }
293
294 if (debug|snmp_debug) print_err(1, "snmp.c:svc_test_snmp:snmp_response = %d", localstruct->snmp_response);
295 if (localstruct->snmp_response)
296 {
297 if (debug|snmp_debug) print_err(1, "snmp.c:snmp_response(%s)", here->checkent->hostname);
298 switch (here->checkent->snmp_test_type)
299 {
300 case SYSM_SNMP_TYPE_REBOOT:
301 if (debug|snmp_debug) print_err(1, "snmp.c:type_reboot:comparing last(%d) > now(%d)", here->checkent->system_uptime, localstruct->snmp_retval);
302 if (here->checkent->system_uptime > localstruct->snmp_retval)
303 {
304 here->retval = SYSM_SNMP_REBOOT;
305 } else {
306 here->retval = SYSM_OK;
307 }
308 here->checkent->system_uptime = localstruct->snmp_retval;
309 break;
310 case SYSM_SNMP_TYPE_HIGH:
311 if (debug|snmp_debug) print_err(1, "snmp.c:type_high:comparing received value %d with configured %d", localstruct->snmp_retval, here->checkent->snmp_high);
312 if (here->checkent->snmp_high < localstruct->snmp_retval)
313 {
314 here->retval = SYSM_SNMP_HIGH;
315 } else {
316 here->retval = SYSM_OK;
317 }
318 /* stash last snmp value */
319 here->checkent->system_uptime = localstruct->snmp_retval;
320 break;
321 case SYSM_SNMP_TYPE_LOW:
322 if (debug|snmp_debug) print_err(1, "snmp.c:type_low:comparing received value %d with configured %d", localstruct->snmp_retval, here->checkent->snmp_low);
323 if (here->checkent->snmp_low > localstruct->snmp_retval)
324 {
325 here->retval = SYSM_SNMP_LOW;
326 } else {
327 here->retval = SYSM_OK;
328 }
329 /* stash last snmp value */
330 here->checkent->system_uptime = localstruct->snmp_retval;
331 break;
332 case SYSM_SNMP_TYPE_RANGE:
333 if ((here->checkent->snmp_low < localstruct->snmp_retval) && (here->checkent->snmp_high > localstruct->snmp_retval))
334 {
335 here->retval = SYSM_SNMP_OOR;
336 } else {
337 here->retval = SYSM_OK;
338 }
339 /* stash last snmp value */
340 here->checkent->system_uptime = localstruct->snmp_retval;
341 break;
342 case SYSM_SNMP_TYPE_EXACT:
343 if (here->checkent->snmp_exact != localstruct->snmp_retval)
344 {
345 here->retval = SYSM_SNMP_NOTEXACT;
346 } else {
347 here->retval = SYSM_OK;
348 }
349 /* stash last snmp value */
350 here->checkent->system_uptime = localstruct->snmp_retval;
351 break;
352 case SYSM_SNMP_TYPE_COMPARE:
353 break;
354 case SYSM_SNMP_TYPE_RATE:
355 rate_time = (localstruct->snmp_response_time - here->checkent->last_snmp_resptime);
356 rate_time_val = (localstruct->snmp_retval - here->checkent->system_uptime);
357 if (here->checkent->snmp_octets)
358 {
359 rate_avg_val=(rate_time_val*8/rate_time);
360 } else {
361 rate_avg_val=(rate_time_val/rate_time);
362 }
363
364 if (debug|snmp_debug)
365 print_err(1, "snmp.c:rate_avg_val = %u ; here->checkent->snmp_rate %u", rate_avg_val, here->checkent->snmp_rate);
366 here->checkent->system_uptime = localstruct->snmp_retval;
367 here->checkent->last_snmp_resptime = localstruct->snmp_response_time;
368 if (rate_avg_val > here->checkent->snmp_rate)
369 {
370 here->retval = SYSM_SNMP_HIGHRATE;
371 } else {
372 here->retval = SYSM_OK;
373 }
374 break;
375 default:
376 print_err(1, "snmp.c:invalid snmp type");
377 here->retval = -2;
378 break;
379 }
380
381 } else {
382 gettimeofday(&now, NULL); /* get the current time */
383 if (mydifftime(here->queueat, now) >= 30)
384 {
385 here->retval = SYSM_NORESP;
386 }
387 }
388
389 if (debug|snmp_debug)
390 {
391 print_err(1, "snmp.c:svc_test_snmp:checking here->retval it is %d", here->retval);
392 }
393
394 if (here->retval != -1)
395 {
396 if (debug|snmp_debug) print_err(1, "snmp.c:svc_test_snmp:here->retval = %d", here->retval);
397 snmp_close(localstruct->sess);
398
399 free(here->monitordata);
400
401 here->monitordata = NULL;
402 }
403
404 return;
405 }
406 #endif /* ENABLE_SNMP */
407