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);
|