xref: /onnv-gate/usr/src/cmd/agents/snmp/snmplib/pdu.c (revision 0:68f95e015346)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <stdio.h>
33 #include <sys/socket.h>
34 #include <errno.h>
35 #include <syslog.h>
36 #include <string.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39 #include <nlist.h>
40 #include <sys/uio.h>
41 #include "snmp_msg.h"
42 #include "impl.h"
43 #include "trace.h"
44 #include "asn1.h"
45 #include "snmp.h"
46 #include "pdu.h"
47 #include "error.h"
48 
49 /***** LOCAL CONSTANTS *****/
50 
51 /*It is practically feasible to have a packet up to around 9k bytes (less than 9.5k).*/
52 #define PACKET_LENGTH		9500             /* The SNMP recommendation is 1500! */
53 #define COMMUNITY_LENGTH	128
54 
55 
56 /***** LOCAL VARIABLES *****/
57 
58 static char static_error_label[500] = "";
59 
60 
61 /***** LOCAL FUNCTIONS *****/
62 
63 static void trace_packet(u_char *packet, int length);
64 static void trace_snmp_variable(SNMP_variable *variable);
65 
66 static SNMP_pdu *snmp_pdu_decode(u_char *packet, int length, char *error_label);
67 static SNMP_variable *snmp_pdu_decode_variable(u_char **data, int *length, char *error_label);
68 static int snmp_pdu_encode(SNMP_pdu *pdu, u_char *packet, int *length, char *error_label);
69 static u_char *snmp_pdu_encode_variable(SNMP_variable *variable, u_char *data, int *length, char *error_label);
70 
71 static void shift_array(u_char *begin, int length, int shift_amount);
72 
73 
74 /********************************************************************/
75 
snmp_variable_new(char * error_label)76 SNMP_variable *snmp_variable_new(char *error_label)
77 {
78 	SNMP_variable *new;
79 
80 
81 	error_label[0] = '\0';
82 
83 	new = (SNMP_variable *) malloc(sizeof(SNMP_variable));
84 	if(new == NULL)
85 	{
86 		sprintf(error_label, ERR_MSG_ALLOC);
87 		return NULL;
88 	}
89 	memset(new, 0, sizeof(SNMP_variable));
90 
91 	return new;
92 }
93 
94 
95 /********************************************************************/
96 
snmp_typed_variable_new(Oid * name,u_char type,SNMP_value * value,char * error_label)97 SNMP_variable *snmp_typed_variable_new(Oid *name, u_char type, SNMP_value *value, char *error_label)
98 {
99 	SNMP_variable *new;
100 
101 
102 	error_label[0] = '\0';
103 
104 	if(name == NULL)
105 	{
106 		sprintf(error_label, "BUG: snmp_typed_variable_new(): name is NULL");
107 		return NULL;
108 	}
109 
110 	if(value == NULL)
111 	{
112 		sprintf(error_label, "BUG: snmp_typed_variable_new(): value is NULL");
113 		return NULL;
114 	}
115 
116 	new = snmp_variable_new(error_label);
117 	if(new == NULL)
118 	{
119 		return NULL;
120 	}
121 
122 	/* name */
123 	if(SSAOidCpy(&(new->name), name, error_label))
124 	{
125 		snmp_variable_free(new);
126 		return NULL;
127 	}
128 
129 	/* type */
130 	new->type = type;
131 
132 	/* val, val_len */
133 	switch(type)
134 	{
135 		case INTEGER:
136 		case COUNTER:
137 		case GAUGE:
138 		case TIMETICKS:
139 			new->val.integer = (int *) malloc(sizeof(int));
140 			if(new->val.integer == NULL)
141 			{
142 				sprintf(error_label, ERR_MSG_ALLOC);
143 				snmp_variable_free(new);
144 				return NULL;
145 			}
146 
147 			*(new->val.integer) = value->v_integer;
148 
149 			new->val_len = sizeof(int32_t);
150 
151 			break;
152 
153 		case IPADDRESS:
154 		case OPAQUE:
155 		case STRING:
156 			new->val.string = (u_char *) malloc(value->v_string.len);
157 			if(new->val.string == NULL)
158 			{
159 				sprintf(error_label, ERR_MSG_ALLOC);
160 				snmp_variable_free(new);
161 				return NULL;
162 			}
163 
164 			memcpy(new->val.string,
165 				value->v_string.chars,
166 				value->v_string.len);
167 
168 			new->val_len = value->v_string.len;
169 
170 			break;
171 
172 		case OBJID:
173 			new->val.objid = (Subid *) malloc(value->v_oid.len * sizeof(Subid));
174 			if(new->val.objid == NULL)
175 			{
176 				sprintf(error_label, ERR_MSG_ALLOC);
177 				snmp_variable_free(new);
178 				return NULL;
179 			}
180 
181 /* Should * sizeof(Subid), yiru's fix*/
182 			memcpy(new->val.objid,
183 				value->v_oid.subids,
184 				value->v_oid.len*sizeof(Subid));
185 
186 			new->val_len = value->v_oid.len * (int32_t)sizeof(Subid);
187 
188 			break;
189 
190 		default:
191 			sprintf(error_label, "BUG: snmp_typed_variable_new(): unsupported type (0x%x)", type);
192 			snmp_variable_free(new);
193 			return NULL;
194 	}
195 
196 
197 	return new;
198 }
199 
200 
201 /********************************************************************/
202 
snmp_typed_variable_append(SNMP_variable * list,Oid * name,u_char type,SNMP_value * value,char * error_label)203 SNMP_variable *snmp_typed_variable_append(SNMP_variable *list, Oid *name, u_char type, SNMP_value *value, char *error_label)
204 {
205 	SNMP_variable *new;
206 
207 
208 	error_label[0] = '\0';
209 
210 	new = snmp_typed_variable_new(name, type, value, error_label);
211 	if(new == NULL)
212 	{
213 		snmp_variable_list_free(list);
214 		return NULL;
215 	}
216 
217 	if(list == NULL)
218 	{
219 		list = new;
220 	}
221 	else
222 	{
223 		SNMP_variable *last = NULL;
224 		SNMP_variable *v;
225 
226 
227 		for(v = list; v; v = v->next_variable)
228 		{
229 			last = v;
230 		}
231 
232 		last->next_variable = new;
233 	}
234 
235 
236 	return list;
237 }
238 
239 
240 /********************************************************************/
241 
snmp_pdu_new(char * error_label)242 SNMP_pdu *snmp_pdu_new(char *error_label)
243 {
244 	SNMP_pdu *new;
245 
246 
247 	error_label[0] = '\0';
248 
249 	new = (SNMP_pdu *) malloc(sizeof(SNMP_pdu));
250 	if(new == NULL)
251 	{
252 		sprintf(error_label, ERR_MSG_ALLOC);
253 		return NULL;
254 	}
255 	new->community = NULL;
256 	new->enterprise.subids = NULL;
257 	new->enterprise.len = 0;
258 	new->first_variable = NULL;
259 
260 
261 	new->version = 0;
262 	new->type = 0;
263 
264 	new->request_id = 0;
265 	new->error_status = 0;
266 	new->error_index = 0;
267 
268 	new->ip_agent_addr.s_addr = 0;
269 	new->generic = 0;
270 	new->specific = 0;
271 	new->time_stamp = 0;
272 
273 
274 	return new;
275 }
276 
277 
278 /********************************************************************/
279 
snmp_pdu_receive(int sd,Address * address,char * error_label)280 SNMP_pdu *snmp_pdu_receive(int sd, Address *address, char *error_label)
281 {
282 	SNMP_pdu *pdu;
283 	u_char * packet;
284 	int length;
285 	socklen_t address_length;
286 	Address network_address;
287 
288 
289 	error_label[0] = '\0';
290 
291 	packet = (u_char *) malloc (PACKET_LENGTH * sizeof (u_char));
292 	if (packet == NULL) {
293 		sprintf(error_label, ERR_MSG_ALLOC);
294 		return NULL;
295 	}
296 	address_length = (socklen_t) sizeof(Address);
297 	/* LINTED */
298 	length = (int)recvfrom(sd, (char *) packet, PACKET_LENGTH, 0,
299 		(struct sockaddr *) &network_address, &address_length);
300 	if(length == -1)
301 	{
302 		sprintf(error_label, ERR_MSG_RECVFROM, errno_string());
303 		free (packet);
304 		return NULL;
305 	}
306 	address->sin_family = network_address.sin_family;
307 	address->sin_addr.s_addr = network_address.sin_addr.s_addr;
308 	address->sin_port = htons(network_address.sin_port);
309 
310 	if(trace_flags & TRACE_TRAFFIC)
311 	{
312 		trace("<< received %d bytes from %s\n\n",
313 			length, address_string(address));
314 	}
315 
316 	if(trace_flags & TRACE_PACKET)
317 	{
318 		trace_packet(packet, length);
319 	}
320 
321 	pdu = snmp_pdu_decode(packet, length, error_label);
322 	free (packet);
323 	if(pdu == NULL)
324 	{
325 		return NULL;
326 	}
327 
328 	if(trace_flags & TRACE_PDU)
329 	{
330 		trace_snmp_pdu(pdu);
331 	}
332 
333 
334 	return pdu;
335 }
336 
337 
338 /********************************************************************/
339 
340 /* this function does not close sd and does not free pdu */
341 
snmp_pdu_send(int sd,Address * address,SNMP_pdu * pdu,char * error_label)342 int snmp_pdu_send(int sd, Address *address, SNMP_pdu *pdu, char *error_label)
343 {
344 	u_char *packet;
345 	int length = PACKET_LENGTH;
346 	int bytes;
347 	Address network_address;
348 
349 
350 	packet = (u_char *) malloc (PACKET_LENGTH * sizeof (u_char));
351 	if (packet == NULL) {
352 		sprintf(error_label, ERR_MSG_ALLOC);
353 		return -1;
354 	}
355 	error_label[0] = '\0';
356 
357 	if(pdu == NULL)
358 	{
359 		sprintf(error_label, "BUG: snmp_pdu_send(): pdu is NULL");
360 		return -1;
361 	}
362 
363 	if(address == NULL)
364 	{
365 		sprintf(error_label, "BUG: snmp_pdu_send(): address is NULL");
366 		free (packet);
367 		return -1;
368 	}
369 
370 	if(trace_flags & TRACE_PDU)
371 	{
372 		trace_snmp_pdu(pdu);
373 	}
374 
375 	if(snmp_pdu_encode(pdu, packet, &length, error_label))
376 	{
377 		free (packet);
378 		return -1;
379 	}
380 
381 	if(trace_flags & TRACE_PACKET)
382 	{
383 		trace_packet(packet, length);
384 	}
385 
386 	network_address.sin_family = AF_INET;
387 	network_address.sin_addr.s_addr = address->sin_addr.s_addr;
388 	network_address.sin_port = htons(address->sin_port);
389 
390 	/* LINTED */
391 	bytes = (int)sendto(sd, (char *) packet, length, 0,
392 		(struct sockaddr *) &network_address, sizeof(Address));
393 	free (packet);
394 	if(bytes == -1)
395 	{
396 		sprintf(error_label, ERR_MSG_SENDTO);
397 		return -1;
398 	}
399 
400 	if(trace_flags & TRACE_TRAFFIC)
401 	{
402 		trace(">> sent %d bytes to %s\n\n",
403 			length, address_string(address));
404 	}
405 
406 
407 	return 0;
408 }
409 
410 
411 /********************************************************************/
412 
snmp_pdu_free(SNMP_pdu * pdu)413 void snmp_pdu_free(SNMP_pdu *pdu)
414 {
415 	if(pdu == NULL)
416 	{
417 		return;
418 	}
419 
420 	if(pdu->community)
421 	{
422 		free(pdu->community);
423 	}
424 	if(pdu->enterprise.subids)
425 	{
426 		free(pdu->enterprise.subids);
427 	}
428 
429 	snmp_variable_list_free(pdu->first_variable);
430 
431 	free(pdu);
432 }
433 
434 
435 /********************************************************************/
436 
snmp_variable_list_free(SNMP_variable * variable_list)437 void snmp_variable_list_free(SNMP_variable *variable_list)
438 {
439 	while(variable_list)
440 	{
441 		SNMP_variable *v;
442 
443 		v = variable_list->next_variable;
444 		snmp_variable_free(variable_list);
445 		variable_list = v;
446 	}
447 }
448 
449 
450 /********************************************************************/
451 
snmp_variable_free(SNMP_variable * variable)452 void snmp_variable_free(SNMP_variable *variable)
453 {
454 	if(variable == NULL)
455 	{
456 		return;
457 	}
458 
459 	if(variable->name.subids)
460 	{
461 		free(variable->name.subids);
462 	}
463 
464 	if(variable->val.string)
465 	{
466 		free(variable->val.string);
467 	}
468 
469 	free(variable);
470 }
471 
472 
473 /********************************************************************/
474 
trace_packet(u_char * packet,int length)475 static void trace_packet(u_char *packet, int length)
476 {
477 	int count;
478 
479 
480 	trace("PACKET:\n");
481 	trace("-------\n");
482 	for(count = 0; count < length; count++)
483 	{
484 		trace("%02X ", packet[count]);
485 		if((count % 16) == 15)
486 		{
487 			trace("\n");
488 		}
489 	}
490 	trace("\n\n");
491 }
492 
493 
494 /********************************************************************/
495 
trace_snmp_pdu(SNMP_pdu * pdu)496 void trace_snmp_pdu(SNMP_pdu *pdu)
497 {
498 	SNMP_variable *variable;
499 
500 
501 	trace("PDU:\n");
502 	trace("----\n");
503 	if(pdu == NULL)
504 	{
505 		trace("pdu is NULL!\n\n");
506 		return;
507 	}
508 
509 	trace("version:      %d\n", pdu->version);
510 	trace("community:    %s\n", pdu->community? pdu->community: "NULL");
511 
512 	trace("type:         %s\n", pdu_type_string(pdu->type));
513 
514 	switch(pdu->type)
515 	{
516 		case GET_REQ_MSG:
517 		case GETNEXT_REQ_MSG:
518 		case GET_RSP_MSG:
519 		case SET_REQ_MSG:
520 			trace("request id:   %d\n", pdu->request_id);
521 			trace("error status: %s\n",
522 				error_status_string(pdu->error_status));
523 			trace("error index:  %d\n", pdu->error_index);
524 			break;
525 
526 		case TRP_REQ_MSG:
527 			trace("enterprise:   %s\n",
528 				SSAOidString(&(pdu->enterprise)));
529 			trace("IP agent addr: %s\n",
530 				ip_address_string(&(pdu->ip_agent_addr)));
531 			trace("generic:      %s\n",
532 				generic_trap_string(pdu->generic));
533 			trace("specific:     %d\n", pdu->specific);
534 			trace("time stamp:   %d\n", pdu->time_stamp);
535 			break;
536 
537 		default:
538 			trace("\n");
539 			return;
540 	}
541 
542 	variable = pdu->first_variable;
543 	while(variable)
544 	{
545 		trace("--------------------------------------------------\n");
546 		trace_snmp_variable(variable);
547 		variable = variable->next_variable;
548 	}
549 	trace("--------------------------------------------------\n\n");
550 }
551 
552 
553 /********************************************************************/
554 
trace_snmp_variable(SNMP_variable * variable)555 static void trace_snmp_variable(SNMP_variable *variable)
556 {
557 	Oid oid;
558 	int i;
559 
560 
561 	if(variable == NULL)
562 	{
563 		trace("variable is NULL\n");
564 	}
565 
566 /*
567 	trace("variable 0x%x\n", variable);
568 	trace("next     0x%x\n", variable->next_variable);
569 */
570 	trace("name:    %s\n", SSAOidString(&(variable->name)));
571 	trace("type:    %s\n", asn1_type_string(variable->type));
572 	trace("length:  %d\n", variable->val_len);
573 	trace("value:   ");
574 	switch(variable->type)
575 	{
576 		case INTEGER:
577 		case COUNTER:
578 		case GAUGE:
579 		case TIMETICKS:
580 			trace("%d\n", *(variable->val.integer));
581 			break;
582 
583 
584 		case IPADDRESS:
585 			if(variable->val_len != 4)
586 			{
587 				trace("val_len should be 4! (%d)\n", variable->val_len);
588 			}
589 			else
590 			{
591 				IPAddress ip_address;
592 
593 				ip_address.s_addr = *(variable->val.integer);
594 				trace("%s\n", ip_address_string(&ip_address));
595 			}
596 			break;
597 
598 		case OBJID:
599 			oid.subids = variable->val.objid;
600 			oid.len = variable->val_len / (int32_t)sizeof(Subid);
601 			trace("%s\n", SSAOidString(&oid));
602 			break;
603 
604 		case STRING:
605 		case OPAQUE:
606 		case NULLOBJ:
607 		default:
608 			for(i = 0; i < variable->val_len; i++)
609 			{
610 				trace("%c", variable->val.string[i]);
611 			}
612 			trace(" ( ");
613 			for(i = 0; i < variable->val_len; i++)
614 			{
615 				trace("%02x ", variable->val.string[i]);
616 			}
617 			trace(")\n");
618 			break;
619 	}
620 }
621 
622 
623 /********************************************************************/
624 
625 /*
626  *	Parses the packet and places the data into the pdu.
627  *	If any errors are encountered, NULL is returned.
628  */
629 
snmp_pdu_decode(u_char * packet,int packet_length,char * error_label)630 static SNMP_pdu *snmp_pdu_decode(u_char *packet, int packet_length, char *error_label)
631 {
632 	u_char *data = packet;
633 	int length = packet_length;
634 	u_char type;
635 	int len;
636 	Subid subids[MAX_OID_LEN];
637 	SNMP_pdu *pdu;
638 	SNMP_variable *last_variable = NULL;
639 	char community[COMMUNITY_LENGTH + 1];
640 
641 
642 	error_label[0] = '\0';
643 
644 	pdu = snmp_pdu_new(error_label);
645 	if(pdu == NULL)
646 	{
647 		return NULL;
648 	}
649 
650 /* header of message */
651 	data = asn_parse_header(data, (uint32_t *)&length, &type, static_error_label);
652 	if(data == NULL)
653 	{
654 		sprintf(error_label, "Decode the header of message failed: %s",
655 			static_error_label);
656 		snmp_pdu_free(pdu);
657 		return NULL;
658 	}
659 	if(type != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
660 	{
661 		sprintf(error_label, "The message has a wrong header type (0x%x)", type);
662 		snmp_pdu_free(pdu);
663 		return NULL;
664 	}
665 
666 /* version */
667 	data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *) &pdu->version,
668 		sizeof(pdu->version), static_error_label);
669 	if(data == NULL)
670 	{
671 		sprintf(error_label, "Decode the version failed: %s",
672 			static_error_label);
673 		snmp_pdu_free(pdu);
674 		return NULL;
675 	}
676 	if(pdu->version != SNMP_VERSION_1)
677 	{
678 		sprintf(error_label, "The message has a wrong version (%d)",
679 			pdu->version);
680 		snmp_pdu_free(pdu);
681 		return NULL;
682 	}
683 
684 /* parse community */
685 	len = COMMUNITY_LENGTH;
686 	data = asn_parse_string(data, (uint32_t *)&length, &type, (u_char *) community,
687 		(uint32_t *)&len, static_error_label);
688 	if(data == NULL)
689 	{
690 		sprintf(error_label, "Decode the community failed: %s",
691 			static_error_label);
692 		snmp_pdu_free(pdu);
693 		return NULL;
694 	}
695 	community[len] = '\0';
696 	pdu->community = strdup(community);
697 	if(pdu->community == NULL)
698 	{
699 		sprintf(error_label, ERR_MSG_ALLOC);
700 		snmp_pdu_free(pdu);
701 		return NULL;
702 	}
703 
704 /* header od pdu */
705 	data = asn_parse_header(data, (uint32_t *)&length, &type, static_error_label);
706 	if(data == NULL)
707 	{
708 		sprintf(error_label, "Decode the header of pdu failed: %s",
709 			static_error_label);
710 		snmp_pdu_free(pdu);
711 		return NULL;
712 	}
713 	pdu->type = type;
714 
715 
716 	switch(pdu->type)
717 	{
718 		case GET_REQ_MSG:
719 		case GETNEXT_REQ_MSG:
720 		case GET_RSP_MSG:
721 		case SET_REQ_MSG:
722 
723 		/* request id */
724 			data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *) &pdu->request_id,
725 				sizeof(pdu->request_id), static_error_label);
726 			if(data == NULL)
727 			{
728 				sprintf(error_label, "Decode the request id failed: %s",
729 					static_error_label);
730 				snmp_pdu_free(pdu);
731 				return NULL;
732 			}
733 
734 		/* error status */
735 			data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *) &pdu->error_status,
736 				sizeof(pdu->error_status), static_error_label);
737 			if (data == NULL)
738 			{
739 				sprintf(error_label, "Decode the error status failed: %s",
740 					static_error_label);
741 				snmp_pdu_free(pdu);
742 				return NULL;
743 			}
744 
745 		/* error index */
746 			data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *)&pdu->error_index,
747 				sizeof(pdu->error_index), static_error_label);
748 			if (data == NULL)
749 			{
750 				sprintf(error_label, "Decode the error index failed: %s",
751 					static_error_label);
752 				snmp_pdu_free(pdu);
753 				return NULL;
754 			}
755 
756 			break;
757 
758 
759 		case TRP_REQ_MSG:
760 
761 		/* enterprise */
762 			pdu->enterprise.len = MAX_OID_LEN;
763 			data = asn_parse_objid(data, (uint32_t *)&length, &type, subids,
764 				&pdu->enterprise.len, static_error_label);
765 			if(data == NULL)
766 			{
767 				sprintf(error_label, "Decode the enterprise failed: %s",
768 					static_error_label);
769 				snmp_pdu_free(pdu);
770 				return NULL;
771 			}
772 			pdu->enterprise.subids = (Subid *) malloc(pdu->enterprise.len * sizeof(Subid));
773 			if(pdu->enterprise.subids == NULL)
774 			{
775 				sprintf(error_label, ERR_MSG_ALLOC);
776 				snmp_pdu_free(pdu);
777 				return NULL;
778 			}
779 			memcpy(pdu->enterprise.subids, subids, pdu->enterprise.len * sizeof(Subid));
780 
781 		/* agent address */
782 			len = 4;
783 			data = asn_parse_string(data, (uint32_t *)&length, &type,
784 				(u_char *)&pdu->ip_agent_addr.s_addr, (uint32_t *)&len, static_error_label);
785 			if(data == NULL)
786 			{
787 				sprintf(error_label, "Decode the agent address failed: %s",
788 					static_error_label);
789 				snmp_pdu_free(pdu);
790 				return NULL;
791 			}
792 
793 		/* generic trap */
794 			data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *)&pdu->generic,
795 				sizeof(pdu->generic), static_error_label);
796 			if(data == NULL)
797 			{
798 				sprintf(error_label, "Decode the generic trap failed: %s",
799 					static_error_label);
800 				snmp_pdu_free(pdu);
801 				return NULL;
802 			}
803 
804 		/* specific trap */
805 			data = asn_parse_int(data, (uint32_t *)&length, &type, (int32_t *)&pdu->specific,
806 				sizeof(pdu->specific), static_error_label);
807 			if(data == NULL)
808 			{
809 				sprintf(error_label, "Decode the specific trap failed: %s",
810 					static_error_label);
811 				snmp_pdu_free(pdu);
812 				return NULL;
813 			}
814 
815 		/* time stamp */
816 			data = asn_parse_unsigned_int(data, (uint32_t *)&length, &type, (int32_t *)&pdu->time_stamp,
817 				sizeof(pdu->time_stamp), static_error_label);
818 			if(data == NULL)
819 			{
820 				sprintf(error_label, "Decode the time stamp failed: %s",
821 					static_error_label);
822 				snmp_pdu_free(pdu);
823 				return NULL;
824 			}
825 
826 			break;
827 
828 
829 		default:
830 			sprintf(error_label, "The type of the pdu is wrong (%d)", pdu->type);
831 			snmp_pdu_free(pdu);
832 			return NULL;
833 	}
834 
835 
836 /* header of variables */
837 	data = asn_parse_header(data, (uint32_t *)&length, &type, static_error_label);
838 	if(data == NULL)
839 	{
840 		sprintf(error_label, "Decode the header of the variables failed: %s",
841 			static_error_label);
842 		snmp_pdu_free(pdu);
843 		return NULL;
844 	}
845 	if(type != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
846 	{
847 		sprintf(error_label, "The header of the variables has a wrong type (%x)", type);
848 		snmp_pdu_free(pdu);
849 		return NULL;
850 	}
851 
852 
853 
854 	while(length > 0)
855 	{
856 		SNMP_variable *variable;
857 
858 
859 		variable = snmp_pdu_decode_variable(&data , &length, error_label);
860 		if(variable == NULL)
861 		{
862 			snmp_pdu_free(pdu);
863 			return NULL;
864 		}
865 
866 		if(pdu->first_variable == NULL)
867 		{
868 			pdu->first_variable = variable;
869 		}
870 		else
871 		{
872 			last_variable->next_variable = variable;
873 		}
874 		last_variable = variable;
875 
876 	} /* while */
877 
878 
879 	return pdu;
880 }
881 
882 
883 /********************************************************************/
884 
snmp_pdu_decode_variable(u_char ** data,int * length,char * error_label)885 static SNMP_variable *snmp_pdu_decode_variable(u_char **data, int *length, char *error_label)
886 {
887 	u_char *d = *data;
888 	u_char *value_start;
889 	int len = *length;
890 	SNMP_variable *variable;
891 	u_char type;
892 	Subid subids[MAX_OID_LEN];
893 
894 
895 	error_label[0] = '\0';
896 
897 	variable = snmp_variable_new(error_label);
898 	if(variable == NULL)
899 	{
900 		return NULL;
901 	}
902 
903 
904 /* header of variable */
905 	d = asn_parse_header(d, (uint32_t *)&len, &type, static_error_label);
906 	if(d == NULL)
907 	{
908 		sprintf(error_label, "Decode the header of a variable failed: %s",
909 			static_error_label);
910 		snmp_variable_free(variable);
911 		return NULL;
912 	}
913 	if(type != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
914 	{
915 		sprintf(error_label, "The header of a variable has a wrong type (%x)", type);
916 		snmp_variable_free(variable);
917 		return NULL;
918 	}
919 
920 
921 /* name */
922 	variable->name.len = MAX_OID_LEN;
923 	d = asn_parse_objid(d, (uint32_t *)&len, &type, subids, &(variable->name.len), static_error_label);
924 	if(d == NULL)
925 	{
926 		sprintf(error_label, "Decode the name of a variable failed: %s",
927 			static_error_label);
928 		snmp_variable_free(variable);
929 		return NULL;
930 	}
931 	if(type != (u_char) OBJID)
932 	{
933 		sprintf(error_label, "The name of a variable has wrong type (%x)", type);
934 		snmp_variable_free(variable);
935 		return NULL;
936 	}
937 	variable->name.subids = (Subid *) malloc(variable->name.len * sizeof(Subid));
938 	if(variable->name.subids == NULL)
939 	{
940 		sprintf(error_label, ERR_MSG_ALLOC);
941 		snmp_variable_free(variable);
942 		return NULL;
943 	}
944 	memcpy(variable->name.subids, subids, variable->name.len * sizeof(Subid));
945 
946 
947 /* find out what type of object this is */
948 	variable->val_len = len;
949 	value_start = d;
950 	d = asn_parse_header(d, (uint32_t *)&variable->val_len, &variable->type, static_error_label);
951 	if(d == NULL)
952 	{
953 		sprintf(error_label, "Decode the type of a variable failed: %s",
954 			static_error_label);
955 		snmp_variable_free(variable);
956 		return NULL;
957 	}
958 
959 	switch(variable->type)
960 	{
961 		case INTEGER:
962 		case COUNTER:
963 		case GAUGE:
964 		case TIMETICKS:
965 			variable->val.integer = (int32_t *) malloc(sizeof(int32_t));
966 			if(variable->val.integer == NULL)
967 			{
968 				sprintf(error_label, ERR_MSG_ALLOC);
969 				snmp_variable_free(variable);
970 				return NULL;
971 			}
972 			variable->val_len = sizeof(int32_t);
973 			d = asn_parse_unsigned_int(value_start, (uint32_t *)&len, &variable->type,
974 				(int32_t *)variable->val.integer, sizeof(int32_t), static_error_label);
975 			if(d == NULL)
976 			{
977 				sprintf(error_label, "Decode a variable of type integer failed: %s",
978 					static_error_label);
979 				snmp_variable_free(variable);
980 				return NULL;
981 			}
982 			break;
983 
984 		case STRING:
985 		case IPADDRESS:
986 		case OPAQUE:
987 			variable->val.string = (u_char *) malloc(variable->val_len);
988 			if(variable->val.string == NULL)
989 			{
990 				sprintf(error_label, ERR_MSG_ALLOC);
991 				snmp_variable_free(variable);
992 				return NULL;
993 			}
994 			d = asn_parse_string(value_start, (uint32_t *)&len, &variable->type,
995 				variable->val.string, (uint32_t *)&variable->val_len, static_error_label);
996 			if(d == NULL)
997 			{
998 				sprintf(error_label, "Decode a variable of type octet string failed: %s",
999 					static_error_label);
1000 				snmp_variable_free(variable);
1001 				return NULL;
1002 			}
1003 			break;
1004 
1005 		case OBJID:
1006 			variable->val_len = MAX_OID_LEN;
1007 			d = asn_parse_objid(value_start, (uint32_t *)&len, &variable->type,
1008 				subids, &variable->val_len, static_error_label);
1009 			if(d == NULL)
1010 			{
1011 				sprintf(error_label, "Decode a variable of type object identifier failed: %s",
1012 					static_error_label);
1013 				snmp_variable_free(variable);
1014 				return NULL;
1015 			}
1016 			variable->val_len = variable->val_len * (int32_t)sizeof(Subid);
1017 			variable->val.objid = (Subid *) malloc(variable->val_len);
1018 			if(variable->val.objid == NULL)
1019 			{
1020 				sprintf(error_label, ERR_MSG_ALLOC);
1021 				snmp_variable_free(variable);
1022 				return NULL;
1023 			}
1024 			memcpy(variable->val.objid, subids, variable->val_len);
1025 			break;
1026 
1027 		case NULLOBJ:
1028 			break;
1029 
1030 		default:
1031 			sprintf(error_label, "A variable has a wrong type (%x)", variable->type);
1032 			snmp_variable_free(variable);
1033 			return NULL;
1034 	}
1035 
1036 	/* LINTED */
1037 	*length = *length - (uint32_t)(d - *data);
1038 	*data = d;
1039 
1040 
1041 	return variable;
1042 }
1043 
1044 
1045 /********************************************************************/
1046 
1047 /*
1048  *	Takes a pdu and serializes the ASN PDU into the area
1049  *	pointed to by packet.  length is the size of the data area available.
1050  *	Returns the length of the completed packet in length.  If any errors
1051  *	occur, -1 is returned.  If all goes well, 0 is returned.
1052  */
1053 
snmp_pdu_encode(SNMP_pdu * pdu,u_char * packet,int * packet_length,char * error_label)1054 static int snmp_pdu_encode(SNMP_pdu *pdu, u_char *packet, int *packet_length, char *error_label)
1055 {
1056 	u_char *buf;
1057 	int buf_len;
1058 	int len;
1059 	SNMP_variable *variable;
1060 	u_char *cp;
1061 	int32_t total_length;
1062 
1063 
1064 	buf = (u_char *) malloc (PACKET_LENGTH * sizeof (u_char));
1065 	if (buf == NULL) {
1066 		sprintf(error_label, ERR_MSG_ALLOC);
1067 		return -1;
1068 	}
1069 	error_label[0] = '\0';
1070 
1071 	cp = packet;
1072 	len = *packet_length;
1073 
1074 /* encode the variables in packet */
1075 	for(variable = pdu->first_variable; variable; variable = variable->next_variable)
1076 	{
1077 		cp = snmp_pdu_encode_variable(variable, cp, &len, error_label);
1078 		if(cp == NULL) {
1079 			free (buf);
1080 			return -1;
1081 		}
1082 	}
1083 	/* LINTED */
1084 	total_length = (int32_t)(cp - packet); /* Better fit in 32 bits */
1085 
1086 /* encode the header for the variables in buf */
1087 	buf_len = PACKET_LENGTH;
1088 	cp = asn_build_header(buf, (uint32_t *)&buf_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1089 		total_length, static_error_label);
1090 	if(cp == NULL)
1091 	{
1092 		sprintf(error_label, "Encode the header of the variables failed: %s",
1093 			static_error_label);
1094 		free (buf);
1095 		return -1;
1096 	}
1097 
1098 /* copy the encoded variables from packet to buf */
1099 	memcpy(cp, packet, total_length);
1100 	/* LINTED */
1101 	total_length += (int32_t)(cp - buf);
1102 
1103 
1104 /* encode the pdu in packet */
1105 	len = *packet_length;
1106 	switch(pdu->type)
1107 	{
1108 		case GET_REQ_MSG:
1109 		case GETNEXT_REQ_MSG:
1110 		case GET_RSP_MSG:
1111 		case SET_REQ_MSG:
1112 
1113 		/* request id */
1114 			cp = asn_build_int(packet, (uint32_t *)&len, (u_char) INTEGER,
1115 				(int32_t *) &pdu->request_id, sizeof(pdu->request_id),
1116 				static_error_label);
1117 			if(cp == NULL)
1118 			{
1119 				sprintf(error_label, "Encode the request id failed: %s",
1120 					static_error_label);
1121 				free (buf);
1122 				return -1;
1123 			}
1124 
1125 		/* error status */
1126 			cp = asn_build_int(cp, (uint32_t *)&len, (u_char) INTEGER,
1127 				(int32_t *) &pdu->error_status, sizeof(pdu->error_status),
1128 				static_error_label);
1129 			if(cp == NULL)
1130 			{
1131 				sprintf(error_label, "Encode the error status failed: %s",
1132 					static_error_label);
1133 				free (buf);
1134 				return -1;
1135 			}
1136 
1137 		/* error index */
1138 			cp = asn_build_int(cp, (uint32_t *)&len, (u_char) INTEGER,
1139 				(int32_t *) &pdu->error_index, sizeof(pdu->error_index),
1140 				static_error_label);
1141 			if(cp == NULL)
1142 			{
1143 				sprintf(error_label, "Encode the error index failed: %s",
1144 					static_error_label);
1145 				free (buf);
1146 				return -1;
1147 			}
1148 
1149 			break;
1150 
1151 
1152 		case TRP_REQ_MSG:
1153 
1154 		/* enterprise */
1155 			cp = asn_build_objid(packet, (uint32_t *)&len, (u_char) OBJID,
1156 				(Subid *) pdu->enterprise.subids, pdu->enterprise.len,
1157 				static_error_label);
1158 			if(cp == NULL)
1159 			{
1160 				sprintf(error_label, "Encode the enterprise failed: %s",
1161 					static_error_label);
1162 				free (buf);
1163 				return -1;
1164 			}
1165 
1166 		/* agent-addr */
1167 			cp = asn_build_string(cp, (uint32_t *)&len, (u_char) IPADDRESS,
1168 				(u_char *) &pdu->ip_agent_addr.s_addr,
1169 				sizeof(pdu->ip_agent_addr.s_addr),
1170 				static_error_label);
1171 			if(cp == NULL)
1172 			{
1173 				sprintf(error_label, "Encode the agent address failed: %s",
1174 					static_error_label);
1175 				free (buf);
1176 				return -1;
1177 			}
1178 
1179 		/* generic trap */
1180 			cp = asn_build_int(cp, (uint32_t *)&len, (u_char) INTEGER,
1181 				(int32_t *) &pdu->generic, sizeof(pdu->generic),
1182 				static_error_label);
1183 			if(cp == NULL)
1184 			{
1185 				sprintf(error_label, "Encode the generic trap failed: %s",
1186 					static_error_label);
1187 				free (buf);
1188 				return -1;
1189 			}
1190 
1191 		/* specific trap */
1192 			cp = asn_build_int(cp, (uint32_t *)&len, (u_char) INTEGER,
1193 				(int32_t *) &pdu->specific, sizeof(pdu->specific),
1194 				static_error_label);
1195 			if(cp == NULL)
1196 			{
1197 				sprintf(error_label, "Encode the specific trap failed: %s",
1198 					static_error_label);
1199 				free (buf);
1200 				return -1;
1201 			}
1202 
1203 		/* time stamp  */
1204 			cp = asn_build_unsigned_int(cp, (uint32_t *)&len, (u_char) TIMETICKS,
1205 				(int32_t *) &pdu->time_stamp, sizeof(pdu->time_stamp),
1206 				static_error_label);
1207 			if(cp == NULL)
1208 			{
1209 				sprintf(error_label, "Encode the time stamp failed: %s",
1210 					static_error_label);
1211 				free (buf);
1212 				return -1;
1213 			}
1214 
1215 			break;
1216 
1217 
1218 		default:
1219 			sprintf(error_label, "The pdu has a wrong type (%x)", pdu->type);
1220 			free (buf);
1221 			return -1;
1222 
1223 	} /* switch */
1224 
1225 
1226 /* copy the encoded variables and their header from buf to packet */
1227 	if(len < total_length)
1228 	{
1229 		sprintf(error_label, "The buffer is too small");
1230 		free (buf);
1231 		return -1;
1232 	}
1233 	memcpy(cp, buf, total_length);
1234 	/* LINTED */
1235 	total_length += (int32_t)(cp - packet);
1236 
1237 
1238 /* encode the header of the pdu in buf */
1239 	len = PACKET_LENGTH;
1240 	/* LINTED */
1241 	cp = asn_build_header(buf, (uint32_t *)&len, (u_char)pdu->type,
1242 		total_length, static_error_label);
1243 	if(cp == NULL)
1244 	{
1245 		sprintf(error_label, "Encode the header of the pdu failed: %s",
1246 			static_error_label);
1247 		free (buf);
1248 		return -1;
1249 	}
1250 
1251 
1252 /* copy the pdu from packet to buf */
1253 	if(len < total_length)
1254 	{
1255 		sprintf(error_label, "The buffer is too small");
1256 		free (buf);
1257 		return -1;
1258 	}
1259 	memcpy(cp, packet, total_length);
1260 	/* LINTED */
1261 	total_length += (int32_t)(cp - buf);
1262 
1263 /* encode the message in packet */
1264 	len = *packet_length;
1265 
1266 	if(pdu->community == NULL)
1267 	{
1268 		sprintf(error_label, "BUG: snmp_pdu_encode(): community is NULL");
1269 		free (buf);
1270 		return -1;
1271 	}
1272 
1273 	cp = asn_build_header(packet, (uint32_t *)&len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1274 		/* LINTED */
1275 		total_length + (int32_t)strlen(pdu->community) + 5,
1276 		static_error_label);
1277 	if(cp == NULL)
1278 	{
1279 		sprintf(error_label, "Encode the header of the message failed: %s",
1280 			static_error_label);
1281 		free (buf);
1282 		return -1;
1283 	}
1284 
1285 /* version */
1286 	cp = asn_build_int(cp, (uint32_t *)&len, (u_char) INTEGER,
1287 		(int32_t *) &pdu->version, sizeof(pdu->version),
1288 		static_error_label);
1289 	if(cp == NULL)
1290 	{
1291 		sprintf(error_label, "Encode the version failed: %s",
1292 			static_error_label);
1293 		free (buf);
1294 		return -1;
1295 	}
1296 
1297 /* community */
1298 	cp = asn_build_string(cp, (uint32_t *)&len, (u_char) STRING,
1299 		/* LINTED */
1300 		(u_char *) pdu->community, (int32_t)strlen(pdu->community),
1301 		static_error_label);
1302 	if(cp == NULL)
1303 	{
1304 		sprintf(error_label, "Encode the community failed: %s",
1305 			static_error_label);
1306 		free (buf);
1307 		return -1;
1308 	}
1309 
1310 
1311 /* copy the pdu and its header from buf to packet */
1312 	if(len < total_length)
1313 	{
1314 		sprintf(error_label, "The buffer is too small");
1315 		free (buf);
1316 		return -1;
1317 	}
1318 
1319 	memcpy(cp, buf, total_length);
1320 	/* LINTED */
1321 	total_length += (int32_t)(cp - packet);
1322 	*packet_length = total_length;
1323 
1324 	free (buf);
1325 	return 0;
1326 }
1327 
1328 
1329 /********************************************************************/
1330 
snmp_pdu_encode_variable(SNMP_variable * variable,u_char * data,int * length,char * error_label)1331 static u_char *snmp_pdu_encode_variable(SNMP_variable *variable, u_char *data, int *length, char *error_label)
1332 {
1333 	int dummy_len, header_len, header_shift;
1334 	u_char *data_ptr;
1335 
1336 
1337 	error_label[0] = '\0';
1338 
1339 	dummy_len = *length;
1340 	data_ptr = data;
1341 	data = asn_build_header(data, (uint32_t *)&dummy_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0,
1342 		static_error_label);
1343 	if(data == NULL) {
1344 		sprintf(error_label, "Encode the header of a variable failed: %s",
1345 			static_error_label);
1346 		return NULL;
1347 	}
1348 
1349 	/* LINTED */
1350 	header_len = (int32_t)(data - data_ptr);
1351 	*length = *length - header_len;
1352 	data = asn_build_objid(data, (uint32_t *)length, (u_char) OBJID,
1353 	    variable->name.subids, variable->name.len, static_error_label);
1354 	if(data == NULL)
1355 	{
1356 		sprintf(error_label, "Encode the name of a variable failed: %s",
1357 			static_error_label);
1358 		return NULL;
1359 	}
1360 
1361 
1362 	switch(variable->type)
1363 	{
1364 		case INTEGER:
1365 		case GAUGE:
1366 		case COUNTER:
1367 		case TIMETICKS:
1368 			if (variable->type == TIMETICKS)
1369 	    			data = asn_build_unsigned_int(data, (uint32_t *)length, variable->type,
1370 					(int32_t *) variable->val.integer, variable->val_len, static_error_label);
1371 			else
1372 	    			data = asn_build_int(data, (uint32_t *)length, variable->type,
1373 					(int32_t *) variable->val.integer, variable->val_len, static_error_label);
1374 			if(data == NULL)
1375 			{
1376 				sprintf(error_label, "Encode a variable of type integer failed: %s",
1377 					static_error_label);
1378 				return NULL;
1379 			}
1380 			break;
1381 
1382 		case STRING:
1383 		case IPADDRESS:
1384 		case OPAQUE:
1385 			data = asn_build_string(data, (uint32_t *)length, variable->type,
1386 				variable->val.string, variable->val_len, static_error_label);
1387 			if(data == NULL)
1388 			{
1389 				sprintf(error_label, "Encode a variable of type octet string failed: %s",
1390 					static_error_label);
1391 				return NULL;
1392 			}
1393 			break;
1394 
1395 		case OBJID:
1396 			data = asn_build_objid(data, (uint32_t *)length, variable->type, variable->val.objid,
1397 				variable->val_len / (int32_t)sizeof(Subid), static_error_label);
1398 			if(data == NULL)
1399 			{
1400 				sprintf(error_label, "Encode a variable of type object identifier failed: %s",
1401 					static_error_label);
1402 				return NULL;
1403 			}
1404 			break;
1405 
1406 		case NULLOBJ:
1407 			data = asn_build_null(data, (uint32_t *)length, variable->type, static_error_label);
1408 			if(data == NULL)
1409 			{
1410 				sprintf(error_label, "Encode a variable of type null failed: %s",
1411 					static_error_label);
1412 				return NULL;
1413 			}
1414 			break;
1415 
1416 		default:
1417 			sprintf(error_label, "A variable has a wrong type (%x)", variable->type);
1418 			return NULL;
1419 	} /* switch */
1420 
1421 
1422 	/* LINTED */
1423 	dummy_len = (uint32_t)(data - data_ptr) - header_len;
1424 	header_shift = 0;
1425 	if(dummy_len >= 0x80)
1426 	{
1427 		header_shift++;
1428 		if(dummy_len > 0xFF)
1429 		{
1430 			header_shift++;
1431 		}
1432 	}
1433 
1434 
1435 	if(header_shift)
1436 	{
1437 		*length = *length - header_shift;
1438 		if(*length < 0)
1439 		{
1440 			sprintf(error_label, "The buffer is too small");
1441 			return NULL;
1442 		}
1443 
1444 		shift_array(data_ptr + header_len, dummy_len, header_shift);
1445 		data = data + header_shift;
1446 		header_len = header_len + header_shift;
1447 	}
1448 
1449 
1450 	if(asn_build_header(data_ptr, (uint32_t *)&dummy_len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
1451 		dummy_len, static_error_label) == NULL)
1452 	{
1453 		sprintf(error_label, "Encode the header of a variable failed: %s",
1454 			static_error_label);
1455 		return NULL;
1456 	}
1457 
1458 
1459 	return data;
1460 }
1461 
1462 
1463 /********************************************************************/
1464 
shift_array(u_char * begin,int length,int shift_amount)1465 static void shift_array(u_char *begin, int length, int shift_amount)
1466 {
1467 	register u_char	*old, *new;
1468 
1469 	if(shift_amount >= 0)
1470 	{
1471 		old = begin + length - 1;
1472 		new = old + shift_amount;
1473 
1474 		while(length--)
1475 		{
1476 			*new-- = *old--;
1477 		}
1478 	}
1479 	else
1480 	{
1481 		old = begin;
1482 		new = begin + shift_amount;
1483 
1484 		while(length--)
1485 		{
1486 			*new++ = *old++;
1487 		}
1488 	}
1489 }
1490 
1491 
1492 /********************************************************************/
1493 
snmp_pdu_dup(SNMP_pdu * pdu,char * error_label)1494 SNMP_pdu *snmp_pdu_dup(SNMP_pdu *pdu, char *error_label)
1495 {
1496 	SNMP_pdu *new;
1497 
1498 
1499 	error_label[0] = '\0';
1500 
1501 	new = snmp_pdu_new(error_label);
1502 	if(new == NULL)
1503 	{
1504 		return NULL;
1505 	}
1506 
1507 	new->version = pdu->version;
1508 	new->community = strdup(pdu->community);
1509 	if(new->community == NULL)
1510 	{
1511 		sprintf(error_label, ERR_MSG_ALLOC);
1512 		snmp_pdu_free(new);
1513 		return NULL;
1514 	}
1515 
1516 	new->type = pdu->type;
1517 
1518 	new->request_id = pdu->request_id;
1519 	new->error_status = pdu->error_status;
1520 	new->error_index = pdu->error_index;
1521 
1522 	if(SSAOidCpy(&(new->enterprise), &(pdu->enterprise), error_label))
1523 	{
1524 		snmp_pdu_free(new);
1525 		return NULL;
1526 	}
1527 
1528 	memcpy(&(new->ip_agent_addr), &(pdu->ip_agent_addr), sizeof(IPAddress));
1529 	new->generic = pdu->generic;
1530 	new->specific = pdu->specific;
1531 	new->time_stamp = pdu->time_stamp;
1532 
1533 
1534 	return new;
1535 }
1536 
1537 
1538 /********************************************************************/
1539 
1540 SNMP_variable *
snmp_variable_dup(SNMP_variable * variable,char * error_label)1541 snmp_variable_dup(SNMP_variable *variable, char *error_label)
1542 {
1543 	SNMP_variable *new;
1544 
1545 
1546 	error_label[0] = '\0';
1547 
1548 	new = snmp_variable_new(error_label);
1549 	if (new == NULL) {
1550 		return (NULL);
1551 	}
1552 
1553 	if (SSAOidCpy(&(new->name), &(variable->name), error_label)) {
1554 		snmp_variable_free(new);
1555 		return (NULL);
1556 	}
1557 
1558 	new->type = variable->type;
1559 	if (variable->val_len > 0) {
1560 		new->val.string = (uchar_t *)malloc(variable->val_len);
1561 		if (new->val.string == NULL) {
1562 			sprintf(error_label, ERR_MSG_ALLOC);
1563 			snmp_variable_free(new);
1564 			return (NULL);
1565 		}
1566 		memcpy(new->val.string, variable->val.string,
1567 			variable->val_len);
1568 	} else {
1569 		new->val.string = NULL;
1570 	}
1571 
1572 	new->val_len = variable->val_len;
1573 
1574 
1575 	return (new);
1576 }
1577 
1578 
1579 /********************************************************************/
1580 
snmp_pdu_append_null_variable(SNMP_pdu * pdu,Oid * name,char * error_label)1581 SNMP_variable *snmp_pdu_append_null_variable(SNMP_pdu *pdu, Oid *name, char *error_label)
1582 {
1583 	SNMP_variable *new;
1584 	SNMP_variable *current, *last;
1585 
1586 
1587 	error_label[0] = '\0';
1588 
1589 	if(pdu == NULL)
1590 	{
1591 		sprintf(error_label, "BUG: snmp_pdu_append_null_variable(): pdu is NULL");
1592 		return NULL;
1593 	}
1594 
1595 	if(name == NULL)
1596 	{
1597 		sprintf(error_label, "BUG: snmp_pdu_append_null_variable(): pdu is NULL");
1598 		return NULL;
1599 	}
1600 
1601 	new = snmp_variable_new(error_label);
1602 	if(new == NULL)
1603 	{
1604 		return NULL;
1605 	}
1606 
1607 	if(SSAOidCpy(&(new->name), name, error_label))
1608 	{
1609 		snmp_variable_free(new);
1610 		return NULL;
1611 	}
1612 
1613 	new->type = NULLOBJ;
1614 
1615 	last = NULL;
1616 	for(current = pdu->first_variable; current; current = current->next_variable)
1617 	{
1618 		last = current;
1619 	}
1620 
1621 	if(last)
1622 	{
1623 		last->next_variable = new;
1624 	}
1625 	else
1626 	{
1627 		pdu->first_variable = new;
1628 	}
1629 
1630 
1631 	return new;
1632 }
1633 
ssa_append_integer_variable(SNMP_variable * list,Oid * oid,int num,char * error_label,u_char asn1_type)1634 SNMP_variable *ssa_append_integer_variable(SNMP_variable *list, Oid *oid, int num,char *error_label,u_char asn1_type)
1635 {
1636   SNMP_value value;
1637 
1638   value.v_integer = num;
1639   list = snmp_typed_variable_append(list,oid,asn1_type,&value,error_label);
1640   if(list == NULL){
1641         error("ssa_append_integer_variable failed: oid: %s, value: %d\n",
1642                 SSAOidString(oid),num);
1643   }
1644   return(list);
1645 }
1646 
1647 SNMP_variable *
ssa_append_string_variable(SNMP_variable * list,Oid * oid,String str,char * error_label)1648 ssa_append_string_variable(SNMP_variable *list, Oid *oid, String str,
1649 	char *error_label)
1650 {
1651 	SNMP_value value;
1652 
1653 	if (str.chars == NULL)
1654 		return (NULL);
1655 	value.v_string.chars = (uchar_t *)str.chars;
1656 	value.v_string.len = str.len;
1657 	list = snmp_typed_variable_append(list, oid, STRING, &value,
1658 		error_label);
1659 	if (list == NULL) {
1660 		error("ssa_append_string_variable failed: oid: %s, \
1661 			value: %s\n", SSAOidString(oid), str);
1662 	}
1663 	return (list);
1664 }
1665 
ssa_append_oid_variable(SNMP_variable * list,Oid * oid,Oid name,char * error_label)1666 SNMP_variable *ssa_append_oid_variable(SNMP_variable *list, Oid *oid, Oid name, char *error_label)
1667 {
1668   SNMP_value value;
1669 
1670   if(oid == NULL || name.subids == NULL || name.len == 0) return NULL;
1671   value.v_oid.subids = name.subids;
1672   value.v_oid.len = name.len;
1673   list = snmp_typed_variable_append(list,oid,OBJID,&value,error_label);
1674   if(list == NULL){
1675         error("ssa_append_oid_varaible(%s,%s) failed\n",
1676                 SSAOidString(oid),SSAOidString(&name));
1677   }
1678   return(list);
1679 }
1680 
1681 
1682 
1683 
1684 
1685 
1686