]>
Commit | Line | Data |
---|---|---|
c04fda28 AJ |
1 | /* |
2 | * Copyright (C) 1996-2014 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 | ||
85269fdf | 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 | |
26ac0430 | 21 | * |
85269fdf | 22 | * All Rights Reserved |
26ac0430 | 23 | * |
85269fdf | 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. | |
26ac0430 | 31 | * |
85269fdf | 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. | |
26ac0430 | 39 | * |
85269fdf | 40 | * Author: Ryan Troll <ryan+@andrew.cmu.edu> |
26ac0430 | 41 | * |
85269fdf | 42 | **********************************************************************/ |
43 | ||
f7f3304a | 44 | #include "squid.h" |
85269fdf | 45 | |
85269fdf | 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> | |
482aa790 | 60 | #elif HAVE_MALLOC_H |
85269fdf | 61 | #include <malloc.h> |
62 | #endif | |
63 | #if HAVE_MEMORY_H | |
64 | #include <memory.h> | |
65 | #endif | |
32d002cb | 66 | #if HAVE_STRING_H |
85269fdf | 67 | #include <string.h> |
68 | #endif | |
32d002cb | 69 | #if HAVE_STRINGS_H |
85269fdf | 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 | ||
85269fdf | 91 | #include "asn1.h" |
602d9612 | 92 | #include "snmp.h" |
85269fdf | 93 | #include "snmp_msg.h" |
602d9612 A |
94 | #include "snmp_pdu.h" |
95 | #include "snmp_vars.h" | |
85269fdf | 96 | |
26ac0430 | 97 | /* |
85269fdf | 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 | ||
43d4303e | 122 | #define ASN_PARSE_ERROR(x) { return(x); } |
85269fdf | 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 | ||
43d4303e | 132 | u_char * |
133 | snmp_msg_Encode(u_char * Buffer, int *BufLenP, | |
26ac0430 AJ |
134 | u_char * Community, int CommLen, |
135 | int Version, | |
136 | struct snmp_pdu *PDU) | |
85269fdf | 137 | { |
43d4303e | 138 | u_char *bufp, *tmp; |
139 | u_char *PDUHeaderPtr, *VARHeaderPtr; | |
140 | u_char *PDUDataStart, *VARDataStart; | |
141 | u_char *MsgPtr; | |
142 | int FakeArg = 1024; | |
143 | ||
33272404 | 144 | snmplib_debug(4, "Buffer=%p BufLenP=%p, buflen=%d\n", Buffer, BufLenP, |
26ac0430 | 145 | *BufLenP); |
43d4303e | 146 | /* Header for the entire thing, with a false, large length */ |
147 | bufp = asn_build_header(Buffer, BufLenP, | |
26ac0430 AJ |
148 | (u_char) (ASN_SEQUENCE | |
149 | ASN_CONSTRUCTOR), | |
150 | (*BufLenP)); | |
43d4303e | 151 | if (bufp == NULL) { |
26ac0430 AJ |
152 | snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Header)!\n"); |
153 | return (NULL); | |
43d4303e | 154 | } |
155 | MsgPtr = bufp; | |
156 | ||
157 | /* Version */ | |
158 | bufp = asn_build_int(bufp, BufLenP, | |
26ac0430 AJ |
159 | (u_char) (ASN_UNIVERSAL | |
160 | ASN_PRIMITIVE | | |
161 | ASN_INTEGER), | |
162 | (int *) (&Version), sizeof(Version)); | |
43d4303e | 163 | if (bufp == NULL) { |
26ac0430 AJ |
164 | snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Version)!\n"); |
165 | return (NULL); | |
43d4303e | 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, | |
26ac0430 AJ |
171 | (u_char) (ASN_UNIVERSAL | |
172 | ASN_PRIMITIVE | | |
173 | ASN_OCTET_STR), | |
174 | Community, CommLen); | |
43d4303e | 175 | if (bufp == NULL) { |
26ac0430 AJ |
176 | snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Community)!\n"); |
177 | return (NULL); | |
43d4303e | 178 | } |
179 | /* Encode the rest. */ | |
180 | ||
26ac0430 | 181 | /* A nice header for this PDU. |
43d4303e | 182 | * Encoded with the wrong length. We'll fix it later. |
183 | */ | |
33272404 | 184 | snmplib_debug(8, "snmp_msg_Encode:Encoding PDU Header at 0x%p (fake len %d) (%d bytes so far)\n", |
26ac0430 | 185 | bufp, *BufLenP, *BufLenP); |
43d4303e | 186 | PDUHeaderPtr = bufp; |
187 | bufp = asn_build_header(bufp, BufLenP, | |
26ac0430 AJ |
188 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), |
189 | (*BufLenP)); | |
43d4303e | 190 | if (bufp == NULL) |
26ac0430 | 191 | return (NULL); |
43d4303e | 192 | |
193 | /* Encode this PDU. */ | |
194 | PDUDataStart = bufp; | |
195 | bufp = snmp_pdu_encode(bufp, BufLenP, PDU); | |
196 | if (bufp == NULL) | |
f53969cc | 197 | return (NULL); /* snmp_pdu_encode registered failure */ |
43d4303e | 198 | |
199 | VARHeaderPtr = bufp; | |
200 | bufp = asn_build_header(bufp, BufLenP, | |
26ac0430 AJ |
201 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), |
202 | FakeArg); | |
43d4303e | 203 | if (bufp == NULL) |
26ac0430 | 204 | return (NULL); |
43d4303e | 205 | VARDataStart = bufp; |
206 | ||
207 | /* And build the variables */ | |
208 | bufp = snmp_var_EncodeVarBind(bufp, BufLenP, PDU->variables, Version); | |
209 | if (bufp == NULL) | |
f53969cc | 210 | return (NULL); /* snmp_var_EncodeVarBind registered failure */ |
43d4303e | 211 | |
212 | /* Cool. Now insert the appropriate lengths. | |
213 | */ | |
32d002cb | 214 | #if DEBUG_MSG_ENCODE |
43d4303e | 215 | snmplib_debug(9, "Msg: Vars returned 0x%x. PDU Started at 0x%x\n", |
26ac0430 | 216 | bufp, PDUHeaderPtr); |
43d4303e | 217 | snmplib_debug(9, "MSG: Entire PDU length is %d (0x%x - 0x%x)\n", |
26ac0430 | 218 | (int) (bufp - PDUDataStart), PDUHeaderPtr, bufp); |
85269fdf | 219 | #endif |
43d4303e | 220 | tmp = asn_build_header(PDUHeaderPtr, &FakeArg, |
26ac0430 AJ |
221 | (u_char) PDU->command, |
222 | (int) (bufp - PDUDataStart)); | |
43d4303e | 223 | /* Length of the PDU and Vars */ |
224 | if (tmp == NULL) | |
26ac0430 | 225 | return (NULL); |
85269fdf | 226 | |
32d002cb | 227 | #if DEBUG_MSG_ENCODE |
43d4303e | 228 | snmplib_debug(9, "MSG: Entire message length is %d (0x%x - 0x%x)\n", |
26ac0430 | 229 | (int) (bufp - MsgPtr), MsgPtr, bufp); |
85269fdf | 230 | #endif |
43d4303e | 231 | tmp = asn_build_header(Buffer, |
26ac0430 AJ |
232 | &FakeArg, |
233 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), | |
f53969cc | 234 | (bufp - MsgPtr)); /* Length of everything */ |
43d4303e | 235 | if (tmp == NULL) |
26ac0430 | 236 | return (NULL); |
43d4303e | 237 | |
238 | tmp = asn_build_header(VARHeaderPtr, | |
26ac0430 AJ |
239 | &FakeArg, |
240 | (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), | |
f53969cc | 241 | (bufp - VARDataStart)); /* Length of everything */ |
43d4303e | 242 | if (tmp == NULL) |
26ac0430 | 243 | return (NULL); |
43d4303e | 244 | |
245 | *BufLenP = (bufp - Buffer); | |
246 | return (u_char *) bufp; | |
85269fdf | 247 | } |
248 | ||
249 | /**********************************************************************/ | |
250 | ||
43d4303e | 251 | u_char * |
252 | snmp_msg_Decode(u_char * Packet, int *PacketLenP, | |
26ac0430 AJ |
253 | u_char * Community, int *CommLenP, |
254 | int *Version, struct snmp_pdu * PDU) | |
85269fdf | 255 | { |
43d4303e | 256 | u_char *bufp; |
257 | u_char type; | |
258 | ||
259 | bufp = asn_parse_header(Packet, PacketLenP, &type); | |
260 | if (bufp == NULL) { | |
14e9491b | 261 | snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n"); |
26ac0430 | 262 | ASN_PARSE_ERROR(NULL); |
43d4303e | 263 | } |
264 | if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { | |
14e9491b | 265 | snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n"); |
26ac0430 | 266 | ASN_PARSE_ERROR(NULL); |
43d4303e | 267 | } |
268 | bufp = asn_parse_int(bufp, PacketLenP, | |
26ac0430 AJ |
269 | &type, |
270 | (int *) Version, sizeof(*Version)); | |
43d4303e | 271 | if (bufp == NULL) { |
14e9491b | 272 | snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Version)!\n"); |
26ac0430 | 273 | ASN_PARSE_ERROR(NULL); |
43d4303e | 274 | } |
275 | bufp = asn_parse_string(bufp, PacketLenP, &type, Community, CommLenP); | |
276 | if (bufp == NULL) { | |
14e9491b | 277 | snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Community)!\n"); |
26ac0430 | 278 | ASN_PARSE_ERROR(NULL); |
43d4303e | 279 | } |
280 | Community[*CommLenP] = '\0'; | |
281 | ||
282 | if ((*Version != SNMP_VERSION_1) && | |
26ac0430 | 283 | (*Version != SNMP_VERSION_2)) { |
43d4303e | 284 | |
26ac0430 AJ |
285 | /* Don't know how to handle this one. */ |
286 | snmplib_debug(4, "snmp_msg_Decode:Unable to parse Version %u\n", *Version); | |
287 | snmplib_debug(4, "snmp_msg_Decode:Continuing anyway\n"); | |
43d4303e | 288 | } |
289 | /* Now that we know the header, decode the PDU */ | |
290 | ||
291 | /* XXXXX -- More than one PDU? */ | |
292 | bufp = snmp_pdu_decode(bufp, PacketLenP, PDU); | |
293 | if (bufp == NULL) | |
26ac0430 AJ |
294 | /* snmp_pdu_decode registered failure */ |
295 | return (NULL); | |
43d4303e | 296 | |
297 | bufp = snmp_var_DecodeVarBind(bufp, PacketLenP, &(PDU->variables), *Version); | |
298 | if (bufp == NULL) | |
26ac0430 AJ |
299 | /* snmp_var_DecodeVarBind registered failure */ |
300 | return (NULL); | |
43d4303e | 301 | |
302 | return (u_char *) bufp; | |
85269fdf | 303 | } |
f53969cc | 304 |