Whamcloud - gitweb
18b49a902d03ebbbcd7a6c318653db7f95bf1210
[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 #include <linux/inetdevice.h>
43
44 #include <libcfs/linux/linux-time.h>
45 #include <libcfs/libcfs.h>
46 #include <lnet/lib-lnet.h>
47
48 int
49 lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
50 {
51         int rc;
52         long jiffies_left = cfs_time_seconds(timeout);
53         unsigned long then;
54
55         LASSERT(nob > 0);
56         /* Caller may pass a zero timeout if she thinks the socket buffer is
57          * empty enough to take the whole message immediately */
58
59         for (;;) {
60                 struct kvec  iov = {
61                         .iov_base = buffer,
62                         .iov_len  = nob
63                 };
64                 struct msghdr msg = {
65                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
66                 };
67
68                 if (timeout != 0) {
69                         struct sock *sk = sock->sk;
70
71                         /* Set send timeout to remaining time */
72                         lock_sock(sk);
73                         sk->sk_sndtimeo = jiffies_left;
74                         release_sock(sk);
75                 }
76
77                 then = jiffies;
78                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
79                 jiffies_left -= jiffies - then;
80
81                 if (rc == nob)
82                         return 0;
83
84                 if (rc < 0)
85                         return rc;
86
87                 if (rc == 0) {
88                         CERROR("Unexpected zero rc\n");
89                         return -ECONNABORTED;
90                 }
91
92                 if (jiffies_left <= 0)
93                         return -EAGAIN;
94
95                 buffer = ((char *)buffer) + rc;
96                 nob -= rc;
97         }
98         return 0;
99 }
100 EXPORT_SYMBOL(lnet_sock_write);
101
102 int
103 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
104 {
105         int rc;
106         long jiffies_left = cfs_time_seconds(timeout);
107         unsigned long then;
108
109         LASSERT(nob > 0);
110         LASSERT(jiffies_left > 0);
111
112         for (;;) {
113                 struct kvec  iov = {
114                         .iov_base = buffer,
115                         .iov_len  = nob
116                 };
117                 struct msghdr msg = {
118                         .msg_flags      = 0
119                 };
120                 struct sock *sk = sock->sk;
121
122                 /* Set receive timeout to remaining time */
123                 lock_sock(sk);
124                 sk->sk_rcvtimeo = jiffies_left;
125                 release_sock(sk);
126
127                 then = jiffies;
128                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
129                 jiffies_left -= jiffies - then;
130
131                 if (rc < 0)
132                         return rc;
133
134                 if (rc == 0)
135                         return -ECONNRESET;
136
137                 buffer = ((char *)buffer) + rc;
138                 nob -= rc;
139
140                 if (nob == 0)
141                         return 0;
142
143                 if (jiffies_left <= 0)
144                         return -ETIMEDOUT;
145         }
146 }
147 EXPORT_SYMBOL(lnet_sock_read);
148
149 int choose_ipv4_src(__u32 *ret, int interface, __u32 dst_ipaddr, struct net *ns)
150 {
151         struct net_device *dev;
152         struct in_device *in_dev;
153         int err;
154         DECLARE_CONST_IN_IFADDR(ifa);
155
156         rcu_read_lock();
157         dev = dev_get_by_index_rcu(ns, interface);
158         err = -EINVAL;
159         if (!dev || !(dev->flags & IFF_UP))
160                 goto out;
161         in_dev = __in_dev_get_rcu(dev);
162         if (!in_dev)
163                 goto out;
164         err = -ENOENT;
165         in_dev_for_each_ifa_rcu(ifa, in_dev) {
166                 if (err ||
167                     ((dst_ipaddr ^ ntohl(ifa->ifa_local))
168                      & ntohl(ifa->ifa_mask)) == 0) {
169                         /* This address at least as good as what we
170                          * already have
171                          */
172                         *ret = ntohl(ifa->ifa_local);
173                         err = 0;
174                 }
175         }
176         endfor_ifa(in_dev);
177 out:
178         rcu_read_unlock();
179         return err;
180 }
181 EXPORT_SYMBOL(choose_ipv4_src);
182
183 static struct socket *
184 lnet_sock_create(int interface, struct sockaddr *remaddr,
185                  int local_port, struct net *ns)
186 {
187         struct socket      *sock;
188         int                 rc;
189         int                 option;
190
191 #ifdef HAVE_SOCK_CREATE_KERN_USE_NET
192         rc = sock_create_kern(ns, PF_INET, SOCK_STREAM, 0, &sock);
193 #else
194         rc = sock_create_kern(PF_INET, SOCK_STREAM, 0, &sock);
195 #endif
196         if (rc) {
197                 CERROR("Can't create socket: %d\n", rc);
198                 return ERR_PTR(rc);
199         }
200
201         option = 1;
202         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
203                                (char *)&option, sizeof(option));
204         if (rc) {
205                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
206                 goto failed;
207         }
208
209         if (interface >= 0 || local_port != 0) {
210                 struct sockaddr_in locaddr = {};
211
212                 locaddr.sin_family = AF_INET;
213                 locaddr.sin_addr.s_addr = INADDR_ANY;
214                 if (interface >= 0) {
215                         struct sockaddr_in *sin = (void *)remaddr;
216                         __u32 ip;
217
218                         rc = choose_ipv4_src(&ip,
219                                              interface,
220                                              ntohl(sin->sin_addr.s_addr),
221                                              ns);
222                         if (rc)
223                                 goto failed;
224                         locaddr.sin_addr.s_addr = htonl(ip);
225                 }
226
227                 locaddr.sin_port = htons(local_port);
228
229                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
230                                  sizeof(locaddr));
231                 if (rc == -EADDRINUSE) {
232                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
233                         goto failed;
234                 }
235                 if (rc != 0) {
236                         CERROR("Error trying to bind to port %d: %d\n",
237                                local_port, rc);
238                         goto failed;
239                 }
240         }
241         return sock;
242
243 failed:
244         sock_release(sock);
245         return ERR_PTR(rc);
246 }
247
248 int
249 lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
250 {
251         int                 option;
252         int                 rc;
253
254         if (txbufsize != 0) {
255                 option = txbufsize;
256                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
257                                        (char *)&option, sizeof(option));
258                 if (rc != 0) {
259                         CERROR("Can't set send buffer %d: %d\n",
260                                 option, rc);
261                         return rc;
262                 }
263         }
264
265         if (rxbufsize != 0) {
266                 option = rxbufsize;
267                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
268                                        (char *)&option, sizeof(option));
269                 if (rc != 0) {
270                         CERROR("Can't set receive buffer %d: %d\n",
271                                 option, rc);
272                         return rc;
273                 }
274         }
275         return 0;
276 }
277 EXPORT_SYMBOL(lnet_sock_setbuf);
278
279 int
280 lnet_sock_getaddr(struct socket *sock, bool remote,
281                   struct sockaddr_storage *peer)
282 {
283         int rc;
284 #ifndef HAVE_KERN_SOCK_GETNAME_2ARGS
285         int len = sizeof(*peer);
286 #endif
287
288         if (remote)
289                 rc = lnet_kernel_getpeername(sock,
290                                              (struct sockaddr *)peer, &len);
291         else
292                 rc = lnet_kernel_getsockname(sock,
293                                              (struct sockaddr *)peer, &len);
294         if (rc < 0) {
295                 CERROR("Error %d getting sock %s IP/port\n",
296                         rc, remote ? "peer" : "local");
297                 return rc;
298         }
299
300         return 0;
301 }
302 EXPORT_SYMBOL(lnet_sock_getaddr);
303
304 int
305 lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
306 {
307         if (txbufsize != NULL)
308                 *txbufsize = sock->sk->sk_sndbuf;
309
310         if (rxbufsize != NULL)
311                 *rxbufsize = sock->sk->sk_rcvbuf;
312
313         return 0;
314 }
315 EXPORT_SYMBOL(lnet_sock_getbuf);
316
317 struct socket *
318 lnet_sock_listen(int local_port, int backlog, struct net *ns)
319 {
320         struct socket *sock;
321         int rc;
322
323         sock = lnet_sock_create(-1, NULL, local_port, ns);
324         if (IS_ERR(sock)) {
325                 rc = PTR_ERR(sock);
326                 if (rc == -EADDRINUSE)
327                         CERROR("Can't create socket: port %d already in use\n",
328                                local_port);
329                 return ERR_PTR(rc);
330         }
331
332         rc = kernel_listen(sock, backlog);
333         if (rc == 0)
334                 return sock;
335
336         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
337         sock_release(sock);
338         return ERR_PTR(rc);
339 }
340
341 struct socket *
342 lnet_sock_connect(int interface, int local_port,
343                   struct sockaddr *peeraddr,
344                   struct net *ns)
345 {
346         struct socket *sock;
347         int rc;
348
349         sock = lnet_sock_create(interface, peeraddr, local_port, ns);
350         if (IS_ERR(sock))
351                 return sock;
352
353         rc = kernel_connect(sock, peeraddr, sizeof(struct sockaddr_in), 0);
354         if (rc == 0)
355                 return sock;
356
357         /* EADDRNOTAVAIL probably means we're already connected to the same
358          * peer/port on the same local port on a differently typed
359          * connection.  Let our caller retry with a different local
360          * port... */
361
362         CDEBUG_LIMIT(rc == -EADDRNOTAVAIL ? D_NET : D_NETERROR,
363                      "Error %d connecting %d -> %pISp\n", rc,
364                      local_port, peeraddr);
365
366         sock_release(sock);
367         return ERR_PTR(rc);
368 }