| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: npf_rproc.c,v 1.8 2013/03/11 01:43:50 christos Exp $ */ | | 1 | /* $NetBSD: npf_rproc.c,v 1.9 2013/03/11 01:56:37 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This material is based upon work partially supported by The | | 7 | * This material is based upon work partially supported by The |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -92,64 +92,64 @@ npf_ext_sysfini(void) | | | @@ -92,64 +92,64 @@ npf_ext_sysfini(void) |
92 | { | | 92 | { |
93 | KASSERT(LIST_EMPTY(&ext_list)); | | 93 | KASSERT(LIST_EMPTY(&ext_list)); |
94 | mutex_destroy(&ext_lock); | | 94 | mutex_destroy(&ext_lock); |
95 | } | | 95 | } |
96 | | | 96 | |
97 | /* | | 97 | /* |
98 | * NPF extension management for the rule procedures. | | 98 | * NPF extension management for the rule procedures. |
99 | */ | | 99 | */ |
100 | | | 100 | |
101 | static const char npf_ext_prefix[] = "npf_ext_"; | | 101 | static const char npf_ext_prefix[] = "npf_ext_"; |
102 | #define NPF_EXT_PREFLEN (sizeof(npf_ext_prefix) - 1) | | 102 | #define NPF_EXT_PREFLEN (sizeof(npf_ext_prefix) - 1) |
103 | | | 103 | |
104 | static npf_ext_t * | | 104 | static npf_ext_t * |
105 | npf_ext_lookup(const char *name) | | 105 | npf_ext_lookup(const char *name, bool autoload) |
106 | { | | 106 | { |
107 | npf_ext_t *ext; | | 107 | npf_ext_t *ext; |
108 | char modname[RPROC_NAME_LEN + NPF_EXT_PREFLEN]; | | 108 | char modname[RPROC_NAME_LEN + NPF_EXT_PREFLEN]; |
109 | int error, loaded = 0; | | 109 | int error; |
110 | | | 110 | |
111 | KASSERT(mutex_owned(&ext_lock)); | | 111 | KASSERT(mutex_owned(&ext_lock)); |
112 | | | 112 | |
113 | again: | | 113 | again: |
114 | LIST_FOREACH(ext, &ext_list, ext_entry) | | 114 | LIST_FOREACH(ext, &ext_list, ext_entry) |
115 | if (strcmp(ext->ext_callname, name) == 0) | | 115 | if (strcmp(ext->ext_callname, name) == 0) |
116 | break; | | 116 | break; |
117 | | | 117 | |
118 | if (ext != NULL || loaded != 0) | | 118 | if (ext != NULL || !autoload) |
119 | return ext; | | 119 | return ext; |
120 | | | 120 | |
121 | mutex_exit(&ext_lock); | | 121 | mutex_exit(&ext_lock); |
122 | loaded++; | | 122 | autoload = false; |
123 | snprintf(modname, sizeof(modname), "%s%s", npf_ext_prefix, name); | | 123 | snprintf(modname, sizeof(modname), "%s%s", npf_ext_prefix, name); |
124 | error = module_autoload(modname, MODULE_CLASS_MISC); | | 124 | error = module_autoload(modname, MODULE_CLASS_MISC); |
125 | mutex_enter(&ext_lock); | | 125 | mutex_enter(&ext_lock); |
126 | | | 126 | |
127 | if (error) | | 127 | if (error) |
128 | return NULL; | | 128 | return NULL; |
129 | goto again; | | 129 | goto again; |
130 | } | | 130 | } |
131 | | | 131 | |
132 | void * | | 132 | void * |
133 | npf_ext_register(const char *name, const npf_ext_ops_t *ops) | | 133 | npf_ext_register(const char *name, const npf_ext_ops_t *ops) |
134 | { | | 134 | { |
135 | npf_ext_t *ext; | | 135 | npf_ext_t *ext; |
136 | | | 136 | |
137 | ext = kmem_zalloc(sizeof(npf_ext_t), KM_SLEEP); | | 137 | ext = kmem_zalloc(sizeof(npf_ext_t), KM_SLEEP); |
138 | strlcpy(ext->ext_callname, name, EXT_NAME_LEN); | | 138 | strlcpy(ext->ext_callname, name, EXT_NAME_LEN); |
139 | ext->ext_ops = ops; | | 139 | ext->ext_ops = ops; |
140 | | | 140 | |
141 | mutex_enter(&ext_lock); | | 141 | mutex_enter(&ext_lock); |
142 | if (npf_ext_lookup(name)) { | | 142 | if (npf_ext_lookup(name, false)) { |
143 | mutex_exit(&ext_lock); | | 143 | mutex_exit(&ext_lock); |
144 | kmem_free(ext, sizeof(npf_ext_t)); | | 144 | kmem_free(ext, sizeof(npf_ext_t)); |
145 | return NULL; | | 145 | return NULL; |
146 | } | | 146 | } |
147 | LIST_INSERT_HEAD(&ext_list, ext, ext_entry); | | 147 | LIST_INSERT_HEAD(&ext_list, ext, ext_entry); |
148 | mutex_exit(&ext_lock); | | 148 | mutex_exit(&ext_lock); |
149 | | | 149 | |
150 | return (void *)ext; | | 150 | return (void *)ext; |
151 | } | | 151 | } |
152 | | | 152 | |
153 | int | | 153 | int |
154 | npf_ext_unregister(void *extid) | | 154 | npf_ext_unregister(void *extid) |
155 | { | | 155 | { |
| @@ -157,48 +157,48 @@ npf_ext_unregister(void *extid) | | | @@ -157,48 +157,48 @@ npf_ext_unregister(void *extid) |
157 | | | 157 | |
158 | /* | | 158 | /* |
159 | * Check if in-use first (re-check with the lock held). | | 159 | * Check if in-use first (re-check with the lock held). |
160 | */ | | 160 | */ |
161 | if (ext->ext_refcnt) { | | 161 | if (ext->ext_refcnt) { |
162 | return EBUSY; | | 162 | return EBUSY; |
163 | } | | 163 | } |
164 | | | 164 | |
165 | mutex_enter(&ext_lock); | | 165 | mutex_enter(&ext_lock); |
166 | if (ext->ext_refcnt) { | | 166 | if (ext->ext_refcnt) { |
167 | mutex_exit(&ext_lock); | | 167 | mutex_exit(&ext_lock); |
168 | return EBUSY; | | 168 | return EBUSY; |
169 | } | | 169 | } |
170 | KASSERT(npf_ext_lookup(ext->ext_callname)); | | 170 | KASSERT(npf_ext_lookup(ext->ext_callname, false)); |
171 | LIST_REMOVE(ext, ext_entry); | | 171 | LIST_REMOVE(ext, ext_entry); |
172 | mutex_exit(&ext_lock); | | 172 | mutex_exit(&ext_lock); |
173 | | | 173 | |
174 | kmem_free(ext, sizeof(npf_ext_t)); | | 174 | kmem_free(ext, sizeof(npf_ext_t)); |
175 | return 0; | | 175 | return 0; |
176 | } | | 176 | } |
177 | | | 177 | |
178 | int | | 178 | int |
179 | npf_ext_construct(const char *name, npf_rproc_t *rp, prop_dictionary_t params) | | 179 | npf_ext_construct(const char *name, npf_rproc_t *rp, prop_dictionary_t params) |
180 | { | | 180 | { |
181 | const npf_ext_ops_t *extops; | | 181 | const npf_ext_ops_t *extops; |
182 | npf_ext_t *ext; | | 182 | npf_ext_t *ext; |
183 | unsigned i; | | 183 | unsigned i; |
184 | int error; | | 184 | int error; |
185 | | | 185 | |
186 | if (rp->rp_ext_count >= RPROC_EXT_COUNT) { | | 186 | if (rp->rp_ext_count >= RPROC_EXT_COUNT) { |
187 | return ENOSPC; | | 187 | return ENOSPC; |
188 | } | | 188 | } |
189 | | | 189 | |
190 | mutex_enter(&ext_lock); | | 190 | mutex_enter(&ext_lock); |
191 | ext = npf_ext_lookup(name); | | 191 | ext = npf_ext_lookup(name, true); |
192 | if (ext) { | | 192 | if (ext) { |
193 | atomic_inc_uint(&ext->ext_refcnt); | | 193 | atomic_inc_uint(&ext->ext_refcnt); |
194 | } | | 194 | } |
195 | mutex_exit(&ext_lock); | | 195 | mutex_exit(&ext_lock); |
196 | | | 196 | |
197 | if (!ext) { | | 197 | if (!ext) { |
198 | return ENOENT; | | 198 | return ENOENT; |
199 | } | | 199 | } |
200 | | | 200 | |
201 | extops = ext->ext_ops; | | 201 | extops = ext->ext_ops; |
202 | KASSERT(extops != NULL); | | 202 | KASSERT(extops != NULL); |
203 | | | 203 | |
204 | error = extops->ctor(rp, params); | | 204 | error = extops->ctor(rp, params); |