?? sock.c
字號(hào):
/* * sock.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */#include <linux/sched.h>#include <linux/smb_fs.h>#include <linux/errno.h>#include <linux/socket.h>#include <linux/fcntl.h>#include <linux/stat.h>#include <asm/segment.h>#include <linux/in.h>#include <linux/net.h>#include <linux/mm.h>#include <linux/netdevice.h>#include <net/ip.h>#include <linux/smb.h>#include <linux/smbno.h>#define _S(nr) (1<<((nr)-1))static int_recvfrom(struct socket *sock, unsigned char *ubuf, int size, int noblock, unsigned flags, struct sockaddr_in *sa, int *addr_len){ struct iovec iov; struct msghdr msg; iov.iov_base = ubuf; iov.iov_len = size; msg.msg_name = (void *) sa; msg.msg_namelen = 0; if (addr_len) msg.msg_namelen = *addr_len; msg.msg_control = NULL; msg.msg_iov = &iov; msg.msg_iovlen = 1; return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);}static int_send(struct socket *sock, const void *buff, int len, int nonblock, unsigned flags){ struct iovec iov; struct msghdr msg; iov.iov_base = (void *) buff; iov.iov_len = len; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_iov = &iov; msg.msg_iovlen = 1; return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);}static voidsmb_data_callback(struct sock *sk, int len){ struct socket *sock = sk->socket; if (!sk->dead) { unsigned char peek_buf[4]; int result; unsigned short fs; fs = get_fs(); set_fs(get_ds()); result = _recvfrom(sock, (void *) peek_buf, 1, 1, MSG_PEEK, NULL, NULL); while ((result != -EAGAIN) && (peek_buf[0] == 0x85)) { /* got SESSION KEEP ALIVE */ result = _recvfrom(sock, (void *) peek_buf, 4, 1, 0, NULL, NULL); DDPRINTK("smb_data_callback:" " got SESSION KEEP ALIVE\n"); if (result == -EAGAIN) { break; } result = _recvfrom(sock, (void *) peek_buf, 1, 1, MSG_PEEK, NULL, NULL); } set_fs(fs); if (result != -EAGAIN) { wake_up_interruptible(sk->sleep); } }}intsmb_catch_keepalive(struct smb_server *server){ struct file *file; struct inode *inode; struct socket *sock; struct sock *sk; if ((server == NULL) || ((file = server->sock_file) == NULL) || ((inode = file->f_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_catch_keepalive: did not get valid server!\n"); server->data_ready = NULL; return -EINVAL; } sock = &(inode->u.socket_i); if (sock->type != SOCK_STREAM) { printk("smb_catch_keepalive: did not get SOCK_STREAM\n"); server->data_ready = NULL; return -EINVAL; } sk = (struct sock *) (sock->data); if (sk == NULL) { printk("smb_catch_keepalive: sk == NULL"); server->data_ready = NULL; return -EINVAL; } DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n", (unsigned int) (sk->data_ready), (unsigned int) (server->data_ready)); if (sk->data_ready == smb_data_callback) { printk("smb_catch_keepalive: already done\n"); return -EINVAL; } server->data_ready = sk->data_ready; sk->data_ready = smb_data_callback; return 0;}intsmb_dont_catch_keepalive(struct smb_server *server){ struct file *file; struct inode *inode; struct socket *sock; struct sock *sk; if ((server == NULL) || ((file = server->sock_file) == NULL) || ((inode = file->f_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_dont_catch_keepalive: " "did not get valid server!\n"); return -EINVAL; } sock = &(inode->u.socket_i); if (sock->type != SOCK_STREAM) { printk("smb_dont_catch_keepalive: did not get SOCK_STREAM\n"); return -EINVAL; } sk = (struct sock *) (sock->data); if (sk == NULL) { printk("smb_dont_catch_keepalive: sk == NULL"); return -EINVAL; } if (server->data_ready == NULL) { printk("smb_dont_catch_keepalive: " "server->data_ready == NULL\n"); return -EINVAL; } if (sk->data_ready != smb_data_callback) { printk("smb_dont_catch_keepalive: " "sk->data_callback != smb_data_callback\n"); return -EINVAL; } DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n", (unsigned int) (sk->data_ready), (unsigned int) (server->data_ready)); sk->data_ready = server->data_ready; server->data_ready = NULL; return 0;}static intsmb_send_raw(struct socket *sock, unsigned char *source, int length){ int result; int already_sent = 0; while (already_sent < length) { result = _send(sock, (void *) (source + already_sent), length - already_sent, 0, 0); if (result < 0) { DPRINTK("smb_send_raw: sendto error = %d\n", -result); return result; } already_sent += result; } return already_sent;}static intsmb_receive_raw(struct socket *sock, unsigned char *target, int length){ int result; int already_read = 0; while (already_read < length) { result = _recvfrom(sock, (void *) (target + already_read), length - already_read, 0, 0, NULL, NULL); if (result == 0) { return -EIO; } if (result < 0) { DPRINTK("smb_receive_raw: recvfrom error = %d\n", -result); return result; } already_read += result; } return already_read;}static intsmb_get_length(struct socket *sock, unsigned char *header){ int result; unsigned char peek_buf[4]; unsigned short fs; re_recv: fs = get_fs(); set_fs(get_ds()); result = smb_receive_raw(sock, peek_buf, 4); set_fs(fs); if (result < 0) { DPRINTK("smb_get_length: recv error = %d\n", -result); return result; } switch (peek_buf[0]) { case 0x00: case 0x82: break; case 0x85: DPRINTK("smb_get_length: Got SESSION KEEP ALIVE\n"); goto re_recv; default: printk("smb_get_length: Invalid NBT packet\n"); return -EIO; } if (header != NULL) { memcpy(header, peek_buf, 4); } /* The length in the RFC NB header is the raw data length */ return smb_len(peek_buf);}static struct socket *server_sock(struct smb_server *server){ struct file *file; struct inode *inode; if (server == NULL) return NULL; if ((file = server->sock_file) == NULL) return NULL; if ((inode = file->f_inode) == NULL) return NULL; return &(inode->u.socket_i);}/* * smb_receive * fs points to the correct segment */static intsmb_receive(struct smb_server *server){ struct socket *sock = server_sock(server); int len; int result; unsigned char peek_buf[4]; len = smb_get_length(sock, peek_buf); if (len < 0) { return len; } if (len + 4 > server->packet_size) { /* Some servers do not care about our max_xmit. They send larger packets */ DPRINTK("smb_receive: Increase packet size from %d to %d\n", server->packet_size, len + 4); smb_vfree(server->packet); server->packet = NULL; server->packet_size = 0; server->packet = smb_vmalloc(len + 4); if (server->packet == NULL) { return -ENOMEM; } server->packet_size = len + 4; } memcpy(server->packet, peek_buf, 4); result = smb_receive_raw(sock, server->packet + 4, len); if (result < 0) { printk("smb_receive: receive error: %d\n", result); return result; } server->rcls = BVAL(server->packet, 9); server->err = WVAL(server->packet, 11); if (server->rcls != 0)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -