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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors