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