2 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/param.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 <netinet/tcp.h>
42 #include <arpa/inet.h>
56 #include <geom/gate/g_gate.h>
60 int g_gate_devfd = -1;
61 int g_gate_verbose = 0;
65 g_gate_vlog(int priority, const char *message, va_list ap)
91 printf("%s: ", prefix);
95 if (priority != LOG_DEBUG)
96 vsyslog(priority, message, ap);
101 g_gate_log(int priority, const char *message, ...)
105 va_start(ap, message);
106 g_gate_vlog(priority, message, ap);
111 g_gate_xvlog(const char *message, va_list ap)
114 g_gate_vlog(LOG_ERR, message, ap);
115 g_gate_vlog(LOG_ERR, "Exiting.", ap);
120 g_gate_xlog(const char *message, ...)
124 va_start(ap, message);
125 g_gate_xvlog(message, ap);
132 g_gate_mediasize(int fd)
137 if (fstat(fd, &sb) == -1)
138 g_gate_xlog("fstat(): %s.", strerror(errno));
139 if (S_ISCHR(sb.st_mode)) {
140 if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
141 g_gate_xlog("Can't get media size: %s.",
144 } else if (S_ISREG(sb.st_mode)) {
145 mediasize = sb.st_size;
147 g_gate_xlog("Unsupported file system object.");
153 g_gate_sectorsize(int fd)
158 if (fstat(fd, &sb) == -1)
159 g_gate_xlog("fstat(): %s.", strerror(errno));
160 if (S_ISCHR(sb.st_mode)) {
161 if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
162 g_gate_xlog("Can't get sector size: %s.",
165 } else if (S_ISREG(sb.st_mode)) {
168 g_gate_xlog("Unsupported file system object.");
174 g_gate_open_device(void)
177 g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
178 if (g_gate_devfd == -1)
179 err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
183 g_gate_close_device(void)
190 g_gate_ioctl(unsigned long req, void *data)
193 if (ioctl(g_gate_devfd, req, data) == -1) {
194 g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
195 G_GATE_CTL_NAME, strerror(errno));
200 g_gate_destroy(int unit, int force)
202 struct g_gate_ctl_destroy ggio;
204 ggio.gctl_version = G_GATE_VERSION;
205 ggio.gctl_unit = unit;
206 ggio.gctl_force = force;
207 g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
211 g_gate_load_module(void)
214 if (modfind("g_gate") == -1) {
215 /* Not present in kernel, try loading it. */
216 if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
217 if (errno != EEXIST) {
219 "geom_gate module not available!");
226 g_gate_send(int s, const void *buf, size_t len, int flags)
228 ssize_t done = 0, done2;
229 const unsigned char *p = buf;
232 done2 = send(s, p, len, flags);
235 else if (done2 == -1) {
236 if (errno == EAGAIN) {
237 printf("%s: EAGAIN\n", __func__);
251 g_gate_recv(int s, void *buf, size_t len, int flags)
256 done = recv(s, buf, len, flags);
257 } while (done == -1 && errno == EAGAIN);
262 unsigned rcvbuf = G_GATE_RCVBUF;
263 unsigned sndbuf = G_GATE_SNDBUF;
266 g_gate_socket_settings(int sfd)
271 /* Socket settings. */
274 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on,
276 g_gate_xlog("setsockopt() error: %s.", strerror(errno));
279 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
280 g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
282 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
283 g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
285 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
286 g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
289 if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
290 g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
293 if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
294 g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
300 static struct gclass *
301 find_class(struct gmesh *mesh, const char *name)
303 struct gclass *class;
305 LIST_FOREACH(class, &mesh->lg_class, lg_class) {
306 if (strcmp(class->lg_name, name) == 0)
313 get_conf(struct ggeom *gp, const char *name)
315 struct gconfig *conf;
317 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
318 if (strcmp(conf->lg_name, name) == 0)
319 return (conf->lg_val);
325 show_config(struct ggeom *gp, int verbose)
327 struct gprovider *pp;
330 pp = LIST_FIRST(&gp->lg_provider);
334 printf("%s\n", pp->lg_name);
337 printf(" NAME: %s\n", pp->lg_name);
338 printf(" info: %s\n", get_conf(gp, "info"));
339 printf(" access: %s\n", get_conf(gp, "access"));
340 printf(" timeout: %s\n", get_conf(gp, "timeout"));
341 printf("queue_count: %s\n", get_conf(gp, "queue_count"));
342 printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
343 printf(" references: %s\n", get_conf(gp, "ref"));
344 humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
345 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
346 printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
347 printf(" sectorsize: %u\n", pp->lg_sectorsize);
348 printf(" mode: %s\n", pp->lg_mode);
353 g_gate_list(int unit, int verbose)
356 struct gclass *class;
361 error = geom_gettree(&mesh);
364 class = find_class(&mesh, G_GATE_CLASS_NAME);
366 geom_deletetree(&mesh);
370 snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
373 LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
374 if (unit != -1 && strcmp(gp->lg_name, name) != 0)
376 show_config(gp, verbose);
378 geom_deletetree(&mesh);
384 g_gate_str2ip(const char *str)
390 if (ip != INADDR_NONE) {
391 /* It is a valid IP address. */
394 /* Check if it is a valid host name. */
395 hp = gethostbyname(str);
397 return (INADDR_NONE);
398 return (((struct in_addr *)(void *)hp->h_addr)->s_addr);