From f1ac1edac99c9c4b3dddecb575b3ef520b14dff2 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 20 Mar 2009 17:49:16 +0000 Subject: Add support for FreeBSD 7.2 jails. --- module/bsnmp-jails.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 125 insertions(+), 11 deletions(-) (limited to 'module') 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); } -- cgit v1.2.3