ggate.c revision 134937
1128763Spjd/*- 2128763Spjd * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3128763Spjd * All rights reserved. 4128763Spjd * 5128763Spjd * Redistribution and use in source and binary forms, with or without 6128763Spjd * modification, are permitted provided that the following conditions 7128763Spjd * are met: 8128763Spjd * 1. Redistributions of source code must retain the above copyright 9128763Spjd * notice, this list of conditions and the following disclaimer. 10128763Spjd * 2. Redistributions in binary form must reproduce the above copyright 11128763Spjd * notice, this list of conditions and the following disclaimer in the 12128763Spjd * documentation and/or other materials provided with the distribution. 13128763Spjd * 14128763Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15128763Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16128763Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17128763Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18128763Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19128763Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20128763Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21128763Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22128763Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23128763Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24128763Spjd * SUCH DAMAGE. 25128763Spjd * 26128763Spjd * $FreeBSD: head/sbin/ggate/shared/ggate.c 134937 2004-09-08 07:57:14Z pjd $ 27128763Spjd */ 28128763Spjd 29128763Spjd#include <stdio.h> 30128763Spjd#include <stdlib.h> 31128763Spjd#include <unistd.h> 32128763Spjd#include <fcntl.h> 33128763Spjd#include <sys/param.h> 34128763Spjd#include <sys/disk.h> 35128763Spjd#include <sys/stat.h> 36128763Spjd#include <sys/endian.h> 37128763Spjd#include <sys/socket.h> 38128763Spjd#include <sys/linker.h> 39128763Spjd#include <sys/module.h> 40128763Spjd#include <netinet/in.h> 41128763Spjd#include <arpa/inet.h> 42128763Spjd#include <signal.h> 43128763Spjd#include <err.h> 44128763Spjd#include <errno.h> 45128763Spjd#include <string.h> 46128763Spjd#include <strings.h> 47128763Spjd#include <libgen.h> 48130837Spjd#include <libutil.h> 49128763Spjd#include <netdb.h> 50128763Spjd#include <syslog.h> 51128763Spjd#include <stdarg.h> 52130837Spjd#include <stdint.h> 53128763Spjd#include <libgeom.h> 54128763Spjd 55128763Spjd#include <geom/gate/g_gate.h> 56128763Spjd#include "ggate.h" 57128763Spjd 58128763Spjd 59128763Spjdint g_gate_devfd = -1; 60128763Spjdint g_gate_verbose = 0; 61128763Spjd 62128763Spjd 63128763Spjdvoid 64128763Spjdg_gate_vlog(int priority, const char *message, va_list ap) 65128763Spjd{ 66128763Spjd 67128763Spjd if (g_gate_verbose) { 68128763Spjd const char *prefix; 69128763Spjd 70128763Spjd switch (priority) { 71128763Spjd case LOG_ERR: 72128763Spjd prefix = "error"; 73128763Spjd break; 74128763Spjd case LOG_WARNING: 75128763Spjd prefix = "warning"; 76128763Spjd break; 77128763Spjd case LOG_NOTICE: 78128763Spjd prefix = "notice"; 79128763Spjd break; 80128763Spjd case LOG_INFO: 81128763Spjd prefix = "info"; 82128763Spjd break; 83128763Spjd case LOG_DEBUG: 84128763Spjd prefix = "debug"; 85128763Spjd break; 86128763Spjd default: 87128763Spjd prefix = "unknown"; 88128763Spjd } 89128763Spjd 90128763Spjd printf("%s: ", prefix); 91128763Spjd vprintf(message, ap); 92128763Spjd printf("\n"); 93128763Spjd } else { 94128763Spjd if (priority != LOG_DEBUG) 95128763Spjd vsyslog(priority, message, ap); 96128763Spjd } 97128763Spjd} 98128763Spjd 99128763Spjdvoid 100128763Spjdg_gate_log(int priority, const char *message, ...) 101128763Spjd{ 102128763Spjd va_list ap; 103128763Spjd 104128763Spjd va_start(ap, message); 105128763Spjd g_gate_vlog(priority, message, ap); 106128763Spjd va_end(ap); 107128763Spjd} 108128763Spjd 109128763Spjdvoid 110128763Spjdg_gate_xvlog(const char *message, va_list ap) 111128763Spjd{ 112128763Spjd 113128763Spjd g_gate_vlog(LOG_ERR, message, ap); 114128763Spjd g_gate_vlog(LOG_ERR, "Exiting.", ap); 115128763Spjd exit(EXIT_FAILURE); 116128763Spjd} 117128763Spjd 118128763Spjdvoid 119128763Spjdg_gate_xlog(const char *message, ...) 120128763Spjd{ 121128763Spjd va_list ap; 122128763Spjd 123128763Spjd va_start(ap, message); 124128763Spjd g_gate_xvlog(message, ap); 125128763Spjd /* NOTREACHED */ 126128763Spjd va_end(ap); 127128763Spjd exit(EXIT_FAILURE); 128128763Spjd} 129128763Spjd 130128763Spjdoff_t 131128763Spjdg_gate_mediasize(int fd) 132128763Spjd{ 133128763Spjd off_t mediasize; 134128763Spjd struct stat sb; 135128763Spjd 136134937Spjd if (fstat(fd, &sb) == -1) 137128763Spjd g_gate_xlog("fstat(): %s.", strerror(errno)); 138128763Spjd if (S_ISCHR(sb.st_mode)) { 139134937Spjd if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) { 140128763Spjd g_gate_xlog("Can't get media size: %s.", 141128763Spjd strerror(errno)); 142128763Spjd } 143128763Spjd } else if (S_ISREG(sb.st_mode)) { 144128763Spjd mediasize = sb.st_size; 145128763Spjd } else { 146128763Spjd g_gate_xlog("Unsupported file system object."); 147128763Spjd } 148128763Spjd return (mediasize); 149128763Spjd} 150128763Spjd 151128763Spjdsize_t 152128763Spjdg_gate_sectorsize(int fd) 153128763Spjd{ 154128763Spjd size_t secsize; 155128763Spjd struct stat sb; 156128763Spjd 157134937Spjd if (fstat(fd, &sb) == -1) 158128763Spjd g_gate_xlog("fstat(): %s.", strerror(errno)); 159128763Spjd if (S_ISCHR(sb.st_mode)) { 160134937Spjd if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) { 161128763Spjd g_gate_xlog("Can't get sector size: %s.", 162128763Spjd strerror(errno)); 163128763Spjd } 164128763Spjd } else if (S_ISREG(sb.st_mode)) { 165128763Spjd secsize = 512; 166128763Spjd } else { 167128763Spjd g_gate_xlog("Unsupported file system object."); 168128763Spjd } 169128763Spjd return (secsize); 170128763Spjd} 171128763Spjd 172128763Spjdvoid 173128763Spjdg_gate_open_device(void) 174128763Spjd{ 175128763Spjd 176128763Spjd g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0); 177134937Spjd if (g_gate_devfd == -1) 178128763Spjd err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME); 179128763Spjd} 180128763Spjd 181128763Spjdvoid 182128763Spjdg_gate_close_device(void) 183128763Spjd{ 184128763Spjd 185128763Spjd close(g_gate_devfd); 186128763Spjd} 187128763Spjd 188128763Spjdvoid 189128763Spjdg_gate_ioctl(unsigned long req, void *data) 190128763Spjd{ 191128763Spjd 192134937Spjd if (ioctl(g_gate_devfd, req, data) == -1) { 193128763Spjd g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(), 194128763Spjd G_GATE_CTL_NAME, strerror(errno)); 195128763Spjd } 196128763Spjd} 197128763Spjd 198128763Spjdvoid 199128763Spjdg_gate_destroy(int unit, int force) 200128763Spjd{ 201128763Spjd struct g_gate_ctl_destroy ggio; 202128763Spjd 203128763Spjd ggio.gctl_version = G_GATE_VERSION; 204128763Spjd ggio.gctl_unit = unit; 205128763Spjd ggio.gctl_force = force; 206128763Spjd g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio); 207128763Spjd} 208128763Spjd 209128763Spjdint 210128763Spjdg_gate_openflags(unsigned ggflags) 211128763Spjd{ 212128763Spjd 213128763Spjd if ((ggflags & G_GATE_FLAG_READONLY) != 0) 214128763Spjd return (O_RDONLY); 215128763Spjd else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0) 216128763Spjd return (O_WRONLY); 217128763Spjd return (O_RDWR); 218128763Spjd} 219128763Spjd 220128763Spjdvoid 221128763Spjdg_gate_load_module(void) 222128763Spjd{ 223128763Spjd 224134937Spjd if (modfind("g_gate") == -1) { 225128763Spjd /* Not present in kernel, try loading it. */ 226134937Spjd if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) { 227128763Spjd if (errno != EEXIST) { 228128763Spjd errx(EXIT_FAILURE, 229128763Spjd "geom_gate module not available!"); 230128763Spjd } 231128763Spjd } 232128763Spjd } 233128763Spjd} 234128763Spjd 235128763Spjd#ifdef LIBGEOM 236128763Spjdstatic struct gclass * 237128763Spjdfind_class(struct gmesh *mesh, const char *name) 238128763Spjd{ 239128763Spjd struct gclass *class; 240128763Spjd 241128763Spjd LIST_FOREACH(class, &mesh->lg_class, lg_class) { 242128763Spjd if (strcmp(class->lg_name, name) == 0) 243128763Spjd return (class); 244128763Spjd } 245128763Spjd return (NULL); 246128763Spjd} 247128763Spjd 248128763Spjdstatic const char * 249128763Spjdget_conf(struct ggeom *gp, const char *name) 250128763Spjd{ 251128763Spjd struct gconfig *conf; 252128763Spjd 253128763Spjd LIST_FOREACH(conf, &gp->lg_config, lg_config) { 254128763Spjd if (strcmp(conf->lg_name, name) == 0) 255128763Spjd return (conf->lg_val); 256128763Spjd } 257128763Spjd return (NULL); 258128763Spjd} 259128763Spjd 260128763Spjdstatic void 261128763Spjdshow_config(struct ggeom *gp, int verbose) 262128763Spjd{ 263128763Spjd struct gprovider *pp; 264130837Spjd char buf[5]; 265128763Spjd 266128763Spjd pp = LIST_FIRST(&gp->lg_provider); 267128763Spjd if (pp == NULL) 268128763Spjd return; 269128763Spjd if (!verbose) { 270128763Spjd printf("%s\n", pp->lg_name); 271128763Spjd return; 272128763Spjd } 273128763Spjd printf(" NAME: %s\n", pp->lg_name); 274128763Spjd printf(" info: %s\n", get_conf(gp, "info")); 275128763Spjd printf(" access: %s\n", get_conf(gp, "access")); 276128763Spjd printf(" timeout: %s\n", get_conf(gp, "timeout")); 277128763Spjd printf("queue_count: %s\n", get_conf(gp, "queue_count")); 278128763Spjd printf(" queue_size: %s\n", get_conf(gp, "queue_size")); 279128763Spjd printf(" references: %s\n", get_conf(gp, "ref")); 280130837Spjd humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "", 281130837Spjd HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 282130837Spjd printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf); 283128763Spjd printf(" sectorsize: %u\n", pp->lg_sectorsize); 284128763Spjd printf(" mode: %s\n", pp->lg_mode); 285128763Spjd printf("\n"); 286128763Spjd} 287128763Spjd 288128763Spjdvoid 289128763Spjdg_gate_list(int unit, int verbose) 290128763Spjd{ 291128763Spjd struct gmesh mesh; 292128763Spjd struct gclass *class; 293128763Spjd struct ggeom *gp; 294128763Spjd char name[64]; 295128763Spjd int error; 296128763Spjd 297128763Spjd error = geom_gettree(&mesh); 298128763Spjd if (error != 0) 299128763Spjd exit(EXIT_FAILURE); 300128763Spjd class = find_class(&mesh, G_GATE_CLASS_NAME); 301128763Spjd if (class == NULL) { 302128763Spjd geom_deletetree(&mesh); 303128763Spjd exit(EXIT_SUCCESS); 304128763Spjd } 305128763Spjd if (unit >= 0) { 306128763Spjd snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME, 307128763Spjd unit); 308128763Spjd } 309128763Spjd LIST_FOREACH(gp, &class->lg_geom, lg_geom) { 310128763Spjd if (unit != -1 && strcmp(gp->lg_name, name) != 0) 311128763Spjd continue; 312128763Spjd show_config(gp, verbose); 313128763Spjd } 314128763Spjd geom_deletetree(&mesh); 315128763Spjd exit(EXIT_SUCCESS); 316128763Spjd} 317128763Spjd#endif /* LIBGEOM */ 318128763Spjd 319128763Spjdin_addr_t 320128763Spjdg_gate_str2ip(const char *str) 321128763Spjd{ 322128763Spjd struct hostent *hp; 323128763Spjd in_addr_t ip; 324128763Spjd 325128763Spjd ip = inet_addr(str); 326128763Spjd if (ip != INADDR_NONE) { 327128763Spjd /* It is a valid IP address. */ 328128763Spjd return (ip); 329128763Spjd } 330128763Spjd /* Check if it is a valid host name. */ 331128763Spjd hp = gethostbyname(str); 332128763Spjd if (hp == NULL) 333128763Spjd return (INADDR_NONE); 334128836Spjd return (((struct in_addr *)(void *)hp->h_addr)->s_addr); 335128763Spjd} 336