]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/ggate/shared/ggate.c
This commit was generated by cvs2svn to compensate for changes in r161630,
[FreeBSD/FreeBSD.git] / sbin / ggate / shared / ggate.c
1 /*-
2  * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/param.h>
34 #include <sys/disk.h>
35 #include <sys/stat.h>
36 #include <sys/endian.h>
37 #include <sys/socket.h>
38 #include <sys/linker.h>
39 #include <sys/module.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 #include <arpa/inet.h>
43 #include <signal.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <string.h>
47 #include <strings.h>
48 #include <libgen.h>
49 #include <libutil.h>
50 #include <netdb.h>
51 #include <syslog.h>
52 #include <stdarg.h>
53 #include <stdint.h>
54 #include <libgeom.h>
55
56 #include <geom/gate/g_gate.h>
57 #include "ggate.h"
58
59
60 int g_gate_devfd = -1;
61 int g_gate_verbose = 0;
62
63
64 void
65 g_gate_vlog(int priority, const char *message, va_list ap)
66 {
67
68         if (g_gate_verbose) {
69                 const char *prefix;
70
71                 switch (priority) {
72                 case LOG_ERR:
73                         prefix = "error";
74                         break;
75                 case LOG_WARNING:
76                         prefix = "warning";
77                         break;
78                 case LOG_NOTICE:
79                         prefix = "notice";
80                         break;
81                 case LOG_INFO:
82                         prefix = "info";
83                         break;
84                 case LOG_DEBUG:
85                         prefix = "debug";
86                         break;
87                 default:
88                         prefix = "unknown";
89                 }
90
91                 printf("%s: ", prefix);
92                 vprintf(message, ap);
93                 printf("\n");
94         } else {
95                 if (priority != LOG_DEBUG)
96                         vsyslog(priority, message, ap);
97         }
98 }
99
100 void
101 g_gate_log(int priority, const char *message, ...)
102 {
103         va_list ap;
104
105         va_start(ap, message);
106         g_gate_vlog(priority, message, ap);
107         va_end(ap);
108 }
109
110 void
111 g_gate_xvlog(const char *message, va_list ap)
112 {
113
114         g_gate_vlog(LOG_ERR, message, ap);
115         g_gate_vlog(LOG_ERR, "Exiting.", ap);
116         exit(EXIT_FAILURE);
117 }
118
119 void
120 g_gate_xlog(const char *message, ...)
121 {
122         va_list ap;
123
124         va_start(ap, message);
125         g_gate_xvlog(message, ap);
126         /* NOTREACHED */
127         va_end(ap);
128         exit(EXIT_FAILURE);
129 }
130
131 off_t
132 g_gate_mediasize(int fd)
133 {
134         off_t mediasize;
135         struct stat sb;
136
137         if (fstat(fd, &sb) == -1)
138                 g_gate_xlog("fstat(): %s.", strerror(errno));
139         if (S_ISCHR(sb.st_mode)) {
140                 if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
141                         g_gate_xlog("Can't get media size: %s.",
142                             strerror(errno));
143                 }
144         } else if (S_ISREG(sb.st_mode)) {
145                 mediasize = sb.st_size;
146         } else {
147                 g_gate_xlog("Unsupported file system object.");
148         }
149         return (mediasize);
150 }
151
152 size_t
153 g_gate_sectorsize(int fd)
154 {
155         size_t secsize;
156         struct stat sb;
157
158         if (fstat(fd, &sb) == -1)
159                 g_gate_xlog("fstat(): %s.", strerror(errno));
160         if (S_ISCHR(sb.st_mode)) {
161                 if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
162                         g_gate_xlog("Can't get sector size: %s.",
163                             strerror(errno));
164                 }
165         } else if (S_ISREG(sb.st_mode)) {
166                 secsize = 512;
167         } else {
168                 g_gate_xlog("Unsupported file system object.");
169         }
170         return (secsize);
171 }
172
173 void
174 g_gate_open_device(void)
175 {
176
177         g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
178         if (g_gate_devfd == -1)
179                 err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
180 }
181
182 void
183 g_gate_close_device(void)
184 {
185
186         close(g_gate_devfd);
187 }
188
189 void
190 g_gate_ioctl(unsigned long req, void *data)
191 {
192
193         if (ioctl(g_gate_devfd, req, data) == -1) {
194                 g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
195                     G_GATE_CTL_NAME, strerror(errno));
196         }
197 }
198
199 void
200 g_gate_destroy(int unit, int force)
201 {
202         struct g_gate_ctl_destroy ggio;
203
204         ggio.gctl_version = G_GATE_VERSION;
205         ggio.gctl_unit = unit;
206         ggio.gctl_force = force;
207         g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
208 }
209
210 void
211 g_gate_load_module(void)
212 {
213
214         if (modfind("g_gate") == -1) {
215                 /* Not present in kernel, try loading it. */
216                 if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
217                         if (errno != EEXIST) {
218                                 errx(EXIT_FAILURE,
219                                     "geom_gate module not available!");
220                         }
221                 }
222         }
223 }
224
225 ssize_t
226 g_gate_send(int s, const void *buf, size_t len, int flags)
227 {
228         ssize_t done = 0, done2;
229         const unsigned char *p = buf;
230
231         while (len > 0) {
232                 done2 = send(s, p, len, flags);
233                 if (done2 == 0)
234                         break;
235                 else if (done2 == -1) {
236                         if (errno == EAGAIN) {
237                                 printf("%s: EAGAIN\n", __func__);
238                                 continue;
239                         }
240                         done = -1;
241                         break;
242                 }
243                 done += done2;
244                 p += done2;
245                 len -= done2;
246         }
247         return (done);
248 }
249
250 ssize_t
251 g_gate_recv(int s, void *buf, size_t len, int flags)
252 {
253
254         return (recv(s, buf, len, flags));
255 }
256
257 int nagle = 1;
258 unsigned rcvbuf = G_GATE_RCVBUF;
259 unsigned sndbuf = G_GATE_SNDBUF;
260
261 void
262 g_gate_socket_settings(int sfd)
263 {
264         struct timeval tv;
265         int bsize, on;
266
267         /* Socket settings. */
268         on = 1;
269         if (nagle) {
270                 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on, 
271                     sizeof(on)) == -1) {
272                         g_gate_xlog("setsockopt() error: %s.", strerror(errno));
273                 }
274         }
275         if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
276                 g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
277         bsize = rcvbuf;
278         if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
279                 g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
280         bsize = sndbuf;
281         if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
282                 g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
283         tv.tv_sec = 1;
284         tv.tv_usec = 0;
285         if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
286                 g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
287                     strerror(errno));
288         }
289         if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
290                 g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
291                     strerror(errno));
292         }
293 }
294
295 #ifdef LIBGEOM
296 static struct gclass *
297 find_class(struct gmesh *mesh, const char *name)
298 {
299         struct gclass *class;
300
301         LIST_FOREACH(class, &mesh->lg_class, lg_class) {
302                 if (strcmp(class->lg_name, name) == 0)
303                         return (class);
304         }
305         return (NULL);
306 }
307
308 static const char *
309 get_conf(struct ggeom *gp, const char *name)
310 {
311         struct gconfig *conf;
312
313         LIST_FOREACH(conf, &gp->lg_config, lg_config) {
314                 if (strcmp(conf->lg_name, name) == 0)
315                         return (conf->lg_val);
316         }
317         return (NULL);
318 }
319
320 static void
321 show_config(struct ggeom *gp, int verbose)
322 {
323         struct gprovider *pp;
324         char buf[5];
325
326         pp = LIST_FIRST(&gp->lg_provider);
327         if (pp == NULL)
328                 return;
329         if (!verbose) {
330                 printf("%s\n", pp->lg_name);
331                 return;
332         }
333         printf("       NAME: %s\n", pp->lg_name);
334         printf("       info: %s\n", get_conf(gp, "info"));
335         printf("     access: %s\n", get_conf(gp, "access"));
336         printf("    timeout: %s\n", get_conf(gp, "timeout"));
337         printf("queue_count: %s\n", get_conf(gp, "queue_count"));
338         printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
339         printf(" references: %s\n", get_conf(gp, "ref"));
340         humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
341             HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
342         printf("  mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
343         printf(" sectorsize: %u\n", pp->lg_sectorsize);
344         printf("       mode: %s\n", pp->lg_mode);
345         printf("\n");
346 }
347
348 void
349 g_gate_list(int unit, int verbose)
350 {
351         struct gmesh mesh;
352         struct gclass *class;
353         struct ggeom *gp;
354         char name[64];
355         int error;
356
357         error = geom_gettree(&mesh);
358         if (error != 0)
359                 exit(EXIT_FAILURE);
360         class = find_class(&mesh, G_GATE_CLASS_NAME);
361         if (class == NULL) {
362                 geom_deletetree(&mesh);
363                 exit(EXIT_SUCCESS);
364         }
365         if (unit >= 0) {
366                 snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
367                     unit);
368         }
369         LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
370                 if (unit != -1 && strcmp(gp->lg_name, name) != 0)
371                         continue;
372                 show_config(gp, verbose);
373         }
374         geom_deletetree(&mesh);
375         exit(EXIT_SUCCESS);
376 }
377 #endif  /* LIBGEOM */
378
379 in_addr_t
380 g_gate_str2ip(const char *str)
381 {
382         struct hostent *hp;
383         in_addr_t ip;
384
385         ip = inet_addr(str);
386         if (ip != INADDR_NONE) {
387                 /* It is a valid IP address. */
388                 return (ip);
389         }
390         /* Check if it is a valid host name. */
391         hp = gethostbyname(str);
392         if (hp == NULL)
393                 return (INADDR_NONE);
394         return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
395 }