static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)

{

  struct tftp_session *spt;

  int s, k;

  size_t prefix_len;

  char *req_fname;



  /* check if a session already exists and if so terminate it */

  s = tftp_session_find(slirp, tp);

  if (s >= 0) {

    tftp_session_terminate(&slirp->tftp_sessions[s]);

  }



  s = tftp_session_allocate(slirp, tp);



  if (s < 0) {

    return;

  }



  spt = &slirp->tftp_sessions[s];



  /* unspecifed prefix means service disabled */

  if (!slirp->tftp_prefix) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  /* skip header fields */

  k = 0;

  pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);



  /* prepend tftp_prefix */

  prefix_len = strlen(slirp->tftp_prefix);

  spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 2);

  memcpy(spt->filename, slirp->tftp_prefix, prefix_len);

  spt->filename[prefix_len] = '/';



  /* get name */

  req_fname = spt->filename + prefix_len + 1;



  while (1) {

    if (k >= TFTP_FILENAME_MAX || k >= pktlen) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

    }

    req_fname[k] = (char)tp->x.tp_buf[k];

    if (req_fname[k++] == '\0') {

      break;

    }

  }



  /* check mode */

  if ((pktlen - k) < 6) {

    tftp_send_error(spt, 2, "Access violation", tp);

    return;

  }



  if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {

      tftp_send_error(spt, 4, "Unsupported transfer mode", tp);

      return;

  }



  k += 6; /* skipping octet */



  /* do sanity checks on the filename */

  if (!strncmp(req_fname, "../", 3) ||

      req_fname[strlen(req_fname) - 1] == '/' ||

      strstr(req_fname, "/../")) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  /* check if the file exists */

  if (tftp_read_data(spt, 0, NULL, 0) < 0) {

      tftp_send_error(spt, 1, "File not found", tp);

      return;

  }



  if (tp->x.tp_buf[pktlen - 1] != 0) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  while (k < pktlen) {

      const char *key, *value;



      key = (const char *)&tp->x.tp_buf[k];

      k += strlen(key) + 1;



      if (k >= pktlen) {

	  tftp_send_error(spt, 2, "Access violation", tp);

	  return;

      }



      value = (const char *)&tp->x.tp_buf[k];

      k += strlen(value) + 1;



      if (strcmp(key, "tsize") == 0) {

	  int tsize = atoi(value);

	  struct stat stat_p;



	  if (tsize == 0) {

	      if (stat(spt->filename, &stat_p) == 0)

		  tsize = stat_p.st_size;

	      else {

		  tftp_send_error(spt, 1, "File not found", tp);

		  return;

	      }

	  }



	  tftp_send_oack(spt, "tsize", tsize, tp);

	  return;

      }

  }



  tftp_send_data(spt, 1, tp);

}

static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)

{

  struct tftp_session *spt;

  int s, k;

  size_t prefix_len;

  char *req_fname;



  

  s = tftp_session_find(slirp, tp);

  if (s >= 0) {

    tftp_session_terminate(&slirp->tftp_sessions[s]);

  }



  s = tftp_session_allocate(slirp, tp);



  if (s < 0) {

    return;

  }



  spt = &slirp->tftp_sessions[s];



  

  if (!slirp->tftp_prefix) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  

  k = 0;

  pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);



  

  prefix_len = strlen(slirp->tftp_prefix);

  spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 2);

  memcpy(spt->filename, slirp->tftp_prefix, prefix_len);

  spt->filename[prefix_len] = '/';



  

  req_fname = spt->filename + prefix_len + 1;



  while (1) {

    if (k >= TFTP_FILENAME_MAX || k >= pktlen) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

    }

    req_fname[k] = (char)tp->x.tp_buf[k];

    if (req_fname[k++] == '\0') {

      break;

    }

  }



  

  if ((pktlen - k) < 6) {

    tftp_send_error(spt, 2, "Access violation", tp);

    return;

  }



  if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {

      tftp_send_error(spt, 4, "Unsupported transfer mode", tp);

      return;

  }



  k += 6; 



  

  if (!strncmp(req_fname, "../", 3) ||

      req_fname[strlen(req_fname) - 1] == '/' ||

      strstr(req_fname, "/../")) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  

  if (tftp_read_data(spt, 0, NULL, 0) < 0) {

      tftp_send_error(spt, 1, "File not found", tp);

      return;

  }



  if (tp->x.tp_buf[pktlen - 1] != 0) {

      tftp_send_error(spt, 2, "Access violation", tp);

      return;

  }



  while (k < pktlen) {

      const char *key, *value;



      key = (const char *)&tp->x.tp_buf[k];

      k += strlen(key) + 1;



      if (k >= pktlen) {

	  tftp_send_error(spt, 2, "Access violation", tp);

	  return;

      }



      value = (const char *)&tp->x.tp_buf[k];

      k += strlen(value) + 1;



      if (strcmp(key, "tsize") == 0) {

	  int tsize = atoi(value);

	  struct stat stat_p;



	  if (tsize == 0) {

	      if (stat(spt->filename, &stat_p) == 0)

		  tsize = stat_p.st_size;

	      else {

		  tftp_send_error(spt, 1, "File not found", tp);

		  return;

	      }

	  }



	  tftp_send_oack(spt, "tsize", tsize, tp);

	  return;

      }

  }



  tftp_send_data(spt, 1, tp);

}

static void FUNC_0(Slirp *VAR_0, struct tftp_t *VAR_1, int VAR_2)

{

  struct tftp_session *VAR_3;

  int VAR_4, VAR_5;

  size_t prefix_len;

  char *VAR_6;



  

  VAR_4 = tftp_session_find(VAR_0, VAR_1);

  if (VAR_4 >= 0) {

    tftp_session_terminate(&VAR_0->tftp_sessions[VAR_4]);

  }



  VAR_4 = tftp_session_allocate(VAR_0, VAR_1);



  if (VAR_4 < 0) {

    return;

  }



  VAR_3 = &VAR_0->tftp_sessions[VAR_4];



  

  if (!VAR_0->tftp_prefix) {

      tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

      return;

  }



  

  VAR_5 = 0;

  VAR_2 -= ((uint8_t *)&VAR_1->x.tp_buf[0] - (uint8_t *)VAR_1);



  

  prefix_len = strlen(VAR_0->tftp_prefix);

  VAR_3->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 2);

  memcpy(VAR_3->filename, VAR_0->tftp_prefix, prefix_len);

  VAR_3->filename[prefix_len] = '/';



  

  VAR_6 = VAR_3->filename + prefix_len + 1;



  while (1) {

    if (VAR_5 >= TFTP_FILENAME_MAX || VAR_5 >= VAR_2) {

      tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

      return;

    }

    VAR_6[VAR_5] = (char)VAR_1->x.tp_buf[VAR_5];

    if (VAR_6[VAR_5++] == '\0') {

      break;

    }

  }



  

  if ((VAR_2 - VAR_5) < 6) {

    tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

    return;

  }



  if (memcmp(&VAR_1->x.tp_buf[VAR_5], "octet\0", 6) != 0) {

      tftp_send_error(VAR_3, 4, "Unsupported transfer mode", VAR_1);

      return;

  }



  VAR_5 += 6; 



  

  if (!strncmp(VAR_6, "../", 3) ||

      VAR_6[strlen(VAR_6) - 1] == '/' ||

      strstr(VAR_6, "/../")) {

      tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

      return;

  }



  

  if (tftp_read_data(VAR_3, 0, NULL, 0) < 0) {

      tftp_send_error(VAR_3, 1, "File not found", VAR_1);

      return;

  }



  if (VAR_1->x.tp_buf[VAR_2 - 1] != 0) {

      tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

      return;

  }



  while (VAR_5 < VAR_2) {

      const char *VAR_7, *VAR_8;



      VAR_7 = (const char *)&VAR_1->x.tp_buf[VAR_5];

      VAR_5 += strlen(VAR_7) + 1;



      if (VAR_5 >= VAR_2) {

	  tftp_send_error(VAR_3, 2, "Access violation", VAR_1);

	  return;

      }



      VAR_8 = (const char *)&VAR_1->x.tp_buf[VAR_5];

      VAR_5 += strlen(VAR_8) + 1;



      if (strcmp(VAR_7, "VAR_9") == 0) {

	  int VAR_9 = atoi(VAR_8);

	  struct stat VAR_10;



	  if (VAR_9 == 0) {

	      if (stat(VAR_3->filename, &VAR_10) == 0)

		  VAR_9 = VAR_10.st_size;

	      else {

		  tftp_send_error(VAR_3, 1, "File not found", VAR_1);

		  return;

	      }

	  }



	  tftp_send_oack(VAR_3, "VAR_9", VAR_9, VAR_1);

	  return;

      }

  }



  tftp_send_data(VAR_3, 1, VAR_1);

}

static void FUNC_0(Slirp *VAR_0, struct tftp_t *VAR_1, int VAR_2)
{ struct tftp_session *VAR_3; int VAR_4, VAR_5; size_t prefix_len; char *VAR_6; VAR_4 = tftp_session_find(VAR_0, VAR_1); if (VAR_4 >= 0) { tftp_session_terminate(&VAR_0->tftp_sessions[VAR_4]); } VAR_4 = tftp_session_allocate(VAR_0, VAR_1); if (VAR_4 < 0) { return; } VAR_3 = &VAR_0->tftp_sessions[VAR_4]; if (!VAR_0->tftp_prefix) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } VAR_5 = 0; VAR_2 -= ((uint8_t *)&VAR_1->x.tp_buf[0] - (uint8_t *)VAR_1); prefix_len = strlen(VAR_0->tftp_prefix); VAR_3->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 2); memcpy(VAR_3->filename, VAR_0->tftp_prefix, prefix_len); VAR_3->filename[prefix_len] = '/'; VAR_6 = VAR_3->filename + prefix_len + 1; while (1) { if (VAR_5 >= TFTP_FILENAME_MAX || VAR_5 >= VAR_2) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } VAR_6[VAR_5] = (char)VAR_1->x.tp_buf[VAR_5]; if (VAR_6[VAR_5++] == '\0') { break; } } if ((VAR_2 - VAR_5) < 6) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } if (memcmp(&VAR_1->x.tp_buf[VAR_5], "octet\0", 6) != 0) { tftp_send_error(VAR_3, 4, "Unsupported transfer mode", VAR_1); return; } VAR_5 += 6; if (!strncmp(VAR_6, "../", 3) ||
VAR_6[strlen(VAR_6) - 1] == '/' ||
strstr(VAR_6, "/../")) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } if (tftp_read_data(VAR_3, 0, NULL, 0) < 0) { tftp_send_error(VAR_3, 1, "File not found", VAR_1); return; } if (VAR_1->x.tp_buf[VAR_2 - 1] != 0) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } while (VAR_5 < VAR_2) { const char *VAR_7, *VAR_8; VAR_7 = (const char *)&VAR_1->x.tp_buf[VAR_5]; VAR_5 += strlen(VAR_7) + 1; if (VAR_5 >= VAR_2) { tftp_send_error(VAR_3, 2, "Access violation", VAR_1); return; } VAR_8 = (const char *)&VAR_1->x.tp_buf[VAR_5]; VAR_5 += strlen(VAR_8) + 1; if (strcmp(VAR_7, "VAR_9") == 0) { int VAR_9 = atoi(VAR_8); struct stat VAR_10; if (VAR_9 == 0) { if (stat(VAR_3->filename, &VAR_10) == 0)
VAR_9 = VAR_10.st_size; else { tftp_send_error(VAR_3, 1, "File not found", VAR_1); return; } } tftp_send_oack(VAR_3, "VAR_9", VAR_9, VAR_1); return; } } tftp_send_data(VAR_3, 1, VAR_1); }