]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/lustre/lnet/lnet/lib-socket.c
staging:lustre: use available kernel wrappers in lib-socket.c
[karo-tx-linux.git] / drivers / staging / lustre / 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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 #define DEBUG_SUBSYSTEM S_LNET
37
38 #include <linux/if.h>
39 #include <linux/in.h>
40 #include <linux/net.h>
41 #include <linux/file.h>
42 #include <linux/pagemap.h>
43 /* For sys_open & sys_close */
44 #include <linux/syscalls.h>
45 #include <net/sock.h>
46
47 #include "../../include/linux/libcfs/libcfs.h"
48 #include "../../include/linux/lnet/lib-lnet.h"
49
50 static int
51 kernel_sock_unlocked_ioctl(struct file *filp, int cmd, unsigned long arg)
52 {
53         mm_segment_t oldfs = get_fs();
54         int err;
55
56         set_fs(KERNEL_DS);
57         err = filp->f_op->unlocked_ioctl(filp, cmd, arg);
58         set_fs(oldfs);
59
60         return err;
61 }
62
63 static int
64 lnet_sock_ioctl(int cmd, unsigned long arg)
65 {
66         struct file    *sock_filp;
67         struct socket  *sock;
68         int             rc;
69
70         rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
71         if (rc != 0) {
72                 CERROR ("Can't create socket: %d\n", rc);
73                 return rc;
74         }
75
76         sock_filp = sock_alloc_file(sock, 0, NULL);
77         if (IS_ERR(sock_filp)) {
78                 sock_release(sock);
79                 rc = PTR_ERR(sock_filp);
80                 goto out;
81         }
82
83         rc = kernel_sock_unlocked_ioctl(sock_filp, cmd, arg);
84
85         fput(sock_filp);
86 out:
87         return rc;
88 }
89
90 int
91 lnet_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
92 {
93         struct ifreq   ifr;
94         int         nob;
95         int         rc;
96         __u32     val;
97
98         nob = strnlen(name, IFNAMSIZ);
99         if (nob == IFNAMSIZ) {
100                 CERROR("Interface name %s too long\n", name);
101                 return -EINVAL;
102         }
103
104         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
105
106         strcpy(ifr.ifr_name, name);
107         rc = lnet_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
108         if (rc != 0) {
109                 CERROR("Can't get flags for interface %s\n", name);
110                 return rc;
111         }
112
113         if ((ifr.ifr_flags & IFF_UP) == 0) {
114                 CDEBUG(D_NET, "Interface %s down\n", name);
115                 *up = 0;
116                 *ip = *mask = 0;
117                 return 0;
118         }
119
120         *up = 1;
121
122         strcpy(ifr.ifr_name, name);
123         ifr.ifr_addr.sa_family = AF_INET;
124         rc = lnet_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
125         if (rc != 0) {
126                 CERROR("Can't get IP address for interface %s\n", name);
127                 return rc;
128         }
129
130         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
131         *ip = ntohl(val);
132
133         strcpy(ifr.ifr_name, name);
134         ifr.ifr_addr.sa_family = AF_INET;
135         rc = lnet_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr);
136         if (rc != 0) {
137                 CERROR("Can't get netmask for interface %s\n", name);
138                 return rc;
139         }
140
141         val = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
142         *mask = ntohl(val);
143
144         return 0;
145 }
146
147 EXPORT_SYMBOL(lnet_ipif_query);
148
149 int
150 lnet_ipif_enumerate (char ***namesp)
151 {
152         /* Allocate and fill in 'names', returning # interfaces/error */
153         char       **names;
154         int          toobig;
155         int          nalloc;
156         int          nfound;
157         struct ifreq   *ifr;
158         struct ifconf   ifc;
159         int          rc;
160         int          nob;
161         int          i;
162
163
164         nalloc = 16;    /* first guess at max interfaces */
165         toobig = 0;
166         for (;;) {
167                 if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) {
168                         toobig = 1;
169                         nalloc = PAGE_CACHE_SIZE/sizeof(*ifr);
170                         CWARN("Too many interfaces: only enumerating first %d\n",
171                               nalloc);
172                 }
173
174                 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
175                 if (ifr == NULL) {
176                         CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
177                         rc = -ENOMEM;
178                         goto out0;
179                 }
180
181                 ifc.ifc_buf = (char *)ifr;
182                 ifc.ifc_len = nalloc * sizeof(*ifr);
183
184                 rc = lnet_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
185                 if (rc < 0) {
186                         CERROR ("Error %d enumerating interfaces\n", rc);
187                         goto out1;
188                 }
189
190                 LASSERT (rc == 0);
191
192                 nfound = ifc.ifc_len/sizeof(*ifr);
193                 LASSERT (nfound <= nalloc);
194
195                 if (nfound < nalloc || toobig)
196                         break;
197
198                 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
199                 nalloc *= 2;
200         }
201
202         if (nfound == 0)
203                 goto out1;
204
205         LIBCFS_ALLOC(names, nfound * sizeof(*names));
206         if (names == NULL) {
207                 rc = -ENOMEM;
208                 goto out1;
209         }
210
211         for (i = 0; i < nfound; i++) {
212
213                 nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
214                 if (nob == IFNAMSIZ) {
215                         /* no space for terminating NULL */
216                         CERROR("interface name %.*s too long (%d max)\n",
217                                nob, ifr[i].ifr_name, IFNAMSIZ);
218                         rc = -ENAMETOOLONG;
219                         goto out2;
220                 }
221
222                 LIBCFS_ALLOC(names[i], IFNAMSIZ);
223                 if (names[i] == NULL) {
224                         rc = -ENOMEM;
225                         goto out2;
226                 }
227
228                 memcpy(names[i], ifr[i].ifr_name, nob);
229                 names[i][nob] = 0;
230         }
231
232         *namesp = names;
233         rc = nfound;
234
235  out2:
236         if (rc < 0)
237                 lnet_ipif_free_enumeration(names, nfound);
238  out1:
239         LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
240  out0:
241         return rc;
242 }
243
244 EXPORT_SYMBOL(lnet_ipif_enumerate);
245
246 void
247 lnet_ipif_free_enumeration (char **names, int n)
248 {
249         int      i;
250
251         LASSERT (n > 0);
252
253         for (i = 0; i < n && names[i] != NULL; i++)
254                 LIBCFS_FREE(names[i], IFNAMSIZ);
255
256         LIBCFS_FREE(names, n * sizeof(*names));
257 }
258
259 EXPORT_SYMBOL(lnet_ipif_free_enumeration);
260
261 int
262 lnet_sock_write (struct socket *sock, void *buffer, int nob, int timeout)
263 {
264         int         rc;
265         long       ticks = timeout * HZ;
266         unsigned long  then;
267         struct timeval tv;
268
269         LASSERT (nob > 0);
270         /* Caller may pass a zero timeout if she thinks the socket buffer is
271          * empty enough to take the whole message immediately */
272
273         for (;;) {
274                 struct kvec  iov = {
275                         .iov_base = buffer,
276                         .iov_len  = nob
277                 };
278                 struct msghdr msg = {
279                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
280                 };
281
282                 if (timeout != 0) {
283                         /* Set send timeout to remaining time */
284                         tv = (struct timeval) {
285                                 .tv_sec = ticks / HZ,
286                                 .tv_usec = ((ticks % HZ) * 1000000) / HZ
287                         };
288                         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
289                                              (char *)&tv, sizeof(tv));
290                         if (rc != 0) {
291                                 CERROR("Can't set socket send timeout %ld.%06d: %d\n",
292                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
293                                 return rc;
294                         }
295                 }
296
297                 then = jiffies;
298                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
299                 ticks -= jiffies - then;
300
301                 if (rc == nob)
302                         return 0;
303
304                 if (rc < 0)
305                         return rc;
306
307                 if (rc == 0) {
308                         CERROR ("Unexpected zero rc\n");
309                         return -ECONNABORTED;
310                 }
311
312                 if (ticks <= 0)
313                         return -EAGAIN;
314
315                 buffer = ((char *)buffer) + rc;
316                 nob -= rc;
317         }
318
319         return 0;
320 }
321 EXPORT_SYMBOL(lnet_sock_write);
322
323 int
324 lnet_sock_read (struct socket *sock, void *buffer, int nob, int timeout)
325 {
326         int         rc;
327         long       ticks = timeout * HZ;
328         unsigned long  then;
329         struct timeval tv;
330
331         LASSERT (nob > 0);
332         LASSERT (ticks > 0);
333
334         for (;;) {
335                 struct kvec  iov = {
336                         .iov_base = buffer,
337                         .iov_len  = nob
338                 };
339                 struct msghdr msg = {
340                         .msg_flags      = 0
341                 };
342
343                 /* Set receive timeout to remaining time */
344                 tv = (struct timeval) {
345                         .tv_sec = ticks / HZ,
346                         .tv_usec = ((ticks % HZ) * 1000000) / HZ
347                 };
348                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
349                                      (char *)&tv, sizeof(tv));
350                 if (rc != 0) {
351                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
352                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
353                         return rc;
354                 }
355
356                 then = jiffies;
357                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
358                 ticks -= jiffies - then;
359
360                 if (rc < 0)
361                         return rc;
362
363                 if (rc == 0)
364                         return -ECONNRESET;
365
366                 buffer = ((char *)buffer) + rc;
367                 nob -= rc;
368
369                 if (nob == 0)
370                         return 0;
371
372                 if (ticks <= 0)
373                         return -ETIMEDOUT;
374         }
375 }
376
377 EXPORT_SYMBOL(lnet_sock_read);
378
379 static int
380 lnet_sock_create (struct socket **sockp, int *fatal,
381                     __u32 local_ip, int local_port)
382 {
383         struct sockaddr_in  locaddr;
384         struct socket      *sock;
385         int              rc;
386         int              option;
387
388         /* All errors are fatal except bind failure if the port is in use */
389         *fatal = 1;
390
391         rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
392         *sockp = sock;
393         if (rc != 0) {
394                 CERROR ("Can't create socket: %d\n", rc);
395                 return rc;
396         }
397
398         option = 1;
399         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
400                              (char *)&option, sizeof (option));
401         if (rc != 0) {
402                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
403                 goto failed;
404         }
405
406         if (local_ip != 0 || local_port != 0) {
407                 memset(&locaddr, 0, sizeof(locaddr));
408                 locaddr.sin_family = AF_INET;
409                 locaddr.sin_port = htons(local_port);
410                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
411                                           INADDR_ANY : htonl(local_ip);
412
413                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
414                                  sizeof(locaddr));
415                 if (rc == -EADDRINUSE) {
416                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
417                         *fatal = 0;
418                         goto failed;
419                 }
420                 if (rc != 0) {
421                         CERROR("Error trying to bind to port %d: %d\n",
422                                local_port, rc);
423                         goto failed;
424                 }
425         }
426
427         return 0;
428
429  failed:
430         sock_release(sock);
431         return rc;
432 }
433
434 int
435 lnet_sock_setbuf (struct socket *sock, int txbufsize, int rxbufsize)
436 {
437         int              option;
438         int              rc;
439
440         if (txbufsize != 0) {
441                 option = txbufsize;
442                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
443                                      (char *)&option, sizeof (option));
444                 if (rc != 0) {
445                         CERROR ("Can't set send buffer %d: %d\n",
446                                 option, rc);
447                         return rc;
448                 }
449         }
450
451         if (rxbufsize != 0) {
452                 option = rxbufsize;
453                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
454                                       (char *)&option, sizeof (option));
455                 if (rc != 0) {
456                         CERROR ("Can't set receive buffer %d: %d\n",
457                                 option, rc);
458                         return rc;
459                 }
460         }
461
462         return 0;
463 }
464
465 EXPORT_SYMBOL(lnet_sock_setbuf);
466
467 int
468 lnet_sock_getaddr (struct socket *sock, bool remote, __u32 *ip, int *port)
469 {
470         struct sockaddr_in sin;
471         int             len = sizeof (sin);
472         int             rc;
473
474         if (remote)
475                 rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &len);
476         else
477                 rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &len);
478         if (rc != 0) {
479                 CERROR ("Error %d getting sock %s IP/port\n",
480                         rc, remote ? "peer" : "local");
481                 return rc;
482         }
483
484         if (ip != NULL)
485                 *ip = ntohl (sin.sin_addr.s_addr);
486
487         if (port != NULL)
488                 *port = ntohs (sin.sin_port);
489
490         return 0;
491 }
492
493 EXPORT_SYMBOL(lnet_sock_getaddr);
494
495 int
496 lnet_sock_getbuf (struct socket *sock, int *txbufsize, int *rxbufsize)
497 {
498
499         if (txbufsize != NULL) {
500                 *txbufsize = sock->sk->sk_sndbuf;
501         }
502
503         if (rxbufsize != NULL) {
504                 *rxbufsize = sock->sk->sk_rcvbuf;
505         }
506
507         return 0;
508 }
509
510 EXPORT_SYMBOL(lnet_sock_getbuf);
511
512 int
513 lnet_sock_listen (struct socket **sockp,
514                     __u32 local_ip, int local_port, int backlog)
515 {
516         int      fatal;
517         int      rc;
518
519         rc = lnet_sock_create(sockp, &fatal, local_ip, local_port);
520         if (rc != 0) {
521                 if (!fatal)
522                         CERROR("Can't create socket: port %d already in use\n",
523                                local_port);
524                 return rc;
525         }
526
527         rc = kernel_listen(*sockp, backlog);
528         if (rc == 0)
529                 return 0;
530
531         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
532         sock_release(*sockp);
533         return rc;
534 }
535
536 EXPORT_SYMBOL(lnet_sock_listen);
537
538 int
539 lnet_sock_accept (struct socket **newsockp, struct socket *sock)
540 {
541         wait_queue_t   wait;
542         struct socket *newsock;
543         int         rc;
544
545         init_waitqueue_entry(&wait, current);
546
547         /* XXX this should add a ref to sock->ops->owner, if
548          * TCP could be a module */
549         rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
550         if (rc) {
551                 CERROR("Can't allocate socket\n");
552                 return rc;
553         }
554
555         newsock->ops = sock->ops;
556
557         rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
558         if (rc == -EAGAIN) {
559                 /* Nothing ready, so wait for activity */
560                 set_current_state(TASK_INTERRUPTIBLE);
561                 add_wait_queue(sk_sleep(sock->sk), &wait);
562                 schedule();
563                 remove_wait_queue(sk_sleep(sock->sk), &wait);
564                 set_current_state(TASK_RUNNING);
565                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
566         }
567
568         if (rc != 0)
569                 goto failed;
570
571         *newsockp = newsock;
572         return 0;
573
574  failed:
575         sock_release(newsock);
576         return rc;
577 }
578
579 EXPORT_SYMBOL(lnet_sock_accept);
580
581 int
582 lnet_sock_connect (struct socket **sockp, int *fatal,
583                      __u32 local_ip, int local_port,
584                      __u32 peer_ip, int peer_port)
585 {
586         struct sockaddr_in  srvaddr;
587         int              rc;
588
589         rc = lnet_sock_create(sockp, fatal, local_ip, local_port);
590         if (rc != 0)
591                 return rc;
592
593         memset (&srvaddr, 0, sizeof (srvaddr));
594         srvaddr.sin_family = AF_INET;
595         srvaddr.sin_port = htons(peer_port);
596         srvaddr.sin_addr.s_addr = htonl(peer_ip);
597
598         rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
599                             sizeof(srvaddr), 0);
600         if (rc == 0)
601                 return 0;
602
603         /* EADDRNOTAVAIL probably means we're already connected to the same
604          * peer/port on the same local port on a differently typed
605          * connection.  Let our caller retry with a different local
606          * port... */
607         *fatal = !(rc == -EADDRNOTAVAIL);
608
609         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
610                "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
611                &local_ip, local_port, &peer_ip, peer_port);
612
613         sock_release(*sockp);
614         return rc;
615 }
616
617 EXPORT_SYMBOL(lnet_sock_connect);