]> git.ipfire.org Git - thirdparty/squid.git/blame - snmplib/snmp_msg.c
SourceFormat Enforcement
[thirdparty/squid.git] / snmplib / snmp_msg.c
CommitLineData
85269fdf 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
26ac0430 13 *
85269fdf 14 * All Rights Reserved
26ac0430 15 *
85269fdf 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.
26ac0430 23 *
85269fdf 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.
26ac0430 31 *
85269fdf 32 * Author: Ryan Troll <ryan+@andrew.cmu.edu>
26ac0430 33 *
85269fdf 34 **********************************************************************/
35
f7f3304a 36#include "squid.h"
85269fdf 37
38#include <stdio.h>
39
40#if HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#if HAVE_STDLIB_H
44#include <stdlib.h>
45#endif
46#if HAVE_SYS_TYPES_H
47#include <sys/types.h>
48#endif
49#if HAVE_CTYPE_H
50#include <ctype.h>
51#endif
52#if HAVE_GNUMALLOC_H
53#include <gnumalloc.h>
482aa790 54#elif HAVE_MALLOC_H
85269fdf 55#include <malloc.h>
56#endif
57#if HAVE_MEMORY_H
58#include <memory.h>
59#endif
32d002cb 60#if HAVE_STRING_H
85269fdf 61#include <string.h>
62#endif
32d002cb 63#if HAVE_STRINGS_H
85269fdf 64#include <strings.h>
65#endif
66#if HAVE_BSTRING_H
67#include <bstring.h>
68#endif
69#if HAVE_SYS_SOCKET_H
70#include <sys/socket.h>
71#endif
72#if HAVE_NETINET_IN_H
73#include <netinet/in.h>
74#endif
75#if HAVE_ARPA_INET_H
76#include <arpa/inet.h>
77#endif
78#if HAVE_SYS_TIME_H
79#include <sys/time.h>
80#endif
81#if HAVE_NETDB_H
82#include <netdb.h>
83#endif
84
85269fdf 85#include "asn1.h"
602d9612 86#include "snmp.h"
85269fdf 87#include "snmp_msg.h"
602d9612
A
88#include "snmp_pdu.h"
89#include "snmp_vars.h"
85269fdf 90
26ac0430 91/*
85269fdf 92 * RFC 1901: Introduction to Community-based SNMPv2
93 *
94 * Message ::=
95 * SEQUENCE {
96 * version INTEGER
97 * community OCTET STRING
98 * data
99 * }
100 *
101 * RFC 1157: A Simple Network Management Protocol (SNMP)
102 *
103 * Message ::=
104 * SEQUENCE {
105 * version INTEGER
106 * community OCTET STRING
107 * data
108 * }
109 *
110 */
111
112/* Encode a SNMP Message Header. Return a pointer to the beginning of the
113 * data.
114 */
115
43d4303e 116#define ASN_PARSE_ERROR(x) { return(x); }
85269fdf 117
118/* Encode an SNMP Message
119 *
120 * Returns a pointer to the end of the message, or NULL.
121 *
122 * *BufLenP (Second Argument) will contain the amount of space left
123 * in the buffer.
124 */
125
43d4303e 126u_char *
127snmp_msg_Encode(u_char * Buffer, int *BufLenP,
26ac0430
AJ
128 u_char * Community, int CommLen,
129 int Version,
130 struct snmp_pdu *PDU)
85269fdf 131{
43d4303e 132 u_char *bufp, *tmp;
133 u_char *PDUHeaderPtr, *VARHeaderPtr;
134 u_char *PDUDataStart, *VARDataStart;
135 u_char *MsgPtr;
136 int FakeArg = 1024;
137
33272404 138 snmplib_debug(4, "Buffer=%p BufLenP=%p, buflen=%d\n", Buffer, BufLenP,
26ac0430 139 *BufLenP);
43d4303e 140 /* Header for the entire thing, with a false, large length */
141 bufp = asn_build_header(Buffer, BufLenP,
26ac0430
AJ
142 (u_char) (ASN_SEQUENCE |
143 ASN_CONSTRUCTOR),
144 (*BufLenP));
43d4303e 145 if (bufp == NULL) {
26ac0430
AJ
146 snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Header)!\n");
147 return (NULL);
43d4303e 148 }
149 MsgPtr = bufp;
150
151 /* Version */
152 bufp = asn_build_int(bufp, BufLenP,
26ac0430
AJ
153 (u_char) (ASN_UNIVERSAL |
154 ASN_PRIMITIVE |
155 ASN_INTEGER),
156 (int *) (&Version), sizeof(Version));
43d4303e 157 if (bufp == NULL) {
26ac0430
AJ
158 snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Version)!\n");
159 return (NULL);
43d4303e 160 }
161 snmplib_debug(8, "snmp_msg_Encode: Encoding community (%s) (%d)\n", Community, CommLen);
162
163 /* Community */
164 bufp = asn_build_string(bufp, BufLenP,
26ac0430
AJ
165 (u_char) (ASN_UNIVERSAL |
166 ASN_PRIMITIVE |
167 ASN_OCTET_STR),
168 Community, CommLen);
43d4303e 169 if (bufp == NULL) {
26ac0430
AJ
170 snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Community)!\n");
171 return (NULL);
43d4303e 172 }
173 /* Encode the rest. */
174
26ac0430 175 /* A nice header for this PDU.
43d4303e 176 * Encoded with the wrong length. We'll fix it later.
177 */
33272404 178 snmplib_debug(8, "snmp_msg_Encode:Encoding PDU Header at 0x%p (fake len %d) (%d bytes so far)\n",
26ac0430 179 bufp, *BufLenP, *BufLenP);
43d4303e 180 PDUHeaderPtr = bufp;
181 bufp = asn_build_header(bufp, BufLenP,
26ac0430
AJ
182 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
183 (*BufLenP));
43d4303e 184 if (bufp == NULL)
26ac0430 185 return (NULL);
43d4303e 186
187 /* Encode this PDU. */
188 PDUDataStart = bufp;
189 bufp = snmp_pdu_encode(bufp, BufLenP, PDU);
190 if (bufp == NULL)
26ac0430 191 return (NULL); /* snmp_pdu_encode registered failure */
43d4303e 192
193 VARHeaderPtr = bufp;
194 bufp = asn_build_header(bufp, BufLenP,
26ac0430
AJ
195 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
196 FakeArg);
43d4303e 197 if (bufp == NULL)
26ac0430 198 return (NULL);
43d4303e 199 VARDataStart = bufp;
200
201 /* And build the variables */
202 bufp = snmp_var_EncodeVarBind(bufp, BufLenP, PDU->variables, Version);
203 if (bufp == NULL)
26ac0430 204 return (NULL); /* snmp_var_EncodeVarBind registered failure */
43d4303e 205
206 /* Cool. Now insert the appropriate lengths.
207 */
32d002cb 208#if DEBUG_MSG_ENCODE
43d4303e 209 snmplib_debug(9, "Msg: Vars returned 0x%x. PDU Started at 0x%x\n",
26ac0430 210 bufp, PDUHeaderPtr);
43d4303e 211 snmplib_debug(9, "MSG: Entire PDU length is %d (0x%x - 0x%x)\n",
26ac0430 212 (int) (bufp - PDUDataStart), PDUHeaderPtr, bufp);
85269fdf 213#endif
43d4303e 214 tmp = asn_build_header(PDUHeaderPtr, &FakeArg,
26ac0430
AJ
215 (u_char) PDU->command,
216 (int) (bufp - PDUDataStart));
43d4303e 217 /* Length of the PDU and Vars */
218 if (tmp == NULL)
26ac0430 219 return (NULL);
85269fdf 220
32d002cb 221#if DEBUG_MSG_ENCODE
43d4303e 222 snmplib_debug(9, "MSG: Entire message length is %d (0x%x - 0x%x)\n",
26ac0430 223 (int) (bufp - MsgPtr), MsgPtr, bufp);
85269fdf 224#endif
43d4303e 225 tmp = asn_build_header(Buffer,
26ac0430
AJ
226 &FakeArg,
227 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
228 (bufp - MsgPtr)); /* Length of everything */
43d4303e 229 if (tmp == NULL)
26ac0430 230 return (NULL);
43d4303e 231
232 tmp = asn_build_header(VARHeaderPtr,
26ac0430
AJ
233 &FakeArg,
234 (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
235 (bufp - VARDataStart)); /* Length of everything */
43d4303e 236 if (tmp == NULL)
26ac0430 237 return (NULL);
43d4303e 238
239 *BufLenP = (bufp - Buffer);
240 return (u_char *) bufp;
85269fdf 241}
242
243/**********************************************************************/
244
43d4303e 245u_char *
246snmp_msg_Decode(u_char * Packet, int *PacketLenP,
26ac0430
AJ
247 u_char * Community, int *CommLenP,
248 int *Version, struct snmp_pdu * PDU)
85269fdf 249{
43d4303e 250 u_char *bufp;
251 u_char type;
252
253 bufp = asn_parse_header(Packet, PacketLenP, &type);
254 if (bufp == NULL) {
14e9491b 255 snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n");
26ac0430 256 ASN_PARSE_ERROR(NULL);
43d4303e 257 }
258 if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {
14e9491b 259 snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n");
26ac0430 260 ASN_PARSE_ERROR(NULL);
43d4303e 261 }
262 bufp = asn_parse_int(bufp, PacketLenP,
26ac0430
AJ
263 &type,
264 (int *) Version, sizeof(*Version));
43d4303e 265 if (bufp == NULL) {
14e9491b 266 snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Version)!\n");
26ac0430 267 ASN_PARSE_ERROR(NULL);
43d4303e 268 }
269 bufp = asn_parse_string(bufp, PacketLenP, &type, Community, CommLenP);
270 if (bufp == NULL) {
14e9491b 271 snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Community)!\n");
26ac0430 272 ASN_PARSE_ERROR(NULL);
43d4303e 273 }
274 Community[*CommLenP] = '\0';
275
276 if ((*Version != SNMP_VERSION_1) &&
26ac0430 277 (*Version != SNMP_VERSION_2)) {
43d4303e 278
26ac0430
AJ
279 /* Don't know how to handle this one. */
280 snmplib_debug(4, "snmp_msg_Decode:Unable to parse Version %u\n", *Version);
281 snmplib_debug(4, "snmp_msg_Decode:Continuing anyway\n");
43d4303e 282 }
283 /* Now that we know the header, decode the PDU */
284
285 /* XXXXX -- More than one PDU? */
286 bufp = snmp_pdu_decode(bufp, PacketLenP, PDU);
287 if (bufp == NULL)
26ac0430
AJ
288 /* snmp_pdu_decode registered failure */
289 return (NULL);
43d4303e 290
291 bufp = snmp_var_DecodeVarBind(bufp, PacketLenP, &(PDU->variables), *Version);
292 if (bufp == NULL)
26ac0430
AJ
293 /* snmp_var_DecodeVarBind registered failure */
294 return (NULL);
43d4303e 295
296 return (u_char *) bufp;
85269fdf 297}