/* * npfctl_load: store passed data i.e. update settings, create passed * tables, rules and atomically activate all them. */ int npfctl_load(u_long cmd, void *data) { struct plistref *pref = data; prop_dictionary_t npf_dict, errdict; prop_array_t alglist, natlist, tables, rprocs, rules, conlist; npf_tableset_t *tblset = NULL; npf_rprocset_t *rpset = NULL; npf_ruleset_t *rlset = NULL; npf_ruleset_t *nset = NULL; npf_conndb_t *conndb = NULL; uint32_t ver = 0; size_t nitems; bool flush; int error; /* Retrieve the dictionary. */ #ifndef _NPF_TESTING error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict); if (error) return error; #else npf_dict = (prop_dictionary_t)pref; #endif /* Dictionary for error reporting and version check. */ errdict = prop_dictionary_create(); prop_dictionary_get_uint32(npf_dict, "version", &ver); if (ver != NPF_VERSION) { error = EPROGMISMATCH; goto fail; } /* ALGs. */ alglist = prop_dictionary_get(npf_dict, "algs"); error = npf_mk_algs(alglist, errdict); if (error) { goto fail; } /* NAT policies. */ natlist = prop_dictionary_get(npf_dict, "nat"); if ((nitems = prop_array_count(natlist)) > NPF_MAX_RULES) { error = E2BIG; goto fail; } nset = npf_ruleset_create(nitems); error = npf_mk_natlist(nset, natlist, errdict); if (error) { goto fail; } /* Tables. */ tables = prop_dictionary_get(npf_dict, "tables"); if ((nitems = prop_array_count(tables)) > NPF_MAX_TABLES) { error = E2BIG; goto fail; } tblset = npf_tableset_create(nitems); error = npf_mk_tables(tblset, tables, errdict); if (error) { goto fail; } /* Rule procedures. */ rprocs = prop_dictionary_get(npf_dict, "rprocs"); if ((nitems = prop_array_count(rprocs)) > NPF_MAX_RPROCS) { error = E2BIG; goto fail; } rpset = npf_rprocset_create(); error = npf_mk_rprocs(rpset, rprocs, errdict); if (error) { goto fail; } /* Rules. */ rules = prop_dictionary_get(npf_dict, "rules"); if ((nitems = prop_array_count(rules)) > NPF_MAX_RULES) { error = E2BIG; goto fail; } rlset = npf_ruleset_create(nitems); error = npf_mk_rules(rlset, rules, rpset, errdict); if (error) { goto fail; } /* Connections (if loading any). */ if ((conlist = prop_dictionary_get(npf_dict, "conn-list")) != NULL) { error = npf_mk_connlist(conlist, nset, &conndb, errdict); if (error) { goto fail; } } flush = false; prop_dictionary_get_bool(npf_dict, "flush", &flush); /* * Finally - perform the load. */ npf_config_load(rlset, tblset, nset, rpset, conndb, flush); /* Done. Since data is consumed now, we shall not destroy it. */ tblset = NULL; rpset = NULL; rlset = NULL; nset = NULL; fail: /* * Note: destroy rulesets first, to drop references to the tableset. */ KASSERT(error == 0 || (nset || rpset || rlset || tblset)); if (nset) { npf_ruleset_destroy(nset); } if (rlset) { npf_ruleset_destroy(rlset); } if (rpset) { npf_rprocset_destroy(rpset); } if (tblset) { npf_tableset_destroy(tblset); } prop_object_release(npf_dict); /* Error report. */ #ifndef _NPF_TESTING prop_dictionary_set_int32(errdict, "errno", error); prop_dictionary_copyout_ioctl(pref, cmd, errdict); prop_object_release(errdict); error = 0; #endif return error; }
/* * npfctl_reload: store passed data i.e. update settings, create passed * tables, rules and atomically activate all them. */ int npfctl_reload(u_long cmd, void *data) { struct plistref *pref = data; prop_dictionary_t npf_dict, errdict; prop_array_t natlist, tables, rprocs, rules; npf_tableset_t *tblset = NULL; npf_ruleset_t *rlset = NULL; npf_ruleset_t *nset = NULL; bool flush; int error; /* Retrieve the dictionary. */ #ifndef _NPF_TESTING error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict); if (error) return error; #else npf_dict = (prop_dictionary_t)pref; #endif /* Dictionary for error reporting. */ errdict = prop_dictionary_create(); /* NAT policies. */ nset = npf_ruleset_create(); natlist = prop_dictionary_get(npf_dict, "translation"); error = npf_mk_natlist(nset, natlist, errdict); if (error) { goto fail; } /* Tables. */ tblset = npf_tableset_create(); tables = prop_dictionary_get(npf_dict, "tables"); error = npf_mk_tables(tblset, tables, errdict); if (error) { goto fail; } /* Rules and rule procedures. */ rlset = npf_ruleset_create(); rprocs = prop_dictionary_get(npf_dict, "rprocs"); rules = prop_dictionary_get(npf_dict, "rules"); error = npf_mk_rules(rlset, rules, rprocs, errdict); if (error) { goto fail; } flush = false; prop_dictionary_get_bool(npf_dict, "flush", &flush); /* * Finally - reload ruleset, tableset and NAT policies. * Operation will be performed as a single transaction. */ npf_reload(npf_dict, rlset, tblset, nset, flush); /* Turn on/off session tracking accordingly. */ npf_session_tracking(!flush); /* Done. Since data is consumed now, we shall not destroy it. */ tblset = NULL; rlset = NULL; nset = NULL; fail: /* * Note: destroy rulesets first, to drop references to the tableset. */ KASSERT(error == 0 || (nset || rlset || tblset)); if (nset) { npf_ruleset_destroy(nset); } if (rlset) { npf_ruleset_destroy(rlset); } if (tblset) { npf_tableset_destroy(tblset); } if (error) { prop_object_release(npf_dict); } /* Error report. */ prop_dictionary_set_int32(errdict, "errno", error); #ifndef _NPF_TESTING prop_dictionary_copyout_ioctl(pref, cmd, errdict); #endif prop_object_release(errdict); return 0; }