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