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 54static Subid sysUptime_subids[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 }; 55 56Oid sysUptime_name = { sysUptime_subids, 8 }; 57Oid sysUptime_instance = { sysUptime_subids, 9 }; 58 59 60/***** LOCAL VARIABLES *****/ 61 62static uint32_t request_id = 0; 63 64static Subid snmpEnableAuthTraps_subids[] = { 1, 3, 6, 1, 2, 1, 11, 30, 0 }; 65static Oid snmpEnableAuthTraps_name = { snmpEnableAuthTraps_subids, 9 }; 66 67 68/********************************************************************/ 69 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 114SNMP_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 236SNMP_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 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 259int32_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 355int 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