Add ability to retrieve /proc/net/snmp6 under linux Prepares ground for following patches Source: http://sourceforge.net/tracker/index.php?func=detail&aid=1702361&group_id=12694&atid=312694 --- agent/mibgroup/mibII/kernel_linux.h.snmp6 2007-04-11 12:00:25.000000000 -0400 +++ agent/mibgroup/mibII/kernel_linux.h 2007-04-17 11:23:39.000000000 -0400 @@ -29,6 +29,31 @@ struct ip_mib { unsigned long ipRoutingDiscards; }; +struct ip6_mib { + unsigned long ip6InReceives; + unsigned long ip6InHdrErrors; + unsigned long ip6InTooBigErrors; + unsigned long ip6InNoRoutes; + unsigned long ip6InAddrErrors; + unsigned long ip6InUnknownProtos; + unsigned long ip6InTruncatedPkts; + unsigned long ip6InDiscards; + unsigned long ip6InDelivers; + unsigned long ip6OutForwDatagrams; + unsigned long ip6OutRequests; + unsigned long ip6OutDiscards; + unsigned long ip6OutNoRoutes; + unsigned long ip6ReasmTimeout; + unsigned long ip6ReasmReqds; + unsigned long ip6ReasmOKs; + unsigned long ip6ReasmFails; + unsigned long ip6FragOKs; + unsigned long ip6FragFails; + unsigned long ip6FragCreates; + unsigned long ip6InMcastPkts; + unsigned long ip6OutMcastPkts; +}; + struct icmp_mib { unsigned long icmpInMsgs; unsigned long icmpInErrors; @@ -58,6 +83,37 @@ struct icmp_mib { unsigned long icmpOutAddrMaskReps; }; +struct icmp6_mib { + unsigned long icmp6InMsgs; + unsigned long icmp6InErrors; + unsigned long icmp6InDestUnreachs; + unsigned long icmp6InPktTooBigs; + unsigned long icmp6InTimeExcds; + unsigned long icmp6InParmProblems; + unsigned long icmp6InEchos; + unsigned long icmp6InEchoReplies; + unsigned long icmp6InGroupMembQueries; + unsigned long icmp6InGroupMembResponses; + unsigned long icmp6InGroupMembReductions; + unsigned long icmp6InRouterSolicits; + unsigned long icmp6InRouterAdvertisements; + unsigned long icmp6InNeighborSolicits; + unsigned long icmp6InNeighborAdvertisements; + unsigned long icmp6InRedirects; + unsigned long icmp6OutMsgs; + unsigned long icmp6OutDestUnreachs; + unsigned long icmp6OutPktTooBigs; + unsigned long icmp6OutTimeExcds; + unsigned long icmp6OutParmProblems; + unsigned long icmp6OutEchoReplies; + unsigned long icmp6OutRouterSolicits; + unsigned long icmp6OutNeighborSolicits; + unsigned long icmp6OutNeighborAdvertisements; + unsigned long icmp6OutRedirects; + unsigned long icmp6OutGroupMembResponses; + unsigned long icmp6OutGroupMembReductions; +}; + struct udp_mib { unsigned long udpInDatagrams; unsigned long udpNoPorts; @@ -65,6 +121,17 @@ struct udp_mib { unsigned long udpOutDatagrams; }; +struct udp6_mib { + unsigned long udp6InDatagrams; + unsigned long udp6NoPorts; + unsigned long udp6InErrors; + unsigned long udp6OutDatagrams; + unsigned long udpLite6InDatagrams; + unsigned long udpLite6NoPorts; + unsigned long udpLite6InErrors; + unsigned long udpLite6OutDatagrams; +}; + struct tcp_mib { unsigned long tcpRtoAlgorithm; unsigned long tcpRtoMin; @@ -86,8 +153,11 @@ struct tcp_mib { int linux_read_ip_stat(struct ip_mib *); +int linux_read_ip6_stat(struct ip6_mib *); int linux_read_icmp_stat(struct icmp_mib *); +int linux_read_icmp6_stat(struct icmp6_mib *); int linux_read_udp_stat(struct udp_mib *); +int linux_read_udp6_stat(struct udp6_mib *); int linux_read_tcp_stat(struct tcp_mib *); #endif /* _MIBGROUP_KERNEL_LINUX_H */ --- agent/mibgroup/mibII/ipv6.c.snmp6 2007-04-11 12:00:25.000000000 -0400 +++ agent/mibgroup/mibII/ipv6.c 2007-04-17 11:23:39.000000000 -0400 @@ -1850,7 +1850,7 @@ linux_read_ip6_stat_ulong(const char *fi return value; } -void +static void linux_read_ip6_stat(struct ip6_mib *ip6stat) { if (!ip6stat) --- agent/mibgroup/mibII/kernel_linux.c.snmp6 2007-04-11 12:00:25.000000000 -0400 +++ agent/mibgroup/mibII/kernel_linux.c 2007-04-17 11:23:39.000000000 -0400 @@ -20,9 +20,12 @@ #include "kernel_linux.h" struct ip_mib cached_ip_mib; +struct ip6_mib cached_ip6_mib; struct icmp_mib cached_icmp_mib; +struct icmp6_mib cached_icmp6_mib; struct tcp_mib cached_tcp_mib; struct udp_mib cached_udp_mib; +struct udp6_mib cached_udp6_mib; #define IP_STATS_LINE "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu" #define ICMP_STATS_LINE "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu" @@ -46,7 +49,9 @@ linux_read_mibII_stats(void) unsigned long value; #endif char line[1024]; - + unsigned long *snmp6_ptr = NULL; + int i; + int ret = -1; if (!in) { DEBUGMSGTL(("mibII/kernel_linux","Unable to open /proc/net/snmp")); return -1; @@ -176,7 +181,50 @@ linux_read_mibII_stats(void) */ if (!cached_tcp_mib.tcpRtoAlgorithm) cached_tcp_mib.tcpRtoAlgorithm = 1; - return 0; + + snmp_log(LOG_CRIT, "MIBII: READING SNMP6 STATS\n"); + in = fopen("/proc/net/snmp6","r"); + + if (!in) + return -1; + + /* + * lets try to accelerate this a bit + * by assuming we know the order that + * the file is in (which we really should) + */ + for (snmp6_ptr = (unsigned long *)&cached_ip6_mib, i=0; + i < (sizeof(struct ip6_mib)/sizeof(unsigned long)); + snmp6_ptr++, i++) { + + if (EOF == fscanf(in, "%*s %lu",snmp6_ptr)) + goto out; + snmp_log(LOG_ERR, "SNMP6: READ VALUE %lu\n",*snmp6_ptr); + } + + for (snmp6_ptr = (unsigned long *)&cached_icmp6_mib, i=0; + i < (sizeof(struct icmp6_mib)/sizeof(unsigned long)); + snmp6_ptr++, i++) { + + if (EOF == fscanf(in, "%*s %lu\n",snmp6_ptr)) + goto out; + snmp_log(LOG_ERR, "SNMP6: READ VALUE %lu\n",*snmp6_ptr); + } + + for (snmp6_ptr = (unsigned long *)&cached_udp6_mib, i=0; + i < (sizeof(struct udp6_mib)/sizeof(unsigned long)); + snmp6_ptr++, i++) { + + if (EOF == fscanf(in, "%*s %lu\n",snmp6_ptr)) + goto out; + snmp_log(LOG_ERR, "SNMP6: READ VALUE %lu\n",*snmp6_ptr); + } + + ret = 0; +out: + fclose(in); + + return ret; } int @@ -189,6 +237,15 @@ linux_read_ip_stat(struct ip_mib *ipstat return 0; } +int linux_read_ip6_stat( struct ip6_mib *ip6stat) +{ + + memset((char *) ip6stat, (0), sizeof(*ip6stat)); + if (linux_read_mibII_stats() == -1) + return -1; + memcpy((char *) ip6stat, (char *) &cached_ip6_mib, sizeof(*ip6stat)); +} + int linux_read_icmp_stat(struct icmp_mib *icmpstat) { @@ -200,6 +257,18 @@ linux_read_icmp_stat(struct icmp_mib *ic return 0; } + +int +linux_read_icmp6_stat(struct icmp6_mib *icmp6stat) +{ + memset((char *) icmp6stat, (0), sizeof(*icmp6stat)); + if (linux_read_mibII_stats() == -1) + return -1; + memcpy((char *) icmp6stat, (char *) &cached_icmp6_mib, + sizeof(*icmp6stat)); + return 0; +} + int linux_read_tcp_stat(struct tcp_mib *tcpstat) { @@ -219,3 +288,13 @@ linux_read_udp_stat(struct udp_mib *udps memcpy((char *) udpstat, (char *) &cached_udp_mib, sizeof(*udpstat)); return 0; } + +int +linux_read_udp6_stat(struct udp6_mib *udp6stat) +{ + memset((char *) udp6stat, (0), sizeof(*udp6stat)); + if (linux_read_mibII_stats() == -1) + return -1; + memcpy((char *) udp6stat, (char *) &cached_udp6_mib, sizeof(*udp6stat)); + return 0; +} icmpStatsTable: http://sourceforge.net/tracker/index.php?func=detail&aid=1702366&group_id=12694&atid=312694 --- agent/mibgroup/mibII/icmp.c.icmp6 2007-04-11 12:00:25.000000000 -0400 +++ agent/mibgroup/mibII/icmp.c 2007-04-17 11:23:57.000000000 -0400 @@ -54,22 +54,146 @@ perfstat_id_t ps_name; *********************/ - /* * Define the OID pointer to the top of the mib tree that we're * registering underneath */ oid icmp_oid[] = { SNMP_OID_MIB2, 5 }; +oid icmp_stats_tbl_oid[] = { SNMP_OID_MIB2, 5, 29 }; #ifdef USING_MIBII_IP_MODULE extern oid ip_module_oid[]; extern int ip_module_oid_len; extern int ip_module_count; #endif +#ifdef linux +struct icmp_stats_table_entry { + __uint32_t ipVer; + __uint32_t icmpStatsInMsgs; + __uint32_t icmpStatsInErrors; + __uint32_t icmpStatsOutMsgs; + __uint32_t icmpStatsOutErrors; +}; + +struct icmp_stats_table_entry icmp_stats_table[3]; + +int +icmp_stats_load(netsnmp_cache *cache, void *vmagic) +{ + + /* + * note don't bother using the passed in cache + * and vmagic pointers. They are useless as they + * currently point to the icmp system stats cache + * since I see little point in registering another + * cache for this table. Its not really needed + */ + + int i; + struct icmp_mib v4icmp; + struct icmp6_mib v6icmp; + for(i=0;i<3;i++) { + switch(i) { + case 1: + linux_read_icmp_stat(&v4icmp); + icmp_stats_table[i].icmpStatsInMsgs = v4icmp.icmpInMsgs; + icmp_stats_table[i].icmpStatsInErrors = v4icmp.icmpInErrors; + icmp_stats_table[i].icmpStatsOutMsgs = v4icmp.icmpOutMsgs; + icmp_stats_table[i].icmpStatsOutErrors = v4icmp.icmpOutErrors; + break; + default: + memset(&icmp_stats_table[i],0, + sizeof(struct icmp_stats_table_entry)); + linux_read_icmp6_stat(&v6icmp); + icmp_stats_table[i].icmpStatsInMsgs = v6icmp.icmp6InMsgs; + icmp_stats_table[i].icmpStatsInErrors = v6icmp.icmp6InErrors; + icmp_stats_table[i].icmpStatsOutMsgs = v6icmp.icmp6OutMsgs; + icmp_stats_table[i].icmpStatsOutErrors = v6icmp.icmp6OutDestUnreachs + + v6icmp.icmp6OutPktTooBigs + v6icmp.icmp6OutTimeExcds + + v6icmp.icmp6OutParmProblems; + break; + } + icmp_stats_table[i].ipVer=i; + } + + return 0; +} + +netsnmp_variable_list * +icmp_stats_next_entry( void **loop_context, + void **data_context, + netsnmp_variable_list *index, + netsnmp_iterator_info *data) +{ + int i = (int)(*loop_context); + netsnmp_variable_list *idx = index; + + if(i > 2) + return NULL; + + + /* + *set IP version + */ + snmp_set_var_typed_value(idx, ASN_INTEGER, (u_char *)&icmp_stats_table[i].ipVer, + sizeof(__uint32_t)); + idx = idx->next_variable; + + + /* + * set icmpStatsInMsgs + */ + snmp_set_var_typed_value(idx, ASN_COUNTER, (u_char *)&icmp_stats_table[i].icmpStatsInMsgs, + sizeof(__uint32_t)); + idx = idx->next_variable; + + /* + * set icmpStatsInErrors + */ + snmp_set_var_typed_value(idx, ASN_COUNTER, (u_char *)&icmp_stats_table[i].icmpStatsInErrors, + sizeof(__uint32_t)); + idx = idx->next_variable; + + /* + * set icmpStatsOutMsgs + */ + snmp_set_var_typed_value(idx, ASN_COUNTER, (u_char *)&icmp_stats_table[i].icmpStatsOutMsgs, + sizeof(__uint32_t)); + idx = idx->next_variable; + + /* + * set icmpStatsOutErrors + */ + snmp_set_var_typed_value(idx, ASN_COUNTER, (u_char *)&icmp_stats_table[i].icmpStatsOutErrors, + sizeof(__uint32_t)); + + *data_context = &icmp_stats_table[i]; + + *loop_context = (void *)(++i); + + return index; +} + + +netsnmp_variable_list * +icmp_stats_first_entry( void **loop_context, + void **data_context, + netsnmp_variable_list *index, + netsnmp_iterator_info *data) +{ + + *loop_context = 0; + *data_context = NULL; + return icmp_stats_next_entry(loop_context, data_context, index, data); +} +#endif + void init_icmp(void) { netsnmp_handler_registration *reginfo; + netsnmp_iterator_info *iinfo; + netsnmp_table_registration_info *table_info; /* * register ourselves with the agent as a group of scalars... @@ -89,6 +213,35 @@ init_icmp(void) icmp_oid, OID_LENGTH(icmp_oid))); #endif +#ifdef linux + reginfo = netsnmp_create_handler_registration("icmpStatsTable", + icmp_stats_table_handler, icmp_stats_tbl_oid, + OID_LENGTH(icmp_stats_tbl_oid), HANDLER_CAN_RONLY); + + table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); + if (!table_info) { + return; + } + + netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, + ASN_COUNTER, + ASN_COUNTER, + ASN_COUNTER, + ASN_COUNTER, 0); + table_info->min_column = 1; + table_info->max_column = 5; + + + iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); + if (!iinfo) { + return; + } + iinfo->get_first_data_point = icmp_stats_first_entry; + iinfo->get_next_data_point = icmp_stats_next_entry; + iinfo->table_reginfo = table_info; + + netsnmp_register_table_iterator(reginfo, iinfo); +#endif #ifdef USING_MIBII_IP_MODULE if (++ip_module_count == 2) REGISTER_SYSOR_TABLE(ip_module_oid, ip_module_oid_len, @@ -551,6 +704,75 @@ icmp_handler(netsnmp_mib_handler } +int +icmp_stats_table_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + netsnmp_request_info *request; + netsnmp_variable_list *requestvb; + netsnmp_table_request_info *table_info; + struct icmp_stats_table_entry *entry; + oid subid; + + switch (reqinfo->mode) { + case MODE_GET: + for (request=requests; request; request=request->next) { + requestvb = request->requestvb; + entry = (struct icmp_stats_table_entry *)netsnmp_extract_iterator_context(request); + if (!entry) + continue; + table_info = netsnmp_extract_table_info(request); + subid = table_info->colnum; + + switch (subid) { + case ICMP_STAT_IPVER: + snmp_set_var_typed_value(requestvb, ASN_INTEGER, + (u_char *)&entry->ipVer, sizeof(__uint32_t)); + break; + case ICMP_STAT_INMSG: + snmp_set_var_typed_value(requestvb, ASN_COUNTER, + (u_char *)&entry->icmpStatsInMsgs, sizeof(__uint32_t)); + break; + case ICMP_STAT_INERR: + snmp_set_var_typed_value(requestvb, ASN_COUNTER, + (u_char *)&entry->icmpStatsInErrors, sizeof(__uint32_t)); + break; + case ICMP_STAT_OUTMSG: + snmp_set_var_typed_value(requestvb, ASN_COUNTER, + (u_char *)&entry->icmpStatsOutMsgs, sizeof(__uint32_t)); + break; + case ICMP_STAT_OUTERR: + snmp_set_var_typed_value(requestvb, ASN_COUNTER, + (u_char *)&entry->icmpStatsOutErrors, sizeof(__uint32_t)); + break; + default: + snmp_log(LOG_WARNING, "mibII/icmpStatsTable: Unrecognised column (%d)\n",(int)subid); + } + } + break; + case MODE_GETNEXT: + case MODE_GETBULK: + case MODE_SET_RESERVE1: + case MODE_SET_RESERVE2: + case MODE_SET_ACTION: + case MODE_SET_COMMIT: + case MODE_SET_FREE: + case MODE_SET_UNDO: + snmp_log(LOG_WARNING, "mibII/icmpStatsTable: Unsupported mode (%d)\n", + reqinfo->mode); + break; + default: + snmp_log(LOG_WARNING, "mibII/icmpStatsTable: Unrecognised mode (%d)\n", + reqinfo->mode); + break; + + } + + return SNMP_ERR_NOERROR; +} + /********************* * * Internal implementation functions @@ -680,6 +902,7 @@ icmp_load(netsnmp_cache *cache, void *vm } else { DEBUGMSGTL(("mibII/icmp", "Loaded ICMP Group (linux)\n")); } + icmp_stats_load(cache, vmagic); return ret_value; } #elif defined(solaris2) --- agent/mibgroup/mibII/icmp.h.icmp6 2007-04-11 12:00:25.000000000 -0400 +++ agent/mibgroup/mibII/icmp.h 2007-04-17 11:23:57.000000000 -0400 @@ -12,6 +12,7 @@ config_arch_require(linux, mibII/kernel_ extern void init_icmp(void); extern Netsnmp_Node_Handler icmp_handler; +extern Netsnmp_Node_Handler icmp_stats_table_handler; extern NetsnmpCacheLoad icmp_load; extern NetsnmpCacheFree icmp_free; @@ -42,4 +43,10 @@ extern NetsnmpCacheFree icmp_free; #define ICMPOUTADDRMASKS 25 #define ICMPOUTADDRMASKREPS 26 +#define ICMPSTATSTABLE 29 +#define ICMP_STAT_IPVER 1 +#define ICMP_STAT_INMSG 2 +#define ICMP_STAT_INERR 3 +#define ICMP_STAT_OUTMSG 4 +#define ICMP_STAT_OUTERR 5 #endif /* _MIBGROUP_ICMP_H */