Whamcloud - gitweb
LU-12140 lnet: adds checking msg len
[fs/lustre-release.git] / lnet / lnet / lib-socket.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2015, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_LNET
33
34 #include <linux/if.h>
35 #include <linux/in.h>
36 #include <linux/net.h>
37 #include <linux/file.h>
38 #include <linux/pagemap.h>
39 /* For sys_open & sys_close */
40 #include <linux/syscalls.h>
41 #include <net/sock.h>
42
43 #include <libcfs/libcfs.h>
44 #include <lnet/lib-lnet.h>
45
46 int
47 lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
48 {
49         int             rc;
50         long            jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
51         unsigned long   then;
52         struct timeval  tv;
53
54         LASSERT(nob > 0);
55         /* Caller may pass a zero timeout if she thinks the socket buffer is
56          * empty enough to take the whole message immediately */
57
58         for (;;) {
59                 struct kvec  iov = {
60                         .iov_base = buffer,
61                         .iov_len  = nob
62                 };
63                 struct msghdr msg = {
64                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
65                 };
66
67                 if (timeout != 0) {
68                         /* Set send timeout to remaining time */
69                         tv = (struct timeval) {
70                                 .tv_sec = jiffies_left /
71                                           msecs_to_jiffies(MSEC_PER_SEC),
72                                 .tv_usec = ((jiffies_left %
73                                              msecs_to_jiffies(MSEC_PER_SEC)) *
74                                              USEC_PER_SEC) /
75                                              msecs_to_jiffies(MSEC_PER_SEC)
76                         };
77
78                         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
79                                                (char *)&tv, sizeof(tv));
80                         if (rc != 0) {
81                                 CERROR("Can't set socket send timeout "
82                                        "%ld.%06d: %d\n",
83                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
84                                 return rc;
85                         }
86                 }
87
88                 then = jiffies;
89                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
90                 jiffies_left -= jiffies - then;
91
92                 if (rc == nob)
93                         return 0;
94
95                 if (rc < 0)
96                         return rc;
97
98                 if (rc == 0) {
99                         CERROR("Unexpected zero rc\n");
100                         return -ECONNABORTED;
101                 }
102
103                 if (jiffies_left <= 0)
104                         return -EAGAIN;
105
106                 buffer = ((char *)buffer) + rc;
107                 nob -= rc;
108         }
109         return 0;
110 }
111 EXPORT_SYMBOL(lnet_sock_write);
112
113 int
114 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
115 {
116         int             rc;
117         long            jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
118         unsigned long   then;
119         struct timeval  tv;
120
121         LASSERT(nob > 0);
122         LASSERT(jiffies_left > 0);
123
124         for (;;) {
125                 struct kvec  iov = {
126                         .iov_base = buffer,
127                         .iov_len  = nob
128                 };
129                 struct msghdr msg = {
130                         .msg_flags      = 0
131                 };
132
133                 /* Set receive timeout to remaining time */
134                 tv = (struct timeval) {
135                         .tv_sec = jiffies_left / msecs_to_jiffies(MSEC_PER_SEC),
136                         .tv_usec = ((jiffies_left %
137                                         msecs_to_jiffies(MSEC_PER_SEC)) *
138                                         USEC_PER_SEC) /
139                                         msecs_to_jiffies(MSEC_PER_SEC)
140                 };
141                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
142                                        (char *)&tv, sizeof(tv));
143                 if (rc != 0) {
144                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
145                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
146                         return rc;
147                 }
148
149                 then = jiffies;
150                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
151                 jiffies_left -= jiffies - then;
152
153                 if (rc < 0)
154                         return rc;
155
156                 if (rc == 0)
157                         return -ECONNRESET;
158
159                 buffer = ((char *)buffer) + rc;
160                 nob -= rc;
161
162                 if (nob == 0)
163                         return 0;
164
165                 if (jiffies_left <= 0)
166                         return -ETIMEDOUT;
167         }
168 }
169 EXPORT_SYMBOL(lnet_sock_read);
170
171 static int
172 lnet_sock_create(struct socket **sockp, int *fatal,
173                  __u32 local_ip, int local_port)
174 {
175         struct sockaddr_in  locaddr;
176         struct socket      *sock;
177         int                 rc;
178         int                 option;
179
180         /* All errors are fatal except bind failure if the port is in use */
181         *fatal = 1;
182
183 #ifdef HAVE_SOCK_CREATE_KERN_USE_NET
184         rc = sock_create_kern(&init_net, PF_INET, SOCK_STREAM, 0, &sock);
185 #else
186         rc = sock_create_kern(PF_INET, SOCK_STREAM, 0, &sock);
187 #endif
188         *sockp = sock;
189         if (rc != 0) {
190                 CERROR("Can't create socket: %d\n", rc);
191                 return rc;
192         }
193
194         option = 1;
195         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
196                                (char *)&option, sizeof(option));
197         if (rc != 0) {
198                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
199                 goto failed;
200         }
201
202         if (local_ip != 0 || local_port != 0) {
203                 memset(&locaddr, 0, sizeof(locaddr));
204                 locaddr.sin_family = AF_INET;
205                 locaddr.sin_port = htons(local_port);
206                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
207                                           INADDR_ANY : htonl(local_ip);
208
209                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
210                                  sizeof(locaddr));
211                 if (rc == -EADDRINUSE) {
212                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
213                         *fatal = 0;
214                         goto failed;
215                 }
216                 if (rc != 0) {
217                         CERROR("Error trying to bind to port %d: %d\n",
218                                local_port, rc);
219                         goto failed;
220                 }
221         }
222         return 0;
223
224 failed:
225         sock_release(sock);
226         return rc;
227 }
228
229 int
230 lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
231 {
232         int                 option;
233         int                 rc;
234
235         if (txbufsize != 0) {
236                 option = txbufsize;
237                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
238                                        (char *)&option, sizeof(option));
239                 if (rc != 0) {
240                         CERROR("Can't set send buffer %d: %d\n",
241                                 option, rc);
242                         return rc;
243                 }
244         }
245
246         if (rxbufsize != 0) {
247                 option = rxbufsize;
248                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
249                                        (char *)&option, sizeof(option));
250                 if (rc != 0) {
251                         CERROR("Can't set receive buffer %d: %d\n",
252                                 option, rc);
253                         return rc;
254                 }
255         }
256         return 0;
257 }
258 EXPORT_SYMBOL(lnet_sock_setbuf);
259
260 int
261 lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port)
262 {
263         struct sockaddr_in sin;
264         int rc;
265 #ifndef HAVE_KERN_SOCK_GETNAME_2ARGS
266         int len = sizeof(sin);
267 #endif
268
269         if (remote)
270                 rc = lnet_kernel_getpeername(sock,
271                                              (struct sockaddr *)&sin, &len);
272         else
273                 rc = lnet_kernel_getsockname(sock,
274                                              (struct sockaddr *)&sin, &len);
275         if (rc < 0) {
276                 CERROR("Error %d getting sock %s IP/port\n",
277                         rc, remote ? "peer" : "local");
278                 return rc;
279         }
280
281         if (ip != NULL)
282                 *ip = ntohl(sin.sin_addr.s_addr);
283
284         if (port != NULL)
285                 *port = ntohs(sin.sin_port);
286
287         return 0;
288 }
289 EXPORT_SYMBOL(lnet_sock_getaddr);
290
291 int
292 lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
293 {
294         if (txbufsize != NULL)
295                 *txbufsize = sock->sk->sk_sndbuf;
296
297         if (rxbufsize != NULL)
298                 *rxbufsize = sock->sk->sk_rcvbuf;
299
300         return 0;
301 }
302 EXPORT_SYMBOL(lnet_sock_getbuf);
303
304 int
305 lnet_sock_listen(struct socket **sockp,
306                    __u32 local_ip, int local_port, int backlog)
307 {
308         int      fatal;
309         int      rc;
310
311         rc = lnet_sock_create(sockp, &fatal, local_ip, local_port);
312         if (rc != 0) {
313                 if (!fatal)
314                         CERROR("Can't create socket: port %d already in use\n",
315                                local_port);
316                 return rc;
317         }
318
319         rc = kernel_listen(*sockp, backlog);
320         if (rc == 0)
321                 return 0;
322
323         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
324         sock_release(*sockp);
325         return rc;
326 }
327
328 #ifndef HAVE_SK_SLEEP
329 static inline wait_queue_head_t *sk_sleep(struct sock *sk)
330 {
331         return sk->sk_sleep;
332 }
333 #endif
334
335 int
336 lnet_sock_accept(struct socket **newsockp, struct socket *sock)
337 {
338         wait_queue_entry_t wait;
339         struct socket *newsock;
340         int            rc;
341
342         /* XXX this should add a ref to sock->ops->owner, if
343          * TCP could be a module */
344         rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
345         if (rc) {
346                 CERROR("Can't allocate socket\n");
347                 return rc;
348         }
349
350         newsock->ops = sock->ops;
351
352 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
353         rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
354 #else
355         rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
356 #endif
357         if (rc == -EAGAIN) {
358                 /* Nothing ready, so wait for activity */
359                 init_waitqueue_entry(&wait, current);
360                 add_wait_queue(sk_sleep(sock->sk), &wait);
361                 set_current_state(TASK_INTERRUPTIBLE);
362                 schedule();
363                 remove_wait_queue(sk_sleep(sock->sk), &wait);
364 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
365                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
366 #else
367                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
368 #endif
369         }
370
371         if (rc != 0)
372                 goto failed;
373
374         *newsockp = newsock;
375         return 0;
376
377 failed:
378         sock_release(newsock);
379         return rc;
380 }
381
382 int
383 lnet_sock_connect(struct socket **sockp, int *fatal,
384                   __u32 local_ip, int local_port,
385                   __u32 peer_ip, int peer_port)
386 {
387         struct sockaddr_in  srvaddr;
388         int                 rc;
389
390         rc = lnet_sock_create(sockp, fatal, local_ip, local_port);
391         if (rc != 0)
392                 return rc;
393
394         memset(&srvaddr, 0, sizeof(srvaddr));
395         srvaddr.sin_family = AF_INET;
396         srvaddr.sin_port = htons(peer_port);
397         srvaddr.sin_addr.s_addr = htonl(peer_ip);
398
399         rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
400                             sizeof(srvaddr), 0);
401         if (rc == 0)
402                 return 0;
403
404         /* EADDRNOTAVAIL probably means we're already connected to the same
405          * peer/port on the same local port on a differently typed
406          * connection.  Let our caller retry with a different local
407          * port... */
408         *fatal = !(rc == -EADDRNOTAVAIL);
409
410         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
411                "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
412                &local_ip, local_port, &peer_ip, peer_port);
413
414         sock_release(*sockp);
415         return rc;
416 }