snmp.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright 1998-2007 by egnite Software GmbH
  3. * Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. */
  33. #include <stdlib.h>
  34. #include <pro/snmp.h>
  35. #include <pro/snmp_api.h>
  36. /*!
  37. * \addtogroup xgSNMP
  38. */
  39. /*@{*/
  40. /*!
  41. * \brief Parse an SNMP variable.
  42. *
  43. * \param data Pointer to start of the name/value pair.
  44. * \param dlen Contains the number of valid bytes following the
  45. * start of the variable. On exit, it is returned as
  46. * the number of valid bytes following the end of
  47. * this variable.
  48. * \param name Pointer to a buffer that receives the name (OID).
  49. * \param nlen On entry, this contains the maximum number of
  50. * sub IDs accepted for the name. On exit, it is
  51. * returned as the actual number sub IDs found in
  52. * the name.
  53. * \param type Pointer to the variable that receives the ASN
  54. * type of the value.
  55. * \param value Pointer to variable that receives a pointer to
  56. * the ASN1 encoded value of variable.
  57. * \param vlen Pointer to the variable that receives the length
  58. * of the value.
  59. *
  60. * \return Pointer to the first byte past the end of this name/value pair.
  61. * Returns NULL on any error.
  62. */
  63. const uint8_t *SnmpVarParse(const uint8_t * data, size_t * dlen, OID * name, size_t * nlen, uint8_t * type,
  64. uint8_t ** value, size_t * vlen)
  65. {
  66. const uint8_t *dp;
  67. uint8_t vtype = ASN_SEQUENCE | ASN_CONSTRUCTOR;
  68. size_t len = *dlen;
  69. /* Get the object's length and check its type. */
  70. if ((dp = AsnSequenceParse(data, &len, vtype)) == NULL) {
  71. return NULL;
  72. }
  73. /* Get type, value and length of the name. */
  74. if ((dp = AsnOidParse(dp, &len, &vtype, name, nlen)) == NULL) {
  75. return NULL;
  76. }
  77. /* Check the name's type. */
  78. if (vtype != (uint8_t) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) {
  79. return NULL;
  80. }
  81. /* Return a pointer to the value. */
  82. *value = (uint8_t *) dp;
  83. /* Find out what type of object this is. */
  84. if ((dp = AsnHeaderParse(dp, &len, type)) == NULL) {
  85. return NULL;
  86. }
  87. *vlen = len;
  88. dp += *vlen;
  89. *dlen -= dp - data;
  90. return dp;
  91. }
  92. /*!
  93. * \brief Build an SNMP variable.
  94. *
  95. * \param data Pointer to start of the output buffer.
  96. * \param dlen Contains the number of valid bytes following the
  97. * start of the variable. On exit, it is returned as
  98. * the number of valid bytes following the end of
  99. * this variable.
  100. * \param name Name (OID).
  101. * \param nlen Number of sub IDs of the name.
  102. * \param type ASN type of the value.
  103. * \param value Pointer to the value.
  104. * \param vlen Length of the value.
  105. *
  106. * \return Pointer to the first byte past the end of this name/value pair.
  107. * Returns NULL on any error.
  108. */
  109. uint8_t *SnmpVarBuild(uint8_t * data, size_t * dlen, const OID * name, size_t nlen, uint8_t type, const uint8_t * value, size_t vlen)
  110. {
  111. size_t headerLen = 4;
  112. uint8_t *dp;
  113. /*
  114. * The final length is not known now, thus the header will have to
  115. * be build later.
  116. */
  117. if (*dlen < headerLen) {
  118. SnmpStatsInc(SNMP_STAT_OUTTOOBIGS);
  119. return NULL;
  120. }
  121. *dlen -= headerLen;
  122. dp = data + headerLen;
  123. /* Build the name. */
  124. if ((dp = AsnOidBuild(dp, dlen, ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID, name, nlen)) == NULL) {
  125. SnmpStatsInc(SNMP_STAT_OUTTOOBIGS);
  126. return NULL;
  127. }
  128. /* Build the value. */
  129. switch (type) {
  130. case ASN_INTEGER:
  131. dp = AsnIntegerBuild(dp, dlen, type, (long *) value);
  132. break;
  133. case ASN_GAUGE:
  134. case ASN_COUNTER:
  135. case ASN_TIMETICKS:
  136. case ASN_UINTEGER:
  137. dp = AsnUnsignedBuild(dp, dlen, type, (uint32_t *) value);
  138. break;
  139. case ASN_COUNTER64:
  140. dp = AsnUnsigned64Build(dp, dlen, type, (UNSIGNED64 *) value);
  141. break;
  142. case ASN_OCTET_STR:
  143. case ASN_IPADDRESS:
  144. case ASN_OPAQUE:
  145. case ASN_NSAP:
  146. dp = AsnOctetStringBuild(dp, dlen, type, value, vlen);
  147. break;
  148. case ASN_OBJECT_ID:
  149. dp = AsnOidBuild(dp, dlen, type, (OID *) value, vlen / sizeof(OID));
  150. break;
  151. case ASN_NULL:
  152. dp = AsnNullBuild(dp, dlen, type);
  153. break;
  154. case ASN_BIT_STR:
  155. dp = AsnBitStringBuild(dp, dlen, type, value, vlen);
  156. break;
  157. case SNMP_NOSUCHOBJECT:
  158. case SNMP_NOSUCHINSTANCE:
  159. case SNMP_ENDOFMIBVIEW:
  160. dp = AsnNullBuild(dp, dlen, type);
  161. break;
  162. default:
  163. SnmpStatsInc(SNMP_STAT_OUTBADVALUES);
  164. return NULL;
  165. }
  166. /* Now build the header. */
  167. if (dp) {
  168. size_t dummyLen = (dp - data) - headerLen;
  169. AsnSequenceBuild(data, &dummyLen, ASN_SEQUENCE | ASN_CONSTRUCTOR, dummyLen);
  170. } else {
  171. SnmpStatsInc(SNMP_STAT_OUTTOOBIGS);
  172. }
  173. return dp;
  174. }
  175. /*@}*/