Work on the radix code, added support to compile on OpenWRT,
[ipfw.git] / ipfw / glue.c
index db90c60..e5876b9 100644 (file)
  */
 
 /*
- * $Id: glue.c 4051 2009-11-16 11:30:05Z luigi $
+ * $Id: glue.c 4469 2009-12-11 20:23:11Z marta $
  *
  * Userland functions missing in linux
  */
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #ifndef HAVE_NAT
 /* dummy nat functions */
@@ -91,10 +92,88 @@ strtonum(const char *nptr, long long minval, long long maxval,
        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)
 {
-       return -1;
+       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 */