ipv6.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:68k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  IP MIB group implementation - ipv6.c
  3.  *
  4.  */
  5. #include <net-snmp/net-snmp-config.h>
  6. #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
  7. #define _KERNEL 1
  8. #define _I_DEFINED_KERNEL
  9. #endif
  10. #include <sys/types.h>
  11. #include <sys/param.h>
  12. #include <sys/socket.h>
  13. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  14. # if HAVE_SYS_SOCKETVAR_H
  15. #  include <sys/socketvar.h>
  16. # endif
  17. #endif
  18. #if STDC_HEADERS
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #else
  22. #if HAVE_STDLIB_H
  23. #include <stdlib.h>
  24. #endif
  25. #endif
  26. #if HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #if HAVE_SYS_IOCTL_H
  30. #include <sys/ioctl.h>
  31. #endif
  32. #if HAVE_NETINET_IN_H
  33. #include <netinet/in.h>
  34. #endif
  35. #if HAVE_SYS_SYSCTL_H
  36. #ifdef _I_DEFINED_KERNEL
  37. #undef _KERNEL
  38. #endif
  39. #include <sys/sysctl.h>
  40. #ifdef _I_DEFINED_KERNEL
  41. #define _KERNEL 1
  42. #endif
  43. #endif
  44. #if HAVE_SYS_SYSMP_H
  45. #include <sys/sysmp.h>
  46. #endif
  47. #if HAVE_SYS_TCPIPSTATS_H
  48. #include <sys/tcpipstats.h>
  49. #endif
  50. #include <net/if.h>
  51. #if HAVE_NET_IF_VAR_H
  52. #include <net/if_var.h>
  53. #endif
  54. #if HAVE_NET_IF_DL_H
  55. #include <net/if_dl.h>
  56. #endif
  57. #ifdef HAVE_NET_IF_MIB_H
  58. #include <net/if_mib.h>
  59. #endif
  60. #ifdef _I_DEFINED_KERNEL
  61. #undef _KERNEL
  62. #endif
  63. #include <netinet/in_systm.h>
  64. #if HAVE_SYS_HASHING_H
  65. #include <sys/hashing.h>
  66. #endif
  67. #if HAVE_SYS_SOCKIO_H
  68. #include <sys/sockio.h>
  69. #endif
  70. #if HAVE_NETINET6_IN6_VAR_H
  71. #include <netinet6/in6_var.h>
  72. #endif
  73. #include <netinet/ip6.h>
  74. #if HAVE_NETINET_IP_VAR_H
  75. # include <netinet/ip_var.h>
  76. #endif
  77. #if HAVE_NETINET6_IP6_VAR_H
  78. # include <netinet6/ip6_var.h>
  79. #endif
  80. #include <net/route.h>
  81. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  82. # if HAVE_NETINET_IN_PCB_H
  83. #  include <netinet/in_pcb.h>
  84. # endif
  85. #endif
  86. #if HAVE_NETINET6_IN6_PCB_H
  87. # include <netinet6/in6_pcb.h>
  88. #endif
  89. #if HAVE_NETINET6_TCP6_H
  90. # define TCP6
  91. #endif
  92. #ifndef TCP6
  93. # if HAVE_NETINET_TCP_H
  94. #  include <netinet/tcp.h>
  95. # endif
  96. # if HAVE_NETINET_TCP_TIMER_H
  97. #  include <netinet/tcp_timer.h>
  98. # endif
  99. # if HAVE_NETINET_TCP_VAR_H
  100. #  include <netinet/tcp_var.h>
  101. # endif
  102. # if HAVE_NETINET_TCP_FSM_H
  103. #  include <netinet/tcp_fsm.h>
  104. # endif
  105. #endif
  106. #if HAVE_NETINET6_TCP6_H
  107. # include <netinet6/tcp6.h>
  108. #endif
  109. #if HAVE_NETINET6_TCP6_TIMER_H
  110. #include <netinet6/tcp6_timer.h>
  111. #endif
  112. #if HAVE_NETINET6_TCP6_VAR_H
  113. #include <netinet6/tcp6_var.h>
  114. #endif
  115. #if HAVE_NETINET6_TCP6_FSM_H
  116. #include <netinet6/tcp6_fsm.h>
  117. #endif
  118. #if HAVE_INET_MIB2_H
  119. #include <inet/mib2.h>
  120. #endif
  121. #ifdef HAVE_SYSLOG_H
  122. #include <syslog.h>
  123. #endif
  124. #ifdef MIB_IPCOUNTER_SYMBOL
  125. #include <sys/mib.h>
  126. #include <netinet/mib_kern.h>
  127. #endif                          /* MIB_IPCOUNTER_SYMBOL */
  128. #include <net-snmp/net-snmp-includes.h>
  129. #include <net-snmp/agent/net-snmp-agent-includes.h>
  130. #include <net-snmp/agent/auto_nlist.h>
  131. #include "kernel.h"
  132. #include "util_funcs.h"
  133. #include "ipv6.h"
  134. #include "interfaces.h"
  135. static int header_ipv6
  136. __P((register struct variable *, oid *, size_t *, int, size_t *,
  137.      WriteMethod **));
  138. static int header_ipv6_scan
  139. __P((register struct variable *, oid *, size_t *, int, size_t *,
  140.      WriteMethod **, int, int));
  141. static int if_initialize __P((void));
  142. static int if_maxifindex __P((void));
  143. static char    *if_getname __P((int));
  144. #ifdef notused
  145. static int if_getindex __P((const char *));
  146. #endif
  147. struct variable3 ipv6_variables[] = {
  148.     {IPV6FORWARDING, ASN_INTEGER, RONLY, var_ipv6, 1, {1}},
  149.     {IPV6DEFAULTHOPLIMIT, ASN_INTEGER, RONLY, var_ipv6, 1, {2}},
  150.     {IPV6INTERFACES, ASN_GAUGE, RONLY, var_ipv6, 1, {3}},
  151.     {IPV6IFTBLLASTCHG, ASN_TIMETICKS, RONLY, var_ipv6, 1, {4}},
  152.     {IPV6IFDESCR, ASN_OCTET_STR, RONLY, var_ifv6Entry, 3, {5, 1, 2}},
  153.     {IPV6IFLOWLAYER, ASN_OBJECT_ID, RONLY, var_ifv6Entry, 3, {5, 1, 3}},
  154.     {IPV6IFEFFECTMTU, ASN_UNSIGNED, RONLY, var_ifv6Entry, 3, {5, 1, 4}},
  155.     {IPV6IFREASMMAXSIZE, ASN_UNSIGNED, RONLY, var_ifv6Entry, 3, {5, 1, 5}},
  156.     {IPV6IFTOKEN, ASN_OCTET_STR, RONLY, var_ifv6Entry, 3, {5, 1, 6}},
  157.     {IPV6IFTOKENLEN, ASN_INTEGER, RONLY, var_ifv6Entry, 3, {5, 1, 7}},
  158.     {IPV6IFPHYSADDRESS, ASN_OCTET_STR, RONLY, var_ifv6Entry, 3, {5, 1, 8}},
  159.     {IPV6IFADMSTATUS, ASN_INTEGER, RONLY, var_ifv6Entry, 3, {5, 1, 9}},
  160.     {IPV6IFOPERSTATUS, ASN_INTEGER, RONLY, var_ifv6Entry, 3, {5, 1, 10}},
  161.     {IPV6IFLASTCHANGE, ASN_TIMETICKS, RONLY, var_ifv6Entry, 3, {5, 1, 11}},
  162.     {IPV6IFSTATSINRCVS, ASN_COUNTER, RONLY, var_ifv6Entry, 3, {6, 1, 1}},
  163.     {IPV6IFSTATSINHDRERRS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  164.      {6, 1, 2}},
  165.     {IPV6IFSTATSTOOBIGERRS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  166.      {6, 1, 3}},
  167.     {IPV6IFSTATSINNOROUTES, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  168.      {6, 1, 4}},
  169.     {IPV6IFSTATSINADDRERRS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  170.      {6, 1, 5}},
  171.     {IPV6IFSTATSINUNKNOWPROTS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  172.      {6, 1, 6}},
  173.     {IPV6IFSTATSINTRUNCATPKTS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  174.      {6, 1, 7}},
  175.     {IPV6IFSTATSINDISCARDS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  176.      {6, 1, 8}},
  177.     {IPV6IFSTATSINDELIVERS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  178.      {6, 1, 9}},
  179.     {IPV6IFSTATSOUTFORWDATAS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  180.      {6, 1, 10}},
  181.     {IPV6IFSTATSOUTREQS, ASN_COUNTER, RONLY, var_ifv6Entry, 3, {6, 1, 11}},
  182.     {IPV6IFSTATSOUTDISCARDS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  183.      {6, 1, 12}},
  184.     {IPV6IFSTATSOUTFRAGOKS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  185.      {6, 1, 13}},
  186.     {IPV6IFSTATSOUTFRAGFAILS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  187.      {6, 1, 14}},
  188.     {IPV6IFSTATSOUTFRAGCREATS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  189.      {6, 1, 15}},
  190.     {IPV6IFSTATSOUTREASMREQS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  191.      {6, 1, 16}},
  192.     {IPV6IFSTATSOUTREASMOKS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  193.      {6, 1, 17}},
  194.     {IPV6IFSTATSOUTREASMFAILS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  195.      {6, 1, 18}},
  196.     {IPV6IFSTATSINMCASTPKTS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  197.      {6, 1, 19}},
  198.     {IPV6IFSTATSOUTMCASTPKTS, ASN_COUNTER, RONLY, var_ifv6Entry, 3,
  199.      {6, 1, 20}},
  200. #if 0
  201.     {IPV6ADDRPREFIXONLINKFLG, INTEGER, RONLY, var_ipv6AddrEntry, 3,
  202.      {7, 1, 3}},
  203.     {IPV6ADDRPREFIXAUTONOMOUSFLAG, INTEGER, RONLY, var_ipv6AddrEntry, 3,
  204.      {7, 1, 4}},
  205.     {IPV6ADDRPREFIXADVPREFERLIFE, UNSIGNED32, RONLY, var_ipv6AddrEntry, 3,
  206.      {7, 1, 5}},
  207.     {IPV6ADDRPREFIXVALIDLIFE, UNSIGNED32, RONLY, var_ipv6AddrEntry, 3,
  208.      {7, 1, 6}},
  209.     {IPV6ADDRPFXLEN, INTEGER, RONLY, var_ipv6AddrEntry, 3, {8, 1, 2}},
  210.     {IPV6ADDRTYPE, INTEGER, RONLY, var_ipv6AddrEntry, 3, {8, 1, 3}},
  211.     {IPV6ADDRANYCASTFLAG, INTEGER, RONLY, var_ipv6AddrEntry, 3, {8, 1, 4}},
  212.     {IPV6ADDRSTATUS, INTEGER, RONLY, var_ipv6AddrEntry, 3, {8, 1, 5}},
  213.     {IPV6ROUTEIFINDEX, IpV6IFINDEX, RONLY, var_ipv6RouteEntry, 3,
  214.      {11, 1, 4}},
  215.     {IPV6ROUTENEXTHOP, IpV6ADDRESS, RONLY, var_ipv6RouteEntry, 3,
  216.      {11, 1, 5}},
  217.     {IPV6ROUTETYPE, INTEGER, RONLY, var_ipv6RouteEntry, 3, {11, 1, 6}},
  218.     {IPV6ROUTEPROTOCOL, INTEGER, RONLY, var_ipv6RouteEntry, 3, {11, 1, 7}},
  219.     {IPV6ROUTEPOLICY, UNSIGNED32, RONLY, var_ipv6RouteEntry, 3,
  220.      {11, 1, 8}},
  221.     {IPV6ROUTEAGE, UNSIGNED32, RONLY, var_ipv6RouteEntry, 3, {11, 1, 9}},
  222.     {IPV6ROUTENEXTHOPRDI, UNSIGNED32, RONLY, var_ipv6RouteEntry, 3,
  223.      {11, 1, 10}},
  224.     {IPV6ROUTEMETRIC, UNSIGNED32, RONLY, var_ipv6RouteEntry, 3,
  225.      {11, 1, 11}},
  226.     {IPV6ROUTEWEIGHT, UNSIGNED32, RONLY, var_ipv6RouteEntry, 3,
  227.      {11, 1, 12}},
  228.     {IPV6ROUTEINFO, OBJID, RONLY, var_ipv6RouteEntry, 3, {11, 1, 13}},
  229.     {IPV6ROUTEVALID, INTEGER, RONLY, var_ipv6RouteEntry, 3, {11, 1, 14}},
  230.     {IPV6NETTOMEDIAPHYADDR, STRING, RONLY, var_ndpEntry, 3, {12, 1, 2}},
  231.     {IPV6NETTOMEDIATYPE, INTEGER, RONLY, var_ndpEntry, 3, {12, 1, 3}},
  232.     {IPV6NETTOMEDIASTATE, INTEGER, RONLY, var_ndpEntry, 3, {12, 1, 4}},
  233.     {IPV6NETTOMEDIALASTUPDATE, TIMETICKS, RONLY, var_ndpEntry, 3,
  234.      {12, 1, 5}},
  235.     {IPV6NETTOMEDIAVALID, INTEGER, RONLY, var_ndpEntry, 3, {12, 1, 6}},
  236. #endif
  237. };
  238. oid             ipv6_variables_oid[] = { SNMP_OID_MIB2, 55, 1 };
  239. #if 0
  240. config_load_mib(MIB .55 .1, 8, ipv6_variables)
  241.     config_add_mib(IPV6 - TC)
  242.     config_add_mib(IPV6 - MIB)
  243. #endif
  244.      struct variable3 ipv6icmp_variables[] = {
  245.          {IPV6IFICMPINMSG, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  246.           {1, 1, 1}},
  247.          {IPV6IFICMPINERRORS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  248.           {1, 1, 2}},
  249.          {IPV6IFICMPINDSTUNRCHS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  250.           {1, 1, 3}},
  251.          {IPV6IFICMPINADMPROHS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  252.           {1, 1, 4}},
  253.          {IPV6IFICMPINTIMEXCDS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  254.           {1, 1, 5}},
  255.          {IPV6IFICMPINPARMPROBS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  256.           {1, 1, 6}},
  257.          {IPV6IFICMPINPKTTOOBIGS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  258.           {1, 1, 7}},
  259.          {IPV6IFICMPINECHOS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  260.           {1, 1, 8}},
  261.          {IPV6IFICMPINECHOREPS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  262.           {1, 1, 9}},
  263.          {IPV6IFICMPINRTRSLICITS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  264.           {1, 1, 10}},
  265.          {IPV6IFICMPINRTRADVS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  266.           {1, 1, 11}},
  267.          {IPV6IFICMPINNBRSLICITS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  268.           {1, 1, 12}},
  269.          {IPV6IFICMPINNBRADVS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  270.           {1, 1, 13}},
  271.          {IPV6IFICMPINREDIRECTS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  272.           {1, 1, 14}},
  273.          {IPV6IFICMPINGRPMEQERYS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  274.           {1, 1, 15}},
  275.          {IPV6IFICMPINGRPMERSPS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  276.           {1, 1, 16}},
  277.          {IPV6IFICMPINGRPMEREDCS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  278.           {1, 1, 17}},
  279.          {IPV6IFICMPOUTMSG, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  280.           {1, 1, 18}},
  281.          {IPV6IFICMPOUTERRORS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  282.           {1, 1, 19}},
  283.          {IPV6IFICMPOUTDSTUNRCHS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  284.           {1, 1, 20}},
  285.          {IPV6IFICMPOUTADMPROHS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  286.           {1, 1, 21}},
  287.          {IPV6IFICMPOUTTIMEXCDS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  288.           {1, 1, 22}},
  289.          {IPV6IFICMPOUTPARMPROBS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  290.           {1, 1, 23}},
  291.          {IPV6IFICMPOUTPKTTOOBIGS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  292.           {1, 1, 24}},
  293.          {IPV6IFICMPOUTECHOS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  294.           {1, 1, 25}},
  295.          {IPV6IFICMPOUTECHOREPS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  296.           {1, 1, 26}},
  297.          {IPV6IFICMPOUTRTRSLICITS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  298.           {1, 1, 27}},
  299.          {IPV6IFICMPOUTRTRADVS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  300.           {1, 1, 28}},
  301.          {IPV6IFICMPOUTNBRSLICITS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  302.           {1, 1, 29}},
  303.          {IPV6IFICMPOUTNBRADVS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  304.           {1, 1, 30}},
  305.          {IPV6IFICMPOUTREDIRECTS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  306.           {1, 1, 31}},
  307.          {IPV6IFICMPOUTGRPMEQERYS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  308.           {1, 1, 32}},
  309.          {IPV6IFICMPOUTGRPMERSPS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  310.           {1, 1, 33}},
  311.          {IPV6IFICMPOUTGRPMEREDCS, ASN_COUNTER, RONLY, var_icmpv6Entry, 3,
  312.           {1, 1, 34}}
  313.      };
  314. oid             ipv6icmp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 56, 1 };
  315. #if 0
  316. config_load_mib(MIB .56 .1, 8, ipv6icmp_variables)
  317.     config_add_mib(IPV6 - ICMP - MIB)
  318. #endif
  319.      struct variable2 ipv6udp_variables[] = {
  320.          {IPV6UDPLOCALADDRESS, ASN_OCTET_STR, RONLY, var_udp6, 2, {1, 1}},
  321.          {IPV6UDPLOCALPORT, ASN_INTEGER, RONLY, var_udp6, 2, {1, 2}},
  322.          {IPV6UDPIFINDEX, ASN_INTEGER, RONLY, var_udp6, 2, {1, 3}}
  323.      };
  324. oid             ipv6udp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 7, 6 };
  325. #if 0
  326. config_load_mib(1.3 .6 .1 .3 .87 .1, 7, ipv6udp_variables)
  327.     config_add_mib(IPV6 - UDP - MIB)
  328. #endif
  329.      struct variable2 ipv6tcp_variables[] = {
  330.          {IPV6TCPLOCALADDR, ASN_OCTET_STR, RONLY, var_tcp6, 2, {1, 1}},
  331.          {IPV6TCPLOCALPORT, ASN_INTEGER, RONLY, var_tcp6, 2, {1, 2}},
  332.          {IPV6TCPREMOTEADDR, ASN_OCTET_STR, RONLY, var_tcp6, 2, {1, 3}},
  333.          {IPV6TCPREMOTEPORT, ASN_INTEGER, RONLY, var_tcp6, 2, {1, 4}},
  334.          {IPV6TCPIFINDEX, ASN_INTEGER, RONLY, var_tcp6, 2, {1, 5}},
  335.          {IPV6TCPCONNSTATE, ASN_INTEGER, RONLY, var_tcp6, 2, {1, 6}},
  336.      };
  337. oid             ipv6tcp_variables_oid[] = { 1, 3, 6, 1, 2, 1, 6, 16 };
  338. #if 0
  339. config_load_mib(1.3 .6 .1 .3 .86 .1, 7, ipv6tcp_variables)
  340.     config_add_mib(IPV6 - TCP - MIB)
  341. #endif
  342.      void
  343.                      init_ipv6()
  344. {
  345.     /*
  346.      * register ourselves with the agent to handle our mib tree 
  347.      */
  348.     REGISTER_MIB("mibII/ipv6", ipv6_variables, variable3,
  349.                  ipv6_variables_oid);
  350.     REGISTER_MIB("mibII/icmpv6", ipv6icmp_variables, variable3,
  351.                  ipv6icmp_variables_oid);
  352.     REGISTER_MIB("mibII/ipv6udp", ipv6udp_variables, variable2,
  353.                  ipv6udp_variables_oid);
  354.     REGISTER_MIB("mibII/ipv6tcp", ipv6tcp_variables, variable2,
  355.                  ipv6tcp_variables_oid);
  356. }
  357. static int
  358. header_ipv6(register struct variable *vp,
  359.             /*
  360.              * IN - pointer to variable entry that points here 
  361.              */
  362.             oid * name,         /* IN/OUT - input name requested, output name found */
  363.             size_t * length,    /* IN/OUT - length of input and output oid's */
  364.             int exact,          /* IN - TRUE if an exact match was requested */
  365.             size_t * var_len,   /* OUT - length of variable or 0 if function returned */
  366.             WriteMethod ** write_method)
  367. {
  368.     oid             newname[MAX_OID_LEN];
  369.     int             result;
  370.     DEBUGMSGTL(("mibII/ipv6", "header_ipv6: "));
  371.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  372.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  373.     memcpy((char *) newname, (char *) vp->name,
  374.            (int) vp->namelen * sizeof(oid));
  375.     newname[(int) vp->namelen] = 0;
  376.     result =
  377.         snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
  378.     if ((exact && (result != 0)) || (!exact && (result >= 0)))
  379.         return (MATCH_FAILED);
  380.     memcpy((char *) name, (char *) newname,
  381.            ((int) vp->namelen + 1) * sizeof(oid));
  382.     *length = vp->namelen + 1;
  383.     *write_method = 0;
  384.     *var_len = sizeof(long);    /* default to 'long' results */
  385.     return (MATCH_SUCCEEDED);
  386. }
  387. static int
  388. header_ipv6_scan(register struct variable *vp,
  389.                  /*
  390.                   * IN - pointer to variable entry that points here 
  391.                   */
  392.                  oid * name,    /* IN/OUT - input name requested, output name found */
  393.                  size_t * length,       /* IN/OUT - length of input and output oid's */
  394.                  int exact,     /* IN - TRUE if an exact match was requested */
  395.                  size_t * var_len,      /* OUT - length of variable or 0 if function returned */
  396.                  WriteMethod ** write_method, int from, int to)
  397. {
  398.     oid             newname[MAX_OID_LEN];
  399.     int             result;
  400.     int             i;
  401.     DEBUGMSGTL(("mibII/ipv6", "header_ipv6_scan: "));
  402.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  403.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  404.     memcpy((char *) newname, (char *) vp->name,
  405.            (int) vp->namelen * sizeof(oid));
  406.     for (i = from; i <= to; i++) {
  407.         newname[(int) vp->namelen] = i;
  408.         result =
  409.             snmp_oid_compare(name, *length, newname,
  410.                              (int) vp->namelen + 1);
  411.         if (((exact && result == 0) || (!exact && result < 0))
  412.             && if_getname(i))
  413.             break;
  414.     }
  415.     if (to < i)
  416.         return (MATCH_FAILED);
  417.     memcpy((char *) name, (char *) newname,
  418.            ((int) vp->namelen + 1) * sizeof(oid));
  419.     *length = vp->namelen + 1;
  420.     *write_method = 0;
  421.     *var_len = sizeof(long);    /* default to 'long' results */
  422.     return (MATCH_SUCCEEDED);
  423. }
  424. static struct if_nameindex *ifnames = NULL;
  425. #ifdef linux
  426. static void     linux_if_freenameindex(struct if_nameindex *);
  427. static struct if_nameindex *linux_if_nameindex(void);
  428. #endif
  429. static int
  430. if_initialize(void)
  431. {
  432. #ifndef HAVE_IF_NAMEINDEX
  433.     return -1;
  434. #else
  435. #ifndef linux
  436.     if (ifnames)
  437.         if_freenameindex(ifnames);
  438.     ifnames = if_nameindex();
  439. #else
  440.     if (ifnames)
  441.         linux_if_freenameindex(ifnames);
  442.     ifnames = linux_if_nameindex();
  443. #endif
  444.     if (!ifnames) {
  445.         ERROR_MSG("if_nameindex() failed");
  446.         return -1;
  447.     }
  448.     return 0;
  449. #endif
  450. }
  451. static int
  452. if_maxifindex(void)
  453. {
  454. #ifndef HAVE_IF_NAMEINDEX
  455.     return -1;
  456. #else
  457.     struct if_nameindex *p;
  458.     int             max = 0;
  459.     if (!ifnames) {
  460.         if (if_initialize() < 0)
  461.             return -1;
  462.     }
  463.     for (p = ifnames; p && p->if_index; p++) {
  464.         if (max < p->if_index)
  465.             max = p->if_index;
  466.     }
  467.     return max;
  468. #endif
  469. }
  470. static int
  471. if_countifindex(void)
  472. {
  473. #ifndef HAVE_IF_NAMEINDEX
  474.     return -1;
  475. #else
  476.     struct if_nameindex *p;
  477.     int             count = 0;
  478.     if (!ifnames) {
  479.         if (if_initialize() < 0)
  480.             return -1;
  481.     }
  482.     for (p = ifnames; p && p->if_index; p++) {
  483.         count++;
  484.     }
  485.     return count;
  486. #endif
  487. }
  488. static char    *
  489. if_getname(int idx)
  490. {
  491. #ifndef HAVE_IF_NAMEINDEX
  492.     return NULL;
  493. #else
  494.     struct if_nameindex *p;
  495.     if (!ifnames) {
  496.         if (if_initialize() < 0)
  497.             return NULL;
  498.     }
  499.     for (p = ifnames; p && p->if_index; p++) {
  500.         if (p->if_index == idx)
  501.             return p->if_name;
  502.     }
  503.     return NULL;
  504. #endif
  505. }
  506. #ifdef notused
  507. static int
  508. if_getindex(const char *name)
  509. {
  510. #ifndef HAVE_IF_NAMEINDEX
  511.     return -1;
  512. #else
  513.     struct if_nameindex *p;
  514.     if (!ifnames) {
  515.         if (if_initialize() < 0)
  516.             return -1;
  517.     }
  518.     for (p = ifnames; p && p->if_index; p++) {
  519.         if (strcmp(name, p->if_name) == 0)
  520.             return p->if_index;
  521.     }
  522.     return -1;
  523. #endif
  524. }
  525. #endif /* notused */
  526. /*------------------------------------------------------------*/
  527. #ifndef linux
  528. /*
  529.  * KAME dependent part 
  530.  */
  531. static int
  532. if_getifnet(int idx, struct ifnet *result)
  533. {
  534.     caddr_t         q;
  535.     struct ifnet    tmp;
  536.     if (!auto_nlist("ifnet", (char *) &q, sizeof(q)))
  537.         return -1;
  538.     while (q) {
  539.         klookup((u_long) q, (char *) &tmp, sizeof(tmp));
  540.         if (idx == tmp.if_index) {
  541.             memcpy(result, &tmp, sizeof(tmp));
  542.             return 0;
  543.         }
  544. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  545.         q = (caddr_t) TAILQ_NEXT(&tmp, if_link);
  546. #else
  547. # if defined(__NetBSD__) || defined(__OpenBSD__)
  548.         q = (caddr_t) TAILQ_NEXT(&tmp, if_list);
  549. # else
  550.         q = (caddr_t) tmp.if_next;
  551. # endif
  552. #endif
  553.     }
  554.     return -1;
  555. }
  556. #if TRUST_IFLASTCHANGE         /*untrustable value returned... */
  557. #ifdef HAVE_NET_IF_MIB_H
  558. #if defined(HAVE_SYS_SYSCTL_H) && defined(CTL_NET)
  559. static int
  560. if_getifmibdata(int idx, struct ifmibdata *result)
  561. {
  562.     int             mib[6] = {
  563.         CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL
  564.     };
  565.     size_t           len;
  566.     struct ifmibdata tmp;
  567.     mib[4] = idx;
  568.     len = sizeof(struct ifmibdata);
  569.     if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &tmp, &len, 0, 0) < 0)
  570.         return -1;
  571.     memcpy(result, &tmp, sizeof(tmp));
  572.     return 0;
  573. }
  574. #endif
  575. #endif                          /*HAVE_NET_IF_MIB_H */
  576. #endif  /* TRUST_IFLASTCHANGE */
  577. #ifdef __KAME__
  578. #define IPV6_FORWARDING_SYMBOL "ip6_forwarding"
  579. #define IPV6_DEFHLIM_SYMBOL "ip6_defhlim"
  580. #endif
  581. u_char         *
  582. var_ipv6(register struct variable * vp,
  583.          oid * name,
  584.          size_t * length,
  585.          int exact, size_t * var_len, WriteMethod ** write_method)
  586. {
  587.     int             i;
  588.     if (header_ipv6(vp, name, length, exact, var_len, write_method)
  589.         == MATCH_FAILED) {
  590.         return NULL;
  591.     }
  592. #if defined(HAVE_SYS_SYSCTL_H) && defined(CTL_NET)
  593.     /*
  594.      * try with sysctl routines 
  595.      */
  596.     {
  597.         int             name[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
  598.         const char     *namestr = NULL;
  599.         int             result;
  600.         size_t          resultsiz;
  601.         resultsiz = sizeof(result);
  602.         switch (vp->magic) {
  603.         case IPV6FORWARDING:
  604.             name[3] = IPV6CTL_FORWARDING;
  605.             namestr = "IPV6CTL_FORWARDING";
  606.             if (sysctl
  607.                 (name, sizeof(name) / sizeof(name[0]), &result, &resultsiz,
  608.                  0, 0) < 0) {
  609.                 DEBUGMSGTL(("mibII/ipv6",
  610.                             "sysctl(CTL_NET, PF_INET6, IPPROTO_IPV6, %s)n",
  611.                             namestr));
  612.                 break;
  613.             } else {
  614.                 if (result)
  615.                     long_return = 1;    /* GATEWAY */
  616.                 else
  617.                     long_return = 2;    /* HOST */
  618.                 return (u_char *) & long_return;
  619.             }
  620.             break;
  621.         case IPV6DEFAULTHOPLIMIT:
  622.             name[3] = IPV6CTL_DEFHLIM;
  623.             namestr = "IPV6CTL_DEFHLIM";
  624.             if (sysctl
  625.                 (name, sizeof(name) / sizeof(name[0]), &result, &resultsiz,
  626.                  0, 0) < 0) {
  627.                 DEBUGMSGTL(("mibII/ipv6",
  628.                             "sysctl(CTL_NET, PF_INET6, IPPROTO_IPV6, %s)n",
  629.                             namestr));
  630.                 break;
  631.             } else {
  632.                 long_return = result;
  633.                 return (u_char *) & long_return;
  634.             }
  635.         }
  636.     }
  637. #endif                          /* not (HAVE_SYS_SYSCTL_H && CTL_NET) */
  638.     /*
  639.      * try looking into the kernel variable 
  640.      */
  641.     switch (vp->magic) {
  642. #ifdef IPV6_FORWARDING_SYMBOL
  643.     case IPV6FORWARDING:
  644.         if (auto_nlist(IPV6_FORWARDING_SYMBOL, (char *) &i, sizeof(i))) {
  645.             if (i)
  646.                 long_return = 1;
  647.             /*GATEWAY*/
  648.             else
  649.                 long_return = 2;
  650.             /*HOST*/ return (u_char *) & long_return;
  651.         }
  652.         break;
  653. #endif
  654. #ifdef IPV6_DEFHLIM_SYMBOL
  655.     case IPV6DEFAULTHOPLIMIT:
  656.         if (auto_nlist(IPV6_DEFHLIM_SYMBOL, (char *) &i, sizeof(i))) {
  657.             long_return = i;
  658.             return (u_char *) & long_return;
  659.         }
  660.         break;
  661. #endif
  662.     case IPV6INTERFACES:
  663. #ifdef HAVE_IF_NAMEINDEX
  664.         /*
  665.          * not really the right answer... we must count IPv6 capable
  666.          * interfaces only.
  667.          */
  668.         long_return = if_countifindex();
  669.         if (long_return < 0)
  670.             break;
  671.         return (u_char *) & long_return;
  672. #endif
  673.         break;
  674. #if 0
  675.     case IPV6IFTBLLASTCHG:
  676.         long_return = 0;
  677.         /*XXX*/ return (u_char *) & long_return;
  678. #endif
  679.     default:
  680.         break;
  681.     }
  682.     ERROR_MSG("");
  683.     return NULL;
  684. }
  685. u_char         *
  686. var_ifv6Entry(register struct variable * vp,
  687.               oid * name,
  688.               size_t * length,
  689.               int exact, size_t * var_len, WriteMethod ** write_method)
  690. {
  691. #ifndef HAVE_IF_NAMEINDEX
  692.     return NULL;
  693. #else
  694.     int             interface;
  695.     int             max;
  696.     char           *p;
  697.     max = if_maxifindex();
  698.     if (max < 0)
  699.         return NULL;
  700.     if (header_ipv6_scan
  701.         (vp, name, length, exact, var_len, write_method, 1, max)
  702.         == MATCH_FAILED) {
  703.         return NULL;
  704.     }
  705.     interface = name[*length - 1];
  706.     DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)n",
  707.                 interface, if_getname(interface)));
  708.     if (interface > max)
  709.         return NULL;
  710.     switch (vp->magic) {
  711.     case IPV6IFDESCR:
  712.         p = if_getname(interface);
  713.         if (p) {
  714.             *var_len = strlen(p);
  715.             return p;
  716.         }
  717.         break;
  718.     case IPV6IFLOWLAYER:
  719.         /*
  720.          * should check if type, this is a hard one... 
  721.          */
  722.         *var_len = nullOidLen;
  723.         return (u_char *) nullOid;
  724.     case IPV6IFEFFECTMTU:
  725.         {
  726. #if defined(SIOCGIFMTU) && !defined(__OpenBSD__)
  727.             struct ifreq    ifr;
  728.             int             s;
  729.             memset(&ifr, 0, sizeof(ifr));
  730.             ifr.ifr_addr.sa_family = AF_INET6;
  731.             strncpy(ifr.ifr_name, if_getname(interface),
  732.                     sizeof(ifr.ifr_name));
  733.             if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
  734.                 break;
  735.             if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0) {
  736.                 close(s);
  737.                 break;
  738.             }
  739.             long_return = ifr.ifr_mtu;
  740.             close(s);
  741.             return (u_char *) & long_return;
  742. #else
  743.             break;
  744. #endif
  745.         }
  746. #if 0                           /*not yet */
  747.     case IPV6IFREASMMAXSIZE:
  748.         /*
  749.          * I dunno what the spec means for this MIB 
  750.          */
  751.     case IPV6IFTOKEN:
  752.     case IPV6IFTOKENLEN:
  753. #endif
  754.     case IPV6IFPHYSADDRESS:
  755.         {
  756.             struct ifnet    ifnet;
  757.             struct ifaddr   ifaddr;
  758.             static struct sockaddr_dl sdl;
  759.             caddr_t         ifa;
  760.             if (if_getifnet(interface, &ifnet) < 0)
  761.                 break;
  762. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  763.             ifa = (caddr_t) TAILQ_FIRST(&ifnet.if_addrhead);
  764. #else
  765. # if defined(__NetBSD__) || defined(__OpenBSD__)
  766.             ifa = (caddr_t) TAILQ_FIRST(&ifnet.if_addrlist);
  767. # else
  768.             ifa = (caddr_t) ifnet.if_addrlist;
  769. # endif
  770. #endif
  771.             while (ifa) {
  772.                 klookup((u_long) ifa, (char *) &ifaddr, sizeof(ifaddr));
  773.                 klookup((u_long) ifaddr.ifa_addr, (char *) &sdl,
  774.                         sizeof(sdl));
  775.                 if (sdl.sdl_family == AF_LINK) {
  776.                     if (sizeof(sdl.sdl_data) < sdl.sdl_nlen + sdl.sdl_alen) {
  777.                         ERROR_MSG("sdl_alen too long for interfacen");
  778.                         break;
  779.                     }
  780.                     *var_len = sdl.sdl_alen;
  781.                     return (u_char *) (sdl.sdl_data + sdl.sdl_nlen);
  782.                 }
  783. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  784.                 ifa = (caddr_t) TAILQ_NEXT(&ifaddr, ifa_link);
  785. #else
  786. # if defined(__NetBSD__) || defined(__OpenBSD__)
  787.                 ifa = (caddr_t) TAILQ_NEXT(&ifaddr, ifa_list);
  788. # else
  789.                 ifa = (caddr_t) ifaddr.ifa_next;
  790. # endif
  791. #endif
  792.             }
  793.             /*
  794.              * no physical address found 
  795.              */
  796.             *var_len = 0;
  797.             return NULL;
  798.         }
  799.     case IPV6IFADMSTATUS:
  800.         {
  801.             struct ifnet    ifnet;
  802.             if (if_getifnet(interface, &ifnet) < 0)
  803.                 break;
  804.             long_return = (ifnet.if_flags & IFF_RUNNING) ? 1 : 2;
  805.             return (u_char *) & long_return;
  806.         }
  807.     case IPV6IFOPERSTATUS:
  808.         {
  809.             struct ifnet    ifnet;
  810.             if (if_getifnet(interface, &ifnet) < 0)
  811.                 break;
  812.             long_return = (ifnet.if_flags & IFF_UP) ? 1 : 2;
  813.             return (u_char *) & long_return;
  814.         }
  815. #if TRUST_IFLASTCHANGE         /*untrustable value returned... */
  816.     case IPV6IFLASTCHANGE:
  817.         {
  818.             struct timeval  lastchange;
  819.             struct timeval  now;
  820.             int             gotanswer;
  821.             gotanswer = 0;
  822.             lastchange.tv_sec = lastchange.tv_usec = 0;
  823. #ifdef HAVE_NET_IF_MIB_H
  824.             if (!gotanswer) {
  825.                 struct ifmibdata ifmd;
  826.                 if (if_getifmibdata(interface, &ifmd) < 0);
  827.                 else {
  828.                     lastchange = ifmd.ifmd_data.ifi_lastchange;
  829.                     gotanswer++;
  830.                 }
  831.             }
  832. #endif
  833. #ifdef STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
  834.             if (!gotanswer) {
  835.                 struct ifnet    ifnet;
  836.                 if (if_getifnet(interface, &ifnet) < 0);
  837.                 else {
  838.                     lastchange = ifnet.if_lastchange;
  839.                     gotanswer++;
  840.                 }
  841.             }
  842. #endif
  843.             DEBUGMSGTL(("mibII/ipv6", "lastchange = { %d.%06d }n",
  844.                         lastchange.tv_sec, lastchange.tv_usec));
  845.             if (lastchange.tv_sec == 0 && lastchange.tv_usec == 0)
  846.                 long_return = 0;
  847.             else {
  848.                 gettimeofday(&now, (struct timezone *) NULL);
  849.                 long_return =
  850.                     (u_long) ((now.tv_sec - lastchange.tv_sec) * 100);
  851.                 long_return +=
  852.                     (u_long) ((now.tv_usec - lastchange.tv_usec) / 10000);
  853.             }
  854.             return (u_char *) & long_return;
  855.         }
  856. #endif  /* TRUST_IFLASTCHANGE */
  857. #ifdef SIOCGIFSTAT_IN6
  858.     case IPV6IFSTATSINRCVS:
  859.     case IPV6IFSTATSINHDRERRS:
  860.     case IPV6IFSTATSTOOBIGERRS:
  861.     case IPV6IFSTATSINNOROUTES:
  862.     case IPV6IFSTATSINADDRERRS:
  863.     case IPV6IFSTATSINUNKNOWPROTS:
  864.     case IPV6IFSTATSINTRUNCATPKTS:
  865.     case IPV6IFSTATSINDISCARDS:
  866.     case IPV6IFSTATSINDELIVERS:
  867.     case IPV6IFSTATSOUTFORWDATAS:
  868.     case IPV6IFSTATSOUTREQS:
  869.     case IPV6IFSTATSOUTDISCARDS:
  870.     case IPV6IFSTATSOUTFRAGOKS:
  871.     case IPV6IFSTATSOUTFRAGFAILS:
  872.     case IPV6IFSTATSOUTFRAGCREATS:
  873.     case IPV6IFSTATSOUTREASMREQS:
  874.     case IPV6IFSTATSOUTREASMOKS:
  875.     case IPV6IFSTATSOUTREASMFAILS:
  876.     case IPV6IFSTATSINMCASTPKTS:
  877.     case IPV6IFSTATSOUTMCASTPKTS:
  878.         {
  879.             struct in6_ifstat *ifs6;
  880.             struct in6_ifreq ifr;
  881.             int             s;
  882.             memset(&ifr, 0, sizeof(ifr));
  883.             strncpy(ifr.ifr_name, if_getname(interface),
  884.                     sizeof(ifr.ifr_name));
  885.             if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
  886.                 break;
  887.             if (ioctl(s, SIOCGIFSTAT_IN6, (caddr_t) & ifr) < 0) {
  888.                 close(s);
  889.                 break;
  890.             }
  891.             close(s);
  892.             ifs6 = &ifr.ifr_ifru.ifru_stat;
  893.             switch (vp->magic) {
  894.             case IPV6IFSTATSINRCVS:
  895.                 long_return = ifs6->ifs6_in_receive;
  896.                 break;
  897.             case IPV6IFSTATSINHDRERRS:
  898.                 long_return = ifs6->ifs6_in_hdrerr;
  899.                 break;
  900.             case IPV6IFSTATSTOOBIGERRS:
  901.                 long_return = ifs6->ifs6_in_toobig;
  902.                 break;
  903.             case IPV6IFSTATSINNOROUTES:
  904.                 long_return = ifs6->ifs6_in_noroute;
  905.                 break;
  906.             case IPV6IFSTATSINADDRERRS:
  907.                 long_return = ifs6->ifs6_in_addrerr;
  908.                 break;
  909.             case IPV6IFSTATSINUNKNOWPROTS:
  910.                 long_return = ifs6->ifs6_in_protounknown;
  911.                 break;
  912.             case IPV6IFSTATSINTRUNCATPKTS:
  913.                 long_return = ifs6->ifs6_in_truncated;
  914.                 break;
  915.             case IPV6IFSTATSINDISCARDS:
  916.                 long_return = ifs6->ifs6_in_discard;
  917.                 break;
  918.             case IPV6IFSTATSINDELIVERS:
  919.                 long_return = ifs6->ifs6_in_deliver;
  920.                 break;
  921.             case IPV6IFSTATSOUTFORWDATAS:
  922.                 long_return = ifs6->ifs6_out_forward;
  923.                 break;
  924.             case IPV6IFSTATSOUTREQS:
  925.                 long_return = ifs6->ifs6_out_request;
  926.                 break;
  927.             case IPV6IFSTATSOUTDISCARDS:
  928.                 long_return = ifs6->ifs6_out_discard;
  929.                 break;
  930.             case IPV6IFSTATSOUTFRAGOKS:
  931.                 long_return = ifs6->ifs6_out_fragok;
  932.                 break;
  933.             case IPV6IFSTATSOUTFRAGFAILS:
  934.                 long_return = ifs6->ifs6_out_fragfail;
  935.                 break;
  936.             case IPV6IFSTATSOUTFRAGCREATS:
  937.                 long_return = ifs6->ifs6_out_fragcreat;
  938.                 break;
  939.             case IPV6IFSTATSOUTREASMREQS:
  940.                 long_return = ifs6->ifs6_reass_reqd;
  941.                 break;
  942.             case IPV6IFSTATSOUTREASMOKS:
  943.                 long_return = ifs6->ifs6_reass_ok;
  944.                 break;
  945.             case IPV6IFSTATSOUTREASMFAILS:
  946.                 long_return = ifs6->ifs6_reass_fail;
  947.                 break;
  948.             case IPV6IFSTATSINMCASTPKTS:
  949.                 long_return = ifs6->ifs6_in_mcast;
  950.                 break;
  951.             case IPV6IFSTATSOUTMCASTPKTS:
  952.                 long_return = ifs6->ifs6_out_mcast;
  953.                 break;
  954.             default:
  955.                 return NULL;
  956.             }
  957.             return (u_char *) & long_return;
  958.         }
  959. #endif
  960.     default:
  961.         break;
  962.     }
  963.     return NULL;
  964. #endif
  965. }
  966. u_char         *
  967. var_icmpv6Entry(register struct variable * vp,
  968.                 oid * name,
  969.                 size_t * length,
  970.                 int exact, size_t * var_len, WriteMethod ** write_method)
  971. {
  972. #ifndef HAVE_IF_NAMEINDEX
  973.     return NULL;
  974. #else
  975.     int             interface;
  976.     int             max;
  977.     max = if_maxifindex();
  978.     if (max < 0)
  979.         return NULL;
  980.     if (header_ipv6_scan
  981.         (vp, name, length, exact, var_len, write_method, 1, max)
  982.         == MATCH_FAILED) {
  983.         return NULL;
  984.     }
  985.     interface = name[*length - 1];
  986.     DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)n",
  987.                 interface, if_getname(interface)));
  988.     if (interface >= max)
  989.         return NULL;
  990.     switch (vp->magic) {
  991. #ifdef SIOCGIFSTAT_ICMP6
  992.     case IPV6IFICMPINMSG:
  993.     case IPV6IFICMPINERRORS:
  994.     case IPV6IFICMPINDSTUNRCHS:
  995.     case IPV6IFICMPINADMPROHS:
  996.     case IPV6IFICMPINTIMEXCDS:
  997.     case IPV6IFICMPINPARMPROBS:
  998.     case IPV6IFICMPINPKTTOOBIGS:
  999.     case IPV6IFICMPINECHOS:
  1000.     case IPV6IFICMPINECHOREPS:
  1001.     case IPV6IFICMPINRTRSLICITS:
  1002.     case IPV6IFICMPINRTRADVS:
  1003.     case IPV6IFICMPINNBRSLICITS:
  1004.     case IPV6IFICMPINNBRADVS:
  1005.     case IPV6IFICMPINREDIRECTS:
  1006.     case IPV6IFICMPINGRPMEQERYS:
  1007.     case IPV6IFICMPINGRPMERSPS:
  1008.     case IPV6IFICMPINGRPMEREDCS:
  1009.     case IPV6IFICMPOUTMSG:
  1010.     case IPV6IFICMPOUTERRORS:
  1011.     case IPV6IFICMPOUTDSTUNRCHS:
  1012.     case IPV6IFICMPOUTADMPROHS:
  1013.     case IPV6IFICMPOUTTIMEXCDS:
  1014.     case IPV6IFICMPOUTPARMPROBS:
  1015.     case IPV6IFICMPOUTPKTTOOBIGS:
  1016.     case IPV6IFICMPOUTECHOS:
  1017.     case IPV6IFICMPOUTECHOREPS:
  1018.     case IPV6IFICMPOUTRTRSLICITS:
  1019.     case IPV6IFICMPOUTRTRADVS:
  1020.     case IPV6IFICMPOUTNBRSLICITS:
  1021.     case IPV6IFICMPOUTNBRADVS:
  1022.     case IPV6IFICMPOUTREDIRECTS:
  1023.     case IPV6IFICMPOUTGRPMEQERYS:
  1024.     case IPV6IFICMPOUTGRPMERSPS:
  1025.     case IPV6IFICMPOUTGRPMEREDCS:
  1026.         {
  1027.             struct icmp6_ifstat *ifs6;
  1028.             struct in6_ifreq ifr;
  1029.             int             s;
  1030.             memset(&ifr, 0, sizeof(ifr));
  1031.             strncpy(ifr.ifr_name, if_getname(interface),
  1032.                     sizeof(ifr.ifr_name));
  1033.             if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
  1034.                 break;
  1035.             if (ioctl(s, SIOCGIFSTAT_ICMP6, (caddr_t) & ifr) < 0) {
  1036.                 close(s);
  1037.                 break;
  1038.             }
  1039.             close(s);
  1040.             ifs6 = &ifr.ifr_ifru.ifru_icmp6stat;
  1041.             switch (vp->magic) {
  1042.             case IPV6IFICMPINMSG:
  1043.                 long_return = ifs6->ifs6_in_msg;
  1044.                 break;
  1045.             case IPV6IFICMPINERRORS:
  1046.                 long_return = ifs6->ifs6_in_error;
  1047.                 break;
  1048.             case IPV6IFICMPINDSTUNRCHS:
  1049.                 long_return = ifs6->ifs6_in_dstunreach;
  1050.                 break;
  1051.             case IPV6IFICMPINADMPROHS:
  1052.                 long_return = ifs6->ifs6_in_adminprohib;
  1053.                 break;
  1054.             case IPV6IFICMPINTIMEXCDS:
  1055.                 long_return = ifs6->ifs6_in_timeexceed;
  1056.                 break;
  1057.             case IPV6IFICMPINPARMPROBS:
  1058.                 long_return = ifs6->ifs6_in_paramprob;
  1059.                 break;
  1060.             case IPV6IFICMPINPKTTOOBIGS:
  1061.                 long_return = ifs6->ifs6_in_pkttoobig;
  1062.                 break;
  1063.             case IPV6IFICMPINECHOS:
  1064.                 long_return = ifs6->ifs6_in_echo;
  1065.                 break;
  1066.             case IPV6IFICMPINECHOREPS:
  1067.                 long_return = ifs6->ifs6_in_echoreply;
  1068.                 break;
  1069.             case IPV6IFICMPINRTRSLICITS:
  1070.                 long_return = ifs6->ifs6_in_routersolicit;
  1071.                 break;
  1072.             case IPV6IFICMPINRTRADVS:
  1073.                 long_return = ifs6->ifs6_in_routeradvert;
  1074.                 break;
  1075.             case IPV6IFICMPINNBRSLICITS:
  1076.                 long_return = ifs6->ifs6_in_neighborsolicit;
  1077.                 break;
  1078.             case IPV6IFICMPINNBRADVS:
  1079.                 long_return = ifs6->ifs6_in_neighboradvert;
  1080.                 break;
  1081.             case IPV6IFICMPINREDIRECTS:
  1082.                 long_return = ifs6->ifs6_in_redirect;
  1083.                 break;
  1084.             case IPV6IFICMPINGRPMEQERYS:
  1085.                 long_return = ifs6->ifs6_in_mldquery;
  1086.                 break;
  1087.             case IPV6IFICMPINGRPMERSPS:
  1088.                 long_return = ifs6->ifs6_in_mldreport;
  1089.                 break;
  1090.             case IPV6IFICMPINGRPMEREDCS:
  1091.                 long_return = ifs6->ifs6_in_mlddone;
  1092.                 break;
  1093.             case IPV6IFICMPOUTMSG:
  1094.                 long_return = ifs6->ifs6_out_msg;
  1095.                 break;
  1096.             case IPV6IFICMPOUTERRORS:
  1097.                 long_return = ifs6->ifs6_out_error;
  1098.                 break;
  1099.             case IPV6IFICMPOUTDSTUNRCHS:
  1100.                 long_return = ifs6->ifs6_out_dstunreach;
  1101.                 break;
  1102.             case IPV6IFICMPOUTADMPROHS:
  1103.                 long_return = ifs6->ifs6_out_adminprohib;
  1104.                 break;
  1105.             case IPV6IFICMPOUTTIMEXCDS:
  1106.                 long_return = ifs6->ifs6_out_timeexceed;
  1107.                 break;
  1108.             case IPV6IFICMPOUTPARMPROBS:
  1109.                 long_return = ifs6->ifs6_out_paramprob;
  1110.                 break;
  1111.             case IPV6IFICMPOUTPKTTOOBIGS:
  1112.                 long_return = ifs6->ifs6_out_pkttoobig;
  1113.                 break;
  1114.             case IPV6IFICMPOUTECHOS:
  1115.                 long_return = ifs6->ifs6_out_echo;
  1116.                 break;
  1117.             case IPV6IFICMPOUTECHOREPS:
  1118.                 long_return = ifs6->ifs6_out_echoreply;
  1119.                 break;
  1120.             case IPV6IFICMPOUTRTRSLICITS:
  1121.                 long_return = ifs6->ifs6_out_routersolicit;
  1122.                 break;
  1123.             case IPV6IFICMPOUTRTRADVS:
  1124.                 long_return = ifs6->ifs6_out_routeradvert;
  1125.                 break;
  1126.             case IPV6IFICMPOUTNBRSLICITS:
  1127.                 long_return = ifs6->ifs6_out_neighborsolicit;
  1128.                 break;
  1129.             case IPV6IFICMPOUTNBRADVS:
  1130.                 long_return = ifs6->ifs6_out_neighboradvert;
  1131.                 break;
  1132.             case IPV6IFICMPOUTREDIRECTS:
  1133.                 long_return = ifs6->ifs6_out_redirect;
  1134.                 break;
  1135.             case IPV6IFICMPOUTGRPMEQERYS:
  1136.                 long_return = ifs6->ifs6_out_mldquery;
  1137.                 break;
  1138.             case IPV6IFICMPOUTGRPMERSPS:
  1139.                 long_return = ifs6->ifs6_out_mldreport;
  1140.                 break;
  1141.             case IPV6IFICMPOUTGRPMEREDCS:
  1142.                 long_return = ifs6->ifs6_out_mlddone;
  1143.                 break;
  1144.             default:
  1145.                 return NULL;
  1146.             }
  1147.             return (u_char *) & long_return;
  1148.         }
  1149. #endif
  1150.     default:
  1151.         break;
  1152.     }
  1153.     return NULL;
  1154. #endif
  1155. }
  1156. u_char         *
  1157. var_udp6(register struct variable * vp,
  1158.          oid * name,
  1159.          size_t * length,
  1160.          int exact, size_t * var_len, WriteMethod ** write_method)
  1161. {
  1162.     oid             newname[MAX_OID_LEN];
  1163.     oid             savname[MAX_OID_LEN];
  1164.     int             result;
  1165.     int             i, j;
  1166.     caddr_t         p;
  1167.     static struct in6pcb in6pcb, savpcb;
  1168.     int             found, savnameLen;
  1169. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1170.     struct inpcbtable udbtable;
  1171.     caddr_t     first;
  1172. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1173.     char           *sysctl_buf;
  1174.     struct xinpgen *xig, *oxig;
  1175. #else
  1176.     static struct in6pcb udb6;
  1177. #endif
  1178.     DEBUGMSGTL(("mibII/ipv6", "var_udp6: "));
  1179.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1180.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1181. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1182.     if (!auto_nlist("udbtable", (char *) &udbtable, sizeof(udbtable)))
  1183.         return NULL;
  1184.     first = p = (caddr_t)udbtable.inpt_queue.cqh_first;
  1185. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1186.     if (!auto_nlist("udb6", (char *) &udb6, sizeof(udb6)))
  1187.         return NULL;
  1188.     p = (caddr_t) udb6.in6p_next;
  1189. #else
  1190.     {
  1191.         const char     *udblist = "net.inet.udp.pcblist";
  1192.         const char     *pp = udblist;
  1193.         size_t          len;
  1194.         if (sysctlbyname(udblist, 0, &len, 0, 0) < 0)
  1195.             return NULL;
  1196.         if ((sysctl_buf = malloc(len)) == NULL)
  1197.             return NULL;
  1198.         udblist = pp;
  1199.         if (sysctlbyname(udblist, sysctl_buf, &len, 0, 0) < 0) {
  1200.             free(sysctl_buf);
  1201.             return NULL;
  1202.         }
  1203.         oxig = (struct xinpgen *) sysctl_buf;
  1204.         xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
  1205.         p = (caddr_t) ((char *) xig); /* silence compiler warning */
  1206.     }
  1207. #endif
  1208.     found = savnameLen = 0;
  1209.     memcpy((char *) newname, (char *) vp->name,
  1210.            (int) vp->namelen * sizeof(oid));
  1211.     DEBUGMSGTL(("mibII/ipv6", "start: p=%xn", p));
  1212.     while (
  1213. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1214.               p &&  p != first
  1215. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1216.               p && (u_long) p != auto_nlist_value("udb6")
  1217. #else
  1218.               xig->xig_len > sizeof(struct xinpgen)
  1219. #endif
  1220.         ) {
  1221.         DEBUGMSGTL(("mibII/ipv6", "looping: p=%xn", p));
  1222. #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1223.         if (klookup((u_long) p, (char *) &in6pcb, sizeof(in6pcb)) < 0) {
  1224.             DEBUGMSGTL(("mibII/ipv6", "klookup fail for udb6 at %xn",
  1225.                         p));
  1226.             found = 0;
  1227.             break;
  1228.         }
  1229. #else
  1230.         in6pcb = ((struct xinpcb *) xig)->xi_inp;
  1231. #endif
  1232. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1233.         if (in6pcb.in6p_af != AF_INET6)
  1234.             goto skip;
  1235. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1236.         if (0 == (in6pcb.inp_vflag & INP_IPV6))
  1237.             goto skip;
  1238. #endif
  1239.         j = (int) vp->namelen;
  1240.         for (i = 0; i < sizeof(struct in6_addr); i++)
  1241.             newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
  1242.         newname[j++] = ntohs(in6pcb.in6p_lport);
  1243.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1244.             newname[j++] =
  1245.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1246.         else
  1247.             newname[j++] = 0;
  1248.         /*XXX*/
  1249.             DEBUGMSGTL(("mibII/ipv6", "var_udp6 new: %d %d ",
  1250.                         (int) vp->namelen, j));
  1251.         DEBUGMSGOID(("mibII/ipv6", newname, j));
  1252.         DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1253.         result = snmp_oid_compare(name, *length, newname, j);
  1254.         if (exact && (result == 0)) {
  1255.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1256.                 savnameLen = j;
  1257.                 memcpy(savname, newname, j * sizeof(oid));
  1258.                 found++;
  1259.                 break;
  1260.         } else if (!exact && (result < 0)) {
  1261.             /*
  1262.              *  take the least greater one
  1263.              */
  1264.             if ((savnameLen == 0) ||
  1265.               (snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
  1266.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1267.                 savnameLen = j;
  1268.                 memcpy(savname, newname, j * sizeof(oid));
  1269.                     found++;
  1270.             }
  1271.         }
  1272.       skip:
  1273. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1274.         p = (caddr_t)in6pcb.in6p_queue.cqe_next;
  1275. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1276.         p = (caddr_t) in6pcb.in6p_next;
  1277. #else
  1278.         xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
  1279. #endif
  1280.     }
  1281. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1282.     free(sysctl_buf);
  1283. #endif
  1284.     DEBUGMSGTL(("mibII/ipv6", "found=%dn", found));
  1285.     if (!found)
  1286.         return NULL;
  1287.     *length = savnameLen;
  1288.     memcpy((char *) name, (char *) savname, *length * sizeof(oid));
  1289.     memcpy(&in6pcb, &savpcb, sizeof(savpcb));
  1290.     *write_method = 0;
  1291.     *var_len = sizeof(long);    /* default to 'long' results */
  1292. /*
  1293.     DEBUGMSGTL(("mibII/ipv6", "var_udp6 found: "));
  1294.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1295.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1296. */
  1297.     DEBUGMSGTL(("mibII/ipv6", "magic=%dn", vp->magic));
  1298.     switch (vp->magic) {
  1299.     case IPV6UDPLOCALADDRESS:
  1300.         *var_len = sizeof(struct in6_addr);
  1301.         return in6pcb.in6p_laddr.s6_addr;
  1302.     case IPV6UDPLOCALPORT:
  1303.         long_return = ntohs(in6pcb.in6p_lport);
  1304.         return (u_char *) & long_return;
  1305.     case IPV6UDPIFINDEX:
  1306.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1307.             long_return =
  1308.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1309.         else
  1310.             long_return = 0;
  1311.         /*XXX*/ return (u_char *) & long_return;
  1312.     default:
  1313.         break;
  1314.     }
  1315.     ERROR_MSG("");
  1316.     return NULL;
  1317. }
  1318. #ifdef TCP6
  1319. u_char         *
  1320. var_tcp6(register struct variable * vp,
  1321.          oid * name,
  1322.          size_t * length,
  1323.          int exact, size_t * var_len, WriteMethod ** write_method)
  1324. {
  1325.     oid             newname[MAX_OID_LEN];
  1326.     oid             savname[MAX_OID_LEN];
  1327.     int             result;
  1328.     int             i, j;
  1329.     caddr_t         p;
  1330.     static struct in6pcb in6pcb, savpcb;
  1331.     struct tcp6cb   tcp6cb;
  1332.     int             found, savnameLen;
  1333.     static int      tcp6statemap[TCP6_NSTATES];
  1334.     static int      initialized = 0;
  1335. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1336.     struct inpcbtable tcbtable;
  1337.     caddr_t     first;
  1338. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1339.     char           *sysctl_buf;
  1340.     struct xinpgen *xig, *oxig;
  1341. #else
  1342.     static struct in6pcb tcb6;
  1343. #endif
  1344.     if (!initialized) {
  1345.         tcp6statemap[TCP6S_CLOSED] = 1;
  1346.         tcp6statemap[TCP6S_LISTEN] = 2;
  1347.         tcp6statemap[TCP6S_SYN_SENT] = 3;
  1348.         tcp6statemap[TCP6S_SYN_RECEIVED] = 4;
  1349.         tcp6statemap[TCP6S_ESTABLISHED] = 5;
  1350.         tcp6statemap[TCP6S_CLOSE_WAIT] = 8;
  1351.         tcp6statemap[TCP6S_FIN_WAIT_1] = 6;
  1352.         tcp6statemap[TCP6S_CLOSING] = 10;
  1353.         tcp6statemap[TCP6S_LAST_ACK] = 9;
  1354.         tcp6statemap[TCP6S_FIN_WAIT_2] = 7;
  1355.         tcp6statemap[TCP6S_TIME_WAIT] = 11;
  1356.         initialized++;
  1357.     }
  1358.     DEBUGMSGTL(("mibII/ipv6", "var_tcp6: "));
  1359.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1360.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1361. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1362.     if (!auto_nlist("tcbtable", (char *) &tcbtable, sizeof(tcbtable)))
  1363.         return NULL;
  1364.     first = p = (caddr_t)tcbtable.inpt_queue.cqh_first;
  1365. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1366.     if (!auto_nlist("tcb6", (char *) &tcb6, sizeof(tcb6)))
  1367.         return NULL;
  1368.     p = (caddr_t) tcb6.in6p_next;
  1369. #else
  1370.     {
  1371.         const char     *tcblist = "net.inet.tcp.pcblist";
  1372.         const char     *pp = tcblist;
  1373.         size_t          len;
  1374.         if (sysctlbyname(tcblist, 0, &len, 0, 0) < 0)
  1375.             return NULL;
  1376.         if ((sysctl_buf = malloc(len)) == NULL)
  1377.             return NULL;
  1378.         tcblist = pp;
  1379.         if (sysctlbyname(tcblist, sysctl_buf, &len, 0, 0) < 0) {
  1380.             free(sysctl_buf);
  1381.             return NULL;
  1382.         }
  1383.         oxig = (struct xinpgen *) sysctl_buf;
  1384.         xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
  1385.         p = (caddr_t) ((char *) xig); /* silence compiler warning */
  1386.     }
  1387. #endif
  1388.     found = savnameLen = 0;
  1389.     memcpy((char *) newname, (char *) vp->name,
  1390.            (int) vp->namelen * sizeof(oid));
  1391.     DEBUGMSGTL(("mibII/ipv6", "start: p=%xn", p));
  1392.     while (
  1393. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1394.               p &&  p != first
  1395. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1396.               p && (u_long) p != auto_nlist_value("tcb6")
  1397. #else
  1398.               xig->xig_len > sizeof(struct xinpgen)
  1399. #endif
  1400.         ) {
  1401.         DEBUGMSGTL(("mibII/ipv6", "looping: p=%xn", p));
  1402. #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1403.         if (klookup((u_long) p, (char *) &in6pcb, sizeof(in6pcb)) < 0) {
  1404.             DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6 at %xn",
  1405.                         p));
  1406.             found = 0;
  1407.             break;
  1408.         }
  1409. #else
  1410.         in6pcb = ((struct xinpcb *) xig)->xi_inp;
  1411. #endif
  1412. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1413.         if (in6pcb.in6p_af != AF_INET6)
  1414.             goto skip;
  1415. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1416.         if (0 == (in6pcb.inp_vflag & INP_IPV6))
  1417.             goto skip;
  1418. #endif
  1419.         if (klookup
  1420.             ((u_long) in6pcb.in6p_ppcb, (char *) &tcp6cb, sizeof(tcp6cb))
  1421.             < 0) {
  1422.             DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6.tcp6cb at %xn",
  1423.                         in6pcb.in6p_ppcb));
  1424.             found = 0;
  1425.             break;
  1426.         }
  1427.         j = (int) vp->namelen;
  1428.         for (i = 0; i < sizeof(struct in6_addr); i++)
  1429.             newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
  1430.         newname[j++] = ntohs(in6pcb.in6p_lport);
  1431.         for (i = 0; i < sizeof(struct in6_addr); i++)
  1432.             newname[j++] = in6pcb.in6p_faddr.s6_addr[i];
  1433.         newname[j++] = ntohs(in6pcb.in6p_fport);
  1434.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1435.             newname[j++] =
  1436.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1437.         else
  1438.             newname[j++] = 0;
  1439.         /*XXX*/ newname[j++] = tcp6statemap[tcp6cb.t_state];
  1440.         DEBUGMSGTL(("mibII/ipv6", "var_tcp6 new: %d %d ",
  1441.                         (int) vp->namelen, j));
  1442.         DEBUGMSGOID(("mibII/ipv6", newname, j));
  1443.         DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1444. #if 1                           /* this is very odd but sometimes happen, and cause infinite loop */
  1445.         if (ntohs(in6pcb.in6p_lport) == 0)
  1446.             goto skip;
  1447. #endif
  1448.         result = snmp_oid_compare(name, *length, newname, j);
  1449.         if (exact && (result == 0)) {
  1450.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1451.                 savnameLen = j;
  1452.                 memcpy(savname, newname, j * sizeof(oid));
  1453.                 found++;
  1454.                 break;
  1455.         } else if (!exact && (result < 0)) {
  1456.             /*
  1457.              *  take the least greater one
  1458.              */
  1459.             if ((savnameLen == 0) ||
  1460.               (snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
  1461.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1462.                 savnameLen = j;
  1463.                 memcpy(savname, newname, j * sizeof(oid));
  1464.                     found++;
  1465.             }
  1466.         }
  1467.       skip:
  1468. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1469.         p = (caddr_t)in6pcb.in6p_queue.cqe_next;
  1470. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1471.         p = (caddr_t) in6pcb.in6p_next;
  1472. #else
  1473.         xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
  1474. #endif
  1475.     }
  1476. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1477.     free(sysctl_buf);
  1478. #endif
  1479.     DEBUGMSGTL(("mibII/ipv6", "found=%dn", found));
  1480.     if (!found)
  1481.         return NULL;
  1482.     *length = savnameLen;
  1483.     memcpy((char *) name, (char *) savname, *length * sizeof(oid));
  1484.     memcpy(&in6pcb, &savpcb, sizeof(savpcb));
  1485.     *write_method = 0;
  1486.     *var_len = sizeof(long);    /* default to 'long' results */
  1487. /*
  1488.     DEBUGMSGTL(("mibII/ipv6", "var_tcp6 found: "));
  1489.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1490.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1491. */
  1492.     DEBUGMSGTL(("mibII/ipv6", "magic=%dn", vp->magic));
  1493.     switch (vp->magic) {
  1494.     case IPV6TCPLOCALADDR:
  1495.         *var_len = sizeof(struct in6_addr);
  1496.         return (u_char *) & in6pcb.in6p_laddr.s6_addr[0];
  1497.     case IPV6TCPLOCALPORT:
  1498.         long_return = ntohs(in6pcb.in6p_lport);
  1499.         return (u_char *) & long_return;
  1500.     case IPV6TCPREMOTEADDR:
  1501.         *var_len = sizeof(struct in6_addr);
  1502.         return (u_char *) & in6pcb.in6p_faddr.s6_addr[0];
  1503.     case IPV6TCPREMOTEPORT:
  1504.         long_return = ntohs(in6pcb.in6p_fport);
  1505.         return (u_char *) & long_return;
  1506.     case IPV6TCPIFINDEX:
  1507.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1508.             long_return =
  1509.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1510.         else
  1511.             long_return = 0;
  1512.         /*XXX*/ return (u_char *) & long_return;
  1513.     case IPV6TCPCONNSTATE:
  1514.         long_return = tcp6statemap[tcp6cb.t_state];
  1515.         return (u_char *) & long_return;
  1516.     default:
  1517.         break;
  1518.     }
  1519.     ERROR_MSG("");
  1520.     return NULL;
  1521. }
  1522. #else  /* ! TCP6 */
  1523. static int mapTcpState( int val)
  1524. {
  1525.     static int      tcpstatemap[16 /*TCP_NSTATES*/];
  1526.     static int      initialized = 0;
  1527.     if (!initialized) {
  1528.         memset(tcpstatemap, 0, sizeof(tcpstatemap));
  1529.         tcpstatemap[TCPS_CLOSED] = 1;
  1530.         tcpstatemap[TCPS_LISTEN] = 2;
  1531.         tcpstatemap[TCPS_SYN_SENT] = 3;
  1532.         tcpstatemap[TCPS_SYN_RECEIVED] = 4;
  1533.         tcpstatemap[TCPS_ESTABLISHED] = 5;
  1534.         tcpstatemap[TCPS_CLOSE_WAIT] = 8;
  1535.         tcpstatemap[TCPS_FIN_WAIT_1] = 6;
  1536.         tcpstatemap[TCPS_CLOSING] = 10;
  1537.         tcpstatemap[TCPS_LAST_ACK] = 9;
  1538.         tcpstatemap[TCPS_FIN_WAIT_2] = 7;
  1539.         tcpstatemap[TCPS_TIME_WAIT] = 11;
  1540.         initialized++;
  1541.     }
  1542.     /* XXX GIGO 0 is an invalid state */
  1543.     return (tcpstatemap[0x0f & val]);
  1544. }
  1545. u_char         *
  1546. var_tcp6(register struct variable * vp,
  1547.          oid * name,
  1548.          size_t * length,
  1549.          int exact, size_t * var_len, WriteMethod ** write_method)
  1550. {
  1551.     oid             newname[MAX_OID_LEN];
  1552.     oid             savname[MAX_OID_LEN];
  1553.     int             result;
  1554.     int             i, j;
  1555.     caddr_t         p;
  1556.     static struct in6pcb in6pcb, savpcb;
  1557.     struct tcpcb    tcpcb;
  1558.     int             found, savnameLen;
  1559. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1560.     struct inpcbtable tcbtable;
  1561.     caddr_t     first;
  1562. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1563.     char           *sysctl_buf;
  1564.     struct xinpgen *xig, *oxig;
  1565. #else
  1566.     static struct in6pcb tcb6;
  1567. #endif
  1568.     DEBUGMSGTL(("mibII/ipv6", "var_tcp6: "));
  1569.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1570.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1571. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1572.     if (!auto_nlist("tcbtable", (char *) &tcbtable, sizeof(tcbtable)))
  1573.         return NULL;
  1574.     first = p = (caddr_t)tcbtable.inpt_queue.cqh_first;
  1575. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1576.     if (!auto_nlist("tcb6", (char *) &tcb6, sizeof(tcb6)))
  1577.         return NULL;
  1578.     p = (caddr_t) tcb6.in6p_next;
  1579. #else
  1580.     {
  1581.         const char     *tcblist = "net.inet.tcp.pcblist";
  1582.         const char     *pp = tcblist;
  1583.         size_t          len;
  1584.         if (sysctlbyname(tcblist, 0, &len, 0, 0) < 0)
  1585.             return NULL;
  1586.         if ((sysctl_buf = malloc(len)) == NULL)
  1587.             return NULL;
  1588.         tcblist = pp;
  1589.         if (sysctlbyname(tcblist, sysctl_buf, &len, 0, 0) < 0) {
  1590.             free(sysctl_buf);
  1591.             return NULL;
  1592.         }
  1593.         oxig = (struct xinpgen *) sysctl_buf;
  1594.         xig = (struct xinpgen *) ((char *) oxig + oxig->xig_len);
  1595.         p = (caddr_t) ((char *) xig); /* silence compiler warning */
  1596.     }
  1597. #endif
  1598.     found = savnameLen = 0;
  1599.     memcpy((char *) newname, (char *) vp->name,
  1600.            (int) vp->namelen * sizeof(oid));
  1601.     DEBUGMSGTL(("mibII/ipv6", "start: p=%xn", p));
  1602.     while (
  1603. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1604.               p && p != first
  1605. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1606.               p && (u_long) p != auto_nlist_value("tcb6")
  1607. #else
  1608.               xig->xig_len > sizeof(struct xinpgen)
  1609. #endif
  1610.         ) {
  1611.         DEBUGMSGTL(("mibII/ipv6", "looping: p=%xn", p));
  1612. #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1613.         if (klookup((u_long) p, (char *) &in6pcb, sizeof(in6pcb)) < 0) {
  1614.             DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6 at %xn",
  1615.                         p));
  1616.             found = 0;
  1617.             break;
  1618.         }
  1619. #else
  1620.         in6pcb = ((struct xinpcb *) xig)->xi_inp;
  1621. #endif
  1622. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1623.         if (in6pcb.in6p_af != AF_INET6)
  1624.             goto skip;
  1625. #elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1626.         if (0 == (in6pcb.inp_vflag & INP_IPV6))
  1627.             goto skip;
  1628. #endif
  1629.         if (klookup
  1630.             ((u_long) in6pcb.in6p_ppcb, (char *) &tcpcb, sizeof(tcpcb))
  1631.             < 0) {
  1632.             DEBUGMSGTL(("mibII/ipv6", "klookup fail for tcb6.tcpcb at %xn",
  1633.                         in6pcb.in6p_ppcb));
  1634.             found = 0;
  1635.             break;
  1636.         }
  1637.         j = (int) vp->namelen;
  1638.         for (i = 0; i < sizeof(struct in6_addr); i++)
  1639.             newname[j++] = in6pcb.in6p_laddr.s6_addr[i];
  1640.         newname[j++] = ntohs(in6pcb.in6p_lport);
  1641.         for (i = 0; i < sizeof(struct in6_addr); i++)
  1642.             newname[j++] = in6pcb.in6p_faddr.s6_addr[i];
  1643.         newname[j++] = ntohs(in6pcb.in6p_fport);
  1644.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1645.             newname[j++] =
  1646.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1647.         else
  1648.             newname[j++] = 0;
  1649.         /*XXX*/ newname[j++] = mapTcpState((int)tcpcb.t_state);
  1650.         DEBUGMSGTL(("mibII/ipv6", "var_tcp6 new: %d %d ",
  1651.                         (int) vp->namelen, j));
  1652.         DEBUGMSGOID(("mibII/ipv6", newname, j));
  1653.         DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1654. #if 1                           /* this is very odd but sometimes happen, and cause infinite loop */
  1655.         if (ntohs(in6pcb.in6p_lport) == 0)
  1656.             goto skip;
  1657. #endif
  1658.         result = snmp_oid_compare(name, *length, newname, j);
  1659.         if (exact && (result == 0)) {
  1660.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1661.                 savnameLen = j;
  1662.                 memcpy(savname, newname, j * sizeof(oid));
  1663.                 found++;
  1664.                 break;
  1665.         } else if (!exact && (result < 0)) {
  1666.             /*
  1667.              *  take the least greater one
  1668.              */
  1669.             if ((savnameLen == 0) ||
  1670.               (snmp_oid_compare(savname, savnameLen, newname, j) > 0)) {
  1671.                 memcpy(&savpcb, &in6pcb, sizeof(savpcb));
  1672.                 savnameLen = j;
  1673.                 memcpy(savname, newname, j * sizeof(oid));
  1674.                     found++;
  1675.             }
  1676.         }
  1677.       skip:
  1678. #if defined(__NetBSD__) && __NetBSD_Version__ >= 106250000 /*1.6Y*/
  1679.         p = (caddr_t)in6pcb.in6p_queue.cqe_next;
  1680. #elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(darwin)
  1681.         p = (caddr_t) in6pcb.in6p_next;
  1682. #else
  1683.         xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
  1684. #endif
  1685.     }
  1686. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(darwin)
  1687.     free(sysctl_buf);
  1688. #endif
  1689.     DEBUGMSGTL(("mibII/ipv6", "found=%dn", found));
  1690.     if (!found)
  1691.         return NULL;
  1692.     *length = savnameLen;
  1693.     memcpy((char *) name, (char *) savname, *length * sizeof(oid));
  1694.     memcpy(&in6pcb, &savpcb, sizeof(savpcb));
  1695.     *write_method = 0;
  1696.     *var_len = sizeof(long);    /* default to 'long' results */
  1697. /*
  1698.     DEBUGMSGTL(("mibII/ipv6", "var_tcp6 found: "));
  1699.     DEBUGMSGOID(("mibII/ipv6", name, *length));
  1700.     DEBUGMSG(("mibII/ipv6", " %dn", exact));
  1701. */
  1702.     DEBUGMSGTL(("mibII/ipv6", "magic=%dn", vp->magic));
  1703.     switch (vp->magic) {
  1704.     case IPV6TCPLOCALADDR:
  1705.         *var_len = sizeof(struct in6_addr);
  1706.         return (u_char *) & in6pcb.in6p_laddr.s6_addr[0];
  1707.     case IPV6TCPLOCALPORT:
  1708.         long_return = ntohs(in6pcb.in6p_lport);
  1709.         return (u_char *) & long_return;
  1710.     case IPV6TCPREMOTEADDR:
  1711.         *var_len = sizeof(struct in6_addr);
  1712.         return (u_char *) & in6pcb.in6p_faddr.s6_addr[0];
  1713.     case IPV6TCPREMOTEPORT:
  1714.         long_return = ntohs(in6pcb.in6p_fport);
  1715.         return (u_char *) & long_return;
  1716.     case IPV6TCPIFINDEX:
  1717.         if (IN6_IS_ADDR_LINKLOCAL(&in6pcb.in6p_laddr))
  1718.             long_return =
  1719.                 ntohs(*(uint16_t *) & in6pcb.in6p_laddr.s6_addr[2]);
  1720.         else
  1721.             long_return = 0;
  1722.         /*XXX*/ return (u_char *) & long_return;
  1723.     case IPV6TCPCONNSTATE:
  1724.         long_return = mapTcpState((int)tcpcb.t_state);
  1725.         return (u_char *) & long_return;
  1726.     default:
  1727.         break;
  1728.     }
  1729.     ERROR_MSG("");
  1730.     return NULL;
  1731. }
  1732. #endif                          /*TCP6 */
  1733. #else                           /* !linux / linux */
  1734. /*
  1735.  * Linux dependent part 
  1736.  */
  1737. static unsigned long
  1738. linux_read_ip6_stat_ulong(const char *file)
  1739. {
  1740.     FILE           *f;
  1741.     unsigned long   value;
  1742.     f = fopen(file, "r");
  1743.     if (!f)
  1744.         return 0;
  1745.     if (fscanf(f, "%lu", &value) != 1) {
  1746.         fclose(f);
  1747.         return 0;
  1748.     }
  1749.     fclose(f);
  1750.     return value;
  1751. }
  1752. void
  1753. linux_read_ip6_stat(struct ip6_mib *ip6stat)
  1754. {
  1755.     if (!ip6stat)
  1756.         return;
  1757.     memset(ip6stat, 0, sizeof(*ip6stat));
  1758.     ip6stat->Ipv6Forwarding =
  1759.         linux_read_ip6_stat_ulong
  1760.         ("/proc/sys/net/ipv6/conf/all/forwarding");
  1761.     ip6stat->Ipv6DefaultHopLimit =
  1762.         linux_read_ip6_stat_ulong
  1763.         ("/proc/sys/net/ipv6/conf/default/hop_limit");
  1764. }
  1765. u_char         *
  1766. var_ipv6(register struct variable *vp,
  1767.          oid * name,
  1768.          size_t * length,
  1769.          int exact, size_t * var_len, WriteMethod ** write_method)
  1770. {
  1771.     static struct ip6_mib ip6stat;
  1772.     if (header_ipv6(vp, name, length, exact, var_len, write_method)
  1773.         == MATCH_FAILED) {
  1774.         return NULL;
  1775.     }
  1776.     linux_read_ip6_stat(&ip6stat);
  1777.     switch (vp->magic) {
  1778.     case IPV6DEFAULTHOPLIMIT:
  1779.         return (u_char *) & ip6stat.Ipv6DefaultHopLimit;
  1780.     case IPV6FORWARDING:
  1781.         long_return = (ip6stat.Ipv6Forwarding) ? 1 : 2;
  1782.         return (u_char *) & long_return;
  1783.     case IPV6INTERFACES:
  1784. #ifdef HAVE_IF_NAMEINDEX
  1785.         long_return = if_countifindex();
  1786.         if (long_return < 0)
  1787.             break;
  1788.         return (u_char *) & long_return;
  1789. #endif
  1790.         break;
  1791.     default:
  1792.         DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipv6n",
  1793.                     vp->magic));
  1794.     }
  1795.     return NULL;
  1796. }
  1797. u_char         *
  1798. var_ifv6Entry(register struct variable * vp,
  1799.               oid * name,
  1800.               size_t * length,
  1801.               int exact, size_t * var_len, WriteMethod ** write_method)
  1802. {
  1803. #ifndef HAVE_IF_NAMEINDEX
  1804.     return NULL;
  1805. #else
  1806.     int             interface;
  1807.     int             max;
  1808.     char           *p;
  1809.     struct ifreq    ifr;
  1810.     int             s;
  1811.     max = if_maxifindex();
  1812.     if (max < 0)
  1813.         return NULL;
  1814.     if (header_ipv6_scan
  1815.         (vp, name, length, exact, var_len, write_method, 1, max)
  1816.         == MATCH_FAILED) {
  1817.         return NULL;
  1818.     }
  1819.     interface = name[*length - 1];
  1820.     DEBUGMSGTL(("mibII/ipv6", "interface: %d(%s)n",
  1821.                 interface, if_getname(interface)));
  1822.     if (interface > max)
  1823.         return NULL;
  1824.     switch (vp->magic) {
  1825.     case IPV6IFDESCR:
  1826.         p = if_getname(interface);
  1827.         if (p) {
  1828.             *var_len = strlen(p);
  1829.             return p;
  1830.         }
  1831.         break;
  1832.     case IPV6IFLOWLAYER:
  1833.         /*
  1834.          * should check if type, this is a hard one... 
  1835.          */
  1836.         *var_len = nullOidLen;
  1837.         return (u_char *) nullOid;
  1838.     case IPV6IFEFFECTMTU:
  1839.         {
  1840.             p = if_getname(interface);
  1841.             if (!p)
  1842.                 break;
  1843.             memset(&ifr, 0, sizeof(ifr));
  1844.             ifr.ifr_addr.sa_family = AF_INET6;
  1845.             strncpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
  1846.             if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
  1847.                 break;
  1848.             if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0) {
  1849.                 close(s);
  1850.                 break;
  1851.             }
  1852.             long_return = ifr.ifr_mtu;
  1853.             close(s);
  1854.             return (u_char *) & long_return;
  1855.         }
  1856.     case IPV6IFPHYSADDRESS:
  1857.         {
  1858.             static struct ifreq buf;
  1859.             int             ok = 0;
  1860.             p = if_getname(interface);
  1861.             if (!p)
  1862.                 break;
  1863.             memset(&ifr, 0, sizeof(ifr));
  1864.             ifr.ifr_addr.sa_family = AF_INET6;
  1865.             strncpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
  1866.             if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
  1867.                 break;
  1868.             if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
  1869.                 memset(buf.ifr_hwaddr.sa_data, 0,
  1870.                        sizeof(buf.ifr_hwaddr.sa_data));
  1871.                 *var_len = 0;
  1872.             } else {
  1873.                 memcpy(buf.ifr_hwaddr.sa_data, ifr.ifr_hwaddr.sa_data, 6);
  1874.                 *var_len = (buf.ifr_hwaddr.sa_data[0] |
  1875.                             buf.ifr_hwaddr.sa_data[1] |
  1876.                             buf.ifr_hwaddr.sa_data[2] |
  1877.                             buf.ifr_hwaddr.sa_data[3] |
  1878.                             buf.ifr_hwaddr.sa_data[4] |
  1879.                             buf.ifr_hwaddr.sa_data[5]) ? 6 : 0;
  1880.                 ok = 1;
  1881.             }
  1882.             close(s);
  1883.             return (ok ? ((u_char *) & buf.ifr_hwaddr.sa_data) : NULL);
  1884.         }
  1885.     case IPV6IFADMSTATUS:
  1886.     case IPV6IFOPERSTATUS:
  1887.         {
  1888.             int             flag = 0;
  1889.             p = if_getname(interface);
  1890.             if (!p)
  1891.                 break;
  1892.             memset(&ifr, 0, sizeof(ifr));
  1893.             ifr.ifr_addr.sa_family = AF_INET6;
  1894.             strncpy(ifr.ifr_name, p, sizeof(ifr.ifr_name));
  1895.             if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
  1896.                 break;
  1897.             if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
  1898.                 close(s);
  1899.                 break;
  1900.             }
  1901.             close(s);
  1902.             switch (vp->magic) {
  1903.             case IPV6IFADMSTATUS:
  1904.                 flag = IFF_RUNNING;
  1905.                 break;
  1906.             case IPV6IFOPERSTATUS:
  1907.                 flag = IFF_UP;
  1908.                 break;
  1909.             }
  1910.             long_return = (ifr.ifr_flags & flag) ? 1 : 2;
  1911.             return (u_char *) & long_return;
  1912.         }
  1913.     }
  1914.     return NULL;
  1915. #endif
  1916. }
  1917. u_char         *
  1918. var_icmpv6Entry(register struct variable * vp,
  1919.                 oid * name,
  1920.                 size_t * length,
  1921.                 int exact, size_t * var_len, WriteMethod ** write_method)
  1922. {
  1923.     return NULL;
  1924. }
  1925. u_char         *
  1926. var_udp6(register struct variable * vp,
  1927.          oid * name,
  1928.          size_t * length,
  1929.          int exact, size_t * var_len, WriteMethod ** write_method)
  1930. {
  1931.     return NULL;
  1932. }
  1933. u_char         *
  1934. var_tcp6(register struct variable * vp,
  1935.          oid * name,
  1936.          size_t * length,
  1937.          int exact, size_t * var_len, WriteMethod ** write_method)
  1938. {
  1939.     return NULL;
  1940. }
  1941. /*
  1942.  * misc functions (against broken kernels ) 
  1943.  */
  1944. void
  1945. linux_if_freenameindex(struct if_nameindex *ifndx)
  1946. {
  1947.     int             i;
  1948.     if (!ifndx)
  1949.         return;
  1950.     for (i = 1; ifndx[i].if_index; i++) {
  1951.         free(ifndx[i].if_name);
  1952.     }
  1953.     free(ifndx);
  1954. }
  1955. #define linux_freeinternalnameindex(ifni, max)  { 
  1956.   int i; 
  1957.   for (i=1; i<=max; i++){
  1958.     if (ifni[i].if_name) free(ifni[i].if_name);
  1959.   }
  1960.   free(ifni);
  1961. }
  1962. #define LINUX_PROC_NET_IFINET6 "/proc/net/if_inet6"
  1963. struct if_nameindex *
  1964. linux_if_nameindex(void)
  1965. {
  1966.     FILE           *f;
  1967.     unsigned long   if_index;
  1968.     char            if_name[256];
  1969.     struct if_nameindex *ifndx = NULL, *iflist = NULL, *new;
  1970.     int             i, j;
  1971.     int             maxidx, if_count = 0;
  1972.     f = fopen(LINUX_PROC_NET_IFINET6, "r");
  1973.     if (f) {
  1974.         if_count = 0;
  1975.         maxidx = -1;
  1976.         while (!feof(f)) {
  1977.             if (fscanf(f, "%*s %lx %*x %*x %*x %s",
  1978.                        &if_index, if_name) != 2)
  1979.                 continue;
  1980.             if (if_index == 0)
  1981.                 continue;
  1982.             if_name[sizeof(if_name) - 1] = '';
  1983.             if (maxidx < 0 || maxidx < if_index) {
  1984.                 new =
  1985.                     realloc(iflist,
  1986.                             (sizeof(struct if_nameindex)) * (if_index +
  1987.                                                              2));
  1988.                 if (!new) {
  1989.                     linux_freeinternalnameindex(iflist, if_index);
  1990.                     if_count = 0;
  1991.                     iflist = NULL;
  1992.                     break;
  1993.                 }
  1994.                 iflist = new;
  1995.                 for (i = maxidx + 1; i <= if_index; i++)
  1996.                     memset(&iflist[i], 0, sizeof(struct if_nameindex));
  1997.                 memset(&iflist[if_index + 1], 0,
  1998.                        sizeof(struct if_nameindex));
  1999.                 maxidx = if_index;
  2000.             }
  2001.             if (iflist[if_index].if_index == 0) {
  2002.                 if_count++;
  2003.                 iflist[if_index].if_index = if_index;
  2004.                 iflist[if_index].if_name = strdup(if_name);
  2005.                 if (!iflist[if_index].if_name) {
  2006.                     linux_freeinternalnameindex(iflist, if_index);
  2007.                     if_count = 0;
  2008.                     iflist = NULL;
  2009.                     break;
  2010.                 }
  2011.             }
  2012.         }
  2013.         fclose(f);
  2014.         if (if_count > 0) {
  2015.             ifndx = malloc(sizeof(struct if_nameindex) * (if_count + 1));
  2016.             j = 0;
  2017.             for (i = 1; i <= maxidx; i++) {
  2018.                 if (iflist[i].if_index > 0 && *iflist[i].if_name) {
  2019.                     memcpy(&ifndx[j++], &iflist[i],
  2020.                            sizeof(struct if_nameindex));
  2021.                 }
  2022.             }
  2023.             ifndx[j].if_index = 0;
  2024.             ifndx[j].if_name = NULL;
  2025.         }
  2026.         free(iflist);
  2027.     }
  2028.     return (ifndx);
  2029. }
  2030. #endif                          /* linux */