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