File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / tftp.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:56:46 2021 UTC (3 years, 4 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_84, HEAD
dnsmasq 2.84

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>