@@ -1,14 +0,0 @@ | |||
# $FreeBSD$ | |||
.include <bsd.own.mk> | |||
SUBDIR= ${_ggatec} \ | |||
${_ggated} \ | |||
ggatel | |||
.if ${MK_LIBTHR} != "no" | |||
_ggatec= ggatec | |||
_ggated= ggated | |||
.endif | |||
.include <bsd.subdir.mk> |
@@ -1,3 +0,0 @@ | |||
# $FreeBSD$ | |||
.include "../Makefile.inc" |
@@ -1,16 +0,0 @@ | |||
# $FreeBSD$ | |||
.PATH: ${.CURDIR}/../shared | |||
PROG= ggatec | |||
MAN= ggatec.8 | |||
SRCS= ggatec.c ggate.c | |||
CFLAGS+= -DMAX_SEND_SIZE=32768 | |||
CFLAGS+= -DLIBGEOM | |||
CFLAGS+= -I${.CURDIR}/../shared | |||
DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} ${LIBPTHREAD} | |||
LDADD= -lgeom -lsbuf -lbsdxml -lutil -lpthread | |||
.include <bsd.prog.mk> |
@@ -1,181 +0,0 @@ | |||
.\" Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
.\" SUCH DAMAGE. | |||
.\" | |||
.\" $FreeBSD$ | |||
.\" | |||
.Dd April 26, 2004 | |||
.Dt GGATEC 8 | |||
.Os | |||
.Sh NAME | |||
.Nm ggatec | |||
.Nd "GEOM Gate network client and control utility" | |||
.Sh SYNOPSIS | |||
.Nm | |||
.Cm create | |||
.Op Fl n | |||
.Op Fl v | |||
.Op Fl o Cm ro | wo | rw | |||
.Op Fl p Ar port | |||
.Op Fl q Ar queue_size | |||
.Op Fl R Ar rcvbuf | |||
.Op Fl S Ar sndbuf | |||
.Op Fl s Ar sectorsize | |||
.Op Fl t Ar timeout | |||
.Op Fl u Ar unit | |||
.Ar host | |||
.Ar path | |||
.Nm | |||
.Cm rescue | |||
.Op Fl n | |||
.Op Fl v | |||
.Op Fl o Cm ro | wo | rw | |||
.Op Fl p Ar port | |||
.Op Fl R Ar rcvbuf | |||
.Op Fl S Ar sndbuf | |||
.Fl u Ar unit | |||
.Ar host | |||
.Ar path | |||
.Nm | |||
.Cm destroy | |||
.Op Fl f | |||
.Fl u Ar unit | |||
.Nm | |||
.Cm list | |||
.Op Fl v | |||
.Op Fl u Ar unit | |||
.Sh DESCRIPTION | |||
The | |||
.Nm | |||
utility is a network client for GEOM Gate class. | |||
It is responsible for creation of | |||
.Nm ggate | |||
devices and forwarding I/O requests between | |||
.Nm geom_gate.ko | |||
kernel module and | |||
.Xr ggated 8 | |||
network daemon. | |||
Available commands: | |||
.Bl -tag -width ".Cm destroy" | |||
.It Cm create | |||
Connect to given | |||
.Xr ggated 8 | |||
daemon and create a | |||
.Nm ggate | |||
provider related to the given remote file or device. | |||
.It Cm rescue | |||
If | |||
.Nm | |||
process died/has been killed, you can save situation with this | |||
command, which creates new connection to the | |||
.Xr ggated 8 | |||
daemon and will handle pending and future requests. | |||
.It Cm destroy | |||
Destroy the given | |||
.Nm ggate | |||
provider. | |||
.It Cm list | |||
List | |||
.Nm ggate | |||
providers. | |||
.El | |||
.Pp | |||
Available options: | |||
.Bl -tag -width ".Fl s Cm ro | wo | rw" | |||
.It Fl f | |||
Forcibly destroy | |||
.Nm ggate | |||
provider (cancels all pending requests). | |||
.It Fl n | |||
Do not use | |||
.Dv TCP_NODELAY | |||
option on TCP sockets. | |||
.It Fl o Cm ro | wo | rw | |||
Specify permission to use when opening the file or device: read-only | |||
.Pq Cm ro , | |||
write-only | |||
.Pq Cm wo , | |||
or read-write | |||
.Pq Cm rw . | |||
Default is | |||
.Cm rw . | |||
.It Fl p Ar port | |||
Port to connect to on the remote host. | |||
Default is 3080. | |||
.It Fl q Ar queue_size | |||
Number of pending I/O requests that can be queued before they will | |||
start to be canceled. | |||
Default is 1024. | |||
.It Fl R Ar rcvbuf | |||
Size of receive buffer to use. | |||
Default is 131072 (128kB). | |||
.It Fl S Ar sndbuf | |||
Size of send buffer to use. | |||
Default is 131072 (128kB). | |||
.It Fl s Ar sectorsize | |||
Sector size for | |||
.Nm ggate | |||
provider. | |||
If not specified, it is taken from device, or set to 512 bytes for files. | |||
.It Fl t Ar timeout | |||
Number of seconds to wait before an I/O request will be canceled. | |||
0 means no timeout. | |||
Default is 0. | |||
.It Fl u Ar unit | |||
Unit number to use. | |||
.It Fl v | |||
Do not fork, run in foreground and print debug informations on standard | |||
output. | |||
.It Ar host | |||
Remote host to connect to. | |||
.It Ar path | |||
Path to a regular file or device. | |||
.El | |||
.Sh EXIT STATUS | |||
Exit status is 0 on success, or 1 if the command fails. | |||
To get details about the failure, | |||
.Nm | |||
should be called with the | |||
.Fl v | |||
option. | |||
.Sh EXAMPLES | |||
Make use of CD-ROM device from remote host. | |||
.Bd -literal -offset indent | |||
server# cat /etc/gg.exports | |||
client RO /dev/acd0 | |||
server# ggated | |||
client# ggatec create -o ro server /dev/acd0 | |||
ggate0 | |||
client# mount_cd9660 /dev/ggate0 /cdrom | |||
.Ed | |||
.Sh SEE ALSO | |||
.Xr geom 4 , | |||
.Xr ggated 8 , | |||
.Xr ggatel 8 , | |||
.Xr mount_cd9660 8 | |||
.Sh AUTHORS | |||
The | |||
.Nm | |||
utility as well as this manual page was written by | |||
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org . |
@@ -1,642 +0,0 @@ | |||
/*- | |||
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* $FreeBSD$ | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <stdint.h> | |||
#include <fcntl.h> | |||
#include <unistd.h> | |||
#include <string.h> | |||
#include <ctype.h> | |||
#include <libgen.h> | |||
#include <pthread.h> | |||
#include <signal.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <assert.h> | |||
#include <sys/param.h> | |||
#include <sys/ioctl.h> | |||
#include <sys/socket.h> | |||
#include <sys/sysctl.h> | |||
#include <sys/syslog.h> | |||
#include <sys/time.h> | |||
#include <sys/bio.h> | |||
#include <netinet/in.h> | |||
#include <netinet/tcp.h> | |||
#include <arpa/inet.h> | |||
#include <geom/gate/g_gate.h> | |||
#include "ggate.h" | |||
enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET; | |||
static const char *path = NULL; | |||
static const char *host = NULL; | |||
static int unit = G_GATE_UNIT_AUTO; | |||
static unsigned flags = 0; | |||
static int force = 0; | |||
static unsigned queue_size = G_GATE_QUEUE_SIZE; | |||
static unsigned port = G_GATE_PORT; | |||
static off_t mediasize; | |||
static unsigned sectorsize = 0; | |||
static unsigned timeout = G_GATE_TIMEOUT; | |||
static int sendfd, recvfd; | |||
static uint32_t token; | |||
static pthread_t sendtd, recvtd; | |||
static int reconnect; | |||
static void | |||
usage(void) | |||
{ | |||
fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] [-p port] " | |||
"[-q queue_size] [-R rcvbuf] [-S sndbuf] [-s sectorsize] " | |||
"[-t timeout] [-u unit] <host> <path>\n", getprogname()); | |||
fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] [-p port] " | |||
"[-R rcvbuf] [-S sndbuf] <-u unit> <host> <path>\n", getprogname()); | |||
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname()); | |||
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname()); | |||
exit(EXIT_FAILURE); | |||
} | |||
static void * | |||
send_thread(void *arg __unused) | |||
{ | |||
struct g_gate_ctl_io ggio; | |||
struct g_gate_hdr hdr; | |||
char buf[MAXPHYS]; | |||
ssize_t data; | |||
int error; | |||
g_gate_log(LOG_NOTICE, "%s: started!", __func__); | |||
ggio.gctl_version = G_GATE_VERSION; | |||
ggio.gctl_unit = unit; | |||
ggio.gctl_data = buf; | |||
for (;;) { | |||
ggio.gctl_length = sizeof(buf); | |||
ggio.gctl_error = 0; | |||
g_gate_ioctl(G_GATE_CMD_START, &ggio); | |||
error = ggio.gctl_error; | |||
switch (error) { | |||
case 0: | |||
break; | |||
case ECANCELED: | |||
if (reconnect) | |||
break; | |||
/* Exit gracefully. */ | |||
g_gate_close_device(); | |||
exit(EXIT_SUCCESS); | |||
#if 0 | |||
case ENOMEM: | |||
/* Buffer too small. */ | |||
ggio.gctl_data = realloc(ggio.gctl_data, | |||
ggio.gctl_length); | |||
if (ggio.gctl_data != NULL) { | |||
bsize = ggio.gctl_length; | |||
goto once_again; | |||
} | |||
/* FALLTHROUGH */ | |||
#endif | |||
case ENXIO: | |||
default: | |||
g_gate_xlog("ioctl(/dev/%s): %s.", G_GATE_CTL_NAME, | |||
strerror(error)); | |||
} | |||
if (reconnect) | |||
break; | |||
switch (ggio.gctl_cmd) { | |||
case BIO_READ: | |||
hdr.gh_cmd = GGATE_CMD_READ; | |||
break; | |||
case BIO_WRITE: | |||
hdr.gh_cmd = GGATE_CMD_WRITE; | |||
break; | |||
} | |||
hdr.gh_seq = ggio.gctl_seq; | |||
hdr.gh_offset = ggio.gctl_offset; | |||
hdr.gh_length = ggio.gctl_length; | |||
hdr.gh_error = 0; | |||
g_gate_swap2n_hdr(&hdr); | |||
data = g_gate_send(sendfd, &hdr, sizeof(hdr), MSG_NOSIGNAL); | |||
g_gate_log(LOG_DEBUG, "Sent hdr packet."); | |||
g_gate_swap2h_hdr(&hdr); | |||
if (reconnect) | |||
break; | |||
if (data != sizeof(hdr)) { | |||
g_gate_log(LOG_ERR, "Lost connection 1."); | |||
reconnect = 1; | |||
pthread_kill(recvtd, SIGUSR1); | |||
break; | |||
} | |||
if (hdr.gh_cmd == GGATE_CMD_WRITE) { | |||
data = g_gate_send(sendfd, ggio.gctl_data, | |||
ggio.gctl_length, MSG_NOSIGNAL); | |||
if (reconnect) | |||
break; | |||
if (data != ggio.gctl_length) { | |||
g_gate_log(LOG_ERR, "Lost connection 2 (%zd != %zd).", data, (ssize_t)ggio.gctl_length); | |||
reconnect = 1; | |||
pthread_kill(recvtd, SIGUSR1); | |||
break; | |||
} | |||
g_gate_log(LOG_DEBUG, "Sent %zd bytes (offset=%llu, " | |||
"size=%u).", data, hdr.gh_offset, hdr.gh_length); | |||
} | |||
} | |||
g_gate_log(LOG_DEBUG, "%s: Died.", __func__); | |||
return (NULL); | |||
} | |||
static void * | |||
recv_thread(void *arg __unused) | |||
{ | |||
struct g_gate_ctl_io ggio; | |||
struct g_gate_hdr hdr; | |||
char buf[MAXPHYS]; | |||
ssize_t data; | |||
g_gate_log(LOG_NOTICE, "%s: started!", __func__); | |||
ggio.gctl_version = G_GATE_VERSION; | |||
ggio.gctl_unit = unit; | |||
ggio.gctl_data = buf; | |||
for (;;) { | |||
data = g_gate_recv(recvfd, &hdr, sizeof(hdr), MSG_WAITALL); | |||
if (reconnect) | |||
break; | |||
g_gate_swap2h_hdr(&hdr); | |||
if (data != sizeof(hdr)) { | |||
if (data == -1 && errno == EAGAIN) | |||
continue; | |||
g_gate_log(LOG_ERR, "Lost connection 3."); | |||
reconnect = 1; | |||
pthread_kill(sendtd, SIGUSR1); | |||
break; | |||
} | |||
g_gate_log(LOG_DEBUG, "Received hdr packet."); | |||
ggio.gctl_seq = hdr.gh_seq; | |||
ggio.gctl_cmd = hdr.gh_cmd; | |||
ggio.gctl_offset = hdr.gh_offset; | |||
ggio.gctl_length = hdr.gh_length; | |||
ggio.gctl_error = hdr.gh_error; | |||
if (ggio.gctl_error == 0 && ggio.gctl_cmd == GGATE_CMD_READ) { | |||
data = g_gate_recv(recvfd, ggio.gctl_data, | |||
ggio.gctl_length, MSG_WAITALL); | |||
if (reconnect) | |||
break; | |||
g_gate_log(LOG_DEBUG, "Received data packet."); | |||
if (data != ggio.gctl_length) { | |||
g_gate_log(LOG_ERR, "Lost connection 4."); | |||
reconnect = 1; | |||
pthread_kill(sendtd, SIGUSR1); | |||
break; | |||
} | |||
g_gate_log(LOG_DEBUG, "Received %d bytes (offset=%ju, " | |||
"size=%zu).", data, (uintmax_t)hdr.gh_offset, | |||
(size_t)hdr.gh_length); | |||
} | |||
g_gate_ioctl(G_GATE_CMD_DONE, &ggio); | |||
} | |||
g_gate_log(LOG_DEBUG, "%s: Died.", __func__); | |||
pthread_exit(NULL); | |||
} | |||
static int | |||
handshake(int dir) | |||
{ | |||
struct g_gate_version ver; | |||
struct g_gate_cinit cinit; | |||
struct g_gate_sinit sinit; | |||
struct sockaddr_in serv; | |||
int sfd; | |||
/* | |||
* Do the network stuff. | |||
*/ | |||
bzero(&serv, sizeof(serv)); | |||
serv.sin_family = AF_INET; | |||
serv.sin_addr.s_addr = g_gate_str2ip(host); | |||
if (serv.sin_addr.s_addr == INADDR_NONE) { | |||
g_gate_log(LOG_DEBUG, "Invalid IP/host name: %s.", host); | |||
return (-1); | |||
} | |||
serv.sin_port = htons(port); | |||
sfd = socket(AF_INET, SOCK_STREAM, 0); | |||
if (sfd == -1) { | |||
g_gate_log(LOG_DEBUG, "Cannot open socket: %s.", | |||
strerror(errno)); | |||
return (-1); | |||
} | |||
g_gate_socket_settings(sfd); | |||
if (connect(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) { | |||
g_gate_log(LOG_DEBUG, "Cannot connect to server: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
g_gate_log(LOG_INFO, "Connected to the server: %s:%d.", host, port); | |||
/* | |||
* Create and send version packet. | |||
*/ | |||
g_gate_log(LOG_DEBUG, "Sending version packet."); | |||
assert(strlen(GGATE_MAGIC) == sizeof(ver.gv_magic)); | |||
bcopy(GGATE_MAGIC, ver.gv_magic, sizeof(ver.gv_magic)); | |||
ver.gv_version = GGATE_VERSION; | |||
ver.gv_error = 0; | |||
g_gate_swap2n_version(&ver); | |||
if (g_gate_send(sfd, &ver, sizeof(ver), MSG_NOSIGNAL) == -1) { | |||
g_gate_log(LOG_DEBUG, "Error while sending version packet: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
bzero(&ver, sizeof(ver)); | |||
if (g_gate_recv(sfd, &ver, sizeof(ver), MSG_WAITALL) == -1) { | |||
g_gate_log(LOG_DEBUG, "Error while receiving data: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
if (ver.gv_error != 0) { | |||
g_gate_log(LOG_DEBUG, "Version verification problem: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
/* | |||
* Create and send initial packet. | |||
*/ | |||
g_gate_log(LOG_DEBUG, "Sending initial packet."); | |||
if (strlcpy(cinit.gc_path, path, sizeof(cinit.gc_path)) >= | |||
sizeof(cinit.gc_path)) { | |||
g_gate_log(LOG_DEBUG, "Path name too long."); | |||
close(sfd); | |||
return (-1); | |||
} | |||
cinit.gc_flags = flags | dir; | |||
cinit.gc_token = token; | |||
cinit.gc_nconn = 2; | |||
g_gate_swap2n_cinit(&cinit); | |||
if (g_gate_send(sfd, &cinit, sizeof(cinit), MSG_NOSIGNAL) == -1) { | |||
g_gate_log(LOG_DEBUG, "Error while sending initial packet: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
g_gate_swap2h_cinit(&cinit); | |||
/* | |||
* Receiving initial packet from server. | |||
*/ | |||
g_gate_log(LOG_DEBUG, "Receiving initial packet."); | |||
if (g_gate_recv(sfd, &sinit, sizeof(sinit), MSG_WAITALL) == -1) { | |||
g_gate_log(LOG_DEBUG, "Error while receiving data: %s.", | |||
strerror(errno)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
g_gate_swap2h_sinit(&sinit); | |||
if (sinit.gs_error != 0) { | |||
g_gate_log(LOG_DEBUG, "Error from server: %s.", | |||
strerror(sinit.gs_error)); | |||
close(sfd); | |||
return (-1); | |||
} | |||
g_gate_log(LOG_DEBUG, "Received initial packet."); | |||
mediasize = sinit.gs_mediasize; | |||
if (sectorsize == 0) | |||
sectorsize = sinit.gs_sectorsize; | |||
return (sfd); | |||
} | |||
static void | |||
mydaemon(void) | |||
{ | |||
if (g_gate_verbose > 0) | |||
return; | |||
if (daemon(0, 0) == 0) | |||
return; | |||
if (action == CREATE) | |||
g_gate_destroy(unit, 1); | |||
err(EXIT_FAILURE, "Cannot daemonize"); | |||
} | |||
static int | |||
g_gatec_connect(void) | |||
{ | |||
token = arc4random(); | |||
/* | |||
* Our receive descriptor is connected to the send descriptor on the | |||
* server side. | |||
*/ | |||
recvfd = handshake(GGATE_FLAG_SEND); | |||
if (recvfd == -1) | |||
return (0); | |||
/* | |||
* Our send descriptor is connected to the receive descriptor on the | |||
* server side. | |||
*/ | |||
sendfd = handshake(GGATE_FLAG_RECV); | |||
if (sendfd == -1) | |||
return (0); | |||
return (1); | |||
} | |||
static void | |||
g_gatec_start(void) | |||
{ | |||
int error; | |||
reconnect = 0; | |||
error = pthread_create(&recvtd, NULL, recv_thread, NULL); | |||
if (error != 0) { | |||
g_gate_destroy(unit, 1); | |||
g_gate_xlog("pthread_create(recv_thread): %s.", | |||
strerror(error)); | |||
} | |||
sendtd = pthread_self(); | |||
send_thread(NULL); | |||
/* Disconnected. */ | |||
close(sendfd); | |||
close(recvfd); | |||
} | |||
static void | |||
signop(int sig __unused) | |||
{ | |||
/* Do nothing. */ | |||
} | |||
static void | |||
g_gatec_loop(void) | |||
{ | |||
struct g_gate_ctl_cancel ggioc; | |||
signal(SIGUSR1, signop); | |||
for (;;) { | |||
g_gatec_start(); | |||
g_gate_log(LOG_NOTICE, "Disconnected [%s %s]. Connecting...", | |||
host, path); | |||
while (!g_gatec_connect()) { | |||
sleep(2); | |||
g_gate_log(LOG_NOTICE, "Connecting [%s %s]...", host, | |||
path); | |||
} | |||
ggioc.gctl_version = G_GATE_VERSION; | |||
ggioc.gctl_unit = unit; | |||
ggioc.gctl_seq = 0; | |||
g_gate_ioctl(G_GATE_CMD_CANCEL, &ggioc); | |||
} | |||
} | |||
static void | |||
g_gatec_create(void) | |||
{ | |||
struct g_gate_ctl_create ggioc; | |||
if (!g_gatec_connect()) | |||
g_gate_xlog("Cannot connect: %s.", strerror(errno)); | |||
/* | |||
* Ok, got both sockets, time to create provider. | |||
*/ | |||
ggioc.gctl_version = G_GATE_VERSION; | |||
ggioc.gctl_mediasize = mediasize; | |||
ggioc.gctl_sectorsize = sectorsize; | |||
ggioc.gctl_flags = flags; | |||
ggioc.gctl_maxcount = queue_size; | |||
ggioc.gctl_timeout = timeout; | |||
ggioc.gctl_unit = unit; | |||
snprintf(ggioc.gctl_info, sizeof(ggioc.gctl_info), "%s:%u %s", host, | |||
port, path); | |||
g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc); | |||
if (unit == -1) { | |||
printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit); | |||
fflush(stdout); | |||
} | |||
unit = ggioc.gctl_unit; | |||
mydaemon(); | |||
g_gatec_loop(); | |||
} | |||
static void | |||
g_gatec_rescue(void) | |||
{ | |||
struct g_gate_ctl_cancel ggioc; | |||
if (!g_gatec_connect()) | |||
g_gate_xlog("Cannot connect: %s.", strerror(errno)); | |||
ggioc.gctl_version = G_GATE_VERSION; | |||
ggioc.gctl_unit = unit; | |||
ggioc.gctl_seq = 0; | |||
g_gate_ioctl(G_GATE_CMD_CANCEL, &ggioc); | |||
mydaemon(); | |||
g_gatec_loop(); | |||
} | |||
int | |||
main(int argc, char *argv[]) | |||
{ | |||
if (argc < 2) | |||
usage(); | |||
if (strcasecmp(argv[1], "create") == 0) | |||
action = CREATE; | |||
else if (strcasecmp(argv[1], "destroy") == 0) | |||
action = DESTROY; | |||
else if (strcasecmp(argv[1], "list") == 0) | |||
action = LIST; | |||
else if (strcasecmp(argv[1], "rescue") == 0) | |||
action = RESCUE; | |||
else | |||
usage(); | |||
argc -= 1; | |||
argv += 1; | |||
for (;;) { | |||
int ch; | |||
ch = getopt(argc, argv, "fno:p:q:R:S:s:t:u:v"); | |||
if (ch == -1) | |||
break; | |||
switch (ch) { | |||
case 'f': | |||
if (action != DESTROY) | |||
usage(); | |||
force = 1; | |||
break; | |||
case 'n': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
nagle = 0; | |||
break; | |||
case 'o': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
if (strcasecmp("ro", optarg) == 0) | |||
flags = G_GATE_FLAG_READONLY; | |||
else if (strcasecmp("wo", optarg) == 0) | |||
flags = G_GATE_FLAG_WRITEONLY; | |||
else if (strcasecmp("rw", optarg) == 0) | |||
flags = 0; | |||
else { | |||
errx(EXIT_FAILURE, | |||
"Invalid argument for '-o' option."); | |||
} | |||
break; | |||
case 'p': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
errno = 0; | |||
port = strtoul(optarg, NULL, 10); | |||
if (port == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid port."); | |||
break; | |||
case 'q': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
queue_size = strtoul(optarg, NULL, 10); | |||
if (queue_size == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid queue_size."); | |||
break; | |||
case 'R': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
errno = 0; | |||
rcvbuf = strtoul(optarg, NULL, 10); | |||
if (rcvbuf == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid rcvbuf."); | |||
break; | |||
case 'S': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
errno = 0; | |||
sndbuf = strtoul(optarg, NULL, 10); | |||
if (sndbuf == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid sndbuf."); | |||
break; | |||
case 's': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
sectorsize = strtoul(optarg, NULL, 10); | |||
if (sectorsize == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid sectorsize."); | |||
break; | |||
case 't': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
timeout = strtoul(optarg, NULL, 10); | |||
if (timeout == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid timeout."); | |||
break; | |||
case 'u': | |||
errno = 0; | |||
unit = strtol(optarg, NULL, 10); | |||
if (unit == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid unit number."); | |||
break; | |||
case 'v': | |||
if (action == DESTROY) | |||
usage(); | |||
g_gate_verbose++; | |||
break; | |||
default: | |||
usage(); | |||
} | |||
} | |||
argc -= optind; | |||
argv += optind; | |||
switch (action) { | |||
case CREATE: | |||
if (argc != 2) | |||
usage(); | |||
g_gate_load_module(); | |||
g_gate_open_device(); | |||
host = argv[0]; | |||
path = argv[1]; | |||
g_gatec_create(); | |||
break; | |||
case DESTROY: | |||
if (unit == -1) { | |||
fprintf(stderr, "Required unit number.\n"); | |||
usage(); | |||
} | |||
g_gate_verbose = 1; | |||
g_gate_open_device(); | |||
g_gate_destroy(unit, force); | |||
break; | |||
case LIST: | |||
g_gate_list(unit, g_gate_verbose); | |||
break; | |||
case RESCUE: | |||
if (argc != 2) | |||
usage(); | |||
if (unit == -1) { | |||
fprintf(stderr, "Required unit number.\n"); | |||
usage(); | |||
} | |||
g_gate_open_device(); | |||
host = argv[0]; | |||
path = argv[1]; | |||
g_gatec_rescue(); | |||
break; | |||
case UNSET: | |||
default: | |||
usage(); | |||
} | |||
g_gate_close_device(); | |||
exit(EXIT_SUCCESS); | |||
} |
@@ -1,14 +0,0 @@ | |||
# $FreeBSD$ | |||
.PATH: ${.CURDIR}/../shared | |||
PROG= ggated | |||
MAN= ggated.8 | |||
SRCS= ggated.c ggate.c | |||
DPADD= ${LIBPTHREAD} | |||
LDADD= -lpthread | |||
CFLAGS+= -I${.CURDIR}/../shared | |||
.include <bsd.prog.mk> |
@@ -1,111 +0,0 @@ | |||
.\" Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
.\" SUCH DAMAGE. | |||
.\" | |||
.\" $FreeBSD$ | |||
.\" | |||
.Dd April 29, 2004 | |||
.Dt GGATED 8 | |||
.Os | |||
.Sh NAME | |||
.Nm ggated | |||
.Nd "GEOM Gate network daemon" | |||
.Sh SYNOPSIS | |||
.Nm | |||
.Op Fl h | |||
.Op Fl n | |||
.Op Fl v | |||
.Op Fl a Ar address | |||
.Op Fl p Ar port | |||
.Op Fl R Ar rcvbuf | |||
.Op Fl S Ar sndbuf | |||
.Op Ar "exports file" | |||
.Sh DESCRIPTION | |||
The | |||
.Nm | |||
utility is a network server for GEOM Gate class. | |||
It runs on a server machine to service GEOM Gate requests from workers | |||
placed on a client machine. | |||
Keep in mind, that connection between | |||
.Xr ggatec 8 | |||
and | |||
.Nm | |||
is not encrypted. | |||
.Pp | |||
Available options: | |||
.Bl -tag -width ".Ar exports\ file" | |||
.It Fl a Ar address | |||
Specifies an IP address to bind to. | |||
.It Fl h | |||
Print available options. | |||
.It Fl n | |||
Do not use | |||
.Dv TCP_NODELAY | |||
option on TCP sockets. | |||
.It Fl p Ar port | |||
Port on which | |||
.Nm | |||
listens for connection. | |||
Default is 3080. | |||
.It Fl R Ar rcvbuf | |||
Size of receive buffer to use. | |||
Default is 131072 (128kB). | |||
.It Fl S Ar sndbuf | |||
Size of send buffer to use. | |||
Default is 131072 (128kB). | |||
.It Fl v | |||
Do not fork, run in foreground and print debug informations on standard | |||
output. | |||
.It Ar "exports file" | |||
An alternate location for the exports file. | |||
.El | |||
.Pp | |||
The format of an exports file is as follows: | |||
.Bd -literal -offset indent | |||
1.2.3.4 RO /dev/acd0 | |||
1.2.3.0/24 RW /tmp/test.img | |||
hostname WO /tmp/image | |||
.Ed | |||
.Sh EXIT STATUS | |||
Exit status is 0 on success, or 1 if the command fails. | |||
To get details about the failure, | |||
.Nm | |||
should be called with the | |||
.Fl v | |||
option. | |||
.Sh EXAMPLES | |||
Export CD-ROM device and a file: | |||
.Bd -literal -offset indent | |||
# echo "1.2.3.0/24 RO /dev/acd0" > /etc/gg.exports | |||
# echo "client RW /image" >> /etc/gg.exports | |||
# ggated | |||
.Ed | |||
.Sh SEE ALSO | |||
.Xr geom 4 , | |||
.Xr ggatec 8 , | |||
.Xr ggatel 8 | |||
.Sh AUTHORS | |||
The | |||
.Nm | |||
utility as well as this manual page was written by | |||
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org . |
@@ -1,15 +0,0 @@ | |||
# $FreeBSD$ | |||
.PATH: ${.CURDIR}/../shared | |||
PROG= ggatel | |||
MAN= ggatel.8 | |||
SRCS= ggatel.c ggate.c | |||
CFLAGS+= -DLIBGEOM | |||
CFLAGS+= -I${.CURDIR}/../shared | |||
DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} | |||
LDADD= -lgeom -lsbuf -lbsdxml -lutil | |||
.include <bsd.prog.mk> |
@@ -1,160 +0,0 @@ | |||
.\" Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
.\" SUCH DAMAGE. | |||
.\" | |||
.\" $FreeBSD$ | |||
.\" | |||
.Dd April 26, 2004 | |||
.Dt GGATEL 8 | |||
.Os | |||
.Sh NAME | |||
.Nm ggatel | |||
.Nd "GEOM Gate local control utility" | |||
.Sh SYNOPSIS | |||
.Nm | |||
.Cm create | |||
.Op Fl v | |||
.Op Fl o Cm ro | wo | rw | |||
.Op Fl q Ar queue_size | |||
.Op Fl s Ar sectorsize | |||
.Op Fl t Ar timeout | |||
.Op Fl u Ar unit | |||
.Ar path | |||
.Nm | |||
.Cm attach | |||
.Op Fl v | |||
.Op Fl o Cm ro | wo | rw | |||
.Fl u Ar unit | |||
.Ar path | |||
.Nm | |||
.Cm destroy | |||
.Op Fl f | |||
.Fl u Ar unit | |||
.Nm | |||
.Cm list | |||
.Op Fl v | |||
.Op Fl u Ar unit | |||
.Sh DESCRIPTION | |||
The | |||
.Nm | |||
utility is a local GEOM Gate class consumer. | |||
It can be used as a replacement for | |||
.Xr md 4 | |||
devices or as a | |||
.Dq GEOMificator | |||
for non GEOM-aware devices, but it was mainly created as an example | |||
on how to use and how to communicate with the GEOM Gate kernel module. | |||
.Pp | |||
Available commands: | |||
.Bl -tag -width ".Cm destroy" | |||
.It Cm create | |||
Create a | |||
.Nm ggate | |||
provider related to the given regular file or device. | |||
.It Cm attach | |||
Attach a worker process to an existing | |||
.Nm ggate | |||
provider. | |||
.It Cm destroy | |||
Destroy the given | |||
.Nm ggate | |||
provider. | |||
.It Cm list | |||
List | |||
.Nm ggate | |||
providers. | |||
.El | |||
.Pp | |||
Available options: | |||
.Bl -tag -width ".Fl s Cm ro | wo | rw" | |||
.It Fl f | |||
Forcibly destroy | |||
.Nm ggate | |||
provider (cancels all pending requests). | |||
.It Fl o Cm ro | wo | rw | |||
Specify permission to use when opening the file or device: read-only | |||
.Pq Cm ro , | |||
write-only | |||
.Pq Cm wo , | |||
or read-write | |||
.Pq Cm rw . | |||
Default is | |||
.Cm rw . | |||
.It Fl q Ar queue_size | |||
Number of pending I/O requests that can be queued before they will | |||
start to be canceled. | |||
Default is 1024. | |||
.It Fl s Ar sectorsize | |||
Sector size for | |||
.Nm ggate | |||
provider. | |||
If not specified, it is taken from device, or set to 512 bytes for files. | |||
.It Fl t Ar timeout | |||
Number of seconds to wait before an I/O request will be canceled. | |||
0 means no timeout. | |||
Default is 30. | |||
.It Fl u Ar unit | |||
Unit number to use. | |||
.It Fl v | |||
Do not fork, run in foreground and print debug informations on standard | |||
output. | |||
.It Ar path | |||
Path to a regular file or device. | |||
.El | |||
.Sh EXIT STATUS | |||
Exit status is 0 on success, or 1 if the command fails. | |||
To get details about the failure, | |||
.Nm | |||
should be called with the | |||
.Fl v | |||
option. | |||
.Sh EXAMPLES | |||
.Dq GEOMify | |||
the | |||
.Dq Li fd0 | |||
device and use | |||
.Xr gbde 8 | |||
to encrypt data on a floppy. | |||
.Bd -literal -offset indent | |||
ggatel create -u 5 /dev/fd0 | |||
gbde init /dev/ggate5 | |||
gbde attach ggate5 | |||
newfs /dev/ggate5.bde | |||
mount /dev/ggate5.bde /secret | |||
cp /private/foo /secret/ | |||
umount /secret | |||
gbde detach ggate5 | |||
ggatel destroy -u 5 | |||
.Ed | |||
.Sh SEE ALSO | |||
.Xr geom 4 , | |||
.Xr gbde 8 , | |||
.Xr ggatec 8 , | |||
.Xr ggated 8 , | |||
.Xr mount 8 , | |||
.Xr newfs 8 | |||
.Sh AUTHORS | |||
The | |||
.Nm | |||
utility as well as this manual page was written by | |||
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org . |
@@ -1,336 +0,0 @@ | |||
/*- | |||
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* $FreeBSD$ | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <stdint.h> | |||
#include <fcntl.h> | |||
#include <unistd.h> | |||
#include <string.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <assert.h> | |||
#include <sys/param.h> | |||
#include <sys/time.h> | |||
#include <sys/bio.h> | |||
#include <sys/disk.h> | |||
#include <sys/ioctl.h> | |||
#include <sys/stat.h> | |||
#include <sys/syslog.h> | |||
#include <geom/gate/g_gate.h> | |||
#include "ggate.h" | |||
enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET; | |||
static const char *path = NULL; | |||
static int unit = G_GATE_UNIT_AUTO; | |||
static unsigned flags = 0; | |||
static int force = 0; | |||
static unsigned queue_size = G_GATE_QUEUE_SIZE; | |||
static unsigned sectorsize = 0; | |||
static unsigned timeout = G_GATE_TIMEOUT; | |||
static void | |||
usage(void) | |||
{ | |||
fprintf(stderr, "usage: %s create [-v] [-o <ro|wo|rw>] [-q queue_size] " | |||
"[-s sectorsize] [-t timeout] [-u unit] <path>\n", getprogname()); | |||
fprintf(stderr, " %s rescue [-v] [-o <ro|wo|rw>] <-u unit> " | |||
"<path>\n", getprogname()); | |||
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname()); | |||
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname()); | |||
exit(EXIT_FAILURE); | |||
} | |||
static int | |||
g_gate_openflags(unsigned ggflags) | |||
{ | |||
if ((ggflags & G_GATE_FLAG_READONLY) != 0) | |||
return (O_RDONLY); | |||
else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0) | |||
return (O_WRONLY); | |||
return (O_RDWR); | |||
} | |||
static void | |||
g_gatel_serve(int fd) | |||
{ | |||
struct g_gate_ctl_io ggio; | |||
size_t bsize; | |||
if (g_gate_verbose == 0) { | |||
if (daemon(0, 0) == -1) { | |||
g_gate_destroy(unit, 1); | |||
err(EXIT_FAILURE, "Cannot daemonize"); | |||
} | |||
} | |||
g_gate_log(LOG_DEBUG, "Worker created: %u.", getpid()); | |||
ggio.gctl_version = G_GATE_VERSION; | |||
ggio.gctl_unit = unit; | |||
bsize = sectorsize; | |||
ggio.gctl_data = malloc(bsize); | |||
for (;;) { | |||
int error; | |||
once_again: | |||
ggio.gctl_length = bsize; | |||
ggio.gctl_error = 0; | |||
g_gate_ioctl(G_GATE_CMD_START, &ggio); | |||
error = ggio.gctl_error; | |||
switch (error) { | |||
case 0: | |||
break; | |||
case ECANCELED: | |||
/* Exit gracefully. */ | |||
free(ggio.gctl_data); | |||
g_gate_close_device(); | |||
close(fd); | |||
exit(EXIT_SUCCESS); | |||
case ENOMEM: | |||
/* Buffer too small. */ | |||
assert(ggio.gctl_cmd == BIO_DELETE || | |||
ggio.gctl_cmd == BIO_WRITE); | |||
ggio.gctl_data = realloc(ggio.gctl_data, | |||
ggio.gctl_length); | |||
if (ggio.gctl_data != NULL) { | |||
bsize = ggio.gctl_length; | |||
goto once_again; | |||
} | |||
/* FALLTHROUGH */ | |||
case ENXIO: | |||
default: | |||
g_gate_xlog("ioctl(/dev/%s): %s.", G_GATE_CTL_NAME, | |||
strerror(error)); | |||
} | |||
error = 0; | |||
switch (ggio.gctl_cmd) { | |||
case BIO_READ: | |||
if ((size_t)ggio.gctl_length > bsize) { | |||
ggio.gctl_data = realloc(ggio.gctl_data, | |||
ggio.gctl_length); | |||
if (ggio.gctl_data != NULL) | |||
bsize = ggio.gctl_length; | |||
else | |||
error = ENOMEM; | |||
} | |||
if (error == 0) { | |||
if (pread(fd, ggio.gctl_data, ggio.gctl_length, | |||
ggio.gctl_offset) == -1) { | |||
error = errno; | |||
} | |||
} | |||
break; | |||
case BIO_DELETE: | |||
case BIO_WRITE: | |||
if (pwrite(fd, ggio.gctl_data, ggio.gctl_length, | |||
ggio.gctl_offset) == -1) { | |||
error = errno; | |||
} | |||
break; | |||
default: | |||
error = EOPNOTSUPP; | |||
} | |||
ggio.gctl_error = error; | |||
g_gate_ioctl(G_GATE_CMD_DONE, &ggio); | |||
} | |||
} | |||
static void | |||
g_gatel_create(void) | |||
{ | |||
struct g_gate_ctl_create ggioc; | |||
int fd; | |||
fd = open(path, g_gate_openflags(flags) | O_DIRECT | O_FSYNC); | |||
if (fd == -1) | |||
err(EXIT_FAILURE, "Cannot open %s", path); | |||
ggioc.gctl_version = G_GATE_VERSION; | |||
ggioc.gctl_unit = unit; | |||
ggioc.gctl_mediasize = g_gate_mediasize(fd); | |||
if (sectorsize == 0) | |||
sectorsize = g_gate_sectorsize(fd); | |||
ggioc.gctl_sectorsize = sectorsize; | |||
ggioc.gctl_timeout = timeout; | |||
ggioc.gctl_flags = flags; | |||
ggioc.gctl_maxcount = queue_size; | |||
strlcpy(ggioc.gctl_info, path, sizeof(ggioc.gctl_info)); | |||
g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc); | |||
if (unit == -1) | |||
printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit); | |||
unit = ggioc.gctl_unit; | |||
g_gatel_serve(fd); | |||
} | |||
static void | |||
g_gatel_rescue(void) | |||
{ | |||
struct g_gate_ctl_cancel ggioc; | |||
int fd; | |||
fd = open(path, g_gate_openflags(flags)); | |||
if (fd == -1) | |||
err(EXIT_FAILURE, "Cannot open %s", path); | |||
ggioc.gctl_version = G_GATE_VERSION; | |||
ggioc.gctl_unit = unit; | |||
ggioc.gctl_seq = 0; | |||
g_gate_ioctl(G_GATE_CMD_CANCEL, &ggioc); | |||
g_gatel_serve(fd); | |||
} | |||
int | |||
main(int argc, char *argv[]) | |||
{ | |||
if (argc < 2) | |||
usage(); | |||
if (strcasecmp(argv[1], "create") == 0) | |||
action = CREATE; | |||
else if (strcasecmp(argv[1], "rescue") == 0) | |||
action = RESCUE; | |||
else if (strcasecmp(argv[1], "destroy") == 0) | |||
action = DESTROY; | |||
else if (strcasecmp(argv[1], "list") == 0) | |||
action = LIST; | |||
else | |||
usage(); | |||
argc -= 1; | |||
argv += 1; | |||
for (;;) { | |||
int ch; | |||
ch = getopt(argc, argv, "fo:q:s:t:u:v"); | |||
if (ch == -1) | |||
break; | |||
switch (ch) { | |||
case 'f': | |||
if (action != DESTROY) | |||
usage(); | |||
force = 1; | |||
break; | |||
case 'o': | |||
if (action != CREATE && action != RESCUE) | |||
usage(); | |||
if (strcasecmp("ro", optarg) == 0) | |||
flags = G_GATE_FLAG_READONLY; | |||
else if (strcasecmp("wo", optarg) == 0) | |||
flags = G_GATE_FLAG_WRITEONLY; | |||
else if (strcasecmp("rw", optarg) == 0) | |||
flags = 0; | |||
else { | |||
errx(EXIT_FAILURE, | |||
"Invalid argument for '-o' option."); | |||
} | |||
break; | |||
case 'q': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
queue_size = strtoul(optarg, NULL, 10); | |||
if (queue_size == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid queue_size."); | |||
break; | |||
case 's': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
sectorsize = strtoul(optarg, NULL, 10); | |||
if (sectorsize == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid sectorsize."); | |||
break; | |||
case 't': | |||
if (action != CREATE) | |||
usage(); | |||
errno = 0; | |||
timeout = strtoul(optarg, NULL, 10); | |||
if (timeout == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid timeout."); | |||
break; | |||
case 'u': | |||
errno = 0; | |||
unit = strtol(optarg, NULL, 10); | |||
if (unit == 0 && errno != 0) | |||
errx(EXIT_FAILURE, "Invalid unit number."); | |||
break; | |||
case 'v': | |||
if (action == DESTROY) | |||
usage(); | |||
g_gate_verbose++; | |||
break; | |||
default: | |||
usage(); | |||
} | |||
} | |||
argc -= optind; | |||
argv += optind; | |||
switch (action) { | |||
case CREATE: | |||
if (argc != 1) | |||
usage(); | |||
g_gate_load_module(); | |||
g_gate_open_device(); | |||
path = argv[0]; | |||
g_gatel_create(); | |||
break; | |||
case RESCUE: | |||
if (argc != 1) | |||
usage(); | |||
if (unit == -1) { | |||
fprintf(stderr, "Required unit number.\n"); | |||
usage(); | |||
} | |||
g_gate_open_device(); | |||
path = argv[0]; | |||
g_gatel_rescue(); | |||
break; | |||
case DESTROY: | |||
if (unit == -1) { | |||
fprintf(stderr, "Required unit number.\n"); | |||
usage(); | |||
} | |||
g_gate_verbose = 1; | |||
g_gate_open_device(); | |||
g_gate_destroy(unit, force); | |||
break; | |||
case LIST: | |||
g_gate_list(unit, g_gate_verbose); | |||
break; | |||
case UNSET: | |||
default: | |||
usage(); | |||
} | |||
g_gate_close_device(); | |||
exit(EXIT_SUCCESS); | |||
} |
@@ -1,409 +0,0 @@ | |||
/*- | |||
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* $FreeBSD$ | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <unistd.h> | |||
#include <fcntl.h> | |||
#include <sys/param.h> | |||
#include <sys/disk.h> | |||
#include <sys/stat.h> | |||
#include <sys/endian.h> | |||
#include <sys/socket.h> | |||
#include <sys/linker.h> | |||
#include <sys/module.h> | |||
#include <netinet/in.h> | |||
#include <netinet/tcp.h> | |||
#include <arpa/inet.h> | |||
#include <signal.h> | |||
#include <err.h> | |||
#include <errno.h> | |||
#include <string.h> | |||
#include <strings.h> | |||
#include <libgen.h> | |||
#include <libutil.h> | |||
#include <netdb.h> | |||
#include <syslog.h> | |||
#include <stdarg.h> | |||
#include <stdint.h> | |||
#include <libgeom.h> | |||
#include <geom/gate/g_gate.h> | |||
#include "ggate.h" | |||
int g_gate_devfd = -1; | |||
int g_gate_verbose = 0; | |||
void | |||
g_gate_vlog(int priority, const char *message, va_list ap) | |||
{ | |||
if (g_gate_verbose) { | |||
const char *prefix; | |||
switch (priority) { | |||
case LOG_ERR: | |||
prefix = "error"; | |||
break; | |||
case LOG_WARNING: | |||
prefix = "warning"; | |||
break; | |||
case LOG_NOTICE: | |||
prefix = "notice"; | |||
break; | |||
case LOG_INFO: | |||
prefix = "info"; | |||
break; | |||
case LOG_DEBUG: | |||
prefix = "debug"; | |||
break; | |||
default: | |||
prefix = "unknown"; | |||
} | |||
printf("%s: ", prefix); | |||
vprintf(message, ap); | |||
printf("\n"); | |||
} else { | |||
if (priority != LOG_DEBUG) | |||
vsyslog(priority, message, ap); | |||
} | |||
} | |||
void | |||
g_gate_log(int priority, const char *message, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, message); | |||
g_gate_vlog(priority, message, ap); | |||
va_end(ap); | |||
} | |||
void | |||
g_gate_xvlog(const char *message, va_list ap) | |||
{ | |||
g_gate_vlog(LOG_ERR, message, ap); | |||
g_gate_vlog(LOG_ERR, "Exiting.", ap); | |||
exit(EXIT_FAILURE); | |||
} | |||
void | |||
g_gate_xlog(const char *message, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, message); | |||
g_gate_xvlog(message, ap); | |||
/* NOTREACHED */ | |||
va_end(ap); | |||
exit(EXIT_FAILURE); | |||
} | |||
off_t | |||
g_gate_mediasize(int fd) | |||
{ | |||
off_t mediasize; | |||
struct stat sb; | |||
if (fstat(fd, &sb) == -1) | |||
g_gate_xlog("fstat(): %s.", strerror(errno)); | |||
if (S_ISCHR(sb.st_mode)) { | |||
if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) { | |||
g_gate_xlog("Can't get media size: %s.", | |||
strerror(errno)); | |||
} | |||
} else if (S_ISREG(sb.st_mode)) { | |||
mediasize = sb.st_size; | |||
} else { | |||
g_gate_xlog("Unsupported file system object."); | |||
} | |||
return (mediasize); | |||
} | |||
unsigned | |||
g_gate_sectorsize(int fd) | |||
{ | |||
unsigned secsize; | |||
struct stat sb; | |||
if (fstat(fd, &sb) == -1) | |||
g_gate_xlog("fstat(): %s.", strerror(errno)); | |||
if (S_ISCHR(sb.st_mode)) { | |||
if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) { | |||
g_gate_xlog("Can't get sector size: %s.", | |||
strerror(errno)); | |||
} | |||
} else if (S_ISREG(sb.st_mode)) { | |||
secsize = 512; | |||
} else { | |||
g_gate_xlog("Unsupported file system object."); | |||
} | |||
return (secsize); | |||
} | |||
void | |||
g_gate_open_device(void) | |||
{ | |||
g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR); | |||
if (g_gate_devfd == -1) | |||
err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME); | |||
} | |||
void | |||
g_gate_close_device(void) | |||
{ | |||
close(g_gate_devfd); | |||
} | |||
void | |||
g_gate_ioctl(unsigned long req, void *data) | |||
{ | |||
if (ioctl(g_gate_devfd, req, data) == -1) { | |||
g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(), | |||
G_GATE_CTL_NAME, strerror(errno)); | |||
} | |||
} | |||
void | |||
g_gate_destroy(int unit, int force) | |||
{ | |||
struct g_gate_ctl_destroy ggio; | |||
ggio.gctl_version = G_GATE_VERSION; | |||
ggio.gctl_unit = unit; | |||
ggio.gctl_force = force; | |||
g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio); | |||
} | |||
void | |||
g_gate_load_module(void) | |||
{ | |||
if (modfind("g_gate") == -1) { | |||
/* Not present in kernel, try loading it. */ | |||
if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) { | |||
if (errno != EEXIST) { | |||
errx(EXIT_FAILURE, | |||
"geom_gate module not available!"); | |||
} | |||
} | |||
} | |||
} | |||
/* | |||
* When we send from ggatec packets larger than 32kB, performance drops | |||
* significantly (eg. to 256kB/s over 1Gbit/s link). This is not a problem | |||
* when data is send from ggated. I don't know why, so for now I limit | |||
* size of packets send from ggatec to 32kB by defining MAX_SEND_SIZE | |||
* in ggatec Makefile. | |||
*/ | |||
#ifndef MAX_SEND_SIZE | |||
#define MAX_SEND_SIZE MAXPHYS | |||
#endif | |||
ssize_t | |||
g_gate_send(int s, const void *buf, size_t len, int flags) | |||
{ | |||
ssize_t done = 0, done2; | |||
const unsigned char *p = buf; | |||
while (len > 0) { | |||
done2 = send(s, p, MIN(len, MAX_SEND_SIZE), flags); | |||
if (done2 == 0) | |||
break; | |||
else if (done2 == -1) { | |||
if (errno == EAGAIN) { | |||
printf("%s: EAGAIN\n", __func__); | |||
continue; | |||
} | |||
done = -1; | |||
break; | |||
} | |||
done += done2; | |||
p += done2; | |||
len -= done2; | |||
} | |||
return (done); | |||
} | |||
ssize_t | |||
g_gate_recv(int s, void *buf, size_t len, int flags) | |||
{ | |||
ssize_t done; | |||
do { | |||
done = recv(s, buf, len, flags); | |||
} while (done == -1 && errno == EAGAIN); | |||
return (done); | |||
} | |||
int nagle = 1; | |||
unsigned rcvbuf = G_GATE_RCVBUF; | |||
unsigned sndbuf = G_GATE_SNDBUF; | |||
void | |||
g_gate_socket_settings(int sfd) | |||
{ | |||
struct timeval tv; | |||
int bsize, on; | |||
/* Socket settings. */ | |||
on = 1; | |||
if (nagle) { | |||
if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on, | |||
sizeof(on)) == -1) { | |||
g_gate_xlog("setsockopt() error: %s.", strerror(errno)); | |||
} | |||
} | |||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) | |||
g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno)); | |||
bsize = rcvbuf; | |||
if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1) | |||
g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno)); | |||
bsize = sndbuf; | |||
if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1) | |||
g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno)); | |||
tv.tv_sec = 8; | |||
tv.tv_usec = 0; | |||
if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { | |||
g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.", | |||
strerror(errno)); | |||
} | |||
if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { | |||
g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.", | |||
strerror(errno)); | |||
} | |||
} | |||
#ifdef LIBGEOM | |||
static struct gclass * | |||
find_class(struct gmesh *mesh, const char *name) | |||
{ | |||
struct gclass *class; | |||
LIST_FOREACH(class, &mesh->lg_class, lg_class) { | |||
if (strcmp(class->lg_name, name) == 0) | |||
return (class); | |||
} | |||
return (NULL); | |||
} | |||
static const char * | |||
get_conf(struct ggeom *gp, const char *name) | |||
{ | |||
struct gconfig *conf; | |||
LIST_FOREACH(conf, &gp->lg_config, lg_config) { | |||
if (strcmp(conf->lg_name, name) == 0) | |||
return (conf->lg_val); | |||
} | |||
return (NULL); | |||
} | |||
static void | |||
show_config(struct ggeom *gp, int verbose) | |||
{ | |||
struct gprovider *pp; | |||
char buf[5]; | |||
pp = LIST_FIRST(&gp->lg_provider); | |||
if (pp == NULL) | |||
return; | |||
if (!verbose) { | |||
printf("%s\n", pp->lg_name); | |||
return; | |||
} | |||
printf(" NAME: %s\n", pp->lg_name); | |||
printf(" info: %s\n", get_conf(gp, "info")); | |||
printf(" access: %s\n", get_conf(gp, "access")); | |||
printf(" timeout: %s\n", get_conf(gp, "timeout")); | |||
printf("queue_count: %s\n", get_conf(gp, "queue_count")); | |||
printf(" queue_size: %s\n", get_conf(gp, "queue_size")); | |||
printf(" references: %s\n", get_conf(gp, "ref")); | |||
humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "", | |||
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); | |||
printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf); | |||
printf(" sectorsize: %u\n", pp->lg_sectorsize); | |||
printf(" mode: %s\n", pp->lg_mode); | |||
printf("\n"); | |||
} | |||
void | |||
g_gate_list(int unit, int verbose) | |||
{ | |||
struct gmesh mesh; | |||
struct gclass *class; | |||
struct ggeom *gp; | |||
char name[64]; | |||
int error; | |||
error = geom_gettree(&mesh); | |||
if (error != 0) | |||
exit(EXIT_FAILURE); | |||
class = find_class(&mesh, G_GATE_CLASS_NAME); | |||
if (class == NULL) { | |||
geom_deletetree(&mesh); | |||
exit(EXIT_SUCCESS); | |||
} | |||
if (unit >= 0) { | |||
snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME, | |||
unit); | |||
} | |||
LIST_FOREACH(gp, &class->lg_geom, lg_geom) { | |||
if (unit != -1 && strcmp(gp->lg_name, name) != 0) | |||
continue; | |||
show_config(gp, verbose); | |||
} | |||
geom_deletetree(&mesh); | |||
exit(EXIT_SUCCESS); | |||
} | |||
#endif /* LIBGEOM */ | |||
in_addr_t | |||
g_gate_str2ip(const char *str) | |||
{ | |||
struct hostent *hp; | |||
in_addr_t ip; | |||
ip = inet_addr(str); | |||
if (ip != INADDR_NONE) { | |||
/* It is a valid IP address. */ | |||
return (ip); | |||
} | |||
/* Check if it is a valid host name. */ | |||
hp = gethostbyname(str); | |||
if (hp == NULL) | |||
return (INADDR_NONE); | |||
return (((struct in_addr *)(void *)hp->h_addr)->s_addr); | |||
} |
@@ -1,196 +0,0 @@ | |||
/*- | |||
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* $FreeBSD$ | |||
*/ | |||
#ifndef _GGATE_H_ | |||
#define _GGATE_H_ | |||
#include <sys/endian.h> | |||
#include <stdarg.h> | |||
#define G_GATE_PORT 3080 | |||
#define G_GATE_RCVBUF 131072 | |||
#define G_GATE_SNDBUF 131072 | |||
#define G_GATE_QUEUE_SIZE 1024 | |||
#define G_GATE_TIMEOUT 0 | |||
#define GGATE_MAGIC "GEOM_GATE " | |||
#define GGATE_VERSION 0 | |||
#define GGATE_FLAG_RDONLY 0x0001 | |||
#define GGATE_FLAG_WRONLY 0x0002 | |||
/* | |||
* If GGATE_FLAG_SEND not GGATE_FLAG_RECV flag is set, this is initial | |||
* connection. | |||
* If GGATE_FLAG_SEND flag is set - this is socket to send data. | |||
* If GGATE_FLAG_RECV flag is set - this is socket to receive data. | |||
*/ | |||
#define GGATE_FLAG_SEND 0x0004 | |||
#define GGATE_FLAG_RECV 0x0008 | |||
#define GGATE_CMD_READ 0 | |||
#define GGATE_CMD_WRITE 1 | |||
extern int g_gate_devfd; | |||
extern int g_gate_verbose; | |||
extern int nagle; | |||
extern unsigned rcvbuf, sndbuf; | |||
struct g_gate_version { | |||
char gv_magic[16]; | |||
uint16_t gv_version; | |||
uint16_t gv_error; | |||
} __packed; | |||
/* Client's initial packet. */ | |||
struct g_gate_cinit { | |||
char gc_path[PATH_MAX + 1]; | |||
uint64_t gc_flags; | |||
uint16_t gc_nconn; | |||
uint32_t gc_token; | |||
} __packed; | |||
/* Server's initial packet. */ | |||
struct g_gate_sinit { | |||
uint8_t gs_flags; | |||
uint64_t gs_mediasize; | |||
uint32_t gs_sectorsize; | |||
uint16_t gs_error; | |||
} __packed; | |||
/* Control struct. */ | |||
struct g_gate_hdr { | |||
uint8_t gh_cmd; /* command */ | |||
uint64_t gh_offset; /* device offset */ | |||
uint32_t gh_length; /* size of block */ | |||
uint64_t gh_seq; /* request number */ | |||
uint16_t gh_error; /* error value (0 if ok) */ | |||
} __packed; | |||
void g_gate_vlog(int priority, const char *message, va_list ap); | |||
void g_gate_log(int priority, const char *message, ...); | |||
void g_gate_xvlog(const char *message, va_list ap); | |||
void g_gate_xlog(const char *message, ...); | |||
off_t g_gate_mediasize(int fd); | |||
unsigned g_gate_sectorsize(int fd); | |||
void g_gate_open_device(void); | |||
void g_gate_close_device(void); | |||
void g_gate_ioctl(unsigned long req, void *data); | |||
void g_gate_destroy(int unit, int force); | |||
void g_gate_load_module(void); | |||
ssize_t g_gate_recv(int s, void *buf, size_t len, int flags); | |||
ssize_t g_gate_send(int s, const void *buf, size_t len, int flags); | |||
void g_gate_socket_settings(int sfd); | |||
#ifdef LIBGEOM | |||
void g_gate_list(int unit, int verbose); | |||
#endif | |||
in_addr_t g_gate_str2ip(const char *str); | |||
/* | |||
* g_gate_swap2h_* - functions swap bytes to host byte order (from big endian). | |||
* g_gate_swap2n_* - functions swap bytes to network byte order (actually | |||
* to big endian byte order). | |||
*/ | |||
static __inline void | |||
g_gate_swap2h_version(struct g_gate_version *ver) | |||
{ | |||
ver->gv_version = be16toh(ver->gv_version); | |||
ver->gv_error = be16toh(ver->gv_error); | |||
} | |||
static __inline void | |||
g_gate_swap2n_version(struct g_gate_version *ver) | |||
{ | |||
ver->gv_version = htobe16(ver->gv_version); | |||
ver->gv_error = htobe16(ver->gv_error); | |||
} | |||
static __inline void | |||
g_gate_swap2h_cinit(struct g_gate_cinit *cinit) | |||
{ | |||
cinit->gc_flags = be64toh(cinit->gc_flags); | |||
cinit->gc_nconn = be16toh(cinit->gc_nconn); | |||
cinit->gc_token = be32toh(cinit->gc_token); | |||
} | |||
static __inline void | |||
g_gate_swap2n_cinit(struct g_gate_cinit *cinit) | |||
{ | |||
cinit->gc_flags = htobe64(cinit->gc_flags); | |||
cinit->gc_nconn = htobe16(cinit->gc_nconn); | |||
cinit->gc_token = htobe32(cinit->gc_token); | |||
} | |||
static __inline void | |||
g_gate_swap2h_sinit(struct g_gate_sinit *sinit) | |||
{ | |||
/* Swap only used fields. */ | |||
sinit->gs_mediasize = be64toh(sinit->gs_mediasize); | |||
sinit->gs_sectorsize = be32toh(sinit->gs_sectorsize); | |||
sinit->gs_error = be16toh(sinit->gs_error); | |||
} | |||
static __inline void | |||
g_gate_swap2n_sinit(struct g_gate_sinit *sinit) | |||
{ | |||
/* Swap only used fields. */ | |||
sinit->gs_mediasize = htobe64(sinit->gs_mediasize); | |||
sinit->gs_sectorsize = htobe32(sinit->gs_sectorsize); | |||
sinit->gs_error = htobe16(sinit->gs_error); | |||
} | |||
static __inline void | |||
g_gate_swap2h_hdr(struct g_gate_hdr *hdr) | |||
{ | |||
/* Swap only used fields. */ | |||
hdr->gh_offset = be64toh(hdr->gh_offset); | |||
hdr->gh_length = be32toh(hdr->gh_length); | |||
hdr->gh_seq = be64toh(hdr->gh_seq); | |||
hdr->gh_error = be16toh(hdr->gh_error); | |||
} | |||
static __inline void | |||
g_gate_swap2n_hdr(struct g_gate_hdr *hdr) | |||
{ | |||
/* Swap only used fields. */ | |||
hdr->gh_offset = htobe64(hdr->gh_offset); | |||
hdr->gh_length = htobe32(hdr->gh_length); | |||
hdr->gh_seq = htobe64(hdr->gh_seq); | |||
hdr->gh_error = htobe16(hdr->gh_error); | |||
} | |||
#endif /* _GGATE_H_ */ |