10Sstevel@tonic-gate /*
2*3820Spd155743 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
60Sstevel@tonic-gate
70Sstevel@tonic-gate /***********************************************************
80Sstevel@tonic-gate Copyright 1989 by Carnegie Mellon University
90Sstevel@tonic-gate
100Sstevel@tonic-gate All Rights Reserved
110Sstevel@tonic-gate
120Sstevel@tonic-gate Permission to use, copy, modify, and distribute this software and its
130Sstevel@tonic-gate documentation for any purpose and without fee is hereby granted,
140Sstevel@tonic-gate provided that the above copyright notice appear in all copies and that
150Sstevel@tonic-gate both that copyright notice and this permission notice appear in
160Sstevel@tonic-gate supporting documentation, and that the name of CMU not be
170Sstevel@tonic-gate used in advertising or publicity pertaining to distribution of the
180Sstevel@tonic-gate software without specific, written prior permission.
190Sstevel@tonic-gate
200Sstevel@tonic-gate CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
210Sstevel@tonic-gate ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
220Sstevel@tonic-gate CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
230Sstevel@tonic-gate ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
240Sstevel@tonic-gate WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
250Sstevel@tonic-gate ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
260Sstevel@tonic-gate SOFTWARE.
270Sstevel@tonic-gate ******************************************************************/
280Sstevel@tonic-gate /************
290Sstevel@tonic-gate * HISTORY
300Sstevel@tonic-gate * 5-14-96 Jerry Yeung add request filter
310Sstevel@tonic-gate * 5-28-96 Jerry Yeung Three phase set protocol(Three Phase)
320Sstevel@tonic-gate * 9-18-96 Jerry Yeung agent_process has wrong arg.
330Sstevel@tonic-gate ***********/
340Sstevel@tonic-gate
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate #include <sys/time.h>
400Sstevel@tonic-gate #include <sys/param.h>
410Sstevel@tonic-gate #include <netinet/in.h>
420Sstevel@tonic-gate #include <sys/socket.h>
430Sstevel@tonic-gate #include <netinet/in.h>
440Sstevel@tonic-gate #include <arpa/inet.h>
450Sstevel@tonic-gate #include <netdb.h>
460Sstevel@tonic-gate #include <sys/times.h>
470Sstevel@tonic-gate #include <limits.h>
480Sstevel@tonic-gate
490Sstevel@tonic-gate #include "impl.h"
500Sstevel@tonic-gate #include "error.h"
510Sstevel@tonic-gate #include "trace.h"
520Sstevel@tonic-gate #include "asn1.h"
530Sstevel@tonic-gate #include "snmp.h"
540Sstevel@tonic-gate #include "pdu.h"
550Sstevel@tonic-gate #include "request.h"
560Sstevel@tonic-gate
570Sstevel@tonic-gate #include "snmprelay_msg.h"
580Sstevel@tonic-gate #include "agent.h"
590Sstevel@tonic-gate #include "subtree.h"
600Sstevel@tonic-gate #include "access.h"
610Sstevel@tonic-gate #include "session.h"
620Sstevel@tonic-gate #include "dispatcher.h"
630Sstevel@tonic-gate #include "trap.h"
640Sstevel@tonic-gate
650Sstevel@tonic-gate
660Sstevel@tonic-gate
670Sstevel@tonic-gate /***** LOCAL CONSTANTS *****/
680Sstevel@tonic-gate
690Sstevel@tonic-gate #define SESSION_ID_MASK 0xffffff00
700Sstevel@tonic-gate #define SESSION_ID_INCREMENT_VALUE 256
710Sstevel@tonic-gate #define REQUEST_ID_MASK 0x000000ff
720Sstevel@tonic-gate #define INVALID_ERROR_INDEX 0
730Sstevel@tonic-gate
740Sstevel@tonic-gate /***** LOCAL VARIABLES *****/
750Sstevel@tonic-gate
76*3820Spd155743 Session *first_session = NULL;
770Sstevel@tonic-gate
780Sstevel@tonic-gate static u_long session_id = 0;
790Sstevel@tonic-gate
800Sstevel@tonic-gate static int session_internal_error = FALSE; /* only used bu session_open() */
810Sstevel@tonic-gate
820Sstevel@tonic-gate /**** Three Phase ****/
830Sstevel@tonic-gate static Three_Phase three_phase;
840Sstevel@tonic-gate
850Sstevel@tonic-gate
860Sstevel@tonic-gate /***** LOCAL FUNCTIONS *****/
870Sstevel@tonic-gate
880Sstevel@tonic-gate static void trace_session(Session *session);
890Sstevel@tonic-gate static void trace_request(Request *request);
900Sstevel@tonic-gate
910Sstevel@tonic-gate static Session *session_open(Address *address, SNMP_pdu *pdu);
92*3820Spd155743 void session_close(Session *session);
930Sstevel@tonic-gate
940Sstevel@tonic-gate static int session_build_request_list(Session *session, int index, SNMP_variable *variable, Subtree *subtree);
950Sstevel@tonic-gate static int session_build_local_sysUptime(Session *session, int index, SNMP_variable *variable);
960Sstevel@tonic-gate
970Sstevel@tonic-gate
98*3820Spd155743 void session_remove_from_list(Session *session);
990Sstevel@tonic-gate
100*3820Spd155743 void session_free(Session *session);
101*3820Spd155743 void request_list_free(Request *request_list);
102*3820Spd155743 void request_free(Request *request);
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate static void session_respond(Session *session);
1050Sstevel@tonic-gate static void session_respond_error(Session *session, int status, int index);
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate static Session *session_find(Address *address, u_long request_id);
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate static int session_send_request(Request *request);
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate static Request *session_move_request(Request *request, Subtree *subtree);
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate static int session_timeout_loop(struct timeval *now);
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /* (5-14-96) */
1160Sstevel@tonic-gate static void session_process_response(SNMP_pdu *pdu_read,int doRespondHere);
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate static int session_send_loopback_request(Request *request,int doRespondHere);
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate static int community_check(Address * address, Agent* agent, int pdu_type, char * community);
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate /* These 3 functions are used to prevent oscillations between */
1230Sstevel@tonic-gate /* 2 agents when we try to retreive an empty table */
1240Sstevel@tonic-gate /* Example: */
1250Sstevel@tonic-gate /* Suppose that we have a table and the columns */
1260Sstevel@tonic-gate /* with an index 1.x are supported by agent A and the */
1270Sstevel@tonic-gate /* columns with an index 2.y are supporeted by agent B */
1280Sstevel@tonic-gate /* Suppose that in fact this table is empty and we send */
1290Sstevel@tonic-gate /* send the request Get-Next(columnA) */
1300Sstevel@tonic-gate /* */
1310Sstevel@tonic-gate /* Here is the sequence: */
1320Sstevel@tonic-gate /* Get-Next(columnA) on subtree columnA ==> No Such Name */
1330Sstevel@tonic-gate /* Get-Next(columnA) on subtree columnA.2 ==> No Such Name */
1340Sstevel@tonic-gate /* Get-Next(columnA) on subtree columnB ==> No Such Name */
1350Sstevel@tonic-gate /* Get-Next(columnA) on subtree columnB.2 ==> No Such Name */
1360Sstevel@tonic-gate /* .... */
1370Sstevel@tonic-gate /* */
1380Sstevel@tonic-gate /* That is why we have to register which agents we have */
1390Sstevel@tonic-gate /* already visited and not only the last one */
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate static int request_add_visited_agent(Request *request, Agent *agent);
1420Sstevel@tonic-gate static void agent_list_free(Agent_List *alp);
1430Sstevel@tonic-gate static int is_in_agent_list(Agent_List *agent_list, Agent *agent);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate /************************************************************************/
1470Sstevel@tonic-gate
trace_sessions()1480Sstevel@tonic-gate void trace_sessions()
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate Session *sp;
1510Sstevel@tonic-gate int count = 0;
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate trace("SESSIONS:\n");
1550Sstevel@tonic-gate trace("---------\n");
1560Sstevel@tonic-gate for(sp = first_session; sp; sp = sp->next_session)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate trace("session %d:\n", sp->session_id);
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate trace_session(sp);
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate count++;
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate trace("NUMBER OF SESSIONS: %d\n", count);
1650Sstevel@tonic-gate trace("\n");
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /************************************************************************/
1700Sstevel@tonic-gate
trace_session(Session * session)1710Sstevel@tonic-gate static void trace_session(Session *session)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate Request *request;
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate trace("\taddress: %s\n",
1770Sstevel@tonic-gate address_string(&(session->address)));
1780Sstevel@tonic-gate if(trace_level > 2)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate trace("\tn_variables: %d\n", session->n_variables);
1810Sstevel@tonic-gate trace("\to_flags: 0x%x\n", session->o_flags);
1820Sstevel@tonic-gate trace("\ti_flags: 0x%x\n", session->i_flags);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate trace_request(request);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /************************************************************************/
1920Sstevel@tonic-gate
trace_request(Request * request)1930Sstevel@tonic-gate static void trace_request(Request *request)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate Session *session = request->session;
1960Sstevel@tonic-gate Subtree *subtree = request->subtree;
1970Sstevel@tonic-gate Agent *agent = NULL;
1980Sstevel@tonic-gate SNMP_variable *variable;
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate if(subtree)
2020Sstevel@tonic-gate {
2030Sstevel@tonic-gate agent = subtree->agent;
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate trace("\trequest %d:\n", request->request_id);
2070Sstevel@tonic-gate if(trace_level > 2)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate trace("\t\tsession: %d\n", session->session_id);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate trace("\t\tsubtree: %s\n", (subtree)? SSAOidString(&(subtree->name)): "NULL");
2120Sstevel@tonic-gate trace("\t\tvisited agents:\n");
2130Sstevel@tonic-gate if(trace_level > 2)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate Agent_List *alp;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate for(alp = request->visited_agent_list; alp; alp = alp->next)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate trace("\t\t\t%s\n", alp->agent->name);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate if(agent)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate trace("\t\tagent: %s (%s)\n",
2260Sstevel@tonic-gate agent->name,
2270Sstevel@tonic-gate address_string(&(agent->address)));
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate else
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate trace("\t\tagent: %s\n", "NULL");
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate if(trace_level > 2)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate trace("\t\tflags: 0x%x\n", request->flags);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate trace("\t\tstate: %d\n", request->state);
2380Sstevel@tonic-gate trace("\t\tvariables:\n");
2390Sstevel@tonic-gate for(variable = request->pdu->first_variable; variable; variable = variable->next_variable)
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate trace("\t\t\t%s\n", SSAOidString(&(variable->name)));
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate if(trace_level > 3)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate trace("\t\ttime: %s\n", timeval_string(&request->time));
2470Sstevel@tonic-gate trace("\t\texpire: %s\n", timeval_string(&request->expire));
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /************************************************************************/
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate /* Three Phase: check for whether multiple agents are involved */
three_phase_protocol_in_action(SNMP_pdu * pdu)2550Sstevel@tonic-gate int three_phase_protocol_in_action(SNMP_pdu *pdu)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate SNMP_variable *variable;
2580Sstevel@tonic-gate int local_access=0;
2590Sstevel@tonic-gate int subagent_access=0;
2600Sstevel@tonic-gate Subtree* subtree;
2610Sstevel@tonic-gate Agent *agent, *prev_agent=NULL;
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate if( pdu->type != SET_REQ_MSG) return(FALSE);
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate for(variable=pdu->first_variable;variable;variable=variable->next_variable){
2660Sstevel@tonic-gate subtree=subtree_match(pdu->type,&(variable->name));
2670Sstevel@tonic-gate if(subtree != NULL){
2680Sstevel@tonic-gate if( (agent=subtree->agent) != NULL){
2690Sstevel@tonic-gate if(prev_agent == NULL){
2700Sstevel@tonic-gate prev_agent = agent;
2710Sstevel@tonic-gate }else if(prev_agent != agent){
2720Sstevel@tonic-gate return(TRUE);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate return(FALSE);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
any_outstanding_session()2800Sstevel@tonic-gate int any_outstanding_session()
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate return(first_session!=NULL ? TRUE: FALSE);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
anyOutstandingSetRequestRunning()2850Sstevel@tonic-gate int anyOutstandingSetRequestRunning()
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate Session *s;
2880Sstevel@tonic-gate for(s=first_session;s;s=s->next_session){
2890Sstevel@tonic-gate if(s->pdu && s->pdu->type == SET_REQ_MSG) return(TRUE);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate return(FALSE);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate
session_dispatch()2950Sstevel@tonic-gate void session_dispatch()
2960Sstevel@tonic-gate {
2970Sstevel@tonic-gate SNMP_pdu *pdu;
2980Sstevel@tonic-gate Address address;
2990Sstevel@tonic-gate Session *session;
3000Sstevel@tonic-gate SNMP_variable *variable;
3010Sstevel@tonic-gate static int VersionWarnings = 10 ;
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate pdu = snmp_pdu_receive(clients_sd, &address, error_label);
3040Sstevel@tonic-gate if(pdu == NULL)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /* To avoid flooding the console and log, print trace "wrong version" messages */
3080Sstevel@tonic-gate /* after 10 console messages. */
3090Sstevel@tonic-gate if (strncmp (error_label, "The message has a wrong version", 31) == 0 && --VersionWarnings >= 0 ) {
3100Sstevel@tonic-gate error(ERR_MSG_PDU_RECEIVED,
3110Sstevel@tonic-gate address_string(&address),
3120Sstevel@tonic-gate error_label);
3130Sstevel@tonic-gate } else {
3140Sstevel@tonic-gate trace(ERR_MSG_PDU_RECEIVED,
3150Sstevel@tonic-gate address_string(&address),
3160Sstevel@tonic-gate error_label);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate return;
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate if(pdu->type != GET_REQ_MSG
3210Sstevel@tonic-gate && pdu->type != GETNEXT_REQ_MSG
3220Sstevel@tonic-gate && pdu->type != SET_REQ_MSG)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate error("bad PDU type (0x%x) received from %s",
3250Sstevel@tonic-gate pdu->type,
3260Sstevel@tonic-gate address_string(&address));
3270Sstevel@tonic-gate snmp_pdu_free(pdu);
3280Sstevel@tonic-gate return;
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate if(pdu->first_variable == NULL)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate error("no variable in PDU received from %s",
3330Sstevel@tonic-gate address_string(&address));
3340Sstevel@tonic-gate snmp_pdu_free(pdu);
3350Sstevel@tonic-gate return;
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate session = session_find(&address, pdu->request_id);
3400Sstevel@tonic-gate if(session)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate if(trace_level > 0)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate trace("!! This request is already being processed by session %d\n\n",
3450Sstevel@tonic-gate session->session_id);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate snmp_pdu_free(pdu);
3480Sstevel@tonic-gate return;
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /* Three Phase: if the request across multi-subagents
3530Sstevel@tonic-gate * create the Three Phase object, pass the pdu from the
3540Sstevel@tonic-gate * session->three_phase->cur_pdu
3550Sstevel@tonic-gate */
3560Sstevel@tonic-gate if(three_phase_protocol_in_action(pdu)){
3570Sstevel@tonic-gate three_phase.origin_pdu = pdu;
3580Sstevel@tonic-gate /* create a corresponding get pdu */
3590Sstevel@tonic-gate three_phase.cur_pdu = snmp_pdu_dup(pdu, error_label);
3600Sstevel@tonic-gate if(three_phase.cur_pdu == NULL)
3610Sstevel@tonic-gate {
3620Sstevel@tonic-gate error("snmp_pdu_dup() failed: %s",error_label);
3630Sstevel@tonic-gate snmp_pdu_free(pdu);
3640Sstevel@tonic-gate three_phase.origin_pdu = NULL;
3650Sstevel@tonic-gate return;
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate three_phase.cur_pdu->type = GET_REQ_MSG;
3680Sstevel@tonic-gate /* form a get variable list.
3690Sstevel@tonic-gate * append to the cur_pdu */
3700Sstevel@tonic-gate for(variable=pdu->first_variable;variable;
3710Sstevel@tonic-gate variable=variable->next_variable){
3720Sstevel@tonic-gate if(snmp_pdu_append_null_variable(three_phase.cur_pdu,
3730Sstevel@tonic-gate &(variable->name),error_label) == NULL){
3740Sstevel@tonic-gate error("snmp_pdu_append_null_variable() failed: %s",
3750Sstevel@tonic-gate error_label);
3760Sstevel@tonic-gate snmp_pdu_free(pdu);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate pdu = three_phase.cur_pdu;
3800Sstevel@tonic-gate three_phase.state = PHASE_1;
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate session = session_open(&address, pdu);
3840Sstevel@tonic-gate if(session == NULL)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate if(session_internal_error == TRUE)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate error("session_open() failed for a pdu received from %s",
3890Sstevel@tonic-gate address_string(&address));
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate return;
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate if(session->i_flags == session->o_flags)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate session_respond(session);
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate return;
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate /****** (5-14-96) ****/
local_agent(Agent * agent)4050Sstevel@tonic-gate int local_agent(Agent *agent)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate return(!strcmp(agent->name,relay_agent_name)? 1 : 0);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate
local_request(Request * request)4100Sstevel@tonic-gate int local_request(Request* request)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate Agent* agent;
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate if(request && request->subtree){
4150Sstevel@tonic-gate agent = request->subtree->agent;
4160Sstevel@tonic-gate return( local_agent(agent));
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate return(FALSE); /* NOT LOCAL */
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate /************************************************************************/
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /*
4250Sstevel@tonic-gate * If this function returns NULL and session_internal_error is
4260Sstevel@tonic-gate * TRUE, an internal error occured.
4270Sstevel@tonic-gate *
4280Sstevel@tonic-gate * But if we succeed to answer the SNMP request before the
4290Sstevel@tonic-gate * end of this function, it returns NULL and session_errno
4300Sstevel@tonic-gate * is FALSE.
4310Sstevel@tonic-gate *
4320Sstevel@tonic-gate *
4330Sstevel@tonic-gate * The pdu must have at least one variable in
4340Sstevel@tonic-gate * its variable list. (This has to be checked before calling
4350Sstevel@tonic-gate * this function)
4360Sstevel@tonic-gate *
4370Sstevel@tonic-gate * As the pdu is attached in a session structure,
4380Sstevel@tonic-gate * you must not free the pdu when this function
4390Sstevel@tonic-gate * returns whether the function succeeds or fails.
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate
session_open(Address * address,SNMP_pdu * pdu)4420Sstevel@tonic-gate static Session *session_open(Address *address, SNMP_pdu *pdu)
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate Session *session;
4450Sstevel@tonic-gate SNMP_variable *variable;
4460Sstevel@tonic-gate Request *request;
4470Sstevel@tonic-gate static Subid ent_subids[] = {1, 3, 6, 1, 4, 1, 42, 2, 1, 1};
4480Sstevel@tonic-gate static Oid ent_oid = {ent_subids, 10};
4490Sstevel@tonic-gate struct tms buffer;
4500Sstevel@tonic-gate u_long time_stamp;
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate if(trace_level > 1)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate trace("## Open session %d\n\n", session_id);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate session = (Session *) malloc(sizeof(Session));
4620Sstevel@tonic-gate if(session == NULL)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate error("malloc() failed");
4650Sstevel@tonic-gate session_internal_error = TRUE;
4660Sstevel@tonic-gate return NULL;
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate session->next_session = NULL;
4690Sstevel@tonic-gate session->pdu = NULL;
4700Sstevel@tonic-gate session->first_request = NULL;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* session_id */
4740Sstevel@tonic-gate session->session_id = session_id;
4750Sstevel@tonic-gate session_id = session_id + SESSION_ID_INCREMENT_VALUE;
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate /* address */
4780Sstevel@tonic-gate memcpy(&(session->address), address, sizeof(Address));
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate /* pdu, n_variables, o_falgs, i_flags */
4810Sstevel@tonic-gate session->pdu = pdu;
4820Sstevel@tonic-gate session->n_variables = 0;
4830Sstevel@tonic-gate session->o_flags = 0;
4840Sstevel@tonic-gate session->i_flags = 0;
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate /* insert session in the session list */
4880Sstevel@tonic-gate session->next_session = first_session;
4890Sstevel@tonic-gate first_session = session;
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate /* build the requests list */
4930Sstevel@tonic-gate for(variable = pdu->first_variable; variable; variable = variable->next_variable)
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate Subtree *subtree;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate (session->n_variables)++;
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate if(session->n_variables > 32)
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate error(ERR_MSG_VARBIND_LIMIT);
5030Sstevel@tonic-gate session_close(session);
5040Sstevel@tonic-gate session_internal_error = TRUE;
5050Sstevel@tonic-gate return NULL;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate if( (
5090Sstevel@tonic-gate ( (pdu->type == GETNEXT_REQ_MSG) && (SSAOidCmp(&(variable->name), &sysUptime_name) == 0) )
5100Sstevel@tonic-gate ||
5110Sstevel@tonic-gate ( (pdu->type == GET_REQ_MSG) && (SSAOidCmp(&(variable->name), &sysUptime_instance) == 0) ) )
5120Sstevel@tonic-gate &&
5130Sstevel@tonic-gate (subtree_match(GET_REQ_MSG, &(variable->name)) == NULL) )
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate if(session_build_local_sysUptime(session, session->n_variables, variable) == -1)
5160Sstevel@tonic-gate {
5170Sstevel@tonic-gate error("session_build_local_sysUptime() failed");
5180Sstevel@tonic-gate session_close(session);
5190Sstevel@tonic-gate session_internal_error = TRUE;
5200Sstevel@tonic-gate return NULL;
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate else
5240Sstevel@tonic-gate {
5250Sstevel@tonic-gate subtree = subtree_match(pdu->type, &(variable->name));
5260Sstevel@tonic-gate if(subtree == NULL)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate /* session_respond_error() closes the session */
5290Sstevel@tonic-gate session_respond_error(session, SNMP_ERR_NOSUCHNAME, session->n_variables);
5300Sstevel@tonic-gate session_internal_error = FALSE;
5310Sstevel@tonic-gate return NULL;
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate if (subtree->agent)
5350Sstevel@tonic-gate set_first_manager (subtree->agent->first_manager);
5360Sstevel@tonic-gate else
5370Sstevel@tonic-gate set_first_manager (NULL);
5380Sstevel@tonic-gate if (community_check(address, subtree->agent, pdu->type,
5390Sstevel@tonic-gate pdu->community) == FALSE) {
5400Sstevel@tonic-gate session_respond_error(session,
5410Sstevel@tonic-gate SNMP_ERR_AUTHORIZATIONERROR,
5420Sstevel@tonic-gate session->n_variables);
5430Sstevel@tonic-gate /* send authentication trap after error response */
5440Sstevel@tonic-gate time_stamp = (Integer) times(&buffer);
5450Sstevel@tonic-gate trap_filter_action(&ent_oid,SNMP_TRAP_AUTHFAIL,0,time_stamp,NULL);
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate session_close(session);
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate session_internal_error = TRUE;
5510Sstevel@tonic-gate return NULL;
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate if(session_build_request_list(session, session->n_variables, variable, subtree) == -1)
5540Sstevel@tonic-gate {
5550Sstevel@tonic-gate error("session_build_request_list() failed");
5560Sstevel@tonic-gate session_close(session);
5570Sstevel@tonic-gate session_internal_error = TRUE;
5580Sstevel@tonic-gate return NULL;
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate if(trace_level > 1)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate trace_session(session);
5670Sstevel@tonic-gate trace("\n");
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate /* send the requests */
5720Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate if(request->state == 0) /* request not sent/process yet */
5750Sstevel@tonic-gate {
5760Sstevel@tonic-gate if(local_request(request)){
5770Sstevel@tonic-gate if(session_send_loopback_request(request,FALSE) == -1){
5780Sstevel@tonic-gate error("session_send_loopback_request() failed");
5790Sstevel@tonic-gate session_close(session);
5800Sstevel@tonic-gate session_internal_error = TRUE;
5810Sstevel@tonic-gate return NULL;
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate }else if(session_send_request(request) == -1)
5840Sstevel@tonic-gate {
5850Sstevel@tonic-gate error("session_send_request() failed");
5860Sstevel@tonic-gate session_close(session);
5870Sstevel@tonic-gate session_internal_error = TRUE;
5880Sstevel@tonic-gate return NULL;
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate return session;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /************************************************************************/
5990Sstevel@tonic-gate
session_build_local_sysUptime(Session * session,int index,SNMP_variable * variable)6000Sstevel@tonic-gate static int session_build_local_sysUptime(Session *session, int index, SNMP_variable *variable)
6010Sstevel@tonic-gate {
6020Sstevel@tonic-gate Request *last_request = NULL;
6030Sstevel@tonic-gate Request *request;
6040Sstevel@tonic-gate u_long request_id = 0;
6050Sstevel@tonic-gate SNMP_value value;
6060Sstevel@tonic-gate struct tms buffer;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate request_id++;
6120Sstevel@tonic-gate last_request = request;
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate request = (Request *) malloc(sizeof(Request));
6170Sstevel@tonic-gate if(request == NULL)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate error("malloc() failed");
6200Sstevel@tonic-gate return -1;
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate memset(request, 0, sizeof(Request));
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate request->session = session;
6250Sstevel@tonic-gate request->subtree = NULL;
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate request->request_id = request_id;
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate request->pdu = snmp_pdu_dup(session->pdu, error_label);
6300Sstevel@tonic-gate if(request->pdu == NULL)
6310Sstevel@tonic-gate {
6320Sstevel@tonic-gate error("snmp_pdu_dup() failed: %s", error_label);
6330Sstevel@tonic-gate request_free(request);
6340Sstevel@tonic-gate return -1;
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate request->pdu->request_id = session->session_id + request->request_id;
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate request->pdu->first_variable = snmp_variable_dup(variable, error_label);
6390Sstevel@tonic-gate if(request->pdu->first_variable == NULL)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate error("snmp_variable_dup() failed: %s", error_label);
6420Sstevel@tonic-gate request_free(request);
6430Sstevel@tonic-gate return -1;
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate request->flags = (1 << (index - 1));
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate request->state = 0;
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /* append this request to the request */
6510Sstevel@tonic-gate /* list of the session */
6520Sstevel@tonic-gate if(last_request)
6530Sstevel@tonic-gate {
6540Sstevel@tonic-gate last_request->next_request = request;
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate else
6570Sstevel@tonic-gate {
6580Sstevel@tonic-gate session->first_request = request;
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate request->flags = (1 << (index - 1));
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate /* now answer! */
6650Sstevel@tonic-gate request->response = snmp_pdu_dup(session->pdu, error_label);
6660Sstevel@tonic-gate if(request->response == NULL)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate error("snmp_pdu_dup() failed: %s", error_label);
6690Sstevel@tonic-gate return -1;
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate request->response->type = GET_RSP_MSG;
6720Sstevel@tonic-gate request->response->request_id = session->session_id + request->request_id;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate value.v_integer = (Integer) times(&buffer);
6750Sstevel@tonic-gate request->response->first_variable = snmp_typed_variable_new(&sysUptime_instance, TIMETICKS,
6760Sstevel@tonic-gate &value, error_label);
6770Sstevel@tonic-gate if(request->response->first_variable == NULL)
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate error("snmp_typed_variable_new() failed: %s", error_label);
6800Sstevel@tonic-gate return -1;
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate session->o_flags = session->o_flags | request->flags;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate request->state = REQUEST_COMPLETED;
6860Sstevel@tonic-gate session->i_flags = session->i_flags | request->flags;
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate return 0;
6900Sstevel@tonic-gate }
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate /************************************************************************/
6940Sstevel@tonic-gate
session_build_request_list(Session * session,int index,SNMP_variable * variable,Subtree * subtree)6950Sstevel@tonic-gate static int session_build_request_list(Session *session, int index, SNMP_variable *variable, Subtree *subtree)
6960Sstevel@tonic-gate {
6970Sstevel@tonic-gate Request *last_request = NULL;
6980Sstevel@tonic-gate Request *request;
6990Sstevel@tonic-gate u_long request_id = 0;
7000Sstevel@tonic-gate SNMP_variable *new_variable;
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate if(mode == MODE_GROUP)
7040Sstevel@tonic-gate {
7050Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate if(request->subtree && request->subtree->agent == subtree->agent)
7080Sstevel@tonic-gate {
7090Sstevel@tonic-gate break;
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate request_id++;
7130Sstevel@tonic-gate last_request = request;
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate }
7160Sstevel@tonic-gate else /* MODE_SPLIT */
7170Sstevel@tonic-gate {
7180Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate request_id++;
7210Sstevel@tonic-gate last_request = request;
7220Sstevel@tonic-gate }
7230Sstevel@tonic-gate }
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate if(request == NULL)
7270Sstevel@tonic-gate {
7280Sstevel@tonic-gate request = (Request *) malloc(sizeof(Request));
7290Sstevel@tonic-gate if(request == NULL)
7300Sstevel@tonic-gate {
7310Sstevel@tonic-gate error("malloc() failed");
7320Sstevel@tonic-gate return -1;
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate request->next_request = NULL;
7350Sstevel@tonic-gate request->visited_agent_list = NULL;
7360Sstevel@tonic-gate request->pdu = NULL;
7370Sstevel@tonic-gate request->response = NULL;
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate request->session = session;
7400Sstevel@tonic-gate request->subtree = subtree;
7410Sstevel@tonic-gate if(request_add_visited_agent(request, subtree->agent) == -1)
7420Sstevel@tonic-gate {
7430Sstevel@tonic-gate request_free(request);
7440Sstevel@tonic-gate return -1;
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate request->request_id = request_id;
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate request->pdu = snmp_pdu_dup(session->pdu, error_label);
7500Sstevel@tonic-gate if(request->pdu == NULL)
7510Sstevel@tonic-gate {
7520Sstevel@tonic-gate error("snmp_pdu_dup() failed: %s", error_label);
7530Sstevel@tonic-gate request_free(request);
7540Sstevel@tonic-gate return -1;
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate request->flags = 0;
7580Sstevel@tonic-gate request->state = 0;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate /* append this request to the request */
7610Sstevel@tonic-gate /* list of the session */
7620Sstevel@tonic-gate if(last_request)
7630Sstevel@tonic-gate {
7640Sstevel@tonic-gate last_request->next_request = request;
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate else
7670Sstevel@tonic-gate {
7680Sstevel@tonic-gate session->first_request = request;
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate new_variable = snmp_variable_dup(variable, error_label);
7740Sstevel@tonic-gate if(new_variable == NULL)
7750Sstevel@tonic-gate {
7760Sstevel@tonic-gate error("snmp_variable_dup() failed: %s", error_label);
7770Sstevel@tonic-gate return -1;
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate request->flags = request->flags | (1 << (index - 1));
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate /* append the new variable to the variable list of request->pdu */
7840Sstevel@tonic-gate if(request->pdu->first_variable)
7850Sstevel@tonic-gate {
7860Sstevel@tonic-gate SNMP_variable *current_variable;
7870Sstevel@tonic-gate SNMP_variable *last_variable;
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate for(current_variable = request->pdu->first_variable; current_variable; current_variable = current_variable->next_variable)
7910Sstevel@tonic-gate {
7920Sstevel@tonic-gate last_variable = current_variable;
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate last_variable->next_variable = new_variable;
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate else
7970Sstevel@tonic-gate {
7980Sstevel@tonic-gate request->pdu->first_variable = new_variable;
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate return 0;
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate /************************************************************************/
8070Sstevel@tonic-gate
session_close(Session * session)808*3820Spd155743 void session_close(Session *session)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate Three_Phase *tp;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate if(trace_level > 1)
8130Sstevel@tonic-gate {
8140Sstevel@tonic-gate trace("## Close session %d\n\n", session->session_id);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate /* remove it from the session list */
8180Sstevel@tonic-gate session_remove_from_list(session);
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate /* free the space allocated for the session */
8210Sstevel@tonic-gate session_free(session);
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate return;
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate /************************************************************************/
8290Sstevel@tonic-gate
session_list_delete()8300Sstevel@tonic-gate void session_list_delete()
8310Sstevel@tonic-gate {
8320Sstevel@tonic-gate Session *sp = first_session;
8330Sstevel@tonic-gate Session *next;
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate while(sp)
8370Sstevel@tonic-gate {
8380Sstevel@tonic-gate next = sp->next_session;
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate session_free(sp);
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate sp = next;
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate
8450Sstevel@tonic-gate first_session = NULL;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate /************************************************************************/
8500Sstevel@tonic-gate
session_remove_from_list(Session * session)851*3820Spd155743 void session_remove_from_list(Session *session)
8520Sstevel@tonic-gate {
8530Sstevel@tonic-gate Session *sp;
8540Sstevel@tonic-gate Session *osp;
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate osp = NULL;
8580Sstevel@tonic-gate for(sp = first_session; sp; sp = sp->next_session)
8590Sstevel@tonic-gate {
8600Sstevel@tonic-gate if(sp == session)
8610Sstevel@tonic-gate {
8620Sstevel@tonic-gate break;
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate osp = sp;
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate if(sp == NULL)
8690Sstevel@tonic-gate {
8700Sstevel@tonic-gate error("session_remove_from_list() : session (0x%x) not found", session);
8710Sstevel@tonic-gate return;
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate if(osp == NULL)
8750Sstevel@tonic-gate {
8760Sstevel@tonic-gate first_session = sp->next_session;
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate else
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate osp->next_session = sp->next_session;
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate return;
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate /************************************************************************/
8890Sstevel@tonic-gate
session_free(Session * session)890*3820Spd155743 void session_free(Session *session)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate if(session == NULL)
8930Sstevel@tonic-gate {
8940Sstevel@tonic-gate return;
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate snmp_pdu_free(session->pdu);
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate request_list_free(session->first_request);
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate free(session);
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate return;
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate /************************************************************************/
9090Sstevel@tonic-gate
request_list_free(Request * request_list)910*3820Spd155743 void request_list_free(Request *request_list)
9110Sstevel@tonic-gate {
9120Sstevel@tonic-gate Request *next_request;
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate while(request_list)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate next_request = request_list->next_request;
9180Sstevel@tonic-gate request_free(request_list);
9190Sstevel@tonic-gate request_list = next_request;
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate /************************************************************************/
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate /* This function will send a response and close the session */
9270Sstevel@tonic-gate /* It should be invoked when o_flags == i_flags */
9280Sstevel@tonic-gate
session_respond(Session * session)9290Sstevel@tonic-gate static void session_respond(Session *session)
9300Sstevel@tonic-gate {
9310Sstevel@tonic-gate SNMP_variable *first_variable = NULL;
9320Sstevel@tonic-gate SNMP_variable *variable;
9330Sstevel@tonic-gate SNMP_variable *last_variable;
9340Sstevel@tonic-gate Request *request;
9350Sstevel@tonic-gate int i;
9360Sstevel@tonic-gate SNMP_pdu *response;
9370Sstevel@tonic-gate Address address;
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate /* Three Phase:
9400Sstevel@tonic-gate * If the session is the three_phase session, basing on the state
9410Sstevel@tonic-gate * we will have different process:
9420Sstevel@tonic-gate * state is 1: if successful, store the variable list. close the
9430Sstevel@tonic-gate * current session. The free the cur_pdu's variable
9440Sstevel@tonic-gate * list, attach the variable list from get.
9450Sstevel@tonic-gate * change cur_pdu->type=SET_REQ_MSG. create a
9460Sstevel@tonic-gate * new session(session_open) for next state. the pdu
9470Sstevel@tonic-gate * is origin_pdu.
9480Sstevel@tonic-gate * state = PHASE_2;
9490Sstevel@tonic-gate * state is PHASE_2: if successful. follows thru. else close the
9500Sstevel@tonic-gate * current session. create a new session with the
9510Sstevel@tonic-gate * cur_pdu. wait for response.
9520Sstevel@tonic-gate * In addition, send error response to appl.
9530Sstevel@tonic-gate * state = PHASE_3;
9540Sstevel@tonic-gate * state is PHASE_3:
9550Sstevel@tonic-gate * drop the response.
9560Sstevel@tonic-gate */
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
9590Sstevel@tonic-gate {
9600Sstevel@tonic-gate if(request->state != REQUEST_COMPLETED)
9610Sstevel@tonic-gate {
9620Sstevel@tonic-gate error("BUG: session_respond() : session %d - request %d: state is not COMPLETED",
9630Sstevel@tonic-gate session->session_id,
9640Sstevel@tonic-gate request->request_id);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate /* we will extract the variables from the request->reponse */
9710Sstevel@tonic-gate /* variable list and append them to the variable list */
9720Sstevel@tonic-gate /* pointed by first_variable */
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate for(i = 0; i < session->n_variables; i++)
9750Sstevel@tonic-gate {
9760Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
9770Sstevel@tonic-gate {
9780Sstevel@tonic-gate if(request->flags & (1 << i))
9790Sstevel@tonic-gate {
9800Sstevel@tonic-gate break;
9810Sstevel@tonic-gate }
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate if(request == NULL)
9850Sstevel@tonic-gate {
9860Sstevel@tonic-gate error("BUG: session_respond(): request is NULL");
9870Sstevel@tonic-gate }
9880Sstevel@tonic-gate
9890Sstevel@tonic-gate if(request->response == NULL)
9900Sstevel@tonic-gate {
9910Sstevel@tonic-gate /* request timeout */
9920Sstevel@tonic-gate if(request->subtree != NULL &&
9930Sstevel@tonic-gate request->subtree->agent !=NULL){
9940Sstevel@tonic-gate /*request->subtree->agent->numOfFailRequest++*/;
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /* session_respond_error() closes the session */
9980Sstevel@tonic-gate session_respond_error(session, SNMP_ERR_NOSUCHNAME, i + 1);
9990Sstevel@tonic-gate snmp_variable_list_free(first_variable);
10000Sstevel@tonic-gate return;
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate if(request->response->error_status != SNMP_ERR_NOERROR)
10040Sstevel@tonic-gate {
10050Sstevel@tonic-gate int j;
10060Sstevel@tonic-gate int index = 0;
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate /* find the index in the variables list */
10100Sstevel@tonic-gate /* of the variable we are currently dealing with*/
10110Sstevel@tonic-gate for(j = 0; j <= i; j++)
10120Sstevel@tonic-gate {
10130Sstevel@tonic-gate if(request->flags & (1<< j))
10140Sstevel@tonic-gate {
10150Sstevel@tonic-gate index++;
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate if(request->response->error_index == index)
10200Sstevel@tonic-gate {
10210Sstevel@tonic-gate /* session_respond_error() closes the session */
10220Sstevel@tonic-gate session_respond_error(session, request->response->error_status, i + 1);
10230Sstevel@tonic-gate snmp_variable_list_free(first_variable);
10240Sstevel@tonic-gate return;
10250Sstevel@tonic-gate }
10260Sstevel@tonic-gate
10270Sstevel@tonic-gate /*
10280Sstevel@tonic-gate * error index should not be zero for a non-zero
10290Sstevel@tonic-gate * error status
10300Sstevel@tonic-gate */
10310Sstevel@tonic-gate if (request->response->error_index ==
10320Sstevel@tonic-gate INVALID_ERROR_INDEX) {
10330Sstevel@tonic-gate /* invalid error packet from sub agent */
10340Sstevel@tonic-gate error("session_respond(): the agent %s \
10350Sstevel@tonic-gate responded with zero error index, on error status : %d \n",
10360Sstevel@tonic-gate request->subtree->agent->name,
10370Sstevel@tonic-gate request->response->error_status);
10380Sstevel@tonic-gate snmp_variable_list_free(first_variable);
10390Sstevel@tonic-gate session_close(session);
10400Sstevel@tonic-gate return;
10410Sstevel@tonic-gate }
10420Sstevel@tonic-gate /* we are no more interested in building the */
10430Sstevel@tonic-gate /* variable list fist_variable */
10440Sstevel@tonic-gate continue;
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate /* remove the first variable from the request->response */
10480Sstevel@tonic-gate variable = request->response->first_variable;
10490Sstevel@tonic-gate if(variable == NULL)
10500Sstevel@tonic-gate {
10510Sstevel@tonic-gate error("session_respond(): the agent %s responded with less variables than it was asked",
10520Sstevel@tonic-gate request->subtree->agent->name);
10530Sstevel@tonic-gate session_close(session);
10540Sstevel@tonic-gate return;
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate request->response->first_variable = variable->next_variable;
10570Sstevel@tonic-gate
10580Sstevel@tonic-gate if(first_variable == NULL)
10590Sstevel@tonic-gate {
10600Sstevel@tonic-gate first_variable = variable;
10610Sstevel@tonic-gate last_variable = variable;
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate else
10640Sstevel@tonic-gate {
10650Sstevel@tonic-gate last_variable->next_variable = variable;
10660Sstevel@tonic-gate last_variable = variable;
10670Sstevel@tonic-gate }
10680Sstevel@tonic-gate } /* for */
10690Sstevel@tonic-gate
10700Sstevel@tonic-gate /* Three Phase: save the variable list */
10710Sstevel@tonic-gate if(three_phase.state == PHASE_1){
10720Sstevel@tonic-gate three_phase.variable = first_variable;
10730Sstevel@tonic-gate memcpy(&address,&(session->address),sizeof(Address));
10740Sstevel@tonic-gate session_close(session);
10750Sstevel@tonic-gate three_phase.cur_pdu = NULL;
10760Sstevel@tonic-gate three_phase.state = PHASE_2;
10770Sstevel@tonic-gate session_open(&address,three_phase.origin_pdu);
10780Sstevel@tonic-gate return;
10790Sstevel@tonic-gate }else if(three_phase.state == PHASE_2){
10800Sstevel@tonic-gate /* successful*/
10810Sstevel@tonic-gate three_phase.state = 0;
10820Sstevel@tonic-gate snmp_variable_list_free(three_phase.variable);
10830Sstevel@tonic-gate three_phase.variable = NULL;
10840Sstevel@tonic-gate three_phase.origin_pdu = NULL;
10850Sstevel@tonic-gate /* follows thru */
10860Sstevel@tonic-gate }else if(three_phase.state == PHASE_3){
10870Sstevel@tonic-gate /* drop the response */
10880Sstevel@tonic-gate session_close(session);
10890Sstevel@tonic-gate return;
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate response = snmp_pdu_dup(session->pdu, error_label);
10930Sstevel@tonic-gate if(response == NULL)
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate error("snmp_pdu_dup() failed: %s", error_label);
10960Sstevel@tonic-gate /* return ??? */
10970Sstevel@tonic-gate }
10980Sstevel@tonic-gate response->type = GET_RSP_MSG;
10990Sstevel@tonic-gate response->first_variable = first_variable;
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate if( (response->error_status != SNMP_ERR_NOERROR)
11020Sstevel@tonic-gate && (response->error_status != SNMP_ERR_NOSUCHNAME) )
11030Sstevel@tonic-gate {
11040Sstevel@tonic-gate error(ERR_MSG_SNMP_ERROR,
11050Sstevel@tonic-gate error_status_string(response->error_status), response->error_index,
11060Sstevel@tonic-gate address_string(&(session->address)));
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate if(snmp_pdu_send(clients_sd, &(session->address), response, error_label))
11100Sstevel@tonic-gate {
11110Sstevel@tonic-gate error(ERR_MSG_PDU_SEND_BACK,
11120Sstevel@tonic-gate address_string(&(session->address)),
11130Sstevel@tonic-gate error_label);
11140Sstevel@tonic-gate snmp_pdu_free(response);
11150Sstevel@tonic-gate session_close(session);
11160Sstevel@tonic-gate return;
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate snmp_pdu_free(response);
11190Sstevel@tonic-gate session_close(session);
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate return;
11230Sstevel@tonic-gate }
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate /************************************************************************/
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate /*
11290Sstevel@tonic-gate * This function sends a error response and closes the session
11300Sstevel@tonic-gate */
11310Sstevel@tonic-gate
session_respond_error(Session * session,int status,int index)11320Sstevel@tonic-gate static void session_respond_error(Session *session, int status, int index)
11330Sstevel@tonic-gate {
11340Sstevel@tonic-gate SNMP_pdu *pdu = session->pdu;
11350Sstevel@tonic-gate Address address;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /* Three Phase: if errors occurs with three phase undertaking.
11380Sstevel@tonic-gate * change the pdu to the three_phase->origin_pdu
11390Sstevel@tonic-gate */
11400Sstevel@tonic-gate if(three_phase.state == PHASE_1){
11410Sstevel@tonic-gate /* clean up three_phase */
11420Sstevel@tonic-gate session->pdu = three_phase.origin_pdu;
11430Sstevel@tonic-gate pdu = session->pdu;
11440Sstevel@tonic-gate snmp_pdu_free(three_phase.cur_pdu);
11450Sstevel@tonic-gate three_phase.cur_pdu = NULL;
11460Sstevel@tonic-gate three_phase.origin_pdu = NULL;
11470Sstevel@tonic-gate three_phase.state = 0;
11480Sstevel@tonic-gate }else if(three_phase.state == PHASE_2){
11490Sstevel@tonic-gate /* set fail, the session->pdu pts to origin_pdu */
11500Sstevel@tonic-gate three_phase.state = PHASE_3;
11510Sstevel@tonic-gate /* rollback */
11520Sstevel@tonic-gate memcpy(&address,&(session->address),sizeof(Address));
11530Sstevel@tonic-gate three_phase.cur_pdu = snmp_pdu_dup(three_phase.origin_pdu,
11540Sstevel@tonic-gate error_label);
11550Sstevel@tonic-gate three_phase.origin_pdu = NULL;
11560Sstevel@tonic-gate if(three_phase.cur_pdu != NULL){
11570Sstevel@tonic-gate three_phase.cur_pdu->first_variable =
11580Sstevel@tonic-gate three_phase.variable;
11590Sstevel@tonic-gate session_open(&address,three_phase.cur_pdu);
11600Sstevel@tonic-gate three_phase.cur_pdu = NULL;
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate }else if(three_phase.state == PHASE_3){
11630Sstevel@tonic-gate /* drop the packet */
11640Sstevel@tonic-gate three_phase.state = 0;
11650Sstevel@tonic-gate session_close(session);
11660Sstevel@tonic-gate return;
11670Sstevel@tonic-gate }
11680Sstevel@tonic-gate
11690Sstevel@tonic-gate pdu->type = GET_RSP_MSG;
11700Sstevel@tonic-gate pdu->error_status = status;
11710Sstevel@tonic-gate pdu->error_index = index;
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate if (pdu->error_status == SNMP_ERR_AUTHORIZATIONERROR) {
11740Sstevel@tonic-gate session_close(session);
11750Sstevel@tonic-gate return;
11760Sstevel@tonic-gate }
11770Sstevel@tonic-gate
11780Sstevel@tonic-gate if( (pdu->error_status != SNMP_ERR_NOERROR)
11790Sstevel@tonic-gate && (pdu->error_status != SNMP_ERR_NOSUCHNAME) )
11800Sstevel@tonic-gate {
11810Sstevel@tonic-gate error(ERR_MSG_SNMP_ERROR,
11820Sstevel@tonic-gate error_status_string(pdu->error_status), pdu->error_index,
11830Sstevel@tonic-gate address_string(&(session->address)));
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate
11860Sstevel@tonic-gate if(snmp_pdu_send(clients_sd, &(session->address), pdu, error_label))
11870Sstevel@tonic-gate {
11880Sstevel@tonic-gate error(ERR_MSG_PDU_SEND_BACK,
11890Sstevel@tonic-gate address_string(&(session->address)),
11900Sstevel@tonic-gate error_label);
11910Sstevel@tonic-gate session_close(session);
11920Sstevel@tonic-gate return;
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate session_close(session);
11950Sstevel@tonic-gate
11960Sstevel@tonic-gate return;
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate /************************************************************************/
12010Sstevel@tonic-gate
session_find(Address * address,u_long request_id)12020Sstevel@tonic-gate static Session *session_find(Address *address, u_long request_id)
12030Sstevel@tonic-gate {
12040Sstevel@tonic-gate Session *session;
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate for(session = first_session; session; session = session->next_session)
12080Sstevel@tonic-gate {
12090Sstevel@tonic-gate if( (session->pdu->request_id == request_id)
12100Sstevel@tonic-gate && (session->address.sin_port == address->sin_port)
12110Sstevel@tonic-gate && (session->address.sin_addr.s_addr == address->sin_addr.s_addr) )
12120Sstevel@tonic-gate {
12130Sstevel@tonic-gate return session;
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate return NULL;
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate /* (5-14-96) */
session_send_loopback_request(Request * request,int doRespondHere)12220Sstevel@tonic-gate static int session_send_loopback_request(Request *request,int doRespondHere)
12230Sstevel@tonic-gate {
12240Sstevel@tonic-gate Session *session = request->session;
12250Sstevel@tonic-gate SNMP_pdu *pdu;
12260Sstevel@tonic-gate Subtree *subtree = request->subtree;
12270Sstevel@tonic-gate Agent *agent;
12280Sstevel@tonic-gate struct timeval tv;
12290Sstevel@tonic-gate SNMP_variable *new_variable, *variable;
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate gettimeofday(&tv, (struct timezone *) 0);
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate if(subtree == NULL || request->pdu == NULL)
12340Sstevel@tonic-gate {
12350Sstevel@tonic-gate error("BUG: session_send_loopback_request(): subtree is NULL");
12360Sstevel@tonic-gate return -1;
12370Sstevel@tonic-gate }
12380Sstevel@tonic-gate agent = subtree->agent;
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate
12410Sstevel@tonic-gate request->time = tv;
12420Sstevel@tonic-gate tv.tv_usec = tv.tv_usec + agent->timeout;
12430Sstevel@tonic-gate tv.tv_sec = tv.tv_sec + tv.tv_usec / 1000000L;
12440Sstevel@tonic-gate tv.tv_usec = tv.tv_usec % 1000000L;
12450Sstevel@tonic-gate request->expire = tv;
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate session->o_flags = session->o_flags | request->flags;
12480Sstevel@tonic-gate request->state = REQUEST_STARTED;
12490Sstevel@tonic-gate /* duplicate the pdu */
12500Sstevel@tonic-gate pdu = snmp_pdu_dup(request->pdu, error_label);
12510Sstevel@tonic-gate pdu->request_id = session->session_id + request->request_id;
12520Sstevel@tonic-gate
12530Sstevel@tonic-gate for(variable = request->pdu->first_variable; variable;
12540Sstevel@tonic-gate variable = variable->next_variable)
12550Sstevel@tonic-gate {
12560Sstevel@tonic-gate new_variable = snmp_variable_dup(variable, error_label);
12570Sstevel@tonic-gate if(pdu->first_variable)
12580Sstevel@tonic-gate {
12590Sstevel@tonic-gate SNMP_variable *current_variable;
12600Sstevel@tonic-gate SNMP_variable *last_variable;
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate for(current_variable = pdu->first_variable;
12630Sstevel@tonic-gate current_variable;
12640Sstevel@tonic-gate current_variable = current_variable->next_variable)
12650Sstevel@tonic-gate {
12660Sstevel@tonic-gate last_variable = current_variable;
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate last_variable->next_variable = new_variable;
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate else
12710Sstevel@tonic-gate {
12720Sstevel@tonic-gate pdu->first_variable = new_variable;
12730Sstevel@tonic-gate }
12740Sstevel@tonic-gate }
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate if (agent_process(&(session->address), pdu) == -1) {
12770Sstevel@tonic-gate if (trace_level > 1) {
12780Sstevel@tonic-gate trace("local pdu process error \n");
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate snmp_pdu_free(pdu);
12810Sstevel@tonic-gate return (-1);
12820Sstevel@tonic-gate }
12830Sstevel@tonic-gate /* pdu stores the response */
12840Sstevel@tonic-gate session_process_response(pdu,doRespondHere);
12850Sstevel@tonic-gate
12860Sstevel@tonic-gate return 1;
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate
12890Sstevel@tonic-gate /************************************************************************/
12900Sstevel@tonic-gate
session_send_request(Request * request)12910Sstevel@tonic-gate static int session_send_request(Request *request)
12920Sstevel@tonic-gate {
12930Sstevel@tonic-gate Session *session = request->session;
12940Sstevel@tonic-gate SNMP_pdu *pdu = request->pdu;
12950Sstevel@tonic-gate Subtree *subtree = request->subtree;
12960Sstevel@tonic-gate Agent *agent;
12970Sstevel@tonic-gate struct timeval tv;
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate
13000Sstevel@tonic-gate pdu->request_id = session->session_id + request->request_id;
13010Sstevel@tonic-gate gettimeofday(&tv, (struct timezone *) 0);
13020Sstevel@tonic-gate
13030Sstevel@tonic-gate if(subtree == NULL)
13040Sstevel@tonic-gate {
13050Sstevel@tonic-gate error("BUG: session_send_request(): subtree is NULL");
13060Sstevel@tonic-gate return -1;
13070Sstevel@tonic-gate }
13080Sstevel@tonic-gate agent = subtree->agent;
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate if(snmp_pdu_send(agents_sd, &(agent->address), pdu, error_label))
13110Sstevel@tonic-gate {
13120Sstevel@tonic-gate error(ERR_MSG_PDU_SEND_TO,
13130Sstevel@tonic-gate address_string(&(agent->address)),
13140Sstevel@tonic-gate error_label);
13150Sstevel@tonic-gate return -1;
13160Sstevel@tonic-gate }
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate request->time = tv;
13190Sstevel@tonic-gate tv.tv_usec = tv.tv_usec + agent->timeout;
13200Sstevel@tonic-gate tv.tv_sec = tv.tv_sec + tv.tv_usec / 1000000L;
13210Sstevel@tonic-gate tv.tv_usec = tv.tv_usec % 1000000L;
13220Sstevel@tonic-gate request->expire = tv;
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate session->o_flags = session->o_flags | request->flags;
13250Sstevel@tonic-gate request->state = REQUEST_STARTED;
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate
13280Sstevel@tonic-gate return 0;
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate /************************************************************************/
13330Sstevel@tonic-gate
session_move_request(Request * request,Subtree * subtree)13340Sstevel@tonic-gate static Request *session_move_request(Request *request, Subtree *subtree)
13350Sstevel@tonic-gate {
13360Sstevel@tonic-gate Session *session = request->session;
13370Sstevel@tonic-gate
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate if(trace_level > 0)
13400Sstevel@tonic-gate {
13410Sstevel@tonic-gate trace("!! session %d - request %d: trying another subtree %s supported by %s\n\n",
13420Sstevel@tonic-gate session->session_id,
13430Sstevel@tonic-gate request->request_id,
13440Sstevel@tonic-gate SSAOidString(&(subtree->name)),
13450Sstevel@tonic-gate subtree->agent->name);
13460Sstevel@tonic-gate }
13470Sstevel@tonic-gate
13480Sstevel@tonic-gate request->subtree = subtree;
13490Sstevel@tonic-gate
13500Sstevel@tonic-gate if (subtree->agent->first_manager != NULL)
13510Sstevel@tonic-gate set_first_manager(subtree->agent->first_manager);
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate if(request_add_visited_agent(request, subtree->agent) == -1)
13540Sstevel@tonic-gate {
13550Sstevel@tonic-gate error("request_add_visited_agent() failed");
13560Sstevel@tonic-gate return NULL;
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate
13590Sstevel@tonic-gate if (local_request(request)) {
13600Sstevel@tonic-gate if (session_send_loopback_request(request, TRUE) == -1) {
13610Sstevel@tonic-gate if (trace_level > 1) {
13620Sstevel@tonic-gate trace("session_send_loopback_request() \
13630Sstevel@tonic-gate failed\n");
13640Sstevel@tonic-gate }
13650Sstevel@tonic-gate return (NULL);
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate } else if(session_send_request(request) == -1) {
13680Sstevel@tonic-gate error("session_send_request() failed");
13690Sstevel@tonic-gate return NULL;
13700Sstevel@tonic-gate }
13710Sstevel@tonic-gate
13720Sstevel@tonic-gate return request;
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate /************************************************************************/
13770Sstevel@tonic-gate
request_free(Request * request)1378*3820Spd155743 void request_free(Request *request)
13790Sstevel@tonic-gate {
13800Sstevel@tonic-gate if(request == NULL)
13810Sstevel@tonic-gate {
13820Sstevel@tonic-gate return;
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate agent_list_free(request->visited_agent_list);
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate snmp_pdu_free(request->pdu);
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate snmp_pdu_free(request->response);
13900Sstevel@tonic-gate
13910Sstevel@tonic-gate free(request);
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate return;
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate
trap_processing()13960Sstevel@tonic-gate void trap_processing()
13970Sstevel@tonic-gate {
13980Sstevel@tonic-gate Address address;
13990Sstevel@tonic-gate SNMP_pdu *trap_request;
14000Sstevel@tonic-gate struct tms buffer;
14010Sstevel@tonic-gate u_long time_stamp;
14020Sstevel@tonic-gate
14030Sstevel@tonic-gate trap_request = snmp_pdu_receive(trap_sd, &address, error_label);
14040Sstevel@tonic-gate if(trap_request == NULL)
14050Sstevel@tonic-gate {
14060Sstevel@tonic-gate error(ERR_MSG_PDU_RECEIVED,
14070Sstevel@tonic-gate address_string(&address),
14080Sstevel@tonic-gate error_label);
14090Sstevel@tonic-gate return;
14100Sstevel@tonic-gate }
14110Sstevel@tonic-gate
14120Sstevel@tonic-gate
14130Sstevel@tonic-gate if(trap_request->type != TRP_REQ_MSG)
14140Sstevel@tonic-gate {
14150Sstevel@tonic-gate error("bad PDU type (0x%x) received from %s",
14160Sstevel@tonic-gate trap_request->type,
14170Sstevel@tonic-gate address_string(&address));
14180Sstevel@tonic-gate snmp_pdu_free(trap_request);
14190Sstevel@tonic-gate return;
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate /* filter the trap_request */
14230Sstevel@tonic-gate /* currently, base on the trap-community names to decide which
14240Sstevel@tonic-gate are the list of target hosts */
14250Sstevel@tonic-gate time_stamp = (Integer) times(&buffer);
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate /* propagate those traps registered by managers */
14280Sstevel@tonic-gate trap_filter_action(&(trap_request->enterprise),
14290Sstevel@tonic-gate trap_request->generic,trap_request->specific,time_stamp,
14300Sstevel@tonic-gate trap_request->first_variable);
14310Sstevel@tonic-gate
14320Sstevel@tonic-gate snmp_pdu_free(trap_request);
14330Sstevel@tonic-gate return;
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate
14360Sstevel@tonic-gate
forward_subtree_match(Subtree * subtree,Oid * name)14370Sstevel@tonic-gate static Subtree *forward_subtree_match(Subtree *subtree, Oid *name)
14380Sstevel@tonic-gate {
14390Sstevel@tonic-gate Subtree *sp;
14400Sstevel@tonic-gate Subtree *last=NULL;
14410Sstevel@tonic-gate Subtree *first_valid_subtree;
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate if(name == NULL || subtree == NULL || first_subtree == NULL)
14450Sstevel@tonic-gate {
14460Sstevel@tonic-gate return NULL;
14470Sstevel@tonic-gate }
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate for(sp = subtree->next_subtree; sp; sp = sp->next_subtree)
14500Sstevel@tonic-gate {
14510Sstevel@tonic-gate /* subtree is invalid skip (vsb)*/
14520Sstevel@tonic-gate if(subtree_is_valid(sp)==FALSE) continue;
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate if(SSAOidCmp(name, &(sp->name)) >= 0 &&
14550Sstevel@tonic-gate sp->agent !=0 && subtree->agent !=0 &&
14560Sstevel@tonic-gate sp->agent != subtree->agent)
14570Sstevel@tonic-gate {
14580Sstevel@tonic-gate return sp;
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate return last;
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate /************************************************************************/
14680Sstevel@tonic-gate /* (5-14-96) partition into two functions */
14690Sstevel@tonic-gate /* pdu_read is not null, this routine is used for local response
14700Sstevel@tonic-gate there is a catch the session_respond is skipped, because, it will
14710Sstevel@tonic-gate be processed later in the session_open call */
14720Sstevel@tonic-gate
session_process_response(SNMP_pdu * pdu_read,int doRespondHere)14730Sstevel@tonic-gate static void session_process_response(SNMP_pdu *pdu_read,int doRespondHere)
14740Sstevel@tonic-gate {
14750Sstevel@tonic-gate Address address;
14760Sstevel@tonic-gate SNMP_pdu *response;
14770Sstevel@tonic-gate Session *session;
14780Sstevel@tonic-gate SNMP_pdu *pdu;
14790Sstevel@tonic-gate Subtree *subtree;
14800Sstevel@tonic-gate Subtree *sub;
14810Sstevel@tonic-gate Request *request;
14820Sstevel@tonic-gate
14830Sstevel@tonic-gate
14840Sstevel@tonic-gate if(pdu_read == NULL)
14850Sstevel@tonic-gate response = snmp_pdu_receive(agents_sd, &address, error_label);
14860Sstevel@tonic-gate else
14870Sstevel@tonic-gate response = pdu_read;
14880Sstevel@tonic-gate
14890Sstevel@tonic-gate if(response == NULL)
14900Sstevel@tonic-gate {
14910Sstevel@tonic-gate error(ERR_MSG_PDU_RECEIVED,
14920Sstevel@tonic-gate address_string(&address),
14930Sstevel@tonic-gate error_label);
14940Sstevel@tonic-gate return;
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate
14980Sstevel@tonic-gate if(response->type != GET_RSP_MSG)
14990Sstevel@tonic-gate {
15000Sstevel@tonic-gate error("bad PDU type (0x%x) received from %s",
15010Sstevel@tonic-gate response->type,
15020Sstevel@tonic-gate address_string(&address));
15030Sstevel@tonic-gate snmp_pdu_free(response);
15040Sstevel@tonic-gate return;
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate
15070Sstevel@tonic-gate
15080Sstevel@tonic-gate for(session = first_session; session; session = session->next_session)
15090Sstevel@tonic-gate {
15100Sstevel@tonic-gate if((response->request_id & SESSION_ID_MASK) == session->session_id)
15110Sstevel@tonic-gate {
15120Sstevel@tonic-gate break;
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate }
15150Sstevel@tonic-gate if(session == NULL)
15160Sstevel@tonic-gate {
15170Sstevel@tonic-gate Agent *agent;
15180Sstevel@tonic-gate
15190Sstevel@tonic-gate
15200Sstevel@tonic-gate agent = agent_find(&address);
15210Sstevel@tonic-gate /*
15220Sstevel@tonic-gate error(ERR_MSG_UNKNOWN_FRAGMENT,
15230Sstevel@tonic-gate agent? agent->name: "???",
15240Sstevel@tonic-gate address_string(&address));
15250Sstevel@tonic-gate */
15260Sstevel@tonic-gate snmp_pdu_free(response);
15270Sstevel@tonic-gate return;
15280Sstevel@tonic-gate }
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate for(request = session->first_request; request; request = request->next_request)
15320Sstevel@tonic-gate {
15330Sstevel@tonic-gate if((response->request_id & REQUEST_ID_MASK) == request->request_id)
15340Sstevel@tonic-gate {
15350Sstevel@tonic-gate break;
15360Sstevel@tonic-gate }
15370Sstevel@tonic-gate }
15380Sstevel@tonic-gate if(request == NULL)
15390Sstevel@tonic-gate {
15400Sstevel@tonic-gate error("request not found for the session %d for a PDU received from %s",
15410Sstevel@tonic-gate session->session_id,
15420Sstevel@tonic-gate address_string(&address));
15430Sstevel@tonic-gate snmp_pdu_free(response);
15440Sstevel@tonic-gate return;
15450Sstevel@tonic-gate }
15460Sstevel@tonic-gate if(request->state == REQUEST_COMPLETED)
15470Sstevel@tonic-gate {
15480Sstevel@tonic-gate error("a PDU has been received from %s for session %d - request %d whereas the request is already completed",
15490Sstevel@tonic-gate address_string(&address),
15500Sstevel@tonic-gate session->session_id,
15510Sstevel@tonic-gate request->request_id);
15520Sstevel@tonic-gate snmp_pdu_free(response);
15530Sstevel@tonic-gate return;
15540Sstevel@tonic-gate }
15550Sstevel@tonic-gate if(request->response)
15560Sstevel@tonic-gate {
15570Sstevel@tonic-gate error("BUG: session_read(): response is not NULL");
15580Sstevel@tonic-gate }
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate
15610Sstevel@tonic-gate pdu = session->pdu;
15620Sstevel@tonic-gate subtree = request->subtree;
15630Sstevel@tonic-gate if(subtree == NULL)
15640Sstevel@tonic-gate {
15650Sstevel@tonic-gate error("BUG: session_read(): subtree is NULL");
15660Sstevel@tonic-gate snmp_pdu_free(response);
15670Sstevel@tonic-gate return;
15680Sstevel@tonic-gate }
15690Sstevel@tonic-gate
15700Sstevel@tonic-gate if (subtree->agent->numOfFailRequest > 0)
15710Sstevel@tonic-gate trace("Agent %s is now OK", subtree->agent->name) ;
15720Sstevel@tonic-gate subtree->agent->numOfFailRequest=0;
15730Sstevel@tonic-gate
15740Sstevel@tonic-gate if(pdu->type == GETNEXT_REQ_MSG)
15750Sstevel@tonic-gate {
15760Sstevel@tonic-gate if( (response->error_status == SNMP_ERR_NOSUCHNAME)
15770Sstevel@tonic-gate && (response->error_index == 1)
15780Sstevel@tonic-gate && (response->first_variable != NULL) )
15790Sstevel@tonic-gate {
15800Sstevel@tonic-gate if(trace_level > 0)
15810Sstevel@tonic-gate {
15820Sstevel@tonic-gate trace("!! session %d - request %d: the Get-Next returned No Such Name\n\n",
15830Sstevel@tonic-gate session->session_id,
15840Sstevel@tonic-gate request->request_id);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate /* Check if another agent supports some */
15880Sstevel@tonic-gate /* variables greater than the first one */
15890Sstevel@tonic-gate /* of the PDU */
15900Sstevel@tonic-gate
15910Sstevel@tonic-gate for(sub = subtree->next_subtree; sub; sub = sub->next_subtree)
15920Sstevel@tonic-gate {
15930Sstevel@tonic-gate /* skip invalid subtree (vsb) */
15940Sstevel@tonic-gate if(subtree_is_valid(sub)==FALSE) continue;
15950Sstevel@tonic-gate if(!is_in_agent_list(request->visited_agent_list, sub->agent))
15960Sstevel@tonic-gate {
15970Sstevel@tonic-gate session_move_request(request, sub);
15980Sstevel@tonic-gate snmp_pdu_free(response);
15990Sstevel@tonic-gate return;
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate }
16020Sstevel@tonic-gate }
16030Sstevel@tonic-gate else
16040Sstevel@tonic-gate if( (response->first_variable != NULL)
16050Sstevel@tonic-gate /*&& ((sub = forward_subtree_match(subtree, &(response->first_variable->name))) != NULL)*/
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate && ((sub = subtree_match(GET_REQ_MSG, &(response->first_variable->name))) != NULL)
16080Sstevel@tonic-gate
16090Sstevel@tonic-gate && (sub != subtree)
16100Sstevel@tonic-gate && (SSAOidCmp(&(subtree->name),&(sub->name)) < 0)
16110Sstevel@tonic-gate /*
16120Sstevel@tonic-gate &&(sub->agent!=NULL && subtree->agent!=NULL && sub->agent!=subtree->agent)
16130Sstevel@tonic-gate */
16140Sstevel@tonic-gate )
16150Sstevel@tonic-gate {
16160Sstevel@tonic-gate /* we are in another subtree */
16170Sstevel@tonic-gate
16180Sstevel@tonic-gate Subtree *s;
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate
16210Sstevel@tonic-gate if(trace_level > 0)
16220Sstevel@tonic-gate {
16230Sstevel@tonic-gate trace("!! session %d - request %d: the Get-Next issued in the subtree %s supported by %s",
16240Sstevel@tonic-gate session->session_id,
16250Sstevel@tonic-gate request->request_id,
16260Sstevel@tonic-gate SSAOidString(&(subtree->name)),
16270Sstevel@tonic-gate subtree->agent->name);
16280Sstevel@tonic-gate trace(" returned a response in the subtree %s supported by %s\n\n",
16290Sstevel@tonic-gate SSAOidString(&(sub->name)),
16300Sstevel@tonic-gate sub->agent->name);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate /* Is there a subtree supported by another agent between */
16350Sstevel@tonic-gate /* subtree and sub ? */
16360Sstevel@tonic-gate
16370Sstevel@tonic-gate /* 12-19-96 snmpgetnext
16380Sstevel@tonic-gate for(s = subtree->next_subtree; s; s = s->next_subtree)
16390Sstevel@tonic-gate {
16400Sstevel@tonic-gate if(subtree_is_valid(s)==FALSE) continue;
16410Sstevel@tonic-gate if(s == sub)
16420Sstevel@tonic-gate {
16430Sstevel@tonic-gate break;
16440Sstevel@tonic-gate }
16450Sstevel@tonic-gate */
16460Sstevel@tonic-gate s = sub;
16470Sstevel@tonic-gate
16480Sstevel@tonic-gate if(subtree->agent != s->agent)
16490Sstevel@tonic-gate {
16500Sstevel@tonic-gate /* There is a subtree supported by another agent */
16510Sstevel@tonic-gate /* between subtree and sub */
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate session_move_request(request, s);
16540Sstevel@tonic-gate snmp_pdu_free(response);
16550Sstevel@tonic-gate return;
16560Sstevel@tonic-gate }
16570Sstevel@tonic-gate /*
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate */
16600Sstevel@tonic-gate }
16610Sstevel@tonic-gate }
16620Sstevel@tonic-gate
16630Sstevel@tonic-gate
16640Sstevel@tonic-gate /* we consider response a valid response for the request request */
16650Sstevel@tonic-gate if(request->response)
16660Sstevel@tonic-gate {
16670Sstevel@tonic-gate error("BUG: session_read(): request->response is not NULL");
16680Sstevel@tonic-gate }
16690Sstevel@tonic-gate request->response = response;
16700Sstevel@tonic-gate request->state = REQUEST_COMPLETED;
16710Sstevel@tonic-gate session->i_flags = session->i_flags | request->flags;
16720Sstevel@tonic-gate
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate if(doRespondHere && session->i_flags == session->o_flags)
16750Sstevel@tonic-gate {
16760Sstevel@tonic-gate session_respond(session);
16770Sstevel@tonic-gate }
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate return;
16800Sstevel@tonic-gate }
16810Sstevel@tonic-gate
session_read()16820Sstevel@tonic-gate void session_read()
16830Sstevel@tonic-gate {
16840Sstevel@tonic-gate session_process_response(NULL,TRUE);
16850Sstevel@tonic-gate
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate
16880Sstevel@tonic-gate /************************************************************************/
16890Sstevel@tonic-gate
session_select_info(struct timeval * timeout)16900Sstevel@tonic-gate void session_select_info(struct timeval *timeout)
16910Sstevel@tonic-gate {
16920Sstevel@tonic-gate Session *sp;
16930Sstevel@tonic-gate Request *rp;
16940Sstevel@tonic-gate struct timeval now, earliest;
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate if(first_session == NULL)
16980Sstevel@tonic-gate {
16990Sstevel@tonic-gate return;
17000Sstevel@tonic-gate }
17010Sstevel@tonic-gate
17020Sstevel@tonic-gate /* For each request in each session, if it is the */
17030Sstevel@tonic-gate /* earliest timeout to expire, mark it as lowest. */
17040Sstevel@tonic-gate
17050Sstevel@tonic-gate timerclear(&earliest);
17060Sstevel@tonic-gate for(sp = first_session; sp; sp = sp->next_session)
17070Sstevel@tonic-gate {
17080Sstevel@tonic-gate for(rp = sp->first_request; rp; rp = rp->next_request)
17090Sstevel@tonic-gate {
17100Sstevel@tonic-gate if(rp->state == REQUEST_COMPLETED)
17110Sstevel@tonic-gate {
17120Sstevel@tonic-gate continue;
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate
17150Sstevel@tonic-gate if(!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <))
17160Sstevel@tonic-gate {
17170Sstevel@tonic-gate earliest = rp->expire;
17180Sstevel@tonic-gate }
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate }
17210Sstevel@tonic-gate
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate /* Now find out how much time until the earliest timeout. This */
17240Sstevel@tonic-gate /* transforms earliest from an absolute time into a delta time, the */
17250Sstevel@tonic-gate /* time left until the select should timeout. */
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate gettimeofday(&now, (struct timezone *)0);
17280Sstevel@tonic-gate earliest.tv_sec--; /* adjust time to make arithmetic easier */
17290Sstevel@tonic-gate earliest.tv_usec += 1000000L;
17300Sstevel@tonic-gate earliest.tv_sec -= now.tv_sec;
17310Sstevel@tonic-gate earliest.tv_usec -= now.tv_usec;
17320Sstevel@tonic-gate while (earliest.tv_usec >= 1000000L)
17330Sstevel@tonic-gate {
17340Sstevel@tonic-gate earliest.tv_usec -= 1000000L;
17350Sstevel@tonic-gate earliest.tv_sec += 1;
17360Sstevel@tonic-gate }
17370Sstevel@tonic-gate if(earliest.tv_sec < 0)
17380Sstevel@tonic-gate {
17390Sstevel@tonic-gate earliest.tv_sec = 0;
17400Sstevel@tonic-gate earliest.tv_usec = 0;
17410Sstevel@tonic-gate }
17420Sstevel@tonic-gate
17430Sstevel@tonic-gate /* if our delta time is less, reset timeout */
17440Sstevel@tonic-gate if(timercmp(&earliest, timeout, <))
17450Sstevel@tonic-gate {
17460Sstevel@tonic-gate *timeout = earliest;
17470Sstevel@tonic-gate }
17480Sstevel@tonic-gate
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate return;
17510Sstevel@tonic-gate }
17520Sstevel@tonic-gate
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate /************************************************************************/
17550Sstevel@tonic-gate
session_timeout()17560Sstevel@tonic-gate void session_timeout()
17570Sstevel@tonic-gate {
17580Sstevel@tonic-gate struct timeval now;
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate
17610Sstevel@tonic-gate gettimeofday(&now, (struct timezone *)0);
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate while(session_timeout_loop(&now) == 1);
17640Sstevel@tonic-gate destroy_hanging_agent(); /* destroy one agent at a time */
17650Sstevel@tonic-gate
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate /************************************************************************/
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate int max_requests = 1000;
17720Sstevel@tonic-gate
session_timeout_loop(struct timeval * now)17730Sstevel@tonic-gate static int session_timeout_loop(struct timeval *now)
17740Sstevel@tonic-gate {
17750Sstevel@tonic-gate Session *sp;
17760Sstevel@tonic-gate Request *rp;
17770Sstevel@tonic-gate int nrequests = 0;
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate /* For each session outstanding, check to see if the timeout has expired. */
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate for(sp = first_session; sp; sp = sp->next_session)
17830Sstevel@tonic-gate {
17840Sstevel@tonic-gate
17850Sstevel@tonic-gate
17860Sstevel@tonic-gate for(rp = sp->first_request; rp; rp = rp->next_request)
17870Sstevel@tonic-gate {
17880Sstevel@tonic-gate nrequests ++;
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate if(rp->state == REQUEST_COMPLETED)
17910Sstevel@tonic-gate {
17920Sstevel@tonic-gate continue;
17930Sstevel@tonic-gate }
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate if(timercmp(&rp->expire, now, <) || nrequests > max_requests)
17960Sstevel@tonic-gate {
17970Sstevel@tonic-gate Subtree *subtree = rp->subtree;
17980Sstevel@tonic-gate
17990Sstevel@tonic-gate
18000Sstevel@tonic-gate if(subtree == NULL)
18010Sstevel@tonic-gate {
18020Sstevel@tonic-gate error("BUG: session_timeout_loop(): subtree is NULL");
18030Sstevel@tonic-gate /* session_respond_error() closes the session */
18040Sstevel@tonic-gate session_respond_error(sp, SNMP_ERR_GENERR, 1);
18050Sstevel@tonic-gate return 1;
18060Sstevel@tonic-gate }
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate if (subtree->agent->numOfFailRequest == 0 )
18090Sstevel@tonic-gate trace(ERR_MSG_AGENT_NOT_RESPONDING, subtree->agent->name);
18100Sstevel@tonic-gate subtree->agent->numOfFailRequest++;
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate /* this timer has expired */
18130Sstevel@tonic-gate if(trace_level > 0)
18140Sstevel@tonic-gate {
18150Sstevel@tonic-gate trace("!! session %d - request %d: timeout\n\n",
18160Sstevel@tonic-gate sp->session_id,
18170Sstevel@tonic-gate rp->request_id);
18180Sstevel@tonic-gate }
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate if(sp->pdu->type == GETNEXT_REQ_MSG)
18210Sstevel@tonic-gate {
18220Sstevel@tonic-gate /* Check if there is a subtree supported */
18230Sstevel@tonic-gate /* by another agent after subtree */
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate Subtree *sub;
18260Sstevel@tonic-gate
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate for(sub = subtree->next_subtree; sub; sub = sub->next_subtree)
18290Sstevel@tonic-gate {
18300Sstevel@tonic-gate if(!is_in_agent_list(rp->visited_agent_list, sub->agent))
18310Sstevel@tonic-gate {
18320Sstevel@tonic-gate session_move_request(rp, sub);
18330Sstevel@tonic-gate return 1;
18340Sstevel@tonic-gate }
18350Sstevel@tonic-gate }
18360Sstevel@tonic-gate }
18370Sstevel@tonic-gate
18380Sstevel@tonic-gate
18390Sstevel@tonic-gate /* No Such Name */
18400Sstevel@tonic-gate
18410Sstevel@tonic-gate sp->i_flags = sp->i_flags | rp->flags;
18420Sstevel@tonic-gate rp->state = REQUEST_COMPLETED;
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate if(sp->i_flags == sp->o_flags)
18450Sstevel@tonic-gate {
18460Sstevel@tonic-gate session_respond(sp);
18470Sstevel@tonic-gate return 1;
18480Sstevel@tonic-gate }
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate }
18510Sstevel@tonic-gate }
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate return 0;
18540Sstevel@tonic-gate }
18550Sstevel@tonic-gate
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate /************************************************************************/
18580Sstevel@tonic-gate
request_add_visited_agent(Request * request,Agent * agent)18590Sstevel@tonic-gate static int request_add_visited_agent(Request *request, Agent *agent)
18600Sstevel@tonic-gate {
18610Sstevel@tonic-gate Agent_List *new;
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate
18640Sstevel@tonic-gate if(request == NULL)
18650Sstevel@tonic-gate {
18660Sstevel@tonic-gate error("BUG: request_add_visited_agent(): request is NULL");
18670Sstevel@tonic-gate return -1;
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate if(agent == NULL)
18710Sstevel@tonic-gate {
18720Sstevel@tonic-gate error("BUG: request_add_visited_agent(): agent is NULL");
18730Sstevel@tonic-gate return -1;
18740Sstevel@tonic-gate }
18750Sstevel@tonic-gate
18760Sstevel@tonic-gate new = (Agent_List *) malloc(sizeof(Agent_List));
18770Sstevel@tonic-gate if(new == NULL)
18780Sstevel@tonic-gate {
18790Sstevel@tonic-gate error("malloc() failed");
18800Sstevel@tonic-gate return -1;
18810Sstevel@tonic-gate }
18820Sstevel@tonic-gate new->next = request->visited_agent_list;
18830Sstevel@tonic-gate request->visited_agent_list = new;
18840Sstevel@tonic-gate new->agent = agent;
18850Sstevel@tonic-gate
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate return 0;
18880Sstevel@tonic-gate }
18890Sstevel@tonic-gate
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate /************************************************************************/
18920Sstevel@tonic-gate
agent_list_free(Agent_List * alp)18930Sstevel@tonic-gate static void agent_list_free(Agent_List *alp)
18940Sstevel@tonic-gate {
18950Sstevel@tonic-gate Agent_List *next;
18960Sstevel@tonic-gate
18970Sstevel@tonic-gate
18980Sstevel@tonic-gate while(alp)
18990Sstevel@tonic-gate {
19000Sstevel@tonic-gate next = alp->next;
19010Sstevel@tonic-gate free(alp);
19020Sstevel@tonic-gate alp = next;
19030Sstevel@tonic-gate }
19040Sstevel@tonic-gate }
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate /************************************************************************/
19080Sstevel@tonic-gate
is_in_agent_list(Agent_List * agent_list,Agent * agent)19090Sstevel@tonic-gate static int is_in_agent_list(Agent_List *agent_list, Agent *agent)
19100Sstevel@tonic-gate {
19110Sstevel@tonic-gate Agent_List *alp;
19120Sstevel@tonic-gate
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate for(alp = agent_list; alp; alp = alp->next)
19150Sstevel@tonic-gate {
19160Sstevel@tonic-gate if(alp->agent == agent)
19170Sstevel@tonic-gate {
19180Sstevel@tonic-gate return True;
19190Sstevel@tonic-gate }
19200Sstevel@tonic-gate }
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate return False;
19230Sstevel@tonic-gate }
19240Sstevel@tonic-gate
no_outstanding_session_for_the_agent(Agent * ap)19250Sstevel@tonic-gate int no_outstanding_session_for_the_agent(Agent* ap)
19260Sstevel@tonic-gate {
19270Sstevel@tonic-gate Session *sp;
19280Sstevel@tonic-gate Request *rp;
19290Sstevel@tonic-gate
19300Sstevel@tonic-gate for(sp = first_session; sp; sp = sp->next_session){
19310Sstevel@tonic-gate for(rp = sp->first_request; rp; rp = rp->next_request){
19320Sstevel@tonic-gate if(rp->subtree && rp->subtree->agent==ap)
19330Sstevel@tonic-gate return 0;
19340Sstevel@tonic-gate }
19350Sstevel@tonic-gate }
19360Sstevel@tonic-gate
19370Sstevel@tonic-gate return 1;
19380Sstevel@tonic-gate }
19390Sstevel@tonic-gate
19400Sstevel@tonic-gate
community_check(Address * address,Agent * agent,int pdu_type,char * community)19410Sstevel@tonic-gate static int community_check (Address * address, Agent * agent, int pdu_type, char * community)
19420Sstevel@tonic-gate {
19430Sstevel@tonic-gate Manager *mgr;
19440Sstevel@tonic-gate int ret;
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate
19470Sstevel@tonic-gate if (agent == NULL) {
19480Sstevel@tonic-gate return TRUE;
19490Sstevel@tonic-gate }
19500Sstevel@tonic-gate if (agent->first_manager == NULL) {
19510Sstevel@tonic-gate return TRUE;
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate /* check host */
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate mgr = is_valid_manager(address, &mgr);
19560Sstevel@tonic-gate
19570Sstevel@tonic-gate if(mgr == NULL)
19580Sstevel@tonic-gate {
19590Sstevel@tonic-gate error("community_check(): unauthorized manager (%s)",
19600Sstevel@tonic-gate ip_address_string(&(address->sin_addr)));
19610Sstevel@tonic-gate return FALSE;
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate if (is_valid_community(community, pdu_type, mgr))
19650Sstevel@tonic-gate return TRUE;
19660Sstevel@tonic-gate else {
19670Sstevel@tonic-gate error("community_check() : bad community from %s",
19680Sstevel@tonic-gate ip_address_string(&(address->sin_addr)));
19690Sstevel@tonic-gate return FALSE;
19700Sstevel@tonic-gate }
19710Sstevel@tonic-gate }
1972