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