xref: /onnv-gate/usr/src/cmd/agents/snmp/snmprelayd/agent.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  *
22*0Sstevel@tonic-gate  * Copyright 1997 Sun Microsystems, Inc.  All Rights Reserved.
23*0Sstevel@tonic-gate  * Use is subject to license terms.
24*0Sstevel@tonic-gate  */
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #include <stdlib.h>
29*0Sstevel@tonic-gate #include <stdio.h>
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <sys/socket.h>
32*0Sstevel@tonic-gate #include <netinet/in.h>
33*0Sstevel@tonic-gate #include <arpa/inet.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include "impl.h"
36*0Sstevel@tonic-gate #include "error.h"
37*0Sstevel@tonic-gate #include "trace.h"
38*0Sstevel@tonic-gate #include "pdu.h"
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include "access.h"
41*0Sstevel@tonic-gate #include "agent.h"
42*0Sstevel@tonic-gate #include "subtree.h"
43*0Sstevel@tonic-gate #include "session.h"
44*0Sstevel@tonic-gate #include "sh_table.h"
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate /***** STATIC VARIABLES *****/
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate int sap_agent_id = 1;
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate /* the agent list */
52*0Sstevel@tonic-gate Agent *first_agent = NULL;
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate /****************************************************************/
56*0Sstevel@tonic-gate 
trace_agents()57*0Sstevel@tonic-gate void trace_agents()
58*0Sstevel@tonic-gate {
59*0Sstevel@tonic-gate 	Agent *ap;
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	trace("AGENTS:\n");
63*0Sstevel@tonic-gate 	for(ap = first_agent; ap; ap = ap->next_agent)
64*0Sstevel@tonic-gate 	{
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate                 trace("\t%X %-30s %-30s %8d %8d %8d %8d %X\n",
67*0Sstevel@tonic-gate 			ap,
68*0Sstevel@tonic-gate                         ap->name?ap->name:"NO NAME",
69*0Sstevel@tonic-gate                         address_string(&(ap->address)),
70*0Sstevel@tonic-gate                         ap->timeout,ap->agentID,ap->agentStatus,
71*0Sstevel@tonic-gate                         ap->agentProcessID,
72*0Sstevel@tonic-gate 			ap->first_manager);
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 	}
75*0Sstevel@tonic-gate 	trace("\n");
76*0Sstevel@tonic-gate }
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate /****************************************************************/
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate /* We must invoke subtree_list_delete() before invoking	*/
82*0Sstevel@tonic-gate /* this function because the first_agent_subtree member	*/
83*0Sstevel@tonic-gate /* of the agent structures should be NULL		*/
84*0Sstevel@tonic-gate 
agent_list_delete()85*0Sstevel@tonic-gate void agent_list_delete()
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	Agent *ap = first_agent;
88*0Sstevel@tonic-gate 	Agent *next;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 	while(ap)
92*0Sstevel@tonic-gate 	{
93*0Sstevel@tonic-gate 		next = ap->next_agent;
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 		agent_free(ap);
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 		ap = next;
98*0Sstevel@tonic-gate 	}
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	first_agent = NULL;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	return;
103*0Sstevel@tonic-gate }
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate /****************************************************************/
107*0Sstevel@tonic-gate 
free_string_content(String str)108*0Sstevel@tonic-gate static void free_string_content(String str)
109*0Sstevel@tonic-gate {
110*0Sstevel@tonic-gate   if(str.chars != NULL && str.len != 0){
111*0Sstevel@tonic-gate 	free(str.chars);
112*0Sstevel@tonic-gate 	str.chars = NULL;
113*0Sstevel@tonic-gate 	str.len = 0;
114*0Sstevel@tonic-gate   }
115*0Sstevel@tonic-gate }
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /* The fisrt_agent_subtree member of the agent		*/
118*0Sstevel@tonic-gate /* structure should be NULL				*/
119*0Sstevel@tonic-gate 
agent_free(Agent * ap)120*0Sstevel@tonic-gate void agent_free(Agent *ap)
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	if(ap == NULL)
123*0Sstevel@tonic-gate 	{
124*0Sstevel@tonic-gate 		return;
125*0Sstevel@tonic-gate 	}
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	if(ap->first_agent_subtree)
128*0Sstevel@tonic-gate 	{
129*0Sstevel@tonic-gate 		error("BUG: agent_free(): first_agent_subtree not NULL");
130*0Sstevel@tonic-gate 	}
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	/* free the extra element */
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	free_string_content(ap->agentPersonalFile);
135*0Sstevel@tonic-gate 	free_string_content(ap->agentConfigFile);
136*0Sstevel@tonic-gate 	free_string_content(ap->agentExecutable);
137*0Sstevel@tonic-gate 	free_string_content(ap->agentVersionNum);
138*0Sstevel@tonic-gate 	free_string_content(ap->agentProtocol);
139*0Sstevel@tonic-gate 	free_string_content(ap->agentName);
140*0Sstevel@tonic-gate 	if(ap->name) free(ap->name);
141*0Sstevel@tonic-gate 	free(ap);
142*0Sstevel@tonic-gate 	ap =NULL;
143*0Sstevel@tonic-gate 	return;
144*0Sstevel@tonic-gate }
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate /****************************************************************/
agent_find_by_id(int id)147*0Sstevel@tonic-gate Agent *agent_find_by_id(int id)
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate 	Agent *ap;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	for(ap = first_agent; ap; ap = ap->next_agent)
153*0Sstevel@tonic-gate 	{
154*0Sstevel@tonic-gate 		if(ap->agentID == id)
155*0Sstevel@tonic-gate 		{
156*0Sstevel@tonic-gate 			return ap;
157*0Sstevel@tonic-gate 		}
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	return NULL;
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 
agent_find_by_name(char * name)164*0Sstevel@tonic-gate Agent *agent_find_by_name(char* name)
165*0Sstevel@tonic-gate {
166*0Sstevel@tonic-gate 	Agent *ap;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	for(ap = first_agent; ap; ap = ap->next_agent)
170*0Sstevel@tonic-gate 	{
171*0Sstevel@tonic-gate 		if(!strcmp(ap->name,name))
172*0Sstevel@tonic-gate 		{
173*0Sstevel@tonic-gate 			return ap;
174*0Sstevel@tonic-gate 		}
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	return NULL;
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate /* agent_find() is used to check if we have not		*/
181*0Sstevel@tonic-gate /* two SNMP agents registered on the same UDP port	*/
182*0Sstevel@tonic-gate 
agent_find(Address * address)183*0Sstevel@tonic-gate Agent *agent_find(Address *address)
184*0Sstevel@tonic-gate {
185*0Sstevel@tonic-gate 	Agent *ap;
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	for(ap = first_agent; ap; ap = ap->next_agent)
189*0Sstevel@tonic-gate 	{
190*0Sstevel@tonic-gate 		if(ap->address.sin_port == address->sin_port)
191*0Sstevel@tonic-gate 		{
192*0Sstevel@tonic-gate 			return ap;
193*0Sstevel@tonic-gate 		}
194*0Sstevel@tonic-gate 	}
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	return NULL;
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate 
agent_update_subtree(Agent * agent)199*0Sstevel@tonic-gate void agent_update_subtree(Agent* agent)
200*0Sstevel@tonic-gate {
201*0Sstevel@tonic-gate   Subtree *sp;
202*0Sstevel@tonic-gate   if(agent == NULL) return ;
203*0Sstevel@tonic-gate   sp = agent->first_agent_subtree;
204*0Sstevel@tonic-gate   for(;sp;sp=sp->next_agent_subtree){
205*0Sstevel@tonic-gate 	sp->regTreeStatus = agent->agentStatus;
206*0Sstevel@tonic-gate   }
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate 
agent_detach_from_list(Agent * agent)209*0Sstevel@tonic-gate void agent_detach_from_list(Agent* agent)
210*0Sstevel@tonic-gate {
211*0Sstevel@tonic-gate 	Agent *ap, *last=NULL;
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate         if(agent == NULL) return;
214*0Sstevel@tonic-gate 	for(ap = first_agent; ap ; ap = ap->next_agent)
215*0Sstevel@tonic-gate 	{
216*0Sstevel@tonic-gate 		if(ap == agent)
217*0Sstevel@tonic-gate 			break;
218*0Sstevel@tonic-gate 		last = ap;
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate 	if(ap==NULL) return;
221*0Sstevel@tonic-gate 	if(last == NULL){
222*0Sstevel@tonic-gate 		first_agent = ap->next_agent;
223*0Sstevel@tonic-gate 	}else{
224*0Sstevel@tonic-gate 		last->next_agent = ap->next_agent;
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	ap->next_agent = NULL;
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 
agent_destroy(Agent * agent)230*0Sstevel@tonic-gate void agent_destroy(Agent* agent)
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate   if(agent!=NULL){
233*0Sstevel@tonic-gate 	if(agent->agentID==sap_agent_id-1)
234*0Sstevel@tonic-gate 		sap_agent_id--;
235*0Sstevel@tonic-gate   }
236*0Sstevel@tonic-gate   agent_detach_from_list(agent);
237*0Sstevel@tonic-gate   agent_manager_list_free(agent->first_manager);
238*0Sstevel@tonic-gate   delete_all_table_from_agent(agent);
239*0Sstevel@tonic-gate   delete_all_subtree_from_agent(agent);
240*0Sstevel@tonic-gate   delete_agent_from_resource_list(agent);
241*0Sstevel@tonic-gate   agent_free(agent);
242*0Sstevel@tonic-gate }
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate /*
245*0Sstevel@tonic-gate ** Maximum number of consecutive timeouts before snmpdx will purge the
246*0Sstevel@tonic-gate ** subagent from the internal tables.
247*0Sstevel@tonic-gate */
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate static	int MaxFails	= 5 ;
250*0Sstevel@tonic-gate 
SetFailThreshold(int v)251*0Sstevel@tonic-gate int	SetFailThreshold ( int v )
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate 	MaxFails = v ;
254*0Sstevel@tonic-gate 	return 0 ;
255*0Sstevel@tonic-gate }
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate /****************************************************************/
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate /* destroy hanging agent when no outstanding session which
262*0Sstevel@tonic-gate    relates to the agent */
destroy_hanging_agent()263*0Sstevel@tonic-gate void destroy_hanging_agent()
264*0Sstevel@tonic-gate {
265*0Sstevel@tonic-gate 	Agent *ap;
266*0Sstevel@tonic-gate 	int rslt ;
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	for (ap = first_agent; ap ; ap = ap->next_agent) {
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 		if (ap->numOfFailRequest <= 5)
271*0Sstevel@tonic-gate 			continue ;
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 		/* Even if the subagent isn't responding, we need to let the
274*0Sstevel@tonic-gate 		** sessions timeout and rip-down thru the normal mechanism.
275*0Sstevel@tonic-gate 		*/
276*0Sstevel@tonic-gate 		if (!no_outstanding_session_for_the_agent (ap))
277*0Sstevel@tonic-gate 			continue ;
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 		/* subagent is quiesced and not talking -- check proces */
280*0Sstevel@tonic-gate 		if ( ap->agentProcessID != 0 && kill (ap->agentProcessID, 0) < 0) {
281*0Sstevel@tonic-gate 			error ("Subagent died: %s PID=%d -- deleted from the agent table",
282*0Sstevel@tonic-gate 				ap->name, ap->agentProcessID ) ;
283*0Sstevel@tonic-gate 			agent_destroy (ap) ;
284*0Sstevel@tonic-gate 			return ; 		/* only kill one at a time */
285*0Sstevel@tonic-gate 		}
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 		/* subagent appears to be alive but hung and not responding */
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 		if (MaxFails <= 0 || ap->numOfFailRequest < MaxFails)
290*0Sstevel@tonic-gate 			continue ;
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 		/* If the subagent receives a request with a bad community string
293*0Sstevel@tonic-gate 		// it is obliged to discard the string and _not_ respond.  This
294*0Sstevel@tonic-gate 		// doesn't jive with our stateful relay model.  We timeout and
295*0Sstevel@tonic-gate 		// can't distinguish a hung agent from an agent that is dropping
296*0Sstevel@tonic-gate 		// packets because of the "bad" community strings.  Thus, before
297*0Sstevel@tonic-gate 		// putting the ax to an agent we see if it's still alive.
298*0Sstevel@tonic-gate 		//
299*0Sstevel@tonic-gate 		// The ssa_subagent_is_alive() routine "pings" the subagent with
300*0Sstevel@tonic-gate 		// a valid but innocuous request packet.  Unfortunately the dummy
301*0Sstevel@tonic-gate 		// we build has the community string set to "public".  If the subagent
302*0Sstevel@tonic-gate 		// doesn't accept "public" requests it will ignore our ping attempt.
303*0Sstevel@tonic-gate 		//
304*0Sstevel@tonic-gate 		// Sunil indicated that snmpdx would pre-validate incoming community
305*0Sstevel@tonic-gate 		// strings and only pass requests that would be accepted by the subagent.
306*0Sstevel@tonic-gate 		// This doesn't appear to work as advertised.
307*0Sstevel@tonic-gate 	 	*/
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 		if (ssa_subagent_is_alive (ap)) {
310*0Sstevel@tonic-gate 			error ("Agent %s appeared dead but responded to ping", ap->name) ;
311*0Sstevel@tonic-gate 			ap->numOfFailRequest = 0 ;
312*0Sstevel@tonic-gate 			continue ;
313*0Sstevel@tonic-gate 		}
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 		error ("Agent not responding: %s -- deleted from the agent table", ap->name ) ;
316*0Sstevel@tonic-gate 		agent_destroy(ap);
317*0Sstevel@tonic-gate 		return;
318*0Sstevel@tonic-gate 	}
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate 
321