Am-Utils Cross Reference
am-utils/fixmount/fixmount.c

source navigation ]
diff markup ]
identifier search ]
freetext search ]
file search ]
 
Version: 6.0.1 ] [ 6.0.2 ] [ 6.0.3 ] [ 6.0.4 ] [ 6.0.5 ] [ 6.0.6 ] [ 6.0.7 ] [ 6.0.8 ] [ 6.0.9 ] [ 6.0.10 ] [ 6.1 ] [ 6.1.1 ]

  1 /*
  2  * Copyright (c) 1997-2005 Erez Zadok
  3  * Copyright (c) 1990 Jan-Simon Pendry
  4  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  5  * Copyright (c) 1990 The Regents of the University of California.
  6  * All rights reserved.
  7  *
  8  * This code is derived from software contributed to Berkeley by
  9  * Jan-Simon Pendry at Imperial College, London.
 10  *
 11  * Redistribution and use in source and binary forms, with or without
 12  * modification, are permitted provided that the following conditions
 13  * are met:
 14  * 1. Redistributions of source code must retain the above copyright
 15  *    notice, this list of conditions and the following disclaimer.
 16  * 2. Redistributions in binary form must reproduce the above copyright
 17  *    notice, this list of conditions and the following disclaimer in the
 18  *    documentation and/or other materials provided with the distribution.
 19  * 3. All advertising materials mentioning features or use of this software
 20  *    must display the following acknowledgment:
 21  *      This product includes software developed by the University of
 22  *      California, Berkeley and its contributors.
 23  * 4. Neither the name of the University nor the names of its contributors
 24  *    may be used to endorse or promote products derived from this software
 25  *    without specific prior written permission.
 26  *
 27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 37  * SUCH DAMAGE.
 38  *
 39  *
 40  * File: am-utils/fixmount/fixmount.c
 41  *
 42  */
 43 
 44 #ifdef HAVE_CONFIG_H
 45 # include <config.h>
 46 #endif /* HAVE_CONFIG_H */
 47 #include <am_defs.h>
 48 
 49 #define CREATE_TIMEOUT  2       /* seconds */
 50 #define CALL_TIMEOUT    5       /* seconds */
 51 
 52 #ifndef INADDR_NONE
 53 # define INADDR_NONE    0xffffffff
 54 #endif /* not INADDR_NONE */
 55 
 56 /* Constant defs */
 57 #define ALL             1
 58 #define DIRS            2
 59 
 60 #define DODUMP          0x1
 61 #define DOEXPORTS       0x2
 62 #define DOREMOVE        0x4
 63 #define DOVERIFY        0x8
 64 #define DOREMALL        0x10
 65 
 66 extern int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path);
 67 
 68 static char dir_path[NFS_MAXPATHLEN];
 69 static char localhost[] = "localhost";
 70 static char thishost[MAXHOSTNAMELEN + 1] = "";
 71 static exports mntexports;
 72 static int quiet = 0;
 73 static int type = 0;
 74 static jmp_buf before_rpc;
 75 static mountlist mntdump;
 76 static struct in_addr thisaddr;
 77 static CLIENT *clnt_create_timeout(char *, struct timeval *);
 78 
 79 RETSIGTYPE create_timeout(int);
 80 int is_same_host(char *, char *, struct in_addr);
 81 int main(int, char *[]);
 82 int remove_all(CLIENT *, char *);
 83 int remove_mount(CLIENT *, char *, mountlist, int);
 84 void fix_rmtab(CLIENT *, char *, mountlist, int, int);
 85 void print_dump(mountlist);
 86 void usage(void);
 87 
 88 
 89 void
 90 usage(void)
 91 {
 92   fprintf(stderr, "usage: fixmount [-adervAqf] [-h hostname] host ...\n");
 93   exit(1);
 94 }
 95 
 96 
 97 /*
 98  * Check hostname against other name and its IP address
 99  */
100 int
101 is_same_host(char *name1, char *name2, struct in_addr addr2)
102 {
103   if (strcasecmp(name1, name2) == 0) {
104     return 1;
105   } else if (addr2.s_addr == INADDR_NONE) {
106     return 0;
107   } else {
108     static char lasthost[MAXHOSTNAMELEN] = "";
109     static struct in_addr addr1;
110     struct hostent *he;
111 
112     /*
113      * To save nameserver lookups, and because this function
114      * is typically called repeatedly on the same names,
115      * cache the last lookup result and reuse it if possible.
116      */
117     if (strcasecmp(name1, lasthost) == 0) {
118       return (addr1.s_addr == addr2.s_addr);
119     } else if (!(he = gethostbyname(name1))) {
120       return 0;
121     } else {
122       xstrlcpy(lasthost, name1, MAXHOSTNAMELEN);
123       memcpy(&addr1, he->h_addr, sizeof(addr1));
124       return (addr1.s_addr == addr2.s_addr);
125     }
126   }
127 }
128 
129 
130 /*
131  * Print the binary tree in inorder so that output is sorted.
132  */
133 void
134 print_dump(mountlist mp)
135 {
136   if (mp == NULL)
137     return;
138   if (is_same_host(mp->ml_hostname, thishost, thisaddr)) {
139     switch (type) {
140     case ALL:
141       printf("%s:%s\n", mp->ml_hostname, mp->ml_directory);
142       break;
143     case DIRS:
144       printf("%s\n", mp->ml_directory);
145       break;
146     default:
147       printf("%s\n", mp->ml_hostname);
148       break;
149     };
150   }
151   if (mp->ml_next)
152     print_dump(mp->ml_next);
153 }
154 
155 
156 /*
157  * remove entry from remote rmtab
158  */
159 int
160 remove_mount(CLIENT *client, char *host, mountlist ml, int fixit)
161 {
162   enum clnt_stat estat;
163   struct timeval tv;
164   char *pathp = dir_path;
165 
166   xstrlcpy(dir_path, ml->ml_directory, sizeof(dir_path));
167 
168   if (!fixit) {
169     printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
170     fflush(stdout);
171   } else {
172     printf("%s: removing %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
173     fflush(stdout);
174 
175     tv.tv_sec = CALL_TIMEOUT;
176     tv.tv_usec = 0;
177 
178     if ((estat = clnt_call(client,
179                            MOUNTPROC_UMNT,
180                            (XDRPROC_T_TYPE) xdr_dirpath,
181                            (char *) &pathp,
182                            (XDRPROC_T_TYPE) xdr_void,
183                            (char *) 0,
184                            tv)) != RPC_SUCCESS) {
185       fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ",
186               host, ml->ml_directory);
187       clnt_perrno(estat);
188       fflush(stderr);
189       return -1;
190     }
191   }
192   return 0;
193 }
194 
195 
196 /*
197  * fix mount list on remote host
198  */
199 void
200 fix_rmtab(CLIENT *client, char *host, mountlist mp, int fixit, int force)
201 {
202   mountlist p;
203   struct hostent *he;
204   struct in_addr hostaddr;
205 
206   /*
207    * Obtain remote address for comparisons
208    */
209   if ((he = gethostbyname(host))) {
210     memcpy(&hostaddr, he->h_addr, sizeof(hostaddr));
211   } else {
212     hostaddr.s_addr = INADDR_NONE;
213   }
214 
215   for (p = mp; p; p = p->ml_next) {
216     if (is_same_host(p->ml_hostname, thishost, thisaddr)) {
217       if (force || !fixmount_check_mount(host, hostaddr, p->ml_directory))
218         remove_mount(client, host, p, fixit);
219     }
220   }
221 }
222 
223 
224 /*
225  * remove all entries from remote rmtab
226  */
227 int
228 remove_all(CLIENT *client, char *host)
229 {
230   enum clnt_stat estat;
231   struct timeval tv;
232 
233   printf("%s: removing ALL\n", host);
234   fflush(stdout);
235 
236   tv.tv_sec = CALL_TIMEOUT;
237   tv.tv_usec = 0;
238 
239   if ((estat = clnt_call(client,
240                          MOUNTPROC_UMNTALL,
241                          (XDRPROC_T_TYPE) xdr_void,
242                          (char *) 0,
243                          (XDRPROC_T_TYPE) xdr_void,
244                          (char *) 0,
245                          tv)) != RPC_SUCCESS) {
246     /*
247      * RPC_SYSTEMERROR is returned even if all went well
248      */
249     if (estat != RPC_SYSTEMERROR) {
250       fprintf(stderr, "%s MOUNTPROC_UMNTALL: ", host);
251       clnt_perrno(estat);
252       fflush(stderr);
253       return -1;
254     }
255   }
256 
257   return 0;
258 }
259 
260 
261 /*
262  * This command queries the NFS mount daemon for it's mount list and/or
263  * it's exports list and prints them out.
264  * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
265  * for detailed information on the protocol.
266  */
267 int
268 main(int argc, char *argv[])
269 {
270   AUTH *auth;
271   CLIENT *client;
272   char *host;
273   enum clnt_stat estat;
274   exports exp;
275   extern char *optarg;
276   extern int optind;
277   groups grp;
278   int ch;
279   int force = 0;
280   int morethanone;
281   register int rpcs = 0;
282   struct timeval tv;
283 
284   while ((ch = getopt(argc, argv, "adervAqfh:")) != -1)
285     switch ((char) ch) {
286 
287     case 'a':
288       if (type == 0) {
289         type = ALL;
290         rpcs |= DODUMP;
291       } else
292         usage();
293       break;
294 
295     case 'd':
296       if (type == 0) {
297         type = DIRS;
298         rpcs |= DODUMP;
299       } else
300         usage();
301       break;
302 
303     case 'e':
304       rpcs |= DOEXPORTS;
305       break;
306 
307     case 'r':
308       rpcs |= DOREMOVE;
309       break;
310 
311     case 'A':
312       rpcs |= DOREMALL;
313       break;
314 
315     case 'v':
316       rpcs |= DOVERIFY;
317       break;
318 
319     case 'q':
320       quiet = 1;
321       break;
322 
323     case 'f':
324       force = 1;
325       break;
326 
327     case 'h':
328       xstrlcpy(thishost, optarg, sizeof(thishost));
329       break;
330 
331     case '?':
332     default:
333       usage();
334     }
335 
336   if (optind == argc)
337     usage();
338 
339   if (rpcs == 0)
340     rpcs = DODUMP;
341 
342   if (!*thishost) {
343     struct hostent *he;
344 
345     if (gethostname(thishost, sizeof(thishost)) < 0) {
346       perror("gethostname");
347       exit(1);
348     }
349     thishost[sizeof(thishost) - 1] = '\0';
350 
351     /*
352      * We need the hostname as it appears to the other side's
353      * mountd, so get our own hostname by reverse address
354      * resolution.
355      */
356     if (!(he = gethostbyname(thishost))) {
357       fprintf(stderr, "gethostbyname failed on %s\n",
358               thishost);
359       exit(1);
360     }
361     memcpy(&thisaddr, he->h_addr, sizeof(thisaddr));
362     if (!(he = gethostbyaddr((char *) &thisaddr, sizeof(thisaddr),
363                              he->h_addrtype))) {
364       fprintf(stderr, "gethostbyaddr failed on %s\n",
365               inet_ntoa(thisaddr));
366       exit(1);
367     }
368     xstrlcpy(thishost, he->h_name, sizeof(thishost));
369   } else {
370     thisaddr.s_addr = INADDR_NONE;
371   }
372 
373   if (!(auth = authunix_create_default())) {
374     fprintf(stderr, "couldn't create authentication handle\n");
375     exit(1);
376   }
377   morethanone = (optind + 1 < argc);
378 
379   for (; optind < argc; optind++) {
380 
381     host = argv[optind];
382     tv.tv_sec = CREATE_TIMEOUT;
383     tv.tv_usec = 0;
384 
385     if (!(client = clnt_create_timeout(host, &tv)))
386         continue;
387 
388     client->cl_auth = auth;
389     tv.tv_sec = CALL_TIMEOUT;
390     tv.tv_usec = 0;
391 
392     if (rpcs & (DODUMP | DOREMOVE | DOVERIFY))
393       if ((estat = clnt_call(client,
394                              MOUNTPROC_DUMP,
395                              (XDRPROC_T_TYPE) xdr_void,
396                              (char *) 0,
397                              (XDRPROC_T_TYPE) xdr_mountlist,
398                              (char *) &mntdump,
399                              tv)) != RPC_SUCCESS) {
400         fprintf(stderr, "%s: MOUNTPROC_DUMP: ", host);
401         clnt_perrno(estat);
402         fflush(stderr);
403         mntdump = NULL;
404         goto next;
405       }
406     if (rpcs & DOEXPORTS)
407       if ((estat = clnt_call(client,
408                              MOUNTPROC_EXPORT,
409                              (XDRPROC_T_TYPE) xdr_void,
410                              (char *) 0,
411                              (XDRPROC_T_TYPE) xdr_exports,
412                              (char *) &mntexports,
413                              tv)) != RPC_SUCCESS) {
414         fprintf(stderr, "%s: MOUNTPROC_EXPORT: ", host);
415         clnt_perrno(estat);
416         fflush(stderr);
417         mntexports = NULL;
418         goto next;
419       }
420 
421     /* Now just print out the results */
422     if ((rpcs & (DODUMP | DOEXPORTS)) &&
423         morethanone) {
424       printf(">>> %s <<<\n", host);
425       fflush(stdout);
426     }
427 
428     if (rpcs & DODUMP) {
429       print_dump(mntdump);
430     }
431 
432     if (rpcs & DOEXPORTS) {
433       exp = mntexports;
434       while (exp) {
435         printf("%-35s", exp->ex_dir);
436         grp = exp->ex_groups;
437         if (grp == NULL) {
438           printf("Everyone\n");
439         } else {
440           while (grp) {
441             printf("%s ", grp->gr_name);
442             grp = grp->gr_next;
443           }
444           printf("\n");
445         }
446         exp = exp->ex_next;
447       }
448     }
449 
450     if (rpcs & DOVERIFY)
451       fix_rmtab(client, host, mntdump, 0, force);
452 
453     if (rpcs & DOREMOVE)
454       fix_rmtab(client, host, mntdump, 1, force);
455 
456     if (rpcs & DOREMALL)
457       remove_all(client, host);
458 
459   next:
460     if (mntdump)
461       (void) clnt_freeres(client,
462                           (XDRPROC_T_TYPE) xdr_mountlist,
463                           (char *) &mntdump);
464     if (mntexports)
465       (void) clnt_freeres(client,
466                           (XDRPROC_T_TYPE) xdr_exports,
467                           (char *) &mntexports);
468 
469     clnt_destroy(client);
470   }
471   exit(0);
472   return 0; /* should never reach here */
473 }
474 
475 
476 RETSIGTYPE
477 create_timeout(int sig)
478 {
479   signal(SIGALRM, SIG_DFL);
480   longjmp(before_rpc, 1);
481 }
482 
483 
484 #ifndef HAVE_TRANSPORT_TYPE_TLI
485 /*
486  * inetresport creates a datagram socket and attempts to bind it to a
487  * secure port.
488  * returns: The bound socket, or -1 to indicate an error.
489  */
490 static int
491 inetresport(int ty)
492 {
493   int alport;
494   struct sockaddr_in addr;
495   int fd;
496 
497   /* Use internet address family */
498   addr.sin_family = AF_INET;
499   addr.sin_addr.s_addr = INADDR_ANY;
500   if ((fd = socket(AF_INET, ty, 0)) < 0)
501     return -1;
502 
503   for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) {
504     addr.sin_port = htons((u_short) alport);
505     if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
506       return fd;
507     if (errno != EADDRINUSE) {
508       close(fd);
509       return -1;
510     }
511   }
512   close(fd);
513   errno = EAGAIN;
514   return -1;
515 }
516 
517 
518 /*
519  * Privsock() calls inetresport() to attempt to bind a socket to a secure
520  * port.  If inetresport() fails, privsock returns a magic socket number which
521  * indicates to RPC that it should make its own socket.
522  * returns: A privileged socket # or RPC_ANYSOCK.
523  */
524 static int
525 privsock(int ty)
526 {
527   int sock = inetresport(ty);
528 
529   if (sock < 0) {
530     errno = 0;
531     /* Couldn't get a secure port, let RPC make an insecure one */
532     sock = RPC_ANYSOCK;
533   }
534   return sock;
535 }
536 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
537 
538 
539 static CLIENT *
540 clnt_create_timeout(char *host, struct timeval *tvp)
541 {
542   CLIENT *clnt;
543   struct sockaddr_in host_addr;
544   struct hostent *hp;
545 #ifndef HAVE_TRANSPORT_TYPE_TLI
546   int s;
547 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
548 
549   if (setjmp(before_rpc)) {
550     if (!quiet) {
551       fprintf(stderr, "%s: ", host);
552       clnt_perrno(RPC_TIMEDOUT);
553       fprintf(stderr, "\n");
554       fflush(stderr);
555     }
556     return NULL;
557   }
558   signal(SIGALRM, create_timeout);
559   ualarm(tvp->tv_sec * 1000000 + tvp->tv_usec, 0);
560 
561   /*
562    * Get address of host
563    */
564   if ((hp = gethostbyname(host)) == 0 && !STREQ(host, localhost)) {
565     fprintf(stderr, "can't get address of %s\n", host);
566     return NULL;
567   }
568   memset(&host_addr, 0, sizeof host_addr);
569   host_addr.sin_family = AF_INET;
570   if (hp) {
571     memmove((voidp) &host_addr.sin_addr, (voidp) hp->h_addr,
572             sizeof(host_addr.sin_addr));
573   } else {
574     /* fake "localhost" */
575     host_addr.sin_addr.s_addr = htonl(0x7f000001);
576   }
577 
578 #ifdef HAVE_TRANSPORT_TYPE_TLI
579   /* try TCP first (in case return data is large), then UDP */
580   clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "tcp");
581   if (!clnt)
582     clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "udp");
583 #else /* not HAVE_TRANSPORT_TYPE_TLI */
584   s = RPC_ANYSOCK;
585   clnt = clnttcp_create(&host_addr, MOUNTPROG, MOUNTVERS, &s, 0, 0);
586   if (!clnt) {
587     /* XXX: do we need to close(s) ? */
588     s = privsock(SOCK_DGRAM);
589     clnt = clntudp_create(&host_addr, MOUNTPROG, MOUNTVERS, *tvp, &s);
590   }
591 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
592 
593   if (!clnt) {
594     ualarm(0, 0);
595     if (!quiet) {
596       clnt_pcreateerror(host);
597       fflush(stderr);
598     }
599     return NULL;
600   }
601 
602   ualarm(0, 0);
603   return clnt;
604 }
605 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
This page is hosted at the Filesystems and Storage Lab at Stony Brook.