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