diff --git a/Makefile b/Makefile deleted file mode 100644 index 8f889f1..0000000 --- a/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD$ - -.include - -SUBDIR= ${_ggatec} \ - ${_ggated} \ - ggatel - -.if ${MK_LIBTHR} != "no" -_ggatec= ggatec -_ggated= ggated -.endif - -.include diff --git a/Makefile.inc b/Makefile.inc deleted file mode 100644 index 265f86d..0000000 --- a/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -# $FreeBSD$ - -.include "../Makefile.inc" diff --git a/ggatec/Makefile b/ggatec/Makefile deleted file mode 100644 index 4d8917f..0000000 --- a/ggatec/Makefile +++ /dev/null @@ -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 diff --git a/ggatec/ggatec.8 b/ggatec/ggatec.8 deleted file mode 100644 index 09f0444..0000000 --- a/ggatec/ggatec.8 +++ /dev/null @@ -1,181 +0,0 @@ -.\" Copyright (c) 2004 Pawel Jakub Dawidek -.\" 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 . diff --git a/ggatec/ggatec.c b/ggatec/ggatec.c deleted file mode 100644 index 660bd8a..0000000 --- a/ggatec/ggatec.c +++ /dev/null @@ -1,642 +0,0 @@ -/*- - * Copyright (c) 2004 Pawel Jakub Dawidek - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#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 ] [-p port] " - "[-q queue_size] [-R rcvbuf] [-S sndbuf] [-s sectorsize] " - "[-t timeout] [-u unit] \n", getprogname()); - fprintf(stderr, " %s rescue [-nv] [-o ] [-p port] " - "[-R rcvbuf] [-S sndbuf] <-u unit> \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); -} diff --git a/ggated/Makefile b/ggated/Makefile deleted file mode 100644 index 4e7708e..0000000 --- a/ggated/Makefile +++ /dev/null @@ -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 diff --git a/ggated/ggated.8 b/ggated/ggated.8 deleted file mode 100644 index 3024a04..0000000 --- a/ggated/ggated.8 +++ /dev/null @@ -1,111 +0,0 @@ -.\" Copyright (c) 2004 Pawel Jakub Dawidek -.\" 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 . diff --git a/ggated/ggated.c b/ggated/ggated.c deleted file mode 100644 index 2997a9c..0000000 --- a/ggated/ggated.c +++ /dev/null @@ -1,1050 +0,0 @@ -/*- - * Copyright (c) 2004 Pawel Jakub Dawidek - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ggate.h" - - -#define GGATED_EXPORT_FILE "/etc/gg.exports" - -struct ggd_connection { - off_t c_mediasize; - unsigned c_sectorsize; - unsigned c_flags; /* flags (RO/RW) */ - int c_diskfd; - int c_sendfd; - int c_recvfd; - time_t c_birthtime; - char *c_path; - uint64_t c_token; - in_addr_t c_srcip; - LIST_ENTRY(ggd_connection) c_next; -}; - -struct ggd_request { - struct g_gate_hdr r_hdr; - char *r_data; - TAILQ_ENTRY(ggd_request) r_next; -}; -#define r_cmd r_hdr.gh_cmd -#define r_offset r_hdr.gh_offset -#define r_length r_hdr.gh_length -#define r_error r_hdr.gh_error - -struct ggd_export { - char *e_path; /* path to device/file */ - in_addr_t e_ip; /* remote IP address */ - in_addr_t e_mask; /* IP mask */ - unsigned e_flags; /* flags (RO/RW) */ - SLIST_ENTRY(ggd_export) e_next; -}; - -static const char *exports_file = GGATED_EXPORT_FILE; -static int got_sighup = 0; -in_addr_t bindaddr; - -static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); -static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); -pthread_mutex_t inqueue_mtx, outqueue_mtx; -pthread_cond_t inqueue_cond, outqueue_cond; - -static SLIST_HEAD(, ggd_export) exports = SLIST_HEAD_INITIALIZER(exports); -static LIST_HEAD(, ggd_connection) connections = LIST_HEAD_INITIALIZER(connections); - -static void *recv_thread(void *arg); -static void *disk_thread(void *arg); -static void *send_thread(void *arg); - -static void -usage(void) -{ - - fprintf(stderr, "usage: %s [-nv] [-a address] [-p port] [-R rcvbuf] " - "[-S sndbuf] [exports file]\n", getprogname()); - exit(EXIT_FAILURE); -} - -static char * -ip2str(in_addr_t ip) -{ - static char sip[16]; - - snprintf(sip, sizeof(sip), "%u.%u.%u.%u", - ((ip >> 24) & 0xff), - ((ip >> 16) & 0xff), - ((ip >> 8) & 0xff), - (ip & 0xff)); - return (sip); -} - -static in_addr_t -countmask(unsigned m) -{ - in_addr_t mask; - - if (m == 0) { - mask = 0x0; - } else { - mask = 1 << (32 - m); - mask--; - mask = ~mask; - } - return (mask); -} - -static void -line_parse(char *line, unsigned lineno) -{ - struct ggd_export *ex; - char *word, *path, *sflags; - unsigned flags, i, vmask; - in_addr_t ip, mask; - - ip = mask = flags = vmask = 0; - path = NULL; - sflags = NULL; - - for (i = 0, word = strtok(line, " \t"); word != NULL; - i++, word = strtok(NULL, " \t")) { - switch (i) { - case 0: /* IP address or host name */ - ip = g_gate_str2ip(strsep(&word, "/")); - if (ip == INADDR_NONE) { - g_gate_xlog("Invalid IP/host name at line %u.", - lineno); - } - ip = ntohl(ip); - if (word == NULL) - vmask = 32; - else { - errno = 0; - vmask = strtoul(word, NULL, 10); - if (vmask == 0 && errno != 0) { - g_gate_xlog("Invalid IP mask value at " - "line %u.", lineno); - } - if ((unsigned)vmask > 32) { - g_gate_xlog("Invalid IP mask value at line %u.", - lineno); - } - } - mask = countmask(vmask); - break; - case 1: /* flags */ - if (strcasecmp("rd", word) == 0 || - strcasecmp("ro", word) == 0) { - flags = O_RDONLY; - } else if (strcasecmp("wo", word) == 0) { - flags = O_WRONLY; - } else if (strcasecmp("rw", word) == 0) { - flags = O_RDWR; - } else { - g_gate_xlog("Invalid value in flags field at " - "line %u.", lineno); - } - sflags = word; - break; - case 2: /* path */ - if (strlen(word) >= MAXPATHLEN) { - g_gate_xlog("Path too long at line %u. ", - lineno); - } - path = word; - break; - default: - g_gate_xlog("Too many arguments at line %u. ", lineno); - } - } - if (i != 3) - g_gate_xlog("Too few arguments at line %u.", lineno); - - ex = malloc(sizeof(*ex)); - if (ex == NULL) - g_gate_xlog("Not enough memory."); - ex->e_path = strdup(path); - if (ex->e_path == NULL) - g_gate_xlog("Not enough memory."); - - /* Made 'and' here. */ - ex->e_ip = (ip & mask); - ex->e_mask = mask; - ex->e_flags = flags; - - SLIST_INSERT_HEAD(&exports, ex, e_next); - - g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", - ip2str(ex->e_ip), vmask, path, sflags); -} - -static void -exports_clear(void) -{ - struct ggd_export *ex; - - while (!SLIST_EMPTY(&exports)) { - ex = SLIST_FIRST(&exports); - SLIST_REMOVE_HEAD(&exports, e_next); - free(ex); - } -} - -#define EXPORTS_LINE_SIZE 2048 -static void -exports_get(void) -{ - char buf[EXPORTS_LINE_SIZE], *line; - unsigned lineno = 0, objs = 0, len; - FILE *fd; - - exports_clear(); - - fd = fopen(exports_file, "r"); - if (fd == NULL) { - g_gate_xlog("Cannot open exports file (%s): %s.", exports_file, - strerror(errno)); - } - - g_gate_log(LOG_INFO, "Reading exports file (%s).", exports_file); - - for (;;) { - if (fgets(buf, sizeof(buf), fd) == NULL) { - if (feof(fd)) - break; - - g_gate_xlog("Error while reading exports file: %s.", - strerror(errno)); - } - - /* Increase line count. */ - lineno++; - - /* Skip spaces and tabs. */ - for (line = buf; *line == ' ' || *line == '\t'; ++line) - ; - - /* Empty line, comment or empty line at the end of file. */ - if (*line == '\n' || *line == '#' || *line == '\0') - continue; - - len = strlen(line); - if (line[len - 1] == '\n') { - /* Remove new line char. */ - line[len - 1] = '\0'; - } else { - if (!feof(fd)) - g_gate_xlog("Line %u too long.", lineno); - } - - line_parse(line, lineno); - objs++; - } - - fclose(fd); - - if (objs == 0) - g_gate_xlog("There are no objects to export."); - - g_gate_log(LOG_INFO, "Exporting %u object(s).", objs); -} - -static int -exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, - struct ggd_connection *conn) -{ - char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */ - int error = 0, flags; - - strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask)); - strlcat(ipmask, "/", sizeof(ipmask)); - strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask)); - if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { - if (ex->e_flags == O_WRONLY) { - g_gate_log(LOG_WARNING, "Read-only access requested, " - "but %s (%s) is exported write-only.", ex->e_path, - ipmask); - return (EPERM); - } else { - conn->c_flags |= GGATE_FLAG_RDONLY; - } - } else if ((cinit->gc_flags & GGATE_FLAG_WRONLY) != 0) { - if (ex->e_flags == O_RDONLY) { - g_gate_log(LOG_WARNING, "Write-only access requested, " - "but %s (%s) is exported read-only.", ex->e_path, - ipmask); - return (EPERM); - } else { - conn->c_flags |= GGATE_FLAG_WRONLY; - } - } else { - if (ex->e_flags == O_RDONLY) { - g_gate_log(LOG_WARNING, "Read-write access requested, " - "but %s (%s) is exported read-only.", ex->e_path, - ipmask); - return (EPERM); - } else if (ex->e_flags == O_WRONLY) { - g_gate_log(LOG_WARNING, "Read-write access requested, " - "but %s (%s) is exported write-only.", ex->e_path, - ipmask); - return (EPERM); - } - } - if ((conn->c_flags & GGATE_FLAG_RDONLY) != 0) - flags = O_RDONLY; - else if ((conn->c_flags & GGATE_FLAG_WRONLY) != 0) - flags = O_WRONLY; - else - flags = O_RDWR; - conn->c_diskfd = open(ex->e_path, flags); - if (conn->c_diskfd == -1) { - error = errno; - g_gate_log(LOG_ERR, "Cannot open %s: %s.", ex->e_path, - strerror(error)); - return (error); - } - return (0); -} - -static struct ggd_export * -exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, - struct ggd_connection *conn) -{ - struct ggd_export *ex; - in_addr_t ip; - int error; - - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); - SLIST_FOREACH(ex, &exports, e_next) { - if ((ip & ex->e_mask) != ex->e_ip) { - g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", - ex->e_path); - continue; - } - if (strcmp(cinit->gc_path, ex->e_path) != 0) { - g_gate_log(LOG_DEBUG, "exports[%s]: Path mismatch.", - ex->e_path); - continue; - } - error = exports_check(ex, cinit, conn); - if (error == 0) - return (ex); - else { - errno = error; - return (NULL); - } - } - g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", - ip2str(ip)); - errno = EPERM; - return (NULL); -} - -/* - * Remove timed out connections. - */ -static void -connection_cleanups(void) -{ - struct ggd_connection *conn, *tconn; - time_t now; - - time(&now); - LIST_FOREACH_SAFE(conn, &connections, c_next, tconn) { - if (now - conn->c_birthtime > 10) { - LIST_REMOVE(conn, c_next); - g_gate_log(LOG_NOTICE, - "Connection from %s [%s] removed.", - ip2str(conn->c_srcip), conn->c_path); - close(conn->c_diskfd); - close(conn->c_sendfd); - close(conn->c_recvfd); - free(conn->c_path); - free(conn); - } - } -} - -static struct ggd_connection * -connection_find(struct g_gate_cinit *cinit) -{ - struct ggd_connection *conn; - - LIST_FOREACH(conn, &connections, c_next) { - if (conn->c_token == cinit->gc_token) - break; - } - return (conn); -} - -static struct ggd_connection * -connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) -{ - struct ggd_connection *conn; - in_addr_t ip; - - /* - * First, look for old connections. - * We probably should do it every X seconds, but what for? - * It is only dangerous if an attacker wants to overload connections - * queue, so here is a good place to do the cleanups. - */ - connection_cleanups(); - - conn = malloc(sizeof(*conn)); - if (conn == NULL) - return (NULL); - conn->c_path = strdup(cinit->gc_path); - if (conn->c_path == NULL) { - free(conn); - return (NULL); - } - conn->c_token = cinit->gc_token; - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); - conn->c_srcip = ip; - conn->c_sendfd = conn->c_recvfd = -1; - if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) - conn->c_sendfd = sfd; - else - conn->c_recvfd = sfd; - conn->c_mediasize = 0; - conn->c_sectorsize = 0; - time(&conn->c_birthtime); - conn->c_flags = cinit->gc_flags; - LIST_INSERT_HEAD(&connections, conn, c_next); - g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(ip), - conn->c_path); - return (conn); -} - -static int -connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, - struct sockaddr *s, int sfd) -{ - in_addr_t ip; - - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); - if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) { - if (conn->c_sendfd != -1) { - g_gate_log(LOG_WARNING, - "Send socket already exists [%s, %s].", ip2str(ip), - conn->c_path); - return (EEXIST); - } - conn->c_sendfd = sfd; - } else { - if (conn->c_recvfd != -1) { - g_gate_log(LOG_WARNING, - "Receive socket already exists [%s, %s].", - ip2str(ip), conn->c_path); - return (EEXIST); - } - conn->c_recvfd = sfd; - } - g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(ip), - conn->c_path); - return (0); -} - -/* - * Remove one socket from the given connection or the whole - * connection if sfd == -1. - */ -static void -connection_remove(struct ggd_connection *conn) -{ - - LIST_REMOVE(conn, c_next); - g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", - ip2str(conn->c_srcip), conn->c_path); - if (conn->c_sendfd != -1) - close(conn->c_sendfd); - if (conn->c_recvfd != -1) - close(conn->c_recvfd); - free(conn->c_path); - free(conn); -} - -static int -connection_ready(struct ggd_connection *conn) -{ - - return (conn->c_sendfd != -1 && conn->c_recvfd != -1); -} - -static void -connection_launch(struct ggd_connection *conn) -{ - pthread_t td; - int error, pid; - - pid = fork(); - if (pid > 0) - return; - else if (pid == -1) { - g_gate_log(LOG_ERR, "Cannot fork: %s.", strerror(errno)); - return; - } - g_gate_log(LOG_DEBUG, "Process created [%s].", conn->c_path); - - /* - * Create condition variables and mutexes for in-queue and out-queue - * synchronization. - */ - error = pthread_mutex_init(&inqueue_mtx, NULL); - if (error != 0) { - g_gate_xlog("pthread_mutex_init(inqueue_mtx): %s.", - strerror(error)); - } - error = pthread_cond_init(&inqueue_cond, NULL); - if (error != 0) { - g_gate_xlog("pthread_cond_init(inqueue_cond): %s.", - strerror(error)); - } - error = pthread_mutex_init(&outqueue_mtx, NULL); - if (error != 0) { - g_gate_xlog("pthread_mutex_init(outqueue_mtx): %s.", - strerror(error)); - } - error = pthread_cond_init(&outqueue_cond, NULL); - if (error != 0) { - g_gate_xlog("pthread_cond_init(outqueue_cond): %s.", - strerror(error)); - } - - /* - * Create threads: - * recvtd - thread for receiving I/O request - * diskio - thread for doing I/O request - * sendtd - thread for sending I/O requests back - */ - error = pthread_create(&td, NULL, send_thread, conn); - if (error != 0) { - g_gate_xlog("pthread_create(send_thread): %s.", - strerror(error)); - } - error = pthread_create(&td, NULL, recv_thread, conn); - if (error != 0) { - g_gate_xlog("pthread_create(recv_thread): %s.", - strerror(error)); - } - disk_thread(conn); -} - -static void -sendfail(int sfd, int error, const char *fmt, ...) -{ - struct g_gate_sinit sinit; - va_list ap; - ssize_t data; - - sinit.gs_error = error; - g_gate_swap2n_sinit(&sinit); - data = g_gate_send(sfd, &sinit, sizeof(sinit), 0); - g_gate_swap2h_sinit(&sinit); - if (data != sizeof(sinit)) { - g_gate_log(LOG_WARNING, "Cannot send initial packet: %s.", - strerror(errno)); - return; - } - if (fmt != NULL) { - va_start(ap, fmt); - g_gate_vlog(LOG_WARNING, fmt, ap); - va_end(ap); - } -} - -static void * -malloc_waitok(size_t size) -{ - void *p; - - while ((p = malloc(size)) == NULL) { - g_gate_log(LOG_DEBUG, "Cannot allocate %zu bytes.", size); - sleep(1); - } - return (p); -} - -static void * -recv_thread(void *arg) -{ - struct ggd_connection *conn; - struct ggd_request *req; - ssize_t data; - int error, fd; - - conn = arg; - g_gate_log(LOG_NOTICE, "%s: started [%s]!", __func__, conn->c_path); - fd = conn->c_recvfd; - for (;;) { - /* - * Get header packet. - */ - req = malloc_waitok(sizeof(*req)); - data = g_gate_recv(fd, &req->r_hdr, sizeof(req->r_hdr), - MSG_WAITALL); - if (data == 0) { - g_gate_log(LOG_DEBUG, "Process %u exiting.", getpid()); - exit(EXIT_SUCCESS); - } else if (data == -1) { - g_gate_xlog("Error while receiving hdr packet: %s.", - strerror(errno)); - } else if (data != sizeof(req->r_hdr)) { - g_gate_xlog("Malformed hdr packet received."); - } - g_gate_log(LOG_DEBUG, "Received hdr packet."); - g_gate_swap2h_hdr(&req->r_hdr); - - g_gate_log(LOG_DEBUG, "%s: offset=%jd length=%u", __func__, - (intmax_t)req->r_offset, (unsigned)req->r_length); - - /* - * Allocate memory for data. - */ - req->r_data = malloc_waitok(req->r_length); - - /* - * Receive data to write for WRITE request. - */ - if (req->r_cmd == GGATE_CMD_WRITE) { - g_gate_log(LOG_DEBUG, "Waiting for %u bytes of data...", - req->r_length); - data = g_gate_recv(fd, req->r_data, req->r_length, - MSG_WAITALL); - if (data == -1) { - g_gate_xlog("Error while receiving data: %s.", - strerror(errno)); - } - } - - /* - * Put the request onto the incoming queue. - */ - error = pthread_mutex_lock(&inqueue_mtx); - assert(error == 0); - TAILQ_INSERT_TAIL(&inqueue, req, r_next); - error = pthread_cond_signal(&inqueue_cond); - assert(error == 0); - error = pthread_mutex_unlock(&inqueue_mtx); - assert(error == 0); - } -} - -static void * -disk_thread(void *arg) -{ - struct ggd_connection *conn; - struct ggd_request *req; - ssize_t data; - int error, fd; - - conn = arg; - g_gate_log(LOG_NOTICE, "%s: started [%s]!", __func__, conn->c_path); - fd = conn->c_diskfd; - for (;;) { - /* - * Get a request from the incoming queue. - */ - error = pthread_mutex_lock(&inqueue_mtx); - assert(error == 0); - while ((req = TAILQ_FIRST(&inqueue)) == NULL) { - error = pthread_cond_wait(&inqueue_cond, &inqueue_mtx); - assert(error == 0); - } - TAILQ_REMOVE(&inqueue, req, r_next); - error = pthread_mutex_unlock(&inqueue_mtx); - assert(error == 0); - - /* - * Check the request. - */ - assert(req->r_cmd == GGATE_CMD_READ || req->r_cmd == GGATE_CMD_WRITE); - assert(req->r_offset + req->r_length <= (uintmax_t)conn->c_mediasize); - assert((req->r_offset % conn->c_sectorsize) == 0); - assert((req->r_length % conn->c_sectorsize) == 0); - - g_gate_log(LOG_DEBUG, "%s: offset=%jd length=%u", __func__, - (intmax_t)req->r_offset, (unsigned)req->r_length); - - /* - * Do the request. - */ - data = 0; - switch (req->r_cmd) { - case GGATE_CMD_READ: - data = pread(fd, req->r_data, req->r_length, - req->r_offset); - break; - case GGATE_CMD_WRITE: - data = pwrite(fd, req->r_data, req->r_length, - req->r_offset); - /* Free data memory here - better sooner. */ - free(req->r_data); - req->r_data = NULL; - break; - } - if (data != (ssize_t)req->r_length) { - /* Report short reads/writes as I/O errors. */ - if (errno == 0) - errno = EIO; - g_gate_log(LOG_ERR, "Disk error: %s", strerror(errno)); - req->r_error = errno; - if (req->r_data != NULL) { - free(req->r_data); - req->r_data = NULL; - } - } - - /* - * Put the request onto the outgoing queue. - */ - error = pthread_mutex_lock(&outqueue_mtx); - assert(error == 0); - TAILQ_INSERT_TAIL(&outqueue, req, r_next); - error = pthread_cond_signal(&outqueue_cond); - assert(error == 0); - error = pthread_mutex_unlock(&outqueue_mtx); - assert(error == 0); - } - - /* NOTREACHED */ - return (NULL); -} - -static void * -send_thread(void *arg) -{ - struct ggd_connection *conn; - struct ggd_request *req; - ssize_t data; - int error, fd; - - conn = arg; - g_gate_log(LOG_NOTICE, "%s: started [%s]!", __func__, conn->c_path); - fd = conn->c_sendfd; - for (;;) { - /* - * Get a request from the outgoing queue. - */ - error = pthread_mutex_lock(&outqueue_mtx); - assert(error == 0); - while ((req = TAILQ_FIRST(&outqueue)) == NULL) { - error = pthread_cond_wait(&outqueue_cond, - &outqueue_mtx); - assert(error == 0); - } - TAILQ_REMOVE(&outqueue, req, r_next); - error = pthread_mutex_unlock(&outqueue_mtx); - assert(error == 0); - - g_gate_log(LOG_DEBUG, "%s: offset=%jd length=%u", __func__, - (intmax_t)req->r_offset, (unsigned)req->r_length); - - /* - * Send the request. - */ - g_gate_swap2n_hdr(&req->r_hdr); - if (g_gate_send(fd, &req->r_hdr, sizeof(req->r_hdr), 0) == -1) { - g_gate_xlog("Error while sending hdr packet: %s.", - strerror(errno)); - } - g_gate_log(LOG_DEBUG, "Sent hdr packet."); - g_gate_swap2h_hdr(&req->r_hdr); - if (req->r_data != NULL) { - data = g_gate_send(fd, req->r_data, req->r_length, 0); - if (data != (ssize_t)req->r_length) { - g_gate_xlog("Error while sending data: %s.", - strerror(errno)); - } - g_gate_log(LOG_DEBUG, - "Sent %zd bytes (offset=%ju, size=%zu).", data, - (uintmax_t)req->r_offset, (size_t)req->r_length); - free(req->r_data); - } - free(req); - } - - /* NOTREACHED */ - return (NULL); -} - -static void -log_connection(struct sockaddr *from) -{ - in_addr_t ip; - - ip = htonl(((struct sockaddr_in *)(void *)from)->sin_addr.s_addr); - g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(ip)); -} - -static int -handshake(struct sockaddr *from, int sfd) -{ - struct g_gate_version ver; - struct g_gate_cinit cinit; - struct g_gate_sinit sinit; - struct ggd_connection *conn; - struct ggd_export *ex; - ssize_t data; - - log_connection(from); - /* - * Phase 1: Version verification. - */ - g_gate_log(LOG_DEBUG, "Receiving version packet."); - data = g_gate_recv(sfd, &ver, sizeof(ver), MSG_WAITALL); - g_gate_swap2h_version(&ver); - if (data != sizeof(ver)) { - g_gate_log(LOG_WARNING, "Malformed version packet."); - return (0); - } - g_gate_log(LOG_DEBUG, "Version packet received."); - if (memcmp(ver.gv_magic, GGATE_MAGIC, strlen(GGATE_MAGIC)) != 0) { - g_gate_log(LOG_WARNING, "Invalid magic field."); - return (0); - } - if (ver.gv_version != GGATE_VERSION) { - g_gate_log(LOG_WARNING, "Version %u is not supported.", - ver.gv_version); - return (0); - } - ver.gv_error = 0; - g_gate_swap2n_version(&ver); - data = g_gate_send(sfd, &ver, sizeof(ver), 0); - g_gate_swap2h_version(&ver); - if (data == -1) { - sendfail(sfd, errno, "Error while sending version packet: %s.", - strerror(errno)); - return (0); - } - - /* - * Phase 2: Request verification. - */ - g_gate_log(LOG_DEBUG, "Receiving initial packet."); - data = g_gate_recv(sfd, &cinit, sizeof(cinit), MSG_WAITALL); - g_gate_swap2h_cinit(&cinit); - if (data != sizeof(cinit)) { - g_gate_log(LOG_WARNING, "Malformed initial packet."); - return (0); - } - g_gate_log(LOG_DEBUG, "Initial packet received."); - conn = connection_find(&cinit); - if (conn != NULL) { - /* - * Connection should already exists. - */ - g_gate_log(LOG_DEBUG, "Found existing connection (token=%lu).", - (unsigned long)conn->c_token); - if (connection_add(conn, &cinit, from, sfd) == -1) { - connection_remove(conn); - return (0); - } - } else { - /* - * New connection, allocate space. - */ - conn = connection_new(&cinit, from, sfd); - if (conn == NULL) { - sendfail(sfd, ENOMEM, - "Cannot allocate new connection."); - return (0); - } - g_gate_log(LOG_DEBUG, "New connection created (token=%lu).", - (unsigned long)conn->c_token); - } - - ex = exports_find(from, &cinit, conn); - if (ex == NULL) { - connection_remove(conn); - sendfail(sfd, errno, NULL); - return (0); - } - if (conn->c_mediasize == 0) { - conn->c_mediasize = g_gate_mediasize(conn->c_diskfd); - conn->c_sectorsize = g_gate_sectorsize(conn->c_diskfd); - } - sinit.gs_mediasize = conn->c_mediasize; - sinit.gs_sectorsize = conn->c_sectorsize; - sinit.gs_error = 0; - - g_gate_log(LOG_DEBUG, "Sending initial packet."); - - g_gate_swap2n_sinit(&sinit); - data = g_gate_send(sfd, &sinit, sizeof(sinit), 0); - g_gate_swap2h_sinit(&sinit); - if (data == -1) { - sendfail(sfd, errno, "Error while sending initial packet: %s.", - strerror(errno)); - return (0); - } - - if (connection_ready(conn)) { - connection_launch(conn); - connection_remove(conn); - } - return (1); -} - -static void -huphandler(int sig __unused) -{ - - got_sighup = 1; -} - -int -main(int argc, char *argv[]) -{ - struct sockaddr_in serv; - struct sockaddr from; - socklen_t fromlen; - int sfd, tmpsfd; - unsigned port; - - bindaddr = htonl(INADDR_ANY); - port = G_GATE_PORT; - for (;;) { - int ch; - - ch = getopt(argc, argv, "a:hnp:R:S:v"); - if (ch == -1) - break; - switch (ch) { - case 'a': - bindaddr = g_gate_str2ip(optarg); - if (bindaddr == INADDR_NONE) { - errx(EXIT_FAILURE, - "Invalid IP/host name to bind to."); - } - break; - case 'n': - nagle = 0; - break; - case 'p': - errno = 0; - port = strtoul(optarg, NULL, 10); - if (port == 0 && errno != 0) - errx(EXIT_FAILURE, "Invalid port."); - break; - case 'R': - errno = 0; - rcvbuf = strtoul(optarg, NULL, 10); - if (rcvbuf == 0 && errno != 0) - errx(EXIT_FAILURE, "Invalid rcvbuf."); - break; - case 'S': - errno = 0; - sndbuf = strtoul(optarg, NULL, 10); - if (sndbuf == 0 && errno != 0) - errx(EXIT_FAILURE, "Invalid sndbuf."); - break; - case 'v': - g_gate_verbose++; - break; - case 'h': - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (argv[0] != NULL) - exports_file = argv[0]; - exports_get(); - - if (!g_gate_verbose) { - /* Run in daemon mode. */ - if (daemon(0, 0) == -1) - g_gate_xlog("Cannot daemonize: %s", strerror(errno)); - } - - signal(SIGCHLD, SIG_IGN); - - sfd = socket(AF_INET, SOCK_STREAM, 0); - if (sfd == -1) - g_gate_xlog("Cannot open stream socket: %s.", strerror(errno)); - bzero(&serv, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = bindaddr; - serv.sin_port = htons(port); - - g_gate_socket_settings(sfd); - - if (bind(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) - g_gate_xlog("bind(): %s.", strerror(errno)); - if (listen(sfd, 5) == -1) - g_gate_xlog("listen(): %s.", strerror(errno)); - - g_gate_log(LOG_INFO, "Listen on port: %d.", port); - - signal(SIGHUP, huphandler); - - for (;;) { - fromlen = sizeof(from); - tmpsfd = accept(sfd, &from, &fromlen); - if (tmpsfd == -1) - g_gate_xlog("accept(): %s.", strerror(errno)); - - if (got_sighup) { - got_sighup = 0; - exports_get(); - } - - if (!handshake(&from, tmpsfd)) - close(tmpsfd); - } - close(sfd); - exit(EXIT_SUCCESS); -} diff --git a/ggatel/Makefile b/ggatel/Makefile deleted file mode 100644 index 604a754..0000000 --- a/ggatel/Makefile +++ /dev/null @@ -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 diff --git a/ggatel/ggatel.8 b/ggatel/ggatel.8 deleted file mode 100644 index 01b964a..0000000 --- a/ggatel/ggatel.8 +++ /dev/null @@ -1,160 +0,0 @@ -.\" Copyright (c) 2004 Pawel Jakub Dawidek -.\" 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 . diff --git a/ggatel/ggatel.c b/ggatel/ggatel.c deleted file mode 100644 index 6a3f26e..0000000 --- a/ggatel/ggatel.c +++ /dev/null @@ -1,336 +0,0 @@ -/*- - * Copyright (c) 2004 Pawel Jakub Dawidek - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#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 ] [-q queue_size] " - "[-s sectorsize] [-t timeout] [-u unit] \n", getprogname()); - fprintf(stderr, " %s rescue [-v] [-o ] <-u unit> " - "\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); -} diff --git a/shared/ggate.c b/shared/ggate.c deleted file mode 100644 index cf9b9ca..0000000 --- a/shared/ggate.c +++ /dev/null @@ -1,409 +0,0 @@ -/*- - * Copyright (c) 2004 Pawel Jakub Dawidek - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#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); -} diff --git a/shared/ggate.h b/shared/ggate.h deleted file mode 100644 index 3e26253..0000000 --- a/shared/ggate.h +++ /dev/null @@ -1,196 +0,0 @@ -/*- - * Copyright (c) 2004 Pawel Jakub Dawidek - * 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 -#include - -#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_ */