1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | #include <sys/types.h> |
34 | #include <sys/mtio.h> |
35 | #include <sys/ioctl.h> |
36 | #include <sys/socket.h> |
37 | #include <sys/time.h> |
38 | #include <ufs/ufs/dinode.h> |
39 | |
40 | #include <netinet/in.h> |
41 | #include <netinet/tcp.h> |
42 | |
43 | #include <protocols/dumprestore.h> |
44 | |
45 | #include <ctype.h> |
46 | #include <err.h> |
47 | #include <netdb.h> |
48 | #include <pwd.h> |
49 | #include <signal.h> |
50 | #include <stdio.h> |
51 | #include <stdlib.h> |
52 | #include <string.h> |
53 | #include <unistd.h> |
54 | #include <limits.h> |
55 | |
56 | #include "pathnames.h" |
57 | #include "mt.h" |
58 | |
59 | #define TS_CLOSED 0 |
60 | #define TS_OPEN 1 |
61 | |
62 | static int rmtstate = TS_CLOSED; |
63 | static int rmtape; |
64 | static char *rmtpeer; |
65 | |
66 | static int okname(char *); |
67 | static int rmtcall(char *, char *); |
68 | static void rmtconnaborted(void); |
69 | static void sigrmtconnaborted(int); |
70 | static int rmtgetb(void); |
71 | static void rmtgetconn(void); |
72 | static void rmtgets(char *, int); |
73 | static int rmtreply(char *); |
74 | |
75 | int |
76 | rmthost(char *host) |
77 | { |
78 | if ((rmtpeer = strdup(host)) == NULL) |
| 1 | Assuming the condition is false | |
|
| |
79 | err(1, "strdup"); |
80 | signal(SIGPIPE, sigrmtconnaborted); |
81 | rmtgetconn(); |
| |
82 | if (rmtape < 0) |
83 | return (0); |
84 | return (1); |
85 | } |
86 | |
87 | |
88 | static void |
89 | sigrmtconnaborted(int signo) |
90 | { |
91 | |
92 | warnx("Lost connection to remote host."); |
93 | _exit(1); |
94 | } |
95 | |
96 | static void |
97 | rmtconnaborted(void) |
98 | { |
99 | |
100 | errx(1, "Lost connection to remote host."); |
101 | } |
102 | |
103 | void |
104 | rmtgetconn(void) |
105 | { |
106 | char *cp; |
107 | static struct passwd *pwd = NULL; |
| 4 | | 'pwd' initialized to a null pointer value | |
|
108 | #ifdef notdef |
109 | static int on = 1; |
110 | #endif |
111 | char *tuser; |
112 | int size; |
113 | int maxseg; |
114 | |
115 | if ((cp = strchr(rmtpeer, '@')) != NULL) { |
| 5 | | Assuming the condition is true | |
|
| |
116 | tuser = rmtpeer; |
117 | *cp = '\0'; |
118 | if (!okname(tuser)) |
| 7 | | Assuming the condition is false | |
|
| |
119 | exit(1); |
120 | rmtpeer = ++cp; |
121 | } else |
122 | tuser = pwd->pw_name; |
123 | |
124 | rmtape = rcmdsh(&rmtpeer, -1, pwd->pw_name, tuser, |
| 9 | | Access to field 'pw_name' results in a dereference of a null pointer (loaded from variable 'pwd') |
|
125 | _PATH_RMT, NULL); |
126 | if (rmtape == -1) |
127 | exit(1); |
128 | |
129 | size = TP_BSIZE; |
130 | if (size > 60 * 1024) |
131 | size = 60 * 1024; |
132 | |
133 | size += 2 * 1024; |
134 | |
135 | while (size > TP_BSIZE && |
136 | setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) == -1) |
137 | size -= TP_BSIZE; |
138 | (void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)); |
139 | |
140 | maxseg = 1024; |
141 | (void)setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG, &maxseg, |
142 | sizeof (maxseg)); |
143 | |
144 | #ifdef notdef |
145 | if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) == -1) |
146 | perror("TCP_NODELAY setsockopt"); |
147 | #endif |
148 | if (pledge("stdio", NULL) == -1) |
149 | err(1, "pledge"); |
150 | } |
151 | |
152 | static int |
153 | okname(char *cp0) |
154 | { |
155 | unsigned char *cp; |
156 | int c; |
157 | |
158 | for (cp = cp0; *cp; cp++) { |
159 | c = (unsigned char)*cp; |
160 | if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) { |
161 | warnx("invalid user name: %s", cp0); |
162 | return (0); |
163 | } |
164 | } |
165 | return (1); |
166 | } |
167 | |
168 | int |
169 | rmtopen(char *tape, int mode) |
170 | { |
171 | char buf[1 + PATH_MAX+1 + 10+1 +1]; |
172 | int r; |
173 | |
174 | r = snprintf(buf, sizeof (buf), "O%s\n%d\n", tape, mode); |
175 | if (r < 0 || r >= sizeof buf) |
176 | errx(1, "tape name too long"); |
177 | rmtstate = TS_OPEN; |
178 | return (rmtcall(tape, buf)); |
179 | } |
180 | |
181 | void |
182 | rmtclose(void) |
183 | { |
184 | |
185 | if (rmtstate != TS_OPEN) |
186 | return; |
187 | rmtcall("close", "C\n"); |
188 | rmtstate = TS_CLOSED; |
189 | } |
190 | |
191 | struct mtget mts; |
192 | |
193 | struct mtget * |
194 | rmtstatus(void) |
195 | { |
196 | int i; |
197 | char *cp; |
198 | |
199 | if (rmtstate != TS_OPEN) |
200 | return (NULL); |
201 | rmtcall("status", "S\n"); |
202 | for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++) |
203 | *cp++ = rmtgetb(); |
204 | return (&mts); |
205 | } |
206 | |
207 | int |
208 | rmtioctl(int cmd, int count) |
209 | { |
210 | char buf[1 + 10+1 + 10+1 +1]; |
211 | int r; |
212 | |
213 | if (count < 0) |
214 | return (-1); |
215 | r = snprintf(buf, sizeof (buf), "I%d\n%d\n", cmd, count); |
216 | if (r < 0 || r >= sizeof buf) |
217 | errx(1, "string error during ioctl"); |
218 | return (rmtcall("ioctl", buf)); |
219 | } |
220 | |
221 | static int |
222 | rmtcall(char *cmd, char *buf) |
223 | { |
224 | |
225 | if (write(rmtape, buf, strlen(buf)) != strlen(buf)) |
226 | rmtconnaborted(); |
227 | return (rmtreply(cmd)); |
228 | } |
229 | |
230 | static int |
231 | rmtreply(char *cmd) |
232 | { |
233 | char *cp; |
234 | char code[30], emsg[BUFSIZ]; |
235 | |
236 | rmtgets(code, sizeof (code)); |
237 | if (*code == 'E' || *code == 'F') { |
238 | rmtgets(emsg, sizeof (emsg)); |
239 | warnx("%s: %s", cmd, emsg); |
240 | if (*code == 'F') { |
241 | rmtstate = TS_CLOSED; |
242 | return (-1); |
243 | } |
244 | return (-1); |
245 | } |
246 | if (*code != 'A') { |
247 | |
248 | cp = code + strlen(code); |
249 | if (cp > code && *--cp == '\n') |
250 | *cp = '\0'; |
251 | |
252 | warnx("Protocol to remote tape server botched (code \"%s\").", |
253 | code); |
254 | rmtconnaborted(); |
255 | } |
256 | return (atoi(code + 1)); |
257 | } |
258 | |
259 | int |
260 | rmtgetb(void) |
261 | { |
262 | char c; |
263 | |
264 | if (read(rmtape, &c, 1) != 1) |
265 | rmtconnaborted(); |
266 | return (c); |
267 | } |
268 | |
269 | |
270 | void |
271 | rmtgets(char *line, int len) |
272 | { |
273 | char *cp = line; |
274 | |
275 | while (len > 1) { |
276 | *cp = rmtgetb(); |
277 | if (*cp == '\n') { |
278 | cp[1] = '\0'; |
279 | return; |
280 | } |
281 | cp++; |
282 | len--; |
283 | } |
284 | *cp = '\0'; |
285 | warnx("Protocol to remote tape server botched."); |
286 | warnx("(rmtgets got \"%s\").", line); |
287 | rmtconnaborted(); |
288 | } |