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