deliver server messages to logged-in users even with UDP or TCP transport.
{ "flags", OPT_INT, 'f' },
{ "wdogpid", OPT_INT, 'w' },
{ "ncpfd", OPT_INT, 'n' },
+ { "infofd", OPT_INT, 'i' }, /* v5 */
{ "version", OPT_INT, 'v' },
{ NULL, 0, 0 } };
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) {
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;
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);
}
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;
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;
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>:
*
}
#endif /* CONFIG_NCPFS_NLS */
+ if (server->info_filp)
+ fput(server->info_filp);
fput(server->ncp_filp);
kill_proc(server->m.wdog_pid, SIGTERM, 1);
__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;
_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 &&
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;
nextreq:;
__ncp_next_request(server);
case 2:
+ next:;
server->rcv.ptr = (unsigned char*)&server->rcv.buf;
server->rcv.len = 10;
server->rcv.state = 0;
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;
}
}
}
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;
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);
unsigned long dir_mode;
};
+#define NCP_MOUNT_VERSION_V5 (5) /* Text only */
+
#ifdef __KERNEL__
struct ncp_mount_data_kernel {
__kernel_gid32_t gid;
__kernel_mode_t file_mode;
__kernel_mode_t dir_mode;
+ int info_fd;
};
#endif /* __KERNEL__ */