dumprmt.c revision 1.10 1 /* $NetBSD: dumprmt.c,v 1.10 1996/03/15 22:39:26 scottr Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)dumprmt.c 8.1 (Berkeley) 6/5/93";
39 #else
40 static char rcsid[] = "$NetBSD: dumprmt.c,v 1.10 1996/03/15 22:39:26 scottr Exp $";
41 #endif
42 #endif /* not lint */
43
44 #include <sys/param.h>
45 #include <sys/mtio.h>
46 #include <sys/ioctl.h>
47 #include <sys/socket.h>
48 #include <sys/time.h>
49 #ifdef sunos
50 #include <sys/vnode.h>
51
52 #include <ufs/inode.h>
53 #else
54 #include <ufs/ufs/dinode.h>
55 #endif
56
57 #include <netinet/in.h>
58 #include <netinet/tcp.h>
59
60 #include <protocols/dumprestore.h>
61
62 #include <ctype.h>
63 #include <err.h>
64 #include <netdb.h>
65 #include <pwd.h>
66 #include <signal.h>
67 #include <stdio.h>
68 #ifdef __STDC__
69 #include <stdlib.h>
70 #include <string.h>
71 #include <unistd.h>
72 #endif
73
74 #include "pathnames.h"
75 #include "dump.h"
76
77 #define TS_CLOSED 0
78 #define TS_OPEN 1
79
80 static int rmtstate = TS_CLOSED;
81 static int rmtape;
82 static char *rmtpeer;
83
84 static int okname __P((char *));
85 static int rmtcall __P((char *, char *));
86 static void rmtconnaborted __P((/* int, int */));
87 static int rmtgetb __P((void));
88 static void rmtgetconn __P((void));
89 static void rmtgets __P((char *, int));
90 static int rmtreply __P((char *));
91
92 extern int ntrec; /* blocking factor on tape */
93 extern uid_t uid; /* real uid */
94 extern uid_t euid; /* effective uid */
95
96 int
97 rmthost(host)
98 char *host;
99 {
100
101 rmtpeer = malloc(strlen(host) + 1);
102 if (rmtpeer)
103 strcpy(rmtpeer, host);
104 else
105 rmtpeer = host;
106 signal(SIGPIPE, rmtconnaborted);
107 rmtgetconn();
108 if (rmtape < 0)
109 return (0);
110 return (1);
111 }
112
113 static void
114 rmtconnaborted()
115 {
116
117 errx(1, "Lost connection to remote host.");
118 }
119
120 void
121 rmtgetconn()
122 {
123 register char *cp;
124 static struct servent *sp = NULL;
125 static struct passwd *pwd = NULL;
126 #ifdef notdef
127 static int on = 1;
128 #endif
129 char *tuser;
130 int size;
131 int maxseg;
132
133 if (sp == NULL) {
134 sp = getservbyname("shell", "tcp");
135 if (sp == NULL)
136 errx(1, "shell/tcp: unknown service");
137 pwd = getpwuid(getuid());
138 if (pwd == NULL)
139 errx(1, "who are you?");
140 }
141 if ((cp = strchr(rmtpeer, '@')) != NULL) {
142 tuser = rmtpeer;
143 *cp = '\0';
144 if (!okname(tuser))
145 exit(1);
146 rmtpeer = ++cp;
147 } else
148 tuser = pwd->pw_name;
149
150 (void) seteuid(euid);
151 rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
152 _PATH_RMT, (int *)0);
153 (void) setuid(uid); /* Just to be Really Really safe */
154
155 size = ntrec * TP_BSIZE;
156 if (size > 60 * 1024) /* XXX */
157 size = 60 * 1024;
158 /* Leave some space for rmt request/response protocol */
159 size += 2 * 1024;
160 while (size > TP_BSIZE &&
161 setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
162 size -= TP_BSIZE;
163 (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
164 maxseg = 1024;
165 if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
166 &maxseg, sizeof (maxseg)) < 0)
167 perror("TCP_MAXSEG setsockopt");
168
169 #ifdef notdef
170 if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
171 perror("TCP_NODELAY setsockopt");
172 #endif
173 }
174
175 static int
176 okname(cp0)
177 char *cp0;
178 {
179 register char *cp;
180 register int c;
181
182 for (cp = cp0; *cp; cp++) {
183 c = *cp;
184 if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
185 warnx("invalid user name: %s", cp0);
186 return (0);
187 }
188 }
189 return (1);
190 }
191
192 int
193 rmtopen(tape, mode)
194 char *tape;
195 int mode;
196 {
197 char buf[256];
198
199 (void)sprintf(buf, "O%s\n%d\n", tape, mode);
200 rmtstate = TS_OPEN;
201 return (rmtcall(tape, buf));
202 }
203
204 void
205 rmtclose()
206 {
207
208 if (rmtstate != TS_OPEN)
209 return;
210 rmtcall("close", "C\n");
211 rmtstate = TS_CLOSED;
212 }
213
214 int
215 rmtread(buf, count)
216 char *buf;
217 int count;
218 {
219 char line[30];
220 int n, i, cc;
221 extern errno;
222
223 (void)sprintf(line, "R%d\n", count);
224 n = rmtcall("read", line);
225 if (n < 0) {
226 errno = n;
227 return (-1);
228 }
229 for (i = 0; i < n; i += cc) {
230 cc = read(rmtape, buf+i, n - i);
231 if (cc <= 0) {
232 rmtconnaborted();
233 }
234 }
235 return (n);
236 }
237
238 int
239 rmtwrite(buf, count)
240 char *buf;
241 int count;
242 {
243 char line[30];
244
245 (void)sprintf(line, "W%d\n", count);
246 write(rmtape, line, strlen(line));
247 write(rmtape, buf, count);
248 return (rmtreply("write"));
249 }
250
251 void
252 rmtwrite0(count)
253 int count;
254 {
255 char line[30];
256
257 (void)sprintf(line, "W%d\n", count);
258 write(rmtape, line, strlen(line));
259 }
260
261 void
262 rmtwrite1(buf, count)
263 char *buf;
264 int count;
265 {
266
267 write(rmtape, buf, count);
268 }
269
270 int
271 rmtwrite2()
272 {
273
274 return (rmtreply("write"));
275 }
276
277 int
278 rmtseek(offset, pos)
279 int offset, pos;
280 {
281 char line[80];
282
283 (void)sprintf(line, "L%d\n%d\n", offset, pos);
284 return (rmtcall("seek", line));
285 }
286
287 struct mtget mts;
288
289 struct mtget *
290 rmtstatus()
291 {
292 register int i;
293 register char *cp;
294
295 if (rmtstate != TS_OPEN)
296 return (NULL);
297 rmtcall("status", "S\n");
298 for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
299 *cp++ = rmtgetb();
300 return (&mts);
301 }
302
303 int
304 rmtioctl(cmd, count)
305 int cmd, count;
306 {
307 char buf[256];
308
309 if (count < 0)
310 return (-1);
311 (void)sprintf(buf, "I%d\n%d\n", cmd, count);
312 return (rmtcall("ioctl", buf));
313 }
314
315 static int
316 rmtcall(cmd, buf)
317 char *cmd, *buf;
318 {
319
320 if (write(rmtape, buf, strlen(buf)) != strlen(buf))
321 rmtconnaborted();
322 return (rmtreply(cmd));
323 }
324
325 static int
326 rmtreply(cmd)
327 char *cmd;
328 {
329 register char *cp;
330 char code[30], emsg[BUFSIZ];
331
332 rmtgets(code, sizeof (code));
333 if (*code == 'E' || *code == 'F') {
334 rmtgets(emsg, sizeof (emsg));
335 msg("%s: %s", cmd, emsg);
336 if (*code == 'F') {
337 rmtstate = TS_CLOSED;
338 return (-1);
339 }
340 return (-1);
341 }
342 if (*code != 'A') {
343 /* Kill trailing newline */
344 cp = code + strlen(code);
345 if (cp > code && *--cp == '\n')
346 *cp = '\0';
347
348 msg("Protocol to remote tape server botched (code \"%s\").\n",
349 code);
350 rmtconnaborted();
351 }
352 return (atoi(code + 1));
353 }
354
355 int
356 rmtgetb()
357 {
358 char c;
359
360 if (read(rmtape, &c, 1) != 1)
361 rmtconnaborted();
362 return (c);
363 }
364
365 /* Get a line (guaranteed to have a trailing newline). */
366 void
367 rmtgets(line, len)
368 char *line;
369 int len;
370 {
371 register char *cp = line;
372
373 while (len > 1) {
374 *cp = rmtgetb();
375 if (*cp == '\n') {
376 cp[1] = '\0';
377 return;
378 }
379 cp++;
380 len--;
381 }
382 *cp = '\0';
383 msg("Protocol to remote tape server botched.\n");
384 msg("(rmtgets got \"%s\").\n", line);
385 rmtconnaborted();
386 }
387