net-snmp/agent/mibgroup/mibII/ipv6.c

2639 lines
82 KiB
C

/*
* IP MIB group implementation - ipv6.c
*
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#include <sys/types.h>
#include <sys/socket.h>
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
#define _KERNEL 1
#define _I_DEFINED_KERNEL
#endif
#if NETSNMP_IFNET_NEEDS_KERNEL_STRUCTURES
#define _KERNEL_STRUCTURES
#endif
#include <sys/param.h>
#if defined(freebsd3) || defined(darwin)
# if HAVE_SYS_SOCKETVAR_H
# include <sys/socketvar.h>
# endif
#endif
#if STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#else
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if HAVE_SYS_SYSCTL_H
#ifdef _I_DEFINED_KERNEL
#undef _KERNEL
#endif
#include <sys/sysctl.h>
#ifdef _I_DEFINED_KERNEL
#define _KERNEL 1
#endif
#endif
#if HAVE_SYS_SYSMP_H
#include <sys/sysmp.h>
#endif
#if HAVE_SYS_TCPIPSTATS_H
#include <sys/tcpipstats.h>
#endif
#ifdef _I_DEFINED_KERNEL
#undef _KERNEL
#endif
#include <net/if.h>
#ifdef _I_DEFINED_KERNEL
#define _KERNEL 1
#endif
#if HAVE_NET_IF_VAR_H
#include <net/if_var.h>
#endif
#if HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif
#ifdef HAVE_NET_IF_MIB_H
#include <net/if_mib.h>
#endif
#ifdef _I_DEFINED_KERNEL
#undef _KERNEL
#endif
#include <netinet/in_systm.h>
#if HAVE_SYS_HASHING_H
#include <sys/hashing.h>
#endif
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#if HAVE_NETINET6_IN6_VAR_H
#include <netinet6/in6_var.h>
#endif
#include <netinet/ip6.h>
#if HAVE_NETINET_IP_VAR_H
# include <netinet/ip_var.h>
#endif
#if HAVE_NETINET6_IP6_VAR_H
# include <sys/queue.h>
# include <netinet6/ip6_var.h>
#endif
#include <net/route.h>
#if defined(freebsd3) || defined(darwin) || defined(openbsd4)
# if HAVE_NETINET_IP_H
# include <netinet/ip.h>
# endif
# if HAVE_NETINET_IN_PCB_H
# include <netinet/in_pcb.h>
# endif
#endif
#if HAVE_NETINET6_IN6_PCB_H
# include <netinet6/in6_pcb.h>
#endif
#if HAVE_NETINET6_TCP6_H
# define TCP6
#endif
#ifndef TCP6
# if HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
# endif
# if HAVE_NETINET_TCP_TIMER_H
# include <netinet/tcp_timer.h>
# endif
# if HAVE_NETINET_TCP_VAR_H
# include <netinet/tcp_var.h>
# endif
# if HAVE_NETINET_TCP_FSM_H
# include <netinet/tcp_fsm.h>
# endif
#endif
#if HAVE_NETINET6_TCP6_H
# include <netinet6/tcp6.h>
#endif
#if HAVE_NETINET6_TCP6_TIMER_H
#include <netinet6/tcp6_timer.h>
#endif
#if HAVE_NETINET6_TCP6_VAR_H
#include <netinet6/tcp6_var.h>
#endif
#if HAVE_NETINET6_TCP6_FSM_H
#include <netinet6/tcp6_fsm.h>
#endif
#if HAVE_INET_MIB2_H
#include <inet/mib2.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#if HAVE_KVM_GETFILES
#if defined(HAVE_KVM_GETFILE2) || !defined(openbsd5)
#undef HAVE_KVM_GETFILES
#endif
#endif
#if HAVE_KVM_GETFILES
#include <kvm.h>
#include <sys/sysctl.h>
#define _KERNEL
#include <sys/file.h>
#undef _KERNEL
#endif
#ifdef MIB_IPCOUNTER_SYMBOL
#include <sys/mib.h>
#include <netinet/mib_kern.h>
#endif /* MIB_IPCOUNTER_SYMBOL */
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/auto_nlist.h>
#include "kernel.h"
#include "ipv6.h"
#include "interfaces.h"
netsnmp_feature_require(linux_read_ip6_stat)
#if defined(netbsd1) && !defined(openbsd4)
#define inp_lport in6p_lport
#define inp_fport in6p_fport
#define inp_ppcb in6p_ppcb
#endif
static int header_ipv6
(register struct variable *, oid *, size_t *, int, size_t *,
WriteMethod **);
static int header_ipv6_scan
(register struct variable *, oid *, size_t *, int, size_t *,
WriteMethod **, int, int);
static int if_initialize (void);
static int if_maxifindex (void);
static char *if_getname (int);
#ifdef notused
static int if_getindex (const char *);
#endif
struct variable3 ipv6_variables[] = {
{IPV6FORWARDING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6, 1, {1}},
{IPV6DEFAULTHOPLIMIT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6, 1, {2}},
{IPV6INTERFACES, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
var_ipv6, 1, {3}},
{IPV6IFTBLLASTCHG, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY,
var_ipv6, 1, {4}},
{IPV6IFDESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 2}},
{IPV6IFLOWLAYER, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 3}},
{IPV6IFEFFECTMTU, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 4}},
{IPV6IFREASMMAXSIZE, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 5}},
{IPV6IFTOKEN, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 6}},
{IPV6IFTOKENLEN, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 7}},
{IPV6IFPHYSADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 8}},
{IPV6IFADMSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 9}},
{IPV6IFOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 10}},
{IPV6IFLASTCHANGE, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {5, 1, 11}},
{IPV6IFSTATSINRCVS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 1}},
{IPV6IFSTATSINHDRERRS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 2}},
{IPV6IFSTATSTOOBIGERRS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 3}},
{IPV6IFSTATSINNOROUTES, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 4}},
{IPV6IFSTATSINADDRERRS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 5}},
{IPV6IFSTATSINUNKNOWPROTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 6}},
{IPV6IFSTATSINTRUNCATPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 7}},
{IPV6IFSTATSINDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 8}},
{IPV6IFSTATSINDELIVERS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 9}},
{IPV6IFSTATSOUTFORWDATAS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 10}},
{IPV6IFSTATSOUTREQS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 11}},
{IPV6IFSTATSOUTDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 12}},
{IPV6IFSTATSOUTFRAGOKS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 13}},
{IPV6IFSTATSOUTFRAGFAILS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 14}},
{IPV6IFSTATSOUTFRAGCREATS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 15}},
{IPV6IFSTATSOUTREASMREQS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 16}},
{IPV6IFSTATSOUTREASMOKS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 17}},
{IPV6IFSTATSOUTREASMFAILS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 18}},
{IPV6IFSTATSINMCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 19}},
{IPV6IFSTATSOUTMCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_ifv6Entry, 3, {6, 1, 20}},
#if 0
{IPV6ADDRPREFIXONLINKFLG, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {7, 1, 3}},
{IPV6ADDRPREFIXAUTONOMOUSFLAG, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {7, 1, 4}},
{IPV6ADDRPREFIXADVPREFERLIFE, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {7, 1, 5}},
{IPV6ADDRPREFIXVALIDLIFE, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {7, 1, 6}},
{IPV6ADDRPFXLEN, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {8, 1, 2}},
{IPV6ADDRTYPE, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {8, 1, 3}},
{IPV6ADDRANYCASTFLAG, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {8, 1, 4}},
{IPV6ADDRSTATUS, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6AddrEntry, 3, {8, 1, 5}},
{IPV6ROUTEIFINDEX, IpV6IFINDEX, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 4}},
{IPV6ROUTENEXTHOP, IpV6ADDRESS, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 5}},
{IPV6ROUTETYPE, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 6}},
{IPV6ROUTEPROTOCOL, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 7}},
{IPV6ROUTEPOLICY, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 8}},
{IPV6ROUTEAGE, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 9}},
{IPV6ROUTENEXTHOPRDI, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 10}},
{IPV6ROUTEMETRIC, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 11}},
{IPV6ROUTEWEIGHT, UNSIGNED32, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 12}},
{IPV6ROUTEINFO, OBJID, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 13}},
{IPV6ROUTEVALID, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ipv6RouteEntry, 3, {11, 1, 14}},
{IPV6NETTOMEDIAPHYADDR, STRING, NETSNMP_OLDAPI_RONLY,
var_ndpEntry, 3, {12, 1, 2}},
{IPV6NETTOMEDIATYPE, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ndpEntry, 3, {12, 1, 3}},
{IPV6NETTOMEDIASTATE, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ndpEntry, 3, {12, 1, 4}},
{IPV6NETTOMEDIALASTUPDATE, TIMETICKS, NETSNMP_OLDAPI_RONLY,
var_ndpEntry, 3, {12, 1, 5}},
{IPV6NETTOMEDIAVALID, INTEGER, NETSNMP_OLDAPI_RONLY,
var_ndpEntry, 3, {12, 1, 6}},
#endif
};
oid ipv6_variables_oid[] = { SNMP_OID_MIB2, 55, 1 };
#if 0
config_load_mib(MIB .55 .1, 8, ipv6_variables)
config_add_mib(IPV6 - TC)
config_add_mib(IPV6 - MIB)
#endif
struct variable3 ipv6icmp_variables[] = {
{IPV6IFICMPINMSG, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 1}},
{IPV6IFICMPINERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 2}},
{IPV6IFICMPINDSTUNRCHS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 3}},
{IPV6IFICMPINADMPROHS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 4}},
{IPV6IFICMPINTIMEXCDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 5}},
{IPV6IFICMPINPARMPROBS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 6}},
{IPV6IFICMPINPKTTOOBIGS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 7}},
{IPV6IFICMPINECHOS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 8}},
{IPV6IFICMPINECHOREPS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 9}},
{IPV6IFICMPINRTRSLICITS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 10}},
{IPV6IFICMPINRTRADVS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 11}},
{IPV6IFICMPINNBRSLICITS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 12}},
{IPV6IFICMPINNBRADVS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 13}},
{IPV6IFICMPINREDIRECTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 14}},
{IPV6IFICMPINGRPMEQERYS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 15}},
{IPV6IFICMPINGRPMERSPS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 16}},
{IPV6IFICMPINGRPMEREDCS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 17}},
{IPV6IFICMPOUTMSG, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 18}},
{IPV6IFICMPOUTERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 19}},
{IPV6IFICMPOUTDSTUNRCHS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 20}},
{IPV6IFICMPOUTADMPROHS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 21}},
{IPV6IFICMPOUTTIMEXCDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 22}},
{IPV6IFICMPOUTPARMPROBS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 23}},
{IPV6IFICMPOUTPKTTOOBIGS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 24}},
{IPV6IFICMPOUTECHOS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 25}},
{IPV6IFICMPOUTECHOREPS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 26}},
{IPV6IFICMPOUTRTRSLICITS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 27}},
{IPV6IFICMPOUTRTRADVS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 28}},
{IPV6IFICMPOUTNBRSLICITS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 29}},
{IPV6IFICMPOUTNBRADVS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 30}},
{IPV6IFICMPOUTREDIRECTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 31}},
{IPV6IFICMPOUTGRPMEQERYS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 32}},
{IPV6IFICMPOUTGRPMERSPS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 33}},
{IPV6IFICMPOUTGRPMEREDCS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_icmpv6Entry, 3, {1, 1, 34}}
};
oid ipv6icmp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 56, 1 };
#if 0
config_load_mib(MIB .56 .1, 8, ipv6icmp_variables)
config_add_mib(IPV6 - ICMP - MIB)
#endif
struct variable2 ipv6udp_variables[] = {
{IPV6UDPIFINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_udp6, 2, {1, 3}}
};
oid ipv6udp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 7, 6 };
#if 0
config_load_mib(1.3 .6 .1 .3 .87 .1, 7, ipv6udp_variables)
config_add_mib(IPV6 - UDP - MIB)
#endif
struct variable2 ipv6tcp_variables[] = {
{IPV6TCPCONNSTATE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_tcp6, 2, {1, 6}},
};
oid ipv6tcp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 6, 16 };
#if 0
config_load_mib(1.3 .6 .1 .3 .86 .1, 7, ipv6tcp_variables)
config_add_mib(IPV6 - TCP - MIB)
#endif
void
init_ipv6(void)
{
/*
* register ourselves with the agent to handle our mib tree
*/
REGISTER_MIB("mibII/ipv6", ipv6_variables, variable3,
ipv6_variables_oid);
REGISTER_MIB("mibII/icmpv6", ipv6icmp_variables, variable3,
ipv6icmp_variables_oid);
REGISTER_MIB("mibII/ipv6udp", ipv6udp_variables, variable2,
ipv6udp_variables_oid);
REGISTER_MIB("mibII/ipv6tcp", ipv6tcp_variables, variable2,
ipv6tcp_variables_oid);
}
static int
header_ipv6(register struct variable *vp,
/*
* IN - pointer to variable entry that points here
*/
oid * name, /* IN/OUT - input name requested, output name found */
size_t * length, /* IN/OUT - length of input and output oid's */
int exact, /* IN - TRUE if an exact match was requested */
size_t * var_len, /* OUT - length of variable or 0 if function returned */
WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
int result;
DEBUGMSGTL(("mibII/ipv6", "header_ipv6: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
newname[(int) vp->namelen] = 0;
result =
snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
if ((exact && (result != 0)) || (!exact && (result >= 0)))
return (MATCH_FAILED);
memcpy((char *) name, (char *) newname,
((int) vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
*write_method = (WriteMethod*)0;
*var_len = sizeof(long); /* default to 'long' results */
return (MATCH_SUCCEEDED);
}
static int
header_ipv6_scan(register struct variable *vp,
/*
* IN - pointer to variable entry that points here
*/
oid * name, /* IN/OUT - input name requested, output name found */
size_t * length, /* IN/OUT - length of input and output oid's */
int exact, /* IN - TRUE if an exact match was requested */
size_t * var_len, /* OUT - length of variable or 0 if function returned */
WriteMethod ** write_method, int from, int to)
{
oid newname[MAX_OID_LEN];
int result;
int i;
DEBUGMSGTL(("mibII/ipv6", "header_ipv6_scan: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
for (i = from; i <= to; i++) {
newname[(int) vp->namelen] = i;
result =
snmp_oid_compare(name, *length, newname,
(int) vp->namelen + 1);
if (((exact && result == 0) || (!exact && result < 0))
&& if_getname(i))
break;
}
if (to < i)
return (MATCH_FAILED);
memcpy((char *) name, (char *) newname,
((int) vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
*write_method = (WriteMethod*)0;
*var_len = sizeof(long); /* default to 'long' results */
return (MATCH_SUCCEEDED);
}
static struct if_nameindex *ifnames = NULL;
#ifdef linux
static void linux_if_freenameindex(struct if_nameindex *);
static struct if_nameindex *linux_if_nameindex(void);
#endif
static int
if_initialize(void)
{
#ifndef HAVE_IF_NAMEINDEX
return -1;
#else
#ifndef linux
if (ifnames)
if_freenameindex(ifnames);
ifnames = if_nameindex();
#else
if (ifnames)
linux_if_freenameindex(ifnames);
ifnames = linux_if_nameindex();
#endif
if (!ifnames) {
ERROR_MSG("if_nameindex() failed");
return -1;
}
return 0;
#endif
}
static int
if_maxifindex(void)
{
#ifndef HAVE_IF_NAMEINDEX
return -1;
#else
struct if_nameindex *p;
int max = 0;
if (!ifnames) {
if (if_initialize() < 0)
return -1;
}
for (p = ifnames; p && p->if_index; p++) {
if (max < p->if_index)
max = p->if_index;
}
return max;
#endif
}
static int
if_countifindex(void)
{
#ifndef HAVE_IF_NAMEINDEX
return -1;
#else
struct if_nameindex *p;
int count = 0;
if (!ifnames) {
if (if_initialize() < 0)
return -1;
}
for (p = ifnames; p && p->if_index; p++) {
count++;
}
return count;
#endif
}
static char *
if_getname(int idx)
{
#ifndef HAVE_IF_NAMEINDEX
return NULL;
#else
struct if_nameindex *p;
if (!ifnames) {
if (if_initialize() < 0)
return NULL;
}
for (p = ifnames; p && p->if_index; p++) {
if (p->if_index == idx)
return p->if_name;
}
return NULL;
#endif
}
#ifdef notused
static int
if_getindex(const char *name)
{
#ifndef HAVE_IF_NAMEINDEX
return -1;
#else
struct if_nameindex *p;
if (!ifnames) {
if (if_initialize() < 0)
return -1;
}
for (p = ifnames; p && p->if_index; p++) {
if (strcmp(name, p->if_name) == 0)
return p->if_index;
}
return -1;
#endif
}
#endif /* notused */
/*------------------------------------------------------------*/
#ifndef linux
#ifdef __OpenBSD__
/*
* It is not possible to use struct ifnet anymore on OpenBSD, get
* interface flags and L2 address through getifaddrs(3).
*/
#include <ifaddrs.h>
static int
if_getifflags(int ifindex, int *ifflags)
{
const char *ifname;
struct ifaddrs *ifa0, *ifa;
int ret = -1;
ifname = if_getname(ifindex);
if (ifname == NULL)
return ret;
if (getifaddrs(&ifa0) != -1) {
for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
if (strcmp(ifa->ifa_name, ifname) == 0) {
*ifflags = ifa->ifa_flags;
ret = 0;
break;
}
}
freeifaddrs(ifa0);
}
return ret;
}
#else
/*
* KAME dependent part
*/
static int
if_getifnet(int idx, struct ifnet *result)
{
caddr_t q;
struct ifnet tmp;
if (!auto_nlist("ifnet", (char *) &q, sizeof(q)))
return -1;
while (q) {
if (!NETSNMP_KLOOKUP(q, (char *) &tmp, sizeof(tmp))) {
DEBUGMSGTL(("mibII/ipv6:if_getifnet", "klookup failed\n"));
return -1;
}
if (idx == tmp.if_index) {
memcpy(result, &tmp, sizeof(tmp));
return 0;
}
#if defined(freebsd3) || defined(darwin)
q = (caddr_t) TAILQ_NEXT(&tmp, if_link);
#else
# if defined(__NetBSD__) || defined(__OpenBSD__)
q = (caddr_t) TAILQ_NEXT(&tmp, if_list);
# else
q = (caddr_t) tmp.if_next;
# endif
#endif
}
return -1;
}
#endif /* !__OpenBSD__ */
#if TRUST_IFLASTCHANGE /*untrustable value returned... */
#ifdef HAVE_NET_IF_MIB_H
#if defined(HAVE_SYS_SYSCTL_H) && defined(CTL_NET)
static int
if_getifmibdata(int idx, struct ifmibdata *result)
{
int mib[6] = {
CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL
};
size_t len;
struct ifmibdata tmp;
mib[4] = idx;
len = sizeof(struct ifmibdata);
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &tmp, &len, 0, 0) < 0)
return -1;
memcpy(result, &tmp, sizeof(tmp));
return 0;
}
#endif
#endif /*HAVE_NET_IF_MIB_H */
#endif /* TRUST_IFLASTCHANGE */
#ifdef __KAME__
#define IPV6_FORWARDING_SYMBOL "ip6_forwarding"
#define IPV6_DEFHLIM_SYMBOL "ip6_defhlim"
#endif
u_char *
var_ipv6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
int i;
if (header_ipv6(vp, name, length, exact, var_len, write_method)
== MATCH_FAILED) {
return NULL;
}
#if defined(HAVE_SYS_SYSCTL_H) && defined(CTL_NET)
/*
* try with sysctl routines
*/
{
int name[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
const char *namestr = NULL;
int result;
size_t resultsiz;
resultsiz = sizeof(result);
switch (vp->magic) {
case IPV6FORWARDING:
name[3] = IPV6CTL_FORWARDING;
namestr = "IPV6CTL_FORWARDING";
if (sysctl
(name, sizeof(name) / sizeof(name[0]), &result, &resultsiz,
0, 0) < 0) {
DEBUGMSGTL(("mibII/ipv6",
"sysctl(CTL_NET, PF_INET6, IPPROTO_IPV6, %s)\n",
namestr));
break;
} else {
if (result)
long_return = 1; /* GATEWAY */
else
long_return = 2; /* HOST */
return (u_char *) & long_return;
}
break;
case IPV6DEFAULTHOPLIMIT:
name[3] = IPV6CTL_DEFHLIM;
namestr = "IPV6CTL_DEFHLIM";
if (sysctl
(name, sizeof(name) / sizeof(name[0]), &result, &resultsiz,
0, 0) < 0) {
DEBUGMSGTL(("mibII/ipv6",
"sysctl(CTL_NET, PF_INET6, IPPROTO_IPV6, %s)\n",
namestr));
break;
} else {
long_return = result;
return (u_char *) & long_return;
}
}
}
#endif /* not (HAVE_SYS_SYSCTL_H && CTL_NET) */
/*
* try looking into the kernel variable
*/
switch (vp->magic) {
#ifdef IPV6_FORWARDING_SYMBOL
case IPV6FORWARDING:
if (auto_nlist(IPV6_FORWARDING_SYMBOL, (char *) &i, sizeof(i))) {
if (i)
long_return = 1;
/*GATEWAY*/
else
long_return = 2;
/*HOST*/ return (u_char *) & long_return;
}
break;
#endif
#ifdef IPV6_DEFHLIM_SYMBOL
case IPV6DEFAULTHOPLIMIT:
if (auto_nlist(IPV6_DEFHLIM_SYMBOL, (char *) &i, sizeof(i))) {
long_return = i;
return (u_char *) & long_return;
}
break;
#endif
case IPV6INTERFACES:
#ifdef HAVE_IF_NAMEINDEX
/*
* not really the right answer... we must count IPv6 capable
* interfaces only.
*/
long_return = if_countifindex();
if (long_return < 0)
break;
return (u_char *) & long_return;
#endif
break;
#if 0
case IPV6IFTBLLASTCHG:
long_return = 0;
/*XXX*/ return (u_char *) & long_return;
#endif
default:
break;
}
ERROR_MSG("");
return NULL;
}
u_char *
var_ifv6Entry(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
#ifndef HAVE_IF_NAMEINDEX
return NULL;
#else
int interface;
int max;
char *p;
/* Reload list of interfaces */
if (if_initialize() < 0)
return NULL;
max = if_maxifindex();
if (max < 0)
return NULL;
if (header_ipv6_scan
(vp, name, length, exact, var_len, write_method, 1, max)
== MATCH_FAILED) {
return NULL;
}
interface = name[*length - 1];
DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)\n",
interface, if_getname(interface)));
if (interface > max)
return NULL;
switch (vp->magic) {
case IPV6IFDESCR:
p = if_getname(interface);
if (p) {
*var_len = strlen(p);
return p;
}
break;
case IPV6IFLOWLAYER:
/*
* should check if type, this is a hard one...
*/
*var_len = nullOidLen;
return (u_char *) nullOid;
case IPV6IFEFFECTMTU:
{
#if defined(SIOCGIFMTU) && !defined(__OpenBSD__)
struct ifreq ifr;
int s;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET6;
strlcpy(ifr.ifr_name, if_getname(interface), sizeof(ifr.ifr_name));
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0) {
close(s);
break;
}
long_return = ifr.ifr_mtu;
close(s);
return (u_char *) & long_return;
#else
break;
#endif
}
#if 0 /*not yet */
case IPV6IFREASMMAXSIZE:
/*
* I dunno what the spec means for this MIB
*/
case IPV6IFTOKEN:
case IPV6IFTOKENLEN:
#endif
case IPV6IFPHYSADDRESS:
{
#ifdef __OpenBSD__
struct ifaddrs *ifa0, *ifa;
static struct sockaddr_dl sdl;
char ifnam[IF_NAMESIZE];
if (if_indextoname(interface, ifnam) == NULL) {
*var_len = 0;
return NULL;
}
if (getifaddrs(&ifa0) != -1) {
for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
if (strcmp(ifnam, ifa->ifa_name) != 0)
continue;
if (ifa->ifa_addr == NULL)
continue;
memcpy(&sdl, ifa->ifa_addr, sizeof(sdl));
if (sdl.sdl_family != AF_LINK)
continue;
freeifaddrs(ifa0);
*var_len = sdl.sdl_alen;
return (u_char *) (sdl.sdl_data + sdl.sdl_nlen);
}
}
freeifaddrs(ifa0);
return NULL;
#else
struct ifnet ifnet;
struct ifaddr ifaddr;
#if defined(__DragonFly__) && __DragonFly_version >= 197700
struct ifaddr_container ifac;
struct ifaddrhead head;
#endif
static struct sockaddr_dl sdl;
caddr_t ifa;
if (if_getifnet(interface, &ifnet) < 0)
break;
#if defined(freebsd3) || defined(darwin)
# if defined(__DragonFly__) && __DragonFly_version >= 197700
/*
* Locate ifaddr head on CPU0
*/
if (!NETSNMP_KLOOKUP(ifnet.if_addrheads, (char *)&head, sizeof(head))) {
DEBUGMSGTL(("mibII/ipv6:var_ipv6", "klookup head failed\n"));
break;
}
if (TAILQ_FIRST(&head) != NULL) {
if (!NETSNMP_KLOOKUP(TAILQ_FIRST(&head), (char *) &ifac, sizeof(ifac))) {
DEBUGMSGTL(("mibII/ipv6:var_ipv6", "klookup ifac failed\n"));
break;
}
ifa = (caddr_t)ifac.ifa;
} else {
ifa = NULL;
}
# else
ifa = (caddr_t) TAILQ_FIRST(&ifnet.if_addrhead);
# endif
#else
# if defined(__NetBSD__) || defined(__OpenBSD__)
ifa = (caddr_t) TAILQ_FIRST(&ifnet.if_addrlist);
# else
ifa = (caddr_t) ifnet.if_addrlist;
# endif
#endif
while (ifa) {
if (!NETSNMP_KLOOKUP(ifa, (char *) &ifaddr, sizeof(ifaddr))) {
DEBUGMSGTL(("mibII/ipv6:var_ipv6", "klookup failed\n"));
break;
}
if (!NETSNMP_KLOOKUP(ifaddr.ifa_addr,
(char *) &sdl, sizeof(sdl))) {
DEBUGMSGTL(("mibII/ipv6:var_ipv6", "klookup failed\n"));
break;
}
if (sdl.sdl_family == AF_LINK) {
if (sizeof(sdl.sdl_data) < sdl.sdl_nlen + sdl.sdl_alen) {
ERROR_MSG("sdl_alen too long for interface\n");
break;
}
*var_len = sdl.sdl_alen;
return (u_char *) (sdl.sdl_data + sdl.sdl_nlen);
}
#if defined(freebsd3) || defined(darwin)
# if defined(__DragonFly__) && __DragonFly_version >= 197700
if (TAILQ_NEXT(&ifac, ifa_link) == NULL) {
ifa = NULL;
} else {
if (!NETSNMP_KLOOKUP(TAILQ_NEXT(&ifac, ifa_link), (char *)&ifac, sizeof(ifac))) {
DEBUGMSGTL(("mibII/ipv6:var_ipv6", "klookup ifac next failed\n"));
break;
}
ifa = (caddr_t)ifac.ifa;
}
# else
ifa = (caddr_t) TAILQ_NEXT(&ifaddr, ifa_link);
# endif
#else
# if defined(__NetBSD__) || defined(__OpenBSD__)
ifa = (caddr_t) TAILQ_NEXT(&ifaddr, ifa_list);
# else
ifa = (caddr_t) ifaddr.ifa_next;
# endif
#endif
}
/*
* no physical address found
*/
*var_len = 0;
return NULL;
#endif /* !__OpenBSD__ */
}
case IPV6IFADMSTATUS:
{
#ifdef __OpenBSD__
int if_flags;
if (if_getifflags(interface, &if_flags) < 0)
break;
long_return = (if_flags & IFF_RUNNING) ? 1 : 2;
#else
struct ifnet ifnet;
if (if_getifnet(interface, &ifnet) < 0)
break;
long_return = (ifnet.if_flags & IFF_RUNNING) ? 1 : 2;
#endif
return (u_char *) & long_return;
}
case IPV6IFOPERSTATUS:
{
#ifdef __OpenBSD__
int if_flags;
if (if_getifflags(interface, &if_flags) < 0)
break;
long_return = (if_flags & IFF_UP) ? 1 : 2;
#else
struct ifnet ifnet;
if (if_getifnet(interface, &ifnet) < 0)
break;
long_return = (ifnet.if_flags & IFF_UP) ? 1 : 2;
#endif
return (u_char *) & long_return;
}
#if TRUST_IFLASTCHANGE /*untrustable value returned... */
case IPV6IFLASTCHANGE:
{
struct timeval lastchange;
struct timeval now;
int gotanswer;
gotanswer = 0;
lastchange.tv_sec = lastchange.tv_usec = 0;
#ifdef HAVE_NET_IF_MIB_H
if (!gotanswer) {
struct ifmibdata ifmd;
if (if_getifmibdata(interface, &ifmd) < 0);
else {
lastchange = ifmd.ifmd_data.ifi_lastchange;
gotanswer++;
}
}
#endif
#ifdef HAVE_STRUCT_IFNET_IF_LASTCHANGE_TV_SEC
if (!gotanswer) {
struct ifnet ifnet;
if (if_getifnet(interface, &ifnet) < 0);
else {
lastchange = ifnet.if_lastchange;
gotanswer++;
}
}
#endif
DEBUGMSGTL(("mibII/ipv6", "lastchange = { %d.%06d }\n",
lastchange.tv_sec, lastchange.tv_usec));
if (lastchange.tv_sec == 0 && lastchange.tv_usec == 0)
long_return = 0;
else {
gettimeofday(&now, (struct timezone *) NULL);
long_return =
(u_long) ((now.tv_sec - lastchange.tv_sec) * 100);
long_return +=
(u_long) ((now.tv_usec - lastchange.tv_usec) / 10000);
}
return (u_char *) & long_return;
}
#endif /* TRUST_IFLASTCHANGE */
#ifdef SIOCGIFSTAT_IN6
case IPV6IFSTATSINRCVS:
case IPV6IFSTATSINHDRERRS:
case IPV6IFSTATSTOOBIGERRS:
case IPV6IFSTATSINNOROUTES:
case IPV6IFSTATSINADDRERRS:
case IPV6IFSTATSINUNKNOWPROTS:
case IPV6IFSTATSINTRUNCATPKTS:
case IPV6IFSTATSINDISCARDS:
case IPV6IFSTATSINDELIVERS:
case IPV6IFSTATSOUTFORWDATAS:
case IPV6IFSTATSOUTREQS:
case IPV6IFSTATSOUTDISCARDS:
case IPV6IFSTATSOUTFRAGOKS:
case IPV6IFSTATSOUTFRAGFAILS:
case IPV6IFSTATSOUTFRAGCREATS:
case IPV6IFSTATSOUTREASMREQS:
case IPV6IFSTATSOUTREASMOKS:
case IPV6IFSTATSOUTREASMFAILS:
case IPV6IFSTATSINMCASTPKTS:
case IPV6IFSTATSOUTMCASTPKTS:
{
struct in6_ifstat *ifs6;
struct in6_ifreq ifr;
int s;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, if_getname(interface), sizeof(ifr.ifr_name));
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFSTAT_IN6, (caddr_t) & ifr) < 0) {
close(s);
break;
}
close(s);
ifs6 = &ifr.ifr_ifru.ifru_stat;
switch (vp->magic) {
case IPV6IFSTATSINRCVS:
long_return = ifs6->ifs6_in_receive;
break;
case IPV6IFSTATSINHDRERRS:
long_return = ifs6->ifs6_in_hdrerr;
break;
case IPV6IFSTATSTOOBIGERRS:
long_return = ifs6->ifs6_in_toobig;
break;
case IPV6IFSTATSINNOROUTES:
long_return = ifs6->ifs6_in_noroute;
break;
case IPV6IFSTATSINADDRERRS:
long_return = ifs6->ifs6_in_addrerr;
break;
case IPV6IFSTATSINUNKNOWPROTS:
long_return = ifs6->ifs6_in_protounknown;
break;
case IPV6IFSTATSINTRUNCATPKTS:
long_return = ifs6->ifs6_in_truncated;
break;
case IPV6IFSTATSINDISCARDS:
long_return = ifs6->ifs6_in_discard;
break;
case IPV6IFSTATSINDELIVERS:
long_return = ifs6->ifs6_in_deliver;
break;
case IPV6IFSTATSOUTFORWDATAS:
long_return = ifs6->ifs6_out_forward;
break;
case IPV6IFSTATSOUTREQS:
long_return = ifs6->ifs6_out_request;
break;
case IPV6IFSTATSOUTDISCARDS:
long_return = ifs6->ifs6_out_discard;
break;
case IPV6IFSTATSOUTFRAGOKS:
long_return = ifs6->ifs6_out_fragok;
break;
case IPV6IFSTATSOUTFRAGFAILS:
long_return = ifs6->ifs6_out_fragfail;
break;
case IPV6IFSTATSOUTFRAGCREATS:
long_return = ifs6->ifs6_out_fragcreat;
break;
case IPV6IFSTATSOUTREASMREQS:
long_return = ifs6->ifs6_reass_reqd;
break;
case IPV6IFSTATSOUTREASMOKS:
long_return = ifs6->ifs6_reass_ok;
break;
case IPV6IFSTATSOUTREASMFAILS:
long_return = ifs6->ifs6_reass_fail;
break;
case IPV6IFSTATSINMCASTPKTS:
long_return = ifs6->ifs6_in_mcast;
break;
case IPV6IFSTATSOUTMCASTPKTS:
long_return = ifs6->ifs6_out_mcast;
break;
default:
return NULL;
}
return (u_char *) & long_return;
}
#endif
default:
break;
}
return NULL;
#endif
}
u_char *
var_icmpv6Entry(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
#ifndef HAVE_IF_NAMEINDEX
return NULL;
#else
int interface;
int max;
/* Reload list of interfaces */
if (if_initialize() < 0)
return NULL;
max = if_maxifindex();
if (max < 0)
return NULL;
if (header_ipv6_scan
(vp, name, length, exact, var_len, write_method, 1, max)
== MATCH_FAILED) {
return NULL;
}
interface = name[*length - 1];
DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)\n",
interface, if_getname(interface)));
if (interface >= max)
return NULL;
switch (vp->magic) {
#ifdef SIOCGIFSTAT_ICMP6
case IPV6IFICMPINMSG:
case IPV6IFICMPINERRORS:
case IPV6IFICMPINDSTUNRCHS:
case IPV6IFICMPINADMPROHS:
case IPV6IFICMPINTIMEXCDS:
case IPV6IFICMPINPARMPROBS:
case IPV6IFICMPINPKTTOOBIGS:
case IPV6IFICMPINECHOS:
case IPV6IFICMPINECHOREPS:
case IPV6IFICMPINRTRSLICITS:
case IPV6IFICMPINRTRADVS:
case IPV6IFICMPINNBRSLICITS:
case IPV6IFICMPINNBRADVS:
case IPV6IFICMPINREDIRECTS:
case IPV6IFICMPINGRPMEQERYS:
case IPV6IFICMPINGRPMERSPS:
case IPV6IFICMPINGRPMEREDCS:
case IPV6IFICMPOUTMSG:
case IPV6IFICMPOUTERRORS:
case IPV6IFICMPOUTDSTUNRCHS:
case IPV6IFICMPOUTADMPROHS:
case IPV6IFICMPOUTTIMEXCDS:
case IPV6IFICMPOUTPARMPROBS:
case IPV6IFICMPOUTPKTTOOBIGS:
case IPV6IFICMPOUTECHOS:
case IPV6IFICMPOUTECHOREPS:
case IPV6IFICMPOUTRTRSLICITS:
case IPV6IFICMPOUTRTRADVS:
case IPV6IFICMPOUTNBRSLICITS:
case IPV6IFICMPOUTNBRADVS:
case IPV6IFICMPOUTREDIRECTS:
case IPV6IFICMPOUTGRPMEQERYS:
case IPV6IFICMPOUTGRPMERSPS:
case IPV6IFICMPOUTGRPMEREDCS:
{
struct icmp6_ifstat *ifs6;
struct in6_ifreq ifr;
int s;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, if_getname(interface), sizeof(ifr.ifr_name));
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFSTAT_ICMP6, (caddr_t) & ifr) < 0) {
close(s);
break;
}
close(s);
ifs6 = &ifr.ifr_ifru.ifru_icmp6stat;
switch (vp->magic) {
case IPV6IFICMPINMSG:
long_return = ifs6->ifs6_in_msg;
break;
case IPV6IFICMPINERRORS:
long_return = ifs6->ifs6_in_error;
break;
case IPV6IFICMPINDSTUNRCHS:
long_return = ifs6->ifs6_in_dstunreach;
break;
case IPV6IFICMPINADMPROHS:
long_return = ifs6->ifs6_in_adminprohib;
break;
case IPV6IFICMPINTIMEXCDS:
long_return = ifs6->ifs6_in_timeexceed;
break;
case IPV6IFICMPINPARMPROBS:
long_return = ifs6->ifs6_in_paramprob;
break;
case IPV6IFICMPINPKTTOOBIGS:
long_return = ifs6->ifs6_in_pkttoobig;
break;
case IPV6IFICMPINECHOS:
long_return = ifs6->ifs6_in_echo;
break;
case IPV6IFICMPINECHOREPS:
long_return = ifs6->ifs6_in_echoreply;
break;
case IPV6IFICMPINRTRSLICITS:
long_return = ifs6->ifs6_in_routersolicit;
break;
case IPV6IFICMPINRTRADVS:
long_return = ifs6->ifs6_in_routeradvert;
break;
case IPV6IFICMPINNBRSLICITS:
long_return = ifs6->ifs6_in_neighborsolicit;
break;
case IPV6IFICMPINNBRADVS:
long_return = ifs6->ifs6_in_neighboradvert;
break;
case IPV6IFICMPINREDIRECTS:
long_return = ifs6->ifs6_in_redirect;
break;
case IPV6IFICMPINGRPMEQERYS:
long_return = ifs6->ifs6_in_mldquery;
break;
case IPV6IFICMPINGRPMERSPS:
long_return = ifs6->ifs6_in_mldreport;
break;
case IPV6IFICMPINGRPMEREDCS:
long_return = ifs6->ifs6_in_mlddone;
break;
case IPV6IFICMPOUTMSG:
long_return = ifs6->ifs6_out_msg;
break;
case IPV6IFICMPOUTERRORS:
long_return = ifs6->ifs6_out_error;
break;
case IPV6IFICMPOUTDSTUNRCHS:
long_return = ifs6->ifs6_out_dstunreach;
break;
case IPV6IFICMPOUTADMPROHS:
long_return = ifs6->ifs6_out_adminprohib;
break;
case IPV6IFICMPOUTTIMEXCDS:
long_return = ifs6->ifs6_out_timeexceed;
break;
case IPV6IFICMPOUTPARMPROBS:
long_return = ifs6->ifs6_out_paramprob;
break;
case IPV6IFICMPOUTPKTTOOBIGS:
long_return = ifs6->ifs6_out_pkttoobig;
break;
case IPV6IFICMPOUTECHOS:
long_return = ifs6->ifs6_out_echo;
break;
case IPV6IFICMPOUTECHOREPS:
long_return = ifs6->ifs6_out_echoreply;
break;
case IPV6IFICMPOUTRTRSLICITS:
long_return = ifs6->ifs6_out_routersolicit;
break;
case IPV6IFICMPOUTRTRADVS:
long_return = ifs6->ifs6_out_routeradvert;
break;
case IPV6IFICMPOUTNBRSLICITS:
long_return = ifs6->ifs6_out_neighborsolicit;
break;
case IPV6IFICMPOUTNBRADVS:
long_return = ifs6->ifs6_out_neighboradvert;
break;
case IPV6IFICMPOUTREDIRECTS:
long_return = ifs6->ifs6_out_redirect;
break;
case IPV6IFICMPOUTGRPMEQERYS:
long_return = ifs6->ifs6_out_mldquery;
break;
case IPV6IFICMPOUTGRPMERSPS:
long_return = ifs6->ifs6_out_mldreport;
break;
case IPV6IFICMPOUTGRPMEREDCS:
long_return = ifs6->ifs6_out_mlddone;
break;
default:
return NULL;
}
return (u_char *) & long_return;
}
#endif
default:
break;
}
return NULL;
#endif
}
#if HAVE_KVM_GETFILES
u_char *
var_udp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
oid savname[MAX_OID_LEN];
int result, count, found, savnameLen;
int p, i, j;
u_char *sa, *savsa;
struct kinfo_file *udp;
udp = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET, sizeof(struct kinfo_file), &count);
found = savnameLen = 0;
memcpy(newname, vp->name, (int) vp->namelen * sizeof(oid));
for (p = 0; p < count; p++) {
if (udp[p].so_protocol != IPPROTO_UDP || udp[p].so_family != AF_INET6)
continue;
j = vp->namelen;
sa = (u_char *)&udp[p].inp_laddru[0];
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = sa[i];
newname[j++] = ntohs(udp[p].inp_lport);
if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sa))
newname[j++] = ntohs(sa[2]);
else
newname[j++] = 0;
DEBUGMSGTL(("mibII/ipv6", "var_udp6 new: %d %d ",
(int) vp->namelen, j));
DEBUGMSGOID(("mibII/ipv6", newname, j));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
result = snmp_oid_compare(name, *length, newname, j);
if (exact && result == 0) {
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
savsa = sa;
found++;
break;
} else if (!exact && result < 0) {
/*
* take the least greater one
*/
if (savnameLen == 0 || snmp_oid_compare(savname, savnameLen, newname, j) > 0) {
savnameLen = j;
savsa = sa;
memcpy(savname, newname, j * sizeof(oid));
found++;
}
}
}
DEBUGMSGTL(("mibII/ipv6", "found=%d\n", found));
if (!found)
return NULL;
*length = savnameLen;
memcpy((char *) name, (char *) savname, *length * sizeof(oid));
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
/*
* DEBUGMSGTL(("mibII/ipv6", "var_udp6 found: "));
* DEBUGMSGOID(("mibII/ipv6", name, *length));
* DEBUGMSG(("mibII/ipv6", " %d\n", exact));
*/
DEBUGMSGTL(("mibII/ipv6", "magic=%d\n", vp->magic));
switch (vp->magic) {
case IPV6UDPIFINDEX:
if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)savsa))
long_return = ntohs(savsa[2]);
else
long_return = 0;
return (u_char *) &long_return;
default:
break;
}
ERROR_MSG("");
return NULL;
}
#else
u_char *
var_udp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
oid savname[MAX_OID_LEN];
int result;
int i, j;
caddr_t p;
#if defined(openbsd4)
static struct inpcb in6pcb, savpcb;
#else
static struct in6pcb in6pcb, savpcb;
#endif
int found, savnameLen;
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
struct inpcbtable udbtable;
caddr_t first;
#elif defined(dragonfly)
char *sysctl_buf;
struct xinpcb *xig;
size_t sysctl_len;
#elif defined(freebsd3) || defined(darwin)
char *sysctl_buf;
struct xinpgen *xig, *oxig;
static struct in6pcb udb6;
#endif
DEBUGMSGTL(("mibII/ipv6", "var_udp6: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
#if defined(__NetBSD__) && __NetBSD_Version__ >= 700000001
if (!auto_nlist("udbtable", (char *) &udbtable, sizeof(udbtable)))
return NULL;
first = p = (caddr_t)udbtable.inpt_queue.tqh_first;
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
if (!auto_nlist("udbtable", (char *) &udbtable, sizeof(udbtable)))
return NULL;
#if defined(openbsd5)
first = p = (caddr_t)TAILQ_FIRST(&udbtable.inpt_queue);
#else
first = p = (caddr_t)udbtable.inpt_queue.cqh_first;
#endif
#elif !defined(freebsd3) && !defined(darwin)
if (!auto_nlist("udb6", (char *) &udb6, sizeof(udb6)))
return NULL;
p = (caddr_t) udb6.in6p_next;
#elif defined(dragonfly)
{
const char *udblist = "net.inet.udp.pcblist";
const char *pp = udblist;
if (sysctlbyname(udblist, 0, &sysctl_len, 0, 0) < 0)
return NULL;
if ((sysctl_buf = malloc(sysctl_len)) == NULL)
return NULL;
udblist = pp;
if (sysctlbyname(udblist, sysctl_buf, &sysctl_len, 0, 0) < 0) {
free(sysctl_buf);
return NULL;
}
xig = (struct xinpcb *) sysctl_buf;
if (xig->xi_len != sizeof(*xig)) {
free(sysctl_buf);
return NULL;
}
p = (caddr_t) ((char *) xig); /* silence compiler warning */
}
#else
{
const char *udblist = "net.inet.udp.pcblist";
const char *pp = udblist;
size_t len;
if (sysctlbyname(udblist, 0, &len, 0, 0) < 0)
return NULL;
if ((sysctl_buf = malloc(len)) == NULL)
return NULL;
udblist = pp;
if (sysctlbyname(udblist, sysctl_buf, &len, 0, 0) < 0) {
free(sysctl_buf);
return NULL;
}
oxig = (struct xinpgen *) sysctl_buf;
xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
p = (caddr_t) ((char *) xig); /* silence compiler warning */
}
#endif
found = savnameLen = 0;
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
DEBUGMSGTL(("mibII/ipv6", "start: p=%p\n", p));
while (
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
p
#elif !defined(freebsd3) && !defined(darwin)
p && (u_long) p != auto_nlist_value("udb6")
#elif defined(dragonfly)
(char *)xig + xig->xi_len <= sysctl_buf + sysctl_len && xig->xi_len != 0
#else
xig->xig_len > sizeof(struct xinpgen)
#endif
) {
DEBUGMSGTL(("mibII/ipv6", "looping: p=%p\n", p));
#if !defined(freebsd3) && !defined(darwin)
if (!NETSNMP_KLOOKUP(p, (char *) &in6pcb, sizeof(in6pcb))) {
DEBUGMSGTL(("mibII/ipv6", "klookup fail for udb6 at %p\n",
p));
found = 0;
break;
}
#else
in6pcb = ((struct xinpcb *) xig)->xi_inp;
#endif
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
if (in6pcb.in6p_af != AF_INET6)
goto skip;
#elif defined(INP_ISIPV6)
if (!INP_ISIPV6(&in6pcb))
goto skip;
#elif defined(freebsd3) || defined(darwin)
if (0 == (in6pcb.inp_vflag & INP_IPV6))
goto skip;
#elif defined(openbsd4)
if (!(in6pcb.inp_flags & INP_IPV6))
goto skip;
#endif
j = (int) vp->namelen;
#if defined(openbsd4)
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.inp_laddr6.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_lport);
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.inp_laddr6))
newname[j++] =
ntohs(*(uint16_t *) &in6pcb.inp_laddr6.s6_addr[2]);
else
newname[j++] = 0;
#else
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_lport);
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
newname[j++] =
ntohs(*(uint16_t *) &in6pcb.in6p_laddr.s6_addr[2]);
else
newname[j++] = 0;
#endif
/*XXX*/
DEBUGMSGTL(("mibII/ipv6", "var_udp6 new: %d %d ",
(int) vp->namelen, j));
DEBUGMSGOID(("mibII/ipv6", newname, j));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
result = snmp_oid_compare(name, *length, newname, j);
if (exact && (result == 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
break;
} else if (!exact && (result < 0)) {
/*
* take the least greater one
*/
if ((savnameLen == 0) ||
(snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
}
}
skip:
#ifdef openbsd5
p = (caddr_t)TAILQ_NEXT(&in6pcb, inp_queue);
if (p == NULL) break;
#elif defined(openbsd4)
p = (caddr_t)in6pcb.inp_queue.cqe_next;
if (p == first) break;
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 700000001
p = (caddr_t)in6pcb.in6p_queue.tqe_next;
if (p == first) break;
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
p = (caddr_t)in6pcb.in6p_queue.cqe_next;
if (p == first) break;
#elif !defined(freebsd3) && !defined(darwin)
p = (caddr_t)in6pcb.in6p_next;
#elif defined(__DragonFly__)
xig = (struct xinpcb *) ((char *) xig + xig->xi_len);
#else
xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
#endif
}
#if defined(freebsd3) || defined(darwin)
free(sysctl_buf);
#endif
DEBUGMSGTL(("mibII/ipv6", "found=%d\n", found));
if (!found)
return NULL;
*length = savnameLen;
memcpy((char *) name, (char *) savname, *length * sizeof(oid));
memcpy(&in6pcb, &savpcb, sizeof(savpcb));
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
/*
DEBUGMSGTL(("mibII/ipv6", "var_udp6 found: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
*/
DEBUGMSGTL(("mibII/ipv6", "magic=%d\n", vp->magic));
switch (vp->magic) {
case IPV6UDPIFINDEX:
#if defined(openbsd4)
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.inp_laddr6))
long_return =
ntohs(*(uint16_t *) & in6pcb.inp_laddr6.s6_addr[2]);
else
long_return = 0;
#else
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
long_return =
ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
else
long_return = 0;
#endif
return (u_char *) & long_return;
default:
break;
}
ERROR_MSG("");
return NULL;
}
#endif /* KVM_GETFILES */
#ifdef TCP6
u_char *
var_tcp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
oid savname[MAX_OID_LEN];
int result;
int i, j;
caddr_t p;
static struct in6pcb in6pcb, savpcb;
struct tcp6cb tcp6cb;
int found, savnameLen;
static int tcp6statemap[TCP6_NSTATES];
static int initialized = 0;
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
struct inpcbtable tcbtable;
caddr_t first;
#elif defined(freebsd3) || defined(darwin)
char *sysctl_buf;
struct xinpgen *xig, *oxig;
#else
static struct in6pcb tcb6;
#endif
if (!initialized) {
tcp6statemap[TCP6S_CLOSED] = 1;
tcp6statemap[TCP6S_LISTEN] = 2;
tcp6statemap[TCP6S_SYN_SENT] = 3;
tcp6statemap[TCP6S_SYN_RECEIVED] = 4;
tcp6statemap[TCP6S_ESTABLISHED] = 5;
tcp6statemap[TCP6S_CLOSE_WAIT] = 8;
tcp6statemap[TCP6S_FIN_WAIT_1] = 6;
tcp6statemap[TCP6S_CLOSING] = 10;
tcp6statemap[TCP6S_LAST_ACK] = 9;
tcp6statemap[TCP6S_FIN_WAIT_2] = 7;
tcp6statemap[TCP6S_TIME_WAIT] = 11;
initialized++;
}
DEBUGMSGTL(("mibII/ipv6", "var_tcp6: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
if (!auto_nlist("tcbtable", (char *) &tcbtable, sizeof(tcbtable)))
return NULL;
first = p = (caddr_t)tcbtable.inpt_queue.cqh_first;
#elif !defined(freebsd3) && !defined(darwin)
if (!auto_nlist("tcb6", (char *) &tcb6, sizeof(tcb6)))
return NULL;
p = (caddr_t) tcb6.in6p_next;
#else
{
const char *tcblist = "net.inet.tcp.pcblist";
const char *pp = tcblist;
size_t len;
if (sysctlbyname(tcblist, 0, &len, 0, 0) < 0)
return NULL;
if ((sysctl_buf = malloc(len)) == NULL)
return NULL;
tcblist = pp;
if (sysctlbyname(tcblist, sysctl_buf, &len, 0, 0) < 0) {
free(sysctl_buf);
return NULL;
}
oxig = (struct xinpgen *) sysctl_buf;
xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
p = (caddr_t) ((char *) xig); /* silence compiler warning */
}
#endif
found = savnameLen = 0;
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
DEBUGMSGTL(("mibII/ipv6", "start: p=%x\n", p));
while (
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
p && p != first
#elif !defined(freebsd3) && !defined(darwin)
p && (u_long) p != auto_nlist_value("tcb6")
#else
xig->xig_len > sizeof(struct xinpgen)
#endif
) {
DEBUGMSGTL(("mibII/ipv6", "looping: p=%x\n", p));
#if !defined(freebsd3) && !defined(darwin)
if (!NETSNMP_KLOOKUP(p, (char *) &in6pcb, sizeof(in6pcb))) {
DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6 at %x\n",
p));
found = 0;
break;
}
#else
in6pcb = ((struct xinpcb *) xig)->xi_inp;
#endif
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
if (in6pcb.in6p_af != AF_INET6)
goto skip;
#elif defined(INP_ISIPV6)
if (!INP_ISIPV6(&in6pcb))
goto skip;
#elif defined(freebsd3) || defined(darwin)
if (0 == (in6pcb.inp_vflag & INP_IPV6))
goto skip;
#endif
if (!NETSNMP_KLOOKUP(in6pcb.in6p_ppcb, (char *) &tcp6cb, sizeof(tcp6cb))) {
DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6.tcp6cb at %x\n",
in6pcb.in6p_ppcb));
found = 0;
break;
}
j = (int) vp->namelen;
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_lport);
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.in6p_faddr.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_fport);
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
newname[j++] =
ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
else
newname[j++] = 0;
DEBUGMSGTL(("mibII/ipv6", "var_tcp6 new: %d %d ",
(int) vp->namelen, j));
DEBUGMSGOID(("mibII/ipv6", newname, j));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
#if 1 /* this is very odd but sometimes happen, and cause infinite loop */
if (ntohs(in6pcb.inp_lport) == 0)
goto skip;
#endif
result = snmp_oid_compare(name, *length, newname, j);
if (exact && (result == 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
break;
} else if (!exact && (result < 0)) {
/*
* take the least greater one
*/
if ((savnameLen == 0) ||
(snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
}
}
skip:
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
p = (caddr_t)in6pcb.in6p_queue.cqe_next;
#elif !defined(freebsd3) && !defined(darwin)
p = (caddr_t)in6pcb.in6p_next;
#else
xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
#endif
}
#if defined(freebsd3) || defined(darwin)
free(sysctl_buf);
#endif
DEBUGMSGTL(("mibII/ipv6", "found=%d\n", found));
if (!found)
return NULL;
*length = savnameLen;
memcpy((char *) name, (char *) savname, *length * sizeof(oid));
memcpy(&in6pcb, &savpcb, sizeof(savpcb));
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
/*
DEBUGMSGTL(("mibII/ipv6", "var_tcp6 found: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
*/
DEBUGMSGTL(("mibII/ipv6", "magic=%d\n", vp->magic));
switch (vp->magic) {
case IPV6TCPCONNSTATE:
long_return = tcp6statemap[in6pcb.t_state];
return (u_char *) & long_return;
default:
break;
}
ERROR_MSG("");
return NULL;
}
#elif HAVE_KVM_GETFILES
u_char *
var_tcp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
oid savname[MAX_OID_LEN];
int result, count, found, savnameLen, savstate;
int p, i, j;
u_char *lsa, *savlsa, *fsa, *savfsa;
struct kinfo_file *tcp;
static int tcp6statemap[16];
static int initialized = 0;
if (!initialized) {
tcp6statemap[TCPS_CLOSED] = 1;
tcp6statemap[TCPS_LISTEN] = 2;
tcp6statemap[TCPS_SYN_SENT] = 3;
tcp6statemap[TCPS_SYN_RECEIVED] = 4;
tcp6statemap[TCPS_ESTABLISHED] = 5;
tcp6statemap[TCPS_CLOSE_WAIT] = 8;
tcp6statemap[TCPS_FIN_WAIT_1] = 6;
tcp6statemap[TCPS_CLOSING] = 10;
tcp6statemap[TCPS_LAST_ACK] = 9;
tcp6statemap[TCPS_FIN_WAIT_2] = 7;
tcp6statemap[TCPS_TIME_WAIT] = 11;
initialized++;
}
tcp = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET, sizeof(struct kinfo_file), &count);
found = savnameLen = 0;
memcpy(newname, vp->name, (int) vp->namelen * sizeof(oid));
for (p = 0; p < count; p++) {
if (tcp[p].so_protocol != IPPROTO_TCP || tcp[p].so_family != AF_INET6)
continue;
j = vp->namelen;
lsa = (u_char *)&tcp[p].inp_laddru[0];
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = lsa[i];
newname[j++] = ntohs(tcp[p].inp_lport);
fsa = (u_char *)&tcp[p].inp_faddru[0];
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = fsa[i];
newname[j++] = ntohs(tcp[p].inp_fport);
if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)lsa))
newname[j++] = ntohs(lsa[2]);
else
newname[j++] = 0;
DEBUGMSGTL(("mibII/ipv6", "var_udp6 new: %d %d ",
(int) vp->namelen, j));
DEBUGMSGOID(("mibII/ipv6", newname, j));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
result = snmp_oid_compare(name, *length, newname, j);
if (exact && result == 0) {
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
savlsa = lsa;
savfsa = fsa;
savstate = tcp[p].t_state;
found++;
break;
} else if (!exact && result < 0) {
/*
* take the least greater one
*/
if (savnameLen == 0 || snmp_oid_compare(savname, savnameLen, newname, j) > 0) {
savnameLen = j;
savlsa = lsa;
savfsa = fsa;
savstate = tcp[p].t_state;
memcpy(savname, newname, j * sizeof(oid));
found++;
}
}
}
DEBUGMSGTL(("mibII/ipv6", "found=%d\n", found));
if (!found)
return NULL;
*length = savnameLen;
memcpy((char *) name, (char *) savname, *length * sizeof(oid));
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
/*
* DEBUGMSGTL(("mibII/ipv6", "var_udp6 found: "));
* DEBUGMSGOID(("mibII/ipv6", name, *length));
* DEBUGMSG(("mibII/ipv6", " %d\n", exact));
*/
DEBUGMSGTL(("mibII/ipv6", "magic=%d\n", vp->magic));
switch (vp->magic) {
case IPV6TCPCONNSTATE:
long_return = tcp6statemap[savstate & 0x0F];
return (u_char *) &long_return;
default:
break;
}
ERROR_MSG("");
return NULL;
}
#else /* ! TCP6 */
static int mapTcpState( int val)
{
static int tcpstatemap[16 /*TCP_NSTATES*/];
static int initialized = 0;
if (!initialized) {
memset(tcpstatemap, 0, sizeof(tcpstatemap));
tcpstatemap[TCPS_CLOSED] = 1;
tcpstatemap[TCPS_LISTEN] = 2;
tcpstatemap[TCPS_SYN_SENT] = 3;
tcpstatemap[TCPS_SYN_RECEIVED] = 4;
tcpstatemap[TCPS_ESTABLISHED] = 5;
tcpstatemap[TCPS_CLOSE_WAIT] = 8;
tcpstatemap[TCPS_FIN_WAIT_1] = 6;
tcpstatemap[TCPS_CLOSING] = 10;
tcpstatemap[TCPS_LAST_ACK] = 9;
tcpstatemap[TCPS_FIN_WAIT_2] = 7;
tcpstatemap[TCPS_TIME_WAIT] = 11;
initialized++;
}
/* XXX GIGO 0 is an invalid state */
return (tcpstatemap[0x0f & val]);
}
u_char *
var_tcp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
oid newname[MAX_OID_LEN];
oid savname[MAX_OID_LEN];
int result;
int i, j;
caddr_t p;
#if defined(openbsd4)
static struct inpcb in6pcb, savpcb;
#else
static struct in6pcb in6pcb, savpcb;
#endif
struct tcpcb tcpcb;
int found, savnameLen;
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
struct inpcbtable tcbtable;
caddr_t first;
#elif defined(dragonfly)
char *sysctl_buf;
size_t sysctl_len;
struct xtcpcb *xtp;
#elif defined(freebsd3) || defined(darwin)
char *sysctl_buf;
struct xinpgen *xig, *oxig;
static struct in6pcb tcb6;
#endif
DEBUGMSGTL(("mibII/ipv6", "var_tcp6: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
if (!auto_nlist("tcbtable", (char *) &tcbtable, sizeof(tcbtable)))
return NULL;
#ifdef openbsd5
first = p = (caddr_t)TAILQ_FIRST(&tcbtable.inpt_queue);
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 700000001
first = p = (caddr_t)tcbtable.inpt_queue.tqh_first;
#else
first = p = (caddr_t)tcbtable.inpt_queue.cqh_first;
#endif
#elif !defined(freebsd3) && !defined(darwin)
if (!auto_nlist("tcb6", (char *) &tcb6, sizeof(tcb6)))
return NULL;
p = (caddr_t) tcb6.in6p_next;
#elif defined(dragonfly)
{
const char *tcblist = "net.inet.tcp.pcblist";
const char *pp = tcblist;
if (sysctlbyname(tcblist, 0, &sysctl_len, 0, 0) < 0)
return NULL;
if ((sysctl_buf = malloc(sysctl_len)) == NULL)
return NULL;
tcblist = pp;
if (sysctlbyname(tcblist, sysctl_buf, &sysctl_len, 0, 0) < 0) {
free(sysctl_buf);
return NULL;
}
xtp = (struct xtcpcb *) sysctl_buf;
if (xtp->xt_len != sizeof(*xtp)) {
free(sysctl_buf);
return NULL;
}
p = (caddr_t) ((char *) xtp); /* silence compiler warning */
}
#else
{
const char *tcblist = "net.inet.tcp.pcblist";
const char *pp = tcblist;
size_t len;
if (sysctlbyname(tcblist, 0, &len, 0, 0) < 0)
return NULL;
if ((sysctl_buf = malloc(len)) == NULL)
return NULL;
tcblist = pp;
if (sysctlbyname(tcblist, sysctl_buf, &len, 0, 0) < 0) {
free(sysctl_buf);
return NULL;
}
oxig = (struct xinpgen *) sysctl_buf;
xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
p = (caddr_t) ((char *) xig); /* silence compiler warning */
}
#endif
found = savnameLen = 0;
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
DEBUGMSGTL(("mibII/ipv6", "start: p=%p\n", p));
while (
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
p
#elif !defined(freebsd3) && !defined(darwin)
p && (u_long) p != auto_nlist_value("tcb6")
#elif defined(dragonfly)
(char *)xtp + xtp->xt_len < sysctl_buf + sysctl_len
#else
xig->xig_len > sizeof(struct xinpgen)
#endif
) {
DEBUGMSGTL(("mibII/ipv6", "looping: p=%p\n", p));
#if !defined(freebsd3) && !defined(darwin)
if (!NETSNMP_KLOOKUP(p, (char *) &in6pcb, sizeof(in6pcb))) {
DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6 at %p\n",
p));
found = 0;
break;
}
#elif defined(dragonfly)
in6pcb = xtp->xt_inp;
#else
in6pcb = ((struct xinpcb *) xig)->xi_inp;
#endif
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
if (in6pcb.in6p_af != AF_INET6)
goto skip;
#elif defined(INP_ISIPV6)
if (!INP_ISIPV6(&in6pcb))
goto skip;
#elif defined(freebsd3) || defined(darwin)
if (0 == (in6pcb.inp_vflag & INP_IPV6))
goto skip;
#elif defined(openbsd4)
if (0 == (in6pcb.inp_flags & INP_IPV6))
goto skip;
#endif
j = (int) vp->namelen;
#if defined(openbsd4)
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.inp_laddr6.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_lport);
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.inp_faddr6.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_fport);
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.inp_laddr6))
newname[j++] =
ntohs(*(uint16_t *) &in6pcb.inp_laddr6.s6_addr[2]);
else
newname[j++] = 0;
#else
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_lport);
for (i = 0; i < sizeof(struct in6_addr); i++)
newname[j++] = in6pcb.in6p_faddr.s6_addr[i];
newname[j++] = ntohs(in6pcb.inp_fport);
if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
newname[j++] =
ntohs(*(uint16_t *) &in6pcb.in6p_laddr.s6_addr[2]);
else
newname[j++] = 0;
#endif
DEBUGMSGTL(("mibII/ipv6", "var_tcp6 new: %d %d ",
(int) vp->namelen, j));
DEBUGMSGOID(("mibII/ipv6", newname, j));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
#if 1 /* this is very odd but sometimes happen, and cause infinite loop */
if (ntohs(in6pcb.inp_lport) == 0)
goto skip;
#endif
result = snmp_oid_compare(name, *length, newname, j);
if (exact && (result == 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
break;
} else if (!exact && (result < 0)) {
/*
* take the least greater one
*/
if ((savnameLen == 0) ||
(snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
memcpy(&savpcb, &in6pcb, sizeof(savpcb));
savnameLen = j;
memcpy(savname, newname, j * sizeof(oid));
found++;
}
}
skip:
#ifdef openbsd5
p = (caddr_t)TAILQ_NEXT(&in6pcb, inp_queue);
if (p == NULL) break;
#elif defined(openbsd4)
p = (caddr_t)in6pcb.inp_queue.cqe_next;
if (p == first) break;
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 700000001
p = (caddr_t)in6pcb.in6p_queue.tqe_next;
if (p == first) break;
#elif defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 || defined(openbsd4) /*1.6Y*/
p = (caddr_t)in6pcb.in6p_queue.cqe_next;
if (p == first) break;
#elif !defined(freebsd3) && !defined(darwin)
p = (caddr_t) in6pcb.in6p_next;
#elif defined(dragonfly)
xtp = (struct xtcpcb *) ((char *)xtp + xtp->xt_len);
#else
xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
#endif
}
#if defined(freebsd3) || defined(darwin)
free(sysctl_buf);
#endif
DEBUGMSGTL(("mibII/ipv6", "found=%d\n", found));
if (!found)
return NULL;
*length = savnameLen;
memcpy((char *) name, (char *) savname, *length * sizeof(oid));
memcpy(&in6pcb, &savpcb, sizeof(savpcb));
if (!NETSNMP_KLOOKUP(in6pcb.inp_ppcb, (char *) &tcpcb, sizeof(tcpcb))) {
DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6.tcpcb at %p\n",
in6pcb.inp_ppcb));
found = 0;
return NULL;
}
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
/*
DEBUGMSGTL(("mibII/ipv6", "var_tcp6 found: "));
DEBUGMSGOID(("mibII/ipv6", name, *length));
DEBUGMSG(("mibII/ipv6", " %d\n", exact));
*/
DEBUGMSGTL(("mibII/ipv6", "magic=%d\n", vp->magic));
switch (vp->magic) {
case IPV6TCPCONNSTATE:
long_return = mapTcpState((int)tcpcb.t_state);
return (u_char *) & long_return;
default:
break;
}
ERROR_MSG("");
return NULL;
}
#endif /*TCP6 */
#else /* !linux / linux */
/*
* Linux dependent part
*/
static unsigned long
linux_read_ip6_stat_ulong(const char *file)
{
FILE *f;
unsigned long value;
f = fopen(file, "r");
if (!f)
return 0;
if (fscanf(f, "%lu", &value) != 1) {
fclose(f);
return 0;
}
fclose(f);
return value;
}
static void
linux_read_ip6_stat(struct ip6_mib *ip6stat)
{
if (!ip6stat)
return;
memset(ip6stat, 0, sizeof(*ip6stat));
ip6stat->Ipv6Forwarding =
linux_read_ip6_stat_ulong
("/proc/sys/net/ipv6/conf/all/forwarding");
ip6stat->Ipv6DefaultHopLimit =
linux_read_ip6_stat_ulong
("/proc/sys/net/ipv6/conf/default/hop_limit");
}
u_char *
var_ipv6(register struct variable *vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
static struct ip6_mib ip6stat;
if (header_ipv6(vp, name, length, exact, var_len, write_method)
== MATCH_FAILED) {
return NULL;
}
linux_read_ip6_stat(&ip6stat);
switch (vp->magic) {
case IPV6DEFAULTHOPLIMIT:
return (u_char *) & ip6stat.Ipv6DefaultHopLimit;
case IPV6FORWARDING:
long_return = (ip6stat.Ipv6Forwarding) ? 1 : 2;
return (u_char *) & long_return;
case IPV6INTERFACES:
#ifdef HAVE_IF_NAMEINDEX
long_return = if_countifindex();
if (long_return < 0)
break;
return (u_char *) & long_return;
#endif
break;
default:
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipv6\n",
vp->magic));
}
return NULL;
}
u_char *
var_ifv6Entry(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
#ifndef HAVE_IF_NAMEINDEX
return NULL;
#else
int interface;
int max;
char *p;
struct ifreq ifr;
int s;
/* Reload list of interfaces */
if (if_initialize() < 0)
return NULL;
max = if_maxifindex();
if (max < 0)
return NULL;
if (header_ipv6_scan
(vp, name, length, exact, var_len, write_method, 1, max)
== MATCH_FAILED) {
return NULL;
}
interface = name[*length - 1];
DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)\n",
interface, if_getname(interface)));
if (interface > max)
return NULL;
switch (vp->magic) {
case IPV6IFDESCR:
p = if_getname(interface);
if (p) {
*var_len = strlen(p);
return (u_char *) p;
}
break;
case IPV6IFLOWLAYER:
/*
* should check if type, this is a hard one...
*/
*var_len = nullOidLen;
return (u_char *) nullOid;
case IPV6IFEFFECTMTU:
{
p = if_getname(interface);
if (!p)
break;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET6;
strlcpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0) {
close(s);
break;
}
long_return = ifr.ifr_mtu;
close(s);
return (u_char *) & long_return;
}
case IPV6IFPHYSADDRESS:
{
static struct ifreq buf;
int ok = 0;
p = if_getname(interface);
if (!p)
break;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET6;
strlcpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
memset(buf.ifr_hwaddr.sa_data, 0,
sizeof(buf.ifr_hwaddr.sa_data));
*var_len = 0;
} else {
memcpy(buf.ifr_hwaddr.sa_data, ifr.ifr_hwaddr.sa_data, 6);
*var_len = (buf.ifr_hwaddr.sa_data[0] |
buf.ifr_hwaddr.sa_data[1] |
buf.ifr_hwaddr.sa_data[2] |
buf.ifr_hwaddr.sa_data[3] |
buf.ifr_hwaddr.sa_data[4] |
buf.ifr_hwaddr.sa_data[5]) ? 6 : 0;
ok = 1;
}
close(s);
return (ok ? ((u_char *) & buf.ifr_hwaddr.sa_data) : NULL);
}
case IPV6IFADMSTATUS:
case IPV6IFOPERSTATUS:
{
int flag = 0;
p = if_getname(interface);
if (!p)
break;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET6;
strlcpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
break;
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
close(s);
break;
}
close(s);
switch (vp->magic) {
case IPV6IFADMSTATUS:
flag = IFF_RUNNING;
break;
case IPV6IFOPERSTATUS:
flag = IFF_UP;
break;
}
long_return = (ifr.ifr_flags & flag) ? 1 : 2;
return (u_char *) & long_return;
}
}
return NULL;
#endif
}
u_char *
var_icmpv6Entry(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
return NULL;
}
u_char *
var_udp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
return NULL;
}
u_char *
var_tcp6(register struct variable * vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
return NULL;
}
/*
* misc functions (against broken kernels )
*/
void
linux_if_freenameindex(struct if_nameindex *ifndx)
{
int i;
if (!ifndx)
return;
for (i = 0; ifndx[i].if_index; i++) {
free(ifndx[i].if_name);
}
free(ifndx);
ifndx = NULL;
}
#define linux_freeinternalnameindex(ifni, max) { \
int i; \
for (i=1; i<=max; i++){ \
if (ifni[i].if_name) free(ifni[i].if_name); \
} \
free(ifni); \
}
#define LINUX_PROC_NET_IFINET6 "/proc/net/if_inet6"
struct if_nameindex *
linux_if_nameindex(void)
{
FILE *f;
unsigned long if_index;
char if_name[256];
struct if_nameindex *ifndx = NULL, *iflist = NULL, *tmp;
int i, j;
int maxidx, if_count = 0;
static int last_if_count;
f = fopen(LINUX_PROC_NET_IFINET6, "r");
if (f) {
if_count = 0;
maxidx = -1;
while (!feof(f)) {
if (fscanf(f, "%*s %lx %*x %*x %*x %255s",
&if_index, if_name) != 2)
continue;
if (if_index == 0)
continue;
if_name[sizeof(if_name) - 1] = '\0';
/*
* Large if_index values can cause the multiplication in the
* realloc() statement to overflow. Hence check if_index.
*/
if (if_index > 65536)
break;
if (maxidx < 0 || maxidx < if_index) {
if (last_if_count < if_index)
last_if_count = if_index;
tmp =
realloc(iflist,
(sizeof(struct if_nameindex)) * (last_if_count +
2));
if (!tmp) {
linux_freeinternalnameindex(iflist, if_index);
if_count = 0;
iflist = NULL;
break;
}
iflist = tmp;
for (i = maxidx + 1; i <= if_index; i++)
memset(&iflist[i], 0, sizeof(struct if_nameindex));
memset(&iflist[if_index + 1], 0,
sizeof(struct if_nameindex));
maxidx = if_index;
}
if (iflist[if_index].if_index == 0) {
if_count++;
iflist[if_index].if_index = if_index;
iflist[if_index].if_name = strdup(if_name);
if (!iflist[if_index].if_name) {
linux_freeinternalnameindex(iflist, if_index);
if_count = 0;
iflist = NULL;
break;
}
}
}
fclose(f);
if (if_count > 0) {
ifndx = malloc(sizeof(struct if_nameindex) * (if_count + 1));
j = 0;
for (i = 1; i <= maxidx; i++) {
if (iflist[i].if_index > 0 && *iflist[i].if_name) {
memcpy(&ifndx[j++], &iflist[i],
sizeof(struct if_nameindex));
}
}
ifndx[j].if_index = 0;
ifndx[j].if_name = NULL;
}
free(iflist);
}
return (ifndx);
}
#endif /* linux */