]> git.hungrycats.org Git - linux/commitdiff
ncpfs: Pass unknown packets from server to userspace daemon. Now we can
authorPetr Vandrovec <vandrove@vc.cvut.cz>
Sat, 21 Sep 2002 00:24:32 +0000 (02:24 +0200)
committerPetr Vandrovec <vandrove@vc.cvut.cz>
Sat, 21 Sep 2002 00:24:32 +0000 (02:24 +0200)
deliver server messages to logged-in users even with UDP or TCP transport.

fs/ncpfs/inode.c
fs/ncpfs/sock.c
include/linux/ncp_fs_sb.h
include/linux/ncp_mount.h

index a6b7004205a392c473e674bef7757bfa2c85e43c..048f4e0f4b53d0acdf2022b360ce01cfe5fc1ce9 100644 (file)
@@ -307,6 +307,7 @@ static const struct ncp_option ncp_opts[] = {
        { "flags",      OPT_INT,        'f' },
        { "wdogpid",    OPT_INT,        'w' },
        { "ncpfd",      OPT_INT,        'n' },
+       { "infofd",     OPT_INT,        'i' },  /* v5 */
        { "version",    OPT_INT,        'v' },
        { NULL,         0,              0 } };
 
@@ -327,6 +328,7 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
        data->gid = 0;
        data->file_mode = 0600;
        data->dir_mode = 0700;
+       data->info_fd = -1;
        data->mounted_vol[0] = 0;
        
        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
@@ -363,11 +365,14 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
                        case 'n':
                                data->ncp_fd = optint;
                                break;
+                       case 'i':
+                               data->info_fd = optint;
+                               break;
                        case 'v':
                                if (optint < NCP_MOUNT_VERSION_V4) {
                                        return -ECHRNG;
                                }
-                               if (optint > NCP_MOUNT_VERSION_V4) {
+                               if (optint > NCP_MOUNT_VERSION_V5) {
                                        return -ECHRNG;
                                }
                                version = optint;
@@ -418,6 +423,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                data.gid = md->gid;
                                data.file_mode = md->file_mode;
                                data.dir_mode = md->dir_mode;
+                               data.info_fd = -1;
                                memcpy(data.mounted_vol, md->mounted_vol,
                                        NCP_VOLNAME_LEN+1);
                        }
@@ -437,6 +443,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                data.gid = md->gid;
                                data.file_mode = md->file_mode;
                                data.dir_mode = md->dir_mode;
+                               data.info_fd = -1;
                                data.mounted_vol[0] = 0;
                        }
                        break;
@@ -478,6 +485,26 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server->ncp_filp = ncp_filp;
        server->ncp_sock = sock;
        
+       if (data.info_fd != -1) {
+               struct socket *info_sock;
+
+               error = -EBADF;
+               server->info_filp = fget(data.info_fd);
+               if (!server->info_filp)
+                       goto out_fput;
+               error = -ENOTSOCK;
+               sock_inode = server->info_filp->f_dentry->d_inode;
+               if (!S_ISSOCK(sock_inode->i_mode))
+                       goto out_fput2;
+               info_sock = SOCKET_I(sock_inode);
+               if (!info_sock)
+                       goto out_fput2;
+               error = -EBADFD;
+               if (info_sock->type != SOCK_STREAM)
+                       goto out_fput2;
+               server->info_sock = info_sock;
+       }
+
 /*     server->lock = 0;       */
        init_MUTEX(&server->sem);
        server->packet = NULL;
@@ -630,6 +657,9 @@ out_nls:
        unload_nls(server->nls_io);
        unload_nls(server->nls_vol);
 #endif
+out_fput2:
+       if (server->info_filp)
+               fput(server->info_filp);
 out_fput:
        /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
         * 
@@ -667,6 +697,8 @@ static void ncp_put_super(struct super_block *sb)
        }
 #endif /* CONFIG_NCPFS_NLS */
 
+       if (server->info_filp)
+               fput(server->info_filp);
        fput(server->ncp_filp);
        kill_proc(server->m.wdog_pid, SIGTERM, 1);
 
index 5e11e90ed333fe3f29cee0f44d5a3538a4bd2fec..f399d7065dc33395c9696c8478142a522a56ef59 100644 (file)
@@ -336,6 +336,31 @@ static void __ncp_next_request(struct ncp_server *server) {
        __ncp_start_request(server, req);
 }
 
+static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) {
+       if (server->info_sock) {
+               struct iovec iov[2];
+               struct msghdr msg;
+               __u32 hdr[2];
+       
+               hdr[0] = cpu_to_be32(len + 8);
+               hdr[1] = cpu_to_be32(id);
+       
+               iov[0].iov_base = hdr;
+               iov[0].iov_len = 8;
+               iov[1].iov_base = (void *) data;
+               iov[1].iov_len = len;
+
+               msg.msg_name = NULL;
+               msg.msg_namelen = 0;
+               msg.msg_control = NULL;
+               msg.msg_iov = iov;
+               msg.msg_iovlen = 2;
+               msg.msg_flags = MSG_NOSIGNAL;
+
+               sock_sendmsg(server->info_sock, &msg, len + 8);
+       }
+}
+
 static void __ncpdgram_rcv_proc(void *s) {
        struct ncp_server *server = s;
        struct socket* sock;
@@ -376,6 +401,14 @@ static void __ncpdgram_rcv_proc(void *s) {
                                _send(sock, buf, sizeof(buf));
                                continue;
                        }
+                       if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
+                               result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
+                               if (result < 0) {
+                                       continue;
+                               }
+                               info_server(server, 0, server->unexpected_packet.data, result);
+                               continue;
+                       }
                        down(&server->rcv.creq_sem);            
                        req = server->rcv.creq;
                        if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
@@ -556,6 +589,15 @@ static int __ncptcp_rcv_proc(struct ncp_server *server) {
                                type = ntohs(server->rcv.buf.type);
 cont:;                         
                                if (type != NCP_REPLY) {
+                                       if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
+                                               *(__u16*)(server->unexpected_packet.data) = htons(type);
+                                               server->unexpected_packet.len = datalen - 8;
+
+                                               server->rcv.state = 5;
+                                               server->rcv.ptr = server->unexpected_packet.data + 2;
+                                               server->rcv.len = datalen - 10;
+                                               break;
+                                       }                                       
                                        DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
 skipdata2:;
                                        server->rcv.state = 2;
@@ -613,6 +655,7 @@ skipdata:;
                        nextreq:;
                                __ncp_next_request(server);
                        case 2:
+                       next:;
                                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
                                server->rcv.len = 10;
                                server->rcv.state = 0;
@@ -620,6 +663,9 @@ skipdata:;
                        case 3:
                                ncp_finish_request(server->rcv.creq, -EIO);
                                goto nextreq;
+                       case 5:
+                               info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
+                               goto next;
                }
        }
 }
index 375c8511ca25dd7ce42e10871aa8070efaa7537b..02ef9bb50b51e3bb6306e02f8d54d02523c11d24 100644 (file)
@@ -27,6 +27,8 @@ struct ncp_server {
 
        struct file *ncp_filp;  /* File pointer to ncp socket */
        struct socket *ncp_sock;/* ncp socket */
+       struct file *info_filp;
+       struct socket *info_sock;
 
        u8 sequence;
        u8 task;
@@ -115,6 +117,10 @@ struct ncp_server {
        struct tq_struct timeout_tq;            /* DGRAM only: associated queue, we run timers from process context */
        int timeout_last;                       /* DGRAM only: current timeout length */
        int timeout_retries;                    /* DGRAM only: retries left */
+       struct {
+               size_t len;
+               __u8 data[128];
+       } unexpected_packet;
 };
 
 extern void ncp_tcp_rcv_proc(void *server);
index 38880685f6f6a600b3c8ebfc48b38975e56131bc..f46bddcdbd3bed4040c6201725e28972d19d523b 100644 (file)
@@ -66,6 +66,8 @@ struct ncp_mount_data_v4 {
        unsigned long dir_mode;
 };
 
+#define NCP_MOUNT_VERSION_V5   (5)     /* Text only */
+
 #ifdef __KERNEL__
 
 struct ncp_mount_data_kernel {
@@ -83,6 +85,7 @@ struct ncp_mount_data_kernel {
        __kernel_gid32_t gid;
        __kernel_mode_t  file_mode;
        __kernel_mode_t  dir_mode;
+       int              info_fd;
 };
 
 #endif /* __KERNEL__ */