xref: /onnv-gate/usr/src/cmd/agents/snmp/snmprelayd/res.c (revision 1706:0e053bac3f94)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <sys/stat.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/times.h>
34 #include <unistd.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <pwd.h>
39 #include <errno.h>
40 
41 #include "impl.h"
42 #include "error.h"
43 #include "trace.h"
44 #include "pdu.h"
45 
46 #include "agent.h"
47 #include "subtree.h"
48 #include "session.h"
49 #include "res.h"
50 #include "dispatcher.h"
51 #include "snmprelay_msg.h"
52 #include <pwd.h>
53 
54 SapResource *first_res = NULL;
55 SapResource *reconfig_first_res = NULL;
56 
57 #define MAX_RES_NAME 128
58 #define CLOCK_TICK 100
59 
60 typedef struct _PidRec {
61 	struct _PidRec *next_pid;
62 	char res_name[MAX_RES_NAME];
63 	char agent_name[MAX_RES_NAME];
64 	int pid;
65 	int port;
66 } PidRec;
67 
68 PidRec *first_pid = NULL;
69 
70 
71 /****************************************************************/
72 
mark_all_resources_not_visit()73 void mark_all_resources_not_visit()
74 {
75   SapResource *ap;
76   for(ap=first_res; ap; ap=ap->next_res)
77 	ap->mark = RES_NOT_VISIT;
78 }
79 
80 
trace_resources()81 void trace_resources()
82 {
83 	SapResource *ap;
84 
85 
86 	trace("RESOURCES:\n");
87 	for(ap = first_res; ap; ap = ap->next_res)
88 	{
89 
90                 trace("\t%Name: %s Dir: %s Personal: %s Sec: %s Policy: %s Type: %s Cmd: %s Agent: %s\n",
91                         ap->res_name?ap->res_name:"NO NAME",
92 			ap->dir_file?ap->dir_file:"",
93 			ap->personal_file?ap->personal_file:"",
94 			ap->sec_file?ap->sec_file:"",
95 			ap->policy?ap->policy:"",
96 			ap->type?ap->type:"",
97 			ap->start_cmd?ap->start_cmd:"",
98                         ap->agent?(ap->agent->name?ap->agent->name:""):"");
99 
100 	}
101 	trace("\n");
102 }
103 
resource_detach(SapResource * tgt)104 void resource_detach(SapResource *tgt)
105 {
106   SapResource *sp, *last=NULL;
107 
108         if(tgt == NULL) return;
109         for(sp = first_res; sp; sp = sp->next_res)
110         {
111                 if(sp == tgt)
112                 {
113                         break;
114                 }
115 
116                 last = sp;
117         }
118 	if(sp==NULL) return;
119 
120         if(last == NULL)
121         {
122                 first_res = tgt->next_res;
123                 tgt->next_res = NULL;
124         }
125         else
126         {
127                 last->next_res = tgt->next_res;
128                 tgt->next_res = NULL;
129         }
130 
131 }
132 
133 
134 
135 /****************************************************************/
136 
137 /* We must invoke subtree_list_delete() before invoking	*/
138 /* this function because the first_agent_subtree member	*/
139 /* of the agent structures should be NULL		*/
140 
resource_list_delete()141 void resource_list_delete()
142 {
143 	SapResource *ap = first_res;
144 	SapResource *next;
145 
146 
147 	while(ap)
148 	{
149 		next = ap->next_res;
150 
151 		if(ap->agent)
152 		  agent_destroy(ap->agent);
153 
154 		resource_free(ap);
155 
156 		ap = next;
157 	}
158 
159 	first_res = NULL;
160 
161 	return;
162 }
163 
164 
165 /****************************************************************/
166 
167 
resource_free(SapResource * ap)168 void resource_free(SapResource *ap)
169 {
170 	if(ap == NULL)
171 	{
172 		return;
173 	}
174 
175 	/* free the extra element */
176 
177         if(ap->res_name) free(ap->res_name);
178 	if(ap->dir_file) free(ap->dir_file);
179 	if(ap->personal_file) free(ap->personal_file);
180 	if(ap->sec_file) free(ap->sec_file);
181 	if(ap->policy) free(ap->policy);
182 	if(ap->type) free(ap->type);
183 	if(ap->start_cmd) free(ap->start_cmd);
184 
185 	free(ap);
186 
187 	return;
188 }
189 
resource_find_by_agent(Agent * agent)190 SapResource *resource_find_by_agent(Agent* agent)
191 {
192   SapResource *ap;
193 
194   if(agent == NULL) return NULL;
195   for(ap=first_res;ap;ap=ap->next_res){
196 	if(ap->agent == agent) return ap;
197   }
198   return NULL;
199 }
200 
resource_find_by_name(char * name)201 SapResource *resource_find_by_name(char* name)
202 {
203   SapResource *ap;
204   if(name == NULL) return NULL;
205   for(ap=first_res;ap;ap=ap->next_res){
206 	if(ap->res_name!=NULL &&
207 	   !strcmp(ap->res_name,name)) return ap;
208   }
209   return NULL;
210 }
211 
resource_find(SapResource * sp)212 SapResource *resource_find(SapResource *sp)
213 {
214   SapResource *ap;
215 
216   if(sp == NULL) return NULL;
217   for(ap=first_res;ap;ap=ap->next_res){
218 	if(resource_cmp(ap,sp)==TRUE) return ap;
219   }
220   return NULL;
221 }
222 
expand_file_name(char * dir_name,char * file_name)223 static char* expand_file_name(char *dir_name,char* file_name)
224 {
225   static char fullname[256];
226   static char dirname[256];
227 
228   fullname[0]='\0';
229   dirname[0]='\0';
230   if(file_name!=NULL){
231 	if(dir_name!=NULL)
232 	  sprintf(dirname,"%s/",dir_name);
233 	sprintf(fullname,"%s%s",dirname,file_name);
234   }
235   return(fullname);
236 }
237 
238 /* if two string are NULL, we treat them as equal */
239 /* equal return 0, otherwise 1 */
string_cmp(char * s1,char * s2)240 static int string_cmp(char *s1, char *s2)
241 {
242   if( (s1 == NULL && s2 != NULL) ||
243       (s1 != NULL && s2 == NULL) ||
244       (s1 != NULL && s2 != NULL
245        && strcmp(s1,s2) ) ) return 1;
246   return 0;
247 }
248 
249 /* return TRUE same, otherwise FALSE */
250 /* s1 is the new one, s2 is old one */
resource_cmp(SapResource * s1,SapResource * s2)251 int resource_cmp(SapResource *s1, SapResource *s2)
252 {
253   char fullname1[256], *name1;
254   char fullname2[256], *name2;
255   time_t filetime;
256 
257   if(s1 == NULL || s2 == NULL) return FALSE;
258 
259   /* res_name may be nil */
260   if(s1->res_name != NULL && s2->res_name != NULL &&
261      strcmp(s1->res_name, s2->res_name))  return FALSE;
262 
263   if(string_cmp(s1->policy,s2->policy) ||
264      string_cmp(s1->start_cmd,s2->start_cmd) ||
265      string_cmp(s1->type,s2->type)) return FALSE;
266 
267   name1 = expand_file_name(s1->dir_file,s1->personal_file);
268   strcpy(fullname1,name1);
269   name2 = expand_file_name(s2->dir_file,s2->personal_file);
270   strcpy(fullname2,name2);
271 
272   if(strcmp(fullname1,fullname2)) return FALSE;
273 
274   /* check the time stamp of the personal file */
275   if(fullname1!=NULL)
276     get_file_modify_time(fullname1,&filetime);
277 
278   /* hack, somehow didnt't initialize */
279   if(fullname2!=NULL && s2->personal_file_time==0)
280     get_file_modify_time(fullname2,&(s2->personal_file_time));
281 
282   if(filetime > s2->personal_file_time) return FALSE;
283 
284   return TRUE;
285 
286   /* same in name, personal_file, policy, start_cmd, type */
287 }
288 
get_file_modify_time(char * filename,time_t * file_time)289 void get_file_modify_time(char* filename,time_t *file_time)
290 {
291   struct stat statb;
292   int fd;
293 
294   *file_time = 0;
295   if((fd = open(filename, O_RDONLY)) < 0)
296   {
297         error(ERR_MSG_OPEN, filename, errno_string());
298         return;
299   }
300 
301   /*
302    * get the size of the file
303    */
304   if(fstat(fd, &statb) < 0)
305   {
306         error(ERR_MSG_FSTAT, filename, errno_string());
307 	close(fd);
308         return;
309    }
310 
311    /* file time stamp */
312    if(file_time) *file_time = statb.st_mtime;
313    close(fd);
314 }
315 
316 
317 
318 
319 /****************************************************************/
resource_handle_child_signal()320 void resource_handle_child_signal()
321 {
322 }
323 
switch_to_user_id(char * user_name)324 int switch_to_user_id(char *user_name)
325 {
326   struct passwd *sp;
327 
328   if(user_name == NULL) return (FALSE);
329   sp = getpwnam(user_name);
330   if(sp != NULL && sp->pw_uid != 0){
331 	setgid(sp->pw_gid);
332 	setuid(sp->pw_uid);
333 	return TRUE;
334   }else{
335  	return FALSE;
336   }
337 }
338 
339 /*
340  * try to get a port, 5 times
341  */
get_a_non_reserved_port()342 static int get_a_non_reserved_port()
343 {
344   struct sockaddr_in me;
345   socklen_t len;
346   int on=1, cnt=0;
347   int sd;
348 
349   sd = socket(AF_INET,SOCK_DGRAM,0);
350   if(sd<0) return 0;
351   me.sin_family = AF_INET;
352   me.sin_addr.s_addr = INADDR_ANY;
353 
354   for(;cnt<5;cnt++){
355     me.sin_port = htons(0);
356     if(bind(sd,(struct sockaddr*)&me,sizeof(me))!=0)continue;
357     len = (socklen_t)sizeof(me);
358     if(getsockname(sd,(struct sockaddr*)&me, &len)==-1) continue;
359     close(sd);
360     return me.sin_port;
361   }
362   close(sd);
363   return 0;
364 }
365 
366 /****************************************************************/
systemUpTime()367 Integer  systemUpTime()
368 {
369   struct tms buffer;
370   return ((Integer)times(&buffer));
371 }
372 
match_pattern_port(char * pat)373 static int match_pattern_port(char* pat)
374 {
375  	if(pat==NULL) return FALSE;
376 	if(pat[0]=='$' && !strcmp(&pat[1],"PORT")) return TRUE;
377 	return FALSE;
378 }
379 
380 
spawn_child(SapResource * res)381 int spawn_child(SapResource *res)
382 {
383   pid_t pid;
384   static char cmd_full_path[256];
385   static char port_str[100];
386   static char sec_str[100];
387   static char per_str[100];
388   char *cmd ;
389   static char *cmd_arg[10];
390   int num_of_args =0;
391   int i, offset, path_len;
392   char *sptr, *eptr, *last_ptr;
393 
394   if(res->agent == NULL || res->agent->agentExecutable.len == 0) return -1;
395   cmd_full_path[0] = '\0';
396   port_str[0]='\0';
397   sec_str[0]='\0';
398   per_str[0]='\0';
399 
400   memcpy(cmd_full_path,res->agent->agentExecutable.chars,
401 	res->agent->agentExecutable.len);
402   cmd_full_path[res->agent->agentExecutable.len] = '\0';
403 
404   memcpy(sec_str,res->agent->agentConfigFile.chars,
405 	res->agent->agentConfigFile.len);
406   sec_str[res->agent->agentConfigFile.len] = '\0';
407 
408   if( (eptr=strchr(cmd_full_path,' ')) != NULL)
409 	path_len = eptr - cmd_full_path;
410   else
411 	path_len = strlen(cmd_full_path);
412 
413   for(i=path_len-1;i>=0 ;i--){
414 	if(cmd_full_path[i] == '/') break;
415   }
416   if(i<0 || i+1>strlen(cmd_full_path)-1) return -1;
417   cmd = &cmd_full_path[i+1];
418 
419   last_ptr = &cmd_full_path[strlen(cmd_full_path)];
420 
421   sprintf(port_str,"%d",res->agent->address.sin_port);
422 
423   if( (pid=fork()) < 0){
424 	exit(1);
425   }else if( pid == 0) {
426 		/* always check for $PORT */
427 		for(eptr=NULL,sptr=cmd;(eptr=strchr(sptr,' '))!=NULL&&sptr<last_ptr;){
428 			*eptr = '\0';
429 			if(match_pattern_port(sptr)==TRUE)
430 				cmd_arg[num_of_args++] = port_str;
431 			else
432 				cmd_arg[num_of_args++] = sptr;
433 			sptr = eptr+1;
434 			if(sptr >= last_ptr) break;
435 		}
436 		if(sptr==cmd){ /* only one argument */
437 			cmd_arg[num_of_args++] = sptr;
438 		}else if(sptr < last_ptr){
439 			/* last argument */
440 			if(match_pattern_port(sptr)==TRUE)
441 				cmd_arg[num_of_args++] = port_str;
442 			else
443 				cmd_arg[num_of_args++] = sptr;
444 		}
445 
446 		if(chdir("/") == -1)
447 		{
448 		  error(ERR_MSG_CHDIR,",",errno_string());
449 		}
450           /*setsid();*/
451 		if(res->user!=NULL)
452 		  if(switch_to_user_id(res->user)==FALSE) exit(1);
453 		execv(cmd_full_path,cmd_arg);
454 		/* if the above function < 0, mark the agent dies */
455 	exit(1);
456   }else{ /* parent */
457   	return pid;
458   }
459   exit(1);
460 }
461 
find_pid_rec_by_res_name(char * name)462 PidRec *find_pid_rec_by_res_name(char *name)
463 {
464   PidRec *ap;
465 
466   for(ap=first_pid; ap; ap=ap->next_pid)
467 	if(!strcmp(ap->res_name,name)) return ap;
468   return NULL;
469 }
470 
res_agent_is_alive(char * res_name)471 int res_agent_is_alive(char *res_name)
472 {
473   /* find the res_name in the pid_list, and send a get pdu to it */
474   PidRec *pp;
475   struct timeval timeout;
476 
477   pp = find_pid_rec_by_res_name(res_name);
478   if(pp==NULL || pp->port<=0) return FALSE;
479 
480   /* assume community string is public,
481    *        agent_address is localhost,
482    *        timeout is 5 sec
483    */
484    timeout.tv_sec = 5;
485    timeout.tv_usec = 0;
486    return(SSAAgentIsAlive(NULL,pp->port,NULL,&timeout));
487 }
488 
489 /******** Resource handling (5-28-96) *********/
490 void
resource_handling(SapResource * rp)491 resource_handling(SapResource *rp)
492 {
493 	/*
494 	*scan the resource list
495 	*if the policy is legacy then
496 	*read the personal file for the subagent.
497 	*spawn the subagent with the given command and the required argument
498 	*/
499 
500 	char fullname[1024];
501 	char dirname[1024];
502 	char buf[1024];
503 	static Agent* prev_agent = NULL;
504 	time_t file_time;
505 	int error_free, port_num;
506 	PidRec *pp;
507 
508 		/* read the config. file */
509 		if (!rp->personal_file) {
510 			error("NULL registration_file for %s", rp->start_cmd);
511 			return;
512 		}
513 		error_free = personal_file_reading(rp->dir_file,
514 			rp->personal_file, &file_time);
515 		rp->personal_file_time = file_time;
516 		/*
517 		* assume that the personal file containing only one
518 		* subagent, then first_agent will point to the previous
519 		* formed subagent
520 		*/
521 	if (first_agent != NULL && first_agent != prev_agent) {
522 		dirname[0] = '\0';
523 		if (rp->dir_file != NULL)
524 			sprintf(dirname, "%s/", rp->dir_file);
525 		first_agent->agentStatus = SSA_OPER_STATUS_LOAD;
526 		rp->agent = first_agent;
527 		prev_agent = first_agent;
528 
529 		/* init the res_name as the agentName */
530 
531 		if (first_agent->agentName.chars != NULL) {
532 			buf[0] = '\0';
533 			memcpy(buf, first_agent->agentName.chars,
534 				first_agent->agentName.len);
535 			buf[first_agent->agentName.len] = '\0';
536 			rp->res_name = strdup(buf);
537 		}
538 
539 		if (rp->personal_file != NULL) {
540 			fullname[0] = '\0';
541 			sprintf(fullname, "%s%s", dirname, rp->personal_file);
542 			(first_agent->agentPersonalFile).chars =
543 				(uchar_t *)strdup(fullname);
544 			(first_agent->agentPersonalFile).len =
545 				strlen(fullname);
546 		}
547 
548 		if (rp->sec_file != NULL) {
549 			fullname[0] = '\0';
550 			sprintf(fullname, "%s%s", dirname, rp->sec_file);
551 			(first_agent->agentConfigFile).chars =
552 				(uchar_t *)strdup(fullname);
553 			(first_agent->agentConfigFile).len =
554 				strlen(fullname);
555 		}
556 
557 		if (rp->start_cmd != NULL) {
558 			fullname[0] = '\0';
559 			sprintf(fullname, "%s%s", dirname, rp->start_cmd);
560 			(first_agent->agentExecutable).chars =
561 				(uchar_t *)strdup(fullname);
562 			(first_agent->agentExecutable).len =
563 				strlen(fullname);
564 		}
565 
566 		if (rp->policy && (strcmp(rp->policy, POLICY_SPAWN) == 0)) {
567 		/*
568 		* check the global flag recovery_on, to decide
569 		* spawn or not, recovery flag should set then reset
570 		*/
571 		if (recovery_on == FALSE || (rp->agent != NULL &&
572 			res_agent_is_alive(rp->res_name) == FALSE)) {
573 			/*
574 			* get the port if not exist
575 			* and store it in rp and agent
576 			*/
577 			if (rp->agent->address.sin_port == 0 ||
578 				rp->agent->agentPortNumber == 0) {
579 				port_num = get_a_non_reserved_port();
580 				rp->agent->agentPortNumber =
581 				rp->agent->address.sin_port = (short)port_num;
582 				if (port_num == 0)
583 				error("can't find a valid port"
584 					"for the agent %s",
585 				(first_agent->name? first_agent->name:""));
586 			}
587 			first_agent ->agentProcessID = spawn_child(rp);
588 			first_agent->agentSystemUpTime = systemUpTime();
589 		} else {
590 			pp = find_pid_rec_by_res_name(rp->res_name);
591 			first_agent->agentProcessID = pp->pid;
592 			if (first_agent->agentPortNumber == 0) {
593 				first_agent->agentPortNumber =
594 				first_agent->address.sin_port = (short)pp->port;
595 			}
596 		}
597 		}
598 
599 		first_agent->agentStatus = SSA_OPER_STATUS_ACTIVE;
600 		/* activate the agent, subtree, table */
601 		sync_subtrees_with_agent(first_agent);
602 		activate_table_for_agent(first_agent);
603 	}
604 
605 	if (first_agent == NULL) {
606 		error_exit("No SNMP agent configured");
607 	}
608 }
609 
ssa_subagent_is_alive(Agent * agent)610 int ssa_subagent_is_alive(Agent *agent)
611 {
612   struct timeval timeout;
613 
614   if(agent==NULL) return FALSE;
615   if(agent->agentPortNumber<0) return FALSE;
616 
617   /*
618    * assume community string is public
619    */
620    timeout.tv_sec = 5;
621    timeout.tv_usec = 0;
622    return(SSAAgentIsAlive(&agent->address.sin_addr,
623 	agent->agentPortNumber,NULL,&timeout));
624 }
625 
trace_pid_rec()626 void trace_pid_rec()
627 {
628 	PidRec *ap;
629 
630 
631 	trace("PID_REC:\n");
632 	for(ap = first_pid; ap; ap = ap->next_pid)
633 	{
634 
635                 trace("\t%ResName: %s AgentName: %s Pid: %d Port: %d\n",
636                         ap->res_name?ap->res_name:"NO-NAME",
637 			ap->agent_name?ap->agent_name:"NO-NAME",
638 			ap->pid,ap->port);
639 
640 	}
641 	trace("\n");
642 }
643 
delete_pid_rec_list()644 void delete_pid_rec_list()
645 {
646 	PidRec *ap = first_pid;
647 	PidRec *next;
648 
649 
650 	while(ap)
651 	{
652 		next = ap->next_pid;
653 
654 		free(ap);
655 
656 		ap = next;
657 	}
658 
659 	first_pid = NULL;
660 }
661 
662 
read_pid_file(char * filename)663 void read_pid_file(char *filename)
664 {
665   PidRec *pid;
666   struct stat statb;
667   FILE *file;
668   int res=4;
669 
670   first_pid = NULL;
671   if((file = fopen(filename, "r")) == NULL)
672   {
673 /* file not exist, ignore it
674         error(ERR_MSG_OPEN, filename, errno_string());
675 */
676 	return;
677   }
678 
679   while(res ==4)
680   {
681   	pid = calloc(1,sizeof(PidRec));
682   	if(pid == NULL){
683 		error("malloc() failed");
684 		fclose(file);
685 		return;
686   	}
687         res =fscanf(file,"%s%s%d%d",
688 	    pid->res_name,pid->agent_name,&(pid->pid),&(pid->port));
689 	if(res==4){
690   	  if(first_pid==NULL){
691 		pid->next_pid = NULL;
692  	   }else{
693 		pid->next_pid = first_pid;
694   	  }
695   	  first_pid = pid;
696 	}else{
697 		free(pid);
698 	}
699   }
700 
701 }
702 
703 
704 void
write_pid_file(char * filename)705 write_pid_file(char *filename)
706 {
707 	char name[256];
708 	FILE *fp;
709 	SapResource *sp1;
710 
711 	umask(S_IWGRP | S_IWOTH);
712 	fp = fopen(filename, "a+");
713 	if (fp == NULL) {
714 		error("can't open the file");
715 		return;
716 	}
717 	/* write the tuple { resouce_name, agent_name, pid, port } */
718 	for (sp1 = first_res; sp1; sp1 = sp1->next_res) {
719 		if (sp1->policy == NULL || strcmp(sp1->policy, POLICY_SPAWN))
720 			continue;
721 		if (sp1->agent == NULL)
722 			continue;
723 		if (sp1->agent->agentName.chars != NULL) {
724 			memcpy(name, sp1->agent->agentName.chars,
725 				sp1->agent->agentName.len);
726 			name[sp1->agent->agentName.len] = '\0';
727 		} else {
728 			strcpy(name, "UNKNOWN");
729 		}
730 		fprintf(fp, "%s %s %d %d\n",
731 			(sp1->res_name != NULL ? sp1->res_name: "UNKNOWN"),
732 			name,
733 			sp1->agent->agentProcessID,
734 			sp1->agent->agentPortNumber);
735 	}
736 fclose(fp);
737 }
738 
739 /*
740  * Add the port number and pid of relay agent to
741  * /var/snmp/snmpdx.st file
742  */
743 void
write_pid_file1(char * filename)744 write_pid_file1(char *filename)
745 {
746 	struct stat buf;
747 	char name[256];
748 	FILE *fp;
749 	Subtree *sp;
750 
751 	sprintf(name, "%s.old", filename);
752 	if (filename == NULL)
753 		return;
754 	if (stat(filename, &buf) == 0) {
755 		if (rename(filename, name) == -1)
756 			error("can't save the pid file");
757 	}
758 
759 	umask(S_IWGRP | S_IWOTH);
760 	fp = fopen(filename, "w");
761 	if (fp == NULL) {
762 		error("can't open the file");
763 		return;
764 	}
765 	for (sp = first_subtree; sp; sp = sp->next_subtree) {
766 		if (sp->agent) {
767 			if (strcmp(sp->agent->name, "relay-agent") == 0) {
768 				fprintf(fp, "%s %s %d %d\n",
769 					sp->agent->name,
770 					sp->agent->name,
771 					sp->agent->agentProcessID,
772 					sp->agent->address.sin_port);
773 			}
774 		}
775 	}
776 fclose(fp);
777 }
778 
merging_resource_list()779 void merging_resource_list()
780 {
781   SapResource* sp, *match_sp, *next;
782   SapResource* merge_res_list=NULL;
783   int port_num;
784 
785   /* scan the reconfig list, find same name resource,
786      if found, see difference, */
787   sp=reconfig_first_res;
788   while(sp){
789     next = sp->next_res;
790     if(sp!=NULL) match_sp = resource_find(sp);
791     if(match_sp != NULL){
792 	/* exists before */
793 	resource_detach(match_sp);
794 	if(resource_cmp(sp,match_sp)==TRUE){
795 	  /* no need to reread the personal file */
796 	  /* spawn process ? */
797 	  resource_free(sp);
798 	  if(match_sp->policy && !strcmp(match_sp->policy,POLICY_SPAWN)){
799 		if(match_sp->agent!=NULL &&
800 		   ssa_subagent_is_alive(match_sp->agent) == FALSE)
801 		{
802 			/* get the port if not exist
803 			 * and store it in rp and agent */
804 		  if(match_sp->agent->address.sin_port == 0 ||
805 		     match_sp->agent->agentPortNumber ==0){
806 			port_num = get_a_non_reserved_port();
807 			match_sp->agent->agentPortNumber =
808 			match_sp->agent->address.sin_port = (short)port_num;
809 		  }
810 	  	  match_sp->agent->agentProcessID = spawn_child(match_sp);
811 		  match_sp->agent->agentSystemUpTime = systemUpTime();
812 		}
813 	  }
814 	  sp=match_sp;
815 	}else{
816 	  /* new info for the agent */
817 	  if(match_sp->agent!=NULL)
818 	  	agent_destroy(match_sp->agent);
819 	   if(match_sp->policy && !strcmp(match_sp->policy,POLICY_SPAWN)){
820 		kill(match_sp->agent->agentProcessID,SIGTERM);
821 	   }
822 	   resource_free(match_sp);
823 	   resource_handling(sp);
824 	}
825     }else{
826 	/* non-exist resource */
827 	resource_handling(sp);
828     }
829     if(merge_res_list==NULL){
830 	sp->next_res = NULL;
831     }else{
832 	sp->next_res = merge_res_list;
833     }
834     merge_res_list = sp;
835 
836     sp=next;
837   }
838 
839   resource_list_delete();
840   first_res = merge_res_list;
841 
842   /* update the PID file */
843 }
844 
delete_agent_from_resource_list(Agent * agent)845 void  delete_agent_from_resource_list(Agent *agent)
846 {
847   SapResource *sp, *last=NULL;
848 
849   if(agent==NULL) return;
850   for(sp=first_res; sp; sp=sp->next_res)
851   {
852 	if(sp->agent == agent) break;
853   	last = sp;
854   }
855   if(sp==NULL) return;
856   if(last==NULL)
857   {
858 	first_res = sp->next_res;
859 	sp->next_res = NULL;
860   }else{
861 	last->next_res = sp->next_res;
862 	sp->next_res = NULL;
863   }
864   resource_free(sp);
865 }
866 
867 
watch_dog_time_is_up(Agent * agent,int elapse_time)868 int watch_dog_time_is_up(Agent *agent,int elapse_time)
869 {
870   if(agent==NULL || agent->agentWatchDogTime==0) return FALSE;
871   if(elapse_time >= agent->agentWatchDogTime) return TRUE;
872   return FALSE;
873 }
874 
875 
876 
watch_dog_in_action()877 void watch_dog_in_action()
878 {
879   SapResource *rp;
880   int port_num;
881   static int start_time=0;
882   static int end_time=0;
883   int time_diff;
884   static struct tms buffer;
885 
886   if(any_outstanding_session()==TRUE) return;
887   end_time = times(&buffer);
888   time_diff = (end_time - start_time)/CLOCK_TICK;
889 
890   for(rp=first_res;rp;rp=rp->next_res){
891 	  if(rp->policy && !strcmp(rp->policy,POLICY_SPAWN)){
892 		if (rp->agent == NULL) {
893 		    if (trace_level > 0)
894 			trace("watch_dog: repopulating agent %s\n", rp->res_name);
895 		    /* the agent was probably deleted by the timeout mechanism */
896 		    resource_handling(rp);
897 		    sync_agent_acl(rp->agent);
898 		}
899 		if(rp->agent != NULL &&
900 		   watch_dog_time_is_up(rp->agent,time_diff) &&
901 		   ssa_subagent_is_alive(rp->agent)==FALSE)
902 		{
903 			/* get the port if not exist
904 			 * and store it in rp and agent */
905 			if(rp->agent->address.sin_port == 0 ||
906 			   rp->agent->agentPortNumber ==0){
907 				port_num = get_a_non_reserved_port();
908 				rp->agent->agentPortNumber =
909 				rp->agent->address.sin_port = (short)port_num;
910 				if(port_num==0)
911 				  error("can't find a valid port for the agent %s",(rp->agent->name? rp->agent->name:""));
912 			}
913                         if (!already_bound_port(rp->agent->agentPortNumber)) {
914 				rp->agent ->agentProcessID = spawn_child(rp);
915 				if (trace_level > 0)
916 					trace("watch_dog: restart agent %s pid %d\n", rp->res_name, rp->agent->agentProcessID);
917 				rp->agent->agentSystemUpTime = systemUpTime();
918                         }
919 		}
920 	}
921   }
922   start_time = end_time;
923 }
924 
already_bound_port(int port_num)925 int already_bound_port(int port_num) {
926 
927 int socket_handle;
928 struct sockaddr_in in_addr;
929 char errmsg[100];
930 
931      socket_handle = socket(AF_INET,SOCK_DGRAM,0) ;
932      if (socket_handle < 0) {
933         error("Unable to open Datagram Socket error = %d",errno);
934         return 0;
935      }
936      in_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
937      in_addr.sin_family = AF_INET;
938      in_addr.sin_port = htons(port_num);
939      memset(in_addr.sin_zero,0,8 );
940 
941      if (bind(socket_handle,(struct sockaddr *)&in_addr, sizeof(struct sockaddr))) {
942             close(socket_handle);
943             return 1;
944      }else {
945             close(socket_handle);
946             return 0;
947      }
948 
949 
950 }
951 
kill_all_pid_rec_list()952 void kill_all_pid_rec_list()
953 {
954 	PidRec *ap;
955 	Agent *ag;
956 	struct timeval timeout;
957 
958    	timeout.tv_sec = 5;
959   	timeout.tv_usec = 0;
960 
961 	for(ap=first_pid;ap;ap=ap->next_pid){
962 	  if(ap->agent_name != NULL &&
963 	     SSAAgentIsAlive(NULL,ap->port,NULL,&timeout)==TRUE){
964 			kill(ap->pid,SIGTERM);
965 	     		if(SSAAgentIsAlive(NULL,ap->port,NULL,&timeout)==TRUE)
966 				kill(ap->pid,SIGKILL);
967 	  }
968 	}
969 }
970 
kill_part_pid_rec_list()971 void kill_part_pid_rec_list()
972 {
973 	PidRec *ap;
974 	Agent *ag;
975 	struct timeval timeout;
976 
977    	timeout.tv_sec = 5;
978   	timeout.tv_usec = 0;
979 
980 	for(ap=first_pid;ap;ap=ap->next_pid){
981 	  if(ap->agent_name != NULL &&
982 	     agent_find_by_name(ap->agent_name) == NULL &&
983 	     SSAAgentIsAlive(NULL,ap->port,NULL,&timeout)==TRUE){
984 			kill(ap->pid,SIGTERM);
985 	  }
986 	}
987 }
988