/contrib/bsnmp/snmpd/export.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 399 lines · 268 code · 46 blank · 85 comment · 52 complexity · f78b6752041f6195ad288c82704a6da4 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/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $
  30. *
  31. * Support functions for modules.
  32. */
  33. #include <sys/types.h>
  34. #include <sys/queue.h>
  35. #include <sys/un.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <syslog.h>
  40. #include <stdarg.h>
  41. #include "snmpmod.h"
  42. #include "snmpd.h"
  43. #include "tree.h"
  44. /*
  45. * Support functions
  46. */
  47. /*
  48. * This is user for SET of string variables. If 'req' is not -1 then
  49. * the arguments is checked to be of that length. The old value is saved
  50. * in scratch->ptr1 and the new value is allocated and copied.
  51. * If there is an old values it must have been allocated by malloc.
  52. */
  53. int
  54. string_save(struct snmp_value *value, struct snmp_context *ctx,
  55. ssize_t req_size, u_char **valp)
  56. {
  57. if (req_size != -1 && value->v.octetstring.len != (u_long)req_size)
  58. return (SNMP_ERR_BADVALUE);
  59. ctx->scratch->ptr1 = *valp;
  60. if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) {
  61. *valp = ctx->scratch->ptr1;
  62. return (SNMP_ERR_RES_UNAVAIL);
  63. }
  64. memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len);
  65. (*valp)[value->v.octetstring.len] = '\0';
  66. return (0);
  67. }
  68. /*
  69. * Commit a string. This is easy - free the old value.
  70. */
  71. void
  72. string_commit(struct snmp_context *ctx)
  73. {
  74. free(ctx->scratch->ptr1);
  75. }
  76. /*
  77. * Rollback a string - free new value and copy back old one.
  78. */
  79. void
  80. string_rollback(struct snmp_context *ctx, u_char **valp)
  81. {
  82. free(*valp);
  83. *valp = ctx->scratch->ptr1;
  84. }
  85. /*
  86. * ROLLBACK or COMMIT fails because instance has disappeared. Free string.
  87. */
  88. void
  89. string_free(struct snmp_context *ctx)
  90. {
  91. free(ctx->scratch->ptr1);
  92. }
  93. /*
  94. * Get a string value for a response packet
  95. */
  96. int
  97. string_get(struct snmp_value *value, const u_char *ptr, ssize_t len)
  98. {
  99. if (ptr == NULL) {
  100. value->v.octetstring.len = 0;
  101. value->v.octetstring.octets = NULL;
  102. return (SNMP_ERR_NOERROR);
  103. }
  104. if (len == -1)
  105. len = strlen(ptr);
  106. value->v.octetstring.len = (u_long)len;
  107. if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
  108. return (SNMP_ERR_RES_UNAVAIL);
  109. memcpy(value->v.octetstring.octets, ptr, (size_t)len);
  110. return (SNMP_ERR_NOERROR);
  111. }
  112. /*
  113. * Get a string value for a response packet but cut it if it is too long.
  114. */
  115. int
  116. string_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len,
  117. size_t maxlen)
  118. {
  119. if (ptr == NULL) {
  120. value->v.octetstring.len = 0;
  121. value->v.octetstring.octets = NULL;
  122. return (SNMP_ERR_NOERROR);
  123. }
  124. if (len == -1)
  125. len = strlen(ptr);
  126. if ((size_t)len > maxlen)
  127. len = maxlen;
  128. value->v.octetstring.len = (u_long)len;
  129. if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL)
  130. return (SNMP_ERR_RES_UNAVAIL);
  131. memcpy(value->v.octetstring.octets, ptr, (size_t)len);
  132. return (SNMP_ERR_NOERROR);
  133. }
  134. /*
  135. * Support for IPADDRESS
  136. *
  137. * Save the old IP address in scratch->int1 and set the new one.
  138. */
  139. int
  140. ip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp)
  141. {
  142. ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8)
  143. | valp[3];
  144. valp[0] = value->v.ipaddress[0];
  145. valp[1] = value->v.ipaddress[1];
  146. valp[2] = value->v.ipaddress[2];
  147. valp[3] = value->v.ipaddress[3];
  148. return (0);
  149. }
  150. /*
  151. * Rollback the address by copying back the old one
  152. */
  153. void
  154. ip_rollback(struct snmp_context *ctx, u_char *valp)
  155. {
  156. valp[0] = ctx->scratch->int1 >> 24;
  157. valp[1] = ctx->scratch->int1 >> 16;
  158. valp[2] = ctx->scratch->int1 >> 8;
  159. valp[3] = ctx->scratch->int1;
  160. }
  161. /*
  162. * Nothing to do for commit
  163. */
  164. void
  165. ip_commit(struct snmp_context *ctx __unused)
  166. {
  167. }
  168. /*
  169. * Retrieve an IP address
  170. */
  171. int
  172. ip_get(struct snmp_value *value, u_char *valp)
  173. {
  174. value->v.ipaddress[0] = valp[0];
  175. value->v.ipaddress[1] = valp[1];
  176. value->v.ipaddress[2] = valp[2];
  177. value->v.ipaddress[3] = valp[3];
  178. return (SNMP_ERR_NOERROR);
  179. }
  180. /*
  181. * Object ID support
  182. *
  183. * Save the old value in a fresh allocated oid pointed to by scratch->ptr1.
  184. */
  185. int
  186. oid_save(struct snmp_value *value, struct snmp_context *ctx,
  187. struct asn_oid *oid)
  188. {
  189. if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL)
  190. return (SNMP_ERR_RES_UNAVAIL);
  191. *(struct asn_oid *)ctx->scratch->ptr1 = *oid;
  192. *oid = value->v.oid;
  193. return (0);
  194. }
  195. void
  196. oid_rollback(struct snmp_context *ctx, struct asn_oid *oid)
  197. {
  198. *oid = *(struct asn_oid *)ctx->scratch->ptr1;
  199. free(ctx->scratch->ptr1);
  200. }
  201. void
  202. oid_commit(struct snmp_context *ctx)
  203. {
  204. free(ctx->scratch->ptr1);
  205. }
  206. int
  207. oid_get(struct snmp_value *value, const struct asn_oid *oid)
  208. {
  209. value->v.oid = *oid;
  210. return (SNMP_ERR_NOERROR);
  211. }
  212. /*
  213. * Decode an index
  214. */
  215. int
  216. index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...)
  217. {
  218. va_list ap;
  219. u_int index_count;
  220. void *octs[10];
  221. u_int nocts;
  222. u_int idx;
  223. va_start(ap, code);
  224. index_count = SNMP_INDEX_COUNT(code);
  225. nocts = 0;
  226. for (idx = 0; idx < index_count; idx++) {
  227. switch (SNMP_INDEX(code, idx)) {
  228. case SNMP_SYNTAX_NULL:
  229. break;
  230. case SNMP_SYNTAX_INTEGER:
  231. if (sub == oid->len)
  232. goto err;
  233. *va_arg(ap, int32_t *) = oid->subs[sub++];
  234. break;
  235. case SNMP_SYNTAX_COUNTER64:
  236. if (sub == oid->len)
  237. goto err;
  238. *va_arg(ap, u_int64_t *) = oid->subs[sub++];
  239. break;
  240. case SNMP_SYNTAX_OCTETSTRING:
  241. {
  242. u_char **cval;
  243. size_t *sval;
  244. u_int i;
  245. /* only variable size supported */
  246. if (sub == oid->len)
  247. goto err;
  248. cval = va_arg(ap, u_char **);
  249. sval = va_arg(ap, size_t *);
  250. *sval = oid->subs[sub++];
  251. if (sub + *sval > oid->len)
  252. goto err;
  253. if ((*cval = malloc(*sval)) == NULL) {
  254. syslog(LOG_ERR, "%s: %m", __func__);
  255. goto err;
  256. }
  257. octs[nocts++] = *cval;
  258. for (i = 0; i < *sval; i++) {
  259. if (oid->subs[sub] > 0xff)
  260. goto err;
  261. (*cval)[i] = oid->subs[sub++];
  262. }
  263. break;
  264. }
  265. case SNMP_SYNTAX_OID:
  266. {
  267. struct asn_oid *aval;
  268. u_int i;
  269. if (sub == oid->len)
  270. goto err;
  271. aval = va_arg(ap, struct asn_oid *);
  272. aval->len = oid->subs[sub++];
  273. if (aval->len > ASN_MAXOIDLEN)
  274. goto err;
  275. for (i = 0; i < aval->len; i++)
  276. aval->subs[i] = oid->subs[sub++];
  277. break;
  278. }
  279. case SNMP_SYNTAX_IPADDRESS:
  280. {
  281. u_int8_t *pval;
  282. u_int i;
  283. if (sub + 4 > oid->len)
  284. goto err;
  285. pval = va_arg(ap, u_int8_t *);
  286. for (i = 0; i < 4; i++) {
  287. if (oid->subs[sub] > 0xff)
  288. goto err;
  289. pval[i] = oid->subs[sub++];
  290. }
  291. break;
  292. }
  293. case SNMP_SYNTAX_COUNTER:
  294. case SNMP_SYNTAX_GAUGE:
  295. case SNMP_SYNTAX_TIMETICKS:
  296. if (sub == oid->len)
  297. goto err;
  298. if (oid->subs[sub] > 0xffffffff)
  299. goto err;
  300. *va_arg(ap, u_int32_t *) = oid->subs[sub++];
  301. break;
  302. }
  303. }
  304. va_end(ap);
  305. return (0);
  306. err:
  307. va_end(ap);
  308. while(nocts > 0)
  309. free(octs[--nocts]);
  310. return (-1);
  311. }
  312. /*
  313. * Compare the index part of an OID and an index.
  314. */
  315. int
  316. index_compare_off(const struct asn_oid *oid, u_int sub,
  317. const struct asn_oid *idx, u_int off)
  318. {
  319. u_int i;
  320. for (i = off; i < idx->len && i < oid->len - sub; i++) {
  321. if (oid->subs[sub + i] < idx->subs[i])
  322. return (-1);
  323. if (oid->subs[sub + i] > idx->subs[i])
  324. return (+1);
  325. }
  326. if (oid->len - sub < idx->len)
  327. return (-1);
  328. if (oid->len - sub > idx->len)
  329. return (+1);
  330. return (0);
  331. }
  332. int
  333. index_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx)
  334. {
  335. return (index_compare_off(oid, sub, idx, 0));
  336. }
  337. /*
  338. * Append an index to an oid
  339. */
  340. void
  341. index_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx,
  342. u_int off)
  343. {
  344. u_int i;
  345. var->len = sub + idx->len;
  346. for (i = off; i < idx->len; i++)
  347. var->subs[sub + i] = idx->subs[i];
  348. }
  349. void
  350. index_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx)
  351. {
  352. index_append_off(var, sub, idx, 0);
  353. }