struct super_block * ncp_read_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data; struct ncp_server *server; struct file *ncp_filp; struct file *wdog_filp; struct file *msg_filp; kdev_t dev = sb->s_dev; int error; if (data == NULL) { printk("ncp_read_super: missing data argument\n"); sb->s_dev = 0; return NULL; } if (data->version != NCP_MOUNT_VERSION) { printk("ncp warning: mount version %s than kernel\n", (data->version < NCP_MOUNT_VERSION) ? "older" : "newer"); sb->s_dev = 0; return NULL; } if ( (data->ncp_fd >= NR_OPEN) || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) { printk("ncp_read_super: invalid ncp socket\n"); sb->s_dev = 0; return NULL; } if ( (data->wdog_fd >= NR_OPEN) || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL) || (!S_ISSOCK(wdog_filp->f_inode->i_mode))) { printk("ncp_read_super: invalid wdog socket\n"); sb->s_dev = 0; return NULL; } if ( (data->message_fd >= NR_OPEN) || ((msg_filp = current->files->fd[data->message_fd]) == NULL) || (!S_ISSOCK(msg_filp->f_inode->i_mode))) { printk("ncp_read_super: invalid wdog socket\n"); sb->s_dev = 0; return NULL; } /* We must malloc our own super-block info */ server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server), GFP_KERNEL); if (server == NULL) { printk("ncp_read_super: could not alloc ncp_server\n"); return NULL; } ncp_filp->f_count += 1; wdog_filp->f_count += 1; msg_filp->f_count += 1; lock_super(sb); NCP_SBP(sb) = server; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_dev = dev; sb->s_op = &ncp_sops; server->ncp_filp = ncp_filp; server->wdog_filp = wdog_filp; server->msg_filp = msg_filp; server->lock = 0; server->wait = NULL; server->packet = NULL; server->buffer_size = 0; server->conn_status = 0; server->m = *data; server->m.file_mode = (server->m.file_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; /* protect against invalid mount points */ server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0'; server->packet_size = NCP_PACKET_SIZE; server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL); if (server->packet == NULL) { printk("ncpfs: could not alloc packet\n"); error = -ENOMEM; unlock_super(sb); goto fail; } /* * Make the connection to the server */ if (ncp_catch_watchdog(server) != 0) { printk("ncp_read_super: Could not catch watchdog\n"); error = -EINVAL; unlock_super(sb); goto fail; } if (ncp_catch_message(server) != 0) { printk("ncp_read_super: Could not catch messages\n"); ncp_dont_catch_watchdog(server); error = -EINVAL; unlock_super(sb); goto fail; } ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); unlock_super(sb); if (error < 0) { sb->s_dev = 0; printk("ncp_read_super: Failed connection, bailing out " "(error = %d).\n", -error); ncp_kfree_s(server->packet, server->packet_size); ncp_dont_catch_watchdog(server); goto fail; } DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb)); ncp_init_root(server); if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root))))) { sb->s_dev = 0; printk("ncp_read_super: get root inode failed\n"); goto disconnect; } if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE, &(server->buffer_size)) != 0) { sb->s_dev = 0; printk("ncp_read_super: could not get bufsize\n"); goto disconnect; } DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); MOD_INC_USE_COUNT; return sb; disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); ncp_kfree_s(server->packet, server->packet_size); ncp_dont_catch_watchdog(server); fail: ncp_filp->f_count -= 1; wdog_filp->f_count -= 1; msg_filp->f_count -= 1; ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); return NULL; }
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; struct ncp_server *server; struct file *ncp_filp; struct inode *root_inode; struct inode *sock_inode; struct socket *sock; int error; int default_bufsize; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncp_entry_info finfo; data.wdog_pid = NULL; server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); if (!server) return -ENOMEM; sb->s_fs_info = server; error = -EFAULT; if (raw_data == NULL) goto out; switch (*(int*)raw_data) { case NCP_MOUNT_VERSION: { struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; data.flags = md->flags; data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; data.mounted_uid = md->mounted_uid; data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = md->uid; 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); } break; case NCP_MOUNT_VERSION_V4: { struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; data.flags = md->flags; data.int_flags = 0; data.mounted_uid = md->mounted_uid; data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = md->uid; 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; default: error = -ECHRNG; if (memcmp(raw_data, "vers", 4) == 0) { error = ncp_parse_options(&data, raw_data); } if (error) goto out; break; } error = -EBADF; ncp_filp = fget(data.ncp_fd); if (!ncp_filp) goto out; error = -ENOTSOCK; sock_inode = ncp_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput; sock = SOCKET_I(sock_inode); if (!sock) goto out_fput; if (sock->type == SOCK_STREAM) default_bufsize = 0xF000; else default_bufsize = 1024; sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ sb->s_maxbytes = 0xFFFFFFFFU; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_op = &ncp_sops; server = NCP_SBP(sb); memset(server, 0, sizeof(*server)); 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_path.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; */ mutex_init(&server->mutex); server->packet = NULL; /* server->buffer_size = 0; */ /* server->conn_status = 0; */ /* server->root_dentry = NULL; */ /* server->root_setuped = 0; */ #ifdef CONFIG_NCPFS_PACKET_SIGNING /* server->sign_wanted = 0; */ /* server->sign_active = 0; */ #endif server->auth.auth_type = NCP_AUTH_NONE; /* server->auth.object_name_len = 0; */ /* server->auth.object_name = NULL; */ /* server->auth.object_type = 0; */ /* server->priv.len = 0; */ /* server->priv.data = NULL; */ server->m = data; /* Althought anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 1) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.time_out = server->m.time_out * HZ / 100; server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; #ifdef CONFIG_NCPFS_NLS /* load the default NLS charsets */ server->nls_vol = load_nls_default(); server->nls_io = load_nls_default(); #endif /* CONFIG_NCPFS_NLS */ server->dentry_ttl = 0; /* no caching */ INIT_LIST_HEAD(&server->tx.requests); mutex_init(&server->rcv.creq_mutex); server->tx.creq = NULL; server->rcv.creq = NULL; server->data_ready = sock->sk->sk_data_ready; server->write_space = sock->sk->sk_write_space; server->error_report = sock->sk->sk_error_report; sock->sk->sk_user_data = server; init_timer(&server->timeout_tm); #undef NCP_PACKET_SIZE #define NCP_PACKET_SIZE 131072 error = -ENOMEM; server->packet_size = NCP_PACKET_SIZE; server->packet = vmalloc(NCP_PACKET_SIZE); if (server->packet == NULL) goto out_nls; server->txbuf = vmalloc(NCP_PACKET_SIZE); if (server->txbuf == NULL) goto out_packet; server->rxbuf = vmalloc(NCP_PACKET_SIZE); if (server->rxbuf == NULL) goto out_txbuf; sock->sk->sk_data_ready = ncp_tcp_data_ready; sock->sk->sk_error_report = ncp_tcp_error_report; if (sock->type == SOCK_STREAM) { server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_rxbuf; DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ #ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, default_bufsize, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, default_bufsize, options & 2, &(server->buffer_size), &options) != 0) { goto out_disconnect; } } if (options & 2) server->sign_wanted = 1; } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, default_bufsize, &(server->buffer_size)) != 0) goto out_disconnect; DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); memset(&finfo, 0, sizeof(finfo)); finfo.i.attributes = aDIR; finfo.i.dataStreamSize = 0; /* ignored */ finfo.i.dirEntNum = 0; finfo.i.DosDirNum = 0; #ifdef CONFIG_NCPFS_SMALLDOS finfo.i.NSCreator = NW_NS_DOS; #endif finfo.volume = NCP_NUMBER_OF_VOLUMES; /* set dates of mountpoint to Jan 1, 1986; 00:00 */ finfo.i.creationTime = finfo.i.modifyTime = cpu_to_le16(0x0000); finfo.i.creationDate = finfo.i.modifyDate = finfo.i.lastAccessDate = cpu_to_le16(0x0C21); finfo.i.nameLen = 0; finfo.i.entryName[0] = '\0'; finfo.opened = 0; finfo.ino = 2; /* tradition */ server->name_space[finfo.volume] = NW_NS_DOS; error = -ENOMEM; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_disconnect; DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) goto out_no_root; sb->s_root->d_op = &ncp_root_dentry_operations; return 0; out_no_root: iput(root_inode); out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); out_rxbuf: ncp_stop_tasks(server); vfree(server->rxbuf); out_txbuf: vfree(server->txbuf); out_packet: vfree(server->packet); out_nls: #ifdef CONFIG_NCPFS_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 <*****@*****.**>: * * The previously used put_filp(ncp_filp); was bogous, since * it doesn't proper unlocking. */ fput(ncp_filp); out: put_pid(data.wdog_pid); sb->s_fs_info = NULL; kfree(server); return error; }
struct super_block * ncp_read_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data; struct ncp_server *server; struct file *ncp_filp; struct inode *root_inode; kdev_t dev = sb->s_dev; int error; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncpfs_inode_info finfo; MOD_INC_USE_COUNT; if (data == NULL) goto out_no_data; if (data->version != NCP_MOUNT_VERSION) goto out_bad_mount; ncp_filp = fget(data->ncp_fd); if (!ncp_filp) goto out_bad_file; if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode)) goto out_bad_file2; lock_super(sb); sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_dev = dev; sb->s_op = &ncp_sops; /* We must malloc our own super-block info */ server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server), GFP_KERNEL); if (server == NULL) goto out_no_server; NCP_SBP(sb) = server; server->ncp_filp = ncp_filp; server->lock = 0; server->wait = NULL; server->packet = NULL; server->buffer_size = 0; server->conn_status = 0; server->root_dentry = NULL; server->root_setuped = 0; #ifdef CONFIG_NCPFS_PACKET_SIGNING server->sign_wanted = 0; server->sign_active = 0; #endif server->auth.auth_type = NCP_AUTH_NONE; server->auth.object_name_len = 0; server->auth.object_name = NULL; server->auth.object_type = 0; server->priv.len = 0; server->priv.data = NULL; server->m = *data; /* Althought anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 10) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.file_mode = (server->m.file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; server->packet_size = NCP_PACKET_SIZE; server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL); if (server->packet == NULL) goto out_no_packet; ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_no_connect; DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); #ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE, options & 2, &(server->buffer_size), &options) != 0) { goto out_no_bufsize; } } if (options & 2) server->sign_wanted = 1; } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE, &(server->buffer_size)) != 0) goto out_no_bufsize; DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size); ncp_init_root(server, &finfo); server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_no_root; DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL); if (!sb->s_root) goto out_no_root; server->root_dentry->d_op = &ncp_dentry_operations; unlock_super(sb); return sb; out_no_root: printk(KERN_ERR "ncp_read_super: get root inode failed\n"); iput(root_inode); goto out_disconnect; out_no_bufsize: printk(KERN_ERR "ncp_read_super: could not get bufsize\n"); out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); goto out_free_packet; out_no_connect: printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error); out_free_packet: ncp_kfree_s(server->packet, server->packet_size); goto out_free_server; out_no_packet: printk(KERN_ERR "ncp_read_super: could not alloc packet\n"); out_free_server: ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); goto out_unlock; out_no_server: printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n"); out_unlock: /* 23/12/1998 Marcin Dalecki <*****@*****.**>: * * The previously used put_filp(ncp_filp); was bogous, since * it doesn't proper unlocking. */ fput(ncp_filp); unlock_super(sb); goto out; out_bad_file2: fput(ncp_filp); out_bad_file: printk(KERN_ERR "ncp_read_super: invalid ncp socket\n"); goto out; out_bad_mount: printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n", NCP_MOUNT_VERSION); goto out; out_no_data: printk(KERN_ERR "ncp_read_super: missing data argument\n"); out: sb->s_dev = 0; MOD_DEC_USE_COUNT; return NULL; }