Whamcloud - gitweb
LU-2800 autoconf: remove LIBCFS_SOCK_MAP_FD_2ARG
[fs/lustre-release.git] / libcfs / libcfs / linux / linux-tcpip.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 <libcfs/libcfs.h>
39 #include <libcfs/libcfs.h>
40
41 #include <linux/if.h>
42 #include <linux/in.h>
43 #include <linux/file.h>
44 /* For sys_open & sys_close */
45 #include <linux/syscalls.h>
46
47 #ifndef HAVE_SK_SLEEP
48 static inline wait_queue_head_t *sk_sleep(struct sock *sk)
49 {
50         return sk->sk_sleep;
51 }
52 #endif
53
54 int
55 libcfs_sock_ioctl(int cmd, unsigned long arg)
56 {
57         mm_segment_t    oldmm = get_fs();
58         struct socket  *sock;
59         int             fd = -1;
60         int             rc;
61         struct file    *sock_filp;
62
63         rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
64         if (rc != 0) {
65                 CERROR ("Can't create socket: %d\n", rc);
66                 return rc;
67         }
68
69 #if !defined(HAVE_SOCK_ALLOC_FILE) && !defined(HAVE_SOCK_ALLOC_FILE_3ARGS)
70         fd = sock_map_fd(sock, 0);
71         if (fd < 0) {
72                 rc = fd;
73                 sock_release(sock);
74                 goto out;
75         }
76         sock_filp = fget(fd);
77 #else
78 # ifdef HAVE_SOCK_ALLOC_FILE_3ARGS
79         sock_filp = sock_alloc_file(sock, 0, NULL);
80 # else
81         sock_filp = sock_alloc_file(sock, 0);
82 # endif
83 #endif
84         if (!sock_filp) {
85                 rc = -ENOMEM;
86                 sock_release(sock);
87                 goto out;
88         }
89
90         set_fs(KERNEL_DS);
91         if (sock_filp->f_op->unlocked_ioctl)
92                 rc = sock_filp->f_op->unlocked_ioctl(sock_filp, cmd, arg);
93         set_fs(oldmm);
94
95         fput(sock_filp);
96
97  out:
98         if (fd >= 0)
99                 sys_close(fd);
100
101         return rc;
102 }
103
104 int
105 libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
106 {
107         struct ifreq   ifr;
108         int            nob;
109         int            rc;
110         __u32          val;
111
112         nob = strnlen(name, IFNAMSIZ);
113         if (nob == IFNAMSIZ) {
114                 CERROR("Interface name %s too long\n", name);
115                 return -EINVAL;
116         }
117
118         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
119
120         if (strlen(name) > sizeof(ifr.ifr_name)-1)
121                 return -E2BIG;
122         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
123
124         rc = libcfs_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
125
126         if (rc != 0) {
127                 CERROR("Can't get flags for interface %s\n", name);
128                 return rc;
129         }
130
131         if ((ifr.ifr_flags & IFF_UP) == 0) {
132                 CDEBUG(D_NET, "Interface %s down\n", name);
133                 *up = 0;
134                 *ip = *mask = 0;
135                 return 0;
136         }
137
138         *up = 1;
139
140         if (strlen(name) > sizeof(ifr.ifr_name)-1)
141                 return -E2BIG;
142         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
143
144         ifr.ifr_addr.sa_family = AF_INET;
145         rc = libcfs_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
146
147         if (rc != 0) {
148                 CERROR("Can't get IP address for interface %s\n", name);
149                 return rc;
150         }
151
152         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
153         *ip = ntohl(val);
154
155         if (strlen(name) > sizeof(ifr.ifr_name)-1)
156                 return -E2BIG;
157         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
158
159         ifr.ifr_addr.sa_family = AF_INET;
160         rc = libcfs_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr);
161
162         if (rc != 0) {
163                 CERROR("Can't get netmask for interface %s\n", name);
164                 return rc;
165         }
166
167         val = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
168         *mask = ntohl(val);
169
170         return 0;
171 }
172
173 EXPORT_SYMBOL(libcfs_ipif_query);
174
175 int
176 libcfs_ipif_enumerate (char ***namesp)
177 {
178         /* Allocate and fill in 'names', returning # interfaces/error */
179         char           **names;
180         int             toobig;
181         int             nalloc;
182         int             nfound;
183         struct ifreq   *ifr;
184         struct ifconf   ifc;
185         int             rc;
186         int             nob;
187         int             i;
188
189
190         nalloc = 16;        /* first guess at max interfaces */
191         toobig = 0;
192         for (;;) {
193                 if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) {
194                         toobig = 1;
195                         nalloc = PAGE_CACHE_SIZE/sizeof(*ifr);
196                         CWARN("Too many interfaces: only enumerating first %d\n",
197                               nalloc);
198                 }
199
200                 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
201                 if (ifr == NULL) {
202                         CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
203                         rc = -ENOMEM;
204                         goto out0;
205                 }
206
207                 ifc.ifc_buf = (char *)ifr;
208                 ifc.ifc_len = nalloc * sizeof(*ifr);
209
210                 rc = libcfs_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
211
212                 if (rc < 0) {
213                         CERROR ("Error %d enumerating interfaces\n", rc);
214                         goto out1;
215                 }
216
217                 LASSERT (rc == 0);
218
219                 nfound = ifc.ifc_len/sizeof(*ifr);
220                 LASSERT (nfound <= nalloc);
221
222                 if (nfound < nalloc || toobig)
223                         break;
224
225                 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
226                 nalloc *= 2;
227         }
228
229         if (nfound == 0)
230                 goto out1;
231
232         LIBCFS_ALLOC(names, nfound * sizeof(*names));
233         if (names == NULL) {
234                 rc = -ENOMEM;
235                 goto out1;
236         }
237         /* NULL out all names[i] */
238         memset (names, 0, nfound * sizeof(*names));
239
240         for (i = 0; i < nfound; i++) {
241
242                 nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
243                 if (nob == IFNAMSIZ) {
244                         /* no space for terminating NULL */
245                         CERROR("interface name %.*s too long (%d max)\n",
246                                nob, ifr[i].ifr_name, IFNAMSIZ);
247                         rc = -ENAMETOOLONG;
248                         goto out2;
249                 }
250
251                 LIBCFS_ALLOC(names[i], IFNAMSIZ);
252                 if (names[i] == NULL) {
253                         rc = -ENOMEM;
254                         goto out2;
255                 }
256
257                 memcpy(names[i], ifr[i].ifr_name, nob);
258                 names[i][nob] = 0;
259         }
260
261         *namesp = names;
262         rc = nfound;
263
264  out2:
265         if (rc < 0)
266                 libcfs_ipif_free_enumeration(names, nfound);
267  out1:
268         LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
269  out0:
270         return rc;
271 }
272
273 EXPORT_SYMBOL(libcfs_ipif_enumerate);
274
275 void
276 libcfs_ipif_free_enumeration (char **names, int n)
277 {
278         int      i;
279
280         LASSERT (n > 0);
281
282         for (i = 0; i < n && names[i] != NULL; i++)
283                 LIBCFS_FREE(names[i], IFNAMSIZ);
284
285         LIBCFS_FREE(names, n * sizeof(*names));
286 }
287
288 EXPORT_SYMBOL(libcfs_ipif_free_enumeration);
289
290 int
291 libcfs_sock_write (struct socket *sock, void *buffer, int nob, int timeout)
292 {
293         int            rc;
294         mm_segment_t   oldmm = get_fs();
295         long           ticks = timeout * HZ;
296         unsigned long  then;
297         struct timeval tv;
298
299         LASSERT (nob > 0);
300         /* Caller may pass a zero timeout if she thinks the socket buffer is
301          * empty enough to take the whole message immediately */
302
303         for (;;) {
304                 struct iovec  iov = {
305                         .iov_base = buffer,
306                         .iov_len  = nob
307                 };
308                 struct msghdr msg = {
309                         .msg_name       = NULL,
310                         .msg_namelen    = 0,
311                         .msg_iov        = &iov,
312                         .msg_iovlen     = 1,
313                         .msg_control    = NULL,
314                         .msg_controllen = 0,
315                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
316                 };
317
318                 if (timeout != 0) {
319                         /* Set send timeout to remaining time */
320                         tv = (struct timeval) {
321                                 .tv_sec = ticks / HZ,
322                                 .tv_usec = ((ticks % HZ) * 1000000) / HZ
323                         };
324                         set_fs(KERNEL_DS);
325                         rc = sock_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
326                                              (char *)&tv, sizeof(tv));
327                         set_fs(oldmm);
328                         if (rc != 0) {
329                                 CERROR("Can't set socket send timeout "
330                                        "%ld.%06d: %d\n",
331                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
332                                 return rc;
333                         }
334                 }
335
336                 set_fs (KERNEL_DS);
337                 then = jiffies;
338                 rc = sock_sendmsg (sock, &msg, iov.iov_len);
339                 ticks -= jiffies - then;
340                 set_fs (oldmm);
341
342                 if (rc == nob)
343                         return 0;
344
345                 if (rc < 0)
346                         return rc;
347
348                 if (rc == 0) {
349                         CERROR ("Unexpected zero rc\n");
350                         return (-ECONNABORTED);
351                 }
352
353                 if (ticks <= 0)
354                         return -EAGAIN;
355
356                 buffer = ((char *)buffer) + rc;
357                 nob -= rc;
358         }
359
360         return (0);
361 }
362 EXPORT_SYMBOL(libcfs_sock_write);
363
364 int
365 libcfs_sock_read (struct socket *sock, void *buffer, int nob, int timeout)
366 {
367         int            rc;
368         mm_segment_t   oldmm = get_fs();
369         long           ticks = timeout * HZ;
370         unsigned long  then;
371         struct timeval tv;
372
373         LASSERT (nob > 0);
374         LASSERT (ticks > 0);
375
376         for (;;) {
377                 struct iovec  iov = {
378                         .iov_base = buffer,
379                         .iov_len  = nob
380                 };
381                 struct msghdr msg = {
382                         .msg_name       = NULL,
383                         .msg_namelen    = 0,
384                         .msg_iov        = &iov,
385                         .msg_iovlen     = 1,
386                         .msg_control    = NULL,
387                         .msg_controllen = 0,
388                         .msg_flags      = 0
389                 };
390
391                 /* Set receive timeout to remaining time */
392                 tv = (struct timeval) {
393                         .tv_sec = ticks / HZ,
394                         .tv_usec = ((ticks % HZ) * 1000000) / HZ
395                 };
396                 set_fs(KERNEL_DS);
397                 rc = sock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
398                                      (char *)&tv, sizeof(tv));
399                 set_fs(oldmm);
400                 if (rc != 0) {
401                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
402                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
403                         return rc;
404                 }
405
406                 set_fs(KERNEL_DS);
407                 then = jiffies;
408                 rc = sock_recvmsg(sock, &msg, iov.iov_len, 0);
409                 ticks -= jiffies - then;
410                 set_fs(oldmm);
411
412                 if (rc < 0)
413                         return rc;
414
415                 if (rc == 0)
416                         return -ECONNRESET;
417
418                 buffer = ((char *)buffer) + rc;
419                 nob -= rc;
420
421                 if (nob == 0)
422                         return 0;
423
424                 if (ticks <= 0)
425                         return -ETIMEDOUT;
426         }
427 }
428
429 EXPORT_SYMBOL(libcfs_sock_read);
430
431 static int
432 libcfs_sock_create (struct socket **sockp, int *fatal,
433                     __u32 local_ip, int local_port)
434 {
435         struct sockaddr_in  locaddr;
436         struct socket      *sock;
437         int                 rc;
438         int                 option;
439         mm_segment_t        oldmm = get_fs();
440
441         /* All errors are fatal except bind failure if the port is in use */
442         *fatal = 1;
443
444         rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
445         *sockp = sock;
446         if (rc != 0) {
447                 CERROR ("Can't create socket: %d\n", rc);
448                 return (rc);
449         }
450
451         set_fs (KERNEL_DS);
452         option = 1;
453         rc = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
454                              (char *)&option, sizeof (option));
455         set_fs (oldmm);
456         if (rc != 0) {
457                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
458                 goto failed;
459         }
460
461         if (local_ip != 0 || local_port != 0) {
462                 memset(&locaddr, 0, sizeof(locaddr));
463                 locaddr.sin_family = AF_INET;
464                 locaddr.sin_port = htons(local_port);
465                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
466                                           INADDR_ANY : htonl(local_ip);
467
468                 rc = sock->ops->bind(sock, (struct sockaddr *)&locaddr,
469                                      sizeof(locaddr));
470                 if (rc == -EADDRINUSE) {
471                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
472                         *fatal = 0;
473                         goto failed;
474                 }
475                 if (rc != 0) {
476                         CERROR("Error trying to bind to port %d: %d\n",
477                                local_port, rc);
478                         goto failed;
479                 }
480         }
481
482         return 0;
483
484  failed:
485         sock_release(sock);
486         return rc;
487 }
488
489 int
490 libcfs_sock_setbuf (struct socket *sock, int txbufsize, int rxbufsize)
491 {
492         mm_segment_t        oldmm = get_fs();
493         int                 option;
494         int                 rc;
495
496         if (txbufsize != 0) {
497                 option = txbufsize;
498                 set_fs (KERNEL_DS);
499                 rc = sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
500                                      (char *)&option, sizeof (option));
501                 set_fs (oldmm);
502                 if (rc != 0) {
503                         CERROR ("Can't set send buffer %d: %d\n",
504                                 option, rc);
505                         return (rc);
506                 }
507         }
508
509         if (rxbufsize != 0) {
510                 option = rxbufsize;
511                 set_fs (KERNEL_DS);
512                 rc = sock_setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
513                                       (char *)&option, sizeof (option));
514                 set_fs (oldmm);
515                 if (rc != 0) {
516                         CERROR ("Can't set receive buffer %d: %d\n",
517                                 option, rc);
518                         return (rc);
519                 }
520         }
521
522         return 0;
523 }
524
525 EXPORT_SYMBOL(libcfs_sock_setbuf);
526
527 int
528 libcfs_sock_getaddr (struct socket *sock, int remote, __u32 *ip, int *port)
529 {
530         struct sockaddr_in sin;
531         int                len = sizeof (sin);
532         int                rc;
533
534         rc = sock->ops->getname (sock, (struct sockaddr *)&sin, &len,
535                                  remote ? 2 : 0);
536         if (rc != 0) {
537                 CERROR ("Error %d getting sock %s IP/port\n",
538                         rc, remote ? "peer" : "local");
539                 return rc;
540         }
541
542         if (ip != NULL)
543                 *ip = ntohl (sin.sin_addr.s_addr);
544
545         if (port != NULL)
546                 *port = ntohs (sin.sin_port);
547
548         return 0;
549 }
550
551 EXPORT_SYMBOL(libcfs_sock_getaddr);
552
553 int
554 libcfs_sock_getbuf (struct socket *sock, int *txbufsize, int *rxbufsize)
555 {
556
557         if (txbufsize != NULL) {
558                 *txbufsize = sock->sk->sk_sndbuf;
559         }
560
561         if (rxbufsize != NULL) {
562                 *rxbufsize = sock->sk->sk_rcvbuf;
563         }
564
565         return 0;
566 }
567
568 EXPORT_SYMBOL(libcfs_sock_getbuf);
569
570 int
571 libcfs_sock_listen (struct socket **sockp,
572                     __u32 local_ip, int local_port, int backlog)
573 {
574         int      fatal;
575         int      rc;
576
577         rc = libcfs_sock_create(sockp, &fatal, local_ip, local_port);
578         if (rc != 0) {
579                 if (!fatal)
580                         CERROR("Can't create socket: port %d already in use\n",
581                                local_port);
582                 return rc;
583         }
584
585         rc = (*sockp)->ops->listen(*sockp, backlog);
586         if (rc == 0)
587                 return 0;
588
589         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
590         sock_release(*sockp);
591         return rc;
592 }
593
594 EXPORT_SYMBOL(libcfs_sock_listen);
595
596 int
597 libcfs_sock_accept (struct socket **newsockp, struct socket *sock)
598 {
599         wait_queue_t   wait;
600         struct socket *newsock;
601         int            rc;
602
603         init_waitqueue_entry(&wait, current);
604
605         /* XXX this should add a ref to sock->ops->owner, if
606          * TCP could be a module */
607         rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
608         if (rc) {
609                 CERROR("Can't allocate socket\n");
610                 return rc;
611         }
612
613         newsock->ops = sock->ops;
614
615         set_current_state(TASK_INTERRUPTIBLE);
616         add_wait_queue(sk_sleep(sock->sk), &wait);
617
618         rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
619         if (rc == -EAGAIN) {
620                 /* Nothing ready, so wait for activity */
621                 schedule();
622                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
623         }
624
625         remove_wait_queue(sk_sleep(sock->sk), &wait);
626         set_current_state(TASK_RUNNING);
627
628         if (rc != 0)
629                 goto failed;
630
631         *newsockp = newsock;
632         return 0;
633
634  failed:
635         sock_release(newsock);
636         return rc;
637 }
638
639 EXPORT_SYMBOL(libcfs_sock_accept);
640
641 void
642 libcfs_sock_abort_accept (struct socket *sock)
643 {
644         wake_up_all(sk_sleep(sock->sk));
645 }
646
647 EXPORT_SYMBOL(libcfs_sock_abort_accept);
648
649 int
650 libcfs_sock_connect (struct socket **sockp, int *fatal,
651                      __u32 local_ip, int local_port,
652                      __u32 peer_ip, int peer_port)
653 {
654         struct sockaddr_in  srvaddr;
655         int                 rc;
656
657         rc = libcfs_sock_create(sockp, fatal, local_ip, local_port);
658         if (rc != 0)
659                 return rc;
660
661         memset (&srvaddr, 0, sizeof (srvaddr));
662         srvaddr.sin_family = AF_INET;
663         srvaddr.sin_port = htons(peer_port);
664         srvaddr.sin_addr.s_addr = htonl(peer_ip);
665
666         rc = (*sockp)->ops->connect(*sockp,
667                                     (struct sockaddr *)&srvaddr, sizeof(srvaddr),
668                                     0);
669         if (rc == 0)
670                 return 0;
671
672         /* EADDRNOTAVAIL probably means we're already connected to the same
673          * peer/port on the same local port on a differently typed
674          * connection.  Let our caller retry with a different local
675          * port... */
676         *fatal = !(rc == -EADDRNOTAVAIL);
677
678         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
679                "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
680                HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);
681
682         sock_release(*sockp);
683         return rc;
684 }
685
686 EXPORT_SYMBOL(libcfs_sock_connect);
687
688 void
689 libcfs_sock_release (struct socket *sock)
690 {
691         sock_release(sock);
692 }
693
694 EXPORT_SYMBOL(libcfs_sock_release);