xref: /freebsd/sbin/ggate/shared/ggate.c (revision 6fd05b64b5b65dd4ba9b86482a0634a5f0b96c29)
1 /*-
2  * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/param.h>
34 #include <sys/disk.h>
35 #include <sys/stat.h>
36 #include <sys/endian.h>
37 #include <sys/socket.h>
38 #include <sys/linker.h>
39 #include <sys/module.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <signal.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <libgen.h>
48 #include <libutil.h>
49 #include <netdb.h>
50 #include <syslog.h>
51 #include <stdarg.h>
52 #include <stdint.h>
53 #include <libgeom.h>
54 
55 #include <geom/gate/g_gate.h>
56 #include "ggate.h"
57 
58 
59 int g_gate_devfd = -1;
60 int g_gate_verbose = 0;
61 
62 
63 void
64 g_gate_vlog(int priority, const char *message, va_list ap)
65 {
66 
67 	if (g_gate_verbose) {
68 		const char *prefix;
69 
70 		switch (priority) {
71 		case LOG_ERR:
72 			prefix = "error";
73 			break;
74 		case LOG_WARNING:
75 			prefix = "warning";
76 			break;
77 		case LOG_NOTICE:
78 			prefix = "notice";
79 			break;
80 		case LOG_INFO:
81 			prefix = "info";
82 			break;
83 		case LOG_DEBUG:
84 			prefix = "debug";
85 			break;
86 		default:
87 			prefix = "unknown";
88 		}
89 
90 		printf("%s: ", prefix);
91 		vprintf(message, ap);
92 		printf("\n");
93 	} else {
94 		if (priority != LOG_DEBUG)
95 			vsyslog(priority, message, ap);
96 	}
97 }
98 
99 void
100 g_gate_log(int priority, const char *message, ...)
101 {
102 	va_list ap;
103 
104 	va_start(ap, message);
105 	g_gate_vlog(priority, message, ap);
106 	va_end(ap);
107 }
108 
109 void
110 g_gate_xvlog(const char *message, va_list ap)
111 {
112 
113 	g_gate_vlog(LOG_ERR, message, ap);
114 	g_gate_vlog(LOG_ERR, "Exiting.", ap);
115 	exit(EXIT_FAILURE);
116 }
117 
118 void
119 g_gate_xlog(const char *message, ...)
120 {
121 	va_list ap;
122 
123 	va_start(ap, message);
124 	g_gate_xvlog(message, ap);
125 	/* NOTREACHED */
126 	va_end(ap);
127 	exit(EXIT_FAILURE);
128 }
129 
130 off_t
131 g_gate_mediasize(int fd)
132 {
133 	off_t mediasize;
134 	struct stat sb;
135 
136 	if (fstat(fd, &sb) < 0)
137 		g_gate_xlog("fstat(): %s.", strerror(errno));
138 	if (S_ISCHR(sb.st_mode)) {
139 		if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) {
140 			g_gate_xlog("Can't get media size: %s.",
141 			    strerror(errno));
142 		}
143 	} else if (S_ISREG(sb.st_mode)) {
144 		mediasize = sb.st_size;
145 	} else {
146 		g_gate_xlog("Unsupported file system object.");
147 	}
148 	return (mediasize);
149 }
150 
151 size_t
152 g_gate_sectorsize(int fd)
153 {
154 	size_t secsize;
155 	struct stat sb;
156 
157 	if (fstat(fd, &sb) < 0)
158 		g_gate_xlog("fstat(): %s.", strerror(errno));
159 	if (S_ISCHR(sb.st_mode)) {
160 		if (ioctl(fd, DIOCGSECTORSIZE, &secsize) < 0) {
161                         g_gate_xlog("Can't get sector size: %s.",
162 			    strerror(errno));
163 		}
164 	} else if (S_ISREG(sb.st_mode)) {
165 		secsize = 512;
166 	} else {
167 		g_gate_xlog("Unsupported file system object.");
168 	}
169 	return (secsize);
170 }
171 
172 void
173 g_gate_open_device(void)
174 {
175 
176 	g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
177 	if (g_gate_devfd < 0)
178 		err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
179 }
180 
181 void
182 g_gate_close_device(void)
183 {
184 
185 	close(g_gate_devfd);
186 }
187 
188 void
189 g_gate_ioctl(unsigned long req, void *data)
190 {
191 
192 	if (ioctl(g_gate_devfd, req, data) < 0) {
193 		g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
194 		    G_GATE_CTL_NAME, strerror(errno));
195 	}
196 }
197 
198 void
199 g_gate_destroy(int unit, int force)
200 {
201 	struct g_gate_ctl_destroy ggio;
202 
203 	ggio.gctl_version = G_GATE_VERSION;
204 	ggio.gctl_unit = unit;
205 	ggio.gctl_force = force;
206 	g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
207 }
208 
209 int
210 g_gate_openflags(unsigned ggflags)
211 {
212 
213 	if ((ggflags & G_GATE_FLAG_READONLY) != 0)
214 		return (O_RDONLY);
215 	else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0)
216 		return (O_WRONLY);
217 	return (O_RDWR);
218 }
219 
220 void
221 g_gate_load_module(void)
222 {
223 
224 	if (modfind("g_gate") < 0) {
225 		/* Not present in kernel, try loading it. */
226 		if (kldload("geom_gate") < 0 || modfind("g_gate") < 0) {
227 			if (errno != EEXIST) {
228 				errx(EXIT_FAILURE,
229 				    "geom_gate module not available!");
230 			}
231 		}
232 	}
233 }
234 
235 #ifdef LIBGEOM
236 static struct gclass *
237 find_class(struct gmesh *mesh, const char *name)
238 {
239 	struct gclass *class;
240 
241 	LIST_FOREACH(class, &mesh->lg_class, lg_class) {
242 		if (strcmp(class->lg_name, name) == 0)
243 			return (class);
244 	}
245 	return (NULL);
246 }
247 
248 static const char *
249 get_conf(struct ggeom *gp, const char *name)
250 {
251 	struct gconfig *conf;
252 
253 	LIST_FOREACH(conf, &gp->lg_config, lg_config) {
254 		if (strcmp(conf->lg_name, name) == 0)
255 			return (conf->lg_val);
256 	}
257 	return (NULL);
258 }
259 
260 static void
261 show_config(struct ggeom *gp, int verbose)
262 {
263 	struct gprovider *pp;
264 	char buf[5];
265 
266 	pp = LIST_FIRST(&gp->lg_provider);
267 	if (pp == NULL)
268 		return;
269 	if (!verbose) {
270 		printf("%s\n", pp->lg_name);
271 		return;
272 	}
273 	printf("       NAME: %s\n", pp->lg_name);
274 	printf("       info: %s\n", get_conf(gp, "info"));
275 	printf("     access: %s\n", get_conf(gp, "access"));
276 	printf("    timeout: %s\n", get_conf(gp, "timeout"));
277 	printf("queue_count: %s\n", get_conf(gp, "queue_count"));
278 	printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
279 	printf(" references: %s\n", get_conf(gp, "ref"));
280 	humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
281 	    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
282 	printf("  mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
283 	printf(" sectorsize: %u\n", pp->lg_sectorsize);
284 	printf("       mode: %s\n", pp->lg_mode);
285 	printf("\n");
286 }
287 
288 void
289 g_gate_list(int unit, int verbose)
290 {
291 	struct gmesh mesh;
292 	struct gclass *class;
293 	struct ggeom *gp;
294 	char name[64];
295 	int error;
296 
297 	error = geom_gettree(&mesh);
298 	if (error != 0)
299 		exit(EXIT_FAILURE);
300 	class = find_class(&mesh, G_GATE_CLASS_NAME);
301 	if (class == NULL) {
302 		geom_deletetree(&mesh);
303 		exit(EXIT_SUCCESS);
304 	}
305 	if (unit >= 0) {
306 		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
307 		    unit);
308 	}
309 	LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
310 		if (unit != -1 && strcmp(gp->lg_name, name) != 0)
311 			continue;
312 		show_config(gp, verbose);
313 	}
314 	geom_deletetree(&mesh);
315 	exit(EXIT_SUCCESS);
316 }
317 #endif	/* LIBGEOM */
318 
319 in_addr_t
320 g_gate_str2ip(const char *str)
321 {
322 	struct hostent *hp;
323 	in_addr_t ip;
324 
325 	ip = inet_addr(str);
326 	if (ip != INADDR_NONE) {
327 		/* It is a valid IP address. */
328 		return (ip);
329 	}
330 	/* Check if it is a valid host name. */
331 	hp = gethostbyname(str);
332 	if (hp == NULL)
333 		return (INADDR_NONE);
334 	return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
335 }
336