Bug Summary

File:src/usr.bin/tftp/tftp.c
Warning:line 607, column 16
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tftp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/tftp/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/tftp/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/tftp/tftp.c
1/* $OpenBSD: tftp.c,v 1.25 2017/09/10 07:29:39 tb Exp $ */
2/* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */
3
4/*
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * TFTP User Program -- Protocol Machines
35 *
36 * This version includes many modifications by Jim Guyton <guyton@rand-unix>
37 */
38
39#include <sys/types.h>
40#include <sys/socket.h>
41#include <sys/time.h>
42#include <sys/stat.h>
43
44#include <netinet/in.h>
45#include <arpa/tftp.h>
46
47#include <err.h>
48#include <errno(*__errno()).h>
49#include <poll.h>
50#include <signal.h>
51#include <stdio.h>
52#include <stddef.h>
53#include <stdlib.h>
54#include <string.h>
55#include <time.h>
56#include <unistd.h>
57#include <netdb.h>
58
59#include "extern.h"
60#include "tftpsubs.h"
61
62static int cmpport(struct sockaddr *, struct sockaddr *);
63static int makerequest(int, const char *, struct tftphdr *, const char *);
64static void nak(int, struct sockaddr *);
65static void tpacket(const char *, struct tftphdr *, int);
66static void startclock(void);
67static void stopclock(void);
68static void printstats(const char *, unsigned long);
69static void printtimeout(void);
70static void oack(struct tftphdr *, int, int);
71static int oack_set(const char *, const char *);
72
73extern struct sockaddr_storage peeraddr; /* filled in by main */
74extern int f; /* the opened socket */
75extern int trace;
76extern int verbose;
77extern int rexmtval;
78extern int maxtimeout;
79extern FILE *file;
80extern volatile sig_atomic_t intrflag;
81extern char *ackbuf;
82extern int has_options;
83extern int opt_tsize;
84extern int opt_tout;
85extern int opt_blksize;
86
87struct timespec tstart;
88struct timespec tstop;
89unsigned int segment_size = SEGSIZE512;
90unsigned int packet_size = SEGSIZE512 + 4;
91
92struct errmsg {
93 int e_code;
94 char *e_msg;
95} errmsgs[] = {
96 { EUNDEF0, "Undefined error code" },
97 { ENOTFOUND1, "File not found" },
98 { EACCESS2, "Access violation" },
99 { ENOSPACE3, "Disk full or allocation exceeded" },
100 { EBADOP4, "Illegal TFTP operation" },
101 { EBADID5, "Unknown transfer ID" },
102 { EEXISTS6, "File already exists" },
103 { ENOUSER7, "No such user" },
104 { EOPTNEG8, "Option negotiation failed" },
105 { -1, NULL((void*)0) }
106};
107
108struct options {
109 const char *o_type;
110} options[] = {
111 { "tsize" },
112 { "timeout" },
113 { "blksize" },
114 { NULL((void*)0) }
115};
116
117enum opt_enum {
118 OPT_TSIZE = 0,
119 OPT_TIMEOUT,
120 OPT_BLKSIZE
121};
122
123/*
124 * Send the requested file.
125 */
126void
127sendfile(int fd, char *name, char *mode)
128{
129 struct tftphdr *dp, *ap; /* data and ack packets */
130 struct sockaddr_storage from, peer;
131 struct sockaddr_storage serv; /* valid server port number */
132 struct pollfd pfd[1];
133 unsigned long amount;
134 socklen_t fromlen;
135 int convert; /* true if converting crlf -> lf */
136 int n, nfds, error, timeouts, size;
137 uint16_t block = 0;
138 int firsttrip = 1;
139
140 startclock(); /* start stat's clock */
141 dp = r_init(); /* reset fillbuf/read-ahead code */
142 ap = (struct tftphdr *)ackbuf;
143 file = fdopen(fd, "r");
144 convert = !strcmp(mode, "netascii");
145 amount = 0;
146 memcpy(&peer, &peeraddr, peeraddr.ss_len);
147 memset(&serv, 0, sizeof(serv));
148
149 do {
150 /* read data from file */
151 if (firsttrip)
152 size = makerequest(WRQ02, name, dp, mode) - 4;
153 else {
154 size = readit(file, &dp, convert, segment_size);
155 if (size < 0) {
156 nak(errno(*__errno()) + 100, (struct sockaddr *)&peer);
157 break;
158 }
159 dp->th_opcode = htons((u_short)DATA)(__uint16_t)(__builtin_constant_p((u_short)03) ? (__uint16_t)
(((__uint16_t)((u_short)03) & 0xffU) << 8 | ((__uint16_t
)((u_short)03) & 0xff00U) >> 8) : __swap16md((u_short
)03))
;
160 dp->th_blockth_u.tu_block = htons(block)(__uint16_t)(__builtin_constant_p(block) ? (__uint16_t)(((__uint16_t
)(block) & 0xffU) << 8 | ((__uint16_t)(block) &
0xff00U) >> 8) : __swap16md(block))
;
161 }
162
163 /* send data to server and wait for server ACK */
164 for (timeouts = 0, error = 0; !intrflag;) {
165 if (timeouts >= maxtimeout) {
166 printtimeout();
167 goto abort;
168 }
169
170 if (!error) {
171 if (trace)
172 tpacket("sent", dp, size + 4);
173 if (sendto(f, dp, size + 4, 0,
174 (struct sockaddr *)&peer,
175 peer.ss_len) != size + 4) {
176 warn("sendto");
177 goto abort;
178 }
179 if (!firsttrip)
180 read_ahead(file, convert, segment_size);
181 }
182 error = 0;
183
184 pfd[0].fd = f;
185 pfd[0].events = POLLIN0x0001;
186 nfds = poll(pfd, 1, rexmtval * 1000);
187 if (nfds == 0) {
188 timeouts += rexmtval;
189 continue;
190 }
191 if (nfds == -1) {
192 error = 1;
193 if (errno(*__errno()) == EINTR4)
194 continue;
195 warn("poll");
196 goto abort;
197 }
198 fromlen = sizeof(from);
199 n = recvfrom(f, ackbuf, packet_size, 0,
200 (struct sockaddr *)&from, &fromlen);
201 if (n == 0) {
202 warn("recvfrom");
203 goto abort;
204 }
205 if (n == -1) {
206 error = 1;
207 if (errno(*__errno()) == EINTR4)
208 continue;
209 warn("recvfrom");
210 goto abort;
211 }
212 if (!serv.ss_family)
213 serv = from;
214 else if (!cmpport((struct sockaddr *)&serv,
215 (struct sockaddr *)&from)) {
216 warn("server port mismatch");
217 goto abort;
218 }
219 peer = from;
220 if (trace)
221 tpacket("received", ap, n);
222
223 ap->th_opcode = ntohs(ap->th_opcode)(__uint16_t)(__builtin_constant_p(ap->th_opcode) ? (__uint16_t
)(((__uint16_t)(ap->th_opcode) & 0xffU) << 8 | (
(__uint16_t)(ap->th_opcode) & 0xff00U) >> 8) : __swap16md
(ap->th_opcode))
;
224
225 if (ap->th_opcode == OACK06) {
226 oack(ap, n, 0);
227 break;
228 }
229
230 ap->th_blockth_u.tu_block = ntohs(ap->th_block)(__uint16_t)(__builtin_constant_p(ap->th_u.tu_block) ? (__uint16_t
)(((__uint16_t)(ap->th_u.tu_block) & 0xffU) << 8
| ((__uint16_t)(ap->th_u.tu_block) & 0xff00U) >>
8) : __swap16md(ap->th_u.tu_block))
;
231
232 if (ap->th_opcode == ERROR05) {
233 printf("Error code %d: %s\n",
234 ap->th_codeth_u.tu_code, ap->th_msgth_data);
235 goto abort;
236 }
237 if (ap->th_opcode == ACK04) {
238 int j;
239 if (ap->th_blockth_u.tu_block == block)
240 break;
241 /* re-synchronize with other side */
242 j = synchnet(f);
243 if (j && trace)
244 printf("discarded %d packets\n", j);
245 if (ap->th_blockth_u.tu_block == (block - 1))
246 continue;
247 }
248 error = 1; /* received packet does not match */
249 }
250
251 if (firsttrip) {
252 size = segment_size;
253 firsttrip = 0;
254 } else
255 amount += size;
256 block++;
257 } while ((size == segment_size) && !intrflag);
258
259abort:
260 fclose(file);
261 stopclock();
262 if (amount > 0) {
263 if (intrflag)
264 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
265 printstats("Sent", amount);
266 }
267}
268
269/*
270 * Receive a file.
271 */
272void
273recvfile(int fd, char *name, char *mode)
274{
275 struct tftphdr *dp, *ap; /* data and ack packets */
276 struct sockaddr_storage from, peer;
277 struct sockaddr_storage serv; /* valid server port number */
278 struct pollfd pfd[1];
279 unsigned long amount;
280 socklen_t fromlen;
281 int convert; /* true if converting crlf -> lf */
282 int n, nfds, error, timeouts, size;
283 int firsttrip;
284 uint16_t block;
285
286 startclock(); /* start stat's clock */
287 dp = w_init(); /* reset fillbuf/read-ahead code */
288 ap = (struct tftphdr *)ackbuf;
289 file = fdopen(fd, "w");
290 convert = !strcmp(mode, "netascii");
291 n = 0;
292 block = 1;
293 amount = 0;
294 firsttrip = 1;
295 memcpy(&peer, &peeraddr, peeraddr.ss_len);
296 memset(&serv, 0, sizeof(serv));
297
298options:
299 do {
300 /* create new ACK packet */
301 if (firsttrip) {
302 size = makerequest(RRQ01, name, ap, mode);
303 firsttrip = 0;
304 } else {
305 ap->th_opcode = htons((u_short)ACK)(__uint16_t)(__builtin_constant_p((u_short)04) ? (__uint16_t)
(((__uint16_t)((u_short)04) & 0xffU) << 8 | ((__uint16_t
)((u_short)04) & 0xff00U) >> 8) : __swap16md((u_short
)04))
;
306 ap->th_blockth_u.tu_block = htons(block)(__uint16_t)(__builtin_constant_p(block) ? (__uint16_t)(((__uint16_t
)(block) & 0xffU) << 8 | ((__uint16_t)(block) &
0xff00U) >> 8) : __swap16md(block))
;
307 size = 4;
308 block++;
309 }
310
311 /* send ACK to server and wait for server data */
312 for (timeouts = 0, error = 0; !intrflag;) {
313 if (timeouts >= maxtimeout) {
314 printtimeout();
315 goto abort;
316 }
317
318 if (!error) {
319 if (trace)
320 tpacket("sent", ap, size);
321 if (sendto(f, ackbuf, size, 0,
322 (struct sockaddr *)&peer,
323 peer.ss_len) != size) {
324 warn("sendto");
325 goto abort;
326 }
327 write_behind(file, convert);
328 }
329 error = 0;
330
331 pfd[0].fd = f;
332 pfd[0].events = POLLIN0x0001;
333 nfds = poll(pfd, 1, rexmtval * 1000);
334 if (nfds == 0) {
335 timeouts += rexmtval;
336 continue;
337 }
338 if (nfds == -1) {
339 error = 1;
340 if (errno(*__errno()) == EINTR4)
341 continue;
342 warn("poll");
343 goto abort;
344 }
345 fromlen = sizeof(from);
346 n = recvfrom(f, dp, packet_size, 0,
347 (struct sockaddr *)&from, &fromlen);
348 if (n == 0) {
349 warn("recvfrom");
350 goto abort;
351 }
352 if (n == -1) {
353 error = 1;
354 if (errno(*__errno()) == EINTR4)
355 continue;
356 warn("recvfrom");
357 goto abort;
358 }
359 if (!serv.ss_family)
360 serv = from;
361 else if (!cmpport((struct sockaddr *)&serv,
362 (struct sockaddr *)&from)) {
363 warn("server port mismatch");
364 goto abort;
365 }
366 peer = from;
367 if (trace)
368 tpacket("received", dp, n);
369
370 dp->th_opcode = ntohs(dp->th_opcode)(__uint16_t)(__builtin_constant_p(dp->th_opcode) ? (__uint16_t
)(((__uint16_t)(dp->th_opcode) & 0xffU) << 8 | (
(__uint16_t)(dp->th_opcode) & 0xff00U) >> 8) : __swap16md
(dp->th_opcode))
;
371
372 if (dp->th_opcode == OACK06) {
373 oack(dp, n, 0);
374 block = 0;
375 goto options;
376 }
377
378 dp->th_blockth_u.tu_block = ntohs(dp->th_block)(__uint16_t)(__builtin_constant_p(dp->th_u.tu_block) ? (__uint16_t
)(((__uint16_t)(dp->th_u.tu_block) & 0xffU) << 8
| ((__uint16_t)(dp->th_u.tu_block) & 0xff00U) >>
8) : __swap16md(dp->th_u.tu_block))
;
379
380 if (dp->th_opcode == ERROR05) {
381 printf("Error code %d: %s\n",
382 dp->th_codeth_u.tu_code, dp->th_msgth_data);
383 goto abort;
384 }
385 if (dp->th_opcode == DATA03) {
386 int j;
387 if (dp->th_blockth_u.tu_block == block)
388 break;
389 /* re-synchronize with other side */
390 j = synchnet(f);
391 if (j && trace)
392 printf("discarded %d packets\n", j);
393 if (dp->th_blockth_u.tu_block == (block - 1))
394 continue;
395 }
396 error = 1; /* received packet does not match */
397 }
398
399 /* write data to file */
400 size = writeit(file, &dp, n - 4, convert);
401 if (size < 0) {
402 nak(errno(*__errno()) + 100, (struct sockaddr *)&peer);
403 break;
404 }
405 amount += size;
406 } while (size == segment_size && !intrflag);
407
408abort:
409 /* ok to ack, since user has seen err msg */
410 ap->th_opcode = htons((u_short)ACK)(__uint16_t)(__builtin_constant_p((u_short)04) ? (__uint16_t)
(((__uint16_t)((u_short)04) & 0xffU) << 8 | ((__uint16_t
)((u_short)04) & 0xff00U) >> 8) : __swap16md((u_short
)04))
;
411 ap->th_blockth_u.tu_block = htons(block)(__uint16_t)(__builtin_constant_p(block) ? (__uint16_t)(((__uint16_t
)(block) & 0xffU) << 8 | ((__uint16_t)(block) &
0xff00U) >> 8) : __swap16md(block))
;
412 (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer,
413 peer.ss_len);
414 write_behind(file, convert); /* flush last buffer */
415
416 fclose(file);
417 stopclock();
418 if (amount > 0) {
419 if (intrflag)
420 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
421 printstats("Received", amount);
422 }
423}
424
425static int
426cmpport(struct sockaddr *sa, struct sockaddr *sb)
427{
428 char a[NI_MAXSERV32], b[NI_MAXSERV32];
429 if (getnameinfo(sa, sa->sa_len, NULL((void*)0), 0, a, sizeof(a), NI_NUMERICSERV2))
430 return (0);
431 if (getnameinfo(sb, sb->sa_len, NULL((void*)0), 0, b, sizeof(b), NI_NUMERICSERV2))
432 return (0);
433 if (strcmp(a, b) != 0)
434 return (0);
435
436 return (1);
437}
438
439static int
440makerequest(int request, const char *name, struct tftphdr *tp,
441 const char *mode)
442{
443 char *cp;
444 int len, pktlen;
445 off_t fsize = 0;
446 struct stat st;
447
448 tp->th_opcode = htons((u_short)request)(__uint16_t)(__builtin_constant_p((u_short)request) ? (__uint16_t
)(((__uint16_t)((u_short)request) & 0xffU) << 8 | (
(__uint16_t)((u_short)request) & 0xff00U) >> 8) : __swap16md
((u_short)request))
;
449 cp = tp->th_stuffth_u.tu_stuff;
450 pktlen = packet_size - offsetof(struct tftphdr, th_stuff)__builtin_offsetof(struct tftphdr, th_u.tu_stuff);
451 len = strlen(name) + 1;
452 strlcpy(cp, name, pktlen);
453 strlcpy(cp + len, mode, pktlen - len);
454 len += strlen(mode) + 1;
455
456 if (opt_tsize) {
457 if (request == WRQ02) {
458 stat(name, &st);
459 fsize = st.st_size;
460 }
461 len += snprintf(cp + len, pktlen - len, "%s%c%lld%c",
462 options[OPT_TSIZE].o_type, 0, fsize, 0);
463 }
464 if (opt_tout)
465 len += snprintf(cp + len, pktlen - len, "%s%c%d%c",
466 options[OPT_TIMEOUT].o_type, 0, rexmtval, 0);
467 if (opt_blksize)
468 len += snprintf(cp + len, pktlen - len, "%s%c%d%c",
469 options[OPT_BLKSIZE].o_type, 0, opt_blksize, 0);
470
471 return (cp + len - (char *)tp);
472}
473
474/*
475 * Send a nak packet (error message).
476 * Error code passed in is one of the
477 * standard TFTP codes, or a UNIX errno
478 * offset by 100.
479 */
480static void
481nak(int error, struct sockaddr *peer)
482{
483 struct errmsg *pe;
484 struct tftphdr *tp;
485 int length;
486
487 tp = (struct tftphdr *)ackbuf;
488 tp->th_opcode = htons((u_short)ERROR)(__uint16_t)(__builtin_constant_p((u_short)05) ? (__uint16_t)
(((__uint16_t)((u_short)05) & 0xffU) << 8 | ((__uint16_t
)((u_short)05) & 0xff00U) >> 8) : __swap16md((u_short
)05))
;
489 tp->th_codeth_u.tu_code = htons((u_short)error)(__uint16_t)(__builtin_constant_p((u_short)error) ? (__uint16_t
)(((__uint16_t)((u_short)error) & 0xffU) << 8 | ((__uint16_t
)((u_short)error) & 0xff00U) >> 8) : __swap16md((u_short
)error))
;
490 for (pe = errmsgs; pe->e_code >= 0; pe++)
491 if (pe->e_code == error)
492 break;
493 if (pe->e_code < 0) {
494 pe->e_msg = strerror(error - 100);
495 tp->th_codeth_u.tu_code = EUNDEF0;
496 }
497 length = strlcpy(tp->th_msgth_data, pe->e_msg, packet_size) + 5;
498 if (length > packet_size)
499 length = packet_size;
500 if (trace)
501 tpacket("sent", tp, length);
502 if (sendto(f, ackbuf, length, 0, peer,
503 peer->sa_len) != length)
504 warn("nak");
505}
506
507static void
508tpacket(const char *s, struct tftphdr *tp, int n)
509{
510 char *cp, *file;
511 static char *opcodes[] =
512 { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
513
514 u_short op = ntohs(tp->th_opcode)(__uint16_t)(__builtin_constant_p(tp->th_opcode) ? (__uint16_t
)(((__uint16_t)(tp->th_opcode) & 0xffU) << 8 | (
(__uint16_t)(tp->th_opcode) & 0xff00U) >> 8) : __swap16md
(tp->th_opcode))
;
515
516 if (op < RRQ01 || op > OACK06)
517 printf("%s opcode=%x ", s, op);
518 else
519 printf("%s %s ", s, opcodes[op]);
520
521 switch (op) {
522 case RRQ01:
523 case WRQ02:
524 n -= 2;
525 file = cp = tp->th_stuffth_u.tu_stuff;
526 cp = strchr(cp, '\0');
527 printf("<file=%s, mode=%s", file, cp + 1);
528 if (has_options)
529 oack(tp, n, 1);
530 printf(">\n");
531 break;
532 case DATA03:
533 printf("<block=%d, %d bytes>\n", ntohs(tp->th_block)(__uint16_t)(__builtin_constant_p(tp->th_u.tu_block) ? (__uint16_t
)(((__uint16_t)(tp->th_u.tu_block) & 0xffU) << 8
| ((__uint16_t)(tp->th_u.tu_block) & 0xff00U) >>
8) : __swap16md(tp->th_u.tu_block))
, n - 4);
534 break;
535 case ACK04:
536 printf("<block=%d>\n", ntohs(tp->th_block)(__uint16_t)(__builtin_constant_p(tp->th_u.tu_block) ? (__uint16_t
)(((__uint16_t)(tp->th_u.tu_block) & 0xffU) << 8
| ((__uint16_t)(tp->th_u.tu_block) & 0xff00U) >>
8) : __swap16md(tp->th_u.tu_block))
);
537 break;
538 case ERROR05:
539 printf("<code=%d, msg=%s>\n", ntohs(tp->th_code)(__uint16_t)(__builtin_constant_p(tp->th_u.tu_code) ? (__uint16_t
)(((__uint16_t)(tp->th_u.tu_code) & 0xffU) << 8 |
((__uint16_t)(tp->th_u.tu_code) & 0xff00U) >> 8
) : __swap16md(tp->th_u.tu_code))
, tp->th_msgth_data);
540 break;
541 case OACK06:
542 printf("<");
543 oack(tp, n, 1);
544 printf(">\n");
545 break;
546 }
547}
548
549static void
550startclock(void)
551{
552 clock_gettime(CLOCK_MONOTONIC3, &tstart);
553}
554
555static void
556stopclock(void)
557{
558 clock_gettime(CLOCK_MONOTONIC3, &tstop);
559}
560
561static void
562printstats(const char *direction, unsigned long amount)
563{
564 double delta;
565
566 /* compute delta in 1/10's second units */
567 delta = ((tstop.tv_sec * 10.) + (tstop.tv_nsec / 100000000)) -
568 ((tstart.tv_sec * 10.) + (tstart.tv_nsec / 100000000));
569 delta = delta / 10.; /* back to seconds */
570 printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
571 if (verbose)
572 printf(" [%.0f bits/sec]", (amount * 8.) / delta);
573 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
574}
575
576static void
577printtimeout(void)
578{
579 printf("Transfer timed out.\n");
580}
581
582static void
583oack(struct tftphdr *tp, int size, int trace)
584{
585 int i, len, off;
586 char *opt, *val;
587
588 u_short op = ntohs(tp->th_opcode)(__uint16_t)(__builtin_constant_p(tp->th_opcode) ? (__uint16_t
)(((__uint16_t)(tp->th_opcode) & 0xffU) << 8 | (
(__uint16_t)(tp->th_opcode) & 0xff00U) >> 8) : __swap16md
(tp->th_opcode))
;
589
590 opt = tp->th_u.tu_stuff;
591 val = tp->th_u.tu_stuff;
592
593 if (op == RRQ01 || op == WRQ02) {
594 len = strlen(opt) + 1;
595 opt = strchr(opt, '\0');
596 opt++;
597 len += strlen(opt) + 1;
598 opt = strchr(opt, '\0');
599 opt++;
600 val = opt;
601 off = len;
602 if (trace)
603 printf(", ");
604 } else
605 off = 2;
606
607 for (i = off, len = 0; i < size - 1; i++) {
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'
608 if (*val != '\0') {
609 val++;
610 continue;
611 }
612 /* got option and value */
613 val++;
614 if (trace)
615 printf("%s=%s", opt, val);
616 else
617 if (oack_set(opt, val) == -1)
618 break;
619 len = strlen(val) + 1;
620 val += len;
621 opt = val;
622 i += len;
623 if (trace && i < size - 1)
624 printf(", ");
625 }
626}
627
628int
629oack_set(const char *option, const char *value)
630{
631 int i, n;
632 const char *errstr;
633 struct sockaddr_storage peer;
634 memcpy(&peer, &peeraddr, peeraddr.ss_len);
635
636 for (i = 0; options[i].o_type != NULL((void*)0); i++) {
637 if (!strcasecmp(options[i].o_type, option)) {
638 if (i == OPT_TSIZE) {
639 /* XXX verify OACK response */
640 }
641 if (i == OPT_TIMEOUT) {
642 /* verify OACK response */
643 n = strtonum(value, TIMEOUT_MIN1, TIMEOUT_MAX255,
644 &errstr);
645 if (errstr || rexmtval != n ||
646 opt_tout == 0) {
647 nak(EOPTNEG8, (struct sockaddr *)&peer);
648 intrflag = 1;
649 return (-1);
650 }
651 /* OK */
652 }
653 if (i == OPT_BLKSIZE) {
654 /* verify OACK response */
655 n = strtonum(value, SEGSIZE_MIN8, SEGSIZE_MAX65464,
656 &errstr);
657 if (errstr || opt_blksize != n ||
658 opt_blksize == 0) {
659 nak(EOPTNEG8, (struct sockaddr *)&peer);
660 intrflag = 1;
661 return (-1);
662 }
663 /* OK, set option */
664 segment_size = n;
665 packet_size = segment_size + 4;
666 }
667 }
668 }
669
670 return (1);
671}