xref: /freebsd/sbin/ggate/shared/ggate.c (revision 15c7f46bcf28b55f91da496e1cdd0cc7f7b9e0f6)
16ac5fe48SPawel Jakub Dawidek /*-
26ac5fe48SPawel Jakub Dawidek  * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
36ac5fe48SPawel Jakub Dawidek  * All rights reserved.
46ac5fe48SPawel Jakub Dawidek  *
56ac5fe48SPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
66ac5fe48SPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
76ac5fe48SPawel Jakub Dawidek  * are met:
86ac5fe48SPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
96ac5fe48SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
106ac5fe48SPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
116ac5fe48SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
126ac5fe48SPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
136ac5fe48SPawel Jakub Dawidek  *
146ac5fe48SPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
156ac5fe48SPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166ac5fe48SPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176ac5fe48SPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
186ac5fe48SPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196ac5fe48SPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206ac5fe48SPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216ac5fe48SPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226ac5fe48SPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236ac5fe48SPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246ac5fe48SPawel Jakub Dawidek  * SUCH DAMAGE.
256ac5fe48SPawel Jakub Dawidek  *
266ac5fe48SPawel Jakub Dawidek  * $FreeBSD$
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
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
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
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
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
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
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
1746ac5fe48SPawel Jakub Dawidek g_gate_open_device(void)
1756ac5fe48SPawel Jakub Dawidek {
1766ac5fe48SPawel Jakub Dawidek 
1776ac5fe48SPawel Jakub Dawidek 	g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
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
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
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
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
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 
2257be67fe3SPawel Jakub Dawidek ssize_t
2267be67fe3SPawel Jakub Dawidek g_gate_send(int s, const void *buf, size_t len, int flags)
2277be67fe3SPawel Jakub Dawidek {
2287be67fe3SPawel Jakub Dawidek 	ssize_t done = 0, done2;
2297be67fe3SPawel Jakub Dawidek 	const unsigned char *p = buf;
2307be67fe3SPawel Jakub Dawidek 
2317be67fe3SPawel Jakub Dawidek 	while (len > 0) {
2327be67fe3SPawel Jakub Dawidek 		done2 = send(s, p, len, flags);
2337be67fe3SPawel Jakub Dawidek 		if (done2 == 0)
2347be67fe3SPawel Jakub Dawidek 			break;
2357be67fe3SPawel Jakub Dawidek 		else if (done2 == -1) {
2367be67fe3SPawel Jakub Dawidek 			if (errno == EAGAIN) {
2377be67fe3SPawel Jakub Dawidek 				printf("%s: EAGAIN\n", __func__);
2387be67fe3SPawel Jakub Dawidek 				continue;
2397be67fe3SPawel Jakub Dawidek 			}
2407be67fe3SPawel Jakub Dawidek 			done = -1;
2417be67fe3SPawel Jakub Dawidek 			break;
2427be67fe3SPawel Jakub Dawidek 		}
2437be67fe3SPawel Jakub Dawidek 		done += done2;
2447be67fe3SPawel Jakub Dawidek 		p += done2;
2457be67fe3SPawel Jakub Dawidek 		len -= done2;
2467be67fe3SPawel Jakub Dawidek 	}
2477be67fe3SPawel Jakub Dawidek 	return (done);
2487be67fe3SPawel Jakub Dawidek }
2497be67fe3SPawel Jakub Dawidek 
2507be67fe3SPawel Jakub Dawidek ssize_t
2517be67fe3SPawel Jakub Dawidek g_gate_recv(int s, void *buf, size_t len, int flags)
2527be67fe3SPawel Jakub Dawidek {
253a930f272SPawel Jakub Dawidek 	ssize_t done;
2547be67fe3SPawel Jakub Dawidek 
255a930f272SPawel Jakub Dawidek 	do {
256a930f272SPawel Jakub Dawidek 		done = recv(s, buf, len, flags);
257a930f272SPawel Jakub Dawidek 	} while (done == -1 && errno == EAGAIN);
258a930f272SPawel Jakub Dawidek 	return (done);
2597be67fe3SPawel Jakub Dawidek }
2607be67fe3SPawel Jakub Dawidek 
2617be67fe3SPawel Jakub Dawidek int nagle = 1;
2627be67fe3SPawel Jakub Dawidek unsigned rcvbuf = G_GATE_RCVBUF;
2637be67fe3SPawel Jakub Dawidek unsigned sndbuf = G_GATE_SNDBUF;
2647be67fe3SPawel Jakub Dawidek 
2657be67fe3SPawel Jakub Dawidek void
2667be67fe3SPawel Jakub Dawidek g_gate_socket_settings(int sfd)
2677be67fe3SPawel Jakub Dawidek {
2687be67fe3SPawel Jakub Dawidek 	struct timeval tv;
2697be67fe3SPawel Jakub Dawidek 	int bsize, on;
2707be67fe3SPawel Jakub Dawidek 
2717be67fe3SPawel Jakub Dawidek 	/* Socket settings. */
2727be67fe3SPawel Jakub Dawidek 	on = 1;
2737be67fe3SPawel Jakub Dawidek 	if (nagle) {
2747be67fe3SPawel Jakub Dawidek 		if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on,
2757be67fe3SPawel Jakub Dawidek 		    sizeof(on)) == -1) {
2767be67fe3SPawel Jakub Dawidek 			g_gate_xlog("setsockopt() error: %s.", strerror(errno));
2777be67fe3SPawel Jakub Dawidek 		}
2787be67fe3SPawel Jakub Dawidek 	}
2797be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
2807be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
2817be67fe3SPawel Jakub Dawidek 	bsize = rcvbuf;
2827be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
2837be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
2847be67fe3SPawel Jakub Dawidek 	bsize = sndbuf;
2857be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
2867be67fe3SPawel Jakub Dawidek 		g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
287a930f272SPawel Jakub Dawidek 	tv.tv_sec = 8;
2887be67fe3SPawel Jakub Dawidek 	tv.tv_usec = 0;
2897be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
2907be67fe3SPawel Jakub Dawidek 		g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
2917be67fe3SPawel Jakub Dawidek 		    strerror(errno));
2927be67fe3SPawel Jakub Dawidek 	}
2937be67fe3SPawel Jakub Dawidek 	if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
2947be67fe3SPawel Jakub Dawidek 		g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
2957be67fe3SPawel Jakub Dawidek 		    strerror(errno));
2967be67fe3SPawel Jakub Dawidek 	}
2977be67fe3SPawel Jakub Dawidek }
2987be67fe3SPawel Jakub Dawidek 
2996ac5fe48SPawel Jakub Dawidek #ifdef LIBGEOM
3006ac5fe48SPawel Jakub Dawidek static struct gclass *
3016ac5fe48SPawel Jakub Dawidek find_class(struct gmesh *mesh, const char *name)
3026ac5fe48SPawel Jakub Dawidek {
3036ac5fe48SPawel Jakub Dawidek 	struct gclass *class;
3046ac5fe48SPawel Jakub Dawidek 
3056ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(class, &mesh->lg_class, lg_class) {
3066ac5fe48SPawel Jakub Dawidek 		if (strcmp(class->lg_name, name) == 0)
3076ac5fe48SPawel Jakub Dawidek 			return (class);
3086ac5fe48SPawel Jakub Dawidek 	}
3096ac5fe48SPawel Jakub Dawidek 	return (NULL);
3106ac5fe48SPawel Jakub Dawidek }
3116ac5fe48SPawel Jakub Dawidek 
3126ac5fe48SPawel Jakub Dawidek static const char *
3136ac5fe48SPawel Jakub Dawidek get_conf(struct ggeom *gp, const char *name)
3146ac5fe48SPawel Jakub Dawidek {
3156ac5fe48SPawel Jakub Dawidek 	struct gconfig *conf;
3166ac5fe48SPawel Jakub Dawidek 
3176ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(conf, &gp->lg_config, lg_config) {
3186ac5fe48SPawel Jakub Dawidek 		if (strcmp(conf->lg_name, name) == 0)
3196ac5fe48SPawel Jakub Dawidek 			return (conf->lg_val);
3206ac5fe48SPawel Jakub Dawidek 	}
3216ac5fe48SPawel Jakub Dawidek 	return (NULL);
3226ac5fe48SPawel Jakub Dawidek }
3236ac5fe48SPawel Jakub Dawidek 
3246ac5fe48SPawel Jakub Dawidek static void
3256ac5fe48SPawel Jakub Dawidek show_config(struct ggeom *gp, int verbose)
3266ac5fe48SPawel Jakub Dawidek {
3276ac5fe48SPawel Jakub Dawidek 	struct gprovider *pp;
32871ae6999SPawel Jakub Dawidek 	char buf[5];
3296ac5fe48SPawel Jakub Dawidek 
3306ac5fe48SPawel Jakub Dawidek 	pp = LIST_FIRST(&gp->lg_provider);
3316ac5fe48SPawel Jakub Dawidek 	if (pp == NULL)
3326ac5fe48SPawel Jakub Dawidek 		return;
3336ac5fe48SPawel Jakub Dawidek 	if (!verbose) {
3346ac5fe48SPawel Jakub Dawidek 		printf("%s\n", pp->lg_name);
3356ac5fe48SPawel Jakub Dawidek 		return;
3366ac5fe48SPawel Jakub Dawidek 	}
3376ac5fe48SPawel Jakub Dawidek 	printf("       NAME: %s\n", pp->lg_name);
3386ac5fe48SPawel Jakub Dawidek 	printf("       info: %s\n", get_conf(gp, "info"));
3396ac5fe48SPawel Jakub Dawidek 	printf("     access: %s\n", get_conf(gp, "access"));
3406ac5fe48SPawel Jakub Dawidek 	printf("    timeout: %s\n", get_conf(gp, "timeout"));
3416ac5fe48SPawel Jakub Dawidek 	printf("queue_count: %s\n", get_conf(gp, "queue_count"));
3426ac5fe48SPawel Jakub Dawidek 	printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
3436ac5fe48SPawel Jakub Dawidek 	printf(" references: %s\n", get_conf(gp, "ref"));
34471ae6999SPawel Jakub Dawidek 	humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
34571ae6999SPawel Jakub Dawidek 	    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
34671ae6999SPawel Jakub Dawidek 	printf("  mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
3476ac5fe48SPawel Jakub Dawidek 	printf(" sectorsize: %u\n", pp->lg_sectorsize);
3486ac5fe48SPawel Jakub Dawidek 	printf("       mode: %s\n", pp->lg_mode);
3496ac5fe48SPawel Jakub Dawidek 	printf("\n");
3506ac5fe48SPawel Jakub Dawidek }
3516ac5fe48SPawel Jakub Dawidek 
3526ac5fe48SPawel Jakub Dawidek void
3536ac5fe48SPawel Jakub Dawidek g_gate_list(int unit, int verbose)
3546ac5fe48SPawel Jakub Dawidek {
3556ac5fe48SPawel Jakub Dawidek 	struct gmesh mesh;
3566ac5fe48SPawel Jakub Dawidek 	struct gclass *class;
3576ac5fe48SPawel Jakub Dawidek 	struct ggeom *gp;
3586ac5fe48SPawel Jakub Dawidek 	char name[64];
3596ac5fe48SPawel Jakub Dawidek 	int error;
3606ac5fe48SPawel Jakub Dawidek 
3616ac5fe48SPawel Jakub Dawidek 	error = geom_gettree(&mesh);
3626ac5fe48SPawel Jakub Dawidek 	if (error != 0)
3636ac5fe48SPawel Jakub Dawidek 		exit(EXIT_FAILURE);
3646ac5fe48SPawel Jakub Dawidek 	class = find_class(&mesh, G_GATE_CLASS_NAME);
3656ac5fe48SPawel Jakub Dawidek 	if (class == NULL) {
3666ac5fe48SPawel Jakub Dawidek 		geom_deletetree(&mesh);
3676ac5fe48SPawel Jakub Dawidek 		exit(EXIT_SUCCESS);
3686ac5fe48SPawel Jakub Dawidek 	}
3696ac5fe48SPawel Jakub Dawidek 	if (unit >= 0) {
3706ac5fe48SPawel Jakub Dawidek 		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
3716ac5fe48SPawel Jakub Dawidek 		    unit);
3726ac5fe48SPawel Jakub Dawidek 	}
3736ac5fe48SPawel Jakub Dawidek 	LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
3746ac5fe48SPawel Jakub Dawidek 		if (unit != -1 && strcmp(gp->lg_name, name) != 0)
3756ac5fe48SPawel Jakub Dawidek 			continue;
3766ac5fe48SPawel Jakub Dawidek 		show_config(gp, verbose);
3776ac5fe48SPawel Jakub Dawidek 	}
3786ac5fe48SPawel Jakub Dawidek 	geom_deletetree(&mesh);
3796ac5fe48SPawel Jakub Dawidek 	exit(EXIT_SUCCESS);
3806ac5fe48SPawel Jakub Dawidek }
3816ac5fe48SPawel Jakub Dawidek #endif	/* LIBGEOM */
3826ac5fe48SPawel Jakub Dawidek 
3836ac5fe48SPawel Jakub Dawidek in_addr_t
3846ac5fe48SPawel Jakub Dawidek g_gate_str2ip(const char *str)
3856ac5fe48SPawel Jakub Dawidek {
3866ac5fe48SPawel Jakub Dawidek 	struct hostent *hp;
3876ac5fe48SPawel Jakub Dawidek 	in_addr_t ip;
3886ac5fe48SPawel Jakub Dawidek 
3896ac5fe48SPawel Jakub Dawidek 	ip = inet_addr(str);
3906ac5fe48SPawel Jakub Dawidek 	if (ip != INADDR_NONE) {
3916ac5fe48SPawel Jakub Dawidek 		/* It is a valid IP address. */
3926ac5fe48SPawel Jakub Dawidek 		return (ip);
3936ac5fe48SPawel Jakub Dawidek 	}
3946ac5fe48SPawel Jakub Dawidek 	/* Check if it is a valid host name. */
3956ac5fe48SPawel Jakub Dawidek 	hp = gethostbyname(str);
3966ac5fe48SPawel Jakub Dawidek 	if (hp == NULL)
3976ac5fe48SPawel Jakub Dawidek 		return (INADDR_NONE);
39886bfa454SPawel Jakub Dawidek 	return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
3996ac5fe48SPawel Jakub Dawidek }
400