ggate.c revision 134937
1128763Spjd/*-
2128763Spjd * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3128763Spjd * All rights reserved.
4128763Spjd *
5128763Spjd * Redistribution and use in source and binary forms, with or without
6128763Spjd * modification, are permitted provided that the following conditions
7128763Spjd * are met:
8128763Spjd * 1. Redistributions of source code must retain the above copyright
9128763Spjd *    notice, this list of conditions and the following disclaimer.
10128763Spjd * 2. Redistributions in binary form must reproduce the above copyright
11128763Spjd *    notice, this list of conditions and the following disclaimer in the
12128763Spjd *    documentation and/or other materials provided with the distribution.
13128763Spjd *
14128763Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15128763Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16128763Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17128763Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18128763Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19128763Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20128763Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21128763Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22128763Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23128763Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24128763Spjd * SUCH DAMAGE.
25128763Spjd *
26128763Spjd * $FreeBSD: head/sbin/ggate/shared/ggate.c 134937 2004-09-08 07:57:14Z pjd $
27128763Spjd */
28128763Spjd
29128763Spjd#include <stdio.h>
30128763Spjd#include <stdlib.h>
31128763Spjd#include <unistd.h>
32128763Spjd#include <fcntl.h>
33128763Spjd#include <sys/param.h>
34128763Spjd#include <sys/disk.h>
35128763Spjd#include <sys/stat.h>
36128763Spjd#include <sys/endian.h>
37128763Spjd#include <sys/socket.h>
38128763Spjd#include <sys/linker.h>
39128763Spjd#include <sys/module.h>
40128763Spjd#include <netinet/in.h>
41128763Spjd#include <arpa/inet.h>
42128763Spjd#include <signal.h>
43128763Spjd#include <err.h>
44128763Spjd#include <errno.h>
45128763Spjd#include <string.h>
46128763Spjd#include <strings.h>
47128763Spjd#include <libgen.h>
48130837Spjd#include <libutil.h>
49128763Spjd#include <netdb.h>
50128763Spjd#include <syslog.h>
51128763Spjd#include <stdarg.h>
52130837Spjd#include <stdint.h>
53128763Spjd#include <libgeom.h>
54128763Spjd
55128763Spjd#include <geom/gate/g_gate.h>
56128763Spjd#include "ggate.h"
57128763Spjd
58128763Spjd
59128763Spjdint g_gate_devfd = -1;
60128763Spjdint g_gate_verbose = 0;
61128763Spjd
62128763Spjd
63128763Spjdvoid
64128763Spjdg_gate_vlog(int priority, const char *message, va_list ap)
65128763Spjd{
66128763Spjd
67128763Spjd	if (g_gate_verbose) {
68128763Spjd		const char *prefix;
69128763Spjd
70128763Spjd		switch (priority) {
71128763Spjd		case LOG_ERR:
72128763Spjd			prefix = "error";
73128763Spjd			break;
74128763Spjd		case LOG_WARNING:
75128763Spjd			prefix = "warning";
76128763Spjd			break;
77128763Spjd		case LOG_NOTICE:
78128763Spjd			prefix = "notice";
79128763Spjd			break;
80128763Spjd		case LOG_INFO:
81128763Spjd			prefix = "info";
82128763Spjd			break;
83128763Spjd		case LOG_DEBUG:
84128763Spjd			prefix = "debug";
85128763Spjd			break;
86128763Spjd		default:
87128763Spjd			prefix = "unknown";
88128763Spjd		}
89128763Spjd
90128763Spjd		printf("%s: ", prefix);
91128763Spjd		vprintf(message, ap);
92128763Spjd		printf("\n");
93128763Spjd	} else {
94128763Spjd		if (priority != LOG_DEBUG)
95128763Spjd			vsyslog(priority, message, ap);
96128763Spjd	}
97128763Spjd}
98128763Spjd
99128763Spjdvoid
100128763Spjdg_gate_log(int priority, const char *message, ...)
101128763Spjd{
102128763Spjd	va_list ap;
103128763Spjd
104128763Spjd	va_start(ap, message);
105128763Spjd	g_gate_vlog(priority, message, ap);
106128763Spjd	va_end(ap);
107128763Spjd}
108128763Spjd
109128763Spjdvoid
110128763Spjdg_gate_xvlog(const char *message, va_list ap)
111128763Spjd{
112128763Spjd
113128763Spjd	g_gate_vlog(LOG_ERR, message, ap);
114128763Spjd	g_gate_vlog(LOG_ERR, "Exiting.", ap);
115128763Spjd	exit(EXIT_FAILURE);
116128763Spjd}
117128763Spjd
118128763Spjdvoid
119128763Spjdg_gate_xlog(const char *message, ...)
120128763Spjd{
121128763Spjd	va_list ap;
122128763Spjd
123128763Spjd	va_start(ap, message);
124128763Spjd	g_gate_xvlog(message, ap);
125128763Spjd	/* NOTREACHED */
126128763Spjd	va_end(ap);
127128763Spjd	exit(EXIT_FAILURE);
128128763Spjd}
129128763Spjd
130128763Spjdoff_t
131128763Spjdg_gate_mediasize(int fd)
132128763Spjd{
133128763Spjd	off_t mediasize;
134128763Spjd	struct stat sb;
135128763Spjd
136134937Spjd	if (fstat(fd, &sb) == -1)
137128763Spjd		g_gate_xlog("fstat(): %s.", strerror(errno));
138128763Spjd	if (S_ISCHR(sb.st_mode)) {
139134937Spjd		if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
140128763Spjd			g_gate_xlog("Can't get media size: %s.",
141128763Spjd			    strerror(errno));
142128763Spjd		}
143128763Spjd	} else if (S_ISREG(sb.st_mode)) {
144128763Spjd		mediasize = sb.st_size;
145128763Spjd	} else {
146128763Spjd		g_gate_xlog("Unsupported file system object.");
147128763Spjd	}
148128763Spjd	return (mediasize);
149128763Spjd}
150128763Spjd
151128763Spjdsize_t
152128763Spjdg_gate_sectorsize(int fd)
153128763Spjd{
154128763Spjd	size_t secsize;
155128763Spjd	struct stat sb;
156128763Spjd
157134937Spjd	if (fstat(fd, &sb) == -1)
158128763Spjd		g_gate_xlog("fstat(): %s.", strerror(errno));
159128763Spjd	if (S_ISCHR(sb.st_mode)) {
160134937Spjd		if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
161128763Spjd                        g_gate_xlog("Can't get sector size: %s.",
162128763Spjd			    strerror(errno));
163128763Spjd		}
164128763Spjd	} else if (S_ISREG(sb.st_mode)) {
165128763Spjd		secsize = 512;
166128763Spjd	} else {
167128763Spjd		g_gate_xlog("Unsupported file system object.");
168128763Spjd	}
169128763Spjd	return (secsize);
170128763Spjd}
171128763Spjd
172128763Spjdvoid
173128763Spjdg_gate_open_device(void)
174128763Spjd{
175128763Spjd
176128763Spjd	g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
177134937Spjd	if (g_gate_devfd == -1)
178128763Spjd		err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
179128763Spjd}
180128763Spjd
181128763Spjdvoid
182128763Spjdg_gate_close_device(void)
183128763Spjd{
184128763Spjd
185128763Spjd	close(g_gate_devfd);
186128763Spjd}
187128763Spjd
188128763Spjdvoid
189128763Spjdg_gate_ioctl(unsigned long req, void *data)
190128763Spjd{
191128763Spjd
192134937Spjd	if (ioctl(g_gate_devfd, req, data) == -1) {
193128763Spjd		g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
194128763Spjd		    G_GATE_CTL_NAME, strerror(errno));
195128763Spjd	}
196128763Spjd}
197128763Spjd
198128763Spjdvoid
199128763Spjdg_gate_destroy(int unit, int force)
200128763Spjd{
201128763Spjd	struct g_gate_ctl_destroy ggio;
202128763Spjd
203128763Spjd	ggio.gctl_version = G_GATE_VERSION;
204128763Spjd	ggio.gctl_unit = unit;
205128763Spjd	ggio.gctl_force = force;
206128763Spjd	g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
207128763Spjd}
208128763Spjd
209128763Spjdint
210128763Spjdg_gate_openflags(unsigned ggflags)
211128763Spjd{
212128763Spjd
213128763Spjd	if ((ggflags & G_GATE_FLAG_READONLY) != 0)
214128763Spjd		return (O_RDONLY);
215128763Spjd	else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0)
216128763Spjd		return (O_WRONLY);
217128763Spjd	return (O_RDWR);
218128763Spjd}
219128763Spjd
220128763Spjdvoid
221128763Spjdg_gate_load_module(void)
222128763Spjd{
223128763Spjd
224134937Spjd	if (modfind("g_gate") == -1) {
225128763Spjd		/* Not present in kernel, try loading it. */
226134937Spjd		if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
227128763Spjd			if (errno != EEXIST) {
228128763Spjd				errx(EXIT_FAILURE,
229128763Spjd				    "geom_gate module not available!");
230128763Spjd			}
231128763Spjd		}
232128763Spjd	}
233128763Spjd}
234128763Spjd
235128763Spjd#ifdef LIBGEOM
236128763Spjdstatic struct gclass *
237128763Spjdfind_class(struct gmesh *mesh, const char *name)
238128763Spjd{
239128763Spjd	struct gclass *class;
240128763Spjd
241128763Spjd	LIST_FOREACH(class, &mesh->lg_class, lg_class) {
242128763Spjd		if (strcmp(class->lg_name, name) == 0)
243128763Spjd			return (class);
244128763Spjd	}
245128763Spjd	return (NULL);
246128763Spjd}
247128763Spjd
248128763Spjdstatic const char *
249128763Spjdget_conf(struct ggeom *gp, const char *name)
250128763Spjd{
251128763Spjd	struct gconfig *conf;
252128763Spjd
253128763Spjd	LIST_FOREACH(conf, &gp->lg_config, lg_config) {
254128763Spjd		if (strcmp(conf->lg_name, name) == 0)
255128763Spjd			return (conf->lg_val);
256128763Spjd	}
257128763Spjd	return (NULL);
258128763Spjd}
259128763Spjd
260128763Spjdstatic void
261128763Spjdshow_config(struct ggeom *gp, int verbose)
262128763Spjd{
263128763Spjd	struct gprovider *pp;
264130837Spjd	char buf[5];
265128763Spjd
266128763Spjd	pp = LIST_FIRST(&gp->lg_provider);
267128763Spjd	if (pp == NULL)
268128763Spjd		return;
269128763Spjd	if (!verbose) {
270128763Spjd		printf("%s\n", pp->lg_name);
271128763Spjd		return;
272128763Spjd	}
273128763Spjd	printf("       NAME: %s\n", pp->lg_name);
274128763Spjd	printf("       info: %s\n", get_conf(gp, "info"));
275128763Spjd	printf("     access: %s\n", get_conf(gp, "access"));
276128763Spjd	printf("    timeout: %s\n", get_conf(gp, "timeout"));
277128763Spjd	printf("queue_count: %s\n", get_conf(gp, "queue_count"));
278128763Spjd	printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
279128763Spjd	printf(" references: %s\n", get_conf(gp, "ref"));
280130837Spjd	humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
281130837Spjd	    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
282130837Spjd	printf("  mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
283128763Spjd	printf(" sectorsize: %u\n", pp->lg_sectorsize);
284128763Spjd	printf("       mode: %s\n", pp->lg_mode);
285128763Spjd	printf("\n");
286128763Spjd}
287128763Spjd
288128763Spjdvoid
289128763Spjdg_gate_list(int unit, int verbose)
290128763Spjd{
291128763Spjd	struct gmesh mesh;
292128763Spjd	struct gclass *class;
293128763Spjd	struct ggeom *gp;
294128763Spjd	char name[64];
295128763Spjd	int error;
296128763Spjd
297128763Spjd	error = geom_gettree(&mesh);
298128763Spjd	if (error != 0)
299128763Spjd		exit(EXIT_FAILURE);
300128763Spjd	class = find_class(&mesh, G_GATE_CLASS_NAME);
301128763Spjd	if (class == NULL) {
302128763Spjd		geom_deletetree(&mesh);
303128763Spjd		exit(EXIT_SUCCESS);
304128763Spjd	}
305128763Spjd	if (unit >= 0) {
306128763Spjd		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
307128763Spjd		    unit);
308128763Spjd	}
309128763Spjd	LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
310128763Spjd		if (unit != -1 && strcmp(gp->lg_name, name) != 0)
311128763Spjd			continue;
312128763Spjd		show_config(gp, verbose);
313128763Spjd	}
314128763Spjd	geom_deletetree(&mesh);
315128763Spjd	exit(EXIT_SUCCESS);
316128763Spjd}
317128763Spjd#endif	/* LIBGEOM */
318128763Spjd
319128763Spjdin_addr_t
320128763Spjdg_gate_str2ip(const char *str)
321128763Spjd{
322128763Spjd	struct hostent *hp;
323128763Spjd	in_addr_t ip;
324128763Spjd
325128763Spjd	ip = inet_addr(str);
326128763Spjd	if (ip != INADDR_NONE) {
327128763Spjd		/* It is a valid IP address. */
328128763Spjd		return (ip);
329128763Spjd	}
330128763Spjd	/* Check if it is a valid host name. */
331128763Spjd	hp = gethostbyname(str);
332128763Spjd	if (hp == NULL)
333128763Spjd		return (INADDR_NONE);
334128836Spjd	return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
335128763Spjd}
336