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