]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/tftp.c
Fix new poll() code for helper pipe. Removed CPU-spin.
[people/ms/dnsmasq.git] / src / tftp.c
CommitLineData
aff33962 1/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
832af0ba
SK
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
824af85b
SK
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
832af0ba
SK
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
824af85b 12
73a08a24
SK
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
832af0ba
SK
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_TFTP
20
8bc4cece 21static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
832af0ba
SK
22static void free_transfer(struct tftp_transfer *transfer);
23static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
1b7ecd11 24static ssize_t tftp_err_oops(char *packet, char *file);
832af0ba
SK
25static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
26static char *next(char **p, char *end);
42fb8153 27static void sanitise(char *buf);
832af0ba
SK
28
29#define OP_RRQ 1
30#define OP_WRQ 2
31#define OP_DATA 3
32#define OP_ACK 4
33#define OP_ERR 5
34#define OP_OACK 6
35
36#define ERR_NOTDEF 0
37#define ERR_FNF 1
38#define ERR_PERM 2
39#define ERR_FULL 3
40#define ERR_ILL 4
41
5aabfc78 42void tftp_request(struct listener *listen, time_t now)
832af0ba
SK
43{
44 ssize_t len;
45 char *packet = daemon->packet;
46 char *filename, *mode, *p, *end, *opt;
28866e95 47 union mysockaddr addr, peer;
832af0ba 48 struct msghdr msg;
832af0ba 49 struct iovec iov;
1f15b81d 50 struct ifreq ifr;
8bc4cece 51 int is_err = 1, if_index = 0, mtu = 0;
832af0ba 52 struct iname *tmp;
5aabfc78 53 struct tftp_transfer *transfer;
824af85b
SK
54 int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
55#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1f15b81d 56 int mtuflag = IP_PMTUDISC_DONT;
824af85b 57#endif
8ef5ada2 58 char namebuff[IF_NAMESIZE];
52d4abf2 59 char *name = NULL;
8ef5ada2
SK
60 char *prefix = daemon->tftp_prefix;
61 struct tftp_prefix *pref;
e25db1f2 62 struct all_addr addra;
2329bef5
SK
63#ifdef HAVE_IPV6
64 /* Can always get recvd interface for IPv6 */
65 int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
66#else
67 int check_dest = !option_bool(OPT_NOWILD);
68#endif
832af0ba
SK
69 union {
70 struct cmsghdr align; /* this ensures alignment */
28866e95
SK
71#ifdef HAVE_IPV6
72 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
73#endif
824af85b 74#if defined(HAVE_LINUX_NETWORK)
832af0ba 75 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
824af85b
SK
76#elif defined(HAVE_SOLARIS_NETWORK)
77 char control[CMSG_SPACE(sizeof(unsigned int))];
7622fc06 78#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
832af0ba
SK
79 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
80#endif
81 } control_u;
82
83 msg.msg_controllen = sizeof(control_u);
84 msg.msg_control = control_u.control;
85 msg.msg_flags = 0;
86 msg.msg_name = &peer;
87 msg.msg_namelen = sizeof(peer);
88 msg.msg_iov = &iov;
89 msg.msg_iovlen = 1;
90
91 iov.iov_base = packet;
92 iov.iov_len = daemon->packet_buff_sz;
93
94 /* we overwrote the buffer... */
95 daemon->srv_save = NULL;
96
97 if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
98 return;
2329bef5
SK
99
100 /* Can always get recvd interface for IPv6 */
101 if (!check_dest)
1f15b81d 102 {
52d4abf2
SK
103 if (listen->iface)
104 {
105 addr = listen->iface->addr;
106 mtu = listen->iface->mtu;
107 name = listen->iface->name;
108 }
109 else
110 {
111 /* we're listening on an address that doesn't appear on an interface,
112 ask the kernel what the socket is bound to */
113 socklen_t tcp_len = sizeof(union mysockaddr);
114 if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
115 return;
116 }
1f15b81d 117 }
1b7ecd11
SK
118 else
119 {
7622fc06 120 struct cmsghdr *cmptr;
8ef5ada2 121
28866e95
SK
122 if (msg.msg_controllen < sizeof(struct cmsghdr))
123 return;
124
125 addr.sa.sa_family = listen->family;
1b7ecd11 126
832af0ba 127#if defined(HAVE_LINUX_NETWORK)
28866e95
SK
128 if (listen->family == AF_INET)
129 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
c72daea8 130 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
28866e95
SK
131 {
132 union {
133 unsigned char *c;
134 struct in_pktinfo *p;
135 } p;
136 p.c = CMSG_DATA(cmptr);
137 addr.in.sin_addr = p.p->ipi_spec_dst;
138 if_index = p.p->ipi_ifindex;
139 }
140
141#elif defined(HAVE_SOLARIS_NETWORK)
142 if (listen->family == AF_INET)
143 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1b7ecd11 144 {
8ef5ada2
SK
145 union {
146 unsigned char *c;
28866e95
SK
147 struct in_addr *a;
148 unsigned int *i;
8ef5ada2
SK
149 } p;
150 p.c = CMSG_DATA(cmptr);
28866e95
SK
151 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
152 addr.in.sin_addr = *(p.a);
153 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
154 if_index = *(p.i);
1b7ecd11 155 }
1b7ecd11 156
7622fc06 157#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
28866e95
SK
158 if (listen->family == AF_INET)
159 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
160 {
161 union {
162 unsigned char *c;
163 struct in_addr *a;
164 struct sockaddr_dl *s;
165 } p;
166 p.c = CMSG_DATA(cmptr);
167 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
168 addr.in.sin_addr = *(p.a);
169 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
170 if_index = p.s->sdl_index;
171 }
8ef5ada2 172
28866e95
SK
173#endif
174
175#ifdef HAVE_IPV6
176 if (listen->family == AF_INET6)
177 {
178 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
c72daea8 179 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
28866e95
SK
180 {
181 union {
182 unsigned char *c;
183 struct in6_pktinfo *p;
184 } p;
185 p.c = CMSG_DATA(cmptr);
186
187 addr.in6.sin6_addr = p.p->ipi6_addr;
188 if_index = p.p->ipi6_ifindex;
189 }
190 }
832af0ba 191#endif
1b7ecd11 192
28866e95 193 if (!indextoname(listen->tftpfd, if_index, namebuff))
1b7ecd11 194 return;
8ef5ada2
SK
195
196 name = namebuff;
e25db1f2
SK
197
198 addra.addr.addr4 = addr.in.sin_addr;
28866e95
SK
199
200#ifdef HAVE_IPV6
201 if (listen->family == AF_INET6)
e25db1f2
SK
202 addra.addr.addr6 = addr.in6.sin6_addr;
203#endif
204
2937f8a0 205 if (daemon->tftp_interfaces)
3169daad 206 {
2937f8a0
SK
207 /* dedicated tftp interface list */
208 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
209 if (tmp->name && wildcard_match(tmp->name, name))
210 break;
211
212 if (!tmp)
3169daad
SK
213 return;
214 }
2937f8a0
SK
215 else
216 {
217 /* Do the same as DHCP */
218 if (!iface_check(listen->family, &addra, name, NULL))
219 {
220 if (!option_bool(OPT_CLEVERBIND))
221 enumerate_interfaces(0);
222 if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
223 !label_exception(if_index, listen->family, &addra) )
224 return;
225 }
226
8ef5ada2 227#ifdef HAVE_DHCP
2937f8a0
SK
228 /* allowed interfaces are the same as for DHCP */
229 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
230 if (tmp->name && wildcard_match(tmp->name, name))
231 return;
8ef5ada2 232#endif
2937f8a0
SK
233 }
234
316e2730 235 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
1f15b81d
SK
236 if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
237 mtu = ifr.ifr_mtu;
1b7ecd11 238 }
7aa970e2 239
52d4abf2
SK
240 if (name)
241 {
242 /* check for per-interface prefix */
243 for (pref = daemon->if_prefix; pref; pref = pref->next)
244 if (strcmp(pref->interface, name) == 0)
8bc4cece 245 prefix = pref->prefix;
52d4abf2 246 }
8ef5ada2 247
7de060b0
SK
248 if (listen->family == AF_INET)
249 {
250 addr.in.sin_port = htons(port);
832af0ba 251#ifdef HAVE_SOCKADDR_SA_LEN
7de060b0 252 addr.in.sin_len = sizeof(addr.in);
832af0ba 253#endif
7de060b0 254 }
28866e95
SK
255#ifdef HAVE_IPV6
256 else
257 {
258 addr.in6.sin6_port = htons(port);
259 addr.in6.sin6_flowinfo = 0;
7de060b0
SK
260 addr.in6.sin6_scope_id = 0;
261#ifdef HAVE_SOCKADDR_SA_LEN
262 addr.in6.sin6_len = sizeof(addr.in6);
263#endif
28866e95
SK
264 }
265#endif
266
5aabfc78 267 if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
832af0ba
SK
268 return;
269
28866e95 270 if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
832af0ba
SK
271 {
272 free(transfer);
273 return;
274 }
275
276 transfer->peer = peer;
5aabfc78 277 transfer->timeout = now + 2;
832af0ba
SK
278 transfer->backoff = 1;
279 transfer->block = 1;
280 transfer->blocksize = 512;
9e038946 281 transfer->offset = 0;
832af0ba
SK
282 transfer->file = NULL;
283 transfer->opt_blocksize = transfer->opt_transize = 0;
9e038946 284 transfer->netascii = transfer->carrylf = 0;
28866e95 285
c72daea8 286 prettyprint_addr(&peer, daemon->addrbuff);
28866e95 287
824af85b
SK
288 /* if we have a nailed-down range, iterate until we find a free one. */
289 while (1)
832af0ba 290 {
7de060b0 291 if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
824af85b 292#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
c72daea8 293 setsockopt(transfer->sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
824af85b
SK
294#endif
295 !fix_fd(transfer->sockfd))
296 {
297 if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
298 {
299 if (++port <= daemon->end_tftp_port)
300 {
28866e95
SK
301 if (listen->family == AF_INET)
302 addr.in.sin_port = htons(port);
303#ifdef HAVE_IPV6
304 else
305 addr.in6.sin6_port = htons(port);
306#endif
824af85b
SK
307 continue;
308 }
7622fc06 309 my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
824af85b
SK
310 }
311 free_transfer(transfer);
312 return;
313 }
314 break;
832af0ba 315 }
824af85b 316
832af0ba
SK
317 p = packet + 2;
318 end = packet + len;
319
320 if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
321 !(filename = next(&p, end)) ||
322 !(mode = next(&p, end)) ||
9e038946 323 (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
6a69ab5e
SK
324 {
325 len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
326 is_err = 1;
327 }
832af0ba
SK
328 else
329 {
9e038946
SK
330 if (strcasecmp(mode, "netascii") == 0)
331 transfer->netascii = 1;
332
832af0ba
SK
333 while ((opt = next(&p, end)))
334 {
77e94da7 335 if (strcasecmp(opt, "blksize") == 0)
832af0ba 336 {
8bc4cece 337 if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
77e94da7
SK
338 {
339 transfer->blocksize = atoi(opt);
340 if (transfer->blocksize < 1)
341 transfer->blocksize = 1;
342 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
343 transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
1f15b81d
SK
344 /* 32 bytes for IP, UDP and TFTP headers */
345 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
346 transfer->blocksize = (unsigned)mtu - 32;
77e94da7
SK
347 transfer->opt_blocksize = 1;
348 transfer->block = 0;
349 }
832af0ba 350 }
77e94da7 351 else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
832af0ba
SK
352 {
353 transfer->opt_transize = 1;
354 transfer->block = 0;
355 }
356 }
357
1f15b81d 358 /* cope with backslashes from windows boxen. */
61ce600b
SK
359 for (p = filename; *p; p++)
360 if (*p == '\\')
361 *p = '/';
362 else if (option_bool(OPT_TFTP_LC))
363 *p = tolower(*p);
364
f2621c7f 365 strcpy(daemon->namebuff, "/");
8ef5ada2 366 if (prefix)
832af0ba 367 {
8ef5ada2 368 if (prefix[0] == '/')
f2621c7f 369 daemon->namebuff[0] = 0;
8ef5ada2
SK
370 strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
371 if (prefix[strlen(prefix)-1] != '/')
77e94da7 372 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
5aabfc78 373
8bc4cece 374 if (option_bool(OPT_TFTP_APREF))
5aabfc78
SK
375 {
376 size_t oldlen = strlen(daemon->namebuff);
377 struct stat statbuf;
378
c72daea8 379 strncat(daemon->namebuff, daemon->addrbuff, (MAXDNAME-1) - strlen(daemon->namebuff));
77e94da7 380 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
5aabfc78
SK
381
382 /* remove unique-directory if it doesn't exist */
383 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
384 daemon->namebuff[oldlen] = 0;
385 }
386
f2621c7f
SK
387 /* Absolute pathnames OK if they match prefix */
388 if (filename[0] == '/')
389 {
390 if (strstr(filename, daemon->namebuff) == filename)
391 daemon->namebuff[0] = 0;
392 else
393 filename++;
394 }
832af0ba 395 }
f2621c7f 396 else if (filename[0] == '/')
832af0ba 397 daemon->namebuff[0] = 0;
77e94da7 398 strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
832af0ba 399
5aabfc78 400 /* check permissions and open file */
8bc4cece 401 if ((transfer->file = check_tftp_fileperm(&len, prefix)))
832af0ba 402 {
1b7ecd11
SK
403 if ((len = get_block(packet, transfer)) == -1)
404 len = tftp_err_oops(packet, daemon->namebuff);
405 else
406 is_err = 0;
832af0ba
SK
407 }
408 }
409
410 while (sendto(transfer->sockfd, packet, len, 0,
04363607 411 (struct sockaddr *)&peer, sa_len(&peer)) == -1 && errno == EINTR);
832af0ba
SK
412
413 if (is_err)
414 free_transfer(transfer);
415 else
416 {
832af0ba
SK
417 transfer->next = daemon->tftp_trans;
418 daemon->tftp_trans = transfer;
419 }
420}
1b7ecd11 421
8bc4cece 422static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
1b7ecd11
SK
423{
424 char *packet = daemon->packet, *namebuff = daemon->namebuff;
425 struct tftp_file *file;
5aabfc78 426 struct tftp_transfer *t;
1b7ecd11
SK
427 uid_t uid = geteuid();
428 struct stat statbuf;
5aabfc78 429 int fd = -1;
1b7ecd11
SK
430
431 /* trick to ban moving out of the subtree */
8ef5ada2 432 if (prefix && strstr(namebuff, "/../"))
5aabfc78
SK
433 goto perm;
434
435 if ((fd = open(namebuff, O_RDONLY)) == -1)
1b7ecd11 436 {
5aabfc78
SK
437 if (errno == ENOENT)
438 {
439 *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
440 return NULL;
441 }
1b7ecd11
SK
442 else if (errno == EACCES)
443 goto perm;
444 else
445 goto oops;
446 }
5aabfc78
SK
447
448 /* stat the file descriptor to avoid stat->open races */
449 if (fstat(fd, &statbuf) == -1)
450 goto oops;
451
1b7ecd11
SK
452 /* running as root, must be world-readable */
453 if (uid == 0)
454 {
455 if (!(statbuf.st_mode & S_IROTH))
5aabfc78 456 goto perm;
1b7ecd11
SK
457 }
458 /* in secure mode, must be owned by user running dnsmasq */
8bc4cece 459 else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
5aabfc78
SK
460 goto perm;
461
462 /* If we're doing many tranfers from the same file, only
463 open it once this saves lots of file descriptors
464 when mass-booting a big cluster, for instance.
465 Be conservative and only share when inode and name match
466 this keeps error messages sane. */
467 for (t = daemon->tftp_trans; t; t = t->next)
468 if (t->file->dev == statbuf.st_dev &&
469 t->file->inode == statbuf.st_ino &&
470 strcmp(t->file->filename, namebuff) == 0)
471 {
472 close(fd);
473 t->file->refcount++;
474 return t->file;
475 }
476
477 if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
1b7ecd11
SK
478 {
479 errno = ENOMEM;
480 goto oops;
481 }
482
5aabfc78 483 file->fd = fd;
1b7ecd11 484 file->size = statbuf.st_size;
5aabfc78
SK
485 file->dev = statbuf.st_dev;
486 file->inode = statbuf.st_ino;
1b7ecd11
SK
487 file->refcount = 1;
488 strcpy(file->filename, namebuff);
489 return file;
5aabfc78 490
1b7ecd11 491 perm:
5aabfc78 492 errno = EACCES;
1b7ecd11 493 *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
5aabfc78
SK
494 if (fd != -1)
495 close(fd);
1b7ecd11
SK
496 return NULL;
497
5aabfc78 498 oops:
1b7ecd11 499 *len = tftp_err_oops(packet, namebuff);
5aabfc78
SK
500 if (fd != -1)
501 close(fd);
1b7ecd11
SK
502 return NULL;
503}
504
b842bc97 505void check_tftp_listeners(time_t now)
832af0ba
SK
506{
507 struct tftp_transfer *transfer, *tmp, **up;
508 ssize_t len;
509
510 struct ack {
511 unsigned short op, block;
512 } *mess = (struct ack *)daemon->packet;
513
514 /* Check for activity on any existing transfers */
515 for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
516 {
517 tmp = transfer->next;
518
6a69ab5e
SK
519 prettyprint_addr(&transfer->peer, daemon->addrbuff);
520
b842bc97 521 if (poll_check(transfer->sockfd, POLLIN))
832af0ba
SK
522 {
523 /* we overwrote the buffer... */
524 daemon->srv_save = NULL;
525
526 if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
527 {
528 if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
529 {
530 /* Got ack, ensure we take the (re)transmit path */
531 transfer->timeout = now;
532 transfer->backoff = 0;
9e038946
SK
533 if (transfer->block++ != 0)
534 transfer->offset += transfer->blocksize - transfer->expansion;
832af0ba
SK
535 }
536 else if (ntohs(mess->op) == OP_ERR)
537 {
538 char *p = daemon->packet + sizeof(struct ack);
539 char *end = daemon->packet + len;
540 char *err = next(&p, end);
28866e95 541
832af0ba
SK
542 /* Sanitise error message */
543 if (!err)
544 err = "";
545 else
7a14dfeb 546 sanitise(err);
6a69ab5e 547
316e2730 548 my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
f2621c7f 549 (int)ntohs(mess->block), err,
c72daea8 550 daemon->addrbuff);
832af0ba
SK
551
552 /* Got err, ensure we take abort */
553 transfer->timeout = now;
554 transfer->backoff = 100;
555 }
556 }
557 }
558
559 if (difftime(now, transfer->timeout) >= 0.0)
560 {
561 int endcon = 0;
562
563 /* timeout, retransmit */
5aabfc78 564 transfer->timeout += 1 + (1<<transfer->backoff);
832af0ba
SK
565
566 /* we overwrote the buffer... */
567 daemon->srv_save = NULL;
568
569 if ((len = get_block(daemon->packet, transfer)) == -1)
570 {
1b7ecd11 571 len = tftp_err_oops(daemon->packet, transfer->file->filename);
832af0ba
SK
572 endcon = 1;
573 }
42fb8153
SK
574 /* don't complain about timeout when we're awaiting the last
575 ACK, some clients never send it */
b4b93080 576 else if (++transfer->backoff > 7 && len != 0)
832af0ba 577 {
42fb8153
SK
578 endcon = 1;
579 len = 0;
832af0ba 580 }
42fb8153 581
832af0ba
SK
582 if (len != 0)
583 while(sendto(transfer->sockfd, daemon->packet, len, 0,
04363607 584 (struct sockaddr *)&transfer->peer, sa_len(&transfer->peer)) == -1 && errno == EINTR);
832af0ba
SK
585
586 if (endcon || len == 0)
587 {
42fb8153
SK
588 strcpy(daemon->namebuff, transfer->file->filename);
589 sanitise(daemon->namebuff);
590 my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
832af0ba
SK
591 /* unlink */
592 *up = tmp;
231d061b
SK
593 if (endcon)
594 free_transfer(transfer);
595 else
596 {
597 /* put on queue to be sent to script and deleted */
598 transfer->next = daemon->tftp_done_trans;
599 daemon->tftp_done_trans = transfer;
600 }
832af0ba
SK
601 continue;
602 }
603 }
604
605 up = &transfer->next;
28866e95 606 }
832af0ba
SK
607}
608
609static void free_transfer(struct tftp_transfer *transfer)
610{
611 close(transfer->sockfd);
612 if (transfer->file && (--transfer->file->refcount) == 0)
613 {
614 close(transfer->file->fd);
615 free(transfer->file);
616 }
617 free(transfer);
618}
619
620static char *next(char **p, char *end)
621{
622 char *ret = *p;
623 size_t len;
624
625 if (*(end-1) != 0 ||
626 *p == end ||
627 (len = strlen(ret)) == 0)
628 return NULL;
629
630 *p += len + 1;
631 return ret;
632}
633
42fb8153
SK
634static void sanitise(char *buf)
635{
7a14dfeb
SK
636 unsigned char *q, *r;
637 for (q = r = (unsigned char *)buf; *r; r++)
11263a46 638 if (isprint((int)*r))
7a14dfeb
SK
639 *(q++) = *r;
640 *q = 0;
42fb8153 641
7a14dfeb 642}
42fb8153 643
832af0ba
SK
644static ssize_t tftp_err(int err, char *packet, char *message, char *file)
645{
646 struct errmess {
647 unsigned short op, err;
648 char message[];
649 } *mess = (struct errmess *)packet;
650 ssize_t ret = 4;
651 char *errstr = strerror(errno);
42fb8153
SK
652
653 sanitise(file);
654
832af0ba
SK
655 mess->op = htons(OP_ERR);
656 mess->err = htons(err);
657 ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
316e2730 658 my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
832af0ba
SK
659
660 return ret;
661}
662
1b7ecd11
SK
663static ssize_t tftp_err_oops(char *packet, char *file)
664{
42fb8153
SK
665 /* May have >1 refs to file, so potentially mangle a copy of the name */
666 strcpy(daemon->namebuff, file);
667 return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
1b7ecd11
SK
668}
669
832af0ba
SK
670/* return -1 for error, zero for done. */
671static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
672{
673 if (transfer->block == 0)
674 {
675 /* send OACK */
676 char *p;
677 struct oackmess {
678 unsigned short op;
679 char data[];
680 } *mess = (struct oackmess *)packet;
681
682 p = mess->data;
683 mess->op = htons(OP_OACK);
684 if (transfer->opt_blocksize)
685 {
686 p += (sprintf(p, "blksize") + 1);
687 p += (sprintf(p, "%d", transfer->blocksize) + 1);
688 }
689 if (transfer->opt_transize)
690 {
691 p += (sprintf(p,"tsize") + 1);
692 p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
693 }
694
695 return p - packet;
696 }
697 else
698 {
699 /* send data packet */
700 struct datamess {
701 unsigned short op, block;
702 unsigned char data[];
703 } *mess = (struct datamess *)packet;
704
9e038946 705 size_t size = transfer->file->size - transfer->offset;
832af0ba 706
9e038946 707 if (transfer->offset > transfer->file->size)
832af0ba
SK
708 return 0; /* finished */
709
710 if (size > transfer->blocksize)
711 size = transfer->blocksize;
712
832af0ba
SK
713 mess->op = htons(OP_DATA);
714 mess->block = htons((unsigned short)(transfer->block));
715
9e038946
SK
716 if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
717 !read_write(transfer->file->fd, mess->data, size, 1))
832af0ba 718 return -1;
9e038946
SK
719
720 transfer->expansion = 0;
721
722 /* Map '\n' to CR-LF in netascii mode */
723 if (transfer->netascii)
724 {
725 size_t i;
726 int newcarrylf;
727
728 for (i = 0, newcarrylf = 0; i < size; i++)
729 if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
730 {
7de060b0
SK
731 transfer->expansion++;
732
733 if (size != transfer->blocksize)
9e038946 734 size++; /* room in this block */
7de060b0
SK
735 else if (i == size - 1)
736 newcarrylf = 1; /* don't expand LF again if it moves to the next block */
737
9e038946
SK
738 /* make space and insert CR */
739 memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
740 mess->data[i] = '\r';
741
742 i++;
743 }
744 transfer->carrylf = newcarrylf;
745
746 }
747
748 return size + 4;
832af0ba
SK
749 }
750}
751
a9530964
SK
752
753int do_tftp_script_run(void)
754{
755 struct tftp_transfer *transfer;
756
757 if ((transfer = daemon->tftp_done_trans))
758 {
759 daemon->tftp_done_trans = transfer->next;
760#ifdef HAVE_SCRIPT
761 queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
762#endif
763 free_transfer(transfer);
764 return 1;
765 }
766
767 return 0;
768}
832af0ba 769#endif