/* * Copyright (C) 2009 Luigi Rizzo, Marta Carbone, Universita` di Pisa * * 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 AUTHOR 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 AUTHOR 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. */ /* * $Id: glue.c 4469 2009-12-11 20:23:11Z marta $ * * Userland functions missing in linux */ #include #include #include #ifndef HAVE_NAT /* dummy nat functions */ void ipfw_show_nat(int ac, char **av) { fprintf(stderr, "%s unsupported\n", __FUNCTION__); } void ipfw_config_nat(int ac, char **av) { fprintf(stderr, "%s unsupported\n", __FUNCTION__); } #endif #ifdef __linux__ int optreset; /* missing in linux */ #endif #if defined( __linux__ ) || defined(_WIN32) /* * not implemented in linux. * taken from /usr/src/lib/libc/string/strlcpy.c */ size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } /* missing in linux and windows */ long long int strtonum(const char *nptr, long long minval, long long maxval, const char **errstr) { return strtoll(nptr, (char **)errstr, 0); } /* * set or get system information * XXX lock acquisition/serialize calls * * we export this as sys/module/ipfw_mod/parameters/___ * This function get or/and set the value of the sysctl passed by * the name parameter. If the old value is not desired, * oldp and oldlenp should be set to NULL. * * XXX * I do not know how this works in FreeBSD in the case * where there are no write permission on the sysctl var. * We read the value and set return variables in any way * but returns -1 on write failures, regardless the * read success. * * Since there is no information on types, in the following * code we assume a lenght of 4 is a int. * * Returns 0 on success, -1 on errors. */ int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { FILE *fp; char *basename = "/sys/module/ipfw_mod/parameters/"; char filename[256]; /* full filename */ char *varp; int ret = 0; /* return value */ int d; /* debug message */ if (0) fprintf(stderr, "%s name %s oldp %p oldlenp %p %d newp %p newlen %d\n", __FUNCTION__, name, \ oldp, oldlenp, oldlenp ? *oldlenp : -1 , newp, (int) newlen); if (name == NULL) /* XXX set errno */ return -1; /* locate the filename */ varp = strrchr(name, '.'); if (varp == NULL) /* XXX set errno */ return -1; snprintf(filename, sizeof(filename), "%s%s", basename, varp+1); /* * XXX we could open the file here, in rw mode * but need to check if a file have write * permissions. */ /* check parameters */ if (oldp && oldlenp) { /* read mode */ fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "%s fopen error reading filename %s\n", __FUNCTION__, filename); return -1; } if (*oldlenp == 4) { if (fscanf(fp, "%d", &d) == 1) memcpy(oldp, &d, *oldlenp); else ret = -1; } fclose(fp); } if (newp && newlen) { /* write */ fp = fopen(filename, "w"); if (fp == NULL) { fprintf(stderr, "%s fopen error writing filename %s\n", __FUNCTION__, filename); return -1; } if (newlen == 4) { if (fprintf(fp, "%d", *(int*)newp) < 1) ret = -1; } fclose(fp); } return ret; } #endif /* __linux__ || _WIN32 */