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