/contrib/bsnmp/snmp_mibII/mibII_udp.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 253 lines · 184 code · 37 blank · 32 comment · 39 complexity · 8547fd261e69b462922a145d69151548 MD5 · raw file

  1. /*
  2. * Copyright (c) 2001-2003
  3. * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
  4. * All rights reserved.
  5. *
  6. * Author: Harti Brandt <harti@freebsd.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $
  30. *
  31. * udp
  32. */
  33. #include "mibII.h"
  34. #include "mibII_oid.h"
  35. #include <sys/socketvar.h>
  36. #include <netinet/in_pcb.h>
  37. #include <netinet/udp.h>
  38. #include <netinet/ip_var.h>
  39. #include <netinet/udp_var.h>
  40. struct udp_index {
  41. struct asn_oid index;
  42. struct xinpcb *inp;
  43. };
  44. static uint64_t udp_tick;
  45. static struct udpstat udpstat;
  46. static struct xinpgen *xinpgen;
  47. static size_t xinpgen_len;
  48. static u_int udp_total;
  49. static u_int oidnum;
  50. static struct udp_index *udpoids;
  51. static int
  52. udp_compare(const void *p1, const void *p2)
  53. {
  54. const struct udp_index *t1 = p1;
  55. const struct udp_index *t2 = p2;
  56. return (asn_compare_oid(&t1->index, &t2->index));
  57. }
  58. static int
  59. fetch_udp(void)
  60. {
  61. size_t len;
  62. struct xinpgen *ptr;
  63. struct xinpcb *inp;
  64. struct udp_index *oid;
  65. in_addr_t inaddr;
  66. len = sizeof(udpstat);
  67. if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) {
  68. syslog(LOG_ERR, "net.inet.udp.stats: %m");
  69. return (-1);
  70. }
  71. if (len != sizeof(udpstat)) {
  72. syslog(LOG_ERR, "net.inet.udp.stats: wrong size");
  73. return (-1);
  74. }
  75. udp_tick = get_ticks();
  76. len = 0;
  77. if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) {
  78. syslog(LOG_ERR, "net.inet.udp.pcblist: %m");
  79. return (-1);
  80. }
  81. if (len > xinpgen_len) {
  82. if ((ptr = realloc(xinpgen, len)) == NULL) {
  83. syslog(LOG_ERR, "%zu: %m", len);
  84. return (-1);
  85. }
  86. xinpgen = ptr;
  87. xinpgen_len = len;
  88. }
  89. if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) {
  90. syslog(LOG_ERR, "net.inet.udp.pcblist: %m");
  91. return (-1);
  92. }
  93. udp_total = 0;
  94. for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
  95. ptr->xig_len > sizeof(struct xinpgen);
  96. ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
  97. inp = (struct xinpcb *)ptr;
  98. if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
  99. (inp->xi_inp.inp_vflag & INP_IPV4) == 0)
  100. continue;
  101. udp_total++;
  102. }
  103. if (oidnum < udp_total) {
  104. oid = realloc(udpoids, udp_total * sizeof(udpoids[0]));
  105. if (oid == NULL) {
  106. free(udpoids);
  107. oidnum = 0;
  108. return (0);
  109. }
  110. udpoids = oid;
  111. oidnum = udp_total;
  112. }
  113. oid = udpoids;
  114. for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);
  115. ptr->xig_len > sizeof(struct xinpgen);
  116. ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
  117. inp = (struct xinpcb *)ptr;
  118. if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
  119. (inp->xi_inp.inp_vflag & INP_IPV4) == 0)
  120. continue;
  121. oid->inp = inp;
  122. oid->index.len = 5;
  123. inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr);
  124. oid->index.subs[0] = (inaddr >> 24) & 0xff;
  125. oid->index.subs[1] = (inaddr >> 16) & 0xff;
  126. oid->index.subs[2] = (inaddr >> 8) & 0xff;
  127. oid->index.subs[3] = (inaddr >> 0) & 0xff;
  128. oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport);
  129. oid++;
  130. }
  131. qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare);
  132. return (0);
  133. }
  134. int
  135. op_udp(struct snmp_context *ctx __unused, struct snmp_value *value,
  136. u_int sub, u_int iidx __unused, enum snmp_op op)
  137. {
  138. switch (op) {
  139. case SNMP_OP_GETNEXT:
  140. abort();
  141. case SNMP_OP_GET:
  142. break;
  143. case SNMP_OP_SET:
  144. return (SNMP_ERR_NOT_WRITEABLE);
  145. case SNMP_OP_ROLLBACK:
  146. case SNMP_OP_COMMIT:
  147. abort();
  148. }
  149. if (udp_tick < this_tick)
  150. if (fetch_udp() == -1)
  151. return (SNMP_ERR_GENERR);
  152. switch (value->var.subs[sub - 1]) {
  153. case LEAF_udpInDatagrams:
  154. value->v.uint32 = udpstat.udps_ipackets;
  155. break;
  156. case LEAF_udpNoPorts:
  157. value->v.uint32 = udpstat.udps_noport +
  158. udpstat.udps_noportbcast +
  159. udpstat.udps_noportmcast;
  160. break;
  161. case LEAF_udpInErrors:
  162. value->v.uint32 = udpstat.udps_hdrops +
  163. udpstat.udps_badsum +
  164. udpstat.udps_badlen +
  165. udpstat.udps_fullsock;
  166. break;
  167. case LEAF_udpOutDatagrams:
  168. value->v.uint32 = udpstat.udps_opackets;
  169. break;
  170. }
  171. return (SNMP_ERR_NOERROR);
  172. }
  173. int
  174. op_udptable(struct snmp_context *ctx __unused, struct snmp_value *value,
  175. u_int sub, u_int iidx __unused, enum snmp_op op)
  176. {
  177. u_int i;
  178. if (udp_tick < this_tick)
  179. if (fetch_udp() == -1)
  180. return (SNMP_ERR_GENERR);
  181. switch (op) {
  182. case SNMP_OP_GETNEXT:
  183. for (i = 0; i < udp_total; i++)
  184. if (index_compare(&value->var, sub, &udpoids[i].index) < 0)
  185. break;
  186. if (i == udp_total)
  187. return (SNMP_ERR_NOSUCHNAME);
  188. index_append(&value->var, sub, &udpoids[i].index);
  189. break;
  190. case SNMP_OP_GET:
  191. for (i = 0; i < udp_total; i++)
  192. if (index_compare(&value->var, sub, &udpoids[i].index) == 0)
  193. break;
  194. if (i == udp_total)
  195. return (SNMP_ERR_NOSUCHNAME);
  196. break;
  197. case SNMP_OP_SET:
  198. return (SNMP_ERR_NOT_WRITEABLE);
  199. case SNMP_OP_ROLLBACK:
  200. case SNMP_OP_COMMIT:
  201. default:
  202. abort();
  203. }
  204. switch (value->var.subs[sub - 1]) {
  205. case LEAF_udpLocalAddress:
  206. value->v.ipaddress[0] = udpoids[i].index.subs[0];
  207. value->v.ipaddress[1] = udpoids[i].index.subs[1];
  208. value->v.ipaddress[2] = udpoids[i].index.subs[2];
  209. value->v.ipaddress[3] = udpoids[i].index.subs[3];
  210. break;
  211. case LEAF_udpLocalPort:
  212. value->v.integer = udpoids[i].index.subs[4];
  213. break;
  214. }
  215. return (SNMP_ERR_NOERROR);
  216. }