sock.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * sock.c
  3. *
  4. * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
  5. * Copyright (C) 1997 by Volker Lendecke
  6. *
  7. * Please add a note about your changes to smbfs in the ChangeLog file.
  8. */
  9. #include <linux/fs.h>
  10. #include <linux/time.h>
  11. #include <linux/errno.h>
  12. #include <linux/socket.h>
  13. #include <linux/fcntl.h>
  14. #include <linux/file.h>
  15. #include <linux/in.h>
  16. #include <linux/net.h>
  17. #include <linux/mm.h>
  18. #include <linux/netdevice.h>
  19. #include <linux/workqueue.h>
  20. #include <net/scm.h>
  21. #include <net/tcp_states.h>
  22. #include <net/ip.h>
  23. #include <linux/smb_fs.h>
  24. #include <linux/smb.h>
  25. #include <linux/smbno.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/ioctls.h>
  28. #include "smb_debug.h"
  29. #include "proto.h"
  30. #include "request.h"
  31. static int
  32. _recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags)
  33. {
  34. struct kvec iov = {ubuf, size};
  35. struct msghdr msg = {.msg_flags = flags};
  36. msg.msg_flags |= MSG_DONTWAIT | MSG_NOSIGNAL;
  37. return kernel_recvmsg(socket, &msg, &iov, 1, size, msg.msg_flags);
  38. }
  39. /*
  40. * Return the server this socket belongs to
  41. */
  42. static struct smb_sb_info *
  43. server_from_socket(struct socket *socket)
  44. {
  45. return socket->sk->sk_user_data;
  46. }
  47. /*
  48. * Called when there is data on the socket.
  49. */
  50. void
  51. smb_data_ready(struct sock *sk, int len)
  52. {
  53. struct smb_sb_info *server = server_from_socket(sk->sk_socket);
  54. void (*data_ready)(struct sock *, int) = server->data_ready;
  55. data_ready(sk, len);
  56. VERBOSE("(%p, %d)\n", sk, len);
  57. smbiod_wake_up();
  58. }
  59. int
  60. smb_valid_socket(struct inode * inode)
  61. {
  62. return (inode && S_ISSOCK(inode->i_mode) &&
  63. SOCKET_I(inode)->type == SOCK_STREAM);
  64. }
  65. static struct socket *
  66. server_sock(struct smb_sb_info *server)
  67. {
  68. struct file *file;
  69. if (server && (file = server->sock_file))
  70. {
  71. #ifdef SMBFS_PARANOIA
  72. if (!smb_valid_socket(file->f_path.dentry->d_inode))
  73. PARANOIA("bad socket!\n");
  74. #endif
  75. return SOCKET_I(file->f_path.dentry->d_inode);
  76. }
  77. return NULL;
  78. }
  79. void
  80. smb_close_socket(struct smb_sb_info *server)
  81. {
  82. struct file * file = server->sock_file;
  83. if (file) {
  84. struct socket *sock = server_sock(server);
  85. VERBOSE("closing socket %p\n", sock);
  86. sock->sk->sk_data_ready = server->data_ready;
  87. server->sock_file = NULL;
  88. fput(file);
  89. }
  90. }
  91. static int
  92. smb_get_length(struct socket *socket, unsigned char *header)
  93. {
  94. int result;
  95. result = _recvfrom(socket, header, 4, MSG_PEEK);
  96. if (result == -EAGAIN)
  97. return -ENODATA;
  98. if (result < 0) {
  99. PARANOIA("recv error = %d\n", -result);
  100. return result;
  101. }
  102. if (result < 4)
  103. return -ENODATA;
  104. switch (header[0]) {
  105. case 0x00:
  106. case 0x82:
  107. break;
  108. case 0x85:
  109. DEBUG1("Got SESSION KEEP ALIVE\n");
  110. _recvfrom(socket, header, 4, 0); /* read away */
  111. return -ENODATA;
  112. default:
  113. PARANOIA("Invalid NBT packet, code=%x\n", header[0]);
  114. return -EIO;
  115. }
  116. /* The length in the RFC NB header is the raw data length */
  117. return smb_len(header);
  118. }
  119. int
  120. smb_recv_available(struct smb_sb_info *server)
  121. {
  122. mm_segment_t oldfs;
  123. int avail, err;
  124. struct socket *sock = server_sock(server);
  125. oldfs = get_fs();
  126. set_fs(get_ds());
  127. err = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail);
  128. set_fs(oldfs);
  129. return (err >= 0) ? avail : err;
  130. }
  131. /*
  132. * Adjust the kvec to move on 'n' bytes (from nfs/sunrpc)
  133. */
  134. static int
  135. smb_move_iov(struct kvec **data, size_t *num, struct kvec *vec, unsigned amount)
  136. {
  137. struct kvec *iv = *data;
  138. int i;
  139. int len;
  140. /*
  141. * Eat any sent kvecs
  142. */
  143. while (iv->iov_len <= amount) {
  144. amount -= iv->iov_len;
  145. iv++;
  146. (*num)--;
  147. }
  148. /*
  149. * And chew down the partial one
  150. */
  151. vec[0].iov_len = iv->iov_len-amount;
  152. vec[0].iov_base =((unsigned char *)iv->iov_base)+amount;
  153. iv++;
  154. len = vec[0].iov_len;
  155. /*
  156. * And copy any others
  157. */
  158. for (i = 1; i < *num; i++) {
  159. vec[i] = *iv++;
  160. len += vec[i].iov_len;
  161. }
  162. *data = vec;
  163. return len;
  164. }
  165. /*
  166. * smb_receive_header
  167. * Only called by the smbiod thread.
  168. */
  169. int
  170. smb_receive_header(struct smb_sb_info *server)
  171. {
  172. struct socket *sock;
  173. int result = 0;
  174. unsigned char peek_buf[4];
  175. result = -EIO;
  176. sock = server_sock(server);
  177. if (!sock)
  178. goto out;
  179. if (sock->sk->sk_state != TCP_ESTABLISHED)
  180. goto out;
  181. if (!server->smb_read) {
  182. result = smb_get_length(sock, peek_buf);
  183. if (result < 0) {
  184. if (result == -ENODATA)
  185. result = 0;
  186. goto out;
  187. }
  188. server->smb_len = result + 4;
  189. if (server->smb_len < SMB_HEADER_LEN) {
  190. PARANOIA("short packet: %d\n", result);
  191. server->rstate = SMB_RECV_DROP;
  192. result = -EIO;
  193. goto out;
  194. }
  195. if (server->smb_len > SMB_MAX_PACKET_SIZE) {
  196. PARANOIA("long packet: %d\n", result);
  197. server->rstate = SMB_RECV_DROP;
  198. result = -EIO;
  199. goto out;
  200. }
  201. }
  202. result = _recvfrom(sock, server->header + server->smb_read,
  203. SMB_HEADER_LEN - server->smb_read, 0);
  204. VERBOSE("_recvfrom: %d\n", result);
  205. if (result < 0) {
  206. VERBOSE("receive error: %d\n", result);
  207. goto out;
  208. }
  209. server->smb_read += result;
  210. if (server->smb_read == SMB_HEADER_LEN)
  211. server->rstate = SMB_RECV_HCOMPLETE;
  212. out:
  213. return result;
  214. }
  215. static char drop_buffer[PAGE_SIZE];
  216. /*
  217. * smb_receive_drop - read and throw away the data
  218. * Only called by the smbiod thread.
  219. *
  220. * FIXME: we are in the kernel, could we just tell the socket that we want
  221. * to drop stuff from the buffer?
  222. */
  223. int
  224. smb_receive_drop(struct smb_sb_info *server)
  225. {
  226. struct socket *sock;
  227. unsigned int flags;
  228. struct kvec iov;
  229. struct msghdr msg;
  230. int rlen = smb_len(server->header) - server->smb_read + 4;
  231. int result = -EIO;
  232. if (rlen > PAGE_SIZE)
  233. rlen = PAGE_SIZE;
  234. sock = server_sock(server);
  235. if (!sock)
  236. goto out;
  237. if (sock->sk->sk_state != TCP_ESTABLISHED)
  238. goto out;
  239. flags = MSG_DONTWAIT | MSG_NOSIGNAL;
  240. iov.iov_base = drop_buffer;
  241. iov.iov_len = PAGE_SIZE;
  242. msg.msg_flags = flags;
  243. msg.msg_name = NULL;
  244. msg.msg_namelen = 0;
  245. msg.msg_control = NULL;
  246. result = kernel_recvmsg(sock, &msg, &iov, 1, rlen, flags);
  247. VERBOSE("read: %d\n", result);
  248. if (result < 0) {
  249. VERBOSE("receive error: %d\n", result);
  250. goto out;
  251. }
  252. server->smb_read += result;
  253. if (server->smb_read >= server->smb_len)
  254. server->rstate = SMB_RECV_END;
  255. out:
  256. return result;
  257. }
  258. /*
  259. * smb_receive
  260. * Only called by the smbiod thread.
  261. */
  262. int
  263. smb_receive(struct smb_sb_info *server, struct smb_request *req)
  264. {
  265. struct socket *sock;
  266. unsigned int flags;
  267. struct kvec iov[4];
  268. struct kvec *p = req->rq_iov;
  269. size_t num = req->rq_iovlen;
  270. struct msghdr msg;
  271. int rlen;
  272. int result = -EIO;
  273. sock = server_sock(server);
  274. if (!sock)
  275. goto out;
  276. if (sock->sk->sk_state != TCP_ESTABLISHED)
  277. goto out;
  278. flags = MSG_DONTWAIT | MSG_NOSIGNAL;
  279. msg.msg_flags = flags;
  280. msg.msg_name = NULL;
  281. msg.msg_namelen = 0;
  282. msg.msg_control = NULL;
  283. /* Dont repeat bytes and count available bufferspace */
  284. rlen = min_t(int, smb_move_iov(&p, &num, iov, req->rq_bytes_recvd),
  285. (req->rq_rlen - req->rq_bytes_recvd));
  286. result = kernel_recvmsg(sock, &msg, p, num, rlen, flags);
  287. VERBOSE("read: %d\n", result);
  288. if (result < 0) {
  289. VERBOSE("receive error: %d\n", result);
  290. goto out;
  291. }
  292. req->rq_bytes_recvd += result;
  293. server->smb_read += result;
  294. out:
  295. return result;
  296. }
  297. /*
  298. * Try to send a SMB request. This may return after sending only parts of the
  299. * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
  300. *
  301. * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
  302. */
  303. int
  304. smb_send_request(struct smb_request *req)
  305. {
  306. struct smb_sb_info *server = req->rq_server;
  307. struct socket *sock;
  308. struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
  309. int slen = req->rq_slen - req->rq_bytes_sent;
  310. int result = -EIO;
  311. struct kvec iov[4];
  312. struct kvec *p = req->rq_iov;
  313. size_t num = req->rq_iovlen;
  314. sock = server_sock(server);
  315. if (!sock)
  316. goto out;
  317. if (sock->sk->sk_state != TCP_ESTABLISHED)
  318. goto out;
  319. /* Dont repeat bytes */
  320. if (req->rq_bytes_sent)
  321. smb_move_iov(&p, &num, iov, req->rq_bytes_sent);
  322. result = kernel_sendmsg(sock, &msg, p, num, slen);
  323. if (result >= 0) {
  324. req->rq_bytes_sent += result;
  325. if (req->rq_bytes_sent >= req->rq_slen)
  326. req->rq_flags |= SMB_REQ_TRANSMITTED;
  327. }
  328. out:
  329. return result;
  330. }