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;
37 /* General routine to send SFTP packet to the SFTP client. */
39 static void silc_sftp_send_packet(SilcSFTPServer sftp,
47 packet = silc_sftp_packet_encode_vp(type, len, vp);
53 SILC_LOG_HEXDUMP(("SFTP packet to client"), packet->data, packet->len);
56 (*sftp->send_packet)(sftp->sock, packet, sftp->send_context);
58 silc_buffer_free(packet);
61 /* Sends error to the client */
63 static void silc_sftp_send_error(SilcSFTPServer sftp,
64 SilcSFTPStatus status,
67 SILC_LOG_DEBUG(("Send error %d", status));
69 silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16,
71 SILC_STR_UI_INT(status),
72 SILC_STR_UI_INT(0), /* Error */
73 SILC_STR_UI_INT(0), /* Language tag */
79 static void silc_sftp_server_status(SilcSFTP sftp,
80 SilcSFTPStatus status,
82 const char *language_tag,
85 SilcSFTPServer server = (SilcSFTPServer)sftp;
86 uint32 id = (uint32)context;
89 SILC_LOG_DEBUG(("Status callback"));
90 SILC_LOG_DEBUG(("Request ID: %d", id));
96 mlen = strlen(message);
97 llen = strlen(language_tag);
99 silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen,
101 SILC_STR_UI_INT(status),
102 SILC_STR_UI_INT(mlen),
103 SILC_STR_UI32_STRING(message),
104 SILC_STR_UI_INT(llen),
105 SILC_STR_UI32_STRING(language_tag),
109 /* Handle callback */
111 static void silc_sftp_server_handle(SilcSFTP sftp,
112 SilcSFTPStatus status,
113 SilcSFTPHandle handle,
116 SilcSFTPServer server = (SilcSFTPServer)sftp;
117 uint32 id = (uint32)context;
118 unsigned char *hdata;
121 SILC_LOG_DEBUG(("Handle callback"));
122 SILC_LOG_DEBUG(("Request ID: %d", id));
124 if (status != SILC_SFTP_STATUS_OK) {
125 silc_sftp_send_error(server, status, id);
129 hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
132 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
136 silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len,
138 SILC_STR_UI_INT(hdata_len),
139 SILC_STR_UI_XNSTRING(hdata, hdata_len),
145 static void silc_sftp_server_data(SilcSFTP sftp,
146 SilcSFTPStatus status,
147 const unsigned char *data,
151 SilcSFTPServer server = (SilcSFTPServer)sftp;
152 uint32 id = (uint32)context;
154 SILC_LOG_DEBUG(("Data callback"));
155 SILC_LOG_DEBUG(("Request ID: %d", id));
157 if (status != SILC_SFTP_STATUS_OK) {
158 silc_sftp_send_error(server, status, id);
162 silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len,
164 SILC_STR_UI_INT(data_len),
165 SILC_STR_UI_XNSTRING(data, data_len),
171 static void silc_sftp_server_name(SilcSFTP sftp,
172 SilcSFTPStatus status,
173 const SilcSFTPName name,
176 SilcSFTPServer server = (SilcSFTPServer)sftp;
177 uint32 id = (uint32)context;
180 SILC_LOG_DEBUG(("Name callback"));
181 SILC_LOG_DEBUG(("Request ID: %d", id));
183 if (status != SILC_SFTP_STATUS_OK) {
184 silc_sftp_send_error(server, status, id);
188 namebuf = silc_sftp_name_encode(name);
190 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
194 silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + namebuf->len,
196 SILC_STR_UI_XNSTRING(namebuf->data, namebuf->len),
200 /* Attributes callback */
202 static void silc_sftp_server_attr(SilcSFTP sftp,
203 SilcSFTPStatus status,
204 const SilcSFTPAttributes attrs,
207 SilcSFTPServer server = (SilcSFTPServer)sftp;
208 uint32 id = (uint32)context;
211 SILC_LOG_DEBUG(("Attr callback"));
212 SILC_LOG_DEBUG(("Request ID: %d", id));
214 if (status != SILC_SFTP_STATUS_OK) {
215 silc_sftp_send_error(server, status, id);
219 attr_buf = silc_sftp_attr_encode(attrs);
221 silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len,
223 SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len),
226 silc_buffer_free(attr_buf);
229 /* Extended callback */
231 static void silc_sftp_server_extended(SilcSFTP sftp,
232 SilcSFTPStatus status,
233 const unsigned char *data,
237 SilcSFTPServer server = (SilcSFTPServer)sftp;
238 uint32 id = (uint32)context;
240 SILC_LOG_DEBUG(("Extended callback"));
241 SILC_LOG_DEBUG(("Request ID: %d", id));
243 if (status != SILC_SFTP_STATUS_OK) {
244 silc_sftp_send_error(server, status, id);
248 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
250 SILC_STR_UI_XNSTRING(data, data_len),
254 /* Starts SFTP server by associating the socket connection `sock' to the
255 created SFTP server context. This function returns the allocated
256 SFTP client context or NULL on error. The `send_packet' is called
257 by the library when it needs to send a packet. The `fs' is the
258 structure containing filesystem access callbacks. */
260 SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
261 SilcSFTPSendPacketCallback send_packet,
263 SilcSFTPFilesystem fs)
265 SilcSFTPServer server;
267 server = silc_calloc(1, sizeof(*server));
269 server->send_packet = send_packet;
270 server->send_context = send_context;
273 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
275 return (SilcSFTP)server;
278 /* Shutdown's the SFTP server. The caller is responsible of closing
279 the associated socket connection. The SFTP context is freed and is
280 invalid after this function returns. */
282 void silc_sftp_server_shutdown(SilcSFTP sftp)
284 SilcSFTPServer server = (SilcSFTPServer)sftp;
286 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
291 /* Sets monitor callback */
293 void silc_sftp_server_set_monitor(SilcSFTP sftp,
294 SilcSFTPMonitors monitors,
295 SilcSFTPMonitor monitor,
298 SilcSFTPServer server = (SilcSFTPServer)sftp;
299 server->monitors = monitors;
300 server->monitor = monitor;
301 server->monitor_context = context;
304 /* Function that is called to process the incmoing SFTP packet. */
305 /* XXX Some day this will go away and we have automatic receive callbacks
306 for SilcSocketConnection API or SilcPacketContext API. */
308 void silc_sftp_server_receive_process(SilcSFTP sftp,
309 SilcSocketConnection sock,
310 SilcPacketContext *packet)
312 SilcSFTPServer server = (SilcSFTPServer)sftp;
314 char *filename = NULL, *path = NULL;
315 const unsigned char *payload = NULL;
318 SilcBufferStruct buf;
320 SilcSFTPAttributes attrs;
321 SilcSFTPHandle handle;
322 SilcSFTPMonitorDataStruct mdata;
324 SILC_LOG_DEBUG(("Start"));
326 /* Parse the packet */
327 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
332 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
334 memset(&mdata, 0, sizeof(mdata));
339 SilcSFTPVersion version;
341 SILC_LOG_DEBUG(("Init request"));
343 ret = silc_buffer_unformat(&buf,
344 SILC_STR_UI_INT(&version),
350 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
351 mdata.version = version;
352 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
353 server->monitor_context);
356 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
357 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
364 SilcSFTPFileOperation pflags;
365 unsigned char *attr_buf;
367 SilcBufferStruct tmpbuf;
369 SILC_LOG_DEBUG(("Open request"));
371 ret = silc_buffer_unformat(&buf,
372 SILC_STR_UI_INT(&id),
373 SILC_STR_UI32_STRING_ALLOC(&filename),
374 SILC_STR_UI_INT(&pflags),
375 SILC_STR_UI32_NSTRING(&attr_buf,
382 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
383 attrs = silc_sftp_attr_decode(&tmpbuf);
385 attrs = silc_calloc(1, sizeof(*attrs));
389 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
390 mdata.name = filename;
391 mdata.pflags = pflags;
392 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
393 server->monitor_context);
397 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
398 attrs, silc_sftp_server_handle, (void *)id);
401 silc_sftp_attr_free(attrs);
405 case SILC_SFTP_CLOSE:
407 unsigned char *hdata;
410 SILC_LOG_DEBUG(("Close request"));
412 ret = silc_buffer_unformat(&buf,
413 SILC_STR_UI_INT(&id),
414 SILC_STR_UI32_NSTRING(&hdata,
421 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
422 (const unsigned char *)hdata,
425 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
430 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
431 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
432 server->monitor_context);
435 /* Close operation */
436 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
437 silc_sftp_server_status, (void *)id);
443 unsigned char *hdata;
448 SILC_LOG_DEBUG(("Read request"));
450 ret = silc_buffer_unformat(&buf,
451 SILC_STR_UI_INT(&id),
452 SILC_STR_UI32_NSTRING(&hdata,
454 SILC_STR_UI_INT64(&offset),
455 SILC_STR_UI_INT(&len),
461 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
462 (const unsigned char *)hdata,
465 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
470 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
471 mdata.offset = offset;
472 mdata.data_len = len;
473 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
474 server->monitor_context);
478 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
480 silc_sftp_server_data, (void *)id);
484 case SILC_SFTP_WRITE:
486 unsigned char *hdata;
492 SILC_LOG_DEBUG(("Read request"));
494 ret = silc_buffer_unformat(&buf,
495 SILC_STR_UI_INT(&id),
496 SILC_STR_UI32_NSTRING(&hdata,
498 SILC_STR_UI_INT64(&offset),
499 SILC_STR_UI32_NSTRING(&data,
506 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
507 (const unsigned char *)hdata,
510 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
515 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
516 mdata.offset = offset;
517 mdata.data_len = data_len;
518 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
519 server->monitor_context);
522 /* Write operation */
523 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
524 (const unsigned char *)data, data_len,
525 silc_sftp_server_status, (void *)id);
529 case SILC_SFTP_REMOVE:
531 SILC_LOG_DEBUG(("Remove request"));
533 ret = silc_buffer_unformat(&buf,
534 SILC_STR_UI_INT(&id),
535 SILC_STR_UI32_STRING_ALLOC(&filename),
541 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
542 mdata.name = filename;
543 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
544 server->monitor_context);
547 /* Remove operation */
548 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
549 silc_sftp_server_status, (void *)id);
555 case SILC_SFTP_RENAME:
557 char *newname = NULL;
559 SILC_LOG_DEBUG(("Rename request"));
561 ret = silc_buffer_unformat(&buf,
562 SILC_STR_UI_INT(&id),
563 SILC_STR_UI32_STRING_ALLOC(&filename),
564 SILC_STR_UI32_STRING_ALLOC(&newname),
570 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
571 mdata.name = filename;
572 mdata.name2 = newname;
573 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
574 server->monitor_context);
577 /* Rename operation */
578 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
580 silc_sftp_server_status, (void *)id);
587 case SILC_SFTP_MKDIR:
589 unsigned char *attr_buf;
591 SilcBufferStruct tmpbuf;
593 SILC_LOG_DEBUG(("Mkdir request"));
595 ret = silc_buffer_unformat(&buf,
596 SILC_STR_UI_INT(&id),
597 SILC_STR_UI32_STRING_ALLOC(&path),
598 SILC_STR_UI32_NSTRING(&attr_buf,
605 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
606 attrs = silc_sftp_attr_decode(&tmpbuf);
608 attrs = silc_calloc(1, sizeof(*attrs));
612 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
614 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
615 server->monitor_context);
618 /* Mkdir operation */
619 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
620 silc_sftp_server_status, (void *)id);
622 silc_sftp_attr_free(attrs);
627 case SILC_SFTP_RMDIR:
629 SILC_LOG_DEBUG(("Rmdir request"));
631 ret = silc_buffer_unformat(&buf,
632 SILC_STR_UI_INT(&id),
633 SILC_STR_UI32_STRING_ALLOC(&path),
639 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
641 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
642 server->monitor_context);
645 /* Rmdir operation */
646 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
647 silc_sftp_server_status, (void *)id);
653 case SILC_SFTP_OPENDIR:
655 SILC_LOG_DEBUG(("Opendir request"));
657 ret = silc_buffer_unformat(&buf,
658 SILC_STR_UI_INT(&id),
659 SILC_STR_UI32_STRING_ALLOC(&path),
665 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
667 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
668 server->monitor_context);
671 /* Opendir operation */
672 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
673 silc_sftp_server_handle, (void *)id);
679 case SILC_SFTP_READDIR:
681 unsigned char *hdata;
684 SILC_LOG_DEBUG(("Readdir request"));
686 ret = silc_buffer_unformat(&buf,
687 SILC_STR_UI_INT(&id),
688 SILC_STR_UI32_NSTRING(&hdata,
695 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
696 (const unsigned char *)hdata,
699 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
704 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
705 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
706 server->monitor_context);
709 /* Readdir operation */
710 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
711 silc_sftp_server_name, (void *)id);
717 SILC_LOG_DEBUG(("Stat request"));
719 ret = silc_buffer_unformat(&buf,
720 SILC_STR_UI_INT(&id),
721 SILC_STR_UI32_STRING_ALLOC(&path),
727 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
729 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
730 server->monitor_context);
734 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
735 silc_sftp_server_attr, (void *)id);
741 case SILC_SFTP_LSTAT:
743 SILC_LOG_DEBUG(("Lstat request"));
745 ret = silc_buffer_unformat(&buf,
746 SILC_STR_UI_INT(&id),
747 SILC_STR_UI32_STRING_ALLOC(&path),
753 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
755 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
756 server->monitor_context);
759 /* Lstat operation */
760 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
761 silc_sftp_server_attr, (void *)id);
767 case SILC_SFTP_FSTAT:
769 unsigned char *hdata;
772 SILC_LOG_DEBUG(("Fstat request"));
774 ret = silc_buffer_unformat(&buf,
775 SILC_STR_UI_INT(&id),
776 SILC_STR_UI32_NSTRING(&hdata,
783 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
784 (const unsigned char *)hdata,
787 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
792 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
793 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
794 server->monitor_context);
797 /* Fstat operation */
798 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
799 silc_sftp_server_attr, (void *)id);
803 case SILC_SFTP_SETSTAT:
805 unsigned char *attr_buf;
807 SilcBufferStruct tmpbuf;
809 SILC_LOG_DEBUG(("Setstat request"));
811 ret = silc_buffer_unformat(&buf,
812 SILC_STR_UI_INT(&id),
813 SILC_STR_UI32_STRING_ALLOC(&path),
814 SILC_STR_UI32_NSTRING(&attr_buf,
821 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
822 attrs = silc_sftp_attr_decode(&tmpbuf);
824 attrs = silc_calloc(1, sizeof(*attrs));
828 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
830 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
831 server->monitor_context);
834 /* Setstat operation */
835 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
836 silc_sftp_server_status, (void *)id);
838 silc_sftp_attr_free(attrs);
843 case SILC_SFTP_FSETSTAT:
845 unsigned char *hdata, *attr_buf;
846 uint32 hdata_len, attr_len = 0;
847 SilcBufferStruct tmpbuf;
849 SILC_LOG_DEBUG(("Fsetstat request"));
851 ret = silc_buffer_unformat(&buf,
852 SILC_STR_UI_INT(&id),
853 SILC_STR_UI32_NSTRING(&hdata,
855 SILC_STR_UI32_NSTRING(&attr_buf,
862 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
863 attrs = silc_sftp_attr_decode(&tmpbuf);
865 attrs = silc_calloc(1, sizeof(*attrs));
869 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
870 (const unsigned char *)hdata,
873 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
878 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
879 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
880 server->monitor_context);
883 /* Fsetstat operation */
884 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
886 silc_sftp_server_status, (void *)id);
888 silc_sftp_attr_free(attrs);
892 case SILC_SFTP_READLINK:
894 SILC_LOG_DEBUG(("Readlink request"));
896 ret = silc_buffer_unformat(&buf,
897 SILC_STR_UI_INT(&id),
898 SILC_STR_UI32_STRING_ALLOC(&path),
904 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
906 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
907 server->monitor_context);
910 /* Readlink operation */
911 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
912 silc_sftp_server_name, (void *)id);
918 case SILC_SFTP_SYMLINK:
922 SILC_LOG_DEBUG(("Symlink request"));
924 ret = silc_buffer_unformat(&buf,
925 SILC_STR_UI_INT(&id),
926 SILC_STR_UI32_STRING_ALLOC(&path),
927 SILC_STR_UI32_STRING_ALLOC(&target),
933 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
935 mdata.name2 = target;
936 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
937 server->monitor_context);
940 /* Symlink operation */
941 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
942 silc_sftp_server_status, (void *)id);
949 case SILC_SFTP_REALPATH:
951 SILC_LOG_DEBUG(("Realpath request"));
953 ret = silc_buffer_unformat(&buf,
954 SILC_STR_UI_INT(&id),
955 SILC_STR_UI32_STRING_ALLOC(&path),
961 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
963 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
964 server->monitor_context);
967 /* Realpath operation */
968 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
969 silc_sftp_server_name, (void *)id);
975 case SILC_SFTP_EXTENDED:
977 char *request = NULL;
981 SILC_LOG_DEBUG(("Extended request"));
983 ret = silc_buffer_unformat(&buf,
984 SILC_STR_UI_INT(&id),
985 SILC_STR_UI32_STRING_ALLOC(&request),
990 data_len = 8 + strlen(request);
991 silc_buffer_pull(&buf, data_len);
992 ret = silc_buffer_unformat(&buf,
993 SILC_STR_UI_XNSTRING(&data, buf.len),
1000 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1001 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1002 server->monitor_context);
1005 /* Extended operation */
1006 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1007 request, data, data_len,
1008 silc_sftp_server_extended, (void *)id);
1021 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);