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>
   1 /*
   2  * Copyright (C) 1993-2001, 2003 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   7  *
   8  * Copyright 2018 Joyent, Inc.
   9  */
  10 
  11 #if !defined(lint)
  12 static const char sccsid[] = "@(#)ip_fil_solaris.c      1.7 07/22/06 (C) 1993-2000 Darren Reed";
  13 static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21:40:46 darrenr Exp $";
  14 #endif
  15 
  16 #include <sys/types.h>
  17 #include <sys/errno.h>
  18 #include <sys/param.h>
  19 #include <sys/cpuvar.h>
  20 #include <sys/open.h>
  21 #include <sys/ioctl.h>
  22 #include <sys/filio.h>
  23 #include <sys/systm.h>
  24 #include <sys/strsubr.h>
  25 #include <sys/strsun.h>
  26 #include <sys/cred.h>
  27 #include <sys/ddi.h>
  28 #include <sys/sunddi.h>


 890 {
 891         int error = 0, tmp;
 892         friostat_t fio;
 893         minor_t unit;
 894         u_int enable;
 895         ipf_stack_t *ifs;
 896         zoneid_t zid;
 897         ipf_devstate_t *isp;
 898 
 899 #ifdef  IPFDEBUG
 900         cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
 901                 dev, cmd, data, mode, cp, rp);
 902 #endif
 903         unit = getminor(dev);
 904 
 905         isp = ddi_get_soft_state(ipf_state, unit);
 906         if (isp == NULL)
 907                 return ENXIO;
 908         unit = isp->ipfs_minor;
 909 



 910         zid = crgetzoneid(cp);
 911         if (cmd == SIOCIPFZONESET) {
 912                 if (zid == GLOBAL_ZONEID)
 913                         return fr_setzoneid(isp, (caddr_t) data);
 914                 return EACCES;
 915         }
 916 
 917         /*
 918          * ipf_find_stack returns with a read lock on ifs_ipf_global
 919          */
 920         ifs = ipf_find_stack(zid, isp);
 921         if (ifs == NULL)
 922                 return ENXIO;
 923 
 924         if (ifs->ifs_fr_running <= 0) {
 925                 if (unit != IPL_LOGIPF) {
 926                         RWLOCK_EXIT(&ifs->ifs_ipf_global);
 927                         return EIO;
 928                 }
 929                 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&


1230  */
1231 /*ARGSUSED*/
1232 int iplopen(devp, flags, otype, cred)
1233 dev_t *devp;
1234 int flags, otype;
1235 cred_t *cred;
1236 {
1237         ipf_devstate_t *isp;
1238         minor_t min = getminor(*devp);
1239         minor_t minor;
1240 
1241 #ifdef  IPFDEBUG
1242         cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred);
1243 #endif
1244         if (!(otype & OTYP_CHR))
1245                 return ENXIO;
1246 
1247         if (IPL_LOGMAX < min)
1248                 return ENXIO;
1249 
















1250         minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
1251             VM_BESTFIT | VM_SLEEP);
1252 
1253         if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
1254                 vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);


1255                 return ENXIO;
1256         }
1257 
1258         *devp = makedevice(getmajor(*devp), minor);
1259         isp = ddi_get_soft_state(ipf_state, minor);
1260         VERIFY(isp != NULL);
1261 
1262         isp->ipfs_minor = min;
1263         isp->ipfs_zoneid = IPFS_ZONE_UNSET;
1264 
1265         return 0;
1266 }
1267 
1268 
1269 /*ARGSUSED*/
1270 int iplclose(dev, flags, otype, cred)
1271 dev_t dev;
1272 int flags, otype;
1273 cred_t *cred;
1274 {
1275         minor_t min = getminor(dev);

1276 
1277 #ifdef  IPFDEBUG
1278         cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
1279 #endif
1280 
1281         if (IPL_LOGMAX < min)
1282                 return ENXIO;
1283 







1284         ddi_soft_state_free(ipf_state, min);
1285         vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
1286 
1287         return 0;
1288 }
1289 
1290 #ifdef  IPFILTER_LOG
1291 /*
1292  * iplread/ipllog
1293  * both of these must operate with at least splnet() lest they be
1294  * called during packet processing and cause an inconsistancy to appear in
1295  * the filter lists.
1296  */
1297 /*ARGSUSED*/
1298 int iplread(dev, uio, cp)
1299 dev_t dev;
1300 register struct uio *uio;
1301 cred_t *cp;
1302 {
1303         ipf_stack_t *ifs;
1304         int ret;
1305         minor_t unit;
1306         ipf_devstate_t *isp;
1307 
1308         unit = getminor(dev);
1309         isp = ddi_get_soft_state(ipf_state, unit);
1310         if (isp == NULL)
1311                 return ENXIO;
1312         unit = isp->ipfs_minor;
1313 



1314         /*
1315          * ipf_find_stack returns with a read lock on ifs_ipf_global
1316          */
1317         ifs = ipf_find_stack(crgetzoneid(cp), isp);
1318         if (ifs == NULL)
1319                 return ENXIO;
1320 
1321 # ifdef IPFDEBUG
1322         cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
1323 # endif
1324 
1325         if (ifs->ifs_fr_running < 1) {
1326                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1327                 return EIO;
1328         }
1329 
1330 # ifdef IPFILTER_SYNC
1331         if (unit == IPL_LOGSYNC) {
1332                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1333                 return ipfsync_read(uio);


1345  * iplread/ipllog
1346  * both of these must operate with at least splnet() lest they be
1347  * called during packet processing and cause an inconsistancy to appear in
1348  * the filter lists.
1349  */
1350 int iplwrite(dev, uio, cp)
1351 dev_t dev;
1352 register struct uio *uio;
1353 cred_t *cp;
1354 {
1355         ipf_stack_t *ifs;
1356         minor_t unit;
1357         ipf_devstate_t *isp;
1358 
1359         unit = getminor(dev);
1360         isp = ddi_get_soft_state(ipf_state, unit);
1361         if (isp == NULL)
1362                 return ENXIO;
1363         unit = isp->ipfs_minor;
1364 



1365         /*
1366          * ipf_find_stack returns with a read lock on ifs_ipf_global
1367          */
1368         ifs = ipf_find_stack(crgetzoneid(cp), isp);
1369         if (ifs == NULL)
1370                 return ENXIO;
1371 
1372 #ifdef  IPFDEBUG
1373         cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
1374 #endif
1375 
1376         if (ifs->ifs_fr_running < 1) {
1377                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1378                 return EIO;
1379         }
1380 
1381 #ifdef  IPFILTER_SYNC
1382         if (getminor(dev) == IPL_LOGSYNC) {
1383                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1384                 return ipfsync_write(uio);


   1 /*
   2  * Copyright (C) 1993-2001, 2003 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   7  *
   8  * Copyright 2019 Joyent, Inc.
   9  */
  10 
  11 #if !defined(lint)
  12 static const char sccsid[] = "@(#)ip_fil_solaris.c      1.7 07/22/06 (C) 1993-2000 Darren Reed";
  13 static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21:40:46 darrenr Exp $";
  14 #endif
  15 
  16 #include <sys/types.h>
  17 #include <sys/errno.h>
  18 #include <sys/param.h>
  19 #include <sys/cpuvar.h>
  20 #include <sys/open.h>
  21 #include <sys/ioctl.h>
  22 #include <sys/filio.h>
  23 #include <sys/systm.h>
  24 #include <sys/strsubr.h>
  25 #include <sys/strsun.h>
  26 #include <sys/cred.h>
  27 #include <sys/ddi.h>
  28 #include <sys/sunddi.h>


 890 {
 891         int error = 0, tmp;
 892         friostat_t fio;
 893         minor_t unit;
 894         u_int enable;
 895         ipf_stack_t *ifs;
 896         zoneid_t zid;
 897         ipf_devstate_t *isp;
 898 
 899 #ifdef  IPFDEBUG
 900         cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
 901                 dev, cmd, data, mode, cp, rp);
 902 #endif
 903         unit = getminor(dev);
 904 
 905         isp = ddi_get_soft_state(ipf_state, unit);
 906         if (isp == NULL)
 907                 return ENXIO;
 908         unit = isp->ipfs_minor;
 909 
 910         if (unit == IPL_LOGEV)
 911                 return (ipf_cfwlog_ioctl(dev, cmd, data, mode, cp, rp));
 912 
 913         zid = crgetzoneid(cp);
 914         if (cmd == SIOCIPFZONESET) {
 915                 if (zid == GLOBAL_ZONEID)
 916                         return fr_setzoneid(isp, (caddr_t) data);
 917                 return EACCES;
 918         }
 919 
 920         /*
 921          * ipf_find_stack returns with a read lock on ifs_ipf_global
 922          */
 923         ifs = ipf_find_stack(zid, isp);
 924         if (ifs == NULL)
 925                 return ENXIO;
 926 
 927         if (ifs->ifs_fr_running <= 0) {
 928                 if (unit != IPL_LOGIPF) {
 929                         RWLOCK_EXIT(&ifs->ifs_ipf_global);
 930                         return EIO;
 931                 }
 932                 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&


1233  */
1234 /*ARGSUSED*/
1235 int iplopen(devp, flags, otype, cred)
1236 dev_t *devp;
1237 int flags, otype;
1238 cred_t *cred;
1239 {
1240         ipf_devstate_t *isp;
1241         minor_t min = getminor(*devp);
1242         minor_t minor;
1243 
1244 #ifdef  IPFDEBUG
1245         cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred);
1246 #endif
1247         if (!(otype & OTYP_CHR))
1248                 return ENXIO;
1249 
1250         if (IPL_LOGMAX < min)
1251                 return ENXIO;
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 
1269         minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
1270             VM_BESTFIT | VM_SLEEP);
1271 
1272         if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
1273                 vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);
1274                 if (min == IPL_LOGEV)
1275                         atomic_dec_uint(&ipf_cfwlog_enabled);
1276                 return ENXIO;
1277         }
1278 
1279         *devp = makedevice(getmajor(*devp), minor);
1280         isp = ddi_get_soft_state(ipf_state, minor);
1281         VERIFY(isp != NULL);
1282 
1283         isp->ipfs_minor = min;
1284         isp->ipfs_zoneid = IPFS_ZONE_UNSET;
1285 
1286         return 0;
1287 }
1288 
1289 
1290 /*ARGSUSED*/
1291 int iplclose(dev, flags, otype, cred)
1292 dev_t dev;
1293 int flags, otype;
1294 cred_t *cred;
1295 {
1296         minor_t min = getminor(dev);
1297         ipf_devstate_t *isp;
1298 
1299 #ifdef  IPFDEBUG
1300         cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
1301 #endif
1302 
1303         if (IPL_LOGMAX < min)
1304                 return ENXIO;
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 
1313         ddi_soft_state_free(ipf_state, min);
1314         vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
1315 
1316         return 0;
1317 }
1318 
1319 #ifdef  IPFILTER_LOG
1320 /*
1321  * iplread/ipllog
1322  * both of these must operate with at least splnet() lest they be
1323  * called during packet processing and cause an inconsistancy to appear in
1324  * the filter lists.
1325  */
1326 /*ARGSUSED*/
1327 int iplread(dev, uio, cp)
1328 dev_t dev;
1329 register struct uio *uio;
1330 cred_t *cp;
1331 {
1332         ipf_stack_t *ifs;
1333         int ret;
1334         minor_t unit;
1335         ipf_devstate_t *isp;
1336 
1337         unit = getminor(dev);
1338         isp = ddi_get_soft_state(ipf_state, unit);
1339         if (isp == NULL)
1340                 return ENXIO;
1341         unit = isp->ipfs_minor;
1342 
1343         if (unit == IPL_LOGEV)
1344                 return (ipf_cfwlog_read(dev, uio, cp));
1345 
1346         /*
1347          * ipf_find_stack returns with a read lock on ifs_ipf_global
1348          */
1349         ifs = ipf_find_stack(crgetzoneid(cp), isp);
1350         if (ifs == NULL)
1351                 return ENXIO;
1352 
1353 # ifdef IPFDEBUG
1354         cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
1355 # endif
1356 
1357         if (ifs->ifs_fr_running < 1) {
1358                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1359                 return EIO;
1360         }
1361 
1362 # ifdef IPFILTER_SYNC
1363         if (unit == IPL_LOGSYNC) {
1364                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1365                 return ipfsync_read(uio);


1377  * iplread/ipllog
1378  * both of these must operate with at least splnet() lest they be
1379  * called during packet processing and cause an inconsistancy to appear in
1380  * the filter lists.
1381  */
1382 int iplwrite(dev, uio, cp)
1383 dev_t dev;
1384 register struct uio *uio;
1385 cred_t *cp;
1386 {
1387         ipf_stack_t *ifs;
1388         minor_t unit;
1389         ipf_devstate_t *isp;
1390 
1391         unit = getminor(dev);
1392         isp = ddi_get_soft_state(ipf_state, unit);
1393         if (isp == NULL)
1394                 return ENXIO;
1395         unit = isp->ipfs_minor;
1396 
1397         if (unit == IPL_LOGEV)
1398                 return (EIO);   /* ipfev doesn't support write yet. */
1399 
1400         /*
1401          * ipf_find_stack returns with a read lock on ifs_ipf_global
1402          */
1403         ifs = ipf_find_stack(crgetzoneid(cp), isp);
1404         if (ifs == NULL)
1405                 return ENXIO;
1406 
1407 #ifdef  IPFDEBUG
1408         cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
1409 #endif
1410 
1411         if (ifs->ifs_fr_running < 1) {
1412                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1413                 return EIO;
1414         }
1415 
1416 #ifdef  IPFILTER_SYNC
1417         if (getminor(dev) == IPL_LOGSYNC) {
1418                 RWLOCK_EXIT(&ifs->ifs_ipf_global);
1419                 return ipfsync_write(uio);