5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 #include "silcsftp_fs.h"
24 #include "sftp_util.h"
26 /* SFTP Server context */
28 SilcSocketConnection sock;
29 SilcSFTPSendPacketCallback send_packet;
31 SilcSFTPMonitors monitors;
32 SilcSFTPMonitor monitor;
33 void *monitor_context;
34 SilcSFTPFilesystem fs;
38 /* General routine to send SFTP packet to the SFTP client. */
40 static void silc_sftp_send_packet(SilcSFTPServer sftp,
48 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
54 SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data,
58 (*sftp->send_packet)(sftp->sock, sftp->packet, sftp->send_context);
61 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
62 sftp->packet->len = 0;
65 /* Sends error to the client */
67 static void silc_sftp_send_error(SilcSFTPServer sftp,
68 SilcSFTPStatus status,
71 SILC_LOG_DEBUG(("Send error %d", status));
73 silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16,
75 SILC_STR_UI_INT(status),
76 SILC_STR_UI_INT(0), /* Error */
77 SILC_STR_UI_INT(0), /* Language tag */
83 static void silc_sftp_server_status(SilcSFTP sftp,
84 SilcSFTPStatus status,
86 const char *language_tag,
89 SilcSFTPServer server = (SilcSFTPServer)sftp;
90 uint32 id = (uint32)context;
93 SILC_LOG_DEBUG(("Status callback"));
94 SILC_LOG_DEBUG(("Request ID: %d", id));
100 mlen = strlen(message);
101 llen = strlen(language_tag);
103 silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen,
105 SILC_STR_UI_INT(status),
106 SILC_STR_UI_INT(mlen),
107 SILC_STR_UI32_STRING(message),
108 SILC_STR_UI_INT(llen),
109 SILC_STR_UI32_STRING(language_tag),
113 /* Handle callback */
115 static void silc_sftp_server_handle(SilcSFTP sftp,
116 SilcSFTPStatus status,
117 SilcSFTPHandle handle,
120 SilcSFTPServer server = (SilcSFTPServer)sftp;
121 uint32 id = (uint32)context;
122 unsigned char *hdata;
125 SILC_LOG_DEBUG(("Handle callback"));
126 SILC_LOG_DEBUG(("Request ID: %d", id));
128 if (status != SILC_SFTP_STATUS_OK) {
129 silc_sftp_send_error(server, status, id);
133 hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
136 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
140 silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len,
142 SILC_STR_UI_INT(hdata_len),
143 SILC_STR_UI_XNSTRING(hdata, hdata_len),
149 static void silc_sftp_server_data(SilcSFTP sftp,
150 SilcSFTPStatus status,
151 const unsigned char *data,
155 SilcSFTPServer server = (SilcSFTPServer)sftp;
156 uint32 id = (uint32)context;
158 SILC_LOG_DEBUG(("Data callback"));
159 SILC_LOG_DEBUG(("Request ID: %d", id));
161 if (status != SILC_SFTP_STATUS_OK) {
162 silc_sftp_send_error(server, status, id);
166 silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len,
168 SILC_STR_UI_INT(data_len),
169 SILC_STR_UI_XNSTRING(data, data_len),
175 static void silc_sftp_server_name(SilcSFTP sftp,
176 SilcSFTPStatus status,
177 const SilcSFTPName name,
180 SilcSFTPServer server = (SilcSFTPServer)sftp;
181 uint32 id = (uint32)context;
184 SILC_LOG_DEBUG(("Name callback"));
185 SILC_LOG_DEBUG(("Request ID: %d", id));
187 if (status != SILC_SFTP_STATUS_OK) {
188 silc_sftp_send_error(server, status, id);
192 namebuf = silc_sftp_name_encode(name);
194 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
198 silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + namebuf->len,
200 SILC_STR_UI_XNSTRING(namebuf->data, namebuf->len),
204 /* Attributes callback */
206 static void silc_sftp_server_attr(SilcSFTP sftp,
207 SilcSFTPStatus status,
208 const SilcSFTPAttributes attrs,
211 SilcSFTPServer server = (SilcSFTPServer)sftp;
212 uint32 id = (uint32)context;
215 SILC_LOG_DEBUG(("Attr callback"));
216 SILC_LOG_DEBUG(("Request ID: %d", id));
218 if (status != SILC_SFTP_STATUS_OK) {
219 silc_sftp_send_error(server, status, id);
223 attr_buf = silc_sftp_attr_encode(attrs);
225 silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len,
227 SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len),
230 silc_buffer_free(attr_buf);
233 /* Extended callback */
235 static void silc_sftp_server_extended(SilcSFTP sftp,
236 SilcSFTPStatus status,
237 const unsigned char *data,
241 SilcSFTPServer server = (SilcSFTPServer)sftp;
242 uint32 id = (uint32)context;
244 SILC_LOG_DEBUG(("Extended callback"));
245 SILC_LOG_DEBUG(("Request ID: %d", id));
247 if (status != SILC_SFTP_STATUS_OK) {
248 silc_sftp_send_error(server, status, id);
252 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
254 SILC_STR_UI_XNSTRING(data, data_len),
258 /* Starts SFTP server by associating the socket connection `sock' to the
259 created SFTP server context. This function returns the allocated
260 SFTP client context or NULL on error. The `send_packet' is called
261 by the library when it needs to send a packet. The `fs' is the
262 structure containing filesystem access callbacks. */
264 SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
265 SilcSFTPSendPacketCallback send_packet,
267 SilcSFTPFilesystem fs)
269 SilcSFTPServer server;
271 server = silc_calloc(1, sizeof(*server));
273 server->send_packet = send_packet;
274 server->send_context = send_context;
277 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
279 return (SilcSFTP)server;
282 /* Shutdown's the SFTP server. The caller is responsible of closing
283 the associated socket connection. The SFTP context is freed and is
284 invalid after this function returns. */
286 void silc_sftp_server_shutdown(SilcSFTP sftp)
288 SilcSFTPServer server = (SilcSFTPServer)sftp;
290 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
293 silc_buffer_free(server->packet);
297 /* Sets monitor callback */
299 void silc_sftp_server_set_monitor(SilcSFTP sftp,
300 SilcSFTPMonitors monitors,
301 SilcSFTPMonitor monitor,
304 SilcSFTPServer server = (SilcSFTPServer)sftp;
305 server->monitors = monitors;
306 server->monitor = monitor;
307 server->monitor_context = context;
310 /* Function that is called to process the incmoing SFTP packet. */
311 /* XXX Some day this will go away and we have automatic receive callbacks
312 for SilcSocketConnection API or SilcPacketContext API. */
314 void silc_sftp_server_receive_process(SilcSFTP sftp,
315 SilcSocketConnection sock,
316 SilcPacketContext *packet)
318 SilcSFTPServer server = (SilcSFTPServer)sftp;
320 char *filename = NULL, *path = NULL;
321 const unsigned char *payload = NULL;
324 SilcBufferStruct buf;
326 SilcSFTPAttributes attrs;
327 SilcSFTPHandle handle;
328 SilcSFTPMonitorDataStruct mdata;
330 SILC_LOG_DEBUG(("Start"));
332 /* Parse the packet */
333 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
338 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
340 memset(&mdata, 0, sizeof(mdata));
345 SilcSFTPVersion version;
347 SILC_LOG_DEBUG(("Init request"));
349 ret = silc_buffer_unformat(&buf,
350 SILC_STR_UI_INT(&version),
356 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
357 mdata.version = version;
358 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
359 server->monitor_context);
362 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
363 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
370 SilcSFTPFileOperation pflags;
371 unsigned char *attr_buf;
373 SilcBufferStruct tmpbuf;
375 SILC_LOG_DEBUG(("Open request"));
377 ret = silc_buffer_unformat(&buf,
378 SILC_STR_UI_INT(&id),
379 SILC_STR_UI32_STRING_ALLOC(&filename),
380 SILC_STR_UI_INT(&pflags),
381 SILC_STR_UI32_NSTRING(&attr_buf,
388 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
389 attrs = silc_sftp_attr_decode(&tmpbuf);
391 attrs = silc_calloc(1, sizeof(*attrs));
395 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
396 mdata.name = filename;
397 mdata.pflags = pflags;
398 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
399 server->monitor_context);
403 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
404 attrs, silc_sftp_server_handle, (void *)id);
407 silc_sftp_attr_free(attrs);
411 case SILC_SFTP_CLOSE:
413 unsigned char *hdata;
416 SILC_LOG_DEBUG(("Close request"));
418 ret = silc_buffer_unformat(&buf,
419 SILC_STR_UI_INT(&id),
420 SILC_STR_UI32_NSTRING(&hdata,
427 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
428 (const unsigned char *)hdata,
431 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
436 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
437 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
438 server->monitor_context);
441 /* Close operation */
442 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
443 silc_sftp_server_status, (void *)id);
449 unsigned char *hdata;
454 SILC_LOG_DEBUG(("Read request"));
456 ret = silc_buffer_unformat(&buf,
457 SILC_STR_UI_INT(&id),
458 SILC_STR_UI32_NSTRING(&hdata,
460 SILC_STR_UI_INT64(&offset),
461 SILC_STR_UI_INT(&len),
467 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
468 (const unsigned char *)hdata,
471 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
476 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
477 mdata.offset = offset;
478 mdata.data_len = len;
479 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
480 server->monitor_context);
484 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
486 silc_sftp_server_data, (void *)id);
490 case SILC_SFTP_WRITE:
492 unsigned char *hdata;
498 SILC_LOG_DEBUG(("Read request"));
500 ret = silc_buffer_unformat(&buf,
501 SILC_STR_UI_INT(&id),
502 SILC_STR_UI32_NSTRING(&hdata,
504 SILC_STR_UI_INT64(&offset),
505 SILC_STR_UI32_NSTRING(&data,
512 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
513 (const unsigned char *)hdata,
516 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
521 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
522 mdata.offset = offset;
523 mdata.data_len = data_len;
524 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
525 server->monitor_context);
528 /* Write operation */
529 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
530 (const unsigned char *)data, data_len,
531 silc_sftp_server_status, (void *)id);
535 case SILC_SFTP_REMOVE:
537 SILC_LOG_DEBUG(("Remove request"));
539 ret = silc_buffer_unformat(&buf,
540 SILC_STR_UI_INT(&id),
541 SILC_STR_UI32_STRING_ALLOC(&filename),
547 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
548 mdata.name = filename;
549 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
550 server->monitor_context);
553 /* Remove operation */
554 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
555 silc_sftp_server_status, (void *)id);
561 case SILC_SFTP_RENAME:
563 char *newname = NULL;
565 SILC_LOG_DEBUG(("Rename request"));
567 ret = silc_buffer_unformat(&buf,
568 SILC_STR_UI_INT(&id),
569 SILC_STR_UI32_STRING_ALLOC(&filename),
570 SILC_STR_UI32_STRING_ALLOC(&newname),
576 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
577 mdata.name = filename;
578 mdata.name2 = newname;
579 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
580 server->monitor_context);
583 /* Rename operation */
584 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
586 silc_sftp_server_status, (void *)id);
593 case SILC_SFTP_MKDIR:
595 unsigned char *attr_buf;
597 SilcBufferStruct tmpbuf;
599 SILC_LOG_DEBUG(("Mkdir request"));
601 ret = silc_buffer_unformat(&buf,
602 SILC_STR_UI_INT(&id),
603 SILC_STR_UI32_STRING_ALLOC(&path),
604 SILC_STR_UI32_NSTRING(&attr_buf,
611 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
612 attrs = silc_sftp_attr_decode(&tmpbuf);
614 attrs = silc_calloc(1, sizeof(*attrs));
618 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
620 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
621 server->monitor_context);
624 /* Mkdir operation */
625 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
626 silc_sftp_server_status, (void *)id);
628 silc_sftp_attr_free(attrs);
633 case SILC_SFTP_RMDIR:
635 SILC_LOG_DEBUG(("Rmdir request"));
637 ret = silc_buffer_unformat(&buf,
638 SILC_STR_UI_INT(&id),
639 SILC_STR_UI32_STRING_ALLOC(&path),
645 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
647 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
648 server->monitor_context);
651 /* Rmdir operation */
652 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
653 silc_sftp_server_status, (void *)id);
659 case SILC_SFTP_OPENDIR:
661 SILC_LOG_DEBUG(("Opendir request"));
663 ret = silc_buffer_unformat(&buf,
664 SILC_STR_UI_INT(&id),
665 SILC_STR_UI32_STRING_ALLOC(&path),
671 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
673 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
674 server->monitor_context);
677 /* Opendir operation */
678 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
679 silc_sftp_server_handle, (void *)id);
685 case SILC_SFTP_READDIR:
687 unsigned char *hdata;
690 SILC_LOG_DEBUG(("Readdir request"));
692 ret = silc_buffer_unformat(&buf,
693 SILC_STR_UI_INT(&id),
694 SILC_STR_UI32_NSTRING(&hdata,
701 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
702 (const unsigned char *)hdata,
705 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
710 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
711 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
712 server->monitor_context);
715 /* Readdir operation */
716 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
717 silc_sftp_server_name, (void *)id);
723 SILC_LOG_DEBUG(("Stat request"));
725 ret = silc_buffer_unformat(&buf,
726 SILC_STR_UI_INT(&id),
727 SILC_STR_UI32_STRING_ALLOC(&path),
733 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
735 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
736 server->monitor_context);
740 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
741 silc_sftp_server_attr, (void *)id);
747 case SILC_SFTP_LSTAT:
749 SILC_LOG_DEBUG(("Lstat request"));
751 ret = silc_buffer_unformat(&buf,
752 SILC_STR_UI_INT(&id),
753 SILC_STR_UI32_STRING_ALLOC(&path),
759 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
761 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
762 server->monitor_context);
765 /* Lstat operation */
766 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
767 silc_sftp_server_attr, (void *)id);
773 case SILC_SFTP_FSTAT:
775 unsigned char *hdata;
778 SILC_LOG_DEBUG(("Fstat request"));
780 ret = silc_buffer_unformat(&buf,
781 SILC_STR_UI_INT(&id),
782 SILC_STR_UI32_NSTRING(&hdata,
789 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
790 (const unsigned char *)hdata,
793 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
798 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
799 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
800 server->monitor_context);
803 /* Fstat operation */
804 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
805 silc_sftp_server_attr, (void *)id);
809 case SILC_SFTP_SETSTAT:
811 unsigned char *attr_buf;
813 SilcBufferStruct tmpbuf;
815 SILC_LOG_DEBUG(("Setstat request"));
817 ret = silc_buffer_unformat(&buf,
818 SILC_STR_UI_INT(&id),
819 SILC_STR_UI32_STRING_ALLOC(&path),
820 SILC_STR_UI32_NSTRING(&attr_buf,
827 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
828 attrs = silc_sftp_attr_decode(&tmpbuf);
830 attrs = silc_calloc(1, sizeof(*attrs));
834 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
836 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
837 server->monitor_context);
840 /* Setstat operation */
841 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
842 silc_sftp_server_status, (void *)id);
844 silc_sftp_attr_free(attrs);
849 case SILC_SFTP_FSETSTAT:
851 unsigned char *hdata, *attr_buf;
852 uint32 hdata_len, attr_len = 0;
853 SilcBufferStruct tmpbuf;
855 SILC_LOG_DEBUG(("Fsetstat request"));
857 ret = silc_buffer_unformat(&buf,
858 SILC_STR_UI_INT(&id),
859 SILC_STR_UI32_NSTRING(&hdata,
861 SILC_STR_UI32_NSTRING(&attr_buf,
868 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
869 attrs = silc_sftp_attr_decode(&tmpbuf);
871 attrs = silc_calloc(1, sizeof(*attrs));
875 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
876 (const unsigned char *)hdata,
879 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
884 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
885 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
886 server->monitor_context);
889 /* Fsetstat operation */
890 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
892 silc_sftp_server_status, (void *)id);
894 silc_sftp_attr_free(attrs);
898 case SILC_SFTP_READLINK:
900 SILC_LOG_DEBUG(("Readlink request"));
902 ret = silc_buffer_unformat(&buf,
903 SILC_STR_UI_INT(&id),
904 SILC_STR_UI32_STRING_ALLOC(&path),
910 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
912 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
913 server->monitor_context);
916 /* Readlink operation */
917 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
918 silc_sftp_server_name, (void *)id);
924 case SILC_SFTP_SYMLINK:
928 SILC_LOG_DEBUG(("Symlink request"));
930 ret = silc_buffer_unformat(&buf,
931 SILC_STR_UI_INT(&id),
932 SILC_STR_UI32_STRING_ALLOC(&path),
933 SILC_STR_UI32_STRING_ALLOC(&target),
939 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
941 mdata.name2 = target;
942 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
943 server->monitor_context);
946 /* Symlink operation */
947 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
948 silc_sftp_server_status, (void *)id);
955 case SILC_SFTP_REALPATH:
957 SILC_LOG_DEBUG(("Realpath request"));
959 ret = silc_buffer_unformat(&buf,
960 SILC_STR_UI_INT(&id),
961 SILC_STR_UI32_STRING_ALLOC(&path),
967 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
969 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
970 server->monitor_context);
973 /* Realpath operation */
974 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
975 silc_sftp_server_name, (void *)id);
981 case SILC_SFTP_EXTENDED:
983 char *request = NULL;
987 SILC_LOG_DEBUG(("Extended request"));
989 ret = silc_buffer_unformat(&buf,
990 SILC_STR_UI_INT(&id),
991 SILC_STR_UI32_STRING_ALLOC(&request),
996 data_len = 8 + strlen(request);
997 silc_buffer_pull(&buf, data_len);
998 ret = silc_buffer_unformat(&buf,
999 SILC_STR_UI_XNSTRING(&data, buf.len),
1006 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1007 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1008 server->monitor_context);
1011 /* Extended operation */
1012 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1013 request, data, data_len,
1014 silc_sftp_server_extended, (void *)id);
1027 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);