2
* ICMP MIB group implementation - icmp.c
6
#include <net-snmp/net-snmp-config.h>
7
#include "mibII_common.h"
9
#if HAVE_NETINET_IP_ICMP_H
10
#include <netinet/ip_icmp.h>
12
#if HAVE_NETINET_ICMP_VAR_H
13
#include <netinet/icmp_var.h>
16
#include <net-snmp/net-snmp-includes.h>
17
#include <net-snmp/agent/net-snmp-agent-includes.h>
18
#include <net-snmp/agent/auto_nlist.h>
20
#include <net-snmp/agent/cache_handler.h>
21
#include <net-snmp/agent/scalar_group.h>
23
#include "util_funcs.h"
25
#include "sysORTable.h"
27
#ifndef MIB_STATS_CACHE_TIMEOUT
28
#define MIB_STATS_CACHE_TIMEOUT 5
30
#ifndef ICMP_STATS_CACHE_TIMEOUT
31
#define ICMP_STATS_CACHE_TIMEOUT MIB_STATS_CACHE_TIMEOUT
34
/*********************
36
* Kernel & interface information,
37
* and internal forward declarations
39
*********************/
41
/*********************
43
* Initialisation & common implementation functions
45
*********************/
50
* Define the OID pointer to the top of the mib tree that we're
51
* registering underneath
53
oid icmp_oid[] = { SNMP_OID_MIB2, 5 };
54
#ifdef USING_MIBII_IP_MODULE
55
extern oid ip_module_oid[];
56
extern int ip_module_oid_len;
57
extern int ip_module_count;
63
netsnmp_handler_registration *reginfo;
66
* register ourselves with the agent as a group of scalars...
68
DEBUGMSGTL(("mibII/icmp", "Initialising ICMP group\n"));
69
reginfo = netsnmp_create_handler_registration("icmp", icmp_handler,
70
icmp_oid, OID_LENGTH(icmp_oid), HANDLER_CAN_RONLY);
71
netsnmp_register_scalar_group(reginfo, ICMPINMSGS, ICMPOUTADDRMASKREPS);
73
* .... with a local cache
74
* (except for HP-UX 11, which extracts objects individually)
77
netsnmp_inject_handler( reginfo,
78
netsnmp_get_cache_handler(ICMP_STATS_CACHE_TIMEOUT,
80
icmp_oid, OID_LENGTH(icmp_oid)));
83
#ifdef USING_MIBII_IP_MODULE
84
if (++ip_module_count == 2)
85
REGISTER_SYSOR_TABLE(ip_module_oid, ip_module_oid_len,
86
"The MIB module for managing IP and ICMP implementations");
89
#ifdef ICMPSTAT_SYMBOL
90
auto_nlist(ICMPSTAT_SYMBOL, 0, 0);
98
/*********************
100
* System specific data formats
102
*********************/
105
#define ICMP_STAT_STRUCTURE int
109
#define ICMP_STAT_STRUCTURE struct icmp_mib
110
#define USES_SNMP_DESIGNED_ICMPSTAT
111
#undef ICMPSTAT_SYMBOL
115
#define ICMP_STAT_STRUCTURE mib2_icmp_t
116
#define USES_SNMP_DESIGNED_ICMPSTAT
120
#include <iphlpapi.h>
121
#define ICMP_STAT_STRUCTURE MIB_ICMP
124
/* ?? #if (defined(CAN_USE_SYSCTL) && defined(ICMPCTL_STATS)) ?? */
126
#ifdef HAVE_SYS_ICMPIPSTATS_H
127
/* or #ifdef HAVE_SYS_TCPIPSTATS_H ??? */
128
#define ICMP_STAT_STRUCTURE struct kna
129
#define USES_TRADITIONAL_ICMPSTAT
132
#if !defined(ICMP_STAT_STRUCTURE)
133
#define ICMP_STAT_STRUCTURE struct icmpstat
134
#define USES_TRADITIONAL_ICMPSTAT
138
ICMP_STAT_STRUCTURE icmpstat;
141
/*********************
143
* System independent handler
146
*********************/
149
icmp_handler(netsnmp_mib_handler *handler,
150
netsnmp_handler_registration *reginfo,
151
netsnmp_agent_request_info *reqinfo,
152
netsnmp_request_info *requests)
154
netsnmp_request_info *request;
155
netsnmp_variable_list *requestvb;
158
#ifdef USES_TRADITIONAL_ICMPSTAT
163
* The cached data should already have been loaded by the
164
* cache handler, higher up the handler chain.
165
* But just to be safe, check this and load it manually if necessary
168
if (netsnmp_is_cache_valid(reqinfo)) {
169
icmp_load( NULL, NULL ); /* XXX - check for failure */
178
DEBUGMSGTL(("mibII/icmp", "Handler - mode %s\n",
179
se_find_label_in_slist("agent_mode", reqinfo->mode)));
180
switch (reqinfo->mode) {
182
for (request=requests; request; request=request->next) {
183
requestvb = request->requestvb;
184
subid = requestvb->name[OID_LENGTH(icmp_oid)]; /* XXX */
185
DEBUGMSGTL(( "mibII/icmp", "oid: "));
186
DEBUGMSGOID(("mibII/icmp", requestvb->name,
187
requestvb->name_length));
188
DEBUGMSG(( "mibII/icmp", "\n"));
191
#ifdef USES_SNMP_DESIGNED_ICMPSTAT
193
ret_value = icmpstat.icmpInMsgs;
196
ret_value = icmpstat.icmpInErrors;
198
case ICMPINDESTUNREACHS:
199
ret_value = icmpstat.icmpInDestUnreachs;
201
case ICMPINTIMEEXCDS:
202
ret_value = icmpstat.icmpInTimeExcds;
204
case ICMPINPARMPROBS:
205
ret_value = icmpstat.icmpInParmProbs;
207
case ICMPINSRCQUENCHS:
208
ret_value = icmpstat.icmpInSrcQuenchs;
210
case ICMPINREDIRECTS:
211
ret_value = icmpstat.icmpInRedirects;
214
ret_value = icmpstat.icmpInEchos;
217
ret_value = icmpstat.icmpInEchoReps;
219
case ICMPINTIMESTAMPS:
220
ret_value = icmpstat.icmpInTimestamps;
222
case ICMPINTIMESTAMPREPS:
223
ret_value = icmpstat.icmpInTimestampReps;
225
case ICMPINADDRMASKS:
226
ret_value = icmpstat.icmpInAddrMasks;
228
case ICMPINADDRMASKREPS:
229
ret_value = icmpstat.icmpInAddrMaskReps;
232
ret_value = icmpstat.icmpOutMsgs;
235
ret_value = icmpstat.icmpOutErrors;
237
case ICMPOUTDESTUNREACHS:
238
ret_value = icmpstat.icmpOutDestUnreachs;
240
case ICMPOUTTIMEEXCDS:
241
ret_value = icmpstat.icmpOutTimeExcds;
243
case ICMPOUTPARMPROBS:
244
ret_value = icmpstat.icmpOutParmProbs;
246
case ICMPOUTSRCQUENCHS:
247
ret_value = icmpstat.icmpOutSrcQuenchs;
249
case ICMPOUTREDIRECTS:
250
ret_value = icmpstat.icmpOutRedirects;
253
ret_value = icmpstat.icmpOutEchos;
255
case ICMPOUTECHOREPS:
256
ret_value = icmpstat.icmpOutEchoReps;
258
case ICMPOUTTIMESTAMPS:
259
ret_value = icmpstat.icmpOutTimestamps;
261
case ICMPOUTTIMESTAMPREPS:
262
ret_value = icmpstat.icmpOutTimestampReps;
264
case ICMPOUTADDRMASKS:
265
ret_value = icmpstat.icmpOutAddrMasks;
267
case ICMPOUTADDRMASKREPS:
268
ret_value = icmpstat.icmpOutAddrMaskReps;
270
#else /* USES_SNMP_DESIGNED_ICMPSTAT */
272
#ifdef USES_TRADITIONAL_ICMPSTAT
274
ret_value = icmpstat.icps_badcode +
275
icmpstat.icps_tooshort +
276
icmpstat.icps_checksum + icmpstat.icps_badlen;
277
for (i = 0; i <= ICMP_MAXTYPE; i++)
278
ret_value += icmpstat.icps_inhist[i];
281
ret_value = icmpstat.icps_badcode +
282
icmpstat.icps_tooshort +
283
icmpstat.icps_checksum + icmpstat.icps_badlen;
285
case ICMPINDESTUNREACHS:
286
ret_value = icmpstat.icps_inhist[ICMP_UNREACH];
288
case ICMPINTIMEEXCDS:
289
ret_value = icmpstat.icps_inhist[ICMP_TIMXCEED];
291
case ICMPINPARMPROBS:
292
ret_value = icmpstat.icps_inhist[ICMP_PARAMPROB];
294
case ICMPINSRCQUENCHS:
295
ret_value = icmpstat.icps_inhist[ICMP_SOURCEQUENCH];
297
case ICMPINREDIRECTS:
298
ret_value = icmpstat.icps_inhist[ICMP_REDIRECT];
301
ret_value = icmpstat.icps_inhist[ICMP_ECHO];
304
ret_value = icmpstat.icps_inhist[ICMP_ECHOREPLY];
306
case ICMPINTIMESTAMPS:
307
ret_value = icmpstat.icps_inhist[ICMP_TSTAMP];
309
case ICMPINTIMESTAMPREPS:
310
ret_value = icmpstat.icps_inhist[ICMP_TSTAMPREPLY];
312
case ICMPINADDRMASKS:
313
ret_value = icmpstat.icps_inhist[ICMP_MASKREQ];
315
case ICMPINADDRMASKREPS:
316
ret_value = icmpstat.icps_inhist[ICMP_MASKREPLY];
319
ret_value = icmpstat.icps_oldshort + icmpstat.icps_oldicmp;
320
for (i = 0; i <= ICMP_MAXTYPE; i++)
321
ret_value += icmpstat.icps_outhist[i];
324
ret_value = icmpstat.icps_oldshort + icmpstat.icps_oldicmp;
326
case ICMPOUTDESTUNREACHS:
327
ret_value = icmpstat.icps_outhist[ICMP_UNREACH];
329
case ICMPOUTTIMEEXCDS:
330
ret_value = icmpstat.icps_outhist[ICMP_TIMXCEED];
332
case ICMPOUTPARMPROBS:
333
ret_value = icmpstat.icps_outhist[ICMP_PARAMPROB];
335
case ICMPOUTSRCQUENCHS:
336
ret_value = icmpstat.icps_outhist[ICMP_SOURCEQUENCH];
338
case ICMPOUTREDIRECTS:
339
ret_value = icmpstat.icps_outhist[ICMP_REDIRECT];
342
ret_value = icmpstat.icps_outhist[ICMP_ECHO];
344
case ICMPOUTECHOREPS:
345
ret_value = icmpstat.icps_outhist[ICMP_ECHOREPLY];
347
case ICMPOUTTIMESTAMPS:
348
ret_value = icmpstat.icps_outhist[ICMP_TSTAMP];
350
case ICMPOUTTIMESTAMPREPS:
351
ret_value = icmpstat.icps_outhist[ICMP_TSTAMPREPLY];
353
case ICMPOUTADDRMASKS:
354
ret_value = icmpstat.icps_outhist[ICMP_MASKREQ];
356
case ICMPOUTADDRMASKREPS:
357
ret_value = icmpstat.icps_outhist[ICMP_MASKREPLY];
359
#else /* USES_TRADITIONAL_ICMPSTAT */
364
case ICMPINDESTUNREACHS:
365
case ICMPINTIMEEXCDS:
366
case ICMPINPARMPROBS:
367
case ICMPINSRCQUENCHS:
368
case ICMPINREDIRECTS:
371
case ICMPINTIMESTAMPS:
372
case ICMPINTIMESTAMPREPS:
373
case ICMPINADDRMASKS:
374
case ICMPINADDRMASKREPS:
377
case ICMPOUTDESTUNREACHS:
378
case ICMPOUTTIMEEXCDS:
379
case ICMPOUTPARMPROBS:
380
case ICMPOUTSRCQUENCHS:
381
case ICMPOUTREDIRECTS:
383
case ICMPOUTECHOREPS:
384
case ICMPOUTTIMESTAMPS:
385
case ICMPOUTTIMESTAMPREPS:
386
case ICMPOUTADDRMASKS:
387
case ICMPOUTADDRMASKREPS:
389
* This is a bit of a hack, to shoehorn the HP-UX 11
390
* single-object retrieval approach into the caching
393
if (icmp_load(NULL, (void*)subid) == -1 ) {
394
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
397
ret_value = icmpstat;
403
ret_value = icmpstat.stats.icmpInStats.dwMsgs;
406
ret_value = icmpstat.stats.icmpInStats.dwErrors;
408
case ICMPINDESTUNREACHS:
409
ret_value = icmpstat.stats.icmpInStats.dwDestUnreachs;
411
case ICMPINTIMEEXCDS:
412
ret_value = icmpstat.stats.icmpInStats.dwTimeExcds;
414
case ICMPINPARMPROBS:
415
ret_value = icmpstat.stats.icmpInStats.dwParmProbs;
417
case ICMPINSRCQUENCHS:
418
ret_value = icmpstat.stats.icmpInStats.dwSrcQuenchs;
420
case ICMPINREDIRECTS:
421
ret_value = icmpstat.stats.icmpInStats.dwRedirects;
424
ret_value = icmpstat.stats.icmpInStats.dwEchos;
427
ret_value = icmpstat.stats.icmpInStats.dwEchoReps;
429
case ICMPINTIMESTAMPS:
430
ret_value = icmpstat.stats.icmpInStats.dwTimestamps;
432
case ICMPINTIMESTAMPREPS:
433
ret_value = icmpstat.stats.icmpInStats.dwTimestampReps;
435
case ICMPINADDRMASKS:
436
ret_value = icmpstat.stats.icmpInStats.dwAddrMasks;
438
case ICMPINADDRMASKREPS:
439
ret_value = icmpstat.stats.icmpInStats.dwAddrMaskReps;
442
ret_value = icmpstat.stats.icmpOutStats.dwMsgs;
445
ret_value = icmpstat.stats.icmpOutStats.dwErrors;
447
case ICMPOUTDESTUNREACHS:
448
ret_value = icmpstat.stats.icmpOutStats.dwDestUnreachs;
450
case ICMPOUTTIMEEXCDS:
451
ret_value = icmpstat.stats.icmpOutStats.dwTimeExcds;
453
case ICMPOUTPARMPROBS:
454
ret_value = icmpstat.stats.icmpOutStats.dwParmProbs;
456
case ICMPOUTSRCQUENCHS:
457
ret_value = icmpstat.stats.icmpOutStats.dwSrcQuenchs;
459
case ICMPOUTREDIRECTS:
460
ret_value = icmpstat.stats.icmpOutStats.dwRedirects;
463
ret_value = icmpstat.stats.icmpOutStats.dwEchos;
465
case ICMPOUTECHOREPS:
466
ret_value = icmpstat.stats.icmpOutStats.dwEchoReps;
468
case ICMPOUTTIMESTAMPS:
469
ret_value = icmpstat.stats.icmpOutStats.dwTimestamps;
471
case ICMPOUTTIMESTAMPREPS:
472
ret_value = icmpstat.stats.icmpOutStats.dwTimestampReps;
474
case ICMPOUTADDRMASKS:
475
ret_value = icmpstat.stats.icmpOutStats.dwAddrMasks;
477
case ICMPOUTADDRMASKREPS:
478
ret_value = icmpstat.stats.icmpOutStats.dwAddrMaskReps;
482
#endif /* USES_TRADITIONAL_ICMPSTAT */
483
#endif /* USES_SNMP_DESIGNED_ICMPSTAT */
485
snmp_set_var_typed_value(request->requestvb, ASN_COUNTER,
486
(u_char *)&ret_value, sizeof(ret_value));
492
case MODE_SET_RESERVE1:
493
case MODE_SET_RESERVE2:
494
case MODE_SET_ACTION:
495
case MODE_SET_COMMIT:
498
snmp_log(LOG_WARNING, "mibII/icmp: Unsupported mode (%d)\n",
502
snmp_log(LOG_WARNING, "mibII/icmp: Unrecognised mode (%d)\n",
507
return SNMP_ERR_NOERROR;
511
/*********************
513
* Internal implementation functions
515
*********************/
519
icmp_load(netsnmp_cache *cache, void *vmagic)
525
int magic = (int) vmagic;
527
if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) < 0) {
528
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP object %d (hpux11)\n", magic));
529
return (-1); /* error */
534
p.objid = ID_icmpInMsgs;
537
p.objid = ID_icmpInErrors;
539
case ICMPINDESTUNREACHS:
540
p.objid = ID_icmpInDestUnreachs;
542
case ICMPINTIMEEXCDS:
543
p.objid = ID_icmpInTimeExcds;
545
case ICMPINPARMPROBS:
546
p.objid = ID_icmpInParmProbs;
548
case ICMPINSRCQUENCHS:
549
p.objid = ID_icmpInSrcQuenchs;
551
case ICMPINREDIRECTS:
552
p.objid = ID_icmpInRedirects;
555
p.objid = ID_icmpInEchos;
558
p.objid = ID_icmpInEchoReps;
560
case ICMPINTIMESTAMPS:
561
p.objid = ID_icmpInTimestamps;
563
case ICMPINTIMESTAMPREPS:
564
p.objid = ID_icmpInTimestampReps;
566
case ICMPINADDRMASKS:
567
p.objid = ID_icmpInAddrMasks;
569
case ICMPINADDRMASKREPS:
570
p.objid = ID_icmpInAddrMaskReps;
573
p.objid = ID_icmpOutMsgs;
576
p.objid = ID_icmpOutErrors;
578
case ICMPOUTDESTUNREACHS:
579
p.objid = ID_icmpOutDestUnreachs;
581
case ICMPOUTTIMEEXCDS:
582
p.objid = ID_icmpOutTimeExcds;
584
case ICMPOUTPARMPROBS:
585
p.objid = ID_icmpOutParmProbs;
587
case ICMPOUTSRCQUENCHS:
588
p.objid = ID_icmpOutSrcQuenchs;
590
case ICMPOUTREDIRECTS:
591
p.objid = ID_icmpOutRedirects;
594
p.objid = ID_icmpOutEchos;
596
case ICMPOUTECHOREPS:
597
p.objid = ID_icmpOutEchoReps;
599
case ICMPOUTTIMESTAMPS:
600
p.objid = ID_icmpOutTimestamps;
602
case ICMPOUTTIMESTAMPREPS:
603
p.objid = ID_icmpOutTimestampReps;
605
case ICMPOUTADDRMASKS:
606
p.objid = ID_icmpOutAddrMasks;
608
case ICMPOUTADDRMASKREPS:
609
p.objid = ID_icmpOutAddrMaskReps;
617
p.buffer = (void *)&icmpstat;
618
ulen = sizeof(ICMP_STAT_STRUCTURE);
620
ret = get_mib_info(fd, &p);
623
DEBUGMSGTL(("mibII/icmp", "%s ICMP object %d (hpux11)\n",
624
(ret < 0 ? "Failed to load" : "Loaded"), magic));
625
return (ret); /* 0: ok, < 0: error */
630
icmp_load(netsnmp_cache *cache, void *vmagic)
634
ret_value = linux_read_icmp_stat(&icmpstat);
636
if ( ret_value < 0 ) {
637
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (linux)\n"));
639
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (linux)\n"));
646
icmp_load(netsnmp_cache *cache, void *vmagic)
651
getMibstat(MIB_ICMP, &icmpstat, sizeof(mib2_icmp_t), GET_FIRST,
652
&Get_everything, NULL);
654
if ( ret_value < 0 ) {
655
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (solaris)\n"));
657
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (solaris)\n"));
664
icmp_load(netsnmp_cache *cache, void *vmagic)
668
ret_value = GetIcmpStatistics(&icmpstat);
670
if ( ret_value < 0 ) {
671
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (win32)\n"));
673
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (win32)\n"));
678
#if (defined(CAN_USE_SYSCTL) && defined(ICMPCTL_STATS))
680
icmp_load(netsnmp_cache *cache, void *vmagic)
683
static int sname[4] =
684
{ CTL_NET, PF_INET, IPPROTO_ICMP, ICMPCTL_STATS };
685
size_t len = sizeof(icmpstat);
687
ret_value = sysctl(sname, 4, &icmpstat, &len, 0, 0);
689
if ( ret_value < 0 ) {
690
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (sysctl)\n"));
692
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (sysctl)\n"));
696
#else /* CAN_USE_SYSCTL && ICMPCTL_STATS */
697
#ifdef HAVE_SYS_TCPIPSTATS_H
699
icmp_load(netsnmp_cache *cache, void *vmagic)
704
sysmp(MP_SAGET, MPSA_TCPIPSTATS, &icmpstat, sizeof icmpstat);
706
if ( ret_value < 0 ) {
707
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (tcpipstats)\n"));
709
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (tcpipstats)\n"));
713
#else /* HAVE_SYS_TCPIPSTATS_H */
714
#ifdef ICMPSTAT_SYMBOL
716
icmp_load(netsnmp_cache *cache, void *vmagic)
720
if (auto_nlist(ICMPSTAT_SYMBOL, (char *)&icmpstat, sizeof(icmpstat)))
723
if ( ret_value < 0 ) {
724
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (icmpstat)\n"));
726
DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (icmpstat)\n"));
730
#else /* ICMPSTAT_SYMBOL */
732
icmp_load(netsnmp_cache *cache, void *vmagic)
736
DEBUGMSGTL(("mibII/icmp", "Failed to load ICMP Group (null)\n"));
739
#endif /* ICMPSTAT_SYMBOL */
740
#endif /* HAVE_SYS_TCPIPSTATS_H */
741
#endif /* CAN_USE_SYSCTL && ICMPCTL_STATS */
743
#endif /* solaris2 */
748
icmp_free(netsnmp_cache *cache, void *magic)
750
memset(&icmpstat, 0, sizeof(icmpstat));