]>
git.ipfire.org Git - thirdparty/squid.git/blob - snmplib/snmp_pdu.c
6 * RFC 1902: Structure of Management Information for SNMPv2
10 /**********************************************************************
12 * Copyright 1997 by Carnegie Mellon University
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.
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
32 * Author: Ryan Troll <ryan+@andrew.cmu.edu>
34 **********************************************************************/
47 #include <sys/types.h>
53 #include <gnumalloc.h>
70 #include <sys/socket.h>
73 #include <netinet/in.h>
76 #include <arpa/inet.h>
87 #include "snmp_error.h"
88 #include "snmp_vars.h"
91 #include "snmp_api_error.h"
95 /* #define DEBUG_PDU 1 */
96 /* #define DEBUG_PDU_DECODE 1 */
97 /* #define DEBUG_PDU_ENCODE 1 */
99 #define ASN_PARSE_ERROR(x) { return(x); }
101 /**********************************************************************/
107 snmp_pdu_create(int command
) {
108 struct snmp_pdu
*pdu
;
111 snmplib_debug(8, "PDU: Creating\n");
114 pdu
= (struct snmp_pdu
*) xmalloc(sizeof(struct snmp_pdu
));
116 snmp_set_api_error(SNMPERR_OS_ERR
);
119 memset((char *) pdu
, '\0', sizeof(struct snmp_pdu
));
121 pdu
->command
= command
;
122 pdu
->errstat
= SNMP_DEFAULT_ERRSTAT
;
123 pdu
->errindex
= SNMP_DEFAULT_ERRINDEX
;
124 pdu
->address
.sin_addr
.s_addr
= SNMP_DEFAULT_ADDRESS
;
125 pdu
->enterprise
= NULL
;
126 pdu
->enterprise_length
= 0;
127 pdu
->variables
= NULL
;
130 snmplib_debug(8, "PDU: Created %x\n", (unsigned int) pdu
);
136 /**********************************************************************/
138 /* Clone an existing PDU.
141 snmp_pdu_clone(struct snmp_pdu
*Src
) {
142 struct snmp_pdu
*Dest
;
145 snmplib_debug(8, "PDU %x: Cloning\n", (unsigned int) Src
);
148 Dest
= (struct snmp_pdu
*) xmalloc(sizeof(struct snmp_pdu
));
150 snmp_set_api_error(SNMPERR_OS_ERR
);
153 xmemcpy((char *) Dest
, (char *) Src
, sizeof(struct snmp_pdu
));
156 snmplib_debug(8, "PDU %x: Created %x\n", (unsigned int) Src
, (unsigned int) Dest
);
161 /**********************************************************************/
164 * If there was an error in the input pdu, creates a clone of the pdu
165 * that includes all the variables except the one marked by the errindex.
166 * The command is set to the input command and the reqid, errstat, and
167 * errindex are set to default values.
168 * If the error status didn't indicate an error, the error index didn't
169 * indicate a variable, the pdu wasn't a get response message, or there
170 * would be no remaining variables, this function will return NULL.
171 * If everything was successful, a pointer to the fixed cloned pdu will
175 snmp_pdu_fix(struct snmp_pdu
*pdu
, int command
) {
176 return (snmp_fix_pdu(pdu
, command
));
180 snmp_fix_pdu(struct snmp_pdu
*pdu
, int command
) {
181 struct variable_list
*var
, *newvar
;
182 struct snmp_pdu
*newpdu
;
187 snmplib_debug(8, "PDU %x: Fixing. Err index is %d\n",
188 (unsigned int) pdu
, (unsigned int) pdu
->errindex
);
191 if (pdu
->command
!= SNMP_PDU_RESPONSE
||
192 pdu
->errstat
== SNMP_ERR_NOERROR
||
193 pdu
->errindex
<= 0) {
194 snmp_set_api_error(SNMPERR_UNABLE_TO_FIX
);
198 newpdu
= snmp_pdu_clone(pdu
);
202 newpdu
->variables
= 0;
203 newpdu
->command
= command
;
204 newpdu
->reqid
= SNMP_DEFAULT_REQID
;
205 newpdu
->errstat
= SNMP_DEFAULT_ERRSTAT
;
206 newpdu
->errindex
= SNMP_DEFAULT_ERRINDEX
;
208 /* Loop through the variables, removing whatever isn't necessary */
210 var
= pdu
->variables
;
213 /* skip first variable if necessary */
214 if (pdu
->errindex
== i
) {
215 var
= var
->next_variable
;
220 /* VAR is the first uncopied variable */
222 /* Clone this variable */
223 newpdu
->variables
= snmp_var_clone(var
);
224 if (newpdu
->variables
== NULL
) {
225 snmp_pdu_free(newpdu
);
230 newvar
= newpdu
->variables
;
232 /* VAR has been copied to NEWVAR. */
233 while (var
->next_variable
) {
235 /* Skip the item that was bad */
236 if (++i
== pdu
->errindex
) {
237 var
= var
->next_variable
;
241 newvar
->next_variable
= snmp_var_clone(var
->next_variable
);
242 if (newvar
->next_variable
== NULL
) {
243 snmp_pdu_free(newpdu
);
246 /* Move to the next one */
247 newvar
= newvar
->next_variable
;
248 var
= var
->next_variable
;
251 newvar
->next_variable
= NULL
;
253 /* If we didn't copy anything, free the new pdu. */
254 if (i
< pdu
->errindex
|| copied
== 0) {
255 snmp_free_pdu(newpdu
);
256 snmp_set_api_error(SNMPERR_UNABLE_TO_FIX
);
260 snmplib_debug(8, "PDU %x: Fixed PDU is %x\n",
261 (unsigned int) pdu
, (unsigned int) newpdu
);
267 /**********************************************************************/
270 snmp_pdu_free(struct snmp_pdu
*pdu
)
276 * Frees the pdu and any xmalloc'd data associated with it.
279 snmp_free_pdu(struct snmp_pdu
*pdu
)
281 struct variable_list
*vp
, *ovp
;
286 vp
= vp
->next_variable
;
291 xfree((char *) pdu
->enterprise
);
295 /**********************************************************************/
297 /* Encode this PDU into DestBuf.
299 * Returns a pointer to the next byte in the buffer (where the Variable
304 * RFC 1902: Structure of Management Information for SNMPv2
308 * request-id INTEGER32
309 * error-status INTEGER
310 * error-index INTEGER
316 * request-id INTEGER32
317 * non-repeaters INTEGER
318 * max-repetitions INTEGER
324 * RFC 1157: A Simple Network Management Protocol (SNMP)
329 * error-status INTEGER
330 * error-index INTEGER
336 * enterprise NetworkAddress
337 * generic-trap INTEGER
338 * specific-trap INTEGER
339 * time-stamp TIMETICKS
345 snmp_pdu_encode(u_char
* DestBuf
, int *DestBufLen
,
346 struct snmp_pdu
*PDU
)
350 #ifdef DEBUG_PDU_ENCODE
351 snmplib_debug(8, "PDU: Encoding %d\n", PDU
->command
);
355 switch (PDU
->command
) {
357 /**********************************************************************/
364 bufp
= asn_build_objid(DestBuf
, DestBufLen
,
365 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OBJECT_ID
),
366 (oid
*) PDU
->enterprise
, PDU
->enterprise_length
);
371 bufp
= asn_build_string(bufp
, DestBufLen
,
372 (u_char
) (SMI_IPADDRESS
| ASN_PRIMITIVE
),
373 (u_char
*) & PDU
->agent_addr
.sin_addr
.s_addr
,
374 sizeof(PDU
->agent_addr
.sin_addr
.s_addr
));
379 bufp
= asn_build_int(bufp
, DestBufLen
,
380 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
381 (int *) &PDU
->trap_type
, sizeof(PDU
->trap_type
));
386 bufp
= asn_build_int(bufp
, DestBufLen
,
387 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
388 (int *) &PDU
->specific_type
,
389 sizeof(PDU
->specific_type
));
394 bufp
= asn_build_unsigned_int(bufp
, DestBufLen
,
395 (u_char
) (SMI_TIMETICKS
| ASN_PRIMITIVE
),
396 &PDU
->time
, sizeof(PDU
->time
));
402 /**********************************************************************/
404 case SNMP_PDU_GETBULK
:
406 /* SNMPv2 Bulk Request */
409 bufp
= asn_build_int(DestBuf
, DestBufLen
,
410 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
411 &PDU
->reqid
, sizeof(PDU
->reqid
));
416 bufp
= asn_build_int(bufp
, DestBufLen
,
417 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
419 sizeof(PDU
->non_repeaters
));
423 /* max-repetitions */
424 bufp
= asn_build_int(bufp
, DestBufLen
,
425 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
426 &PDU
->max_repetitions
,
427 sizeof(PDU
->max_repetitions
));
432 /**********************************************************************/
436 /* Normal PDU Encoding */
439 #ifdef DEBUG_PDU_ENCODE
440 snmplib_debug(8, "PDU: Request ID %d (0x%x)\n", PDU
->reqid
, DestBuf
);
442 bufp
= asn_build_int(DestBuf
, DestBufLen
,
443 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
444 &PDU
->reqid
, sizeof(PDU
->reqid
));
449 #ifdef DEBUG_PDU_ENCODE
450 snmplib_debug(8, "PDU: Error Status %d (0x%x)\n", PDU
->errstat
, bufp
);
452 bufp
= asn_build_int(bufp
, DestBufLen
,
453 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
454 &PDU
->errstat
, sizeof(PDU
->errstat
));
459 #ifdef DEBUG_PDU_ENCODE
460 snmplib_debug(8, "PDU: Error index %d (0x%x)\n", PDU
->errindex
, bufp
);
462 bufp
= asn_build_int(bufp
, DestBufLen
,
463 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
464 &PDU
->errindex
, sizeof(PDU
->errindex
));
468 } /* End of encoding */
473 /**********************************************************************/
475 /* Decodes PDU from Packet into PDU.
477 * Returns a pointer to the next byte of the packet, which is where the
478 * Variable Bindings start.
481 snmp_pdu_decode(u_char
* Packet
, /* data */
482 int *Length
, /* &length */
483 struct snmp_pdu
* PDU
)
490 oid objid
[MAX_NAME_LEN
];
493 bufp
= asn_parse_header(Packet
, Length
, &PDUType
);
495 ASN_PARSE_ERROR(NULL
);
497 #ifdef DEBUG_PDU_DECODE
498 snmplib_debug(8, "PDU Type: %d\n", PDUType
);
501 PDU
->command
= PDUType
;
507 /* SNMPv1 Trap Message */
510 PDU
->enterprise_length
= MAX_NAME_LEN
;
511 bufp
= asn_parse_objid(bufp
, Length
,
512 &ASNType
, objid
, &PDU
->enterprise_length
);
514 ASN_PARSE_ERROR(NULL
);
516 PDU
->enterprise
= (oid
*) xmalloc(PDU
->enterprise_length
* sizeof(oid
));
517 if (PDU
->enterprise
== NULL
) {
518 snmp_set_api_error(SNMPERR_OS_ERR
);
521 xmemcpy((char *) PDU
->enterprise
, (char *) objid
,
522 PDU
->enterprise_length
* sizeof(oid
));
526 bufp
= asn_parse_string(bufp
, Length
,
528 (u_char
*) & PDU
->agent_addr
.sin_addr
.s_addr
,
531 ASN_PARSE_ERROR(NULL
);
534 bufp
= asn_parse_int(bufp
, Length
,
536 (int *) &PDU
->trap_type
,
537 sizeof(PDU
->trap_type
));
539 ASN_PARSE_ERROR(NULL
);
542 bufp
= asn_parse_int(bufp
, Length
,
544 (int *) &PDU
->specific_type
,
545 sizeof(PDU
->specific_type
));
547 ASN_PARSE_ERROR(NULL
);
550 bufp
= asn_parse_unsigned_int(bufp
, Length
,
552 &PDU
->time
, sizeof(PDU
->time
));
554 ASN_PARSE_ERROR(NULL
);
558 /**********************************************************************/
560 case SNMP_PDU_GETBULK
:
562 /* SNMPv2 Bulk Request */
565 bufp
= asn_parse_int(bufp
, Length
,
567 &PDU
->reqid
, sizeof(PDU
->reqid
));
569 ASN_PARSE_ERROR(NULL
);
572 bufp
= asn_parse_int(bufp
, Length
,
574 &PDU
->non_repeaters
, sizeof(PDU
->non_repeaters
));
576 ASN_PARSE_ERROR(NULL
);
578 /* max-repetitions */
579 bufp
= asn_parse_int(bufp
, Length
,
581 &PDU
->max_repetitions
, sizeof(PDU
->max_repetitions
));
583 ASN_PARSE_ERROR(NULL
);
586 /**********************************************************************/
590 /* Normal PDU Encoding */
593 bufp
= asn_parse_int(bufp
, Length
,
595 &PDU
->reqid
, sizeof(PDU
->reqid
));
597 ASN_PARSE_ERROR(NULL
);
599 #ifdef DEBUG_PDU_DECODE
600 snmplib_debug(8, "PDU Request ID: %d\n", PDU
->reqid
);
604 bufp
= asn_parse_int(bufp
, Length
,
606 &PDU
->errstat
, sizeof(PDU
->errstat
));
608 ASN_PARSE_ERROR(NULL
);
610 #ifdef DEBUG_PDU_DECODE
611 snmplib_debug(8, "PDU Error Status: %d\n", PDU
->errstat
);
615 bufp
= asn_parse_int(bufp
, Length
,
617 &PDU
->errindex
, sizeof(PDU
->errindex
));
619 ASN_PARSE_ERROR(NULL
);
621 #ifdef DEBUG_PDU_DECODE
622 snmplib_debug(8, "PDU Error Index: %d\n", PDU
->errindex
);
632 * Add a null variable with the requested name to the end of the list of
633 * variables for this pdu.
636 snmp_add_null_var(struct snmp_pdu
*pdu
, oid
* name
, int name_length
)
638 struct variable_list
*vars
;
639 struct variable_list
*ptr
;
641 vars
= snmp_var_new(name
, name_length
);
643 perror("snmp_add_null_var:xmalloc");
646 if (pdu
->variables
== NULL
) {
647 pdu
->variables
= vars
;
650 /* Insert at the end */
651 for (ptr
= pdu
->variables
;
653 ptr
= ptr
->next_variable
)
655 ptr
->next_variable
= vars
;