xref: /onnv-gate/usr/src/cmd/agents/snmp/snmprelayd/session.c (revision 3820:8adf9090a487)
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