summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/bsnmp-jails.c136
1 files changed, 125 insertions, 11 deletions
diff --git a/module/bsnmp-jails.c b/module/bsnmp-jails.c
index 31b3848..a6ea004 100644
--- a/module/bsnmp-jails.c
+++ b/module/bsnmp-jails.c
@@ -77,6 +77,13 @@
* COMPAT
*/
+/*
+ * First jail structure kernel version in
+ * FreeBSD 4.x to 7.1 (unpatched)
+ */
+
+#ifndef HAVE_XPRISON_V1
+
struct xprison_v1 {
int pr_version;
int pr_id;
@@ -85,6 +92,17 @@ struct xprison_v1 {
u_int32_t pr_ip;
};
+/* It's now defined */
+#define HAVE_XPRISON_V1 1
+
+#endif /* HAVE_XPRISON_V1 */
+
+
+/*
+ * Second jail structure kernel version, used by multiple
+ * IP jail patches that applied to 5.x, 6.x and 7.0
+ */
+
#ifndef JAIL_MAX_IPS
#define JAIL_MAX_IPS 256
#endif
@@ -98,6 +116,24 @@ struct xprison_v2 {
u_int pr_nips;
};
+/* This one is always defined */
+#define HAVE_XPRISON_V2 1
+
+
+/*
+ * Third jail structure kernel version, used by FreeBSD
+ * 7.2 and later.
+ */
+
+#if XPRISON_VERSION == 3
+
+/* The system definition is V3 */
+#define xprison_v3 xprison
+#define HAVE_XPRISON_V3 1
+
+#endif
+
+
/* -------------------------------------------------------------------
* DECLARATIONS
*/
@@ -1048,7 +1084,7 @@ jail_free (struct jaildat *jail)
static int
jail_update (struct jaildat *jail, int jailid, const char *host,
- const char *path, u_int32_t *ips, u_int n_ips)
+ const char *path, struct in_addr *ips, u_int n_ips)
{
struct monitor *mon = NULL;
struct sockaddr_in addr;
@@ -1100,13 +1136,15 @@ jail_update (struct jaildat *jail, int jailid, const char *host,
top = (jail->n_addrs > n_ips ? jail->n_addrs : n_ips);
for (i = 0; i < top; ++i) {
+fprintf (stderr, "IP: %s\n", inet_ntoa (ips[i]));
+
/* Setup the address */
if (i < n_ips) {
memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
addr.sin_len = sizeof (addr);
addr.sin_port = 0;
- addr.sin_addr.s_addr = ntohl (ips[i]);
+ addr.sin_addr.s_addr = ips[i].s_addr;
/* Same? skip. */
if (i < jail->n_addrs &&
@@ -1151,7 +1189,7 @@ jail_update (struct jaildat *jail, int jailid, const char *host,
static struct jaildat*
jail_alloc (int jailid, const char *host, const char *path,
- u_int32_t *ips, u_int n_ips)
+ struct in_addr *ips, u_int n_ips)
{
struct jaildat *jail;
@@ -1171,10 +1209,13 @@ jail_alloc (int jailid, const char *host, const char *path,
return jail;
}
+#ifdef HAVE_XPRISON_V1
+
static void
jail_refresh_v1 (struct xprison_v1 *xp, size_t len)
{
struct jaildat *jail;
+ struct in_addr in;
int i;
/* Make sure its kosher */
@@ -1189,23 +1230,29 @@ jail_refresh_v1 (struct xprison_v1 *xp, size_t len)
* (some possibly zombies), then we'll see the most recent one.
*/
for (i = (len / sizeof (*xp)) - 1; i >= 0; --i) {
+ in.s_addr = htonl (xp[i].pr_ip);
jail = hsh_get (jaildat_by_host, xp[i].pr_host, HSH_KEY_STRING);
if (!jail)
jail = jail_alloc (xp[i].pr_id, xp[i].pr_host, xp[i].pr_path,
- &xp[i].pr_ip, 1);
+ &in, 1);
else
jail_update (jail, xp[i].pr_id, xp[i].pr_host, xp[i].pr_path,
- &xp[i].pr_ip, 1);
+ &in, 1);
if (jail)
jail->mark = 0;
}
}
+#endif /* HAVE_XPRISON_V1 */
+
+#ifdef HAVE_XPRISON_V2
+
static void
jail_refresh_v2 (struct xprison_v2 *xp, size_t len)
{
+ struct in_addr ins[JAIL_MAX_IPS];
struct jaildat *jail;
- int i;
+ int i, j;
/* Make sure its kosher */
if (len < sizeof (*xp) || len % sizeof (*xp)) {
@@ -1219,18 +1266,68 @@ jail_refresh_v2 (struct xprison_v2 *xp, size_t len)
* (some possibly zombies), then we'll see the most recent one.
*/
for (i = (len / sizeof (*xp)) - 1; i >= 0; --i) {
+ for (j = 0; j < xp[i].pr_nips; ++j)
+ ins[j].s_addr = htonl (xp[i].pr_ips[j]);
jail = hsh_get (jaildat_by_host, xp[i].pr_host, HSH_KEY_STRING);
if (!jail)
jail = jail_alloc (xp[i].pr_id, xp[i].pr_host, xp[i].pr_path,
- xp[i].pr_ips, xp[i].pr_nips);
+ ins, xp[i].pr_nips);
else
jail_update (jail, xp[i].pr_id, xp[i].pr_host, xp[i].pr_path,
- xp[i].pr_ips, xp[i].pr_nips);
+ ins, xp[i].pr_nips);
if (jail)
jail->mark = 0;
}
}
+#endif /* HAVE_XPRISON_V2 */
+
+#ifdef HAVE_XPRISON_V3
+
+static void
+jail_refresh_v3 (struct xprison_v3 *xp, size_t len)
+{
+ struct jaildat *jail;
+ size_t xlen;
+
+ while (len > 0) {
+
+ /* Make sure its kosher */
+ if (len < sizeof (*xp)) {
+ emsg ("not a valid v3 xprison. kernel and userland out of sync?");
+ return;
+ }
+
+ /* The length of this block */
+ xlen = sizeof (*xp) + (xp->pr_ip4s * sizeof (struct in_addr)) +
+ (xp->pr_ip6s * sizeof (struct in6_addr));
+
+ /* Make sure its kosher */
+ if (len < xlen) {
+ emsg ("not a valid v3 xprison struct. kernel and userland out of sync?");
+ return;
+ }
+
+ if (xp->pr_state == PRISON_STATE_ALIVE) {
+ jail = hsh_get (jaildat_by_host, xp->pr_host, HSH_KEY_STRING);
+ if (!jail)
+ jail = jail_alloc (xp->pr_id, xp->pr_host, xp->pr_path,
+ (struct in_addr*)(xp + 1), xp->pr_ip4s);
+ else
+ jail_update (jail, xp->pr_id, xp->pr_host, xp->pr_path,
+ (struct in_addr*)(xp + 1), xp->pr_ip4s);
+
+ if (jail)
+ jail->mark = 0;
+ }
+
+ xp = (struct xprison_v3*)(((unsigned char*)xp) + xlen);
+ len -= xlen;
+ }
+}
+
+#endif /* HAVE_XPRISON_V3 */
+
static void
jail_refresh_all (void* unused)
{
@@ -1276,12 +1373,29 @@ jail_refresh_all (void* unused)
jail->mark = 1;
if (len > 0) {
- if (sxp->pr_version == 1)
+ switch (sxp->pr_version) {
+
+#ifdef HAVE_XPRISON_V1
+ case 1:
jail_refresh_v1 ((struct xprison_v1*)sxp, len);
- else if (sxp->pr_version == 2)
+ break;
+#endif
+
+#ifdef HAVE_XPRISON_V2
+ case 2:
jail_refresh_v2 ((struct xprison_v2*)sxp, len);
- else
+ break;
+#endif
+
+#ifdef HAVE_XPRISON_V3
+ case 3:
+ jail_refresh_v3 ((struct xprison_v3*)sxp, len);
+ break;
+#endif
+
+ default:
emsg ("unsupported kernel structure version: %d\n", sxp->pr_version);
+ }
free (sxp);
}