19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 #pragma ident "%Z%%M% %I% %E% SMI"
40
41 /*
42 * sm_statd.c consists of routines used for the intermediate
43 * statd implementation(3.2 rpc.statd);
44 * it creates an entry in "current" directory for each site that it monitors;
45 * after crash and recovery, it moves all entries in "current"
46 * to "backup" directory, and notifies the corresponding statd of its recovery.
47 */
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <string.h>
53 #include <syslog.h>
54 #include <netdb.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <sys/file.h>
58 #include <sys/param.h>
59 #include <arpa/inet.h>
113 * If that fails, give up.
114 */
115 if ((fp = fopen(STATE, "r+")) == (FILE *)NULL)
116 if ((fp = fopen(STATE, "w+")) == (FILE *)NULL) {
117 syslog(LOG_ERR, "can't open %s: %m", STATE);
118 exit(1);
119 } else
120 (void) chmod(STATE, 0644);
121 if ((fscanf(fp, "%d", &LOCAL_STATE)) == EOF) {
122 if (debug >= 2)
123 (void) printf("empty file\n");
124 LOCAL_STATE = 0;
125 }
126
127 /*
128 * Scan alternate paths for largest "state" number
129 */
130 for (i = 0; i < pathix; i++) {
131 (void) sprintf(state_file, "%s/statmon/state", path_name[i]);
132 if ((fp_tmp = fopen(state_file, "r+")) == (FILE *)NULL) {
133 if ((fp_tmp = fopen(state_file, "w+"))
134 == (FILE *)NULL) {
135 if (debug)
136 syslog(LOG_ERR,
137 "can't open %s: %m",
138 state_file);
139 continue;
140 } else
141 (void) chmod(state_file, 0644);
142 }
143 if ((fscanf(fp_tmp, "%d", &tmp_state)) == EOF) {
144 if (debug)
145 syslog(LOG_ERR,
146 "statd: %s: file empty\n", state_file);
147 (void) fclose(fp_tmp);
148 continue;
149 }
150 if (tmp_state > LOCAL_STATE) {
151 LOCAL_STATE = tmp_state;
152 if (debug)
153 (void) printf("Update LOCAL STATE: %d\n",
154 tmp_state);
163 LOCAL_STATE = 1;
164 }
165
166 /* Copy the LOCAL_STATE value back to all stat files */
167 if (fseek(fp, 0, 0) == -1) {
168 syslog(LOG_ERR, "statd: fseek failed\n");
169 exit(1);
170 }
171
172 (void) fprintf(fp, "%-10d", LOCAL_STATE);
173 (void) fflush(fp);
174 if (fsync(fileno(fp)) == -1) {
175 syslog(LOG_ERR, "statd: fsync failed\n");
176 exit(1);
177 }
178 (void) fclose(fp);
179
180 for (i = 0; i < pathix; i++) {
181 (void) sprintf(state_file, "%s/statmon/state", path_name[i]);
182 if ((fp_tmp = fopen(state_file, "r+")) == (FILE *)NULL) {
183 if ((fp_tmp = fopen(state_file, "w+"))
184 == (FILE *)NULL) {
185 syslog(LOG_ERR,
186 "can't open %s: %m", state_file);
187 continue;
188 } else
189 (void) chmod(state_file, 0644);
190 }
191 (void) fprintf(fp_tmp, "%-10d", LOCAL_STATE);
192 (void) fflush(fp_tmp);
193 if (fsync(fileno(fp_tmp)) == -1) {
194 syslog(LOG_ERR,
195 "statd: %s: fsync failed\n", state_file);
196 (void) fclose(fp_tmp);
197 exit(1);
198 }
199 (void) fclose(fp_tmp);
200 }
201
202 if (debug)
203 (void) printf("local state = %d\n", LOCAL_STATE);
204
289 thr_join(0, 0, 0);
290 num_threads -= num_join;
291 }
292
293 /*
294 * If can't alloc name then print error msg and
295 * continue to next item on list.
296 */
297 name = strdup(dirp->d_name);
298 if (name == (char *)NULL) {
299 syslog(LOG_ERR,
300 "statd: unable to allocate space for name %s\n",
301 dirp->d_name);
302 continue;
303 }
304
305 /* Create a thread to do a statd_call_statd for name */
306 if (thr_create(NULL, NULL, thr_call_statd,
307 (void *) name, 0, 0)) {
308 syslog(LOG_ERR,
309 "statd: unable to create thr_call_statd() for name %s.\n",
310 dirp->d_name);
311 free(name);
312 continue;
313 }
314 num_threads++;
315 }
316
317 /*
318 * Join the other threads created above before processing the
319 * legacies. This allows all symlinks and the regular files
320 * to which they correspond to be processed and deleted.
321 */
322 for (i = 0; i < num_threads; i++) {
323 thr_join(0, 0, 0);
324 }
325
326 /*
327 * The second pass checks for `legacies': regular files which
328 * never had symlinks pointing to them at all, just like in the
329 * good old (pre-1184192 fix) days. Once a machine has cleaned
330 * up its legacies they should only reoccur due to catastrophes
364 thr_join(0, 0, 0);
365 num_threads -= num_join;
366 }
367
368 /*
369 * If can't alloc name then print error msg and
370 * continue to next item on list.
371 */
372 name = strdup(dirp->d_name);
373 if (name == (char *)NULL) {
374 syslog(LOG_ERR,
375 "statd: unable to allocate space for name %s\n",
376 dirp->d_name);
377 continue;
378 }
379
380 /* Create a thread to do a statd_call_statd for name */
381 if (thr_create(NULL, NULL, thr_call_statd,
382 (void *) name, 0, 0)) {
383 syslog(LOG_ERR,
384 "statd: unable to create thr_call_statd() for name %s.\n",
385 dirp->d_name);
386 free(name);
387 continue;
388 }
389 num_threads++;
390 }
391
392 (void) closedir(dp);
393
394 /*
395 * Join the other threads created above before creating thread
396 * to process items in recovery table.
397 */
398 for (i = 0; i < num_threads; i++) {
399 thr_join(0, 0, 0);
400 }
401
402 /*
403 * Need to only copy /var/statmon/sm.bak to alternate paths, since
404 * the only hosts in /var/statmon/sm should be the ones currently
405 * being monitored and already should be in alternate paths as part
472 (void) insert_name(&recov_q.sm_recovhdp, name, 0);
473 mutex_unlock(&recov_q.lock);
474
475 /*
476 * If we queued a symlink name in the recovery queue,
477 * we now clean up the regular file to which it referred.
478 * This may leave a severed symlink if multiple links
479 * referred to one regular file; this is unaesthetic but
480 * it works. The big benefit is that it prevents us
481 * from recovering the same host twice (as symlink and
482 * as regular file) needlessly, usually on separate reboots.
483 */
484 (void) strcpy(path, BACKUP);
485 (void) strcat(path, "/");
486 (void) strcat(path, name);
487 if (is_symlink(path)) {
488 n = readlink(path, rname, MAXNAMELEN);
489 if (n <= 0) {
490 if (debug >= 2) {
491 (void) printf(
492 "thr_call_statd: can't read link %s\n",
493 path);
494 }
495 } else {
496 rname[n] = '\0';
497
498 tail = strrchr(path, '/') + 1;
499
500 if ((strlen(BACKUP) + strlen(rname) + 2) <=
501 MAXPATHLEN) {
502 (void) strcpy(tail, rname);
503 delete_file(path);
504 } else if (debug) {
505 printf("thr_call_statd: path over"
506 "maxpathlen!\n");
507 }
508 }
509
510 }
511
512 if (debug)
513 pr_name(name, 0);
564 if ((strncmp(name, SM_ADDR_IPV4, unq_len) == 0) ||
565 (strncmp(name, SM_ADDR_IPV6, unq_len) == 0)) {
566 name_or_addr = strchr(name, '.') + 1;
567 } else {
568 name_or_addr = name;
569 }
570
571 /*
572 * NOTE: We depend here upon the fact that the RPC client code
573 * allows us to use ASCII dotted quad `names', i.e. "192.9.200.1".
574 * This may change in a future release.
575 */
576 if (debug) {
577 (void) printf("statd_call_statd: calling create_client(%s)\n",
578 name_or_addr);
579 }
580
581 tottimeout.tv_sec = SM_RPC_TIMEOUT;
582 tottimeout.tv_usec = 0;
583
584 if ((clnt = create_client(name_or_addr, SM_PROG, SM_VERS,
585 &tottimeout)) == (CLIENT *) NULL) {
586 return (-1);
587 }
588
589 /* Perform notification to client */
590 rc = 0;
591 clnt_stat = clnt_call(clnt, SM_NOTIFY, xdr_stat_chge, (char *)&ntf,
592 xdr_void, NULL, tottimeout);
593 if (debug) {
594 (void) printf("clnt_stat=%s(%d)\n",
595 clnt_sperrno(clnt_stat), clnt_stat);
596 }
597 if (clnt_stat != (int)RPC_SUCCESS) {
598 syslog(LOG_WARNING,
599 "statd: cannot talk to statd at %s, %s(%d)\n",
600 name_or_addr, clnt_sperrno(clnt_stat), clnt_stat);
601 rc = -1;
602 }
603
604 /* For HA systems and multi-homed hosts */
605 ntf.state = LOCAL_STATE;
658 break;
659
660 mutex_unlock(&crash_lock);
661
662 while (((nl = next) != (name_entry *)NULL) && (!die)) {
663 next = next->nxt;
664 if (statd_call_statd(nl->name) == 0) {
665 /* remove name from BACKUP */
666 remove_name(nl->name, 1, 0);
667 mutex_lock(&recov_q.lock);
668 /* remove entry from recovery_q */
669 delete_name(&recov_q.sm_recovhdp, nl->name);
670 mutex_unlock(&recov_q.lock);
671 } else {
672 /*
673 * Print message only once since unreachable
674 * host can be contacted forever.
675 */
676 if (delay == 0)
677 syslog(LOG_WARNING,
678 "statd: host %s is not responding\n",
679 nl->name);
680 }
681 }
682 /*
683 * Increment the amount of delay before restarting again.
684 * The amount of delay should not exceed the MAX_DELAYTIME.
685 */
686 if (delay <= MAX_DELAYTIME)
687 delay += INC_DELAYTIME;
688 mutex_lock(&crash_lock);
689 }
690
691 mutex_unlock(&crash_lock);
692 mutex_unlock(&sm_trylock);
693 out:
694 rw_unlock(&thr_rwlock);
695 if (debug)
696 (void) printf("EXITING sm_try\n");
697 thr_exit((void *) 0);
698 #ifdef lint
699 return (0);
1018 */
1019 if (startup == 0) {
1020 for (i = 0; i < pathix; i++) {
1021 remove_single_name(name, path_name[i], alt_dir);
1022 }
1023 }
1024 }
1025
1026 /*
1027 * Remove the name from the specified directory, which is dir1/dir2 or
1028 * dir1, depending on whether dir2 is NULL.
1029 */
1030 static void
1031 remove_single_name(char *name, char *dir1, char *dir2)
1032 {
1033 int n, error;
1034 char path[MAXPATHLEN+MAXNAMELEN+SM_MAXPATHLEN]; /* why > MAXPATHLEN? */
1035 char dirpath[MAXPATHLEN];
1036 char rname[MAXNAMELEN + 1]; /* +1 for NULL term */
1037
1038 if (strlen(name) + strlen(dir1) + (dir2 != NULL ? strlen(dir2) : 0)
1039 + 3 > MAXPATHLEN) {
1040 if (dir2 != NULL)
1041 syslog(LOG_ERR,
1042 "statd: pathname too long: %s/%s/%s\n",
1043 dir1, dir2, name);
1044 else
1045 syslog(LOG_ERR,
1046 "statd: pathname too long: %s/%s\n",
1047 dir1, name);
1048
1049 return;
1050 }
1051
1052 (void) strcpy(path, dir1);
1053 (void) strcat(path, "/");
1054 if (dir2 != NULL) {
1055 (void) strcat(path, dir2);
1056 (void) strcat(path, "/");
1057 }
1058 (void) strcpy(dirpath, path); /* save here - we may need it shortly */
1059 (void) strcat(path, name);
1061 /*
1062 * Despite the name of this routine :-@), `path' may be a symlink
1063 * to a regular file. If it is, and if that file has no other
1064 * links to it, we must remove it now as well.
1065 */
1066 if (is_symlink(path)) {
1067 n = readlink(path, rname, MAXNAMELEN);
1068 if (n > 0) {
1069 rname[n] = '\0';
1070
1071 if (count_symlinks(dirpath, rname, &n) < 0) {
1072 return;
1073 }
1074
1075 if (n == 1) {
1076 (void) strcat(dirpath, rname);
1077 error = unlink(dirpath);
1078 if (debug >= 2) {
1079 if (error < 0) {
1080 (void) printf(
1081 "remove_name: can't unlink %s\n",
1082 dirpath);
1083 } else {
1084 (void) printf(
1085 "remove_name: unlinked %s\n",
1086 dirpath);
1087 }
1088 }
1089 }
1090 } else {
1091 /*
1092 * Policy: if we can't read the symlink, leave it
1093 * here for analysis by the system administrator.
1094 */
1095 syslog(LOG_ERR,
1096 "statd: can't read link %s: %m\n", path);
1097 }
1098 }
1099
1100 /*
1101 * If it's a regular file, we can assume all symlinks and the
1102 * files to which they refer have been processed already - just
1103 * fall through to here to remove it.
1104 */
1105 delete_file(path);
1106 }
1124 syslog(LOG_ERR, "count_symlinks: open %s dir, error %m\n",
1125 dir);
1126 return (-1);
1127 }
1128
1129 while ((dirp = readdir(dp)) != NULL) {
1130 if (strcmp(dirp->d_name, ".") == 0 ||
1131 strcmp(dirp->d_name, "..") == 0) {
1132 continue;
1133 }
1134
1135 (void) sprintf(lpath, "%s%s", dir, dirp->d_name);
1136 if (is_symlink(lpath)) {
1137 /*
1138 * Fetch the name of the file the symlink refers to.
1139 */
1140 n = readlink(lpath, rname, MAXNAMELEN);
1141 if (n <= 0) {
1142 if (debug >= 2) {
1143 (void) printf(
1144 "count_symlinks: can't read link %s\n",
1145 lpath);
1146 }
1147 continue;
1148 }
1149 rname[n] = '\0';
1150
1151 /*
1152 * If `rname' matches `name', bump the count. There
1153 * may well be multiple symlinks to the same name, so
1154 * we must continue to process the entire directory.
1155 */
1156 if (strcmp(rname, name) == 0) {
1157 cnt++;
1158 }
1159 }
1160 }
1161
1162 (void) closedir(dp);
1163
1164 if (debug) {
1165 (void) printf("count_symlinks: found %d symlinks\n", cnt);
1348 syslog(LOG_DEBUG,
1349 "record_addr: unsupported address family %d\n",
1350 family);
1351 return;
1352 }
1353
1354 switch (family) {
1355 char abuf[INET6_ADDRSTRLEN];
1356 case AF_INET:
1357 (void) sprintf(ascii_addr, "%s.%s", famstr, inet_ntoa(addr));
1358 break;
1359
1360 case AF_INET6:
1361 (void) sprintf(ascii_addr, "%s.%s", famstr,\
1362 inet_ntop(family, addr6, abuf, sizeof (abuf)));
1363 break;
1364
1365 default:
1366 if (debug) {
1367 (void) printf(
1368 "record_addr: family2string supports unknown family %d (%s)\n",
1369 family,
1370 famstr);
1371 }
1372 free(famstr);
1373 return;
1374 }
1375
1376 if (debug) {
1377 (void) printf("record_addr: ascii_addr= %s\n", ascii_addr);
1378 }
1379 free(famstr);
1380
1381 /*
1382 * Make the symlink in CURRENT. The `name' file should have
1383 * been created previously by record_name().
1384 */
1385 (void) create_symlink(CURRENT, name, ascii_addr);
1386
1387 /*
1388 * Similarly for alternate paths.
1389 */
1390 for (i = 0; i < pathix; i++) {
|
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 /*
40 * Copyright (c) 2012 by Delphix. All rights reserved.
41 */
42
43 /*
44 * sm_statd.c consists of routines used for the intermediate
45 * statd implementation(3.2 rpc.statd);
46 * it creates an entry in "current" directory for each site that it monitors;
47 * after crash and recovery, it moves all entries in "current"
48 * to "backup" directory, and notifies the corresponding statd of its recovery.
49 */
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <string.h>
55 #include <syslog.h>
56 #include <netdb.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <sys/file.h>
60 #include <sys/param.h>
61 #include <arpa/inet.h>
115 * If that fails, give up.
116 */
117 if ((fp = fopen(STATE, "r+")) == (FILE *)NULL)
118 if ((fp = fopen(STATE, "w+")) == (FILE *)NULL) {
119 syslog(LOG_ERR, "can't open %s: %m", STATE);
120 exit(1);
121 } else
122 (void) chmod(STATE, 0644);
123 if ((fscanf(fp, "%d", &LOCAL_STATE)) == EOF) {
124 if (debug >= 2)
125 (void) printf("empty file\n");
126 LOCAL_STATE = 0;
127 }
128
129 /*
130 * Scan alternate paths for largest "state" number
131 */
132 for (i = 0; i < pathix; i++) {
133 (void) sprintf(state_file, "%s/statmon/state", path_name[i]);
134 if ((fp_tmp = fopen(state_file, "r+")) == (FILE *)NULL) {
135 if ((fp_tmp = fopen(state_file, "w+")) ==
136 (FILE *)NULL) {
137 if (debug)
138 syslog(LOG_ERR,
139 "can't open %s: %m",
140 state_file);
141 continue;
142 } else
143 (void) chmod(state_file, 0644);
144 }
145 if ((fscanf(fp_tmp, "%d", &tmp_state)) == EOF) {
146 if (debug)
147 syslog(LOG_ERR,
148 "statd: %s: file empty\n", state_file);
149 (void) fclose(fp_tmp);
150 continue;
151 }
152 if (tmp_state > LOCAL_STATE) {
153 LOCAL_STATE = tmp_state;
154 if (debug)
155 (void) printf("Update LOCAL STATE: %d\n",
156 tmp_state);
165 LOCAL_STATE = 1;
166 }
167
168 /* Copy the LOCAL_STATE value back to all stat files */
169 if (fseek(fp, 0, 0) == -1) {
170 syslog(LOG_ERR, "statd: fseek failed\n");
171 exit(1);
172 }
173
174 (void) fprintf(fp, "%-10d", LOCAL_STATE);
175 (void) fflush(fp);
176 if (fsync(fileno(fp)) == -1) {
177 syslog(LOG_ERR, "statd: fsync failed\n");
178 exit(1);
179 }
180 (void) fclose(fp);
181
182 for (i = 0; i < pathix; i++) {
183 (void) sprintf(state_file, "%s/statmon/state", path_name[i]);
184 if ((fp_tmp = fopen(state_file, "r+")) == (FILE *)NULL) {
185 if ((fp_tmp = fopen(state_file, "w+")) ==
186 (FILE *)NULL) {
187 syslog(LOG_ERR,
188 "can't open %s: %m", state_file);
189 continue;
190 } else
191 (void) chmod(state_file, 0644);
192 }
193 (void) fprintf(fp_tmp, "%-10d", LOCAL_STATE);
194 (void) fflush(fp_tmp);
195 if (fsync(fileno(fp_tmp)) == -1) {
196 syslog(LOG_ERR,
197 "statd: %s: fsync failed\n", state_file);
198 (void) fclose(fp_tmp);
199 exit(1);
200 }
201 (void) fclose(fp_tmp);
202 }
203
204 if (debug)
205 (void) printf("local state = %d\n", LOCAL_STATE);
206
291 thr_join(0, 0, 0);
292 num_threads -= num_join;
293 }
294
295 /*
296 * If can't alloc name then print error msg and
297 * continue to next item on list.
298 */
299 name = strdup(dirp->d_name);
300 if (name == (char *)NULL) {
301 syslog(LOG_ERR,
302 "statd: unable to allocate space for name %s\n",
303 dirp->d_name);
304 continue;
305 }
306
307 /* Create a thread to do a statd_call_statd for name */
308 if (thr_create(NULL, NULL, thr_call_statd,
309 (void *) name, 0, 0)) {
310 syslog(LOG_ERR,
311 "statd: unable to create thr_call_statd() "
312 "for name %s.\n", dirp->d_name);
313 free(name);
314 continue;
315 }
316 num_threads++;
317 }
318
319 /*
320 * Join the other threads created above before processing the
321 * legacies. This allows all symlinks and the regular files
322 * to which they correspond to be processed and deleted.
323 */
324 for (i = 0; i < num_threads; i++) {
325 thr_join(0, 0, 0);
326 }
327
328 /*
329 * The second pass checks for `legacies': regular files which
330 * never had symlinks pointing to them at all, just like in the
331 * good old (pre-1184192 fix) days. Once a machine has cleaned
332 * up its legacies they should only reoccur due to catastrophes
366 thr_join(0, 0, 0);
367 num_threads -= num_join;
368 }
369
370 /*
371 * If can't alloc name then print error msg and
372 * continue to next item on list.
373 */
374 name = strdup(dirp->d_name);
375 if (name == (char *)NULL) {
376 syslog(LOG_ERR,
377 "statd: unable to allocate space for name %s\n",
378 dirp->d_name);
379 continue;
380 }
381
382 /* Create a thread to do a statd_call_statd for name */
383 if (thr_create(NULL, NULL, thr_call_statd,
384 (void *) name, 0, 0)) {
385 syslog(LOG_ERR,
386 "statd: unable to create thr_call_statd() "
387 "for name %s.\n", dirp->d_name);
388 free(name);
389 continue;
390 }
391 num_threads++;
392 }
393
394 (void) closedir(dp);
395
396 /*
397 * Join the other threads created above before creating thread
398 * to process items in recovery table.
399 */
400 for (i = 0; i < num_threads; i++) {
401 thr_join(0, 0, 0);
402 }
403
404 /*
405 * Need to only copy /var/statmon/sm.bak to alternate paths, since
406 * the only hosts in /var/statmon/sm should be the ones currently
407 * being monitored and already should be in alternate paths as part
474 (void) insert_name(&recov_q.sm_recovhdp, name, 0);
475 mutex_unlock(&recov_q.lock);
476
477 /*
478 * If we queued a symlink name in the recovery queue,
479 * we now clean up the regular file to which it referred.
480 * This may leave a severed symlink if multiple links
481 * referred to one regular file; this is unaesthetic but
482 * it works. The big benefit is that it prevents us
483 * from recovering the same host twice (as symlink and
484 * as regular file) needlessly, usually on separate reboots.
485 */
486 (void) strcpy(path, BACKUP);
487 (void) strcat(path, "/");
488 (void) strcat(path, name);
489 if (is_symlink(path)) {
490 n = readlink(path, rname, MAXNAMELEN);
491 if (n <= 0) {
492 if (debug >= 2) {
493 (void) printf(
494 "thr_call_statd: can't read "
495 "link %s\n", path);
496 }
497 } else {
498 rname[n] = '\0';
499
500 tail = strrchr(path, '/') + 1;
501
502 if ((strlen(BACKUP) + strlen(rname) + 2) <=
503 MAXPATHLEN) {
504 (void) strcpy(tail, rname);
505 delete_file(path);
506 } else if (debug) {
507 printf("thr_call_statd: path over"
508 "maxpathlen!\n");
509 }
510 }
511
512 }
513
514 if (debug)
515 pr_name(name, 0);
566 if ((strncmp(name, SM_ADDR_IPV4, unq_len) == 0) ||
567 (strncmp(name, SM_ADDR_IPV6, unq_len) == 0)) {
568 name_or_addr = strchr(name, '.') + 1;
569 } else {
570 name_or_addr = name;
571 }
572
573 /*
574 * NOTE: We depend here upon the fact that the RPC client code
575 * allows us to use ASCII dotted quad `names', i.e. "192.9.200.1".
576 * This may change in a future release.
577 */
578 if (debug) {
579 (void) printf("statd_call_statd: calling create_client(%s)\n",
580 name_or_addr);
581 }
582
583 tottimeout.tv_sec = SM_RPC_TIMEOUT;
584 tottimeout.tv_usec = 0;
585
586 if ((clnt = create_client(name_or_addr, SM_PROG, SM_VERS, NULL,
587 &tottimeout)) == NULL) {
588 return (-1);
589 }
590
591 /* Perform notification to client */
592 rc = 0;
593 clnt_stat = clnt_call(clnt, SM_NOTIFY, xdr_stat_chge, (char *)&ntf,
594 xdr_void, NULL, tottimeout);
595 if (debug) {
596 (void) printf("clnt_stat=%s(%d)\n",
597 clnt_sperrno(clnt_stat), clnt_stat);
598 }
599 if (clnt_stat != (int)RPC_SUCCESS) {
600 syslog(LOG_WARNING,
601 "statd: cannot talk to statd at %s, %s(%d)\n",
602 name_or_addr, clnt_sperrno(clnt_stat), clnt_stat);
603 rc = -1;
604 }
605
606 /* For HA systems and multi-homed hosts */
607 ntf.state = LOCAL_STATE;
660 break;
661
662 mutex_unlock(&crash_lock);
663
664 while (((nl = next) != (name_entry *)NULL) && (!die)) {
665 next = next->nxt;
666 if (statd_call_statd(nl->name) == 0) {
667 /* remove name from BACKUP */
668 remove_name(nl->name, 1, 0);
669 mutex_lock(&recov_q.lock);
670 /* remove entry from recovery_q */
671 delete_name(&recov_q.sm_recovhdp, nl->name);
672 mutex_unlock(&recov_q.lock);
673 } else {
674 /*
675 * Print message only once since unreachable
676 * host can be contacted forever.
677 */
678 if (delay == 0)
679 syslog(LOG_WARNING,
680 "statd: host %s is not "
681 "responding\n", nl->name);
682 }
683 }
684 /*
685 * Increment the amount of delay before restarting again.
686 * The amount of delay should not exceed the MAX_DELAYTIME.
687 */
688 if (delay <= MAX_DELAYTIME)
689 delay += INC_DELAYTIME;
690 mutex_lock(&crash_lock);
691 }
692
693 mutex_unlock(&crash_lock);
694 mutex_unlock(&sm_trylock);
695 out:
696 rw_unlock(&thr_rwlock);
697 if (debug)
698 (void) printf("EXITING sm_try\n");
699 thr_exit((void *) 0);
700 #ifdef lint
701 return (0);
1020 */
1021 if (startup == 0) {
1022 for (i = 0; i < pathix; i++) {
1023 remove_single_name(name, path_name[i], alt_dir);
1024 }
1025 }
1026 }
1027
1028 /*
1029 * Remove the name from the specified directory, which is dir1/dir2 or
1030 * dir1, depending on whether dir2 is NULL.
1031 */
1032 static void
1033 remove_single_name(char *name, char *dir1, char *dir2)
1034 {
1035 int n, error;
1036 char path[MAXPATHLEN+MAXNAMELEN+SM_MAXPATHLEN]; /* why > MAXPATHLEN? */
1037 char dirpath[MAXPATHLEN];
1038 char rname[MAXNAMELEN + 1]; /* +1 for NULL term */
1039
1040 if (strlen(name) + strlen(dir1) + (dir2 != NULL ? strlen(dir2) : 0) +
1041 3 > MAXPATHLEN) {
1042 if (dir2 != NULL)
1043 syslog(LOG_ERR,
1044 "statd: pathname too long: %s/%s/%s\n",
1045 dir1, dir2, name);
1046 else
1047 syslog(LOG_ERR,
1048 "statd: pathname too long: %s/%s\n",
1049 dir1, name);
1050
1051 return;
1052 }
1053
1054 (void) strcpy(path, dir1);
1055 (void) strcat(path, "/");
1056 if (dir2 != NULL) {
1057 (void) strcat(path, dir2);
1058 (void) strcat(path, "/");
1059 }
1060 (void) strcpy(dirpath, path); /* save here - we may need it shortly */
1061 (void) strcat(path, name);
1063 /*
1064 * Despite the name of this routine :-@), `path' may be a symlink
1065 * to a regular file. If it is, and if that file has no other
1066 * links to it, we must remove it now as well.
1067 */
1068 if (is_symlink(path)) {
1069 n = readlink(path, rname, MAXNAMELEN);
1070 if (n > 0) {
1071 rname[n] = '\0';
1072
1073 if (count_symlinks(dirpath, rname, &n) < 0) {
1074 return;
1075 }
1076
1077 if (n == 1) {
1078 (void) strcat(dirpath, rname);
1079 error = unlink(dirpath);
1080 if (debug >= 2) {
1081 if (error < 0) {
1082 (void) printf(
1083 "remove_name: can't "
1084 "unlink %s\n",
1085 dirpath);
1086 } else {
1087 (void) printf(
1088 "remove_name: unlinked ",
1089 "%s\n", dirpath);
1090 }
1091 }
1092 }
1093 } else {
1094 /*
1095 * Policy: if we can't read the symlink, leave it
1096 * here for analysis by the system administrator.
1097 */
1098 syslog(LOG_ERR,
1099 "statd: can't read link %s: %m\n", path);
1100 }
1101 }
1102
1103 /*
1104 * If it's a regular file, we can assume all symlinks and the
1105 * files to which they refer have been processed already - just
1106 * fall through to here to remove it.
1107 */
1108 delete_file(path);
1109 }
1127 syslog(LOG_ERR, "count_symlinks: open %s dir, error %m\n",
1128 dir);
1129 return (-1);
1130 }
1131
1132 while ((dirp = readdir(dp)) != NULL) {
1133 if (strcmp(dirp->d_name, ".") == 0 ||
1134 strcmp(dirp->d_name, "..") == 0) {
1135 continue;
1136 }
1137
1138 (void) sprintf(lpath, "%s%s", dir, dirp->d_name);
1139 if (is_symlink(lpath)) {
1140 /*
1141 * Fetch the name of the file the symlink refers to.
1142 */
1143 n = readlink(lpath, rname, MAXNAMELEN);
1144 if (n <= 0) {
1145 if (debug >= 2) {
1146 (void) printf(
1147 "count_symlinks: can't read link "
1148 "%s\n", lpath);
1149 }
1150 continue;
1151 }
1152 rname[n] = '\0';
1153
1154 /*
1155 * If `rname' matches `name', bump the count. There
1156 * may well be multiple symlinks to the same name, so
1157 * we must continue to process the entire directory.
1158 */
1159 if (strcmp(rname, name) == 0) {
1160 cnt++;
1161 }
1162 }
1163 }
1164
1165 (void) closedir(dp);
1166
1167 if (debug) {
1168 (void) printf("count_symlinks: found %d symlinks\n", cnt);
1351 syslog(LOG_DEBUG,
1352 "record_addr: unsupported address family %d\n",
1353 family);
1354 return;
1355 }
1356
1357 switch (family) {
1358 char abuf[INET6_ADDRSTRLEN];
1359 case AF_INET:
1360 (void) sprintf(ascii_addr, "%s.%s", famstr, inet_ntoa(addr));
1361 break;
1362
1363 case AF_INET6:
1364 (void) sprintf(ascii_addr, "%s.%s", famstr,\
1365 inet_ntop(family, addr6, abuf, sizeof (abuf)));
1366 break;
1367
1368 default:
1369 if (debug) {
1370 (void) printf(
1371 "record_addr: family2string supports unknown "
1372 "family %d (%s)\n", family, famstr);
1373 }
1374 free(famstr);
1375 return;
1376 }
1377
1378 if (debug) {
1379 (void) printf("record_addr: ascii_addr= %s\n", ascii_addr);
1380 }
1381 free(famstr);
1382
1383 /*
1384 * Make the symlink in CURRENT. The `name' file should have
1385 * been created previously by record_name().
1386 */
1387 (void) create_symlink(CURRENT, name, ascii_addr);
1388
1389 /*
1390 * Similarly for alternate paths.
1391 */
1392 for (i = 0; i < pathix; i++) {
|