snmp_msg.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:8k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * SNMP Message Encoding Routines
  3.  *
  4.  * Complies with:
  5.  *
  6.  * RFC 1901: Introduction to Community-based SNMPv2
  7.  * RFC 1157: A Simple Network Management Protocol (SNMP)
  8.  *
  9.  */
  10. /**********************************************************************
  11.  *
  12.  *           Copyright 1997 by Carnegie Mellon University
  13.  * 
  14.  *                       All Rights Reserved
  15.  * 
  16.  * Permission to use, copy, modify, and distribute this software and its
  17.  * documentation for any purpose and without fee is hereby granted,
  18.  * provided that the above copyright notice appear in all copies and that
  19.  * both that copyright notice and this permission notice appear in
  20.  * supporting documentation, and that the name of CMU not be
  21.  * used in advertising or publicity pertaining to distribution of the
  22.  * software without specific, written prior permission.
  23.  * 
  24.  * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  25.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  26.  * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  27.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  28.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  29.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  30.  * SOFTWARE.
  31.  * 
  32.  * Author: Ryan Troll <ryan+@andrew.cmu.edu>
  33.  * 
  34.  **********************************************************************/
  35. #include "config.h"
  36. #include <stdio.h>
  37. #if HAVE_UNISTD_H
  38. #include <unistd.h>
  39. #endif
  40. #if HAVE_STDLIB_H
  41. #include <stdlib.h>
  42. #endif
  43. #if HAVE_SYS_TYPES_H
  44. #include <sys/types.h>
  45. #endif
  46. #if HAVE_CTYPE_H
  47. #include <ctype.h>
  48. #endif
  49. #if HAVE_GNUMALLOC_H
  50. #include <gnumalloc.h>
  51. #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_)
  52. #include <malloc.h>
  53. #endif
  54. #if HAVE_MEMORY_H
  55. #include <memory.h>
  56. #endif
  57. #ifdef HAVE_STRING_H
  58. #include <string.h>
  59. #endif
  60. #ifdef HAVE_STRINGS_H
  61. #include <strings.h>
  62. #endif
  63. #if HAVE_BSTRING_H
  64. #include <bstring.h>
  65. #endif
  66. #if HAVE_SYS_SOCKET_H
  67. #include <sys/socket.h>
  68. #endif
  69. #if HAVE_NETINET_IN_H
  70. #include <netinet/in.h>
  71. #endif
  72. #if HAVE_ARPA_INET_H
  73. #include <arpa/inet.h>
  74. #endif
  75. #if HAVE_SYS_TIME_H
  76. #include <sys/time.h>
  77. #endif
  78. #if HAVE_NETDB_H
  79. #include <netdb.h>
  80. #endif
  81. #include "snmp.h"
  82. #include "asn1.h"
  83. #include "snmp_vars.h"
  84. #include "snmp_pdu.h"
  85. #include "snmp_msg.h"
  86. /* 
  87.  * RFC 1901: Introduction to Community-based SNMPv2
  88.  *
  89.  *  Message ::=
  90.  *    SEQUENCE {
  91.  *      version   INTEGER
  92.  *      community OCTET STRING
  93.  *      data
  94.  *    }
  95.  *
  96.  * RFC 1157: A Simple Network Management Protocol (SNMP)
  97.  *
  98.  *  Message ::=
  99.  *    SEQUENCE {
  100.  *      version   INTEGER
  101.  *      community OCTET STRING
  102.  *      data
  103.  *    }
  104.  *
  105.  */
  106. /* Encode a SNMP Message Header.  Return a pointer to the beginning of the
  107.  * data.
  108.  */
  109. #define ASN_PARSE_ERROR(x) {  return(x); }
  110. /* Encode an SNMP Message
  111.  *
  112.  * Returns a pointer to the end of the message, or NULL.
  113.  *
  114.  * *BufLenP (Second Argument) will contain the amount of space left
  115.  *          in the buffer.
  116.  */
  117. u_char *
  118. snmp_msg_Encode(u_char * Buffer, int *BufLenP,
  119.     u_char * Community, int CommLen,
  120.     int Version,
  121.     struct snmp_pdu * PDU)
  122. {
  123.     u_char *bufp, *tmp;
  124.     u_char *PDUHeaderPtr, *VARHeaderPtr;
  125.     u_char *PDUDataStart, *VARDataStart;
  126.     u_char *MsgPtr;
  127.     int FakeArg = 1024;
  128.     snmplib_debug(4, "Buffer=%x BufLenP=%x, buflen=%dn", Buffer, BufLenP,
  129. *BufLenP);
  130.     /* Header for the entire thing, with a false, large length */
  131.     bufp = asn_build_header(Buffer, BufLenP,
  132. (u_char) (ASN_SEQUENCE |
  133.     ASN_CONSTRUCTOR),
  134. (*BufLenP));
  135.     if (bufp == NULL) {
  136. snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Header)!n");
  137. return (NULL);
  138.     }
  139.     MsgPtr = bufp;
  140.     /* Version */
  141.     bufp = asn_build_int(bufp, BufLenP,
  142. (u_char) (ASN_UNIVERSAL |
  143.     ASN_PRIMITIVE |
  144.     ASN_INTEGER),
  145. (int *) (&Version), sizeof(Version));
  146.     if (bufp == NULL) {
  147. snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Version)!n");
  148. return (NULL);
  149.     }
  150.     snmplib_debug(8, "snmp_msg_Encode: Encoding community (%s) (%d)n", Community, CommLen);
  151.     /* Community */
  152.     bufp = asn_build_string(bufp, BufLenP,
  153. (u_char) (ASN_UNIVERSAL |
  154.     ASN_PRIMITIVE |
  155.     ASN_OCTET_STR),
  156. Community, CommLen);
  157.     if (bufp == NULL) {
  158. snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Community)!n");
  159. return (NULL);
  160.     }
  161.     /* Encode the rest. */
  162.     /* A nice header for this PDU. 
  163.      * Encoded with the wrong length.  We'll fix it later.
  164.      */
  165.     snmplib_debug(8, "snmp_msg_Encode:Encoding PDU Header at 0x%x (fake len %d) (%d bytes so far)n",
  166. bufp, *BufLenP, *BufLenP);
  167.     PDUHeaderPtr = bufp;
  168.     bufp = asn_build_header(bufp, BufLenP,
  169. (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  170. (*BufLenP));
  171.     if (bufp == NULL)
  172. return (NULL);
  173.     /* Encode this PDU. */
  174.     PDUDataStart = bufp;
  175.     bufp = snmp_pdu_encode(bufp, BufLenP, PDU);
  176.     if (bufp == NULL)
  177. return (NULL); /* snmp_pdu_encode registered failure */
  178.     VARHeaderPtr = bufp;
  179.     bufp = asn_build_header(bufp, BufLenP,
  180. (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  181. FakeArg);
  182.     if (bufp == NULL)
  183. return (NULL);
  184.     VARDataStart = bufp;
  185.     /* And build the variables */
  186.     bufp = snmp_var_EncodeVarBind(bufp, BufLenP, PDU->variables, Version);
  187.     if (bufp == NULL)
  188. return (NULL); /* snmp_var_EncodeVarBind registered failure */
  189.     /* Cool.  Now insert the appropriate lengths.
  190.      */
  191. #ifdef DEBUG_MSG_ENCODE
  192.     snmplib_debug(9, "Msg:  Vars returned 0x%x.  PDU Started at 0x%xn",
  193. bufp, PDUHeaderPtr);
  194.     snmplib_debug(9, "MSG:  Entire PDU length is %d (0x%x - 0x%x)n",
  195. (int) (bufp - PDUDataStart), PDUHeaderPtr, bufp);
  196. #endif
  197.     tmp = asn_build_header(PDUHeaderPtr, &FakeArg,
  198. (u_char) PDU->command,
  199. (int) (bufp - PDUDataStart));
  200.     /* Length of the PDU and Vars */
  201.     if (tmp == NULL)
  202. return (NULL);
  203. #ifdef DEBUG_MSG_ENCODE
  204.     snmplib_debug(9, "MSG:  Entire message length is %d (0x%x - 0x%x)n",
  205. (int) (bufp - MsgPtr), MsgPtr, bufp);
  206. #endif
  207.     tmp = asn_build_header(Buffer,
  208. &FakeArg,
  209. (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  210. (bufp - MsgPtr)); /* Length of everything */
  211.     if (tmp == NULL)
  212. return (NULL);
  213.     tmp = asn_build_header(VARHeaderPtr,
  214. &FakeArg,
  215. (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
  216. (bufp - VARDataStart)); /* Length of everything */
  217.     if (tmp == NULL)
  218. return (NULL);
  219.     *BufLenP = (bufp - Buffer);
  220.     return (u_char *) bufp;
  221. }
  222. /**********************************************************************/
  223. u_char *
  224. snmp_msg_Decode(u_char * Packet, int *PacketLenP,
  225.     u_char * Community, int *CommLenP,
  226.     int *Version, struct snmp_pdu * PDU)
  227. {
  228.     u_char *bufp;
  229.     u_char type;
  230.     bufp = asn_parse_header(Packet, PacketLenP, &type);
  231.     if (bufp == NULL) {
  232. snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Messsage Header (Header)!n");
  233. ASN_PARSE_ERROR(NULL);
  234.     }
  235.     if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
  236. snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Messsage Header (Header)!n");
  237. ASN_PARSE_ERROR(NULL);
  238.     }
  239.     bufp = asn_parse_int(bufp, PacketLenP,
  240. &type,
  241. (int *) Version, sizeof(*Version));
  242.     if (bufp == NULL) {
  243. snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Messsage Header (Version)!n");
  244. ASN_PARSE_ERROR(NULL);
  245.     }
  246.     bufp = asn_parse_string(bufp, PacketLenP, &type, Community, CommLenP);
  247.     if (bufp == NULL) {
  248. snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Messsage Header (Community)!n");
  249. ASN_PARSE_ERROR(NULL);
  250.     }
  251.     Community[*CommLenP] = '';
  252.     if ((*Version != SNMP_VERSION_1) &&
  253. (*Version != SNMP_VERSION_2)) {
  254. /* Don't know how to handle this one. */
  255. snmplib_debug(4, "snmp_msg_Decode:Unable to parse Version %un", *Version);
  256. snmplib_debug(4, "snmp_msg_Decode:Continuing anywayn");
  257.     }
  258.     /* Now that we know the header, decode the PDU */
  259.     /* XXXXX -- More than one PDU? */
  260.     bufp = snmp_pdu_decode(bufp, PacketLenP, PDU);
  261.     if (bufp == NULL)
  262. /* snmp_pdu_decode registered failure */
  263. return (NULL);
  264.     bufp = snmp_var_DecodeVarBind(bufp, PacketLenP, &(PDU->variables), *Version);
  265.     if (bufp == NULL)
  266. /* snmp_var_DecodeVarBind registered failure */
  267. return (NULL);
  268.     return (u_char *) bufp;
  269. }