"Fossies" - the Fresh Open Source Software Archive

Member "dnsmasq-2.85/src/tftp.c" (7 Apr 2021, 24432 Bytes) of package /linux/misc/dns/dnsmasq-2.85.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tftp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.84_vs_2.85.

    1 /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
    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
    5    the Free Software Foundation; version 2 dated June, 1991, or
    6    (at your option) version 3 dated 29 June, 2007.
    7  
    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.
   12      
   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/>.
   15 */
   16 
   17 #include "dnsmasq.h"
   18 
   19 #ifdef HAVE_TFTP
   20 
   21 static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len);
   22 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
   23 static void free_transfer(struct tftp_transfer *transfer);
   24 static ssize_t tftp_err(int err, char *packet, char *message, char *file);
   25 static ssize_t tftp_err_oops(char *packet, const char *file);
   26 static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
   27 static char *next(char **p, char *end);
   28 static void sanitise(char *buf);
   29 
   30 #define OP_RRQ  1
   31 #define OP_WRQ  2
   32 #define OP_DATA 3
   33 #define OP_ACK  4
   34 #define OP_ERR  5
   35 #define OP_OACK 6
   36 
   37 #define ERR_NOTDEF 0
   38 #define ERR_FNF    1
   39 #define ERR_PERM   2
   40 #define ERR_FULL   3
   41 #define ERR_ILL    4
   42 #define ERR_TID    5
   43 
   44 void tftp_request(struct listener *listen, time_t now)
   45 {
   46   ssize_t len;
   47   char *packet = daemon->packet;
   48   char *filename, *mode, *p, *end, *opt;
   49   union mysockaddr addr, peer;
   50   struct msghdr msg;
   51   struct iovec iov;
   52   struct ifreq ifr;
   53   int is_err = 1, if_index = 0, mtu = 0;
   54   struct iname *tmp;
   55   struct tftp_transfer *transfer = NULL, **up;
   56   int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
   57 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
   58   int mtuflag = IP_PMTUDISC_DONT;
   59 #endif
   60   char namebuff[IF_NAMESIZE];
   61   char *name = NULL;
   62   char *prefix = daemon->tftp_prefix;
   63   struct tftp_prefix *pref;
   64   union all_addr addra;
   65   int family = listen->addr.sa.sa_family;
   66   /* Can always get recvd interface for IPv6 */
   67   int check_dest = !option_bool(OPT_NOWILD) || family == AF_INET6;
   68   union {
   69     struct cmsghdr align; /* this ensures alignment */
   70     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
   71 #if defined(HAVE_LINUX_NETWORK)
   72     char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
   73 #elif defined(HAVE_SOLARIS_NETWORK)
   74     char control[CMSG_SPACE(sizeof(struct in_addr)) +
   75          CMSG_SPACE(sizeof(unsigned int))];
   76 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
   77     char control[CMSG_SPACE(sizeof(struct in_addr)) +
   78          CMSG_SPACE(sizeof(struct sockaddr_dl))];
   79 #endif
   80   } control_u; 
   81 
   82   msg.msg_controllen = sizeof(control_u);
   83   msg.msg_control = control_u.control;
   84   msg.msg_flags = 0;
   85   msg.msg_name = &peer;
   86   msg.msg_namelen = sizeof(peer);
   87   msg.msg_iov = &iov;
   88   msg.msg_iovlen = 1;
   89 
   90   iov.iov_base = packet;
   91   iov.iov_len = daemon->packet_buff_sz;
   92 
   93   /* we overwrote the buffer... */
   94   daemon->srv_save = NULL;
   95 
   96   if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
   97     return;
   98   
   99   /* Can always get recvd interface for IPv6 */
  100   if (!check_dest)
  101     {
  102       if (listen->iface)
  103     {
  104       addr = listen->iface->addr;
  105       name = listen->iface->name;
  106       mtu = listen->iface->mtu;
  107       if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
  108         mtu = daemon->tftp_mtu;
  109     }
  110       else
  111     {
  112       /* we're listening on an address that doesn't appear on an interface,
  113          ask the kernel what the socket is bound to */
  114       socklen_t tcp_len = sizeof(union mysockaddr);
  115       if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
  116         return;
  117     }
  118     }
  119   else
  120     {
  121       struct cmsghdr *cmptr;
  122 
  123       if (msg.msg_controllen < sizeof(struct cmsghdr))
  124         return;
  125       
  126       addr.sa.sa_family = family;
  127       
  128 #if defined(HAVE_LINUX_NETWORK)
  129       if (family == AF_INET)
  130     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  131       if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
  132         {
  133           union {
  134         unsigned char *c;
  135         struct in_pktinfo *p;
  136           } p;
  137           p.c = CMSG_DATA(cmptr);
  138           addr.in.sin_addr = p.p->ipi_spec_dst;
  139           if_index = p.p->ipi_ifindex;
  140         }
  141       
  142 #elif defined(HAVE_SOLARIS_NETWORK)
  143       if (family == AF_INET)
  144     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  145       {
  146         union {
  147           unsigned char *c;
  148           struct in_addr *a;
  149           unsigned int *i;
  150         } p;
  151         p.c = CMSG_DATA(cmptr);
  152         if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
  153         addr.in.sin_addr = *(p.a);
  154         else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
  155         if_index = *(p.i);
  156       }
  157       
  158 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
  159       if (family == AF_INET)
  160     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  161       {
  162         union {
  163           unsigned char *c;
  164           struct in_addr *a;
  165           struct sockaddr_dl *s;
  166         } p;
  167         p.c = CMSG_DATA(cmptr);
  168         if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
  169           addr.in.sin_addr = *(p.a);
  170         else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
  171           if_index = p.s->sdl_index;
  172       }
  173       
  174 #endif
  175 
  176       if (family == AF_INET6)
  177         {
  178           for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  179             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
  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         }
  191       
  192       if (!indextoname(listen->tftpfd, if_index, namebuff))
  193     return;
  194 
  195       name = namebuff;
  196       
  197       addra.addr4 = addr.in.sin_addr;
  198 
  199       if (family == AF_INET6)
  200     addra.addr6 = addr.in6.sin6_addr;
  201 
  202       if (daemon->tftp_interfaces)
  203     {
  204       /* dedicated tftp interface list */
  205       for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
  206         if (tmp->name && wildcard_match(tmp->name, name))
  207           break;
  208 
  209       if (!tmp)
  210         return;
  211     }
  212       else
  213     {
  214       /* Do the same as DHCP */
  215       if (!iface_check(family, &addra, name, NULL))
  216         {
  217           if (!option_bool(OPT_CLEVERBIND))
  218         enumerate_interfaces(0); 
  219           if (!loopback_exception(listen->tftpfd, family, &addra, name) &&
  220           !label_exception(if_index, family, &addra))
  221         return;
  222         }
  223       
  224 #ifdef HAVE_DHCP      
  225       /* allowed interfaces are the same as for DHCP */
  226       for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
  227         if (tmp->name && wildcard_match(tmp->name, name))
  228           return;
  229 #endif
  230     }
  231 
  232       safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
  233       if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
  234     {
  235       mtu = ifr.ifr_mtu;  
  236       if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
  237         mtu = daemon->tftp_mtu;    
  238     }
  239     }
  240 
  241   /* Failed to get interface mtu - can use configured value. */
  242   if (mtu == 0)
  243     mtu = daemon->tftp_mtu;
  244 
  245   /* data transfer via server listening socket */
  246   if (option_bool(OPT_SINGLE_PORT))
  247     {
  248       int tftp_cnt;
  249 
  250       for (tftp_cnt = 0, transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; up = &transfer->next, transfer = transfer->next)
  251     {
  252       tftp_cnt++;
  253 
  254       if (sockaddr_isequal(&peer, &transfer->peer))
  255         {
  256           if (ntohs(*((unsigned short *)packet)) == OP_RRQ)
  257         {
  258           /* Handle repeated RRQ or abandoned transfer from same host and port 
  259              by unlinking and reusing the struct transfer. */
  260           *up = transfer->next;
  261           break;
  262         }
  263           else
  264         {
  265           handle_tftp(now, transfer, len);
  266           return;
  267         }
  268         }
  269     }
  270       
  271       /* Enforce simultaneous transfer limit. In non-single-port mode
  272      this is doene by not listening on the server socket when
  273      too many transfers are in progress. */
  274       if (!transfer && tftp_cnt >= daemon->tftp_max)
  275     return;
  276     }
  277   
  278   if (name)
  279     {
  280       /* check for per-interface prefix */ 
  281       for (pref = daemon->if_prefix; pref; pref = pref->next)
  282     if (strcmp(pref->interface, name) == 0)
  283       prefix = pref->prefix;  
  284     }
  285 
  286   if (family == AF_INET)
  287     {
  288       addr.in.sin_port = htons(port);
  289 #ifdef HAVE_SOCKADDR_SA_LEN
  290       addr.in.sin_len = sizeof(addr.in);
  291 #endif
  292     }
  293   else
  294     {
  295       addr.in6.sin6_port = htons(port);
  296       addr.in6.sin6_flowinfo = 0;
  297       addr.in6.sin6_scope_id = 0;
  298 #ifdef HAVE_SOCKADDR_SA_LEN
  299       addr.in6.sin6_len = sizeof(addr.in6);
  300 #endif
  301     }
  302 
  303   /* May reuse struct transfer from abandoned transfer in single port mode. */
  304   if (!transfer && !(transfer = whine_malloc(sizeof(struct tftp_transfer))))
  305     return;
  306   
  307   if (option_bool(OPT_SINGLE_PORT))
  308     transfer->sockfd = listen->tftpfd;
  309   else if ((transfer->sockfd = socket(family, SOCK_DGRAM, 0)) == -1)
  310     {
  311       free(transfer);
  312       return;
  313     }
  314   
  315   transfer->peer = peer;
  316   transfer->source = addra;
  317   transfer->if_index = if_index;
  318   transfer->timeout = now + 2;
  319   transfer->backoff = 1;
  320   transfer->block = 1;
  321   transfer->blocksize = 512;
  322   transfer->offset = 0;
  323   transfer->file = NULL;
  324   transfer->opt_blocksize = transfer->opt_transize = 0;
  325   transfer->netascii = transfer->carrylf = 0;
  326  
  327   (void)prettyprint_addr(&peer, daemon->addrbuff);
  328   
  329   /* if we have a nailed-down range, iterate until we find a free one. */
  330   while (!option_bool(OPT_SINGLE_PORT))
  331     {
  332       if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
  333 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
  334       setsockopt(transfer->sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
  335 #endif
  336       !fix_fd(transfer->sockfd))
  337     {
  338       if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
  339         {
  340           if (++port <= daemon->end_tftp_port)
  341         { 
  342           if (family == AF_INET)
  343             addr.in.sin_port = htons(port);
  344           else
  345             addr.in6.sin6_port = htons(port);
  346           
  347           continue;
  348         }
  349           my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
  350         }
  351       free_transfer(transfer);
  352       return;
  353     }
  354       break;
  355     }
  356   
  357   p = packet + 2;
  358   end = packet + len;
  359   
  360   if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
  361       !(filename = next(&p, end)) ||
  362       !(mode = next(&p, end)) ||
  363       (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
  364     {
  365       len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
  366       is_err = 1;
  367     }
  368   else
  369     {
  370       if (strcasecmp(mode, "netascii") == 0)
  371     transfer->netascii = 1;
  372       
  373       while ((opt = next(&p, end)))
  374     {
  375       if (strcasecmp(opt, "blksize") == 0)
  376         {
  377           if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
  378         {
  379           /* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
  380           int overhead = (family == AF_INET) ? 32 : 52;
  381           transfer->blocksize = atoi(opt);
  382           if (transfer->blocksize < 1)
  383             transfer->blocksize = 1;
  384           if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
  385             transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
  386           if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
  387             transfer->blocksize = (unsigned)mtu - overhead;
  388           transfer->opt_blocksize = 1;
  389           transfer->block = 0;
  390         }
  391         }
  392       else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
  393         {
  394           transfer->opt_transize = 1;
  395           transfer->block = 0;
  396         }
  397     }
  398 
  399       /* cope with backslashes from windows boxen. */
  400       for (p = filename; *p; p++)
  401     if (*p == '\\')
  402       *p = '/';
  403     else if (option_bool(OPT_TFTP_LC))
  404       *p = tolower(*p);
  405         
  406       strcpy(daemon->namebuff, "/");
  407       if (prefix)
  408     {
  409       if (prefix[0] == '/')
  410         daemon->namebuff[0] = 0;
  411       strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
  412       if (prefix[strlen(prefix)-1] != '/')
  413         strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
  414 
  415       if (option_bool(OPT_TFTP_APREF_IP))
  416         {
  417           size_t oldlen = strlen(daemon->namebuff);
  418           struct stat statbuf;
  419           
  420           strncat(daemon->namebuff, daemon->addrbuff, (MAXDNAME-1) - strlen(daemon->namebuff));
  421           strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
  422           
  423           /* remove unique-directory if it doesn't exist */
  424           if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
  425         daemon->namebuff[oldlen] = 0;
  426         }
  427       
  428       if (option_bool(OPT_TFTP_APREF_MAC))
  429         {
  430           unsigned char *macaddr = NULL;
  431           unsigned char macbuf[DHCP_CHADDR_MAX];
  432           
  433 #ifdef HAVE_DHCP
  434           if (daemon->dhcp && peer.sa.sa_family == AF_INET)
  435             {
  436           /* Check if the client IP is in our lease database */
  437           struct dhcp_lease *lease = lease_find_by_addr(peer.in.sin_addr);
  438           if (lease && lease->hwaddr_type == ARPHRD_ETHER && lease->hwaddr_len == ETHER_ADDR_LEN)
  439             macaddr = lease->hwaddr;
  440         }
  441 #endif
  442           
  443           /* If no luck, try to find in ARP table. This only works if client is in same (V)LAN */
  444           if (!macaddr && find_mac(&peer, macbuf, 1, now) > 0)
  445         macaddr = macbuf;
  446           
  447           if (macaddr)
  448             {
  449           size_t oldlen = strlen(daemon->namebuff);
  450           struct stat statbuf;
  451 
  452           snprintf(daemon->namebuff + oldlen, (MAXDNAME-1) - oldlen, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x/",
  453                macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
  454           
  455           /* remove unique-directory if it doesn't exist */
  456           if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
  457             daemon->namebuff[oldlen] = 0;
  458         }
  459         }
  460       
  461       /* Absolute pathnames OK if they match prefix */
  462       if (filename[0] == '/')
  463         {
  464           if (strstr(filename, daemon->namebuff) == filename)
  465         daemon->namebuff[0] = 0;
  466           else
  467         filename++;
  468         }
  469     }
  470       else if (filename[0] == '/')
  471     daemon->namebuff[0] = 0;
  472       strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
  473       
  474       /* check permissions and open file */
  475       if ((transfer->file = check_tftp_fileperm(&len, prefix)))
  476     {
  477       if ((len = get_block(packet, transfer)) == -1)
  478         len = tftp_err_oops(packet, daemon->namebuff);
  479       else
  480         is_err = 0;
  481     }
  482     }
  483 
  484   send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index);
  485   
  486   if (is_err)
  487     free_transfer(transfer);
  488   else
  489     {
  490       transfer->next = daemon->tftp_trans;
  491       daemon->tftp_trans = transfer;
  492     }
  493 }
  494  
  495 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
  496 {
  497   char *packet = daemon->packet, *namebuff = daemon->namebuff;
  498   struct tftp_file *file;
  499   struct tftp_transfer *t;
  500   uid_t uid = geteuid();
  501   struct stat statbuf;
  502   int fd = -1;
  503 
  504   /* trick to ban moving out of the subtree */
  505   if (prefix && strstr(namebuff, "/../"))
  506     goto perm;
  507   
  508   if ((fd = open(namebuff, O_RDONLY)) == -1)
  509     {
  510       if (errno == ENOENT)
  511     {
  512       *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
  513       return NULL;
  514     }
  515       else if (errno == EACCES)
  516     goto perm;
  517       else
  518     goto oops;
  519     }
  520   
  521   /* stat the file descriptor to avoid stat->open races */
  522   if (fstat(fd, &statbuf) == -1)
  523     goto oops;
  524   
  525   /* running as root, must be world-readable */
  526   if (uid == 0)
  527     {
  528       if (!(statbuf.st_mode & S_IROTH))
  529     goto perm;
  530     }
  531   /* in secure mode, must be owned by user running dnsmasq */
  532   else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
  533     goto perm;
  534       
  535   /* If we're doing many transfers from the same file, only 
  536      open it once this saves lots of file descriptors 
  537      when mass-booting a big cluster, for instance. 
  538      Be conservative and only share when inode and name match
  539      this keeps error messages sane. */
  540   for (t = daemon->tftp_trans; t; t = t->next)
  541     if (t->file->dev == statbuf.st_dev && 
  542     t->file->inode == statbuf.st_ino &&
  543     strcmp(t->file->filename, namebuff) == 0)
  544       {
  545     close(fd);
  546     t->file->refcount++;
  547     return t->file;
  548       }
  549   
  550   if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
  551     {
  552       errno = ENOMEM;
  553       goto oops;
  554     }
  555 
  556   file->fd = fd;
  557   file->size = statbuf.st_size;
  558   file->dev = statbuf.st_dev;
  559   file->inode = statbuf.st_ino;
  560   file->refcount = 1;
  561   strcpy(file->filename, namebuff);
  562   return file;
  563   
  564  perm:
  565   errno = EACCES;
  566   *len =  tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
  567   if (fd != -1)
  568     close(fd);
  569   return NULL;
  570 
  571  oops:
  572   *len =  tftp_err_oops(packet, namebuff);
  573   if (fd != -1)
  574     close(fd);
  575   return NULL;
  576 }
  577 
  578 void check_tftp_listeners(time_t now)
  579 {
  580   struct tftp_transfer *transfer, *tmp, **up;
  581   
  582   /* In single port mode, all packets come via port 69 and tftp_request() */
  583   if (!option_bool(OPT_SINGLE_PORT))
  584     for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
  585       if (poll_check(transfer->sockfd, POLLIN))
  586     {
  587       union mysockaddr peer;
  588       socklen_t addr_len = sizeof(union mysockaddr);
  589       ssize_t len;
  590       
  591       /* we overwrote the buffer... */
  592       daemon->srv_save = NULL;
  593 
  594       if ((len = recvfrom(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0, &peer.sa, &addr_len)) > 0)
  595         {
  596           if (sockaddr_isequal(&peer, &transfer->peer)) 
  597         handle_tftp(now, transfer, len);
  598           else
  599         {
  600           /* Wrong source address. See rfc1350 para 4. */
  601           prettyprint_addr(&peer, daemon->addrbuff);
  602           len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff);
  603           sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer));
  604         }
  605         }
  606     }
  607       
  608   for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
  609     {
  610       tmp = transfer->next;
  611       
  612       if (difftime(now, transfer->timeout) >= 0.0)
  613     {
  614       int endcon = 0;
  615       ssize_t len;
  616 
  617       /* timeout, retransmit */
  618       transfer->timeout += 1 + (1<<(transfer->backoff/2));
  619           
  620       /* we overwrote the buffer... */
  621       daemon->srv_save = NULL;
  622 
  623       if ((len = get_block(daemon->packet, transfer)) == -1)
  624         {
  625           len = tftp_err_oops(daemon->packet, transfer->file->filename);
  626           endcon = 1;
  627         }
  628       else if (++transfer->backoff > 7)
  629         {
  630           /* don't complain about timeout when we're awaiting the last
  631          ACK, some clients never send it */
  632           if ((unsigned)len == transfer->blocksize + 4)
  633         endcon = 1;
  634           len = 0;
  635         }
  636 
  637       if (len != 0)
  638         send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len,
  639               &transfer->peer, &transfer->source, transfer->if_index);
  640           
  641       if (endcon || len == 0)
  642         {
  643           strcpy(daemon->namebuff, transfer->file->filename);
  644           sanitise(daemon->namebuff);
  645           (void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
  646           my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
  647           /* unlink */
  648           *up = tmp;
  649           if (endcon)
  650         free_transfer(transfer);
  651           else
  652         {
  653           /* put on queue to be sent to script and deleted */
  654           transfer->next = daemon->tftp_done_trans;
  655           daemon->tftp_done_trans = transfer;
  656         }
  657           continue;
  658         }
  659     }
  660 
  661       up = &transfer->next;
  662     }    
  663 }
  664       
  665 /* packet in daemon->packet as this is called. */
  666 static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
  667 {
  668   struct ack {
  669     unsigned short op, block;
  670   } *mess = (struct ack *)daemon->packet;
  671   
  672   if (len >= (ssize_t)sizeof(struct ack))
  673     {
  674       if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) 
  675     {
  676       /* Got ack, ensure we take the (re)transmit path */
  677       transfer->timeout = now;
  678       transfer->backoff = 0;
  679       if (transfer->block++ != 0)
  680         transfer->offset += transfer->blocksize - transfer->expansion;
  681     }
  682       else if (ntohs(mess->op) == OP_ERR)
  683     {
  684       char *p = daemon->packet + sizeof(struct ack);
  685       char *end = daemon->packet + len;
  686       char *err = next(&p, end);
  687       
  688       (void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
  689       
  690       /* Sanitise error message */
  691       if (!err)
  692         err = "";
  693       else
  694         sanitise(err);
  695       
  696       my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
  697             (int)ntohs(mess->block), err, 
  698             daemon->addrbuff);  
  699       
  700       /* Got err, ensure we take abort */
  701       transfer->timeout = now;
  702       transfer->backoff = 100;
  703     }
  704     }
  705 }
  706 
  707 static void free_transfer(struct tftp_transfer *transfer)
  708 {
  709   if (!option_bool(OPT_SINGLE_PORT))
  710     close(transfer->sockfd);
  711 
  712   if (transfer->file && (--transfer->file->refcount) == 0)
  713     {
  714       close(transfer->file->fd);
  715       free(transfer->file);
  716     }
  717   
  718   free(transfer);
  719 }
  720 
  721 static char *next(char **p, char *end)
  722 {
  723   char *ret = *p;
  724   size_t len;
  725 
  726   if (*(end-1) != 0 || 
  727       *p == end ||
  728       (len = strlen(ret)) == 0)
  729     return NULL;
  730 
  731   *p += len + 1;
  732   return ret;
  733 }
  734 
  735 static void sanitise(char *buf)
  736 {
  737   unsigned char *q, *r;
  738   for (q = r = (unsigned char *)buf; *r; r++)
  739     if (isprint((int)*r))
  740       *(q++) = *r;
  741   *q = 0;
  742 
  743 }
  744 
  745 #define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */ 
  746 static ssize_t tftp_err(int err, char *packet, char *message, char *file)
  747 {
  748   struct errmess {
  749     unsigned short op, err;
  750     char message[];
  751   } *mess = (struct errmess *)packet;
  752   ssize_t len, ret = 4;
  753   char *errstr = strerror(errno);
  754   
  755   memset(packet, 0, daemon->packet_buff_sz);
  756   if (file)
  757     sanitise(file);
  758   
  759   mess->op = htons(OP_ERR);
  760   mess->err = htons(err);
  761   len = snprintf(mess->message, MAXMESSAGE,  message, file, errstr);
  762   ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
  763   
  764   my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
  765   
  766   return  ret;
  767 }
  768 
  769 static ssize_t tftp_err_oops(char *packet, const char *file)
  770 {
  771   /* May have >1 refs to file, so potentially mangle a copy of the name */
  772   if (file != daemon->namebuff)
  773     strcpy(daemon->namebuff, file);
  774   return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
  775 }
  776 
  777 /* return -1 for error, zero for done. */
  778 static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
  779 {
  780   memset(packet, 0, daemon->packet_buff_sz);
  781   
  782   if (transfer->block == 0)
  783     {
  784       /* send OACK */
  785       char *p;
  786       struct oackmess {
  787     unsigned short op;
  788     char data[];
  789       } *mess = (struct oackmess *)packet;
  790       
  791       p = mess->data;
  792       mess->op = htons(OP_OACK);
  793       if (transfer->opt_blocksize)
  794     {
  795       p += (sprintf(p, "blksize") + 1);
  796       p += (sprintf(p, "%u", transfer->blocksize) + 1);
  797     }
  798       if (transfer->opt_transize)
  799     {
  800       p += (sprintf(p,"tsize") + 1);
  801       p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
  802     }
  803 
  804       return p - packet;
  805     }
  806   else
  807     {
  808       /* send data packet */
  809       struct datamess {
  810     unsigned short op, block;
  811     unsigned char data[];
  812       } *mess = (struct datamess *)packet;
  813       
  814       size_t size = transfer->file->size - transfer->offset; 
  815       
  816       if (transfer->offset > transfer->file->size)
  817     return 0; /* finished */
  818       
  819       if (size > transfer->blocksize)
  820     size = transfer->blocksize;
  821       
  822       mess->op = htons(OP_DATA);
  823       mess->block = htons((unsigned short)(transfer->block));
  824       
  825       if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
  826       !read_write(transfer->file->fd, mess->data, size, 1))
  827     return -1;
  828       
  829       transfer->expansion = 0;
  830       
  831       /* Map '\n' to CR-LF in netascii mode */
  832       if (transfer->netascii)
  833     {
  834       size_t i;
  835       int newcarrylf;
  836 
  837       for (i = 0, newcarrylf = 0; i < size; i++)
  838         if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
  839           {
  840         transfer->expansion++;
  841 
  842         if (size != transfer->blocksize)
  843           size++; /* room in this block */
  844         else  if (i == size - 1)
  845           newcarrylf = 1; /* don't expand LF again if it moves to the next block */
  846           
  847         /* make space and insert CR */
  848         memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
  849         mess->data[i] = '\r';
  850         
  851         i++;
  852           }
  853       transfer->carrylf = newcarrylf;
  854       
  855     }
  856 
  857       return size + 4;
  858     }
  859 }
  860 
  861 
  862 int do_tftp_script_run(void)
  863 {
  864   struct tftp_transfer *transfer;
  865 
  866   if ((transfer = daemon->tftp_done_trans))
  867     {
  868       daemon->tftp_done_trans = transfer->next;
  869 #ifdef HAVE_SCRIPT
  870       queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
  871 #endif
  872       free_transfer(transfer);
  873       return 1;
  874     }
  875 
  876   return 0;
  877 }
  878 #endif