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 [sun.com URL with a
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>
54 #if defined(__sun__) || defined(__sun)
55 #include <sys/sockio.h>
58 #include <sys/syscall.h>
62 * Functions to get network interfaces info
66 libcfs_sock_ioctl(int cmd, unsigned long arg)
70 fd = socket(AF_INET, SOCK_STREAM, 0);
74 CERROR("socket() failed: errno==%d\n", errno);
78 rc = ioctl(fd, cmd, arg);
85 libcfs_ipif_query (char *name, int *up, __u32 *ip)
93 if (nob >= IFNAMSIZ) {
94 CERROR("Interface name %s too long\n", name);
98 CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
100 strcpy(ifr.ifr_name, name);
101 rc = libcfs_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
104 CERROR("Can't get flags for interface %s\n", name);
108 if ((ifr.ifr_flags & IFF_UP) == 0) {
109 CDEBUG(D_NET, "Interface %s down\n", name);
117 strcpy(ifr.ifr_name, name);
118 ifr.ifr_addr.sa_family = AF_INET;
119 rc = libcfs_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
122 CERROR("Can't get IP address for interface %s\n", name);
126 val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
133 libcfs_ipif_free_enumeration (char **names, int n)
139 for (i = 0; i < n && names[i] != NULL; i++)
140 LIBCFS_FREE(names[i], IFNAMSIZ);
142 LIBCFS_FREE(names, n * sizeof(*names));
146 libcfs_ipif_enumerate (char ***namesp)
148 /* Allocate and fill in 'names', returning # interfaces/error */
159 nalloc = 16; /* first guess at max interfaces */
161 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
163 CERROR ("ENOMEM enumerating up to %d interfaces\n",
169 ifc.ifc_buf = (char *)ifr;
170 ifc.ifc_len = nalloc * sizeof(*ifr);
172 rc = libcfs_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
175 CERROR ("Error %d enumerating interfaces\n", rc);
181 nfound = ifc.ifc_len/sizeof(*ifr);
182 LASSERT (nfound <= nalloc);
187 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
194 LIBCFS_ALLOC(names, nfound * sizeof(*names));
199 /* NULL out all names[i] */
200 memset (names, 0, nfound * sizeof(*names));
202 for (i = 0; i < nfound; i++) {
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);
213 LIBCFS_ALLOC(names[i], IFNAMSIZ);
214 if (names[i] == NULL) {
219 memcpy(names[i], ifr[i].ifr_name, nob);
228 libcfs_ipif_free_enumeration(names, nfound);
230 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
236 * Network functions used by user-land lnet acceptor
240 libcfs_sock_listen (int *sockp, __u32 local_ip, int local_port, int backlog)
244 struct sockaddr_in locaddr;
246 *sockp = socket(AF_INET, SOCK_STREAM, 0);
249 CERROR("socket() failed: errno==%d\n", errno);
254 if ( setsockopt(*sockp, SOL_SOCKET, SO_REUSEADDR,
255 (char *)&option, sizeof (option)) ) {
257 CERROR("setsockopt(SO_REUSEADDR) failed: errno==%d\n", errno);
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);
268 if ( bind(*sockp, (struct sockaddr *)&locaddr, sizeof(locaddr)) ) {
270 if ( errno == -EADDRINUSE )
271 CDEBUG(D_NET, "Port %d already in use\n",
274 CERROR("bind() to port %d failed: errno==%d\n",
280 if ( listen(*sockp, backlog) ) {
282 CERROR("listen() with backlog==%d failed: errno==%d\n",
295 libcfs_sock_accept (int *newsockp, int sock, __u32 *peer_ip, int *peer_port)
297 struct sockaddr_in accaddr;
298 socklen_t accaddr_len = sizeof(struct sockaddr_in);
300 *newsockp = accept(sock, (struct sockaddr *)&accaddr, &accaddr_len);
302 if ( *newsockp < 0 ) {
303 CERROR("accept() failed: errno==%d\n", errno);
307 *peer_ip = ntohl(accaddr.sin_addr.s_addr);
308 *peer_port = ntohs(accaddr.sin_port);
314 libcfs_sock_read (int sock, void *buffer, int nob, int timeout)
318 cfs_time_t start_time = cfs_time_current();
324 /* poll(2) measures timeout in msec */
327 while (nob != 0 && timeout > 0) {
328 cfs_time_t current_time;
330 rc = poll(&pfd, 1, timeout);
335 if ((pfd.revents & POLLIN) == 0)
338 rc = read(sock, buffer, nob);
344 buffer = ((char *)buffer) + rc;
347 current_time = cfs_time_current();
348 timeout -= cfs_duration_sec(cfs_time_sub(cfs_time_current(),
358 /* Just try to connect to localhost to wake up entity that are
359 * sleeping in accept() */
361 libcfs_sock_abort_accept(__u16 port)
364 struct sockaddr_in locaddr;
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");
371 fd = socket(AF_INET, SOCK_STREAM, 0);
373 CERROR("socket() failed: errno==%d\n", errno);
377 rc = connect(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
379 if ( errno != ECONNREFUSED )
380 CERROR("connect() failed: errno==%d\n", errno);
382 CDEBUG(D_NET, "Nobody to wake up at %d\n", port);
389 * Network functions of common use
393 libcfs_getpeername(int sock_fd, __u32 *ipaddr_p, __u16 *port_p)
396 struct sockaddr_in peer_addr;
397 socklen_t peer_addr_len = sizeof(peer_addr);
399 rc = getpeername(sock_fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
403 if (ipaddr_p != NULL)
404 *ipaddr_p = ntohl(peer_addr.sin_addr.s_addr);
406 *port_p = ntohs(peer_addr.sin_port);
412 libcfs_socketpair(int *fdp)
416 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fdp);
419 CERROR ("Cannot create socket pair\n");
423 for (i = 0; i < 2; i++) {
424 rc = libcfs_fcntl_nonblock(fdp[i]);
436 libcfs_fcntl_nonblock(int fd)
440 flags = fcntl(fd, F_GETFL, 0);
443 CERROR ("Cannot get socket flags\n");
447 rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
450 CERROR ("Cannot set socket flags\n");
458 libcfs_sock_set_nagle(int fd, int nagle)
461 int option = nagle ? 0 : 1;
463 #if defined(__sun__) || defined(__sun)
464 rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
466 rc = setsockopt(fd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
471 CERROR ("Cannot set NODELAY socket option\n");
479 libcfs_sock_set_bufsiz(int fd, int bufsiz)
483 LASSERT (bufsiz != 0);
486 rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &option, sizeof(option));
489 CERROR ("Cannot set SNDBUF socket option\n");
494 rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &option, sizeof(option));
497 CERROR ("Cannot set RCVBUF socket option\n");
505 libcfs_sock_create(int *fdp)
509 fd = socket(AF_INET, SOCK_STREAM, 0);
512 CERROR ("Cannot create socket\n");
517 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
518 &option, sizeof(option));
521 CERROR ("Cannot set SO_REUSEADDR for socket\n");
531 libcfs_sock_bind_to_port(int fd, __u16 port)
534 struct sockaddr_in locaddr;
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);
541 rc = bind(fd, (struct sockaddr *)&locaddr, sizeof(locaddr));
544 CERROR ("Cannot bind to port %d\n", port);
552 libcfs_sock_connect(int fd, __u32 ip, __u16 port)
555 struct sockaddr_in addr;
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);
562 rc = connect(fd, (struct sockaddr *)&addr,
563 sizeof(struct sockaddr_in));
565 if(rc != 0 && errno != EINPROGRESS) {
567 if (rc != -EADDRINUSE && rc != -EADDRNOTAVAIL)
568 CERROR ("Cannot connect to %u.%u.%u.%u:%d (err=%d)\n",
569 HIPQUAD(ip), port, errno);
576 /* NB: EPIPE and ECONNRESET are considered as non-fatal
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)
584 rc = syscall(SYS_writev, fd, vector, count);
586 if (rc == 0) /* write nothing */
590 if (errno == EAGAIN || /* write nothing */
591 errno == EPIPE || /* non-fatal error */
592 errno == ECONNRESET) /* non-fatal error */
601 int libcfs_sock_readv(int fd, const struct iovec *vector, int count)
605 rc = syscall(SYS_readv, fd, vector, count);
607 if (rc == 0) /* EOF */
611 if (errno == EAGAIN) /* read nothing */
620 #endif /* !__KERNEL__ || !defined(REDSTORM) */