/* * IP MIB group implementation - ipv6.c * */ #include #include /* For FreeBSD */ #define _WANT_INPCB 1 #define _WANT_TCPCB 1 #include #include #if HAVE_SYS_IOCTL_H #include #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 #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #if HAVE_SYS_SOCKETVAR_H # include #endif #if STDC_HEADERS #include #include #else #if HAVE_STDLIB_H #include #endif #endif #if HAVE_UNISTD_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_SYS_SYSCTL_H #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #include #ifdef _I_DEFINED_KERNEL #define _KERNEL 1 #endif #endif #if HAVE_SYS_SYSMP_H #include #endif #if HAVE_SYS_TCPIPSTATS_H #include #endif #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #include #ifdef _I_DEFINED_KERNEL #define _KERNEL 1 #endif #if HAVE_NET_IF_VAR_H #include #endif #if HAVE_NET_IF_DL_H #include #endif #ifdef HAVE_NET_IF_MIB_H #include #endif #ifdef _I_DEFINED_KERNEL #undef _KERNEL #endif #include #if HAVE_SYS_HASHING_H #include #endif #if HAVE_SYS_SOCKIO_H #include #endif #if HAVE_NETINET6_IN6_VAR_H #include #endif #include #if HAVE_NETINET_IP_VAR_H # include #endif #if HAVE_NETINET_ICMP6_H # include #endif #if HAVE_NETINET6_IP6_VAR_H # include # include #endif #include #if HAVE_NETINET_IP_H # include #endif #if HAVE_NETINET_IN_PCB_H # include #endif #if HAVE_NETINET6_IN6_PCB_H # include #endif #if HAVE_NETINET6_TCP6_H # define TCP6 #endif #ifndef TCP6 # if HAVE_NETINET_TCP_H # include # endif # if HAVE_NETINET_TCP_TIMER_H # include # endif # if HAVE_NETINET_TCP_VAR_H # include # endif # if HAVE_NETINET_TCP_FSM_H # include # endif #endif #if HAVE_NETINET6_TCP6_H # include #endif #if HAVE_NETINET6_TCP6_TIMER_H #include #endif #if HAVE_NETINET6_TCP6_VAR_H #include #endif #if HAVE_NETINET6_TCP6_FSM_H #include #endif #if HAVE_INET_MIB2_H #include #endif #ifdef HAVE_SYSLOG_H #include #endif #if HAVE_KVM_GETFILES #if defined(HAVE_KVM_GETFILE2) || !defined(openbsd5) #undef HAVE_KVM_GETFILES #endif #endif #if HAVE_KVM_GETFILES #include #include #define _KERNEL #include #undef _KERNEL #endif #ifdef MIB_IPCOUNTER_SYMBOL #include #include #endif /* MIB_IPCOUNTER_SYMBOL */ #include #include #include #include "kernel.h" #include "ipv6.h" #include "interfaces.h" #ifdef freebsd3 #undef in6pcb #endif 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 #if defined(__OpenBSD__) || defined(freebsd3) /* * It is not possible to use struct ifnet anymore on OpenBSD, get * interface flags and L2 address through getifaddrs(3). */ #include 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 (u_char *)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: { #if defined(__OpenBSD__) || defined(freebsd3) 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: { #if defined(__OpenBSD__) || defined(freebsd3) 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: { #if defined(__OpenBSD__) || defined(freebsd3) 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) || defined(freebsd3) 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; #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(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 */ } #elif !defined(freebsd3) && !defined(darwin) { static struct in6pcb udb6; if (!auto_nlist("udb6", (char *) &udb6, sizeof(udb6))) return NULL; p = (caddr_t) udb6.in6p_next; } #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) /* To do: fill in in6pcb properly. */ memset(&in6pcb, 0, sizeof(in6pcb)); #elif defined(darwin) in6pcb = ((struct xinpcb *) xig)->xi_inp; #else if (!NETSNMP_KLOOKUP(p, (char *) &in6pcb, sizeof(in6pcb))) { DEBUGMSGTL(("mibII/ipv6", "klookup fail for udb6 at %p\n", p)); found = 0; break; } #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(__DragonFly__) xig = (struct xinpcb *) ((char *) xig + xig->xi_len); #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_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; #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) { static struct in6pcb tcb6; 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) || defined(freebsd3) 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; #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(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 */ } #elif !defined(freebsd3) && !defined(darwin) { static struct in6pcb tcb6; 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=%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) /* To do: fill in in6pcb properly. */ memset(&in6pcb, 0, sizeof(in6pcb)); #elif defined(dragonfly) in6pcb = xtp->xt_inp; #elif defined(darwin) in6pcb = ((struct xinpcb *) xig)->xi_inp; #else if (!NETSNMP_KLOOKUP(p, (char *) &in6pcb, sizeof(in6pcb))) { DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6 at %p\n", p)); found = 0; break; } #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(dragonfly) xtp = (struct xtcpcb *) ((char *)xtp + xtp->xt_len); #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)); 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 */