1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #if !defined(__KERNEL__) || !defined(REDSTORM)
39 #include <libcfs/libcfs.h>
41 #include <sys/socket.h>
42 #ifdef HAVE_NETINET_IN_H
43 #include <netinet/in.h>
45 #include <netinet/tcp.h>
46 #include <sys/ioctl.h>
52 #include <arpa/inet.h>
55 #if defined(__sun__) || defined(__sun)
56 #include <sys/sockio.h>
59 #include <sys/syscall.h>
63 * Functions to get network interfaces info
67 libcfs_sock_ioctl(int cmd, unsigned long arg)
71 fd = socket(AF_INET, SOCK_STREAM, 0);
75 CERROR("socket() failed: errno==%d\n", errno);
79 rc = ioctl(fd, cmd, arg);
86 libcfs_ipif_query (char *name, int *up, __u32 *ip)
94 if (nob >= IFNAMSIZ) {
95 CERROR("Interface name %s too long\n", name);
99 CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
101 strcpy(ifr.ifr_name, name);
102 rc = libcfs_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
105 CERROR("Can't get flags for interface %s\n", name);
109 if ((ifr.ifr_flags & IFF_UP) == 0) {
110 CDEBUG(D_NET, "Interface %s down\n", name);
118 strcpy(ifr.ifr_name, name);
119 ifr.ifr_addr.sa_family = AF_INET;
120 rc = libcfs_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
123 CERROR("Can't get IP address for interface %s\n", name);
127 val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
134 libcfs_ipif_free_enumeration (char **names, int n)
140 for (i = 0; i < n && names[i] != NULL; i++)
141 LIBCFS_FREE(names[i], IFNAMSIZ);
143 LIBCFS_FREE(names, n * sizeof(*names));
147 libcfs_ipif_enumerate (char ***namesp)
149 /* Allocate and fill in 'names', returning # interfaces/error */
160 nalloc = 16; /* first guess at max interfaces */
162 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
164 CERROR ("ENOMEM enumerating up to %d interfaces\n",
170 ifc.ifc_buf = (char *)ifr;
171 ifc.ifc_len = nalloc * sizeof(*ifr);
173 rc = libcfs_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
176 CERROR ("Error %d enumerating interfaces\n", rc);
182 nfound = ifc.ifc_len/sizeof(*ifr);
183 LASSERT (nfound <= nalloc);
188 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
195 LIBCFS_ALLOC(names, nfound * sizeof(*names));
200 /* NULL out all names[i] */
201 memset (names, 0, nfound * sizeof(*names));
203 for (i = 0; i < nfound; i++) {
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);
214 LIBCFS_ALLOC(names[i], IFNAMSIZ);
215 if (names[i] == NULL) {
220 memcpy(names[i], ifr[i].ifr_name, nob);
229 libcfs_ipif_free_enumeration(names, nfound);
231 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
237 * Network functions used by user-land lnet acceptor
241 libcfs_sock_listen (int *sockp, __u32 local_ip, int local_port, int backlog)
245 struct sockaddr_in locaddr;
247 *sockp = socket(AF_INET, SOCK_STREAM, 0);
250 CERROR("socket() failed: errno==%d\n", errno);
255 if ( setsockopt(*sockp, SOL_SOCKET, SO_REUSEADDR,
256 (char *)&option, sizeof (option)) ) {
258 CERROR("setsockopt(SO_REUSEADDR) failed: errno==%d\n", errno);
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);
269 if ( bind(*sockp, (struct sockaddr *)&locaddr, sizeof(locaddr)) ) {
271 if ( errno == -EADDRINUSE )
272 CDEBUG(D_NET, "Port %d already in use\n",
275 CERROR("bind() to port %d failed: errno==%d\n",
281 if ( listen(*sockp, backlog) ) {
283 CERROR("listen() with backlog==%d failed: errno==%d\n",
296 libcfs_sock_accept (int *newsockp, int sock, __u32 *peer_ip, int *peer_port)
298 struct sockaddr_in accaddr;
299 socklen_t accaddr_len = sizeof(struct sockaddr_in);
301 *newsockp = accept(sock, (struct sockaddr *)&accaddr, &accaddr_len);
303 if ( *newsockp < 0 ) {
304 CERROR("accept() failed: errno==%d\n", errno);
308 *peer_ip = ntohl(accaddr.sin_addr.s_addr);
309 *peer_port = ntohs(accaddr.sin_port);
315 libcfs_sock_read (int sock, void *buffer, int nob, int timeout)
319 cfs_time_t start_time = cfs_time_current();
325 /* poll(2) measures timeout in msec */
328 while (nob != 0 && timeout > 0) {
329 cfs_time_t current_time;
331 rc = poll(&pfd, 1, timeout);
336 if ((pfd.revents & POLLIN) == 0)
339 rc = read(sock, buffer, nob);
345 buffer = ((char *)buffer) + rc;
348 current_time = cfs_time_current();
349 timeout -= cfs_duration_sec(cfs_time_sub(cfs_time_current(),
359 /* Just try to connect to localhost to wake up entity that are
360 * sleeping in accept() */
362 libcfs_sock_abort_accept(__u16 port)
365 struct sockaddr_in locaddr;
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");
372 fd = socket(AF_INET, SOCK_STREAM, 0);
374 CERROR("socket() failed: errno==%d\n", errno);
378 rc = connect(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
380 if ( errno != ECONNREFUSED )
381 CERROR("connect() failed: errno==%d\n", errno);
383 CDEBUG(D_NET, "Nobody to wake up at %d\n", port);
390 * Network functions of common use
394 libcfs_getpeername(int sock_fd, __u32 *ipaddr_p, __u16 *port_p)
397 struct sockaddr_in peer_addr;
398 socklen_t peer_addr_len = sizeof(peer_addr);
400 rc = getpeername(sock_fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
404 if (ipaddr_p != NULL)
405 *ipaddr_p = ntohl(peer_addr.sin_addr.s_addr);
407 *port_p = ntohs(peer_addr.sin_port);
413 libcfs_socketpair(int *fdp)
417 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fdp);
420 CERROR ("Cannot create socket pair\n");
424 for (i = 0; i < 2; i++) {
425 rc = libcfs_fcntl_nonblock(fdp[i]);
437 libcfs_fcntl_nonblock(int fd)
441 flags = fcntl(fd, F_GETFL, 0);
444 CERROR ("Cannot get socket flags\n");
448 rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
451 CERROR ("Cannot set socket flags\n");
459 libcfs_sock_set_nagle(int fd, int nagle)
462 int option = nagle ? 0 : 1;
464 #if defined(__sun__) || defined(__sun)
465 rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
467 rc = setsockopt(fd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
472 CERROR ("Cannot set NODELAY socket option\n");
480 libcfs_sock_set_bufsiz(int fd, int bufsiz)
484 LASSERT (bufsiz != 0);
487 rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &option, sizeof(option));
490 CERROR ("Cannot set SNDBUF socket option\n");
495 rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &option, sizeof(option));
498 CERROR ("Cannot set RCVBUF socket option\n");
506 libcfs_sock_create(int *fdp)
510 fd = socket(AF_INET, SOCK_STREAM, 0);
513 CERROR ("Cannot create socket\n");
518 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
519 &option, sizeof(option));
522 CERROR ("Cannot set SO_REUSEADDR for socket\n");
531 void libcfs_sock_release(int fd)
537 libcfs_sock_bind_to_port(int fd, __u16 port)
540 struct sockaddr_in locaddr;
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);
547 rc = bind(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
550 CERROR ("Cannot bind to port %d\n", port);
558 libcfs_sock_connect(int fd, __u32 ip, __u16 port)
561 struct sockaddr_in addr;
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);
568 rc = connect(fd, (struct sockaddr *)&addr,
569 sizeof(struct sockaddr_in));
571 if(rc != 0 && errno != EINPROGRESS) {
573 if (rc != -EADDRINUSE && rc != -EADDRNOTAVAIL)
574 CERROR ("Cannot connect to %u.%u.%u.%u:%d (err=%d)\n",
575 HIPQUAD(ip), port, errno);
582 /* NB: EPIPE and ECONNRESET are considered as non-fatal
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)
590 rc = syscall(SYS_writev, fd, vector, count);
592 if (rc == 0) /* write nothing */
596 if (errno == EAGAIN || /* write nothing */
597 errno == EPIPE || /* non-fatal error */
598 errno == ECONNRESET) /* non-fatal error */
607 int libcfs_sock_readv(int fd, const struct iovec *vector, int count)
611 rc = syscall(SYS_readv, fd, vector, count);
613 if (rc == 0) /* EOF */
617 if (errno == EAGAIN) /* read nothing */
626 #endif /* !__KERNEL__ || !defined(REDSTORM) */