diff --git a/shared/ggate.c b/shared/ggate.c new file mode 100644 index 0000000..9002b91 --- /dev/null +++ b/shared/ggate.c @@ -0,0 +1,330 @@ +/*- + * 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" + + +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) < 0) + g_gate_xlog("fstat(): %s.", strerror(errno)); + if (S_ISCHR(sb.st_mode)) { + if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) { + 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); +} + +size_t +g_gate_sectorsize(int fd) +{ + size_t secsize; + struct stat sb; + + if (fstat(fd, &sb) < 0) + g_gate_xlog("fstat(): %s.", strerror(errno)); + if (S_ISCHR(sb.st_mode)) { + if (ioctl(fd, DIOCGSECTORSIZE, &secsize) < 0) { + 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, 0); + if (g_gate_devfd < 0) + 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) < 0) { + 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); +} + +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); +} + +void +g_gate_load_module(void) +{ + + if (modfind("g_gate") < 0) { + /* Not present in kernel, try loading it. */ + if (kldload("geom_gate") < 0 || modfind("g_gate") < 0) { + if (errno != EEXIST) { + errx(EXIT_FAILURE, + "geom_gate module not available!"); + } + } + } +} + +#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; + + 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")); + printf(" mediasize: %jd\n", pp->lg_mediasize); + 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 *)(hp->h_addr))->s_addr); +} diff --git a/shared/ggate.h b/shared/ggate.h new file mode 100644 index 0000000..d4d8253 --- /dev/null +++ b/shared/ggate.h @@ -0,0 +1,143 @@ +/*- + * 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 + +#define G_GATE_BUFSIZE_START 65536 +#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 30 + +extern int g_gate_devfd; +extern int g_gate_verbose; + +/* Client's initial packet. */ +struct g_gate_cinit { + char gc_path[PATH_MAX + 1]; + uint8_t gc_flags; +}; + +/* Server's initial packet. */ +struct g_gate_sinit { + uint8_t gs_flags; + uint64_t gs_mediasize; + uint32_t gs_sectorsize; + uint16_t gs_error; +}; + +/* Control struct. */ +struct g_gate_hdr { + uint8_t gh_cmd; /* command */ + uint64_t gh_offset; /* device offset */ + uint32_t gh_length; /* size of block */ + int16_t gh_error; /* error value (0 if ok) */ +}; + +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); +size_t 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); +int g_gate_openflags(unsigned ggflags); +void g_gate_load_module(void); +#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_cinit(struct g_gate_cinit *cinit __unused) +{ + + /* Nothing here for now. */ +} + +static __inline void +g_gate_swap2n_cinit(struct g_gate_cinit *cinit __unused) +{ + + /* Nothing here for now. */ +} + +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_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_error = htobe16(hdr->gh_error); +} +#endif /* _GGATE_H_ */