2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/param.h>
38 #include <sys/endian.h>
39 #include <sys/socket.h>
40 #include <sys/linker.h>
41 #include <sys/module.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
58 #include <geom/gate/g_gate.h>
62 int g_gate_devfd = -1;
63 int g_gate_verbose = 0;
67 g_gate_vlog(int priority, const char *message, va_list ap)
93 printf("%s: ", prefix);
97 if (priority != LOG_DEBUG)
98 vsyslog(priority, message, ap);
103 g_gate_log(int priority, const char *message, ...)
107 va_start(ap, message);
108 g_gate_vlog(priority, message, ap);
113 g_gate_xvlog(const char *message, va_list ap)
116 g_gate_vlog(LOG_ERR, message, ap);
117 g_gate_vlog(LOG_ERR, "Exiting.", ap);
122 g_gate_xlog(const char *message, ...)
126 va_start(ap, message);
127 g_gate_xvlog(message, ap);
134 g_gate_mediasize(int fd)
139 if (fstat(fd, &sb) == -1)
140 g_gate_xlog("fstat(): %s.", strerror(errno));
141 if (S_ISCHR(sb.st_mode)) {
142 if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
143 g_gate_xlog("Can't get media size: %s.",
146 } else if (S_ISREG(sb.st_mode)) {
147 mediasize = sb.st_size;
149 g_gate_xlog("Unsupported file system object.");
155 g_gate_sectorsize(int fd)
160 if (fstat(fd, &sb) == -1)
161 g_gate_xlog("fstat(): %s.", strerror(errno));
162 if (S_ISCHR(sb.st_mode)) {
163 if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
164 g_gate_xlog("Can't get sector size: %s.",
167 } else if (S_ISREG(sb.st_mode)) {
170 g_gate_xlog("Unsupported file system object.");
176 g_gate_open_device(void)
179 g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR);
180 if (g_gate_devfd == -1)
181 err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
185 g_gate_close_device(void)
192 g_gate_ioctl(unsigned long req, void *data)
195 if (ioctl(g_gate_devfd, req, data) == -1) {
196 g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
197 G_GATE_CTL_NAME, strerror(errno));
202 g_gate_destroy(int unit, int force)
204 struct g_gate_ctl_destroy ggio;
206 ggio.gctl_version = G_GATE_VERSION;
207 ggio.gctl_unit = unit;
208 ggio.gctl_force = force;
209 g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
213 g_gate_load_module(void)
216 if (modfind("g_gate") == -1) {
217 /* Not present in kernel, try loading it. */
218 if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
219 if (errno != EEXIST) {
221 "geom_gate module not available!");
228 * When we send from ggatec packets larger than 32kB, performance drops
229 * significantly (eg. to 256kB/s over 1Gbit/s link). This is not a problem
230 * when data is send from ggated. I don't know why, so for now I limit
231 * size of packets send from ggatec to 32kB by defining MAX_SEND_SIZE
232 * in ggatec Makefile.
234 #ifndef MAX_SEND_SIZE
235 #define MAX_SEND_SIZE MAXPHYS
238 g_gate_send(int s, const void *buf, size_t len, int flags)
240 ssize_t done = 0, done2;
241 const unsigned char *p = buf;
244 done2 = send(s, p, MIN(len, MAX_SEND_SIZE), flags);
247 else if (done2 == -1) {
248 if (errno == EAGAIN) {
249 printf("%s: EAGAIN\n", __func__);
263 g_gate_recv(int s, void *buf, size_t len, int flags)
268 done = recv(s, buf, len, flags);
269 } while (done == -1 && errno == EAGAIN);
274 unsigned rcvbuf = G_GATE_RCVBUF;
275 unsigned sndbuf = G_GATE_SNDBUF;
278 g_gate_socket_settings(int sfd)
283 /* Socket settings. */
286 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on,
288 g_gate_xlog("setsockopt() error: %s.", strerror(errno));
291 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
292 g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
294 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
295 g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
297 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
298 g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
301 if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
302 g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
305 if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
306 g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
312 static struct gclass *
313 find_class(struct gmesh *mesh, const char *name)
315 struct gclass *class;
317 LIST_FOREACH(class, &mesh->lg_class, lg_class) {
318 if (strcmp(class->lg_name, name) == 0)
325 get_conf(struct ggeom *gp, const char *name)
327 struct gconfig *conf;
329 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
330 if (strcmp(conf->lg_name, name) == 0)
331 return (conf->lg_val);
337 show_config(struct ggeom *gp, int verbose)
339 struct gprovider *pp;
342 pp = LIST_FIRST(&gp->lg_provider);
346 printf("%s\n", pp->lg_name);
349 printf(" NAME: %s\n", pp->lg_name);
350 printf(" info: %s\n", get_conf(gp, "info"));
351 printf(" access: %s\n", get_conf(gp, "access"));
352 printf(" timeout: %s\n", get_conf(gp, "timeout"));
353 printf("queue_count: %s\n", get_conf(gp, "queue_count"));
354 printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
355 printf(" references: %s\n", get_conf(gp, "ref"));
356 humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
357 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
358 printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
359 printf(" sectorsize: %u\n", pp->lg_sectorsize);
360 printf(" mode: %s\n", pp->lg_mode);
365 g_gate_list(int unit, int verbose)
368 struct gclass *class;
373 error = geom_gettree(&mesh);
376 class = find_class(&mesh, G_GATE_CLASS_NAME);
378 geom_deletetree(&mesh);
382 snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
385 LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
386 if (unit != -1 && strcmp(gp->lg_name, name) != 0)
388 show_config(gp, verbose);
390 geom_deletetree(&mesh);
396 g_gate_str2ip(const char *str)
402 if (ip != INADDR_NONE) {
403 /* It is a valid IP address. */
406 /* Check if it is a valid host name. */
407 hp = gethostbyname(str);
409 return (INADDR_NONE);
410 return (((struct in_addr *)(void *)hp->h_addr)->s_addr);