static int npf_fini(void) { /* At first, detach device and remove pfil hooks. */ #ifdef _MODULE devsw_detach(NULL, &npf_cdevsw); #endif npf_pfil_unregister(true); /* Flush all sessions, destroy configuration (ruleset, etc). */ npf_session_tracking(false); npf_config_fini(); /* Finally, safe to destroy the subsystems. */ npf_ext_sysfini(); npf_alg_sysfini(); npf_nat_sysfini(); npf_session_sysfini(); npf_tableset_sysfini(); npf_bpf_sysfini(); /* Note: worker is the last. */ npf_worker_sysfini(); if (npf_sysctl) { sysctl_teardown(&npf_sysctl); } percpu_free(npf_stats_percpu, NPF_STATS_SIZE); return 0; }
/* * 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; }