Whamcloud - gitweb
b=14132
[fs/lustre-release.git] / libcfs / libcfs / user-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
37 #if !defined(__KERNEL__) || !defined(REDSTORM)
38
39 #include <libcfs/libcfs.h>
40
41 #include <sys/socket.h>
42 #ifdef  HAVE_NETINET_IN_H
43 #include <netinet/in.h>
44 #endif
45 #include <netinet/tcp.h>
46 #include <sys/ioctl.h>
47 #include <unistd.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <poll.h>
51 #include <net/if.h>
52 #include <arpa/inet.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #if defined(__sun__) || defined(__sun)
56 #include <sys/sockio.h>
57 #endif
58 #ifndef __CYGWIN__
59 #include <sys/syscall.h>
60 #endif
61
62 /*
63  * Functions to get network interfaces info
64  */
65
66 int
67 libcfs_sock_ioctl(int cmd, unsigned long arg)
68 {
69         int fd, rc;
70
71         fd = socket(AF_INET, SOCK_STREAM, 0);
72
73         if (fd < 0) {
74                 rc = -errno;
75                 CERROR("socket() failed: errno==%d\n", errno);
76                 return rc;
77         }
78
79         rc = ioctl(fd, cmd, arg);
80
81         close(fd);
82         return rc;
83 }
84
85 int
86 libcfs_ipif_query (char *name, int *up, __u32 *ip)
87 {
88         struct ifreq   ifr;
89         int            nob;
90         int            rc;
91         __u32          val;
92
93         nob = strlen(name);
94         if (nob >= IFNAMSIZ) {
95                 CERROR("Interface name %s too long\n", name);
96                 return -EINVAL;
97         }
98
99         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
100
101         strcpy(ifr.ifr_name, name);
102         rc = libcfs_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
103
104         if (rc != 0) {
105                 CERROR("Can't get flags for interface %s\n", name);
106                 return rc;
107         }
108
109         if ((ifr.ifr_flags & IFF_UP) == 0) {
110                 CDEBUG(D_NET, "Interface %s down\n", name);
111                 *up = 0;
112                 *ip = 0;
113                 return 0;
114         }
115
116         *up = 1;
117
118         strcpy(ifr.ifr_name, name);
119         ifr.ifr_addr.sa_family = AF_INET;
120         rc = libcfs_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
121
122         if (rc != 0) {
123                 CERROR("Can't get IP address for interface %s\n", name);
124                 return rc;
125         }
126
127         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
128         *ip = ntohl(val);
129
130         return 0;
131 }
132
133 void
134 libcfs_ipif_free_enumeration (char **names, int n)
135 {
136         int      i;
137
138         LASSERT (n > 0);
139
140         for (i = 0; i < n && names[i] != NULL; i++)
141                 LIBCFS_FREE(names[i], IFNAMSIZ);
142
143         LIBCFS_FREE(names, n * sizeof(*names));
144 }
145
146 int
147 libcfs_ipif_enumerate (char ***namesp)
148 {
149         /* Allocate and fill in 'names', returning # interfaces/error */
150         char          **names;
151         int             nalloc;
152         int             nfound;
153         struct ifreq   *ifr;
154         struct ifconf   ifc;
155         int             rc;
156         int             nob;
157         int             i;
158
159
160         nalloc = 16;        /* first guess at max interfaces */
161         for (;;) {
162                 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
163                 if (ifr == NULL) {
164                         CERROR ("ENOMEM enumerating up to %d interfaces\n",
165                                 nalloc);
166                         rc = -ENOMEM;
167                         goto out0;
168                 }
169
170                 ifc.ifc_buf = (char *)ifr;
171                 ifc.ifc_len = nalloc * sizeof(*ifr);
172
173                 rc = libcfs_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
174
175                 if (rc < 0) {
176                         CERROR ("Error %d enumerating interfaces\n", rc);
177                         goto out1;
178                 }
179
180                 LASSERT (rc == 0);
181
182                 nfound = ifc.ifc_len/sizeof(*ifr);
183                 LASSERT (nfound <= nalloc);
184
185                 if (nfound < nalloc)
186                         break;
187
188                 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
189                 nalloc *= 2;
190         }
191
192         if (nfound == 0)
193                 goto out1;
194
195         LIBCFS_ALLOC(names, nfound * sizeof(*names));
196         if (names == NULL) {
197                 rc = -ENOMEM;
198                 goto out1;
199         }
200         /* NULL out all names[i] */
201         memset (names, 0, nfound * sizeof(*names));
202
203         for (i = 0; i < nfound; i++) {
204
205                 nob = strlen (ifr[i].ifr_name);
206                 if (nob >= IFNAMSIZ) {
207                         /* no space for terminating NULL */
208                         CERROR("interface name %.*s too long (%d max)\n",
209                                nob, ifr[i].ifr_name, IFNAMSIZ);
210                         rc = -ENAMETOOLONG;
211                         goto out2;
212                 }
213
214                 LIBCFS_ALLOC(names[i], IFNAMSIZ);
215                 if (names[i] == NULL) {
216                         rc = -ENOMEM;
217                         goto out2;
218                 }
219
220                 memcpy(names[i], ifr[i].ifr_name, nob);
221                 names[i][nob] = 0;
222         }
223
224         *namesp = names;
225         rc = nfound;
226
227  out2:
228         if (rc < 0)
229                 libcfs_ipif_free_enumeration(names, nfound);
230  out1:
231         LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
232  out0:
233         return rc;
234 }
235
236 /*
237  * Network functions used by user-land lnet acceptor
238  */
239
240 int
241 libcfs_sock_listen (cfs_socket_t **sockp,
242                     __u32 local_ip, int local_port, int backlog)
243 {
244         int rc;
245         int fatal;
246
247         rc = libcfs_sock_create(sockp, &fatal, local_ip, local_port);
248         if (rc != 0)
249                 return rc;
250
251         if ( listen((*sockp)->s_fd, backlog) ) {
252                 rc = -errno;
253                 CERROR("listen() with backlog==%d failed: errno==%d\n",
254                        backlog, errno);
255                 goto failed;
256         }
257
258         return 0;
259
260   failed:
261         libcfs_sock_release(*sockp);
262         return rc;
263 }
264
265 void
266 libcfs_sock_release (cfs_socket_t *sock)
267 {
268         close(sock->s_fd);
269         LIBCFS_FREE(sock, sizeof(cfs_socket_t));
270 }
271
272 int
273 libcfs_sock_accept (cfs_socket_t **newsockp, cfs_socket_t *sock)
274 {
275         struct sockaddr_in accaddr;
276         socklen_t          accaddr_len = sizeof(struct sockaddr_in);
277
278         LIBCFS_ALLOC(*newsockp, sizeof(cfs_socket_t));
279         if (*newsockp == NULL) {
280                 CERROR ("Can't alloc memory for cfs_socket_t\n");
281                 return -ENOMEM;
282         }
283
284         (*newsockp)->s_fd = accept(sock->s_fd,
285                                    (struct sockaddr *)&accaddr, &accaddr_len);
286
287         if ( (*newsockp)->s_fd < 0 ) {
288                 int rc = -errno;
289                 CERROR("accept() failed: errno==%d\n", -rc);
290                 LIBCFS_FREE(*newsockp, sizeof(cfs_socket_t));
291                 return rc;
292         }
293
294         return 0;
295 }
296
297 int
298 libcfs_sock_read (cfs_socket_t *sock, void *buffer, int nob, int timeout)
299 {
300         int           rc;
301         struct pollfd pfd;
302         cfs_time_t    start_time = cfs_time_current();
303
304         pfd.fd = sock->s_fd;
305         pfd.events = POLLIN;
306         pfd.revents = 0;
307
308         /* poll(2) measures timeout in msec */
309         timeout *= 1000;
310
311         while (nob != 0 && timeout > 0) {
312                 cfs_time_t current_time;
313
314                 rc = poll(&pfd, 1, timeout);
315                 if (rc < 0)
316                         return -errno;
317                 if (rc == 0)
318                         return -ETIMEDOUT;
319                 if ((pfd.revents & POLLIN) == 0)
320                         return -EIO;
321
322                 rc = read(sock->s_fd, buffer, nob);
323                 if (rc < 0)
324                         return -errno;
325                 if (rc == 0)
326                         return -EIO;
327
328                 buffer = ((char *)buffer) + rc;
329                 nob -= rc;
330
331                 current_time = cfs_time_current();
332                 timeout -= 1000 *
333                         cfs_duration_sec(cfs_time_sub(current_time,
334                                                       start_time));
335                 start_time = current_time;
336         }
337
338         if (nob == 0)
339                 return 0;
340         else
341                 return -ETIMEDOUT;
342 }
343
344 int
345 libcfs_sock_write (cfs_socket_t *sock, void *buffer, int nob, int timeout)
346 {
347         int           rc;
348         struct pollfd pfd;
349         cfs_time_t    start_time = cfs_time_current();
350
351         pfd.fd = sock->s_fd;
352         pfd.events = POLLOUT;
353         pfd.revents = 0;
354
355         /* poll(2) measures timeout in msec */
356         timeout *= 1000;
357
358         while (nob != 0 && timeout > 0) {
359                 cfs_time_t current_time;
360
361                 rc = poll(&pfd, 1, timeout);
362                 if (rc < 0)
363                         return -errno;
364                 if (rc == 0)
365                         return -ETIMEDOUT;
366                 if ((pfd.revents & POLLOUT) == 0)
367                         return -EIO;
368
369                 rc = write(sock->s_fd, buffer, nob);
370                 if (rc < 0)
371                         return -errno;
372                 if (rc == 0)
373                         return -EIO;
374
375                 buffer = ((char *)buffer) + rc;
376                 nob -= rc;
377
378                 current_time = cfs_time_current();
379                 timeout -= 1000 *
380                         cfs_duration_sec(cfs_time_sub(current_time,
381                                                       start_time));
382                 start_time = current_time;
383         }
384
385         if (nob == 0)
386                 return 0;
387         else
388                 return -ETIMEDOUT;
389 }
390
391 /* Just try to connect to localhost to wake up entity that are
392  * sleeping in accept() */
393 void
394 libcfs_sock_abort_accept(cfs_socket_t *sock)
395 {
396         int                fd, rc;
397         struct sockaddr_in remaddr;
398         struct sockaddr_in locaddr;
399         socklen_t          alen = sizeof(struct sockaddr_in);
400
401         rc = getsockname(sock->s_fd, (struct sockaddr *)&remaddr, &alen);
402         if ( rc != 0 ) {
403                 CERROR("getsockname() failed: errno==%d\n", errno);
404                 return;
405         }
406
407         memset(&locaddr, 0, sizeof(locaddr));
408         locaddr.sin_family = AF_INET;
409         locaddr.sin_port = remaddr.sin_port;
410         locaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
411
412         fd = socket(AF_INET, SOCK_STREAM, 0);
413         if ( fd < 0 ) {
414                 CERROR("socket() failed: errno==%d\n", errno);
415                 return;
416         }
417
418         rc = connect(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
419         if ( rc != 0 ) {
420                 if ( errno != ECONNREFUSED )
421                         CERROR("connect() failed: errno==%d\n", errno);
422                 else
423                         CDEBUG(D_NET, "Nobody to wake up at %d\n",
424                                ntohs(remaddr.sin_port));
425         }
426
427         close(fd);
428 }
429
430 int
431 libcfs_sock_getaddr(cfs_socket_t *sock, int remote, __u32 *ip, int *port)
432 {
433         int                rc;
434         struct sockaddr_in peer_addr;
435         socklen_t          peer_addr_len = sizeof(peer_addr);
436
437         LASSERT(remote == 1);
438
439         rc = getpeername(sock->s_fd,
440                          (struct sockaddr *)&peer_addr, &peer_addr_len);
441         if (rc != 0)
442                 return -errno;
443
444         if (ip != NULL)
445                 *ip = ntohl(peer_addr.sin_addr.s_addr);
446         if (port != NULL)
447                 *port = ntohs(peer_addr.sin_port);
448
449         return rc;
450 }
451
452 /*
453  * Network functions of common use
454  */
455
456 int
457 libcfs_socketpair(cfs_socket_t **sockp)
458 {
459         int rc, i, fdp[2];
460
461         LIBCFS_ALLOC(sockp[0], sizeof(cfs_socket_t));
462         if (sockp[0] == NULL) {
463                 CERROR ("Can't alloc memory for cfs_socket_t (1)\n");
464                 return -ENOMEM;
465         }
466
467         LIBCFS_ALLOC(sockp[1], sizeof(cfs_socket_t));
468         if (sockp[1] == NULL) {
469                 CERROR ("Can't alloc memory for cfs_socket_t (2)\n");
470                 LIBCFS_FREE(sockp[0], sizeof(cfs_socket_t));
471                 return -ENOMEM;
472         }
473
474         rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fdp);
475         if (rc != 0) {
476                 rc = -errno;
477                 CERROR ("Cannot create socket pair\n");
478                 LIBCFS_FREE(sockp[0], sizeof(cfs_socket_t));
479                 LIBCFS_FREE(sockp[1], sizeof(cfs_socket_t));
480                 return rc;
481         }
482
483         sockp[0]->s_fd = fdp[0];
484         sockp[1]->s_fd = fdp[1];
485
486         for (i = 0; i < 2; i++) {
487                 rc = libcfs_fcntl_nonblock(sockp[i]);
488                 if (rc) {
489                         libcfs_sock_release(sockp[0]);
490                         libcfs_sock_release(sockp[1]);
491                         return rc;
492                 }
493         }
494
495         return 0;
496 }
497
498 int
499 libcfs_fcntl_nonblock(cfs_socket_t *sock)
500 {
501         int rc, flags;
502
503         flags = fcntl(sock->s_fd, F_GETFL, 0);
504         if (flags == -1) {
505                 rc = -errno;
506                 CERROR ("Cannot get socket flags\n");
507                 return rc;
508         }
509
510         rc = fcntl(sock->s_fd, F_SETFL, flags | O_NONBLOCK);
511         if (rc != 0) {
512                 rc = -errno;
513                 CERROR ("Cannot set socket flags\n");
514                 return rc;
515         }
516
517         return 0;
518 }
519
520 int
521 libcfs_sock_set_nagle(cfs_socket_t *sock, int nagle)
522 {
523         int rc;
524         int option = nagle ? 0 : 1;
525
526 #if defined(__sun__) || defined(__sun)
527         rc = setsockopt(sock->s_fd,
528                         IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
529 #else
530         rc = setsockopt(sock->s_fd,
531                         SOL_TCP, TCP_NODELAY, &option, sizeof(option));
532 #endif
533
534         if (rc != 0) {
535                 rc = -errno;
536                 CERROR ("Cannot set NODELAY socket option\n");
537                 return rc;
538         }
539
540         return 0;
541 }
542
543 int
544 libcfs_sock_set_bufsiz(cfs_socket_t *sock, int bufsiz)
545 {
546         int rc, option;
547
548         LASSERT (bufsiz != 0);
549
550         option = bufsiz;
551         rc = setsockopt(sock->s_fd,
552                         SOL_SOCKET, SO_SNDBUF, &option, sizeof(option));
553         if (rc != 0) {
554                 rc = -errno;
555                 CERROR ("Cannot set SNDBUF socket option\n");
556                 return rc;
557         }
558
559         option = bufsiz;
560         rc = setsockopt(sock->s_fd,
561                         SOL_SOCKET, SO_RCVBUF, &option, sizeof(option));
562         if (rc != 0) {
563                 rc = -errno;
564                 CERROR ("Cannot set RCVBUF socket option\n");
565                 return rc;
566         }
567
568         return 0;
569 }
570
571 int
572 libcfs_sock_bind(cfs_socket_t *sock, __u32 ip, __u16 port)
573 {
574         int                rc;
575         struct sockaddr_in locaddr;
576
577         if (ip == 0 && port == 0)
578                 return 0;
579
580         memset(&locaddr, 0, sizeof(locaddr));
581         locaddr.sin_family = AF_INET;
582         locaddr.sin_addr.s_addr = (ip == 0) ? INADDR_ANY : htonl(ip);
583         locaddr.sin_port = htons(port);
584
585         rc = bind(sock->s_fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
586         if (rc != 0) {
587                 rc = -errno;
588                 CERROR("Cannot bind to %d.%d.%d.%d %d: %d\n",
589                        HIPQUAD(ip), port, rc);
590                 return rc;
591         }
592
593         return 0;
594 }
595
596 int
597 libcfs_sock_create(cfs_socket_t **sockp, int *fatal,
598                    __u32 local_ip, int local_port)
599 {
600         int rc, fd, option;
601
602         *fatal = 1;
603
604         LIBCFS_ALLOC(*sockp, sizeof(cfs_socket_t));
605         if (*sockp == NULL) {
606                 CERROR("Can't alloc memory for cfs_socket_t\n");
607                 return -ENOMEM;
608         }
609
610         fd = socket(AF_INET, SOCK_STREAM, 0);
611         if (fd < 0) {
612                 rc = -errno;
613                 CERROR("Cannot create socket: %d\n", rc);
614                 LIBCFS_FREE(*sockp, sizeof(cfs_socket_t));
615                 return rc;
616         }
617
618         (*sockp)->s_fd = fd;
619
620         option = 1;
621         rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
622                         &option, sizeof(option));
623         if (rc != 0) {
624                 rc = -errno;
625                 CERROR("Cannot set SO_REUSEADDR for socket: %d\n", rc);
626                 libcfs_sock_release(*sockp);
627                 return rc;
628         }
629
630         rc = libcfs_sock_bind(*sockp, local_ip, local_port);
631         if (rc != 0) {
632                 *fatal = 0;
633                 libcfs_sock_release(*sockp);
634         }
635
636         return rc;
637 }
638
639 int
640 libcfs_sock_connect(cfs_socket_t *sock, __u32 ip, __u16 port)
641 {
642         int                rc;
643         struct sockaddr_in addr;
644
645         memset(&addr, 0, sizeof(addr));
646         addr.sin_family      = AF_INET;
647         addr.sin_addr.s_addr = htonl(ip);
648         addr.sin_port        = htons(port);
649
650         rc = connect(sock->s_fd, (struct sockaddr *)&addr,
651                      sizeof(struct sockaddr_in));
652
653         if(rc != 0 && errno != EINPROGRESS) {
654                 rc = -errno;
655                 if (rc != -EADDRINUSE && rc != -EADDRNOTAVAIL)
656                         CERROR ("Cannot connect to %u.%u.%u.%u:%d (err=%d)\n",
657                                 HIPQUAD(ip), port, errno);
658                 return rc;
659         }
660
661         return 0;
662 }
663
664 /* NB: EPIPE and ECONNRESET are considered as non-fatal
665  * because:
666  * 1) it still makes sense to continue reading &&
667  * 2) anyway, poll() will set up POLLHUP|POLLERR flags */
668 int
669 libcfs_sock_writev(cfs_socket_t *sock, const struct iovec *vector, int count)
670 {
671         int rc;
672
673         rc = syscall(SYS_writev, sock->s_fd, vector, count);
674
675         if (rc == 0) /* write nothing */
676                 return 0;
677
678         if (rc < 0) {
679                 if (errno == EAGAIN ||   /* write nothing   */
680                     errno == EPIPE ||    /* non-fatal error */
681                     errno == ECONNRESET) /* non-fatal error */
682                         return 0;
683                 else
684                         return -errno;
685         }
686
687         return rc;
688 }
689
690 int
691 libcfs_sock_readv(cfs_socket_t *sock, const struct iovec *vector, int count)
692 {
693         int rc;
694
695         rc = syscall(SYS_readv, sock->s_fd, vector, count);
696
697         if (rc == 0) /* EOF */
698                 return -EIO;
699
700         if (rc < 0) {
701                 if (errno == EAGAIN) /* read nothing */
702                         return 0;
703                 else
704                         return -errno;
705         }
706
707         return rc;
708 }
709
710 #endif /* !__KERNEL__ || !defined(REDSTORM) */