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