Print this page
OS-7667 IPFilter needs to keep and report state for cloud firewall logging
Portions contributed by: Mike Gerdts <mike.gerdts@joyent.com>
@@ -3,11 +3,11 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*
- * Copyright 2018 Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil_solaris.c 1.7 07/22/06 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21:40:46 darrenr Exp $";
@@ -905,10 +905,13 @@
isp = ddi_get_soft_state(ipf_state, unit);
if (isp == NULL)
return ENXIO;
unit = isp->ipfs_minor;
+ if (unit == IPL_LOGEV)
+ return (ipf_cfwlog_ioctl(dev, cmd, data, mode, cp, rp));
+
zid = crgetzoneid(cp);
if (cmd == SIOCIPFZONESET) {
if (zid == GLOBAL_ZONEID)
return fr_setzoneid(isp, (caddr_t) data);
return EACCES;
@@ -1245,15 +1248,33 @@
return ENXIO;
if (IPL_LOGMAX < min)
return ENXIO;
+ /* Special-case ipfev: global-zone-open only. */
+ if (min == IPL_LOGEV) {
+ if (crgetzoneid(cred) != GLOBAL_ZONEID)
+ return (ENXIO);
+ /*
+ * Else enable the CFW logging of events.
+ * NOTE: For now, we only allow one open at a time.
+ * Use atomic_add to confirm/deny. And also for now,
+ * assume sizeof (boolean_t) == sizeof (int).
+ */
+ if (atomic_inc_uint_nv(&ipf_cfwlog_enabled) > 1) {
+ atomic_dec_uint(&ipf_cfwlog_enabled);
+ return (EBUSY);
+ }
+ }
+
minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
VM_BESTFIT | VM_SLEEP);
if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);
+ if (min == IPL_LOGEV)
+ atomic_dec_uint(&ipf_cfwlog_enabled);
return ENXIO;
}
*devp = makedevice(getmajor(*devp), minor);
isp = ddi_get_soft_state(ipf_state, minor);
@@ -1271,18 +1292,26 @@
dev_t dev;
int flags, otype;
cred_t *cred;
{
minor_t min = getminor(dev);
+ ipf_devstate_t *isp;
#ifdef IPFDEBUG
cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
#endif
if (IPL_LOGMAX < min)
return ENXIO;
+ isp = ddi_get_soft_state(ipf_state, min);
+ if (isp != NULL && isp->ipfs_minor == IPL_LOGEV) {
+ /* Disable CFW logging. */
+ membar_exit();
+ atomic_dec_uint(&ipf_cfwlog_enabled);
+ }
+
ddi_soft_state_free(ipf_state, min);
vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
return 0;
}
@@ -1309,10 +1338,13 @@
isp = ddi_get_soft_state(ipf_state, unit);
if (isp == NULL)
return ENXIO;
unit = isp->ipfs_minor;
+ if (unit == IPL_LOGEV)
+ return (ipf_cfwlog_read(dev, uio, cp));
+
/*
* ipf_find_stack returns with a read lock on ifs_ipf_global
*/
ifs = ipf_find_stack(crgetzoneid(cp), isp);
if (ifs == NULL)
@@ -1360,10 +1392,13 @@
isp = ddi_get_soft_state(ipf_state, unit);
if (isp == NULL)
return ENXIO;
unit = isp->ipfs_minor;
+ if (unit == IPL_LOGEV)
+ return (EIO); /* ipfev doesn't support write yet. */
+
/*
* ipf_find_stack returns with a read lock on ifs_ipf_global
*/
ifs = ipf_find_stack(crgetzoneid(cp), isp);
if (ifs == NULL)