BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file net_iptables.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * iptables and ebtables module.
32 *
33 * Note that all iptables/ebtables commands (in general) must be issued synchronously, or
34 * the kernel may randomly report errors if there is another iptables/ebtables command in
35 * progress. To solve this, the NCD process contains a single "iptables lock". All
36 * iptables/ebtables commands exposed here go through that lock.
37 * In case you wish to call iptables/ebtables directly, the lock is exposed via
38 * net.iptables.lock().
39 *
40 * The append and insert commands, instead of using the variable-argument form below
41 * as documented below, may alternatively be called with a single list argument.
42 *
43 * Synopsis:
44 * net.iptables.append(string table, string chain, string arg1 ...)
45 * Description:
46 * init: iptables -t table -A chain arg1 ...
47 * deinit: iptables -t table -D chain arg1 ...
48 *
49 * Synopsis:
50 * net.iptables.insert(string table, string chain, string arg1 ...)
51 * Description:
52 * init: iptables -t table -I chain arg1 ...
53 * deinit: iptables -t table -D chain arg1 ...
54 *
55 * Synopsis:
56 * net.iptables.policy(string table, string chain, string target, string revert_target)
57 * Description:
58 * init: iptables -t table -P chain target
59 * deinit: iptables -t table -P chain revert_target
60 *
61 * Synopsis:
62 * net.iptables.newchain(string table, string chain)
63 * net.iptables.newchain(string chain) // DEPRECATED, defaults to table="filter"
64 * Description:
65 * init: iptables -t table -N chain
66 * deinit: iptables -t table -X chain
67 *
68 * Synopsis:
69 * net.ebtables.append(string table, string chain, string arg1 ...)
70 * Description:
71 * init: ebtables -t table -A chain arg1 ...
72 * deinit: ebtables -t table -D chain arg1 ...
73 *
74 * Synopsis:
75 * net.ebtables.insert(string table, string chain, string arg1 ...)
76 * Description:
77 * init: ebtables -t table -I chain arg1 ...
78 * deinit: ebtables -t table -D chain arg1 ...
79 *
80 * Synopsis:
81 * net.ebtables.policy(string table, string chain, string target, string revert_target)
82 * Description:
83 * init: ebtables -t table -P chain target
84 * deinit: ebtables -t table -P chain revert_target
85 *
86 * Synopsis:
87 * net.ebtables.newchain(string table, string chain)
88 * Description:
89 * init: ebtables -t table -N chain
90 * deinit: ebtables -t table -X chain
91 *
92 * Synopsis:
93 * net.iptables.lock()
94 * Description:
95 * Use at the beginning of a block of custom iptables/ebtables commands to make sure
96 * they do not interfere with other iptables/ebtables commands.
97 * WARNING: improper usage of the lock can lead to deadlock. In particular:
98 * - Do not call any of the iptables/ebtables wrappers above from a lock section;
99 * those will attempt to aquire the lock themselves.
100 * - Do not enter another lock section from a lock section.
101 * - Do not perform any potentially long wait from a lock section.
102 *
103 * Synopsis:
104 * net.iptables.lock::unlock()
105 * Description:
106 * Use at the end of a block of custom iptables/ebtables commands to make sure
107 * they do not interfere with other iptables/ebtables commands.
108 */
109  
110 #include <stdlib.h>
111 #include <string.h>
112 #include <unistd.h>
113  
114 #include <misc/debug.h>
115 #include <misc/find_program.h>
116 #include <misc/balloc.h>
117 #include <ncd/modules/command_template.h>
118  
119 #include <ncd/module_common.h>
120  
121 #include <generated/blog_channel_ncd_net_iptables.h>
122  
123 static void template_free_func (void *vo, int is_error);
124  
125 struct global {
126 BEventLock iptables_lock;
127 };
128  
129 struct instance {
130 NCDModuleInst *i;
131 command_template_instance cti;
132 };
133  
134 struct unlock_instance;
135  
136 #define LOCK_STATE_LOCKING 1
137 #define LOCK_STATE_LOCKED 2
138 #define LOCK_STATE_UNLOCKED 3
139 #define LOCK_STATE_RELOCKING 4
140  
141 struct lock_instance {
142 NCDModuleInst *i;
143 BEventLockJob lock_job;
144 struct unlock_instance *unlock;
145 int state;
146 };
147  
148 struct unlock_instance {
149 NCDModuleInst *i;
150 struct lock_instance *lock;
151 };
152  
153 static void unlock_free (struct unlock_instance *o);
154  
155 static int build_append_or_insert_cmdline (NCDModuleInst *i, NCDValRef args, const char *prog, int remove, char **exec, CmdLine *cl, const char *type)
156 {
157 if (NCDVal_ListRead(args, 1, &args) && !NCDVal_IsList(args)) {
158 ModuleLog(i, BLOG_ERROR, "in one-argument form a list is expected");
159 goto fail0;
160 }
161  
162 // read arguments
163 NCDValRef table_arg;
164 NCDValRef chain_arg;
165 if (!NCDVal_ListReadHead(args, 2, &table_arg, &chain_arg)) {
166 ModuleLog(i, BLOG_ERROR, "wrong arity");
167 goto fail0;
168 }
169 if (!NCDVal_IsStringNoNulls(table_arg) || !NCDVal_IsStringNoNulls(chain_arg)) {
170 ModuleLog(i, BLOG_ERROR, "wrong type");
171 goto fail0;
172 }
173 MemRef table = NCDVal_StringMemRef(table_arg);
174 MemRef chain = NCDVal_StringMemRef(chain_arg);
175  
176 // find program
177 if (!(*exec = badvpn_find_program(prog))) {
178 ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
179 goto fail0;
180 }
181  
182 // start cmdline
183 if (!CmdLine_Init(cl)) {
184 ModuleLog(i, BLOG_ERROR, "CmdLine_Init failed");
185 goto fail1;
186 }
187  
188 // add header
189 if (!CmdLine_Append(cl, *exec) || !CmdLine_Append(cl, "-t") || !CmdLine_AppendNoNullMr(cl, table) || !CmdLine_Append(cl, (remove ? "-D" : type)) || !CmdLine_AppendNoNullMr(cl, chain)) {
190 ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
191 goto fail2;
192 }
193  
194 // add additional arguments
195 size_t count = NCDVal_ListCount(args);
196 for (size_t j = 2; j < count; j++) {
197 NCDValRef arg = NCDVal_ListGet(args, j);
198  
199 if (!NCDVal_IsStringNoNulls(arg)) {
200 ModuleLog(i, BLOG_ERROR, "wrong type");
201 goto fail2;
202 }
203  
204 if (!CmdLine_AppendNoNullMr(cl, NCDVal_StringMemRef(arg))) {
205 ModuleLog(i, BLOG_ERROR, "CmdLine_AppendNoNullMr failed");
206 goto fail2;
207 }
208 }
209  
210 // finish
211 if (!CmdLine_Finish(cl)) {
212 ModuleLog(i, BLOG_ERROR, "CmdLine_Finish failed");
213 goto fail2;
214 }
215  
216 return 1;
217  
218 fail2:
219 CmdLine_Free(cl);
220 fail1:
221 free(*exec);
222 fail0:
223 return 0;
224 }
225  
226 static int build_append_cmdline (NCDModuleInst *i, NCDValRef args, const char *prog, int remove, char **exec, CmdLine *cl)
227 {
228 return build_append_or_insert_cmdline(i, args, prog, remove, exec, cl, "-A");
229 }
230  
231 static int build_insert_cmdline (NCDModuleInst *i, NCDValRef args, const char *prog, int remove, char **exec, CmdLine *cl)
232 {
233 return build_append_or_insert_cmdline(i, args, prog, remove, exec, cl, "-I");
234 }
235  
236 static int build_policy_cmdline (NCDModuleInst *i, NCDValRef args, const char *prog, int remove, char **exec, CmdLine *cl)
237 {
238 // read arguments
239 NCDValRef table_arg;
240 NCDValRef chain_arg;
241 NCDValRef target_arg;
242 NCDValRef revert_target_arg;
243 if (!NCDVal_ListRead(args, 4, &table_arg, &chain_arg, &target_arg, &revert_target_arg)) {
244 ModuleLog(i, BLOG_ERROR, "wrong arity");
245 goto fail0;
246 }
247 if (!NCDVal_IsStringNoNulls(table_arg) || !NCDVal_IsStringNoNulls(chain_arg) ||
248 !NCDVal_IsStringNoNulls(target_arg) || !NCDVal_IsStringNoNulls(revert_target_arg)
249 ) {
250 ModuleLog(i, BLOG_ERROR, "wrong type");
251 goto fail0;
252 }
253 MemRef table = NCDVal_StringMemRef(table_arg);
254 MemRef chain = NCDVal_StringMemRef(chain_arg);
255 MemRef target = NCDVal_StringMemRef(target_arg);
256 MemRef revert_target = NCDVal_StringMemRef(revert_target_arg);
257  
258 // find program
259 if (!(*exec = badvpn_find_program(prog))) {
260 ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
261 goto fail0;
262 }
263  
264 // start cmdline
265 if (!CmdLine_Init(cl)) {
266 ModuleLog(i, BLOG_ERROR, "CmdLine_Init failed");
267 goto fail1;
268 }
269  
270 // add arguments
271 if (!CmdLine_Append(cl, *exec) || !CmdLine_Append(cl, "-t") || !CmdLine_AppendNoNullMr(cl, table) ||
272 !CmdLine_Append(cl, "-P") || !CmdLine_AppendNoNullMr(cl, chain) ||
273 !CmdLine_AppendNoNullMr(cl, (remove ? revert_target : target))
274 ) {
275 ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
276 goto fail2;
277 }
278  
279 // finish
280 if (!CmdLine_Finish(cl)) {
281 ModuleLog(i, BLOG_ERROR, "CmdLine_Finish failed");
282 goto fail2;
283 }
284  
285 return 1;
286  
287 fail2:
288 CmdLine_Free(cl);
289 fail1:
290 free(*exec);
291 fail0:
292 return 0;
293 }
294  
295 static int build_newchain_cmdline (NCDModuleInst *i, NCDValRef args, const char *prog, int remove, char **exec, CmdLine *cl)
296 {
297 // read arguments
298 NCDValRef table_arg = NCDVal_NewInvalid();
299 NCDValRef chain_arg;
300 if (!NCDVal_ListRead(args, 1, &chain_arg) && !NCDVal_ListRead(args, 2, &table_arg, &chain_arg)) {
301 ModuleLog(i, BLOG_ERROR, "wrong arity");
302 goto fail0;
303 }
304 if ((!NCDVal_IsInvalid(table_arg) && !NCDVal_IsStringNoNulls(table_arg)) || !NCDVal_IsStringNoNulls(chain_arg)) {
305 ModuleLog(i, BLOG_ERROR, "wrong type");
306 goto fail0;
307 }
308 MemRef table = NCDVal_IsInvalid(table_arg) ? MemRef_MakeCstr("filter") : NCDVal_StringMemRef(table_arg);
309 MemRef chain = NCDVal_StringMemRef(chain_arg);
310  
311 // find program
312 if (!(*exec = badvpn_find_program(prog))) {
313 ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
314 goto fail0;
315 }
316  
317 // start cmdline
318 if (!CmdLine_Init(cl)) {
319 ModuleLog(i, BLOG_ERROR, "CmdLine_Init failed");
320 goto fail1;
321 }
322  
323 // add arguments
324 if (!CmdLine_AppendMulti(cl, 2, *exec, "-t") ||
325 !CmdLine_AppendNoNullMr(cl, table) ||
326 !CmdLine_Append(cl, (remove ? "-X" : "-N")) ||
327 !CmdLine_AppendNoNullMr(cl, chain)
328 ) {
329 ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
330 goto fail2;
331 }
332  
333 // finish
334 if (!CmdLine_Finish(cl)) {
335 ModuleLog(i, BLOG_ERROR, "CmdLine_Finish failed");
336 goto fail2;
337 }
338  
339 return 1;
340  
341 fail2:
342 CmdLine_Free(cl);
343 fail1:
344 free(*exec);
345 fail0:
346 return 0;
347 }
348  
349 static int build_iptables_append_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
350 {
351 return build_append_cmdline(i, args, "iptables", remove, exec, cl);
352 }
353  
354 static int build_iptables_insert_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
355 {
356 return build_insert_cmdline(i, args, "iptables", remove, exec, cl);
357 }
358  
359 static int build_iptables_policy_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
360 {
361 return build_policy_cmdline(i, args, "iptables", remove, exec, cl);
362 }
363  
364 static int build_iptables_newchain_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
365 {
366 return build_newchain_cmdline(i, args, "iptables", remove, exec, cl);
367 }
368  
369 static int build_ip6tables_append_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
370 {
371 return build_append_cmdline(i, args, "ip6tables", remove, exec, cl);
372 }
373  
374 static int build_ip6tables_insert_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
375 {
376 return build_insert_cmdline(i, args, "ip6tables", remove, exec, cl);
377 }
378  
379 static int build_ip6tables_policy_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
380 {
381 return build_policy_cmdline(i, args, "ip6tables", remove, exec, cl);
382 }
383  
384 static int build_ip6tables_newchain_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
385 {
386 return build_newchain_cmdline(i, args, "ip6tables", remove, exec, cl);
387 }
388  
389 static int build_ebtables_append_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
390 {
391 return build_append_cmdline(i, args, "ebtables", remove, exec, cl);
392 }
393  
394 static int build_ebtables_insert_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
395 {
396 return build_insert_cmdline(i, args, "ebtables", remove, exec, cl);
397 }
398  
399 static int build_ebtables_policy_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
400 {
401 return build_policy_cmdline(i, args, "ebtables", remove, exec, cl);
402 }
403  
404 static int build_ebtables_newchain_cmdline (NCDModuleInst *i, NCDValRef args, int remove, char **exec, CmdLine *cl)
405 {
406 return build_newchain_cmdline(i, args, "ebtables", remove, exec, cl);
407 }
408  
409 static void lock_job_handler (struct lock_instance *o)
410 {
411 ASSERT(o->state == LOCK_STATE_LOCKING || o->state == LOCK_STATE_RELOCKING)
412  
413 if (o->state == LOCK_STATE_LOCKING) {
414 ASSERT(!o->unlock)
415  
416 // up
417 NCDModuleInst_Backend_Up(o->i);
418  
419 // set state locked
420 o->state = LOCK_STATE_LOCKED;
421 }
422 else if (o->state == LOCK_STATE_RELOCKING) {
423 ASSERT(o->unlock)
424 ASSERT(o->unlock->lock == o)
425  
426 // die unlock
427 unlock_free(o->unlock);
428 o->unlock = NULL;
429  
430 // set state locked
431 o->state = LOCK_STATE_LOCKED;
432 }
433 }
434  
435 static int func_globalinit (struct NCDInterpModuleGroup *group, const struct NCDModuleInst_iparams *params)
436 {
437 // allocate global state structure
438 struct global *g = BAlloc(sizeof(*g));
439 if (!g) {
440 BLog(BLOG_ERROR, "BAlloc failed");
441 return 0;
442 }
443  
444 // set group state pointer
445 group->group_state = g;
446  
447 // init iptables lock
448 BEventLock_Init(&g->iptables_lock, BReactor_PendingGroup(params->reactor));
449  
450 return 1;
451 }
452  
453 static void func_globalfree (struct NCDInterpModuleGroup *group)
454 {
455 struct global *g = group->group_state;
456  
457 // free iptables lock
458 BEventLock_Free(&g->iptables_lock);
459  
460 // free global state structure
461 BFree(g);
462 }
463  
464 static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params, command_template_build_cmdline build_cmdline)
465 {
466 struct global *g = ModuleGlobal(i);
467 struct instance *o = vo;
468 o->i = i;
469  
470 command_template_new(&o->cti, i, params, build_cmdline, template_free_func, o, BLOG_CURRENT_CHANNEL, &g->iptables_lock);
471 }
472  
473 void template_free_func (void *vo, int is_error)
474 {
475 struct instance *o = vo;
476  
477 if (is_error) {
478 NCDModuleInst_Backend_DeadError(o->i);
479 } else {
480 NCDModuleInst_Backend_Dead(o->i);
481 }
482 }
483  
484 static void append_iptables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
485 {
486 func_new(vo, i, params, build_iptables_append_cmdline);
487 }
488  
489 static void insert_iptables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
490 {
491 func_new(vo, i, params, build_iptables_insert_cmdline);
492 }
493  
494 static void policy_iptables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
495 {
496 func_new(vo, i, params, build_iptables_policy_cmdline);
497 }
498  
499 static void newchain_iptables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
500 {
501 func_new(vo, i, params, build_iptables_newchain_cmdline);
502 }
503  
504 static void append_ip6tables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
505 {
506 func_new(vo, i, params, build_ip6tables_append_cmdline);
507 }
508  
509 static void insert_ip6tables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
510 {
511 func_new(vo, i, params, build_ip6tables_insert_cmdline);
512 }
513  
514 static void policy_ip6tables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
515 {
516 func_new(vo, i, params, build_ip6tables_policy_cmdline);
517 }
518  
519 static void newchain_ip6tables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
520 {
521 func_new(vo, i, params, build_ip6tables_newchain_cmdline);
522 }
523  
524 static void append_ebtables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
525 {
526 func_new(vo, i, params, build_ebtables_append_cmdline);
527 }
528  
529 static void insert_ebtables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
530 {
531 func_new(vo, i, params, build_ebtables_insert_cmdline);
532 }
533  
534 static void policy_ebtables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
535 {
536 func_new(vo, i, params, build_ebtables_policy_cmdline);
537 }
538  
539 static void newchain_ebtables_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
540 {
541 func_new(vo, i, params, build_ebtables_newchain_cmdline);
542 }
543  
544 static void func_die (void *vo)
545 {
546 struct instance *o = vo;
547  
548 command_template_die(&o->cti);
549 }
550  
551 static void lock_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
552 {
553 struct global *g = ModuleGlobal(i);
554 struct lock_instance *o = vo;
555 o->i = i;
556  
557 // init lock job
558 BEventLockJob_Init(&o->lock_job, &g->iptables_lock, (BEventLock_handler)lock_job_handler, o);
559 BEventLockJob_Wait(&o->lock_job);
560  
561 // set no unlock
562 o->unlock = NULL;
563  
564 // set state locking
565 o->state = LOCK_STATE_LOCKING;
566 }
567  
568 static void lock_func_die (void *vo)
569 {
570 struct lock_instance *o = vo;
571  
572 if (o->state == LOCK_STATE_UNLOCKED) {
573 ASSERT(o->unlock)
574 ASSERT(o->unlock->lock == o)
575 o->unlock->lock = NULL;
576 }
577 else if (o->state == LOCK_STATE_RELOCKING) {
578 ASSERT(o->unlock)
579 ASSERT(o->unlock->lock == o)
580 unlock_free(o->unlock);
581 }
582 else {
583 ASSERT(!o->unlock)
584 }
585  
586 // free lock job
587 BEventLockJob_Free(&o->lock_job);
588  
589 // dead
590 NCDModuleInst_Backend_Dead(o->i);
591 }
592  
593 static void unlock_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
594 {
595 struct unlock_instance *o = vo;
596 o->i = i;
597  
598 // get lock lock
599 struct lock_instance *lock = NCDModuleInst_Backend_GetUser((NCDModuleInst *)params->method_user);
600  
601 // make sure lock doesn't already have an unlock
602 if (lock->unlock) {
603 BLog(BLOG_ERROR, "lock already has an unlock");
604 goto fail0;
605 }
606  
607 // make sure lock is locked
608 if (lock->state != LOCK_STATE_LOCKED) {
609 BLog(BLOG_ERROR, "lock is not locked");
610 goto fail0;
611 }
612  
613 // set lock
614 o->lock = lock;
615  
616 // set unlock in lock
617 lock->unlock = o;
618  
619 // up
620 NCDModuleInst_Backend_Up(o->i);
621  
622 // release lock
623 BEventLockJob_Release(&lock->lock_job);
624  
625 // set lock state unlocked
626 lock->state = LOCK_STATE_UNLOCKED;
627 return;
628  
629 fail0:
630 NCDModuleInst_Backend_DeadError(i);
631 }
632  
633 static void unlock_func_die (void *vo)
634 {
635 struct unlock_instance *o = vo;
636  
637 // if lock is gone, die right away
638 if (!o->lock) {
639 unlock_free(o);
640 return;
641 }
642  
643 ASSERT(o->lock->unlock == o)
644 ASSERT(o->lock->state == LOCK_STATE_UNLOCKED)
645  
646 // wait lock
647 BEventLockJob_Wait(&o->lock->lock_job);
648  
649 // set lock state relocking
650 o->lock->state = LOCK_STATE_RELOCKING;
651 }
652  
653 static void unlock_free (struct unlock_instance *o)
654 {
655 NCDModuleInst_Backend_Dead(o->i);
656 }
657  
658 static struct NCDModule modules[] = {
659 {
660 .type = "net.iptables.append",
661 .func_new2 = append_iptables_func_new,
662 .func_die = func_die,
663 .alloc_size = sizeof(struct instance)
664 }, {
665 .type = "net.iptables.insert",
666 .func_new2 = insert_iptables_func_new,
667 .func_die = func_die,
668 .alloc_size = sizeof(struct instance)
669 }, {
670 .type = "net.iptables.policy",
671 .func_new2 = policy_iptables_func_new,
672 .func_die = func_die,
673 .alloc_size = sizeof(struct instance)
674 }, {
675 .type = "net.iptables.newchain",
676 .func_new2 = newchain_iptables_func_new,
677 .func_die = func_die,
678 .alloc_size = sizeof(struct instance)
679 }, {
680 .type = "net.ip6tables.append",
681 .func_new2 = append_ip6tables_func_new,
682 .func_die = func_die,
683 .alloc_size = sizeof(struct instance)
684 }, {
685 .type = "net.ip6tables.insert",
686 .func_new2 = insert_ip6tables_func_new,
687 .func_die = func_die,
688 .alloc_size = sizeof(struct instance)
689 }, {
690 .type = "net.ip6tables.policy",
691 .func_new2 = policy_ip6tables_func_new,
692 .func_die = func_die,
693 .alloc_size = sizeof(struct instance)
694 }, {
695 .type = "net.ip6tables.newchain",
696 .func_new2 = newchain_ip6tables_func_new,
697 .func_die = func_die,
698 .alloc_size = sizeof(struct instance)
699 }, {
700 .type = "net.ebtables.append",
701 .func_new2 = append_ebtables_func_new,
702 .func_die = func_die,
703 .alloc_size = sizeof(struct instance)
704 }, {
705 .type = "net.ebtables.insert",
706 .func_new2 = insert_ebtables_func_new,
707 .func_die = func_die,
708 .alloc_size = sizeof(struct instance)
709 }, {
710 .type = "net.ebtables.policy",
711 .func_new2 = policy_ebtables_func_new,
712 .func_die = func_die,
713 .alloc_size = sizeof(struct instance)
714 }, {
715 .type = "net.ebtables.newchain",
716 .func_new2 = newchain_ebtables_func_new,
717 .func_die = func_die,
718 .alloc_size = sizeof(struct instance)
719 }, {
720 .type = "net.iptables.lock",
721 .func_new2 = lock_func_new,
722 .func_die = lock_func_die,
723 .alloc_size = sizeof(struct lock_instance)
724 }, {
725 .type = "net.iptables.lock::unlock",
726 .func_new2 = unlock_func_new,
727 .func_die = unlock_func_die,
728 .alloc_size = sizeof(struct unlock_instance)
729 }, {
730 .type = NULL
731 }
732 };
733  
734 const struct NCDModuleGroup ncdmodule_net_iptables = {
735 .modules = modules,
736 .func_globalinit = func_globalinit,
737 .func_globalfree = func_globalfree
738 };