]>
Commit | Line | Data |
---|---|---|
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 | 126 | u_char * |
127 | snmp_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 | 245 | u_char * |
246 | snmp_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 | } |