xref: /freebsd/sbin/ggate/shared/ggate.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
16ac5fe48SPawel Jakub Dawidek /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
46ac5fe48SPawel Jakub Dawidek  * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
56ac5fe48SPawel Jakub Dawidek  * All rights reserved.
66ac5fe48SPawel Jakub Dawidek  *
76ac5fe48SPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
86ac5fe48SPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
96ac5fe48SPawel Jakub Dawidek  * are met:
106ac5fe48SPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
116ac5fe48SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
126ac5fe48SPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
136ac5fe48SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
146ac5fe48SPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
156ac5fe48SPawel Jakub Dawidek  *
166ac5fe48SPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
176ac5fe48SPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186ac5fe48SPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
196ac5fe48SPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
206ac5fe48SPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216ac5fe48SPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
226ac5fe48SPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
236ac5fe48SPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
246ac5fe48SPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256ac5fe48SPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266ac5fe48SPawel Jakub Dawidek  * SUCH DAMAGE.
276ac5fe48SPawel Jakub Dawidek  */
286ac5fe48SPawel Jakub Dawidek 
296ac5fe48SPawel Jakub Dawidek #include <stdio.h>
306ac5fe48SPawel Jakub Dawidek #include <stdlib.h>
316ac5fe48SPawel Jakub Dawidek #include <unistd.h>
326ac5fe48SPawel Jakub Dawidek #include <fcntl.h>
336ac5fe48SPawel Jakub Dawidek #include <sys/param.h>
346ac5fe48SPawel Jakub Dawidek #include <sys/disk.h>
356ac5fe48SPawel Jakub Dawidek #include <sys/stat.h>
366ac5fe48SPawel Jakub Dawidek #include <sys/endian.h>
376ac5fe48SPawel Jakub Dawidek #include <sys/socket.h>
386ac5fe48SPawel Jakub Dawidek #include <sys/linker.h>
396ac5fe48SPawel Jakub Dawidek #include <sys/module.h>
406ac5fe48SPawel Jakub Dawidek #include <netinet/in.h>
417be67fe3SPawel Jakub Dawidek #include <netinet/tcp.h>
426ac5fe48SPawel Jakub Dawidek #include <arpa/inet.h>
436ac5fe48SPawel Jakub Dawidek #include <signal.h>
446ac5fe48SPawel Jakub Dawidek #include <err.h>
456ac5fe48SPawel Jakub Dawidek #include <errno.h>
466ac5fe48SPawel Jakub Dawidek #include <string.h>
476ac5fe48SPawel Jakub Dawidek #include <strings.h>
486ac5fe48SPawel Jakub Dawidek #include <libgen.h>
4971ae6999SPawel Jakub Dawidek #include <libutil.h>
506ac5fe48SPawel Jakub Dawidek #include <netdb.h>
516ac5fe48SPawel Jakub Dawidek #include <syslog.h>
526ac5fe48SPawel Jakub Dawidek #include <stdarg.h>
5371ae6999SPawel Jakub Dawidek #include <stdint.h>
546ac5fe48SPawel Jakub Dawidek #include <libgeom.h>
556ac5fe48SPawel Jakub Dawidek 
566ac5fe48SPawel Jakub Dawidek #include <geom/gate/g_gate.h>
576ac5fe48SPawel Jakub Dawidek #include "ggate.h"
586ac5fe48SPawel Jakub Dawidek 
596ac5fe48SPawel Jakub Dawidek 
606ac5fe48SPawel Jakub Dawidek int g_gate_devfd = -1;
616ac5fe48SPawel Jakub Dawidek int g_gate_verbose = 0;
626ac5fe48SPawel Jakub Dawidek 
636ac5fe48SPawel Jakub Dawidek 
646ac5fe48SPawel Jakub Dawidek void
g_gate_vlog(int priority,const char * message,va_list ap)656ac5fe48SPawel Jakub Dawidek g_gate_vlog(int priority, const char *message, va_list ap)
666ac5fe48SPawel Jakub Dawidek {
676ac5fe48SPawel Jakub Dawidek 
686ac5fe48SPawel Jakub Dawidek 	if (g_gate_verbose) {
696ac5fe48SPawel Jakub Dawidek 		const char *prefix;
706ac5fe48SPawel Jakub Dawidek 
716ac5fe48SPawel Jakub Dawidek 		switch (priority) {
726ac5fe48SPawel Jakub Dawidek 		case LOG_ERR:
736ac5fe48SPawel Jakub Dawidek 			prefix = "error";
746ac5fe48SPawel Jakub Dawidek 			break;
756ac5fe48SPawel Jakub Dawidek 		case LOG_WARNING:
766ac5fe48SPawel Jakub Dawidek 			prefix = "warning";
776ac5fe48SPawel Jakub Dawidek 			break;
786ac5fe48SPawel Jakub Dawidek 		case LOG_NOTICE:
796ac5fe48SPawel Jakub Dawidek 			prefix = "notice";
806ac5fe48SPawel Jakub Dawidek 			break;
816ac5fe48SPawel Jakub Dawidek 		case LOG_INFO:
826ac5fe48SPawel Jakub Dawidek 			prefix = "info";
836ac5fe48SPawel Jakub Dawidek 			break;
846ac5fe48SPawel Jakub Dawidek 		case LOG_DEBUG:
856ac5fe48SPawel Jakub Dawidek 			prefix = "debug";
866ac5fe48SPawel Jakub Dawidek 			break;
876ac5fe48SPawel Jakub Dawidek 		default:
886ac5fe48SPawel Jakub Dawidek 			prefix = "unknown";
896ac5fe48SPawel Jakub Dawidek 		}
906ac5fe48SPawel Jakub Dawidek 
916ac5fe48SPawel Jakub Dawidek 		printf("%s: ", prefix);
926ac5fe48SPawel Jakub Dawidek 		vprintf(message, ap);
936ac5fe48SPawel Jakub Dawidek 		printf("\n");
946ac5fe48SPawel Jakub Dawidek 	} else {
956ac5fe48SPawel Jakub Dawidek 		if (priority != LOG_DEBUG)
966ac5fe48SPawel Jakub Dawidek 			vsyslog(priority, message, ap);
976ac5fe48SPawel Jakub Dawidek 	}
986ac5fe48SPawel Jakub Dawidek }
996ac5fe48SPawel Jakub Dawidek 
1006ac5fe48SPawel Jakub Dawidek void
g_gate_log(int priority,const char * message,...)1016ac5fe48SPawel Jakub Dawidek g_gate_log(int priority, const char *message, ...)
1026ac5fe48SPawel Jakub Dawidek {
1036ac5fe48SPawel Jakub Dawidek 	va_list ap;
1046ac5fe48SPawel Jakub Dawidek 
1056ac5fe48SPawel Jakub Dawidek 	va_start(ap, message);
1066ac5fe48SPawel Jakub Dawidek 	g_gate_vlog(priority, message, ap);
1076ac5fe48SPawel Jakub Dawidek 	va_end(ap);
1086ac5fe48SPawel Jakub Dawidek }
1096ac5fe48SPawel Jakub Dawidek 
1106ac5fe48SPawel Jakub Dawidek void
g_gate_xvlog(const char * message,va_list ap)1116ac5fe48SPawel Jakub Dawidek g_gate_xvlog(const char *message, va_list ap)
1126ac5fe48SPawel Jakub Dawidek {
1136ac5fe48SPawel Jakub Dawidek 
1146ac5fe48SPawel Jakub Dawidek 	g_gate_vlog(LOG_ERR, message, ap);
1156ac5fe48SPawel Jakub Dawidek 	g_gate_vlog(LOG_ERR, "Exiting.", ap);
1166ac5fe48SPawel Jakub Dawidek 	exit(EXIT_FAILURE);
1176ac5fe48SPawel Jakub Dawidek }
1186ac5fe48SPawel Jakub Dawidek 
1196ac5fe48SPawel Jakub Dawidek void
g_gate_xlog(const char * message,...)1206ac5fe48SPawel Jakub Dawidek g_gate_xlog(const char *message, ...)
1216ac5fe48SPawel Jakub Dawidek {
1226ac5fe48SPawel Jakub Dawidek 	va_list ap;
1236ac5fe48SPawel Jakub Dawidek 
1246ac5fe48SPawel Jakub Dawidek 	va_start(ap, message);
1256ac5fe48SPawel Jakub Dawidek 	g_gate_xvlog(message, ap);
1266ac5fe48SPawel Jakub Dawidek 	/* NOTREACHED */
1276ac5fe48SPawel Jakub Dawidek 	va_end(ap);
1286ac5fe48SPawel Jakub Dawidek 	exit(EXIT_FAILURE);
1296ac5fe48SPawel Jakub Dawidek }
1306ac5fe48SPawel Jakub Dawidek 
1316ac5fe48SPawel Jakub Dawidek off_t
g_gate_mediasize(int fd)1326ac5fe48SPawel Jakub Dawidek g_gate_mediasize(int fd)
1336ac5fe48SPawel Jakub Dawidek {
1346ac5fe48SPawel Jakub Dawidek 	off_t mediasize;
1356ac5fe48SPawel Jakub Dawidek 	struct stat sb;
1366ac5fe48SPawel Jakub Dawidek 
137122abe03SPawel Jakub Dawidek 	if (fstat(fd, &sb) == -1)
1386ac5fe48SPawel Jakub Dawidek 		g_gate_xlog("fstat(): %s.", strerror(errno));
1396ac5fe48SPawel Jakub Dawidek 	if (S_ISCHR(sb.st_mode)) {
140122abe03SPawel Jakub Dawidek 		if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
1416ac5fe48SPawel Jakub Dawidek 			g_gate_xlog("Can't get media size: %s.",
1426ac5fe48SPawel Jakub Dawidek 			    strerror(errno));
1436ac5fe48SPawel Jakub Dawidek 		}
1446ac5fe48SPawel Jakub Dawidek 	} else if (S_ISREG(sb.st_mode)) {
1456ac5fe48SPawel Jakub Dawidek 		mediasize = sb.st_size;
1466ac5fe48SPawel Jakub Dawidek 	} else {
1476ac5fe48SPawel Jakub Dawidek 		g_gate_xlog("Unsupported file system object.");
1486ac5fe48SPawel Jakub Dawidek 	}
1496ac5fe48SPawel Jakub Dawidek 	return (mediasize);
1506ac5fe48SPawel Jakub Dawidek }
1516ac5fe48SPawel Jakub Dawidek 
15215c7f46bSPawel Jakub Dawidek unsigned
g_gate_sectorsize(int fd)1536ac5fe48SPawel Jakub Dawidek g_gate_sectorsize(int fd)
1546ac5fe48SPawel Jakub Dawidek {
15515c7f46bSPawel Jakub Dawidek 	unsigned secsize;
1566ac5fe48SPawel Jakub Dawidek 	struct stat sb;
1576ac5fe48SPawel Jakub Dawidek 
158122abe03SPawel Jakub Dawidek 	if (fstat(fd, &sb) == -1)
1596ac5fe48SPawel Jakub Dawidek 		g_gate_xlog("fstat(): %s.", strerror(errno));
1606ac5fe48SPawel Jakub Dawidek 	if (S_ISCHR(sb.st_mode)) {
161122abe03SPawel Jakub Dawidek 		if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
1626ac5fe48SPawel Jakub Dawidek 			g_gate_xlog("Can't get sector size: %s.",
1636ac5fe48SPawel Jakub Dawidek 			    strerror(errno));
1646ac5fe48SPawel Jakub Dawidek 		}
1656ac5fe48SPawel Jakub Dawidek 	} else if (S_ISREG(sb.st_mode)) {
1666ac5fe48SPawel Jakub Dawidek 		secsize = 512;
1676ac5fe48SPawel Jakub Dawidek 	} else {
1686ac5fe48SPawel Jakub Dawidek 		g_gate_xlog("Unsupported file system object.");
1696ac5fe48SPawel Jakub Dawidek 	}
1706ac5fe48SPawel Jakub Dawidek 	return (secsize);
1716ac5fe48SPawel Jakub Dawidek }
1726ac5fe48SPawel Jakub Dawidek 
1736ac5fe48SPawel Jakub Dawidek void
g_gate_open_device(void)1746ac5fe48SPawel Jakub Dawidek g_gate_open_device(void)
1756ac5fe48SPawel Jakub Dawidek {
1766ac5fe48SPawel Jakub Dawidek 
177d44dbcbbSPawel Jakub Dawidek 	g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR);
178122abe03SPawel Jakub Dawidek 	if (g_gate_devfd == -1)
1796ac5fe48SPawel Jakub Dawidek 		err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
1806ac5fe48SPawel Jakub Dawidek }
1816ac5fe48SPawel Jakub Dawidek 
1826ac5fe48SPawel Jakub Dawidek void
g_gate_close_device(void)1836ac5fe48SPawel Jakub Dawidek g_gate_close_device(void)
1846ac5fe48SPawel Jakub Dawidek {
1856ac5fe48SPawel Jakub Dawidek 
1866ac5fe48SPawel Jakub Dawidek 	close(g_gate_devfd);
1876ac5fe48SPawel Jakub Dawidek }
1886ac5fe48SPawel Jakub Dawidek 
1896ac5fe48SPawel Jakub Dawidek void
g_gate_ioctl(unsigned long req,void * data)1906ac5fe48SPawel Jakub Dawidek g_gate_ioctl(unsigned long req, void *data)
1916ac5fe48SPawel Jakub Dawidek {
1926ac5fe48SPawel Jakub Dawidek 
193122abe03SPawel Jakub Dawidek 	if (ioctl(g_gate_devfd, req, data) == -1) {
1946ac5fe48SPawel Jakub Dawidek 		g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
1956ac5fe48SPawel Jakub Dawidek 		    G_GATE_CTL_NAME, strerror(errno));
1966ac5fe48SPawel Jakub Dawidek 	}
1976ac5fe48SPawel Jakub Dawidek }
1986ac5fe48SPawel Jakub Dawidek 
1996ac5fe48SPawel Jakub Dawidek void
g_gate_destroy(int unit,int force)2006ac5fe48SPawel Jakub Dawidek g_gate_destroy(int unit, int force)
2016ac5fe48SPawel Jakub Dawidek {
2026ac5fe48SPawel Jakub Dawidek 	struct g_gate_ctl_destroy ggio;
2036ac5fe48SPawel Jakub Dawidek 
2046ac5fe48SPawel Jakub Dawidek 	ggio.gctl_version = G_GATE_VERSION;
2056ac5fe48SPawel Jakub Dawidek 	ggio.gctl_unit = unit;
2066ac5fe48SPawel Jakub Dawidek 	ggio.gctl_force = force;
2076ac5fe48SPawel Jakub Dawidek 	g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
2086ac5fe48SPawel Jakub Dawidek }
2096ac5fe48SPawel Jakub Dawidek 
2106ac5fe48SPawel Jakub Dawidek void
g_gate_load_module(void)2116ac5fe48SPawel Jakub Dawidek g_gate_load_module(void)
2126ac5fe48SPawel Jakub Dawidek {
2136ac5fe48SPawel Jakub Dawidek 
214122abe03SPawel Jakub Dawidek 	if (modfind("g_gate") == -1) {
2156ac5fe48SPawel Jakub Dawidek 		/* Not present in kernel, try loading it. */
216122abe03SPawel Jakub Dawidek 		if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
2176ac5fe48SPawel Jakub Dawidek 			if (errno != EEXIST) {
2186ac5fe48SPawel Jakub Dawidek 				errx(EXIT_FAILURE,
2196ac5fe48SPawel Jakub Dawidek 				    "geom_gate module not available!");
2206ac5fe48SPawel Jakub Dawidek 			}
2216ac5fe48SPawel Jakub Dawidek 		}
2226ac5fe48SPawel Jakub Dawidek 	}
2236ac5fe48SPawel Jakub Dawidek }
2246ac5fe48SPawel Jakub Dawidek 
2252663c885SPawel Jakub Dawidek /*
2262663c885SPawel Jakub Dawidek  * When we send from ggatec packets larger than 32kB, performance drops
2272663c885SPawel Jakub Dawidek  * significantly (eg. to 256kB/s over 1Gbit/s link). This is not a problem
2282663c885SPawel Jakub Dawidek  * when data is send from ggated. I don't know why, so for now I limit
2292663c885SPawel Jakub Dawidek  * size of packets send from ggatec to 32kB by defining MAX_SEND_SIZE
2302663c885SPawel Jakub Dawidek  * in ggatec Makefile.
2312663c885SPawel Jakub Dawidek  */
2322663c885SPawel Jakub Dawidek #ifndef	MAX_SEND_SIZE
2332663c885SPawel Jakub Dawidek #define	MAX_SEND_SIZE	MAXPHYS
2342663c885SPawel Jakub Dawidek #endif
2357be67fe3SPawel Jakub Dawidek ssize_t
g_gate_send(int s,const void * buf,size_t len,int flags)2367be67fe3SPawel Jakub Dawidek g_gate_send(int s, const void *buf, size_t len, int flags)
2377be67fe3SPawel Jakub Dawidek {
2387be67fe3SPawel Jakub Dawidek 	ssize_t done = 0, done2;
2397be67fe3SPawel Jakub Dawidek 	const unsigned char *p = buf;
2407be67fe3SPawel Jakub Dawidek 
2417be67fe3SPawel Jakub Dawidek 	while (len > 0) {
2422663c885SPawel Jakub Dawidek 		done2 = send(s, p, MIN(len, MAX_SEND_SIZE), flags);
2437be67fe3SPawel Jakub Dawidek 		if (done2 == 0)
2447be67fe3SPawel Jakub Dawidek 			break;
2457be67fe3SPawel Jakub Dawidek 		else if (done2 == -1) {
2467be67fe3SPawel Jakub Dawidek 			if (errno == EAGAIN) {
2477be67fe3SPawel Jakub Dawidek 				printf("%s: EAGAIN\n", __func__);
2487be67fe3SPawel Jakub Dawidek 				continue;
2497be67fe3SPawel Jakub Dawidek 			}
2507be67fe3SPawel Jakub Dawidek 			done = -1;
2517be67fe3SPawel Jakub Dawidek 			break;
2527be67fe3SPawel Jakub Dawidek 		}
2537be67fe3SPawel Jakub Dawidek 		done += done2;
2547be67fe3SPawel Jakub Dawidek 		p += done2;
2557be67fe3SPawel Jakub Dawidek 		len -= done2;
2567be67fe3SPawel Jakub Dawidek 	}
2577be67fe3SPawel Jakub Dawidek 	return (done);
2587be67fe3SPawel Jakub Dawidek }
2597be67fe3SPawel Jakub Dawidek 
2607be67fe3SPawel Jakub Dawidek ssize_t
g_gate_recv(int s,void * buf,size_t len,int flags)2617be67fe3SPawel Jakub Dawidek g_gate_recv(int s, void *buf, size_t len, int flags)
2627be67fe3SPawel Jakub Dawidek {
263a930f272SPawel Jakub Dawidek 	ssize_t done;
2647be67fe3SPawel Jakub Dawidek 
265a930f272SPawel Jakub Dawidek 	do {
266a930f272SPawel Jakub Dawidek 		done = recv(s, buf, len, flags);
267a930f272SPawel Jakub Dawidek 	} while (done == -1 && errno == EAGAIN);
268a930f272SPawel Jakub Dawidek 	return (done);
2697be67fe3SPawel Jakub Dawidek }
2707be67fe3SPawel Jakub Dawidek 
2717be67fe3SPawel Jakub Dawidek int nagle = 1;
2727be67fe3SPawel Jakub Dawidek unsigned rcvbuf = G_GATE_RCVBUF;
2737be67fe3SPawel Jakub Dawidek unsigned sndbuf = G_GATE_SNDBUF;
2747be67fe3SPawel Jakub Dawidek 
2757be67fe3SPawel Jakub Dawidek void
g_gate_socket_settings(int sfd)2767be67fe3SPawel Jakub Dawidek g_gate_socket_settings(int sfd)
2777be67fe3SPawel Jakub Dawidek {
2787be67fe3SPawel Jakub Dawidek 	struct timeval tv;
2797be67fe3SPawel Jakub Dawidek 	int bsize, on;
2807be67fe3SPawel Jakub Dawidek 
2817be67fe3SPawel Jakub Dawidek 	/* Socket settings. */
2827be67fe3SPawel Jakub Dawidek 	on = 1;
2837be67fe3SPawel Jakub Dawidek 	if (nagle) {
2847be67fe3SPawel Jakub Dawidek 		if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on,
2857be67fe3SPawel Jakub Dawidek 		    sizeof(on)) == -1) {
2867be67fe3SPawel Jakub Dawidek 			g_gate_xlog("setsockopt() error: %s.", strerror(errno));
2877be67fe3SPawel Jakub Dawidek 		}
2887be67fe3SPawel Jakub Dawidek 	}
2897be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
2907be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
2917be67fe3SPawel Jakub Dawidek 	bsize = rcvbuf;
2927be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
2937be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
2947be67fe3SPawel Jakub Dawidek 	bsize = sndbuf;
2957be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
2967be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
297a930f272SPawel Jakub Dawidek 	tv.tv_sec = 8;
2987be67fe3SPawel Jakub Dawidek 	tv.tv_usec = 0;
2997be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
3007be67fe3SPawel Jakub Dawidek 		g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
3017be67fe3SPawel Jakub Dawidek 		    strerror(errno));
3027be67fe3SPawel Jakub Dawidek 	}
3037be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
3047be67fe3SPawel Jakub Dawidek 		g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
3057be67fe3SPawel Jakub Dawidek 		    strerror(errno));
3067be67fe3SPawel Jakub Dawidek 	}
3077be67fe3SPawel Jakub Dawidek }
3087be67fe3SPawel Jakub Dawidek 
3096ac5fe48SPawel Jakub Dawidek #ifdef LIBGEOM
3106ac5fe48SPawel Jakub Dawidek static struct gclass *
find_class(struct gmesh * mesh,const char * name)3116ac5fe48SPawel Jakub Dawidek find_class(struct gmesh *mesh, const char *name)
3126ac5fe48SPawel Jakub Dawidek {
3136ac5fe48SPawel Jakub Dawidek 	struct gclass *class;
3146ac5fe48SPawel Jakub Dawidek 
3156ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(class, &mesh->lg_class, lg_class) {
3166ac5fe48SPawel Jakub Dawidek 		if (strcmp(class->lg_name, name) == 0)
3176ac5fe48SPawel Jakub Dawidek 			return (class);
3186ac5fe48SPawel Jakub Dawidek 	}
3196ac5fe48SPawel Jakub Dawidek 	return (NULL);
3206ac5fe48SPawel Jakub Dawidek }
3216ac5fe48SPawel Jakub Dawidek 
3226ac5fe48SPawel Jakub Dawidek static const char *
get_conf(struct ggeom * gp,const char * name)3236ac5fe48SPawel Jakub Dawidek get_conf(struct ggeom *gp, const char *name)
3246ac5fe48SPawel Jakub Dawidek {
3256ac5fe48SPawel Jakub Dawidek 	struct gconfig *conf;
3266ac5fe48SPawel Jakub Dawidek 
3276ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(conf, &gp->lg_config, lg_config) {
3286ac5fe48SPawel Jakub Dawidek 		if (strcmp(conf->lg_name, name) == 0)
3296ac5fe48SPawel Jakub Dawidek 			return (conf->lg_val);
3306ac5fe48SPawel Jakub Dawidek 	}
3316ac5fe48SPawel Jakub Dawidek 	return (NULL);
3326ac5fe48SPawel Jakub Dawidek }
3336ac5fe48SPawel Jakub Dawidek 
3346ac5fe48SPawel Jakub Dawidek static void
show_config(struct ggeom * gp,int verbose)3356ac5fe48SPawel Jakub Dawidek show_config(struct ggeom *gp, int verbose)
3366ac5fe48SPawel Jakub Dawidek {
3376ac5fe48SPawel Jakub Dawidek 	struct gprovider *pp;
33871ae6999SPawel Jakub Dawidek 	char buf[5];
3396ac5fe48SPawel Jakub Dawidek 
3406ac5fe48SPawel Jakub Dawidek 	pp = LIST_FIRST(&gp->lg_provider);
3416ac5fe48SPawel Jakub Dawidek 	if (pp == NULL)
3426ac5fe48SPawel Jakub Dawidek 		return;
3436ac5fe48SPawel Jakub Dawidek 	if (!verbose) {
3446ac5fe48SPawel Jakub Dawidek 		printf("%s\n", pp->lg_name);
3456ac5fe48SPawel Jakub Dawidek 		return;
3466ac5fe48SPawel Jakub Dawidek 	}
3476ac5fe48SPawel Jakub Dawidek 	printf("       NAME: %s\n", pp->lg_name);
3486ac5fe48SPawel Jakub Dawidek 	printf("       info: %s\n", get_conf(gp, "info"));
3496ac5fe48SPawel Jakub Dawidek 	printf("     access: %s\n", get_conf(gp, "access"));
3506ac5fe48SPawel Jakub Dawidek 	printf("    timeout: %s\n", get_conf(gp, "timeout"));
3516ac5fe48SPawel Jakub Dawidek 	printf("queue_count: %s\n", get_conf(gp, "queue_count"));
3526ac5fe48SPawel Jakub Dawidek 	printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
3536ac5fe48SPawel Jakub Dawidek 	printf(" references: %s\n", get_conf(gp, "ref"));
35471ae6999SPawel Jakub Dawidek 	humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
35571ae6999SPawel Jakub Dawidek 	    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
35671ae6999SPawel Jakub Dawidek 	printf("  mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
3576ac5fe48SPawel Jakub Dawidek 	printf(" sectorsize: %u\n", pp->lg_sectorsize);
3586ac5fe48SPawel Jakub Dawidek 	printf("       mode: %s\n", pp->lg_mode);
3596ac5fe48SPawel Jakub Dawidek 	printf("\n");
3606ac5fe48SPawel Jakub Dawidek }
3616ac5fe48SPawel Jakub Dawidek 
3626ac5fe48SPawel Jakub Dawidek void
g_gate_list(int unit,int verbose)3636ac5fe48SPawel Jakub Dawidek g_gate_list(int unit, int verbose)
3646ac5fe48SPawel Jakub Dawidek {
3656ac5fe48SPawel Jakub Dawidek 	struct gmesh mesh;
3666ac5fe48SPawel Jakub Dawidek 	struct gclass *class;
3676ac5fe48SPawel Jakub Dawidek 	struct ggeom *gp;
3686ac5fe48SPawel Jakub Dawidek 	char name[64];
3696ac5fe48SPawel Jakub Dawidek 	int error;
3706ac5fe48SPawel Jakub Dawidek 
3716ac5fe48SPawel Jakub Dawidek 	error = geom_gettree(&mesh);
3726ac5fe48SPawel Jakub Dawidek 	if (error != 0)
3736ac5fe48SPawel Jakub Dawidek 		exit(EXIT_FAILURE);
3746ac5fe48SPawel Jakub Dawidek 	class = find_class(&mesh, G_GATE_CLASS_NAME);
3756ac5fe48SPawel Jakub Dawidek 	if (class == NULL) {
3766ac5fe48SPawel Jakub Dawidek 		geom_deletetree(&mesh);
3776ac5fe48SPawel Jakub Dawidek 		exit(EXIT_SUCCESS);
3786ac5fe48SPawel Jakub Dawidek 	}
3796ac5fe48SPawel Jakub Dawidek 	if (unit >= 0) {
3806ac5fe48SPawel Jakub Dawidek 		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
3816ac5fe48SPawel Jakub Dawidek 		    unit);
3826ac5fe48SPawel Jakub Dawidek 	}
3836ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
3846ac5fe48SPawel Jakub Dawidek 		if (unit != -1 && strcmp(gp->lg_name, name) != 0)
3856ac5fe48SPawel Jakub Dawidek 			continue;
3866ac5fe48SPawel Jakub Dawidek 		show_config(gp, verbose);
3876ac5fe48SPawel Jakub Dawidek 	}
3886ac5fe48SPawel Jakub Dawidek 	geom_deletetree(&mesh);
3896ac5fe48SPawel Jakub Dawidek 	exit(EXIT_SUCCESS);
3906ac5fe48SPawel Jakub Dawidek }
3916ac5fe48SPawel Jakub Dawidek #endif	/* LIBGEOM */
3926ac5fe48SPawel Jakub Dawidek 
3936ac5fe48SPawel Jakub Dawidek in_addr_t
g_gate_str2ip(const char * str)3946ac5fe48SPawel Jakub Dawidek g_gate_str2ip(const char *str)
3956ac5fe48SPawel Jakub Dawidek {
3966ac5fe48SPawel Jakub Dawidek 	struct hostent *hp;
3976ac5fe48SPawel Jakub Dawidek 	in_addr_t ip;
3986ac5fe48SPawel Jakub Dawidek 
3996ac5fe48SPawel Jakub Dawidek 	ip = inet_addr(str);
4006ac5fe48SPawel Jakub Dawidek 	if (ip != INADDR_NONE) {
4016ac5fe48SPawel Jakub Dawidek 		/* It is a valid IP address. */
4026ac5fe48SPawel Jakub Dawidek 		return (ip);
4036ac5fe48SPawel Jakub Dawidek 	}
4046ac5fe48SPawel Jakub Dawidek 	/* Check if it is a valid host name. */
4056ac5fe48SPawel Jakub Dawidek 	hp = gethostbyname(str);
4066ac5fe48SPawel Jakub Dawidek 	if (hp == NULL)
4076ac5fe48SPawel Jakub Dawidek 		return (INADDR_NONE);
40886bfa454SPawel Jakub Dawidek 	return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
4096ac5fe48SPawel Jakub Dawidek }
410