Ejemplo n.º 1
0
void silc_sftp_name_free(SilcSFTPName name)
{
  int i;

  for (i = 0; i < name->count; i++) {
    silc_free(name->filename[i]);
    silc_free(name->long_filename[i]);
    silc_sftp_attr_free(name->attrs[i]);
  }

  silc_free(name->filename);
  silc_free(name->long_filename);
  silc_free(name->attrs);
  silc_free(name);
}
Ejemplo n.º 2
0
SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
{
  SilcSFTPAttributes attr;

  attr = silc_calloc(1, sizeof(*attr));
  if (!attr)
    return NULL;

  if (silc_buffer_unformat(buffer,
			   SILC_STR_UI_INT(&attr->flags),
			   SILC_STR_END) < 0)
    goto out;

  silc_buffer_pull(buffer, 4);

  if (attr->flags & SILC_SFTP_ATTR_SIZE) {
    if (silc_buffer_unformat(buffer,
			     SILC_STR_UI_INT64(&attr->size),
			     SILC_STR_END) < 0)
      goto out;

    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
    if (silc_buffer_unformat(buffer,
			     SILC_STR_UI_INT(&attr->uid),
			     SILC_STR_UI_INT(&attr->gid),
			     SILC_STR_END) < 0)
      goto out;

    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
    if (silc_buffer_unformat(buffer,
			     SILC_STR_UI_INT(&attr->permissions),
			     SILC_STR_END) < 0)
      goto out;

    silc_buffer_pull(buffer, 4);
  }

  if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
    if (silc_buffer_unformat(buffer,
			     SILC_STR_UI_INT(&attr->atime),
			     SILC_STR_UI_INT(&attr->mtime),
			     SILC_STR_END) < 0)
      goto out;

    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
    int i;

    if (silc_buffer_unformat(buffer,
			     SILC_STR_UI_INT(&attr->extended_count),
			     SILC_STR_END) < 0)
      goto out;

    silc_buffer_pull(buffer, 4);

    attr->extended_type = silc_calloc(attr->extended_count,
				      sizeof(*attr->extended_type));
    attr->extended_data = silc_calloc(attr->extended_count,
				      sizeof(*attr->extended_data));
    if (!attr->extended_type || !attr->extended_data)
      return NULL;

    for (i = 0; i < attr->extended_count; i++) {
      unsigned char *tmp, *tmp2;
      SilcUInt32 tmp_len, tmp2_len;

      if (silc_buffer_unformat(buffer,
			       SILC_STR_UI32_NSTRING(&tmp, &tmp_len),
			       SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len),
			       SILC_STR_END) < 0)
	goto out;

      attr->extended_type[i] = silc_buffer_alloc(tmp_len);
      attr->extended_data[i] = silc_buffer_alloc(tmp2_len);
      if (!attr->extended_type[i] || !attr->extended_data[i])
	return NULL;
      silc_buffer_put(attr->extended_type[i], tmp, tmp_len);
      silc_buffer_put(attr->extended_data[i], tmp2, tmp2_len);

      silc_buffer_pull(buffer, tmp_len + 4 + tmp2_len + 4);
    }
  }

  return attr;

 out:
  silc_sftp_attr_free(attr);
  return NULL;
}
Ejemplo n.º 3
0
static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
{
  SilcSFTPServer server = (SilcSFTPServer)sftp;
  SilcSFTPPacket type;
  char *filename = NULL, *path = NULL;
  unsigned char *payload = NULL;
  SilcUInt32 payload_len;
  int ret;
  SilcBufferStruct buf;
  SilcUInt32 id;
  SilcSFTPAttributes attrs;
  SilcSFTPHandle handle;
  SilcSFTPMonitorDataStruct mdata;

  SILC_LOG_DEBUG(("Start"));

  /* Parse the packet */
  type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
  if (type <= 0)
    return;

  silc_buffer_set(&buf, payload, payload_len);

  memset(&mdata, 0, sizeof(mdata));

  switch (type) {
  case SILC_SFTP_READ:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;
      SilcUInt64 offset;
      SilcUInt32 len;

      SILC_LOG_DEBUG(("Read request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI_INT64(&offset),
				 SILC_STR_UI_INT(&len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Read operation */
      server->fs->fs->sftp_read(server->fs->fs_context, sftp,
				handle, offset, len,
				silc_sftp_server_data, SILC_32_TO_PTR(id));

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
	mdata.offset = offset;
	mdata.data_len = len;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
			   server->monitor_context);
      }
    }
    break;

  case SILC_SFTP_WRITE:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;
      SilcUInt64 offset;
      unsigned char *data;
      SilcUInt32 data_len;

      SILC_LOG_DEBUG(("Read request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI_INT64(&offset),
				 SILC_STR_UI32_NSTRING(&data,
						       &data_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Write operation */
      server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
				 (const unsigned char *)data, data_len,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
	mdata.offset = offset;
	mdata.data_len = data_len;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
			   server->monitor_context);
      }
    }
    break;

  case SILC_SFTP_INIT:
    {
      SilcSFTPVersion version;

      SILC_LOG_DEBUG(("Init request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&version),
				 SILC_STR_END);
      if (ret < 0)
	break;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
	mdata.version = version;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
			   server->monitor_context);
      }

      silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
			    SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
			    SILC_STR_END);
    }
    break;

  case SILC_SFTP_OPEN:
    {
      SilcSFTPFileOperation pflags;
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Open request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_UI_INT(&pflags),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
	mdata.name = filename;
	mdata.pflags = pflags;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
			   server->monitor_context);
      }

      /* Open operation */
      server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
				attrs, silc_sftp_server_handle,
				SILC_32_TO_PTR(id));

      silc_free(filename);
      silc_sftp_attr_free(attrs);
    }
    break;

  case SILC_SFTP_CLOSE:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Close request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
			   server->monitor_context);
      }

      /* Close operation */
      server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

    }
    break;

  case SILC_SFTP_REMOVE:
    {
      SILC_LOG_DEBUG(("Remove request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
	mdata.name = filename;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
			   server->monitor_context);
      }

      /* Remove operation */
      server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
				  silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(filename);
    }
    break;

  case SILC_SFTP_RENAME:
    {
      char *newname = NULL;

      SILC_LOG_DEBUG(("Rename request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_UI32_STRING_ALLOC(&newname),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
	mdata.name = filename;
	mdata.name2 = newname;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
			   server->monitor_context);
      }

      /* Rename operation */
      server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
				  filename, newname,
				  silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(filename);
      silc_free(newname);
    }
    break;

  case SILC_SFTP_MKDIR:
    {
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Mkdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
			   server->monitor_context);
      }

      /* Mkdir operation */
      server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
      silc_free(path);
    }
    break;

  case SILC_SFTP_RMDIR:
    {
      SILC_LOG_DEBUG(("Rmdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
			   server->monitor_context);
      }

      /* Rmdir operation */
      server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_OPENDIR:
    {
      SILC_LOG_DEBUG(("Opendir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
			   server->monitor_context);
      }

      /* Opendir operation */
      server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
				   silc_sftp_server_handle, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_READDIR:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Readdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
			   server->monitor_context);
      }

      /* Readdir operation */
      server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
				   silc_sftp_server_name, SILC_32_TO_PTR(id));
    }
    break;

  case SILC_SFTP_STAT:
    {
      SILC_LOG_DEBUG(("Stat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
			   server->monitor_context);
      }

      /* Stat operation */
      server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
				silc_sftp_server_attr, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_LSTAT:
    {
      SILC_LOG_DEBUG(("Lstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
			   server->monitor_context);
      }

      /* Lstat operation */
      server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
				 silc_sftp_server_attr, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_FSTAT:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Fstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
			   server->monitor_context);
      }

      /* Fstat operation */
      server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
				 silc_sftp_server_attr, SILC_32_TO_PTR(id));
    }
    break;

  case SILC_SFTP_SETSTAT:
    {
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Setstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
			   server->monitor_context);
      }

      /* Setstat operation */
      server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
				   silc_sftp_server_status,
				   SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
      silc_free(path);
    }
    break;

  case SILC_SFTP_FSETSTAT:
    {
      unsigned char *hdata, *attr_buf;
      SilcUInt32 hdata_len, attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Fsetstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
			   server->monitor_context);
      }

      /* Fsetstat operation */
      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
				    handle, attrs,
				    silc_sftp_server_status,
				    SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
    }
    break;

  case SILC_SFTP_READLINK:
    {
      SILC_LOG_DEBUG(("Readlink request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
			   server->monitor_context);
      }

      /* Readlink operation */
      server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
				    silc_sftp_server_name, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_SYMLINK:
    {
      char *target = NULL;

      SILC_LOG_DEBUG(("Symlink request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_STRING_ALLOC(&target),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
	mdata.name = path;
	mdata.name2 = target;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
			   server->monitor_context);
      }

      /* Symlink operation */
      server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
				   silc_sftp_server_status,
				   SILC_32_TO_PTR(id));

      silc_free(path);
      silc_free(target);
    }
    break;

  case SILC_SFTP_REALPATH:
    {
      SILC_LOG_DEBUG(("Realpath request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
			   server->monitor_context);
      }

      /* Realpath operation */
      server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
				    silc_sftp_server_name, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_EXTENDED:
    {
      char *request = NULL;
      unsigned char *data;
      SilcUInt32 data_len;

      SILC_LOG_DEBUG(("Extended request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&request),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      data_len = 8 + strlen(request);
      silc_buffer_pull(&buf, data_len);
      ret = silc_buffer_unformat(&buf,
				 SILC_STR_DATA(&data, silc_buffer_len(&buf)),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;
      data_len = silc_buffer_len(&buf);

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
			   server->monitor_context);
      }

      /* Extended operation */
      server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
				    request, data, data_len,
				    silc_sftp_server_extended,
				    SILC_32_TO_PTR(id));

      silc_free(request);
    }
    break;

  default:
    break;
  }

  return;

 failure:
  silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
}