Whamcloud - gitweb
Branch HEAD
[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 (int *sockp, __u32 local_ip, int local_port, int backlog)
242 {
243         int                rc;
244         int                option;
245         struct sockaddr_in locaddr;
246         
247         *sockp = socket(AF_INET, SOCK_STREAM, 0);
248         if (*sockp < 0) {
249                 rc = -errno;
250                 CERROR("socket() failed: errno==%d\n", errno);
251                 return rc;
252         }
253
254         option = 1;
255         if ( setsockopt(*sockp, SOL_SOCKET, SO_REUSEADDR,
256                         (char *)&option, sizeof (option)) ) {
257                 rc = -errno;
258                 CERROR("setsockopt(SO_REUSEADDR) failed: errno==%d\n", errno);
259                 goto failed;
260         }
261
262         if (local_ip != 0 || local_port != 0) {
263                 memset(&locaddr, 0, sizeof(locaddr));
264                 locaddr.sin_family = AF_INET;
265                 locaddr.sin_port = htons(local_port);
266                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
267                                           INADDR_ANY : htonl(local_ip);
268
269                 if ( bind(*sockp, (struct sockaddr *)&locaddr, sizeof(locaddr)) ) {
270                         rc = -errno;
271                         if ( errno == -EADDRINUSE )
272                                 CDEBUG(D_NET, "Port %d already in use\n",
273                                        local_port);
274                         else
275                                 CERROR("bind() to port %d failed: errno==%d\n",
276                                        local_port, errno);
277                         goto failed;
278                 }
279         }
280
281         if ( listen(*sockp, backlog) ) {
282                 rc = -errno;
283                 CERROR("listen() with backlog==%d failed: errno==%d\n",
284                        backlog, errno);
285                 goto failed;
286         }
287         
288         return 0;
289
290   failed:
291         close(*sockp);
292         return rc;
293 }
294
295 int
296 libcfs_sock_accept (int *newsockp, int sock, __u32 *peer_ip, int *peer_port)
297 {
298         struct sockaddr_in accaddr;
299         socklen_t accaddr_len = sizeof(struct sockaddr_in);
300
301         *newsockp = accept(sock, (struct sockaddr *)&accaddr, &accaddr_len);
302
303         if ( *newsockp < 0 ) {
304                 CERROR("accept() failed: errno==%d\n", errno);
305                 return -errno;
306         }
307
308         *peer_ip = ntohl(accaddr.sin_addr.s_addr);
309         *peer_port = ntohs(accaddr.sin_port);
310         
311         return 0;
312 }
313
314 int
315 libcfs_sock_read (int sock, void *buffer, int nob, int timeout)
316 {
317         int rc;
318         struct pollfd pfd;
319         cfs_time_t start_time = cfs_time_current();
320
321         pfd.fd = sock;
322         pfd.events = POLLIN;
323         pfd.revents = 0;
324
325         /* poll(2) measures timeout in msec */
326         timeout *= 1000;
327         
328         while (nob != 0 && timeout > 0) {
329                 cfs_time_t current_time;
330
331                 rc = poll(&pfd, 1, timeout);
332                 if (rc < 0)
333                         return -errno;
334                 if (rc == 0)
335                         return -ETIMEDOUT;
336                 if ((pfd.revents & POLLIN) == 0)
337                         return -EIO;
338                                 
339                 rc = read(sock, buffer, nob);                
340                 if (rc < 0)
341                         return -errno;
342                 if (rc == 0)
343                         return -EIO;
344                 
345                 buffer = ((char *)buffer) + rc;
346                 nob -= rc;
347
348                 current_time = cfs_time_current();
349                 timeout -= cfs_duration_sec(cfs_time_sub(cfs_time_current(),
350                                                         start_time));
351         }
352         
353         if (nob == 0)
354                 return 0;
355         else
356                 return -ETIMEDOUT;
357 }
358
359 /* Just try to connect to localhost to wake up entity that are
360  * sleeping in accept() */
361 void
362 libcfs_sock_abort_accept(__u16 port)
363 {
364         int                fd, rc;
365         struct sockaddr_in locaddr;
366
367         memset(&locaddr, 0, sizeof(locaddr));
368         locaddr.sin_family = AF_INET;
369         locaddr.sin_port = htons(port);
370         locaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
371
372         fd = socket(AF_INET, SOCK_STREAM, 0);
373         if ( fd < 0 ) {
374                 CERROR("socket() failed: errno==%d\n", errno);
375                 return;
376         }        
377         
378         rc = connect(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
379         if ( rc != 0 ) {
380                 if ( errno != ECONNREFUSED )
381                         CERROR("connect() failed: errno==%d\n", errno);
382                 else
383                         CDEBUG(D_NET, "Nobody to wake up at %d\n", port);
384         }
385         
386         close(fd);
387 }
388
389 /*
390  * Network functions of common use
391  */
392
393 int
394 libcfs_getpeername(int sock_fd, __u32 *ipaddr_p, __u16 *port_p)
395 {
396         int                rc;
397         struct sockaddr_in peer_addr;
398         socklen_t          peer_addr_len = sizeof(peer_addr);
399
400         rc = getpeername(sock_fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
401         if (rc != 0)
402                 return -errno;
403         
404         if (ipaddr_p != NULL)
405                 *ipaddr_p = ntohl(peer_addr.sin_addr.s_addr);
406         if (port_p != NULL)
407                 *port_p = ntohs(peer_addr.sin_port);
408
409         return 0;
410 }
411
412 int
413 libcfs_socketpair(int *fdp)
414 {
415         int rc, i;
416         
417         rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fdp);
418         if (rc != 0) {
419                 rc = -errno;
420                 CERROR ("Cannot create socket pair\n");
421                 return rc;
422         }
423         
424         for (i = 0; i < 2; i++) {
425                 rc = libcfs_fcntl_nonblock(fdp[i]);
426                 if (rc) {
427                         close(fdp[0]);                        
428                         close(fdp[1]);
429                         return rc;
430                 }
431         }
432         
433         return 0;
434 }
435
436 int
437 libcfs_fcntl_nonblock(int fd)
438 {
439         int rc, flags;
440         
441         flags = fcntl(fd, F_GETFL, 0);
442         if (flags == -1) {
443                 rc = -errno;
444                 CERROR ("Cannot get socket flags\n");
445                 return rc;
446         }
447         
448         rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
449         if (rc != 0) {
450                 rc = -errno;
451                 CERROR ("Cannot set socket flags\n");
452                 return rc;
453         }
454         
455         return 0;
456 }
457
458 int
459 libcfs_sock_set_nagle(int fd, int nagle)
460 {
461         int rc;
462         int option = nagle ? 0 : 1;
463
464 #if defined(__sun__) || defined(__sun)
465         rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
466 #else
467         rc = setsockopt(fd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
468 #endif
469
470         if (rc != 0) {
471                 rc = -errno;
472                 CERROR ("Cannot set NODELAY socket option\n");
473                 return rc;
474         }
475
476         return 0;
477 }
478
479 int
480 libcfs_sock_set_bufsiz(int fd, int bufsiz)
481 {
482         int rc, option;
483         
484         LASSERT (bufsiz != 0);
485
486         option = bufsiz;
487         rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &option, sizeof(option));
488         if (rc != 0) {
489                 rc = -errno;
490                 CERROR ("Cannot set SNDBUF socket option\n");
491                 return rc;
492         }
493
494         option = bufsiz;
495         rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &option, sizeof(option));
496         if (rc != 0) {
497                 rc = -errno;
498                 CERROR ("Cannot set RCVBUF socket option\n");
499                 return rc;
500         }
501
502         return 0;
503 }
504
505 int
506 libcfs_sock_create(int *fdp)
507 {
508         int rc, fd, option;
509
510         fd = socket(AF_INET, SOCK_STREAM, 0);
511         if (fd < 0) {
512                 rc = -errno;
513                 CERROR ("Cannot create socket\n");
514                 return rc;
515         }
516
517         option = 1;
518         rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
519                         &option, sizeof(option));
520         if (rc != 0) {
521                 rc = -errno;
522                 CERROR  ("Cannot set SO_REUSEADDR for socket\n");
523                 close(fd);
524                 return rc;
525         } 
526         
527         *fdp = fd;
528         return 0;
529 }
530
531 void libcfs_sock_release(int fd)
532 {
533         close(fd);
534 }
535
536 int
537 libcfs_sock_bind_to_port(int fd, __u16 port)
538 {
539         int                rc;
540         struct sockaddr_in locaddr;
541
542         memset(&locaddr, 0, sizeof(locaddr)); 
543         locaddr.sin_family = AF_INET; 
544         locaddr.sin_addr.s_addr = INADDR_ANY;
545         locaddr.sin_port = htons(port);
546
547         rc = bind(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
548         if (rc != 0) {
549                 rc = -errno;
550                 CERROR  ("Cannot bind to port %d\n", port);
551                 return rc;
552         }
553
554         return 0;
555 }
556
557 int
558 libcfs_sock_connect(int fd, __u32 ip, __u16 port)
559 {
560         int                rc;
561         struct sockaddr_in addr;
562
563         memset(&addr, 0, sizeof(addr));
564         addr.sin_family      = AF_INET;
565         addr.sin_addr.s_addr = htonl(ip);
566         addr.sin_port        = htons(port);
567         
568         rc = connect(fd, (struct sockaddr *)&addr,
569                      sizeof(struct sockaddr_in));
570
571         if(rc != 0 && errno != EINPROGRESS) {
572                 rc = -errno;
573                 if (rc != -EADDRINUSE && rc != -EADDRNOTAVAIL)
574                         CERROR ("Cannot connect to %u.%u.%u.%u:%d (err=%d)\n",
575                                 HIPQUAD(ip), port, errno);
576                 return rc;
577         }
578
579         return 0;
580 }
581
582 /* NB: EPIPE and ECONNRESET are considered as non-fatal
583  * because:
584  * 1) it still makes sense to continue reading &&
585  * 2) anyway, poll() will set up POLLHUP|POLLERR flags */ 
586 int libcfs_sock_writev(int fd, const struct iovec *vector, int count)
587 {
588         int rc;
589         
590         rc = syscall(SYS_writev, fd, vector, count);
591         
592         if (rc == 0) /* write nothing */ 
593                 return 0;
594         
595         if (rc < 0) {
596                 if (errno == EAGAIN ||   /* write nothing   */
597                     errno == EPIPE ||    /* non-fatal error */
598                     errno == ECONNRESET) /* non-fatal error */
599                         return 0;
600                 else
601                         return -errno;
602         }
603
604         return rc;
605 }
606
607 int libcfs_sock_readv(int fd, const struct iovec *vector, int count)
608 {
609         int rc;
610         
611         rc = syscall(SYS_readv, fd, vector, count);
612         
613         if (rc == 0) /* EOF */ 
614                 return -EIO;
615         
616         if (rc < 0) {
617                 if (errno == EAGAIN) /* read nothing */
618                         return 0;
619                 else
620                         return -errno;
621         }
622
623         return rc;
624 }
625
626 #endif /* !__KERNEL__ || !defined(REDSTORM) */