]> git.ipfire.org Git - thirdparty/squid.git/blame - snmplib/snmp_pdu.c
SourceFormat Enforcement
[thirdparty/squid.git] / snmplib / snmp_pdu.c
CommitLineData
85269fdf 1/*
2 * SNMP PDU Encoding
3 *
4 * Complies with:
5 *
6 * RFC 1902: Structure of Management Information for SNMPv2
7 *
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
A
86#include "snmp.h"
87#include "snmp_api_error.h"
85269fdf 88#include "snmp_error.h"
85269fdf 89#include "snmp_msg.h"
602d9612
A
90#include "snmp_pdu.h"
91#include "snmp_vars.h"
85269fdf 92
93#include "util.h"
94
95/* #define DEBUG_PDU 1 */
96/* #define DEBUG_PDU_DECODE 1 */
97/* #define DEBUG_PDU_ENCODE 1 */
98
43d4303e 99#define ASN_PARSE_ERROR(x) { return(x); }
85269fdf 100
101/**********************************************************************/
102
103/* Create a PDU.
104 */
105
43d4303e 106struct snmp_pdu *
e1381638 107snmp_pdu_create(int command) {
43d4303e 108 struct snmp_pdu *pdu;
85269fdf 109
32d002cb 110#if DEBUG_PDU
43d4303e 111 snmplib_debug(8, "PDU: Creating\n");
85269fdf 112#endif
113
43d4303e 114 pdu = (struct snmp_pdu *) xmalloc(sizeof(struct snmp_pdu));
115 if (pdu == NULL) {
26ac0430
AJ
116 snmp_set_api_error(SNMPERR_OS_ERR);
117 return (NULL);
43d4303e 118 }
119 memset((char *) pdu, '\0', sizeof(struct snmp_pdu));
85269fdf 120
43d4303e 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;
85269fdf 128
32d002cb 129#if DEBUG_PDU
43d4303e 130 snmplib_debug(8, "PDU: Created %x\n", (unsigned int) pdu);
85269fdf 131#endif
132
43d4303e 133 return (pdu);
85269fdf 134}
135
136/**********************************************************************/
137
138/* Clone an existing PDU.
139 */
43d4303e 140struct snmp_pdu *
e1381638 141snmp_pdu_clone(struct snmp_pdu *Src) {
43d4303e 142 struct snmp_pdu *Dest;
85269fdf 143
32d002cb 144#if DEBUG_PDU
43d4303e 145 snmplib_debug(8, "PDU %x: Cloning\n", (unsigned int) Src);
85269fdf 146#endif
147
43d4303e 148 Dest = (struct snmp_pdu *) xmalloc(sizeof(struct snmp_pdu));
149 if (Dest == NULL) {
26ac0430
AJ
150 snmp_set_api_error(SNMPERR_OS_ERR);
151 return (NULL);
43d4303e 152 }
41d00cd3 153 memcpy((char *) Dest, (char *) Src, sizeof(struct snmp_pdu));
85269fdf 154
32d002cb 155#if DEBUG_PDU
43d4303e 156 snmplib_debug(8, "PDU %x: Created %x\n", (unsigned int) Src, (unsigned int) Dest);
85269fdf 157#endif
43d4303e 158 return (Dest);
85269fdf 159}
160
161/**********************************************************************/
162
163/*
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
172 * be returned.
173 */
43d4303e 174struct snmp_pdu *
e1381638 175snmp_pdu_fix(struct snmp_pdu *pdu, int command) {
43d4303e 176 return (snmp_fix_pdu(pdu, command));
85269fdf 177}
178
43d4303e 179struct snmp_pdu *
e1381638 180snmp_fix_pdu(struct snmp_pdu *pdu, int command) {
43d4303e 181 struct variable_list *var, *newvar;
182 struct snmp_pdu *newpdu;
5c52f59a 183 int i;
43d4303e 184 int copied = 0;
85269fdf 185
32d002cb 186#if DEBUG_PDU
43d4303e 187 snmplib_debug(8, "PDU %x: Fixing. Err index is %d\n",
26ac0430 188 (unsigned int) pdu, (unsigned int) pdu->errindex);
85269fdf 189#endif
190
43d4303e 191 if (pdu->command != SNMP_PDU_RESPONSE ||
26ac0430
AJ
192 pdu->errstat == SNMP_ERR_NOERROR ||
193 pdu->errindex <= 0) {
194 snmp_set_api_error(SNMPERR_UNABLE_TO_FIX);
195 return (NULL);
85269fdf 196 }
43d4303e 197 /* clone the pdu */
198 newpdu = snmp_pdu_clone(pdu);
199 if (newpdu == NULL)
26ac0430 200 return (NULL);
43d4303e 201
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;
85269fdf 207
43d4303e 208 /* Loop through the variables, removing whatever isn't necessary */
85269fdf 209
43d4303e 210 var = pdu->variables;
5c52f59a 211 i = 1;
85269fdf 212
43d4303e 213 /* skip first variable if necessary */
5c52f59a 214 if (pdu->errindex == i) {
26ac0430
AJ
215 var = var->next_variable;
216 i++;
43d4303e 217 }
218 if (var != NULL) {
219
26ac0430
AJ
220 /* VAR is the first uncopied variable */
221
222 /* Clone this variable */
223 newpdu->variables = snmp_var_clone(var);
224 if (newpdu->variables == NULL) {
225 snmp_pdu_free(newpdu);
226 return (NULL);
227 }
228 copied++;
229
230 newvar = newpdu->variables;
231
232 /* VAR has been copied to NEWVAR. */
233 while (var->next_variable) {
234
235 /* Skip the item that was bad */
236 if (++i == pdu->errindex) {
237 var = var->next_variable;
238 continue;
239 }
240 /* Copy this var */
241 newvar->next_variable = snmp_var_clone(var->next_variable);
242 if (newvar->next_variable == NULL) {
243 snmp_pdu_free(newpdu);
244 return (NULL);
245 }
246 /* Move to the next one */
247 newvar = newvar->next_variable;
248 var = var->next_variable;
249 copied++;
250 }
251 newvar->next_variable = NULL;
43d4303e 252 }
253 /* If we didn't copy anything, free the new pdu. */
5c52f59a 254 if (i < pdu->errindex || copied == 0) {
26ac0430
AJ
255 snmp_free_pdu(newpdu);
256 snmp_set_api_error(SNMPERR_UNABLE_TO_FIX);
257 return (NULL);
85269fdf 258 }
32d002cb 259#if DEBUG_PDU
43d4303e 260 snmplib_debug(8, "PDU %x: Fixed PDU is %x\n",
26ac0430 261 (unsigned int) pdu, (unsigned int) newpdu);
85269fdf 262#endif
43d4303e 263 return (newpdu);
85269fdf 264}
265
85269fdf 266/**********************************************************************/
267
468ae12b 268void
43d4303e 269snmp_pdu_free(struct snmp_pdu *pdu)
85269fdf 270{
43d4303e 271 snmp_free_pdu(pdu);
85269fdf 272}
273
274/*
275 * Frees the pdu and any xmalloc'd data associated with it.
276 */
468ae12b 277void
43d4303e 278snmp_free_pdu(struct snmp_pdu *pdu)
85269fdf 279{
43d4303e 280 struct variable_list *vp, *ovp;
281
282 vp = pdu->variables;
283 while (vp) {
26ac0430
AJ
284 ovp = vp;
285 vp = vp->next_variable;
286 snmp_var_free(ovp);
43d4303e 287 }
288
289 if (pdu->enterprise)
26ac0430 290 xfree((char *) pdu->enterprise);
43d4303e 291 xfree((char *) pdu);
85269fdf 292}
293
294/**********************************************************************/
295
296/* Encode this PDU into DestBuf.
297 *
298 * Returns a pointer to the next byte in the buffer (where the Variable
299 * Bindings belong.)
300 */
301
302/*
303 * RFC 1902: Structure of Management Information for SNMPv2
304 *
26ac0430 305 * PDU ::=
85269fdf 306 * SEQUENCE {
307 * request-id INTEGER32
308 * error-status INTEGER
309 * error-index INTEGER
310 * Variable Bindings
311 * }
312 *
313 * BulkPDU ::=
314 * SEQUENCE {
315 * request-id INTEGER32
316 * non-repeaters INTEGER
317 * max-repetitions INTEGER
318 * Variable Bindings
319 * }
320 */
321
322/*
323 * RFC 1157: A Simple Network Management Protocol (SNMP)
324 *
26ac0430 325 * PDU ::=
85269fdf 326 * SEQUENCE {
327 * request-id INTEGER
328 * error-status INTEGER
329 * error-index INTEGER
330 * Variable Bindings
331 * }
332 *
333 * TrapPDU ::=
334 * SEQUENCE {
335 * enterprise NetworkAddress
336 * generic-trap INTEGER
337 * specific-trap INTEGER
338 * time-stamp TIMETICKS
339 * Variable Bindings
340 * }
341 */
342
43d4303e 343u_char *
344snmp_pdu_encode(u_char * DestBuf, int *DestBufLen,
26ac0430 345 struct snmp_pdu *PDU)
85269fdf 346{
43d4303e 347 u_char *bufp;
85269fdf 348
32d002cb 349#if DEBUG_PDU_ENCODE
43d4303e 350 snmplib_debug(8, "PDU: Encoding %d\n", PDU->command);
85269fdf 351#endif
352
43d4303e 353 /* ASN.1 Header */
354 switch (PDU->command) {
85269fdf 355
26ac0430 356 /**********************************************************************/
32d002cb 357#if TRP_REQ_MSG
43d4303e 358 case TRP_REQ_MSG:
359
26ac0430
AJ
360 /* SNMPv1 Trap */
361
362 /* enterprise */
363 bufp = asn_build_objid(DestBuf, DestBufLen,
364 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
365 (oid *) PDU->enterprise, PDU->enterprise_length);
366 if (bufp == NULL)
367 return (NULL);
368
369 /* agent-addr */
370 bufp = asn_build_string(bufp, DestBufLen,
371 (u_char) (SMI_IPADDRESS | ASN_PRIMITIVE),
372 (u_char *) & PDU->agent_addr.sin_addr.s_addr,
373 sizeof(PDU->agent_addr.sin_addr.s_addr));
374 if (bufp == NULL)
375 return (NULL);
376
377 /* generic trap */
378 bufp = asn_build_int(bufp, DestBufLen,
379 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
380 (int *) &PDU->trap_type, sizeof(PDU->trap_type));
381 if (bufp == NULL)
382 return (NULL);
383
384 /* specific trap */
385 bufp = asn_build_int(bufp, DestBufLen,
386 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
387 (int *) &PDU->specific_type,
388 sizeof(PDU->specific_type));
389 if (bufp == NULL)
390 return (NULL);
391
392 /* timestamp */
393 bufp = asn_build_unsigned_int(bufp, DestBufLen,
394 (u_char) (SMI_TIMETICKS | ASN_PRIMITIVE),
395 &PDU->time, sizeof(PDU->time));
396 if (bufp == NULL)
397 return (NULL);
398 break;
a56db080 399#endif
85269fdf 400
26ac0430 401 /**********************************************************************/
85269fdf 402
43d4303e 403 case SNMP_PDU_GETBULK:
404
26ac0430
AJ
405 /* SNMPv2 Bulk Request */
406
407 /* request id */
408 bufp = asn_build_int(DestBuf, DestBufLen,
409 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
410 &PDU->reqid, sizeof(PDU->reqid));
411 if (bufp == NULL)
412 return (NULL);
413
414 /* non-repeaters */
415 bufp = asn_build_int(bufp, DestBufLen,
416 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
417 &PDU->non_repeaters,
418 sizeof(PDU->non_repeaters));
419 if (bufp == NULL)
420 return (NULL);
421
422 /* max-repetitions */
423 bufp = asn_build_int(bufp, DestBufLen,
424 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
425 &PDU->max_repetitions,
426 sizeof(PDU->max_repetitions));
427 if (bufp == NULL)
428 return (NULL);
429 break;
430
431 /**********************************************************************/
85269fdf 432
43d4303e 433 default:
85269fdf 434
26ac0430 435 /* Normal PDU Encoding */
85269fdf 436
26ac0430 437 /* request id */
32d002cb 438#if DEBUG_PDU_ENCODE
26ac0430 439 snmplib_debug(8, "PDU: Request ID %d (0x%x)\n", PDU->reqid, DestBuf);
85269fdf 440#endif
26ac0430
AJ
441 bufp = asn_build_int(DestBuf, DestBufLen,
442 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
443 &PDU->reqid, sizeof(PDU->reqid));
444 if (bufp == NULL)
445 return (NULL);
85269fdf 446
26ac0430 447 /* error status */
32d002cb 448#if DEBUG_PDU_ENCODE
26ac0430 449 snmplib_debug(8, "PDU: Error Status %d (0x%x)\n", PDU->errstat, bufp);
85269fdf 450#endif
26ac0430
AJ
451 bufp = asn_build_int(bufp, DestBufLen,
452 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
453 &PDU->errstat, sizeof(PDU->errstat));
454 if (bufp == NULL)
455 return (NULL);
85269fdf 456
26ac0430 457 /* error index */
32d002cb 458#if DEBUG_PDU_ENCODE
26ac0430 459 snmplib_debug(8, "PDU: Error index %d (0x%x)\n", PDU->errindex, bufp);
85269fdf 460#endif
26ac0430
AJ
461 bufp = asn_build_int(bufp, DestBufLen,
462 (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
463 &PDU->errindex, sizeof(PDU->errindex));
464 if (bufp == NULL)
465 return (NULL);
466 break;
43d4303e 467 } /* End of encoding */
468
469 return (bufp);
85269fdf 470}
471
472/**********************************************************************/
473
474/* Decodes PDU from Packet into PDU.
475 *
476 * Returns a pointer to the next byte of the packet, which is where the
477 * Variable Bindings start.
478 */
43d4303e 479u_char *
480snmp_pdu_decode(u_char * Packet, /* data */
26ac0430
AJ
481 int *Length, /* &length */
482 struct snmp_pdu * PDU)
43d4303e 483{ /* pdu */
484 u_char *bufp;
485 u_char PDUType;
43d4303e 486 u_char ASNType;
32d002cb 487#if UNUSED_CODE
a56db080 488 int four;
43d4303e 489 oid objid[MAX_NAME_LEN];
a56db080 490#endif
43d4303e 491
492 bufp = asn_parse_header(Packet, Length, &PDUType);
493 if (bufp == NULL)
26ac0430 494 ASN_PARSE_ERROR(NULL);
85269fdf 495
32d002cb 496#if DEBUG_PDU_DECODE
43d4303e 497 snmplib_debug(8, "PDU Type: %d\n", PDUType);
85269fdf 498#endif
499
43d4303e 500 PDU->command = PDUType;
501 switch (PDUType) {
502
32d002cb 503#if TRP_REQ_MSG
43d4303e 504 case TRP_REQ_MSG:
505
26ac0430
AJ
506 /* SNMPv1 Trap Message */
507
508 /* enterprise */
509 PDU->enterprise_length = MAX_NAME_LEN;
510 bufp = asn_parse_objid(bufp, Length,
511 &ASNType, objid, &PDU->enterprise_length);
512 if (bufp == NULL)
513 ASN_PARSE_ERROR(NULL);
514
515 PDU->enterprise = (oid *) xmalloc(PDU->enterprise_length * sizeof(oid));
516 if (PDU->enterprise == NULL) {
517 snmp_set_api_error(SNMPERR_OS_ERR);
518 return (NULL);
519 }
41d00cd3 520 memcpy((char *) PDU->enterprise, (char *) objid,
e34763f4 521 PDU->enterprise_length * sizeof(oid));
26ac0430
AJ
522
523 /* Agent-addr */
524 four = 4;
525 bufp = asn_parse_string(bufp, Length,
526 &ASNType,
527 (u_char *) & PDU->agent_addr.sin_addr.s_addr,
528 &four);
529 if (bufp == NULL)
530 ASN_PARSE_ERROR(NULL);
531
532 /* Generic trap */
533 bufp = asn_parse_int(bufp, Length,
534 &ASNType,
535 (int *) &PDU->trap_type,
536 sizeof(PDU->trap_type));
537 if (bufp == NULL)
538 ASN_PARSE_ERROR(NULL);
539
540 /* Specific Trap */
541 bufp = asn_parse_int(bufp, Length,
542 &ASNType,
543 (int *) &PDU->specific_type,
544 sizeof(PDU->specific_type));
545 if (bufp == NULL)
546 ASN_PARSE_ERROR(NULL);
547
548 /* Timestamp */
549 bufp = asn_parse_unsigned_int(bufp, Length,
550 &ASNType,
551 &PDU->time, sizeof(PDU->time));
552 if (bufp == NULL)
553 ASN_PARSE_ERROR(NULL);
554 break;
a56db080 555#endif
85269fdf 556
26ac0430 557 /**********************************************************************/
85269fdf 558
43d4303e 559 case SNMP_PDU_GETBULK:
85269fdf 560
26ac0430 561 /* SNMPv2 Bulk Request */
a56db080 562
26ac0430
AJ
563 /* request id */
564 bufp = asn_parse_int(bufp, Length,
565 &ASNType,
566 &PDU->reqid, sizeof(PDU->reqid));
567 if (bufp == NULL)
568 ASN_PARSE_ERROR(NULL);
569
570 /* non-repeaters */
571 bufp = asn_parse_int(bufp, Length,
572 &ASNType,
573 &PDU->non_repeaters, sizeof(PDU->non_repeaters));
574 if (bufp == NULL)
575 ASN_PARSE_ERROR(NULL);
576
577 /* max-repetitions */
578 bufp = asn_parse_int(bufp, Length,
579 &ASNType,
580 &PDU->max_repetitions, sizeof(PDU->max_repetitions));
581 if (bufp == NULL)
582 ASN_PARSE_ERROR(NULL);
583 break;
584
585 /**********************************************************************/
85269fdf 586
43d4303e 587 default:
85269fdf 588
26ac0430 589 /* Normal PDU Encoding */
85269fdf 590
26ac0430
AJ
591 /* request id */
592 bufp = asn_parse_int(bufp, Length,
593 &ASNType,
594 &PDU->reqid, sizeof(PDU->reqid));
595 if (bufp == NULL)
596 ASN_PARSE_ERROR(NULL);
85269fdf 597
32d002cb 598#if DEBUG_PDU_DECODE
26ac0430 599 snmplib_debug(8, "PDU Request ID: %d\n", PDU->reqid);
85269fdf 600#endif
601
26ac0430
AJ
602 /* error status */
603 bufp = asn_parse_int(bufp, Length,
604 &ASNType,
605 &PDU->errstat, sizeof(PDU->errstat));
606 if (bufp == NULL)
607 ASN_PARSE_ERROR(NULL);
85269fdf 608
32d002cb 609#if DEBUG_PDU_DECODE
26ac0430 610 snmplib_debug(8, "PDU Error Status: %d\n", PDU->errstat);
85269fdf 611#endif
612
26ac0430
AJ
613 /* error index */
614 bufp = asn_parse_int(bufp, Length,
615 &ASNType,
616 &PDU->errindex, sizeof(PDU->errindex));
617 if (bufp == NULL)
618 ASN_PARSE_ERROR(NULL);
85269fdf 619
32d002cb 620#if DEBUG_PDU_DECODE
26ac0430 621 snmplib_debug(8, "PDU Error Index: %d\n", PDU->errindex);
85269fdf 622#endif
623
26ac0430 624 break;
43d4303e 625 }
85269fdf 626
43d4303e 627 return (bufp);
85269fdf 628}
629
85269fdf 630/*
631 * Add a null variable with the requested name to the end of the list of
632 * variables for this pdu.
633 */
468ae12b 634void
43d4303e 635snmp_add_null_var(struct snmp_pdu *pdu, oid * name, int name_length)
85269fdf 636{
43d4303e 637 struct variable_list *vars;
638 struct variable_list *ptr;
85269fdf 639
43d4303e 640 vars = snmp_var_new(name, name_length);
641 if (vars == NULL) {
26ac0430
AJ
642 perror("snmp_add_null_var:xmalloc");
643 return;
43d4303e 644 }
645 if (pdu->variables == NULL) {
26ac0430 646 pdu->variables = vars;
43d4303e 647 } else {
648
26ac0430
AJ
649 /* Insert at the end */
650 for (ptr = pdu->variables;
651 ptr->next_variable;
652 ptr = ptr->next_variable)
653 /*EXIT */ ;
654 ptr->next_variable = vars;
43d4303e 655 }
85269fdf 656
43d4303e 657 return;
85269fdf 658}