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