Esempio n. 1
0
File: tftp.c Progetto: JMR-b/qemu
static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
{
  int s;

  s = tftp_session_find(slirp, tp);

  if (s < 0) {
    return;
  }

  tftp_session_terminate(&slirp->tftp_sessions[s]);
}
Esempio n. 2
0
File: tftp.c Progetto: JMR-b/qemu
static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
{
  int s;

  s = tftp_session_find(slirp, tp);

  if (s < 0) {
    return;
  }

  tftp_send_next_block(&slirp->tftp_sessions[s], tp);
}
Esempio n. 3
0
static void tftp_handle_ack(PNATState pData, struct tftp_t *tp, int pktlen)
{
    int s;

    s = tftp_session_find(pData, tp);
    if (s < 0)
        return;

    if (tftp_send_data(pData, &tftp_sessions[s],
                       RT_N2H_U16(tp->x.tp_data.tp_block_nr) + 1, tp) < 0)
    {
        /* XXX */
    }
}
Esempio n. 4
0
static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
{
  int s;

  s = tftp_session_find(slirp, tp);

  if (s < 0) {
    return;
  }

  if (tftp_send_data(&slirp->tftp_sessions[s],
		     ntohs(tp->x.tp_data.tp_block_nr) + 1,
		     tp) < 0) {
    return;
  }
}
Esempio n. 5
0
File: tftp.c Progetto: JMR-b/qemu
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;
  const char *option_name[2];
  uint32_t option_value[2];
  int nb_options = 0;

  /* 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];

  /* unspecified prefix means service disabled */
  if (!slirp->tftp_prefix) {
      tftp_send_error(spt, 2, "Access violation", tp);
      return;
  }

  /* skip header fields */
  k = 0;
  pktlen -= offsetof(struct tftp_t, x.tp_buf);

  /* prepend tftp_prefix */
  prefix_len = strlen(slirp->tftp_prefix);
  spt->filename = g_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] = 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 (strcasecmp(&tp->x.tp_buf[k], "octet") != 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 && nb_options < ARRAY_SIZE(option_name)) {
      const char *key, *value;

      key = &tp->x.tp_buf[k];
      k += strlen(key) + 1;

      if (k >= pktlen) {
	  tftp_send_error(spt, 2, "Access violation", tp);
	  return;
      }

      value = &tp->x.tp_buf[k];
      k += strlen(value) + 1;

      if (strcasecmp(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;
	      }
	  }

          option_name[nb_options] = "tsize";
          option_value[nb_options] = tsize;
          nb_options++;
      } else if (strcasecmp(key, "blksize") == 0) {
          int blksize = atoi(value);

          /* If blksize option is bigger than what we will
           * emit, accept the option with our packet size.
           * Otherwise, simply do as we didn't see the option.
           */
          if (blksize >= 512) {
              option_name[nb_options] = "blksize";
              option_value[nb_options] = 512;
              nb_options++;
          }
      }
  }

  if (nb_options > 0) {
      assert(nb_options <= ARRAY_SIZE(option_name));
      tftp_send_oack(spt, option_name, option_value, nb_options, tp);
      return;
  }

  spt->block_nr = 0;
  tftp_send_next_block(spt, tp);
}
Esempio n. 6
0
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 (strcasecmp((const char *)&tp->x.tp_buf[k], "octet") != 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 (strcasecmp(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);
}