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