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