fb3d5c31c0f93d0737860d9801e2c0989770d1e8
[ipfw.git] / ipfw / glue.c
1 /*
2  * Copyright (C) 2009 Luigi Rizzo, Marta Carbone, Universita` di Pisa
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*
27  * $Id: glue.c 4540 2009-12-16 17:22:47Z marta $
28  *
29  * Userland functions missing in linux
30  */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #ifndef HAVE_NAT
37 /* dummy nat functions */
38 void
39 ipfw_show_nat(int ac, char **av)
40 {
41         fprintf(stderr, "%s unsupported\n", __FUNCTION__);
42 }
43
44 void
45 ipfw_config_nat(int ac, char **av)
46 {
47         fprintf(stderr, "%s unsupported\n", __FUNCTION__);
48 }
49 #endif
50
51 #ifdef __linux__
52 int optreset;   /* missing in linux */
53 #endif
54
55 #if defined( __linux__ ) || defined(_WIN32)
56 /*
57  * not implemented in linux.
58  * taken from /usr/src/lib/libc/string/strlcpy.c
59  */
60 size_t
61 strlcpy(char *dst, const char *src, size_t siz)
62 {
63         char *d = dst;
64         const char *s = src;
65         size_t n = siz;
66  
67         /* Copy as many bytes as will fit */
68         if (n != 0 && --n != 0) {
69                 do {
70                         if ((*d++ = *s++) == 0)
71                                 break;
72                 } while (--n != 0);
73         }
74
75         /* Not enough room in dst, add NUL and traverse rest of src */
76         if (n == 0) {
77                 if (siz != 0)
78                         *d = '\0';              /* NUL-terminate dst */
79                 while (*s++)
80                         ;
81         }
82
83         return(s - src - 1);    /* count does not include NUL */
84 }
85
86
87 /* missing in linux and windows */
88 long long int
89 strtonum(const char *nptr, long long minval, long long maxval,
90          const char **errstr)
91 {
92         return strtoll(nptr, (char **)errstr, 0);
93 }
94
95 /*
96  * set or get system information
97  * XXX lock acquisition/serialize calls 
98  *
99  * we export this as sys/module/ipfw_mod/parameters/___ 
100  * This function get or/and set the value of the sysctl passed by
101  * the name parameter. If the old value is not desired,
102  * oldp and oldlenp should be set to NULL.
103  *
104  * XXX
105  * I do not know how this works in FreeBSD in the case
106  * where there are no write permission on the sysctl var.
107  * We read the value and set return variables in any way
108  * but returns -1 on write failures, regardless the
109  * read success.
110  * 
111  * Since there is no information on types, in the following
112  * code we assume a lenght of 4 is a int.
113  * 
114  * Returns 0 on success, -1 on errors.
115  */
116 int
117 sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
118          size_t newlen)
119 {
120         FILE *fp;
121         char *basename = "/sys/module/ipfw_mod/parameters/";
122         char filename[256];     /* full filename */
123         char *varp;
124         int ret = 0;            /* return value */
125         int d;
126
127         if (name == NULL) /* XXX set errno */
128                 return -1;
129
130         /* locate the filename */
131         varp = strrchr(name, '.');
132         if (varp == NULL) /* XXX set errno */
133                 return -1;
134
135         snprintf(filename, sizeof(filename), "%s%s", basename, varp+1);
136
137         /*
138          * XXX we could open the file here, in rw mode
139          * but need to check if a file have write
140          * permissions.
141          */
142
143         /* check parameters */
144         if (oldp && oldlenp) { /* read mode */
145                 fp = fopen(filename, "r");
146                 if (fp == NULL) {
147                         fprintf(stderr, "%s fopen error reading filename %s\n", __FUNCTION__, filename);
148                         return -1;
149                 }
150                 if (*oldlenp == 4) {
151                         if (fscanf(fp, "%d", &d) == 1)
152                                 memcpy(oldp, &d, *oldlenp);
153                         else
154                                 ret = -1;
155                 }
156                 fclose(fp);
157         }
158
159         if (newp && newlen) { /* write */
160                 fp = fopen(filename, "w");
161                 if (fp == NULL) {
162                         fprintf(stderr, "%s fopen error writing filename %s\n", __FUNCTION__, filename);
163                         return -1;
164                 }
165                 if (newlen == 4) {
166                         if (fprintf(fp, "%d", *(int*)newp) < 1)
167                                 ret = -1;
168                 }
169                         
170                 fclose(fp);
171         }
172
173         return ret;
174 }
175 #endif /* __linux__ || _WIN32 */