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