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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
          +++ new/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
   1    1  /*
   2    2   * Copyright (C) 1993-2001, 2003 by Darren Reed.
   3    3   *
   4    4   * See the IPFILTER.LICENCE file for details on licencing.
   5    5   *
   6    6   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   7    7   *
   8      - * Copyright 2018 Joyent, Inc.
        8 + * Copyright 2019 Joyent, Inc.
   9    9   */
  10   10  
  11   11  #if !defined(lint)
  12   12  static const char sccsid[] = "@(#)ip_fil_solaris.c      1.7 07/22/06 (C) 1993-2000 Darren Reed";
  13   13  static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21:40:46 darrenr Exp $";
  14   14  #endif
  15   15  
  16   16  #include <sys/types.h>
  17   17  #include <sys/errno.h>
  18   18  #include <sys/param.h>
↓ open down ↓ 881 lines elided ↑ open up ↑
 900  900          cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
 901  901                  dev, cmd, data, mode, cp, rp);
 902  902  #endif
 903  903          unit = getminor(dev);
 904  904  
 905  905          isp = ddi_get_soft_state(ipf_state, unit);
 906  906          if (isp == NULL)
 907  907                  return ENXIO;
 908  908          unit = isp->ipfs_minor;
 909  909  
      910 +        if (unit == IPL_LOGEV)
      911 +                return (ipf_cfwlog_ioctl(dev, cmd, data, mode, cp, rp));
      912 +
 910  913          zid = crgetzoneid(cp);
 911  914          if (cmd == SIOCIPFZONESET) {
 912  915                  if (zid == GLOBAL_ZONEID)
 913  916                          return fr_setzoneid(isp, (caddr_t) data);
 914  917                  return EACCES;
 915  918          }
 916  919  
 917  920          /*
 918  921           * ipf_find_stack returns with a read lock on ifs_ipf_global
 919  922           */
↓ open down ↓ 320 lines elided ↑ open up ↑
1240 1243  
1241 1244  #ifdef  IPFDEBUG
1242 1245          cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred);
1243 1246  #endif
1244 1247          if (!(otype & OTYP_CHR))
1245 1248                  return ENXIO;
1246 1249  
1247 1250          if (IPL_LOGMAX < min)
1248 1251                  return ENXIO;
1249 1252  
     1253 +        /* Special-case ipfev: global-zone-open only. */
     1254 +        if (min == IPL_LOGEV) {
     1255 +                if (crgetzoneid(cred) != GLOBAL_ZONEID)
     1256 +                        return (ENXIO);
     1257 +                /*
     1258 +                 * Else enable the CFW logging of events.
     1259 +                 * NOTE: For now, we only allow one open at a time.
     1260 +                 * Use atomic_add to confirm/deny. And also for now,
     1261 +                 * assume sizeof (boolean_t) == sizeof (int).
     1262 +                 */
     1263 +                if (atomic_inc_uint_nv(&ipf_cfwlog_enabled) > 1) {
     1264 +                        atomic_dec_uint(&ipf_cfwlog_enabled);
     1265 +                        return (EBUSY);
     1266 +                }
     1267 +        }
     1268 +
1250 1269          minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
1251 1270              VM_BESTFIT | VM_SLEEP);
1252 1271  
1253 1272          if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
1254 1273                  vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);
     1274 +                if (min == IPL_LOGEV)
     1275 +                        atomic_dec_uint(&ipf_cfwlog_enabled);
1255 1276                  return ENXIO;
1256 1277          }
1257 1278  
1258 1279          *devp = makedevice(getmajor(*devp), minor);
1259 1280          isp = ddi_get_soft_state(ipf_state, minor);
1260 1281          VERIFY(isp != NULL);
1261 1282  
1262 1283          isp->ipfs_minor = min;
1263 1284          isp->ipfs_zoneid = IPFS_ZONE_UNSET;
1264 1285  
↓ open down ↓ 1 lines elided ↑ open up ↑
1266 1287  }
1267 1288  
1268 1289  
1269 1290  /*ARGSUSED*/
1270 1291  int iplclose(dev, flags, otype, cred)
1271 1292  dev_t dev;
1272 1293  int flags, otype;
1273 1294  cred_t *cred;
1274 1295  {
1275 1296          minor_t min = getminor(dev);
     1297 +        ipf_devstate_t *isp;
1276 1298  
1277 1299  #ifdef  IPFDEBUG
1278 1300          cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
1279 1301  #endif
1280 1302  
1281 1303          if (IPL_LOGMAX < min)
1282 1304                  return ENXIO;
1283 1305  
     1306 +        isp = ddi_get_soft_state(ipf_state, min);
     1307 +        if (isp != NULL && isp->ipfs_minor == IPL_LOGEV) {
     1308 +                /* Disable CFW logging. */
     1309 +                membar_exit();
     1310 +                atomic_dec_uint(&ipf_cfwlog_enabled);
     1311 +        }
     1312 +
1284 1313          ddi_soft_state_free(ipf_state, min);
1285 1314          vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
1286 1315  
1287 1316          return 0;
1288 1317  }
1289 1318  
1290 1319  #ifdef  IPFILTER_LOG
1291 1320  /*
1292 1321   * iplread/ipllog
1293 1322   * both of these must operate with at least splnet() lest they be
↓ open down ↓ 10 lines elided ↑ open up ↑
1304 1333          int ret;
1305 1334          minor_t unit;
1306 1335          ipf_devstate_t *isp;
1307 1336  
1308 1337          unit = getminor(dev);
1309 1338          isp = ddi_get_soft_state(ipf_state, unit);
1310 1339          if (isp == NULL)
1311 1340                  return ENXIO;
1312 1341          unit = isp->ipfs_minor;
1313 1342  
     1343 +        if (unit == IPL_LOGEV)
     1344 +                return (ipf_cfwlog_read(dev, uio, cp));
     1345 +
1314 1346          /*
1315 1347           * ipf_find_stack returns with a read lock on ifs_ipf_global
1316 1348           */
1317 1349          ifs = ipf_find_stack(crgetzoneid(cp), isp);
1318 1350          if (ifs == NULL)
1319 1351                  return ENXIO;
1320 1352  
1321 1353  # ifdef IPFDEBUG
1322 1354          cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
1323 1355  # endif
↓ open down ↓ 31 lines elided ↑ open up ↑
1355 1387          ipf_stack_t *ifs;
1356 1388          minor_t unit;
1357 1389          ipf_devstate_t *isp;
1358 1390  
1359 1391          unit = getminor(dev);
1360 1392          isp = ddi_get_soft_state(ipf_state, unit);
1361 1393          if (isp == NULL)
1362 1394                  return ENXIO;
1363 1395          unit = isp->ipfs_minor;
1364 1396  
     1397 +        if (unit == IPL_LOGEV)
     1398 +                return (EIO);   /* ipfev doesn't support write yet. */
     1399 +
1365 1400          /*
1366 1401           * ipf_find_stack returns with a read lock on ifs_ipf_global
1367 1402           */
1368 1403          ifs = ipf_find_stack(crgetzoneid(cp), isp);
1369 1404          if (ifs == NULL)
1370 1405                  return ENXIO;
1371 1406  
1372 1407  #ifdef  IPFDEBUG
1373 1408          cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
1374 1409  #endif
↓ open down ↓ 2104 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX