Annotation of src/sys/net/npf/npf_conf.c, Revision 1.13.2.2
1.1 rmind 1: /*-
2: * Copyright (c) 2013 The NetBSD Foundation, Inc.
3: * All rights reserved.
4: *
5: * This material is based upon work partially supported by The
6: * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27: * POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: /*
31: * NPF config loading mechanism.
32: *
33: * There are few main operations on the config:
34: * 1) Read access which is primarily from the npf_packet_handler() et al.
35: * 2) Write access on particular set, mainly rule or table updates.
36: * 3) Deletion of the config, which is done during the reload operation.
37: *
38: * Synchronisation
39: *
40: * For (1) case, passive serialisation is used to allow concurrent
41: * access to the configuration set (ruleset, etc). It guarantees
42: * that the config will not be destroyed while accessing it.
43: *
44: * Writers, i.e. cases (2) and (3) use mutual exclusion and when
45: * necessary writer-side barrier of the passive serialisation.
46: */
47:
1.10 christos 48: #ifdef _KERNEL
1.1 rmind 49: #include <sys/cdefs.h>
1.13.2.2! martin 50: __KERNEL_RCSID(0, "$NetBSD: npf_conf.c,v 1.13.2.1 2019/08/13 14:35:55 martin Exp $");
1.1 rmind 51:
52: #include <sys/param.h>
53: #include <sys/types.h>
54:
55: #include <sys/atomic.h>
56: #include <sys/kmem.h>
57: #include <sys/mutex.h>
1.10 christos 58: #endif
1.1 rmind 59:
60: #include "npf_impl.h"
1.7 rmind 61: #include "npf_conn.h"
1.1 rmind 62:
63: void
1.10 christos 64: npf_config_init(npf_t *npf)
1.1 rmind 65: {
1.13.2.2! martin 66: npf_config_t *nc;
1.1 rmind 67:
1.10 christos 68: mutex_init(&npf->config_lock, MUTEX_DEFAULT, IPL_SOFTNET);
1.13.2.2! martin 69: nc = npf_config_create();
! 70:
! 71: /*
! 72: * Load an empty configuration.
! 73: */
! 74: nc->ruleset = npf_ruleset_create(0);
! 75: nc->nat_ruleset = npf_ruleset_create(0);
! 76: nc->rule_procs = npf_rprocset_create();
! 77: nc->tableset = npf_tableset_create(0);
! 78: nc->default_pass = true;
1.1 rmind 79:
1.13.2.2! martin 80: npf_config_load(npf, nc, NULL, true);
1.10 christos 81: KASSERT(npf->config != NULL);
1.1 rmind 82: }
83:
1.13.2.2! martin 84: npf_config_t *
! 85: npf_config_create(void)
! 86: {
! 87: return kmem_zalloc(sizeof(npf_config_t), KM_SLEEP);
! 88: }
! 89:
! 90: void
1.1 rmind 91: npf_config_destroy(npf_config_t *nc)
92: {
1.13.2.2! martin 93: /*
! 94: * Note: the rulesets must be destroyed first, in order to drop
! 95: * any references to the tableset.
! 96: */
! 97: npf_ruleset_destroy(nc->ruleset);
! 98: npf_ruleset_destroy(nc->nat_ruleset);
! 99: npf_rprocset_destroy(nc->rule_procs);
! 100: npf_tableset_destroy(nc->tableset);
1.1 rmind 101: kmem_free(nc, sizeof(npf_config_t));
102: }
103:
104: void
1.10 christos 105: npf_config_fini(npf_t *npf)
1.1 rmind 106: {
1.9 rmind 107: npf_conndb_t *cd = npf_conndb_create();
108:
1.7 rmind 109: /* Flush the connections. */
1.10 christos 110: mutex_enter(&npf->config_lock);
111: npf_conn_tracking(npf, false);
1.13.2.2! martin 112: npf_ebr_full_sync(npf->ebr);
1.10 christos 113: npf_conn_load(npf, cd, false);
114: npf_ifmap_flush(npf);
115: mutex_exit(&npf->config_lock);
116:
117: npf_config_destroy(npf->config);
118: mutex_destroy(&npf->config_lock);
1.1 rmind 119: }
120:
121: /*
1.7 rmind 122: * npf_config_load: the main routine performing configuration load.
1.1 rmind 123: * Performs the necessary synchronisation and destroys the old config.
124: */
125: void
1.13.2.2! martin 126: npf_config_load(npf_t *npf, npf_config_t *nc, npf_conndb_t *conns, bool flush)
1.1 rmind 127: {
1.9 rmind 128: const bool load = conns != NULL;
1.13.2.2! martin 129: npf_config_t *onc;
1.1 rmind 130:
1.13.2.2! martin 131: nc->default_pass = flush;
1.1 rmind 132:
133: /*
134: * Acquire the lock and perform the first phase:
135: * - Scan and use existing dynamic tables, reload only static.
136: * - Scan and use matching NAT policies to preserve the connections.
137: */
1.10 christos 138: mutex_enter(&npf->config_lock);
139: if ((onc = npf->config) != NULL) {
1.13.2.2! martin 140: npf_ruleset_reload(npf, nc->ruleset, onc->ruleset, load);
! 141: npf_tableset_reload(npf, nc->tableset, onc->tableset);
! 142: npf_ruleset_reload(npf, nc->nat_ruleset, onc->nat_ruleset, load);
1.1 rmind 143: }
144:
145: /*
146: * Set the new config and release the lock.
147: */
148: membar_sync();
1.10 christos 149: npf->config = nc;
1.1 rmind 150: if (onc == NULL) {
151: /* Initial load, done. */
1.10 christos 152: npf_ifmap_flush(npf);
153: npf_conn_load(npf, conns, !flush);
154: mutex_exit(&npf->config_lock);
1.11 rmind 155: goto done;
1.1 rmind 156: }
157:
1.7 rmind 158: /*
159: * If we are going to flush the connections or load the new ones,
160: * then disable the connection tracking for the grace period.
161: */
162: if (flush || conns) {
1.10 christos 163: npf_conn_tracking(npf, false);
1.7 rmind 164: }
165:
1.1 rmind 166: /* Synchronise: drain all references. */
1.13.2.2! martin 167: npf_ebr_full_sync(npf->ebr);
1.3 rmind 168: if (flush) {
1.13.2.1 martin 169: npf_portmap_flush(npf->portmap);
1.10 christos 170: npf_ifmap_flush(npf);
1.3 rmind 171: }
1.5 rmind 172:
1.7 rmind 173: /*
174: * G/C the existing connections and, if passed, load the new ones.
175: * If not flushing - enable the connection tracking.
176: */
1.10 christos 177: npf_conn_load(npf, conns, !flush);
178: mutex_exit(&npf->config_lock);
1.1 rmind 179:
180: /* Finally, it is safe to destroy the old config. */
181: npf_config_destroy(onc);
1.11 rmind 182: done:
183: /* Sync all interface address tables (can be done asynchronously). */
184: npf_ifaddr_syncall(npf);
1.1 rmind 185: }
186:
187: /*
188: * Writer-side exclusive locking.
189: */
190:
1.13.2.2! martin 191: npf_config_t *
1.10 christos 192: npf_config_enter(npf_t *npf)
1.1 rmind 193: {
1.10 christos 194: mutex_enter(&npf->config_lock);
1.13.2.2! martin 195: return npf->config;
1.1 rmind 196: }
197:
198: void
1.10 christos 199: npf_config_exit(npf_t *npf)
1.1 rmind 200: {
1.10 christos 201: mutex_exit(&npf->config_lock);
1.1 rmind 202: }
203:
204: bool
1.10 christos 205: npf_config_locked_p(npf_t *npf)
1.1 rmind 206: {
1.10 christos 207: return mutex_owned(&npf->config_lock);
1.1 rmind 208: }
209:
1.2 rmind 210: void
1.10 christos 211: npf_config_sync(npf_t *npf)
1.2 rmind 212: {
1.10 christos 213: KASSERT(npf_config_locked_p(npf));
1.13.2.2! martin 214: npf_ebr_full_sync(npf->ebr);
1.2 rmind 215: }
216:
1.1 rmind 217: /*
218: * Reader-side synchronisation routines.
219: */
220:
221: int
1.13.2.2! martin 222: npf_config_read_enter(npf_t *npf)
1.1 rmind 223: {
1.13.2.2! martin 224: return npf_ebr_enter(npf->ebr);
1.1 rmind 225: }
226:
227: void
1.13.2.2! martin 228: npf_config_read_exit(npf_t *npf, int s)
1.1 rmind 229: {
1.13.2.2! martin 230: npf_ebr_exit(npf->ebr, s);
1.1 rmind 231: }
232:
233: /*
234: * Accessors.
235: */
236:
237: npf_ruleset_t *
1.10 christos 238: npf_config_ruleset(npf_t *npf)
1.1 rmind 239: {
1.13.2.2! martin 240: KASSERT(npf_config_locked_p(npf) || npf_ebr_incrit_p(npf->ebr));
! 241: return npf->config->ruleset;
1.1 rmind 242: }
243:
244: npf_ruleset_t *
1.10 christos 245: npf_config_natset(npf_t *npf)
1.1 rmind 246: {
1.13.2.2! martin 247: KASSERT(npf_config_locked_p(npf) || npf_ebr_incrit_p(npf->ebr));
! 248: return npf->config->nat_ruleset;
1.1 rmind 249: }
250:
251: npf_tableset_t *
1.10 christos 252: npf_config_tableset(npf_t *npf)
1.1 rmind 253: {
1.13.2.2! martin 254: KASSERT(npf_config_locked_p(npf) || npf_ebr_incrit_p(npf->ebr));
! 255: return npf->config->tableset;
1.1 rmind 256: }
257:
258: bool
1.10 christos 259: npf_default_pass(npf_t *npf)
1.1 rmind 260: {
1.13.2.2! martin 261: KASSERT(npf_config_locked_p(npf) || npf_ebr_incrit_p(npf->ebr));
! 262: return npf->config->default_pass;
1.1 rmind 263: }
CVSweb <webmaster@jp.NetBSD.org>