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