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