xref: /onnv-gate/usr/src/cmd/agents/snmp/snmplib/request.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 2004 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 <unistd.h>
30 #include <sys/types.h>
31 #include <sys/times.h>
32 #include <netinet/in.h>
33 #include <stdio.h>
34 #include <sys/socket.h>
35 #include <errno.h>
36 #include <syslog.h>
37 #include <string.h>
38 #include <arpa/inet.h>
39 #include <netdb.h>
40 #include <nlist.h>
41 
42 #include "snmp_msg.h"
43 #include "impl.h"
44 #include "trace.h"
45 #include "snmp.h"
46 #include "pdu.h"
47 #include "request.h"
48 #include "error.h"
49 
50 
51 
52 /***** GLOBAL VARIABLES *****/
53 
54 static Subid sysUptime_subids[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
55 
56 Oid sysUptime_name = { sysUptime_subids, 8 };
57 Oid sysUptime_instance = { sysUptime_subids, 9 };
58 
59 
60 /***** LOCAL VARIABLES *****/
61 
62 static uint32_t request_id = 0;
63 
64 static Subid snmpEnableAuthTraps_subids[] = { 1, 3, 6, 1, 2, 1, 11, 30, 0 };
65 static Oid snmpEnableAuthTraps_name = { snmpEnableAuthTraps_subids, 9 };
66 
67 
68 /********************************************************************/
69 
request_create(char * community,int type,char * error_label)70 /* static */ SNMP_pdu *request_create(char *community, int type, char *error_label)
71 {
72 	SNMP_pdu *request;
73 
74 
75 	error_label[0] = '\0';
76 
77 	switch(type)
78 	{
79 		case GET_REQ_MSG:
80 		case GETNEXT_REQ_MSG:
81 		case SET_REQ_MSG:
82 			break;
83 
84 		default:
85 			sprintf(error_label, "BUG: request_create(): bad type (0x%x)",
86 				type);
87 			return NULL;
88 	}
89 
90 	request = snmp_pdu_new(error_label);
91 	if(request == NULL)
92 	{
93 		return NULL;
94 	}
95 
96 	request->version = SNMP_VERSION_1;
97 	request->community = strdup(community);
98 	if(request->community == NULL)
99 	{
100 		sprintf(error_label, ERR_MSG_ALLOC);
101 		snmp_pdu_free(request);
102 		return NULL;
103 	}
104 	request->type = type;
105 	request->request_id = request_id++;
106 
107 
108 	return request;
109 }
110 
111 
112 /********************************************************************/
113 
request_send_to_port_time_out_blocking(IPAddress * ip_address,int port,struct timeval * timeout,SNMP_pdu * request,char * error_label)114 SNMP_pdu *request_send_to_port_time_out_blocking(IPAddress *ip_address, int port,struct timeval *timeout,SNMP_pdu *request, char *error_label)
115 {
116 	int sd;
117 	Address address;
118 	SNMP_pdu *response;
119 	Address me;
120 	int numfds;
121 	fd_set fdset;
122 	int count;
123 
124 
125 	error_label[0] = '\0';
126 
127 	if(request == NULL)
128 	{
129 		sprintf(error_label, "BUG: request_send_blocking(): request is NULL");
130 		return NULL;
131 	}
132 
133 	switch(request->type)
134 	{
135 		case GET_REQ_MSG:
136 		case GETNEXT_REQ_MSG:
137 		case SET_REQ_MSG:
138 			break;
139 
140 		default:
141 			sprintf(error_label, "BUG: request_send_blocking(): bad type (0x%x)",
142 				request->type);
143 			return NULL;
144 	}
145 
146 	/* sd */
147 	sd = socket(AF_INET, SOCK_DGRAM, 0);
148 	if(sd < 0)
149 	{
150 		sprintf(error_label, ERR_MSG_SOCKET,
151 			errno_string());
152 		return (NULL);
153 	}
154 
155 	memset(&me, 0, sizeof (Address));
156 	me.sin_family = AF_INET;
157 	if ((request->type) == SET_REQ_MSG)
158 		me.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
159 	else
160 		me.sin_addr.s_addr = htonl(INADDR_ANY);
161 	me.sin_port = htons(0);
162 	if(bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0)
163 	{
164 		sprintf(error_label, ERR_MSG_BIND,
165 			errno_string());
166 		(void)close(sd);
167 		return NULL;
168 	}
169 
170 	/* address */
171 	memset(&address, 0, sizeof(Address));
172 	address.sin_family = AF_INET;
173 	/* LINTED */
174 	address.sin_port = (short)port;
175 	address.sin_addr.s_addr = ip_address->s_addr;
176 
177 	if(snmp_pdu_send(sd, &address, request, error_label))
178 	{
179 		(void)close(sd);
180 		return NULL;
181 	}
182 
183 
184 	for (;;)
185 	{
186 		numfds = 0;
187 		FD_ZERO(&fdset);
188 
189 		numfds = sd + 1;
190 		FD_SET(sd, &fdset);
191 
192 		count = select(numfds, &fdset, 0, 0, timeout);
193 		if(count > 0)
194 		{
195 			if(FD_ISSET(sd, &fdset))
196 			{
197 				response = snmp_pdu_receive(sd, &address, error_label);
198 				if(response == NULL)
199 				{
200 					(void)close(sd);
201 					return NULL;
202 				}
203 				(void)close(sd);
204 
205 				return response;
206 			}
207 		}
208 		else
209 		{
210 			switch(count)
211 			{
212 				case 0:
213 					sprintf(error_label, ERR_MSG_TIMEOUT);
214 					(void)close(sd);
215 					return NULL;
216 
217 				case -1:
218 					if(errno == EINTR)
219 					{
220 						continue;
221 					}
222 					else
223 					{
224 						sprintf(error_label, ERR_MSG_SELECT,
225 							errno_string());
226 						(void)close(sd);
227 						return NULL;
228 					}
229 			}
230 		}
231 	}
232 	/* NOTREACHED */
233 }
234 
235 
request_send_to_port_blocking(IPAddress * ip_address,int port,SNMP_pdu * request,char * error_label)236 SNMP_pdu *request_send_to_port_blocking(IPAddress *ip_address, int port,SNMP_pdu *request, char *error_label)
237 {
238 	struct timeval timeout;
239 
240 	timeout.tv_sec = 100;
241 	timeout.tv_usec = 0;
242 	return(request_send_to_port_time_out_blocking
243 		(ip_address,port,&timeout,request,error_label));
244 }
245 
246 
request_send_blocking(IPAddress * ip_address,SNMP_pdu * request,char * error_label)247 /*static*/ SNMP_pdu *request_send_blocking(IPAddress *ip_address, SNMP_pdu *request, char *error_label)
248 {
249   return(request_send_to_port_blocking(ip_address,SNMP_PORT,request,error_label));
250 }
251 
252 /********************************************************************/
253 
254 /*
255  *	if the request failed, this function returns 0
256  *	otherwise it returns sysUpTime
257  */
258 
request_sysUpTime(char * error_label,char * community_name)259 int32_t request_sysUpTime(char *error_label, char *community_name)
260 {
261 	static int my_ip_address_initialized = False;
262 	static IPAddress my_ip_address;
263 	SNMP_pdu *request;
264 	SNMP_pdu *response;
265 	SNMP_variable *variable;
266 	static int32_t sysUpTime = 0;
267 	static clock_t last = 0;
268 	clock_t now;
269 	struct tms buffer;
270 
271 
272 	error_label[0] = '\0';
273 
274 	now = times(&buffer);
275 	if( (last == 0) || ((now - last) > 360000) )	/* 1 hour */
276 	{
277 		if(my_ip_address_initialized == False)
278 		{
279 			if(get_my_ip_address(&my_ip_address, error_label))
280 			{
281 				return 0;
282 			}
283 
284 			my_ip_address_initialized = True;
285 		}
286 
287 		if(community_name == NULL)
288 			request = request_create("public", GET_REQ_MSG, error_label);
289 		else
290 			request = request_create(community_name, GET_REQ_MSG, error_label);
291 
292 		if(request == NULL)
293 		{
294 			return 0;
295 		}
296 
297 		if(snmp_pdu_append_null_variable(request, &sysUptime_instance, error_label) == NULL)
298 		{
299 			snmp_pdu_free(request);
300 			return 0;
301 		}
302 
303 		response = request_send_blocking(&my_ip_address, request, error_label);
304 		if(response == NULL)
305 		{
306 			snmp_pdu_free(request);
307 			return 0;
308 		}
309 		snmp_pdu_free(request);
310 
311 		if(response->error_status)
312 		{
313 			sprintf(error_label, "%s",
314 				error_status_string(response->error_status));
315 			snmp_pdu_free(response);
316 			return 0;
317 		}
318 
319 		variable = response->first_variable;
320 		if(variable->next_variable
321 			|| SSAOidCmp(&(variable->name), &sysUptime_instance)
322 			|| (variable->type != TIMETICKS)
323 			|| (variable->val.integer == NULL)
324 			|| (variable->val_len != sizeof(int32_t)) )
325 		{
326 			sprintf(error_label, ERR_MSG_BAD_RESPONSE);
327 			snmp_pdu_free(response);
328 			return 0;
329 		}
330 		sysUpTime = *(variable->val.integer);
331 		last = now;
332 		snmp_pdu_free(response);
333 
334 		if(trace_level > 0)
335 		{
336 			trace("sysUpTime: %d\n\n", sysUpTime);
337 		}
338 
339 		return sysUpTime;
340 	}
341 
342 	/* LINTED */
343 	return (sysUpTime + (int32_t)(now - last));
344 }
345 
346 
347 /********************************************************************/
348 
349 /*
350  *	if the request failed, this function returns  -1
351  *	otherwise it returns True or False accordind to the
352  *	value of snmpEnableAuthTraps
353  */
354 
request_snmpEnableAuthTraps(char * error_label)355 int request_snmpEnableAuthTraps(char *error_label)
356 {
357 	static int my_ip_address_initialized = False;
358 	static IPAddress my_ip_address;
359 	SNMP_pdu *request;
360 	SNMP_pdu *response;
361 	SNMP_variable *variable;
362 	int snmpEnableAuthTraps;
363 	struct timeval timeout;
364 
365 	timeout.tv_sec = 5;
366 	timeout.tv_usec = 0;
367 
368 
369 	error_label[0] = '\0';
370 
371 	if(my_ip_address_initialized == False)
372 	{
373 		if(get_my_ip_address(&my_ip_address, error_label))
374 		{
375 			return -1;
376 		}
377 
378 		my_ip_address_initialized = True;
379 	}
380 
381 	request = request_create("public", GET_REQ_MSG, error_label);
382 	if(request == NULL)
383 	{
384 		return -1;
385 	}
386 
387 	if(snmp_pdu_append_null_variable(request, &snmpEnableAuthTraps_name, error_label) == NULL)
388 	{
389 		snmp_pdu_free(request);
390 		return -1;
391 	}
392 
393 	response = request_send_to_port_time_out_blocking(&my_ip_address, \
394 		SNMP_PORT, &timeout, request, error_label);
395 	if(response == NULL)
396 	{
397 		snmp_pdu_free(request);
398 		return -1;
399 	}
400 	snmp_pdu_free(request);
401 
402 	if(response->error_status)
403 	{
404 		sprintf(error_label, "%s",
405 			error_status_string(response->error_status));
406 		snmp_pdu_free(response);
407 		return -1;
408 	}
409 
410 	variable = response->first_variable;
411 	if(variable->next_variable
412 		|| SSAOidCmp(&(variable->name), &snmpEnableAuthTraps_name)
413 		|| (variable->type != INTEGER)
414 		|| (variable->val.integer == NULL)
415 		|| (variable->val_len != sizeof(int32_t)) )
416 	{
417 		sprintf(error_label, ERR_MSG_BAD_RESPONSE);
418 		snmp_pdu_free(response);
419 		return -1;
420 	}
421 	snmpEnableAuthTraps = *(variable->val.integer);
422 	snmp_pdu_free(response);
423 
424 	if(trace_level > 0)
425 	{
426 		trace("snmpAuthTraps: %s\n\n",
427 			(snmpEnableAuthTraps == 1)? "enabled(1)": "disabled(2)");
428 	}
429 
430 	switch(snmpEnableAuthTraps)
431 	{
432 		case 1: /* enabled(1) */
433 			return TRUE;
434 		case 2: /* disable(2) */
435 			return FALSE;
436 		default:
437 			sprintf(error_label, ERR_MSG_BAD_VALUE);
438 			return -1;
439 	}
440 }
441 
442 
443 /********************************************************************/
444 
445