diff options
Diffstat (limited to 'agent/mibgroup/mibII/ipv6.c')
-rw-r--r-- | agent/mibgroup/mibII/ipv6.c | 2301 |
1 files changed, 2301 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/ipv6.c b/agent/mibgroup/mibII/ipv6.c new file mode 100644 index 0000000..99d50e8 --- /dev/null +++ b/agent/mibgroup/mibII/ipv6.c @@ -0,0 +1,2301 @@ +/* + * IP MIB group implementation - ipv6.c + * + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-features.h> +#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/types.h> +#include <sys/param.h> +#include <sys/socket.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_SYS_IOCTL_H +#include <sys/ioctl.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 +#include <net/if.h> +#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 <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 + +#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 +/* + * 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; +} + +#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: + { + 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; + } + case IPV6IFADMSTATUS: + { + struct ifnet ifnet; + + if (if_getifnet(interface, &ifnet) < 0) + break; + long_return = (ifnet.if_flags & IFF_RUNNING) ? 1 : 2; + return (u_char *) & long_return; + } + case IPV6IFOPERSTATUS: + { + struct ifnet ifnet; + + if (if_getifnet(interface, &ifnet) < 0) + break; + long_return = (ifnet.if_flags & IFF_UP) ? 1 : 2; + 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 +} + +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__ >= 106250000 || defined(openbsd4) /*1.6Y*/ + if (!auto_nlist("udbtable", (char *) &udbtable, sizeof(udbtable))) + return NULL; + first = p = (caddr_t)udbtable.inpt_queue.cqh_first; +#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(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: +#if defined(openbsd4) + p = (caddr_t)in6pcb.inp_queue.cqe_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; +} + +#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(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; +} + +#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; + 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; +#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(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: +#if defined(openbsd4) + p = (caddr_t)in6pcb.inp_queue.cqe_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 %s", + &if_index, if_name) != 2) + continue; + if (if_index == 0) + continue; + if_name[sizeof(if_name) - 1] = '\0'; + 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 */ |