dnsmasq: re-apply original Tomato specific code
[tomato.git] / release / src / router / dnsmasq / src / tftp.c
blob5e4a32ab3429163087b4faed24703944f8a1ac6e
1 /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
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
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
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.
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/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_TFTP
21 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
22 static void free_transfer(struct tftp_transfer *transfer);
23 static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
24 static ssize_t tftp_err_oops(char *packet, char *file);
25 static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
26 static char *next(char **p, char *end);
27 static void sanitise(char *buf);
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
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
42 void tftp_request(struct listener *listen, time_t now)
44 ssize_t len;
45 char *packet = daemon->packet;
46 char *filename, *mode, *p, *end, *opt;
47 union mysockaddr addr, peer;
48 struct msghdr msg;
49 struct iovec iov;
50 struct ifreq ifr;
51 int is_err = 1, if_index = 0, mtu = 0;
52 struct iname *tmp;
53 struct tftp_transfer *transfer;
54 int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
55 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
56 int mtuflag = IP_PMTUDISC_DONT;
57 #endif
58 char namebuff[IF_NAMESIZE];
59 char *name = NULL;
60 char *prefix = daemon->tftp_prefix;
61 struct tftp_prefix *pref;
62 struct all_addr addra;
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
69 union {
70 struct cmsghdr align; /* this ensures alignment */
71 #ifdef HAVE_IPV6
72 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
73 #endif
74 #if defined(HAVE_LINUX_NETWORK)
75 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
76 #elif defined(HAVE_SOLARIS_NETWORK)
77 char control[CMSG_SPACE(sizeof(unsigned int))];
78 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
79 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
80 #endif
81 } control_u;
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;
91 iov.iov_base = packet;
92 iov.iov_len = daemon->packet_buff_sz;
94 /* we overwrote the buffer... */
95 daemon->srv_save = NULL;
97 if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
98 return;
100 /* Can always get recvd interface for IPv6 */
101 if (!check_dest)
103 if (listen->iface)
105 addr = listen->iface->addr;
106 name = listen->iface->name;
107 mtu = listen->iface->mtu;
108 if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
109 mtu = daemon->tftp_mtu;
111 else
113 /* we're listening on an address that doesn't appear on an interface,
114 ask the kernel what the socket is bound to */
115 socklen_t tcp_len = sizeof(union mysockaddr);
116 if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
117 return;
120 else
122 struct cmsghdr *cmptr;
124 if (msg.msg_controllen < sizeof(struct cmsghdr))
125 return;
127 addr.sa.sa_family = listen->family;
129 #if defined(HAVE_LINUX_NETWORK)
130 if (listen->family == AF_INET)
131 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
132 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
134 union {
135 unsigned char *c;
136 struct in_pktinfo *p;
137 } p;
138 p.c = CMSG_DATA(cmptr);
139 addr.in.sin_addr = p.p->ipi_spec_dst;
140 if_index = p.p->ipi_ifindex;
143 #elif defined(HAVE_SOLARIS_NETWORK)
144 if (listen->family == AF_INET)
145 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
147 union {
148 unsigned char *c;
149 struct in_addr *a;
150 unsigned int *i;
151 } p;
152 p.c = CMSG_DATA(cmptr);
153 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
154 addr.in.sin_addr = *(p.a);
155 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
156 if_index = *(p.i);
159 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
160 if (listen->family == AF_INET)
161 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
163 union {
164 unsigned char *c;
165 struct in_addr *a;
166 struct sockaddr_dl *s;
167 } p;
168 p.c = CMSG_DATA(cmptr);
169 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
170 addr.in.sin_addr = *(p.a);
171 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
172 if_index = p.s->sdl_index;
175 #endif
177 #ifdef HAVE_IPV6
178 if (listen->family == AF_INET6)
180 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
181 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
183 union {
184 unsigned char *c;
185 struct in6_pktinfo *p;
186 } p;
187 p.c = CMSG_DATA(cmptr);
189 addr.in6.sin6_addr = p.p->ipi6_addr;
190 if_index = p.p->ipi6_ifindex;
193 #endif
195 if (!indextoname(listen->tftpfd, if_index, namebuff))
196 return;
198 name = namebuff;
200 addra.addr.addr4 = addr.in.sin_addr;
202 #ifdef HAVE_IPV6
203 if (listen->family == AF_INET6)
204 addra.addr.addr6 = addr.in6.sin6_addr;
205 #endif
207 if (daemon->tftp_interfaces)
209 /* dedicated tftp interface list */
210 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
211 if (tmp->name && wildcard_match(tmp->name, name))
212 break;
214 if (!tmp)
215 return;
217 else
219 /* Do the same as DHCP */
220 if (!iface_check(listen->family, &addra, name, NULL))
222 if (!option_bool(OPT_CLEVERBIND))
223 enumerate_interfaces(0);
224 if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
225 !label_exception(if_index, listen->family, &addra) )
226 return;
229 #ifdef HAVE_DHCP
230 /* allowed interfaces are the same as for DHCP */
231 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
232 if (tmp->name && wildcard_match(tmp->name, name))
233 return;
234 #endif
237 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
238 if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
240 mtu = ifr.ifr_mtu;
241 if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
242 mtu = daemon->tftp_mtu;
246 /* Failed to get interface mtu - can use configured value. */
247 if (mtu == 0)
248 mtu = daemon->tftp_mtu;
250 if (name)
252 /* check for per-interface prefix */
253 for (pref = daemon->if_prefix; pref; pref = pref->next)
254 if (strcmp(pref->interface, name) == 0)
255 prefix = pref->prefix;
258 if (listen->family == AF_INET)
260 addr.in.sin_port = htons(port);
261 #ifdef HAVE_SOCKADDR_SA_LEN
262 addr.in.sin_len = sizeof(addr.in);
263 #endif
265 #ifdef HAVE_IPV6
266 else
268 addr.in6.sin6_port = htons(port);
269 addr.in6.sin6_flowinfo = 0;
270 addr.in6.sin6_scope_id = 0;
271 #ifdef HAVE_SOCKADDR_SA_LEN
272 addr.in6.sin6_len = sizeof(addr.in6);
273 #endif
275 #endif
277 if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
278 return;
280 if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
282 free(transfer);
283 return;
286 transfer->peer = peer;
287 transfer->timeout = now + 2;
288 transfer->backoff = 1;
289 transfer->block = 1;
290 transfer->blocksize = 512;
291 transfer->offset = 0;
292 transfer->file = NULL;
293 transfer->opt_blocksize = transfer->opt_transize = 0;
294 transfer->netascii = transfer->carrylf = 0;
296 prettyprint_addr(&peer, daemon->addrbuff);
298 /* if we have a nailed-down range, iterate until we find a free one. */
299 while (1)
301 if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
302 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
303 setsockopt(transfer->sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
304 #endif
305 !fix_fd(transfer->sockfd))
307 if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
309 if (++port <= daemon->end_tftp_port)
311 if (listen->family == AF_INET)
312 addr.in.sin_port = htons(port);
313 #ifdef HAVE_IPV6
314 else
315 addr.in6.sin6_port = htons(port);
316 #endif
317 continue;
319 my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
321 free_transfer(transfer);
322 return;
324 break;
327 p = packet + 2;
328 end = packet + len;
330 if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
331 !(filename = next(&p, end)) ||
332 !(mode = next(&p, end)) ||
333 (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
335 len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
336 is_err = 1;
338 else
340 if (strcasecmp(mode, "netascii") == 0)
341 transfer->netascii = 1;
343 while ((opt = next(&p, end)))
345 if (strcasecmp(opt, "blksize") == 0)
347 if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
349 /* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
350 int overhead = (listen->family == AF_INET) ? 32 : 52;
351 transfer->blocksize = atoi(opt);
352 if (transfer->blocksize < 1)
353 transfer->blocksize = 1;
354 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
355 transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
356 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
357 transfer->blocksize = (unsigned)mtu - overhead;
358 transfer->opt_blocksize = 1;
359 transfer->block = 0;
362 else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
364 transfer->opt_transize = 1;
365 transfer->block = 0;
369 /* cope with backslashes from windows boxen. */
370 for (p = filename; *p; p++)
371 if (*p == '\\')
372 *p = '/';
373 else if (option_bool(OPT_TFTP_LC))
374 *p = tolower(*p);
376 strcpy(daemon->namebuff, "/");
377 if (prefix)
379 if (prefix[0] == '/')
380 daemon->namebuff[0] = 0;
381 strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
382 if (prefix[strlen(prefix)-1] != '/')
383 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
385 if (option_bool(OPT_TFTP_APREF))
387 size_t oldlen = strlen(daemon->namebuff);
388 struct stat statbuf;
390 strncat(daemon->namebuff, daemon->addrbuff, (MAXDNAME-1) - strlen(daemon->namebuff));
391 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
393 /* remove unique-directory if it doesn't exist */
394 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
395 daemon->namebuff[oldlen] = 0;
398 /* Absolute pathnames OK if they match prefix */
399 if (filename[0] == '/')
401 if (strstr(filename, daemon->namebuff) == filename)
402 daemon->namebuff[0] = 0;
403 else
404 filename++;
407 else if (filename[0] == '/')
408 daemon->namebuff[0] = 0;
409 strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
411 /* check permissions and open file */
412 if ((transfer->file = check_tftp_fileperm(&len, prefix)))
414 if ((len = get_block(packet, transfer)) == -1)
415 len = tftp_err_oops(packet, daemon->namebuff);
416 else
417 is_err = 0;
421 while (sendto(transfer->sockfd, packet, len, 0,
422 (struct sockaddr *)&peer, sa_len(&peer)) == -1 && errno == EINTR);
424 if (is_err)
425 free_transfer(transfer);
426 else
428 transfer->next = daemon->tftp_trans;
429 daemon->tftp_trans = transfer;
433 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
435 char *packet = daemon->packet, *namebuff = daemon->namebuff;
436 struct tftp_file *file;
437 struct tftp_transfer *t;
438 uid_t uid = geteuid();
439 struct stat statbuf;
440 int fd = -1;
442 /* trick to ban moving out of the subtree */
443 if (prefix && strstr(namebuff, "/../"))
444 goto perm;
446 if ((fd = open(namebuff, O_RDONLY)) == -1)
448 if (errno == ENOENT)
450 *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
451 return NULL;
453 else if (errno == EACCES)
454 goto perm;
455 else
456 goto oops;
459 /* stat the file descriptor to avoid stat->open races */
460 if (fstat(fd, &statbuf) == -1)
461 goto oops;
463 /* running as root, must be world-readable */
464 if (uid == 0)
466 if (!(statbuf.st_mode & S_IROTH))
467 goto perm;
469 /* in secure mode, must be owned by user running dnsmasq */
470 else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
471 goto perm;
473 /* If we're doing many tranfers from the same file, only
474 open it once this saves lots of file descriptors
475 when mass-booting a big cluster, for instance.
476 Be conservative and only share when inode and name match
477 this keeps error messages sane. */
478 for (t = daemon->tftp_trans; t; t = t->next)
479 if (t->file->dev == statbuf.st_dev &&
480 t->file->inode == statbuf.st_ino &&
481 strcmp(t->file->filename, namebuff) == 0)
483 close(fd);
484 t->file->refcount++;
485 return t->file;
488 if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
490 errno = ENOMEM;
491 goto oops;
494 file->fd = fd;
495 file->size = statbuf.st_size;
496 file->dev = statbuf.st_dev;
497 file->inode = statbuf.st_ino;
498 file->refcount = 1;
499 strcpy(file->filename, namebuff);
500 return file;
502 perm:
503 errno = EACCES;
504 *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
505 if (fd != -1)
506 close(fd);
507 return NULL;
509 oops:
510 *len = tftp_err_oops(packet, namebuff);
511 if (fd != -1)
512 close(fd);
513 return NULL;
516 void check_tftp_listeners(time_t now)
518 struct tftp_transfer *transfer, *tmp, **up;
519 ssize_t len;
521 struct ack {
522 unsigned short op, block;
523 } *mess = (struct ack *)daemon->packet;
525 /* Check for activity on any existing transfers */
526 for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
528 tmp = transfer->next;
530 prettyprint_addr(&transfer->peer, daemon->addrbuff);
532 if (poll_check(transfer->sockfd, POLLIN))
534 /* we overwrote the buffer... */
535 daemon->srv_save = NULL;
537 if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
539 if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
541 /* Got ack, ensure we take the (re)transmit path */
542 transfer->timeout = now;
543 transfer->backoff = 0;
544 if (transfer->block++ != 0)
545 transfer->offset += transfer->blocksize - transfer->expansion;
547 else if (ntohs(mess->op) == OP_ERR)
549 char *p = daemon->packet + sizeof(struct ack);
550 char *end = daemon->packet + len;
551 char *err = next(&p, end);
553 /* Sanitise error message */
554 if (!err)
555 err = "";
556 else
557 sanitise(err);
559 my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
560 (int)ntohs(mess->block), err,
561 daemon->addrbuff);
563 /* Got err, ensure we take abort */
564 transfer->timeout = now;
565 transfer->backoff = 100;
570 if (difftime(now, transfer->timeout) >= 0.0)
572 int endcon = 0;
574 /* timeout, retransmit */
575 transfer->timeout += 1 + (1<<transfer->backoff);
577 /* we overwrote the buffer... */
578 daemon->srv_save = NULL;
580 if ((len = get_block(daemon->packet, transfer)) == -1)
582 len = tftp_err_oops(daemon->packet, transfer->file->filename);
583 endcon = 1;
585 /* don't complain about timeout when we're awaiting the last
586 ACK, some clients never send it */
587 else if (++transfer->backoff > 7 && len != 0)
589 endcon = 1;
590 len = 0;
593 if (len != 0)
594 while(sendto(transfer->sockfd, daemon->packet, len, 0,
595 (struct sockaddr *)&transfer->peer, sa_len(&transfer->peer)) == -1 && errno == EINTR);
597 if (endcon || len == 0)
599 strcpy(daemon->namebuff, transfer->file->filename);
600 sanitise(daemon->namebuff);
601 my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
602 /* unlink */
603 *up = tmp;
604 if (endcon)
605 free_transfer(transfer);
606 else
608 /* put on queue to be sent to script and deleted */
609 transfer->next = daemon->tftp_done_trans;
610 daemon->tftp_done_trans = transfer;
612 continue;
616 up = &transfer->next;
620 static void free_transfer(struct tftp_transfer *transfer)
622 close(transfer->sockfd);
623 if (transfer->file && (--transfer->file->refcount) == 0)
625 close(transfer->file->fd);
626 free(transfer->file);
628 free(transfer);
631 static char *next(char **p, char *end)
633 char *ret = *p;
634 size_t len;
636 if (*(end-1) != 0 ||
637 *p == end ||
638 (len = strlen(ret)) == 0)
639 return NULL;
641 *p += len + 1;
642 return ret;
645 static void sanitise(char *buf)
647 unsigned char *q, *r;
648 for (q = r = (unsigned char *)buf; *r; r++)
649 if (isprint((int)*r))
650 *(q++) = *r;
651 *q = 0;
655 static ssize_t tftp_err(int err, char *packet, char *message, char *file)
657 struct errmess {
658 unsigned short op, err;
659 char message[];
660 } *mess = (struct errmess *)packet;
661 ssize_t ret = 4;
662 char *errstr = strerror(errno);
664 sanitise(file);
666 mess->op = htons(OP_ERR);
667 mess->err = htons(err);
668 ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
669 my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
671 return ret;
674 static ssize_t tftp_err_oops(char *packet, char *file)
676 /* May have >1 refs to file, so potentially mangle a copy of the name */
677 strcpy(daemon->namebuff, file);
678 return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
681 /* return -1 for error, zero for done. */
682 static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
684 if (transfer->block == 0)
686 /* send OACK */
687 char *p;
688 struct oackmess {
689 unsigned short op;
690 char data[];
691 } *mess = (struct oackmess *)packet;
693 p = mess->data;
694 mess->op = htons(OP_OACK);
695 if (transfer->opt_blocksize)
697 p += (sprintf(p, "blksize") + 1);
698 p += (sprintf(p, "%d", transfer->blocksize) + 1);
700 if (transfer->opt_transize)
702 p += (sprintf(p,"tsize") + 1);
703 p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
706 return p - packet;
708 else
710 /* send data packet */
711 struct datamess {
712 unsigned short op, block;
713 unsigned char data[];
714 } *mess = (struct datamess *)packet;
716 size_t size = transfer->file->size - transfer->offset;
718 if (transfer->offset > transfer->file->size)
719 return 0; /* finished */
721 if (size > transfer->blocksize)
722 size = transfer->blocksize;
724 mess->op = htons(OP_DATA);
725 mess->block = htons((unsigned short)(transfer->block));
727 if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
728 !read_write(transfer->file->fd, mess->data, size, 1))
729 return -1;
731 transfer->expansion = 0;
733 /* Map '\n' to CR-LF in netascii mode */
734 if (transfer->netascii)
736 size_t i;
737 int newcarrylf;
739 for (i = 0, newcarrylf = 0; i < size; i++)
740 if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
742 transfer->expansion++;
744 if (size != transfer->blocksize)
745 size++; /* room in this block */
746 else if (i == size - 1)
747 newcarrylf = 1; /* don't expand LF again if it moves to the next block */
749 /* make space and insert CR */
750 memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
751 mess->data[i] = '\r';
753 i++;
755 transfer->carrylf = newcarrylf;
759 return size + 4;
764 int do_tftp_script_run(void)
766 struct tftp_transfer *transfer;
768 if ((transfer = daemon->tftp_done_trans))
770 daemon->tftp_done_trans = transfer->next;
771 #ifdef HAVE_SCRIPT
772 queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
773 #endif
774 free_transfer(transfer);
775 return 1;
778 return 0;
780 #endif