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